Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
X
xxdk-wasm
Manage
Activity
Members
Labels
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Terraform modules
Analyze
Contributor analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
elixxir
xxdk-wasm
Commits
25eb4e4b
Commit
25eb4e4b
authored
2 years ago
by
Jono Wenger
Browse files
Options
Downloads
Patches
Plain Diff
Update test
parent
775a48f9
No related branches found
No related tags found
Loading
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
test/index.html
+14
-7
14 additions, 7 deletions
test/index.html
test/wasm_exec.js
+643
-0
643 additions, 0 deletions
test/wasm_exec.js
with
657 additions
and
7 deletions
test/index.html
+
14
−
7
View file @
25eb4e4b
...
@@ -12,12 +12,19 @@
...
@@ -12,12 +12,19 @@
<title>
xxDk WebAssembly Test
</title>
<title>
xxDk WebAssembly Test
</title>
<script
src=
"../wasm_exec.js"
></script>
<script
src=
"../wasm_exec.js"
></script>
<script>
const
go
=
new
Go
();
WebAssembly
.
instantiateStreaming
(
fetch
(
"
xxdk.wasm
"
),
go
.
importObject
).
then
((
result
)
=>
{
go
.
run
(
result
.
instance
);
});
</script>
</head>
</head>
<body></body>
<body>
<script>
const
go
=
new
Go
();
let
mod
,
inst
;
WebAssembly
.
instantiateStreaming
(
fetch
(
"
xxdk.wasm
"
),
go
.
importObject
).
then
(
async
(
result
)
=>
{
mod
=
result
.
module
;
inst
=
result
.
instance
;
await
go
.
run
(
inst
);
inst
=
await
WebAssembly
.
instantiate
(
mod
,
go
.
importObject
);
// reset instance
}).
catch
((
err
)
=>
{
console
.
error
(
err
);
});
</script>
</body>
</html>
</html>
\ No newline at end of file
This diff is collapsed.
Click to expand it.
test/wasm_exec.js
0 → 100644
+
643
−
0
View file @
25eb4e4b
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
(()
=>
{
// Map multiple JavaScript environments to a single common API,
// preferring web standards over Node.js API.
//
// Environments considered:
// - Browsers
// - Node.js
// - Electron
// - Parcel
// - Webpack
if
(
typeof
global
!==
"
undefined
"
)
{
// global already exists
}
else
if
(
typeof
window
!==
"
undefined
"
)
{
window
.
global
=
window
;
}
else
if
(
typeof
self
!==
"
undefined
"
)
{
self
.
global
=
self
;
}
else
{
throw
new
Error
(
"
cannot export Go (neither global, window nor self is defined)
"
);
}
if
(
!
global
.
require
&&
typeof
require
!==
"
undefined
"
)
{
global
.
require
=
require
;
}
if
(
!
global
.
fs
&&
global
.
require
)
{
const
fs
=
require
(
"
fs
"
);
if
(
typeof
fs
===
"
object
"
&&
fs
!==
null
&&
Object
.
keys
(
fs
).
length
!==
0
)
{
global
.
fs
=
fs
;
}
}
const
enosys
=
()
=>
{
const
err
=
new
Error
(
"
not implemented
"
);
err
.
code
=
"
ENOSYS
"
;
return
err
;
};
if
(
!
global
.
fs
)
{
let
outputBuf
=
""
;
global
.
fs
=
{
constants
:
{
O_WRONLY
:
-
1
,
O_RDWR
:
-
1
,
O_CREAT
:
-
1
,
O_TRUNC
:
-
1
,
O_APPEND
:
-
1
,
O_EXCL
:
-
1
},
// unused
writeSync
(
fd
,
buf
)
{
outputBuf
+=
decoder
.
decode
(
buf
);
const
nl
=
outputBuf
.
lastIndexOf
(
"
\n
"
);
if
(
nl
!=
-
1
)
{
console
.
log
(
outputBuf
.
substr
(
0
,
nl
));
outputBuf
=
outputBuf
.
substr
(
nl
+
1
);
}
return
buf
.
length
;
},
write
(
fd
,
buf
,
offset
,
length
,
position
,
callback
)
{
if
(
offset
!==
0
||
length
!==
buf
.
length
||
position
!==
null
)
{
callback
(
enosys
());
return
;
}
const
n
=
this
.
writeSync
(
fd
,
buf
);
callback
(
null
,
n
);
},
chmod
(
path
,
mode
,
callback
)
{
callback
(
enosys
());
},
chown
(
path
,
uid
,
gid
,
callback
)
{
callback
(
enosys
());
},
close
(
fd
,
callback
)
{
callback
(
enosys
());
},
fchmod
(
fd
,
mode
,
callback
)
{
callback
(
enosys
());
},
fchown
(
fd
,
uid
,
gid
,
callback
)
{
callback
(
enosys
());
},
fstat
(
fd
,
callback
)
{
callback
(
enosys
());
},
fsync
(
fd
,
callback
)
{
callback
(
null
);
},
ftruncate
(
fd
,
length
,
callback
)
{
callback
(
enosys
());
},
lchown
(
path
,
uid
,
gid
,
callback
)
{
callback
(
enosys
());
},
link
(
path
,
link
,
callback
)
{
callback
(
enosys
());
},
lstat
(
path
,
callback
)
{
callback
(
enosys
());
},
mkdir
(
path
,
perm
,
callback
)
{
callback
(
enosys
());
},
open
(
path
,
flags
,
mode
,
callback
)
{
callback
(
enosys
());
},
read
(
fd
,
buffer
,
offset
,
length
,
position
,
callback
)
{
callback
(
enosys
());
},
readdir
(
path
,
callback
)
{
callback
(
enosys
());
},
readlink
(
path
,
callback
)
{
callback
(
enosys
());
},
rename
(
from
,
to
,
callback
)
{
callback
(
enosys
());
},
rmdir
(
path
,
callback
)
{
callback
(
enosys
());
},
stat
(
path
,
callback
)
{
callback
(
enosys
());
},
symlink
(
path
,
link
,
callback
)
{
callback
(
enosys
());
},
truncate
(
path
,
length
,
callback
)
{
callback
(
enosys
());
},
unlink
(
path
,
callback
)
{
callback
(
enosys
());
},
utimes
(
path
,
atime
,
mtime
,
callback
)
{
callback
(
enosys
());
},
};
}
if
(
!
global
.
process
)
{
global
.
process
=
{
getuid
()
{
return
-
1
;
},
getgid
()
{
return
-
1
;
},
geteuid
()
{
return
-
1
;
},
getegid
()
{
return
-
1
;
},
getgroups
()
{
throw
enosys
();
},
pid
:
-
1
,
ppid
:
-
1
,
umask
()
{
throw
enosys
();
},
cwd
()
{
throw
enosys
();
},
chdir
()
{
throw
enosys
();
},
}
}
if
(
!
global
.
crypto
&&
global
.
require
)
{
const
nodeCrypto
=
require
(
"
crypto
"
);
global
.
crypto
=
{
getRandomValues
(
b
)
{
nodeCrypto
.
randomFillSync
(
b
);
},
};
}
if
(
!
global
.
crypto
)
{
throw
new
Error
(
"
global.crypto is not available, polyfill required (getRandomValues only)
"
);
}
if
(
!
global
.
performance
)
{
global
.
performance
=
{
now
()
{
const
[
sec
,
nsec
]
=
process
.
hrtime
();
return
sec
*
1000
+
nsec
/
1000000
;
},
};
}
if
(
!
global
.
TextEncoder
&&
global
.
require
)
{
global
.
TextEncoder
=
require
(
"
util
"
).
TextEncoder
;
}
if
(
!
global
.
TextEncoder
)
{
throw
new
Error
(
"
global.TextEncoder is not available, polyfill required
"
);
}
if
(
!
global
.
TextDecoder
&&
global
.
require
)
{
global
.
TextDecoder
=
require
(
"
util
"
).
TextDecoder
;
}
if
(
!
global
.
TextDecoder
)
{
throw
new
Error
(
"
global.TextDecoder is not available, polyfill required
"
);
}
// End of polyfills for common API.
const
encoder
=
new
TextEncoder
(
"
utf-8
"
);
const
decoder
=
new
TextDecoder
(
"
utf-8
"
);
global
.
Go
=
class
{
constructor
()
{
this
.
argv
=
[
"
js
"
];
this
.
env
=
{};
this
.
exit
=
(
code
)
=>
{
if
(
code
!==
0
)
{
console
.
warn
(
"
exit code:
"
,
code
);
}
};
this
.
_exitPromise
=
new
Promise
((
resolve
)
=>
{
this
.
_resolveExitPromise
=
resolve
;
});
this
.
_pendingEvent
=
null
;
this
.
_scheduledTimeouts
=
new
Map
();
this
.
_nextCallbackTimeoutID
=
1
;
const
setInt64
=
(
addr
,
v
)
=>
{
this
.
mem
.
setUint32
(
addr
+
0
,
v
,
true
);
this
.
mem
.
setUint32
(
addr
+
4
,
Math
.
floor
(
v
/
4294967296
),
true
);
}
const
getInt64
=
(
addr
)
=>
{
const
low
=
this
.
mem
.
getUint32
(
addr
+
0
,
true
);
const
high
=
this
.
mem
.
getInt32
(
addr
+
4
,
true
);
return
low
+
high
*
4294967296
;
}
const
loadValue
=
(
addr
)
=>
{
const
f
=
this
.
mem
.
getFloat64
(
addr
,
true
);
if
(
f
===
0
)
{
return
undefined
;
}
if
(
!
isNaN
(
f
))
{
return
f
;
}
const
id
=
this
.
mem
.
getUint32
(
addr
,
true
);
return
this
.
_values
[
id
];
}
const
storeValue
=
(
addr
,
v
)
=>
{
const
nanHead
=
0x7FF80000
;
if
(
typeof
v
===
"
number
"
&&
v
!==
0
)
{
if
(
isNaN
(
v
))
{
this
.
mem
.
setUint32
(
addr
+
4
,
nanHead
,
true
);
this
.
mem
.
setUint32
(
addr
,
0
,
true
);
return
;
}
this
.
mem
.
setFloat64
(
addr
,
v
,
true
);
return
;
}
if
(
v
===
undefined
)
{
this
.
mem
.
setFloat64
(
addr
,
0
,
true
);
return
;
}
let
id
=
this
.
_ids
.
get
(
v
);
if
(
id
===
undefined
)
{
id
=
this
.
_idPool
.
pop
();
if
(
id
===
undefined
)
{
id
=
this
.
_values
.
length
;
}
this
.
_values
[
id
]
=
v
;
this
.
_goRefCounts
[
id
]
=
0
;
this
.
_ids
.
set
(
v
,
id
);
}
this
.
_goRefCounts
[
id
]
++
;
let
typeFlag
=
0
;
switch
(
typeof
v
)
{
case
"
object
"
:
if
(
v
!==
null
)
{
typeFlag
=
1
;
}
break
;
case
"
string
"
:
typeFlag
=
2
;
break
;
case
"
symbol
"
:
typeFlag
=
3
;
break
;
case
"
function
"
:
typeFlag
=
4
;
break
;
}
this
.
mem
.
setUint32
(
addr
+
4
,
nanHead
|
typeFlag
,
true
);
this
.
mem
.
setUint32
(
addr
,
id
,
true
);
}
const
loadSlice
=
(
addr
)
=>
{
const
array
=
getInt64
(
addr
+
0
);
const
len
=
getInt64
(
addr
+
8
);
return
new
Uint8Array
(
this
.
_inst
.
exports
.
mem
.
buffer
,
array
,
len
);
}
const
loadSliceOfValues
=
(
addr
)
=>
{
const
array
=
getInt64
(
addr
+
0
);
const
len
=
getInt64
(
addr
+
8
);
const
a
=
new
Array
(
len
);
for
(
let
i
=
0
;
i
<
len
;
i
++
)
{
a
[
i
]
=
loadValue
(
array
+
i
*
8
);
}
return
a
;
}
const
loadString
=
(
addr
)
=>
{
const
saddr
=
getInt64
(
addr
+
0
);
const
len
=
getInt64
(
addr
+
8
);
return
decoder
.
decode
(
new
DataView
(
this
.
_inst
.
exports
.
mem
.
buffer
,
saddr
,
len
));
}
const
timeOrigin
=
Date
.
now
()
-
performance
.
now
();
this
.
importObject
=
{
go
:
{
// Go's SP does not change as long as no Go code is running. Some operations (e.g. calls, getters and setters)
// may synchronously trigger a Go event handler. This makes Go code get executed in the middle of the imported
// function. A goroutine can switch to a new stack if the current stack is too small (see morestack function).
// This changes the SP, thus we have to update the SP used by the imported function.
// func wasmExit(code int32)
"
runtime.wasmExit
"
:
(
sp
)
=>
{
sp
>>>=
0
;
const
code
=
this
.
mem
.
getInt32
(
sp
+
8
,
true
);
this
.
exited
=
true
;
delete
this
.
_inst
;
delete
this
.
_values
;
delete
this
.
_goRefCounts
;
delete
this
.
_ids
;
delete
this
.
_idPool
;
this
.
exit
(
code
);
},
// func wasmWrite(fd uintptr, p unsafe.Pointer, n int32)
"
runtime.wasmWrite
"
:
(
sp
)
=>
{
sp
>>>=
0
;
const
fd
=
getInt64
(
sp
+
8
);
const
p
=
getInt64
(
sp
+
16
);
const
n
=
this
.
mem
.
getInt32
(
sp
+
24
,
true
);
fs
.
writeSync
(
fd
,
new
Uint8Array
(
this
.
_inst
.
exports
.
mem
.
buffer
,
p
,
n
));
},
// func resetMemoryDataView()
"
runtime.resetMemoryDataView
"
:
(
sp
)
=>
{
sp
>>>=
0
;
this
.
mem
=
new
DataView
(
this
.
_inst
.
exports
.
mem
.
buffer
);
},
// func nanotime1() int64
"
runtime.nanotime1
"
:
(
sp
)
=>
{
sp
>>>=
0
;
setInt64
(
sp
+
8
,
(
timeOrigin
+
performance
.
now
())
*
1000000
);
},
// func walltime() (sec int64, nsec int32)
"
runtime.walltime
"
:
(
sp
)
=>
{
sp
>>>=
0
;
const
msec
=
(
new
Date
).
getTime
();
setInt64
(
sp
+
8
,
msec
/
1000
);
this
.
mem
.
setInt32
(
sp
+
16
,
(
msec
%
1000
)
*
1000000
,
true
);
},
// func scheduleTimeoutEvent(delay int64) int32
"
runtime.scheduleTimeoutEvent
"
:
(
sp
)
=>
{
sp
>>>=
0
;
const
id
=
this
.
_nextCallbackTimeoutID
;
this
.
_nextCallbackTimeoutID
++
;
this
.
_scheduledTimeouts
.
set
(
id
,
setTimeout
(
()
=>
{
this
.
_resume
();
while
(
this
.
_scheduledTimeouts
.
has
(
id
))
{
// for some reason Go failed to register the timeout event, log and try again
// (temporary workaround for https://github.com/golang/go/issues/28975)
console
.
warn
(
"
scheduleTimeoutEvent: missed timeout event
"
);
this
.
_resume
();
}
},
getInt64
(
sp
+
8
)
+
1
,
// setTimeout has been seen to fire up to 1 millisecond early
));
this
.
mem
.
setInt32
(
sp
+
16
,
id
,
true
);
},
// func clearTimeoutEvent(id int32)
"
runtime.clearTimeoutEvent
"
:
(
sp
)
=>
{
sp
>>>=
0
;
const
id
=
this
.
mem
.
getInt32
(
sp
+
8
,
true
);
clearTimeout
(
this
.
_scheduledTimeouts
.
get
(
id
));
this
.
_scheduledTimeouts
.
delete
(
id
);
},
// func getRandomData(r []byte)
"
runtime.getRandomData
"
:
(
sp
)
=>
{
sp
>>>=
0
;
crypto
.
getRandomValues
(
loadSlice
(
sp
+
8
));
},
// func finalizeRef(v ref)
"
syscall/js.finalizeRef
"
:
(
sp
)
=>
{
sp
>>>=
0
;
const
id
=
this
.
mem
.
getUint32
(
sp
+
8
,
true
);
this
.
_goRefCounts
[
id
]
--
;
if
(
this
.
_goRefCounts
[
id
]
===
0
)
{
const
v
=
this
.
_values
[
id
];
this
.
_values
[
id
]
=
null
;
this
.
_ids
.
delete
(
v
);
this
.
_idPool
.
push
(
id
);
}
},
// func stringVal(value string) ref
"
syscall/js.stringVal
"
:
(
sp
)
=>
{
sp
>>>=
0
;
storeValue
(
sp
+
24
,
loadString
(
sp
+
8
));
},
// func valueGet(v ref, p string) ref
"
syscall/js.valueGet
"
:
(
sp
)
=>
{
sp
>>>=
0
;
const
result
=
Reflect
.
get
(
loadValue
(
sp
+
8
),
loadString
(
sp
+
16
));
sp
=
this
.
_inst
.
exports
.
getsp
()
>>>
0
;
// see comment above
storeValue
(
sp
+
32
,
result
);
},
// func valueSet(v ref, p string, x ref)
"
syscall/js.valueSet
"
:
(
sp
)
=>
{
sp
>>>=
0
;
Reflect
.
set
(
loadValue
(
sp
+
8
),
loadString
(
sp
+
16
),
loadValue
(
sp
+
32
));
},
// func valueDelete(v ref, p string)
"
syscall/js.valueDelete
"
:
(
sp
)
=>
{
sp
>>>=
0
;
Reflect
.
deleteProperty
(
loadValue
(
sp
+
8
),
loadString
(
sp
+
16
));
},
// func valueIndex(v ref, i int) ref
"
syscall/js.valueIndex
"
:
(
sp
)
=>
{
sp
>>>=
0
;
storeValue
(
sp
+
24
,
Reflect
.
get
(
loadValue
(
sp
+
8
),
getInt64
(
sp
+
16
)));
},
// valueSetIndex(v ref, i int, x ref)
"
syscall/js.valueSetIndex
"
:
(
sp
)
=>
{
sp
>>>=
0
;
Reflect
.
set
(
loadValue
(
sp
+
8
),
getInt64
(
sp
+
16
),
loadValue
(
sp
+
24
));
},
// func valueCall(v ref, m string, args []ref) (ref, bool)
"
syscall/js.valueCall
"
:
(
sp
)
=>
{
sp
>>>=
0
;
try
{
const
v
=
loadValue
(
sp
+
8
);
const
m
=
Reflect
.
get
(
v
,
loadString
(
sp
+
16
));
const
args
=
loadSliceOfValues
(
sp
+
32
);
const
result
=
Reflect
.
apply
(
m
,
v
,
args
);
sp
=
this
.
_inst
.
exports
.
getsp
()
>>>
0
;
// see comment above
storeValue
(
sp
+
56
,
result
);
this
.
mem
.
setUint8
(
sp
+
64
,
1
);
}
catch
(
err
)
{
sp
=
this
.
_inst
.
exports
.
getsp
()
>>>
0
;
// see comment above
storeValue
(
sp
+
56
,
err
);
this
.
mem
.
setUint8
(
sp
+
64
,
0
);
}
},
// func valueInvoke(v ref, args []ref) (ref, bool)
"
syscall/js.valueInvoke
"
:
(
sp
)
=>
{
sp
>>>=
0
;
try
{
const
v
=
loadValue
(
sp
+
8
);
const
args
=
loadSliceOfValues
(
sp
+
16
);
const
result
=
Reflect
.
apply
(
v
,
undefined
,
args
);
sp
=
this
.
_inst
.
exports
.
getsp
()
>>>
0
;
// see comment above
storeValue
(
sp
+
40
,
result
);
this
.
mem
.
setUint8
(
sp
+
48
,
1
);
}
catch
(
err
)
{
sp
=
this
.
_inst
.
exports
.
getsp
()
>>>
0
;
// see comment above
storeValue
(
sp
+
40
,
err
);
this
.
mem
.
setUint8
(
sp
+
48
,
0
);
}
},
// func valueNew(v ref, args []ref) (ref, bool)
"
syscall/js.valueNew
"
:
(
sp
)
=>
{
sp
>>>=
0
;
try
{
const
v
=
loadValue
(
sp
+
8
);
const
args
=
loadSliceOfValues
(
sp
+
16
);
const
result
=
Reflect
.
construct
(
v
,
args
);
sp
=
this
.
_inst
.
exports
.
getsp
()
>>>
0
;
// see comment above
storeValue
(
sp
+
40
,
result
);
this
.
mem
.
setUint8
(
sp
+
48
,
1
);
}
catch
(
err
)
{
sp
=
this
.
_inst
.
exports
.
getsp
()
>>>
0
;
// see comment above
storeValue
(
sp
+
40
,
err
);
this
.
mem
.
setUint8
(
sp
+
48
,
0
);
}
},
// func valueLength(v ref) int
"
syscall/js.valueLength
"
:
(
sp
)
=>
{
sp
>>>=
0
;
setInt64
(
sp
+
16
,
parseInt
(
loadValue
(
sp
+
8
).
length
));
},
// valuePrepareString(v ref) (ref, int)
"
syscall/js.valuePrepareString
"
:
(
sp
)
=>
{
sp
>>>=
0
;
const
str
=
encoder
.
encode
(
String
(
loadValue
(
sp
+
8
)));
storeValue
(
sp
+
16
,
str
);
setInt64
(
sp
+
24
,
str
.
length
);
},
// valueLoadString(v ref, b []byte)
"
syscall/js.valueLoadString
"
:
(
sp
)
=>
{
sp
>>>=
0
;
const
str
=
loadValue
(
sp
+
8
);
loadSlice
(
sp
+
16
).
set
(
str
);
},
// func valueInstanceOf(v ref, t ref) bool
"
syscall/js.valueInstanceOf
"
:
(
sp
)
=>
{
sp
>>>=
0
;
this
.
mem
.
setUint8
(
sp
+
24
,
(
loadValue
(
sp
+
8
)
instanceof
loadValue
(
sp
+
16
))
?
1
:
0
);
},
// func copyBytesToGo(dst []byte, src ref) (int, bool)
"
syscall/js.copyBytesToGo
"
:
(
sp
)
=>
{
sp
>>>=
0
;
const
dst
=
loadSlice
(
sp
+
8
);
const
src
=
loadValue
(
sp
+
32
);
if
(
!
(
src
instanceof
Uint8Array
||
src
instanceof
Uint8ClampedArray
))
{
this
.
mem
.
setUint8
(
sp
+
48
,
0
);
return
;
}
const
toCopy
=
src
.
subarray
(
0
,
dst
.
length
);
dst
.
set
(
toCopy
);
setInt64
(
sp
+
40
,
toCopy
.
length
);
this
.
mem
.
setUint8
(
sp
+
48
,
1
);
},
// func copyBytesToJS(dst ref, src []byte) (int, bool)
"
syscall/js.copyBytesToJS
"
:
(
sp
)
=>
{
sp
>>>=
0
;
const
dst
=
loadValue
(
sp
+
8
);
const
src
=
loadSlice
(
sp
+
16
);
if
(
!
(
dst
instanceof
Uint8Array
||
dst
instanceof
Uint8ClampedArray
))
{
this
.
mem
.
setUint8
(
sp
+
48
,
0
);
return
;
}
const
toCopy
=
src
.
subarray
(
0
,
dst
.
length
);
dst
.
set
(
toCopy
);
setInt64
(
sp
+
40
,
toCopy
.
length
);
this
.
mem
.
setUint8
(
sp
+
48
,
1
);
},
"
debug
"
:
(
value
)
=>
{
console
.
log
(
value
);
},
// func throw(exception string, message string)
'
gitlab.com/elixxir/xxdk-wasm/utils.throw
'
:
(
sp
)
=>
{
const
exception
=
loadString
(
sp
+
8
)
const
message
=
loadString
(
sp
+
24
)
throw
globalThis
[
exception
](
message
)
},
}
};
}
async
run
(
instance
)
{
if
(
!
(
instance
instanceof
WebAssembly
.
Instance
))
{
throw
new
Error
(
"
Go.run: WebAssembly.Instance expected
"
);
}
this
.
_inst
=
instance
;
this
.
mem
=
new
DataView
(
this
.
_inst
.
exports
.
mem
.
buffer
);
this
.
_values
=
[
// JS values that Go currently has references to, indexed by reference id
NaN
,
0
,
null
,
true
,
false
,
global
,
this
,
];
this
.
_goRefCounts
=
new
Array
(
this
.
_values
.
length
).
fill
(
Infinity
);
// number of references that Go has to a JS value, indexed by reference id
this
.
_ids
=
new
Map
([
// mapping from JS values to reference ids
[
0
,
1
],
[
null
,
2
],
[
true
,
3
],
[
false
,
4
],
[
global
,
5
],
[
this
,
6
],
]);
this
.
_idPool
=
[];
// unused ids that have been garbage collected
this
.
exited
=
false
;
// whether the Go program has exited
// Pass command line arguments and environment variables to WebAssembly by writing them to the linear memory.
let
offset
=
4096
;
const
strPtr
=
(
str
)
=>
{
const
ptr
=
offset
;
const
bytes
=
encoder
.
encode
(
str
+
"
\
0
"
);
new
Uint8Array
(
this
.
mem
.
buffer
,
offset
,
bytes
.
length
).
set
(
bytes
);
offset
+=
bytes
.
length
;
if
(
offset
%
8
!==
0
)
{
offset
+=
8
-
(
offset
%
8
);
}
return
ptr
;
};
const
argc
=
this
.
argv
.
length
;
const
argvPtrs
=
[];
this
.
argv
.
forEach
((
arg
)
=>
{
argvPtrs
.
push
(
strPtr
(
arg
));
});
argvPtrs
.
push
(
0
);
const
keys
=
Object
.
keys
(
this
.
env
).
sort
();
keys
.
forEach
((
key
)
=>
{
argvPtrs
.
push
(
strPtr
(
`
${
key
}
=
${
this
.
env
[
key
]}
`
));
});
argvPtrs
.
push
(
0
);
const
argv
=
offset
;
argvPtrs
.
forEach
((
ptr
)
=>
{
this
.
mem
.
setUint32
(
offset
,
ptr
,
true
);
this
.
mem
.
setUint32
(
offset
+
4
,
0
,
true
);
offset
+=
8
;
});
// The linker guarantees global data starts from at least wasmMinDataAddr.
// Keep in sync with cmd/link/internal/ld/data.go:wasmMinDataAddr.
const
wasmMinDataAddr
=
4096
+
8192
;
if
(
offset
>=
wasmMinDataAddr
)
{
throw
new
Error
(
"
total length of command line and environment variables exceeds limit
"
);
}
this
.
_inst
.
exports
.
run
(
argc
,
argv
);
if
(
this
.
exited
)
{
this
.
_resolveExitPromise
();
}
await
this
.
_exitPromise
;
}
_resume
()
{
if
(
this
.
exited
)
{
throw
new
Error
(
"
Go program has already exited
"
);
}
this
.
_inst
.
exports
.
resume
();
if
(
this
.
exited
)
{
this
.
_resolveExitPromise
();
}
}
_makeFuncWrapper
(
id
)
{
const
go
=
this
;
return
function
()
{
const
event
=
{
id
:
id
,
this
:
this
,
args
:
arguments
};
go
.
_pendingEvent
=
event
;
go
.
_resume
();
return
event
.
result
;
};
}
}
if
(
typeof
module
!==
"
undefined
"
&&
global
.
require
&&
global
.
require
.
main
===
module
&&
global
.
process
&&
global
.
process
.
versions
&&
!
global
.
process
.
versions
.
electron
)
{
if
(
process
.
argv
.
length
<
3
)
{
console
.
error
(
"
usage: go_js_wasm_exec [wasm binary] [arguments]
"
);
process
.
exit
(
1
);
}
const
go
=
new
Go
();
go
.
argv
=
process
.
argv
.
slice
(
2
);
go
.
env
=
Object
.
assign
({
TMPDIR
:
require
(
"
os
"
).
tmpdir
()
},
process
.
env
);
go
.
exit
=
process
.
exit
;
WebAssembly
.
instantiate
(
fs
.
readFileSync
(
process
.
argv
[
2
]),
go
.
importObject
).
then
((
result
)
=>
{
process
.
on
(
"
exit
"
,
(
code
)
=>
{
// Node.js exits if no event handler is pending
if
(
code
===
0
&&
!
go
.
exited
)
{
// deadlock, make Go print error and stack traces
go
.
_pendingEvent
=
{
id
:
0
};
go
.
_resume
();
}
});
return
go
.
run
(
result
.
instance
);
}).
catch
((
err
)
=>
{
console
.
error
(
err
);
process
.
exit
(
1
);
});
}
})();
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment