Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
canifa_note
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Vũ Hoàng Anh
canifa_note
Commits
ebcf43c9
Commit
ebcf43c9
authored
Mar 03, 2024
by
Steven
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
chore: update gomark.wasm
parent
cfb50f19
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
582 additions
and
558 deletions
+582
-558
gomark.wasm
web/src/assets/gomark.wasm
+0
-0
wasm_exec.js
web/src/assets/wasm_exec.js
+581
-556
main.tsx
web/src/main.tsx
+1
-2
No files found.
web/src/assets/gomark.wasm
View file @
ebcf43c9
No preview for this file type
web/src/assets/wasm_exec.js
View file @
ebcf43c9
// Copyright 2018 The Go Authors. All rights reserved.
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// license that can be found in the LICENSE file.
//
"use strict"
;
// This file has been modified for use by the TinyGo compiler.
(()
=>
{
(()
=>
{
// Map multiple JavaScript environments to a single common API,
// preferring web standards over Node.js API.
//
// Environments considered:
// - Browsers
// - Node.js
// - Electron
// - Parcel
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
)
{
global
.
fs
=
require
(
"fs"
);
}
const
enosys
=
()
=>
{
const
enosys
=
()
=>
{
const
err
=
new
Error
(
"not implemented"
);
const
err
=
new
Error
(
"not implemented"
);
err
.
code
=
"ENOSYS"
;
err
.
code
=
"ENOSYS"
;
return
err
;
return
err
;
};
};
if
(
!
globalThis
.
fs
)
{
if
(
!
global
.
fs
)
{
let
outputBuf
=
""
;
let
outputBuf
=
""
;
globalThis
.
fs
=
{
global
.
fs
=
{
constants
:
{
O_WRONLY
:
-
1
,
O_RDWR
:
-
1
,
O_CREAT
:
-
1
,
O_TRUNC
:
-
1
,
O_APPEND
:
-
1
,
O_EXCL
:
-
1
},
// unused
constants
:
{
O_WRONLY
:
-
1
,
O_RDWR
:
-
1
,
O_CREAT
:
-
1
,
O_TRUNC
:
-
1
,
O_APPEND
:
-
1
,
O_EXCL
:
-
1
},
// unused
writeSync
(
fd
,
buf
)
{
writeSync
(
fd
,
buf
)
{
outputBuf
+=
decoder
.
decode
(
buf
);
outputBuf
+=
decoder
.
decode
(
buf
);
const
nl
=
outputBuf
.
lastIndexOf
(
"
\n
"
);
const
nl
=
outputBuf
.
lastIndexOf
(
"
\n
"
);
if
(
nl
!=
-
1
)
{
if
(
nl
!=
-
1
)
{
console
.
log
(
outputBuf
.
substring
(
0
,
nl
));
console
.
log
(
outputBuf
.
substr
(
0
,
nl
));
outputBuf
=
outputBuf
.
substring
(
nl
+
1
);
outputBuf
=
outputBuf
.
substr
(
nl
+
1
);
}
}
return
buf
.
length
;
return
buf
.
length
;
},
},
...
@@ -32,99 +59,155 @@
...
@@ -32,99 +59,155 @@
const
n
=
this
.
writeSync
(
fd
,
buf
);
const
n
=
this
.
writeSync
(
fd
,
buf
);
callback
(
null
,
n
);
callback
(
null
,
n
);
},
},
chmod
(
path
,
mode
,
callback
)
{
callback
(
enosys
());
},
chmod
(
path
,
mode
,
callback
)
{
chown
(
path
,
uid
,
gid
,
callback
)
{
callback
(
enosys
());
},
callback
(
enosys
());
close
(
fd
,
callback
)
{
callback
(
enosys
());
},
},
fchmod
(
fd
,
mode
,
callback
)
{
callback
(
enosys
());
},
chown
(
path
,
uid
,
gid
,
callback
)
{
fchown
(
fd
,
uid
,
gid
,
callback
)
{
callback
(
enosys
());
},
callback
(
enosys
());
fstat
(
fd
,
callback
)
{
callback
(
enosys
());
},
},
fsync
(
fd
,
callback
)
{
callback
(
null
);
},
close
(
fd
,
callback
)
{
ftruncate
(
fd
,
length
,
callback
)
{
callback
(
enosys
());
},
callback
(
enosys
());
lchown
(
path
,
uid
,
gid
,
callback
)
{
callback
(
enosys
());
},
},
link
(
path
,
link
,
callback
)
{
callback
(
enosys
());
},
fchmod
(
fd
,
mode
,
callback
)
{
lstat
(
path
,
callback
)
{
callback
(
enosys
());
},
callback
(
enosys
());
mkdir
(
path
,
perm
,
callback
)
{
callback
(
enosys
());
},
},
open
(
path
,
flags
,
mode
,
callback
)
{
callback
(
enosys
());
},
fchown
(
fd
,
uid
,
gid
,
callback
)
{
read
(
fd
,
buffer
,
offset
,
length
,
position
,
callback
)
{
callback
(
enosys
());
},
callback
(
enosys
());
readdir
(
path
,
callback
)
{
callback
(
enosys
());
},
},
readlink
(
path
,
callback
)
{
callback
(
enosys
());
},
fstat
(
fd
,
callback
)
{
rename
(
from
,
to
,
callback
)
{
callback
(
enosys
());
},
callback
(
enosys
());
rmdir
(
path
,
callback
)
{
callback
(
enosys
());
},
},
stat
(
path
,
callback
)
{
callback
(
enosys
());
},
fsync
(
fd
,
callback
)
{
symlink
(
path
,
link
,
callback
)
{
callback
(
enosys
());
},
callback
(
null
);
truncate
(
path
,
length
,
callback
)
{
callback
(
enosys
());
},
},
unlink
(
path
,
callback
)
{
callback
(
enosys
());
},
ftruncate
(
fd
,
length
,
callback
)
{
utimes
(
path
,
atime
,
mtime
,
callback
)
{
callback
(
enosys
());
},
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
(
!
globalThis
.
process
)
{
if
(
!
global
.
process
)
{
globalThis
.
process
=
{
global
.
process
=
{
getuid
()
{
return
-
1
;
},
getuid
()
{
getgid
()
{
return
-
1
;
},
return
-
1
;
geteuid
()
{
return
-
1
;
},
},
getegid
()
{
return
-
1
;
},
getgid
()
{
getgroups
()
{
throw
enosys
();
},
return
-
1
;
},
geteuid
()
{
return
-
1
;
},
getegid
()
{
return
-
1
;
},
getgroups
()
{
throw
enosys
();
},
pid
:
-
1
,
pid
:
-
1
,
ppid
:
-
1
,
ppid
:
-
1
,
umask
()
{
throw
enosys
();
},
umask
()
{
cwd
()
{
throw
enosys
();
},
throw
enosys
();
chdir
()
{
throw
enosys
();
},
},
}
cwd
()
{
throw
enosys
();
},
chdir
()
{
throw
enosys
();
},
};
}
}
if
(
!
globalThis
.
crypto
)
{
if
(
!
global
.
crypto
)
{
throw
new
Error
(
"globalThis.crypto is not available, polyfill required (crypto.getRandomValues only)"
);
const
nodeCrypto
=
require
(
"crypto"
);
global
.
crypto
=
{
getRandomValues
(
b
)
{
nodeCrypto
.
randomFillSync
(
b
);
},
};
}
}
if
(
!
globalThis
.
performance
)
{
if
(
!
global
.
performance
)
{
throw
new
Error
(
"globalThis.performance is not available, polyfill required (performance.now only)"
);
global
.
performance
=
{
now
()
{
const
[
sec
,
nsec
]
=
process
.
hrtime
();
return
sec
*
1000
+
nsec
/
1000000
;
},
};
}
}
if
(
!
globalThis
.
TextEncoder
)
{
if
(
!
global
.
TextEncoder
)
{
throw
new
Error
(
"globalThis.TextEncoder is not available, polyfill required"
)
;
global
.
TextEncoder
=
require
(
"util"
).
TextEncoder
;
}
}
if
(
!
globalThis
.
TextDecoder
)
{
if
(
!
global
.
TextDecoder
)
{
throw
new
Error
(
"globalThis.TextDecoder is not available, polyfill required"
)
;
global
.
TextDecoder
=
require
(
"util"
).
TextDecoder
;
}
}
// End of polyfills for common API.
const
encoder
=
new
TextEncoder
(
"utf-8"
);
const
encoder
=
new
TextEncoder
(
"utf-8"
);
const
decoder
=
new
TextDecoder
(
"utf-8"
);
const
decoder
=
new
TextDecoder
(
"utf-8"
);
let
reinterpretBuf
=
new
DataView
(
new
ArrayBuffer
(
8
));
var
logLine
=
[];
globalThis
.
Go
=
class
{
global
.
Go
=
class
{
constructor
()
{
constructor
()
{
this
.
argv
=
[
"js"
];
this
.
_callbackTimeouts
=
new
Map
();
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
;
this
.
_nextCallbackTimeoutID
=
1
;
const
setInt64
=
(
addr
,
v
)
=>
{
const
mem
=
()
=>
{
this
.
mem
.
setUint32
(
addr
+
0
,
v
,
true
);
// The buffer may change when requesting more memory.
this
.
mem
.
setUint32
(
addr
+
4
,
Math
.
floor
(
v
/
4294967296
),
true
);
return
new
DataView
(
this
.
_inst
.
exports
.
memory
.
buffer
);
}
};
const
setInt32
=
(
addr
,
v
)
=>
{
this
.
mem
.
setUint32
(
addr
+
0
,
v
,
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
unboxValue
=
(
v_ref
)
=>
{
const
f
=
this
.
mem
.
getFloat64
(
addr
,
true
);
reinterpretBuf
.
setBigInt64
(
0
,
v_ref
,
true
);
const
f
=
reinterpretBuf
.
getFloat64
(
0
,
true
);
if
(
f
===
0
)
{
if
(
f
===
0
)
{
return
undefined
;
return
undefined
;
}
}
...
@@ -132,410 +215,335 @@
...
@@ -132,410 +215,335 @@
return
f
;
return
f
;
}
}
const
id
=
this
.
mem
.
getUint32
(
addr
,
true
)
;
const
id
=
v_ref
&
0xffffffff
n
;
return
this
.
_values
[
id
];
return
this
.
_values
[
id
];
}
};
const
storeValue
=
(
addr
,
v
)
=>
{
const
loadValue
=
(
addr
)
=>
{
const
nanHead
=
0x7FF80000
;
let
v_ref
=
mem
().
getBigUint64
(
addr
,
true
);
return
unboxValue
(
v_ref
);
};
const
boxValue
=
(
v
)
=>
{
const
nanHead
=
0x7ff80000
n
;
if
(
typeof
v
===
"number"
&&
v
!==
0
)
{
if
(
typeof
v
===
"number"
)
{
if
(
isNaN
(
v
))
{
if
(
isNaN
(
v
))
{
this
.
mem
.
setUint32
(
addr
+
4
,
nanHead
,
true
);
return
nanHead
<<
32
n
;
this
.
mem
.
setUint32
(
addr
,
0
,
true
);
return
;
}
}
this
.
mem
.
setFloat64
(
addr
,
v
,
true
);
if
(
v
===
0
)
{
return
;
return
(
nanHead
<<
32
n
)
|
1
n
;
}
reinterpretBuf
.
setFloat64
(
0
,
v
,
true
);
return
reinterpretBuf
.
getBigInt64
(
0
,
true
);
}
}
if
(
v
===
undefined
)
{
switch
(
v
)
{
this
.
mem
.
setFloat64
(
addr
,
0
,
true
);
case
undefined
:
return
;
return
0
n
;
case
null
:
return
(
nanHead
<<
32
n
)
|
2
n
;
case
true
:
return
(
nanHead
<<
32
n
)
|
3
n
;
case
false
:
return
(
nanHead
<<
32
n
)
|
4
n
;
}
}
let
id
=
this
.
_ids
.
get
(
v
);
let
id
=
this
.
_ids
.
get
(
v
);
if
(
id
===
undefined
)
{
if
(
id
===
undefined
)
{
id
=
this
.
_idPool
.
pop
();
id
=
this
.
_idPool
.
pop
();
if
(
id
===
undefined
)
{
if
(
id
===
undefined
)
{
id
=
this
.
_values
.
length
;
id
=
BigInt
(
this
.
_values
.
length
)
;
}
}
this
.
_values
[
id
]
=
v
;
this
.
_values
[
id
]
=
v
;
this
.
_goRefCounts
[
id
]
=
0
;
this
.
_goRefCounts
[
id
]
=
0
;
this
.
_ids
.
set
(
v
,
id
);
this
.
_ids
.
set
(
v
,
id
);
}
}
this
.
_goRefCounts
[
id
]
++
;
this
.
_goRefCounts
[
id
]
++
;
let
typeFlag
=
0
;
let
typeFlag
=
1
n
;
switch
(
typeof
v
)
{
switch
(
typeof
v
)
{
case
"object"
:
if
(
v
!==
null
)
{
typeFlag
=
1
;
}
break
;
case
"string"
:
case
"string"
:
typeFlag
=
2
;
typeFlag
=
2
n
;
break
;
break
;
case
"symbol"
:
case
"symbol"
:
typeFlag
=
3
;
typeFlag
=
3
n
;
break
;
break
;
case
"function"
:
case
"function"
:
typeFlag
=
4
;
typeFlag
=
4
n
;
break
;
break
;
}
}
this
.
mem
.
setUint32
(
addr
+
4
,
nanHead
|
typeFlag
,
true
);
return
id
|
((
nanHead
|
typeFlag
)
<<
32
n
);
this
.
mem
.
setUint32
(
addr
,
id
,
true
);
};
}
const
loadSlice
=
(
addr
)
=>
{
const
storeValue
=
(
addr
,
v
)
=>
{
const
array
=
getInt64
(
addr
+
0
);
let
v_ref
=
boxValue
(
v
);
const
len
=
getInt64
(
addr
+
8
);
mem
().
setBigUint64
(
addr
,
v_ref
,
true
);
return
new
Uint8Array
(
this
.
_inst
.
exports
.
mem
.
buffer
,
array
,
len
);
};
}
const
loadSlice
=
(
array
,
len
,
cap
)
=>
{
return
new
Uint8Array
(
this
.
_inst
.
exports
.
memory
.
buffer
,
array
,
len
);
};
const
loadSliceOfValues
=
(
addr
)
=>
{
const
loadSliceOfValues
=
(
array
,
len
,
cap
)
=>
{
const
array
=
getInt64
(
addr
+
0
);
const
len
=
getInt64
(
addr
+
8
);
const
a
=
new
Array
(
len
);
const
a
=
new
Array
(
len
);
for
(
let
i
=
0
;
i
<
len
;
i
++
)
{
for
(
let
i
=
0
;
i
<
len
;
i
++
)
{
a
[
i
]
=
loadValue
(
array
+
i
*
8
);
a
[
i
]
=
loadValue
(
array
+
i
*
8
);
}
}
return
a
;
return
a
;
}
};
const
loadString
=
(
addr
)
=>
{
const
loadString
=
(
ptr
,
len
)
=>
{
const
saddr
=
getInt64
(
addr
+
0
);
return
decoder
.
decode
(
new
DataView
(
this
.
_inst
.
exports
.
memory
.
buffer
,
ptr
,
len
));
const
len
=
getInt64
(
addr
+
8
);
};
return
decoder
.
decode
(
new
DataView
(
this
.
_inst
.
exports
.
mem
.
buffer
,
saddr
,
len
));
}
const
timeOrigin
=
Date
.
now
()
-
performance
.
now
();
const
timeOrigin
=
Date
.
now
()
-
performance
.
now
();
this
.
importObject
=
{
this
.
importObject
=
{
_gotest
:
{
wasi_snapshot_preview1
:
{
add
:
(
a
,
b
)
=>
a
+
b
,
// https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#fd_write
fd_write
:
function
(
fd
,
iovs_ptr
,
iovs_len
,
nwritten_ptr
)
{
let
nwritten
=
0
;
if
(
fd
==
1
)
{
for
(
let
iovs_i
=
0
;
iovs_i
<
iovs_len
;
iovs_i
++
)
{
let
iov_ptr
=
iovs_ptr
+
iovs_i
*
8
;
// assuming wasm32
let
ptr
=
mem
().
getUint32
(
iov_ptr
+
0
,
true
);
let
len
=
mem
().
getUint32
(
iov_ptr
+
4
,
true
);
nwritten
+=
len
;
for
(
let
i
=
0
;
i
<
len
;
i
++
)
{
let
c
=
mem
().
getUint8
(
ptr
+
i
);
if
(
c
==
13
)
{
// CR
// ignore
}
else
if
(
c
==
10
)
{
// LF
// write line
let
line
=
decoder
.
decode
(
new
Uint8Array
(
logLine
));
logLine
=
[];
console
.
log
(
line
);
}
else
{
logLine
.
push
(
c
);
}
}
}
}
else
{
console
.
error
(
"invalid file descriptor:"
,
fd
);
}
mem
().
setUint32
(
nwritten_ptr
,
nwritten
,
true
);
return
0
;
},
fd_close
:
()
=>
0
,
// dummy
fd_fdstat_get
:
()
=>
0
,
// dummy
fd_seek
:
()
=>
0
,
// dummy
proc_exit
:
(
code
)
=>
{
if
(
global
.
process
)
{
// Node.js
process
.
exit
(
code
);
}
else
{
// Can't exit in a browser.
throw
"trying to exit with code "
+
code
;
}
},
random_get
:
(
bufPtr
,
bufLen
)
=>
{
crypto
.
getRandomValues
(
loadSlice
(
bufPtr
,
bufLen
));
return
0
;
},
},
},
gojs
:
{
gojs
:
{
// Go's SP does not change as long as no Go code is running. Some operations (e.g. calls, getters and setters)
// func ticks() float64
// may synchronously trigger a Go event handler. This makes Go code get executed in the middle of the imported
"runtime.ticks"
:
()
=>
{
// function. A goroutine can switch to a new stack if the current stack is too small (see morestack function).
return
timeOrigin
+
performance
.
now
();
// This changes the SP, thus we have to update the SP used by the imported function.
},
// func wasmExit(code int32)
// func sleepTicks(timeout float64)
"runtime.wasmExit"
:
(
sp
)
=>
{
"runtime.sleepTicks"
:
(
timeout
)
=>
{
sp
>>>=
0
;
// Do not sleep, only reactivate scheduler after the given timeout.
const
code
=
this
.
mem
.
getInt32
(
sp
+
8
,
true
);
setTimeout
(
this
.
_inst
.
exports
.
go_scheduler
,
timeout
);
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
),
));
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)
// func finalizeRef(v ref)
"syscall/js.finalizeRef"
:
(
sp
)
=>
{
"syscall/js.finalizeRef"
:
(
v_ref
)
=>
{
sp
>>>=
0
;
// Note: TinyGo does not support finalizers so this should never be
const
id
=
this
.
mem
.
getUint32
(
sp
+
8
,
true
);
// called.
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
// func stringVal(value string) ref
"syscall/js.stringVal"
:
(
sp
)
=>
{
"syscall/js.stringVal"
:
(
value_ptr
,
value_len
)
=>
{
sp
>>>=
0
;
const
s
=
loadString
(
value_ptr
,
value_len
)
;
storeValue
(
sp
+
24
,
loadString
(
sp
+
8
)
);
return
boxValue
(
s
);
},
},
// func valueGet(v ref, p string) ref
// func valueGet(v ref, p string) ref
"syscall/js.valueGet"
:
(
sp
)
=>
{
"syscall/js.valueGet"
:
(
v_ref
,
p_ptr
,
p_len
)
=>
{
sp
>>>=
0
;
let
prop
=
loadString
(
p_ptr
,
p_len
)
;
const
result
=
Reflect
.
get
(
loadValue
(
sp
+
8
),
loadString
(
sp
+
16
)
);
let
v
=
unboxValue
(
v_ref
);
sp
=
this
.
_inst
.
exports
.
getsp
()
>>>
0
;
// see comment above
let
result
=
Reflect
.
get
(
v
,
prop
);
storeValue
(
sp
+
32
,
result
);
return
boxValue
(
result
);
},
},
// func valueSet(v ref, p string, x ref)
// func valueSet(v ref, p string, x ref)
"syscall/js.valueSet"
:
(
sp
)
=>
{
"syscall/js.valueSet"
:
(
v_ref
,
p_ptr
,
p_len
,
x_ref
)
=>
{
sp
>>>=
0
;
const
v
=
unboxValue
(
v_ref
);
Reflect
.
set
(
loadValue
(
sp
+
8
),
loadString
(
sp
+
16
),
loadValue
(
sp
+
32
));
const
p
=
loadString
(
p_ptr
,
p_len
);
const
x
=
unboxValue
(
x_ref
);
Reflect
.
set
(
v
,
p
,
x
);
},
},
// func valueDelete(v ref, p string)
// func valueDelete(v ref, p string)
"syscall/js.valueDelete"
:
(
sp
)
=>
{
"syscall/js.valueDelete"
:
(
v_ref
,
p_ptr
,
p_len
)
=>
{
sp
>>>=
0
;
const
v
=
unboxValue
(
v_ref
);
Reflect
.
deleteProperty
(
loadValue
(
sp
+
8
),
loadString
(
sp
+
16
));
const
p
=
loadString
(
p_ptr
,
p_len
);
Reflect
.
deleteProperty
(
v
,
p
);
},
},
// func valueIndex(v ref, i int) ref
// func valueIndex(v ref, i int) ref
"syscall/js.valueIndex"
:
(
sp
)
=>
{
"syscall/js.valueIndex"
:
(
v_ref
,
i
)
=>
{
sp
>>>=
0
;
return
boxValue
(
Reflect
.
get
(
unboxValue
(
v_ref
),
i
));
storeValue
(
sp
+
24
,
Reflect
.
get
(
loadValue
(
sp
+
8
),
getInt64
(
sp
+
16
)));
},
},
// valueSetIndex(v ref, i int, x ref)
// valueSetIndex(v ref, i int, x ref)
"syscall/js.valueSetIndex"
:
(
sp
)
=>
{
"syscall/js.valueSetIndex"
:
(
v_ref
,
i
,
x_ref
)
=>
{
sp
>>>=
0
;
Reflect
.
set
(
unboxValue
(
v_ref
),
i
,
unboxValue
(
x_ref
));
Reflect
.
set
(
loadValue
(
sp
+
8
),
getInt64
(
sp
+
16
),
loadValue
(
sp
+
24
));
},
},
// func valueCall(v ref, m string, args []ref) (ref, bool)
// func valueCall(v ref, m string, args []ref) (ref, bool)
"syscall/js.valueCall"
:
(
sp
)
=>
{
"syscall/js.valueCall"
:
(
ret_addr
,
v_ref
,
m_ptr
,
m_len
,
args_ptr
,
args_len
,
args_cap
)
=>
{
sp
>>>=
0
;
const
v
=
unboxValue
(
v_ref
);
const
name
=
loadString
(
m_ptr
,
m_len
);
const
args
=
loadSliceOfValues
(
args_ptr
,
args_len
,
args_cap
);
try
{
try
{
const
v
=
loadValue
(
sp
+
8
);
const
m
=
Reflect
.
get
(
v
,
name
);
const
m
=
Reflect
.
get
(
v
,
loadString
(
sp
+
16
));
storeValue
(
ret_addr
,
Reflect
.
apply
(
m
,
v
,
args
));
const
args
=
loadSliceOfValues
(
sp
+
32
);
mem
().
setUint8
(
ret_addr
+
8
,
1
);
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
)
{
}
catch
(
err
)
{
sp
=
this
.
_inst
.
exports
.
getsp
()
>>>
0
;
// see comment above
storeValue
(
ret_addr
,
err
);
storeValue
(
sp
+
56
,
err
);
mem
().
setUint8
(
ret_addr
+
8
,
0
);
this
.
mem
.
setUint8
(
sp
+
64
,
0
);
}
}
},
},
// func valueInvoke(v ref, args []ref) (ref, bool)
// func valueInvoke(v ref, args []ref) (ref, bool)
"syscall/js.valueInvoke"
:
(
sp
)
=>
{
"syscall/js.valueInvoke"
:
(
ret_addr
,
v_ref
,
args_ptr
,
args_len
,
args_cap
)
=>
{
sp
>>>=
0
;
try
{
try
{
const
v
=
loadValue
(
sp
+
8
);
const
v
=
unboxValue
(
v_ref
);
const
args
=
loadSliceOfValues
(
sp
+
16
);
const
args
=
loadSliceOfValues
(
args_ptr
,
args_len
,
args_cap
);
const
result
=
Reflect
.
apply
(
v
,
undefined
,
args
);
storeValue
(
ret_addr
,
Reflect
.
apply
(
v
,
undefined
,
args
));
sp
=
this
.
_inst
.
exports
.
getsp
()
>>>
0
;
// see comment above
mem
().
setUint8
(
ret_addr
+
8
,
1
);
storeValue
(
sp
+
40
,
result
);
this
.
mem
.
setUint8
(
sp
+
48
,
1
);
}
catch
(
err
)
{
}
catch
(
err
)
{
sp
=
this
.
_inst
.
exports
.
getsp
()
>>>
0
;
// see comment above
storeValue
(
ret_addr
,
err
);
storeValue
(
sp
+
40
,
err
);
mem
().
setUint8
(
ret_addr
+
8
,
0
);
this
.
mem
.
setUint8
(
sp
+
48
,
0
);
}
}
},
},
// func valueNew(v ref, args []ref) (ref, bool)
// func valueNew(v ref, args []ref) (ref, bool)
"syscall/js.valueNew"
:
(
sp
)
=>
{
"syscall/js.valueNew"
:
(
ret_addr
,
v_ref
,
args_ptr
,
args_len
,
args_cap
)
=>
{
sp
>>>=
0
;
const
v
=
unboxValue
(
v_ref
);
const
args
=
loadSliceOfValues
(
args_ptr
,
args_len
,
args_cap
);
try
{
try
{
const
v
=
loadValue
(
sp
+
8
);
storeValue
(
ret_addr
,
Reflect
.
construct
(
v
,
args
));
const
args
=
loadSliceOfValues
(
sp
+
16
);
mem
().
setUint8
(
ret_addr
+
8
,
1
);
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
)
{
}
catch
(
err
)
{
sp
=
this
.
_inst
.
exports
.
getsp
()
>>>
0
;
// see comment above
storeValue
(
ret_addr
,
err
);
storeValue
(
sp
+
40
,
err
);
mem
().
setUint8
(
ret_addr
+
8
,
0
);
this
.
mem
.
setUint8
(
sp
+
48
,
0
);
}
}
},
},
// func valueLength(v ref) int
// func valueLength(v ref) int
"syscall/js.valueLength"
:
(
sp
)
=>
{
"syscall/js.valueLength"
:
(
v_ref
)
=>
{
sp
>>>=
0
;
return
unboxValue
(
v_ref
).
length
;
setInt64
(
sp
+
16
,
parseInt
(
loadValue
(
sp
+
8
).
length
));
},
},
// valuePrepareString(v ref) (ref, int)
// valuePrepareString(v ref) (ref, int)
"syscall/js.valuePrepareString"
:
(
sp
)
=>
{
"syscall/js.valuePrepareString"
:
(
ret_addr
,
v_ref
)
=>
{
sp
>>>=
0
;
const
s
=
String
(
unboxValue
(
v_ref
))
;
const
str
=
encoder
.
encode
(
String
(
loadValue
(
sp
+
8
))
);
const
str
=
encoder
.
encode
(
s
);
storeValue
(
sp
+
16
,
str
);
storeValue
(
ret_addr
,
str
);
setInt64
(
sp
+
24
,
str
.
length
);
mem
().
setInt32
(
ret_addr
+
8
,
str
.
length
,
true
);
},
},
// valueLoadString(v ref, b []byte)
// valueLoadString(v ref, b []byte)
"syscall/js.valueLoadString"
:
(
sp
)
=>
{
"syscall/js.valueLoadString"
:
(
v_ref
,
slice_ptr
,
slice_len
,
slice_cap
)
=>
{
sp
>>>=
0
;
const
str
=
unboxValue
(
v_ref
);
const
str
=
loadValue
(
sp
+
8
);
loadSlice
(
slice_ptr
,
slice_len
,
slice_cap
).
set
(
str
);
loadSlice
(
sp
+
16
).
set
(
str
);
},
},
// func valueInstanceOf(v ref, t ref) bool
// func valueInstanceOf(v ref, t ref) bool
"syscall/js.valueInstanceOf"
:
(
sp
)
=>
{
"syscall/js.valueInstanceOf"
:
(
v_ref
,
t_ref
)
=>
{
sp
>>>=
0
;
return
unboxValue
(
v_ref
)
instanceof
unboxValue
(
t_ref
);
this
.
mem
.
setUint8
(
sp
+
24
,
(
loadValue
(
sp
+
8
)
instanceof
loadValue
(
sp
+
16
))
?
1
:
0
);
},
},
// func copyBytesToGo(dst []byte, src ref) (int, bool)
// func copyBytesToGo(dst []byte, src ref) (int, bool)
"syscall/js.copyBytesToGo"
:
(
sp
)
=>
{
"syscall/js.copyBytesToGo"
:
(
ret_addr
,
dest_addr
,
dest_len
,
dest_cap
,
src_ref
)
=>
{
sp
>>>=
0
;
let
num_bytes_copied_addr
=
ret_addr
;
const
dst
=
loadSlice
(
sp
+
8
);
let
returned_status_addr
=
ret_addr
+
4
;
// Address of returned boolean status variable
const
src
=
loadValue
(
sp
+
32
);
const
dst
=
loadSlice
(
dest_addr
,
dest_len
);
const
src
=
unboxValue
(
src_ref
);
if
(
!
(
src
instanceof
Uint8Array
||
src
instanceof
Uint8ClampedArray
))
{
if
(
!
(
src
instanceof
Uint8Array
||
src
instanceof
Uint8ClampedArray
))
{
this
.
mem
.
setUint8
(
sp
+
48
,
0
);
mem
().
setUint8
(
returned_status_addr
,
0
);
// Return "not ok" status
return
;
return
;
}
}
const
toCopy
=
src
.
subarray
(
0
,
dst
.
length
);
const
toCopy
=
src
.
subarray
(
0
,
dst
.
length
);
dst
.
set
(
toCopy
);
dst
.
set
(
toCopy
);
setInt64
(
sp
+
40
,
toCopy
.
length
);
mem
().
setUint32
(
num_bytes_copied_addr
,
toCopy
.
length
,
true
);
this
.
mem
.
setUint8
(
sp
+
48
,
1
);
mem
().
setUint8
(
returned_status_addr
,
1
);
// Return "ok" status
},
},
// func copyBytesToJS(dst ref, src []byte) (int, bool)
// copyBytesToJS(dst ref, src []byte) (int, bool)
"syscall/js.copyBytesToJS"
:
(
sp
)
=>
{
// Originally copied from upstream Go project, then modified:
sp
>>>=
0
;
// https://github.com/golang/go/blob/3f995c3f3b43033013013e6c7ccc93a9b1411ca9/misc/wasm/wasm_exec.js#L404-L416
const
dst
=
loadValue
(
sp
+
8
);
"syscall/js.copyBytesToJS"
:
(
ret_addr
,
dst_ref
,
src_addr
,
src_len
,
src_cap
)
=>
{
const
src
=
loadSlice
(
sp
+
16
);
let
num_bytes_copied_addr
=
ret_addr
;
let
returned_status_addr
=
ret_addr
+
4
;
// Address of returned boolean status variable
const
dst
=
unboxValue
(
dst_ref
);
const
src
=
loadSlice
(
src_addr
,
src_len
);
if
(
!
(
dst
instanceof
Uint8Array
||
dst
instanceof
Uint8ClampedArray
))
{
if
(
!
(
dst
instanceof
Uint8Array
||
dst
instanceof
Uint8ClampedArray
))
{
this
.
mem
.
setUint8
(
sp
+
48
,
0
);
mem
().
setUint8
(
returned_status_addr
,
0
);
// Return "not ok" status
return
;
return
;
}
}
const
toCopy
=
src
.
subarray
(
0
,
dst
.
length
);
const
toCopy
=
src
.
subarray
(
0
,
dst
.
length
);
dst
.
set
(
toCopy
);
dst
.
set
(
toCopy
);
setInt64
(
sp
+
40
,
toCopy
.
length
);
mem
().
setUint32
(
num_bytes_copied_addr
,
toCopy
.
length
,
true
);
this
.
mem
.
setUint8
(
sp
+
48
,
1
);
mem
().
setUint8
(
returned_status_addr
,
1
);
// Return "ok" status
},
},
"debug"
:
(
value
)
=>
{
console
.
log
(
value
);
},
},
}
};
};
// Go 1.20 uses 'env'. Go 1.21 uses 'gojs'.
// For compatibility, we use both as long as Go 1.20 is supported.
this
.
importObject
.
env
=
this
.
importObject
.
gojs
;
}
}
async
run
(
instance
)
{
async
run
(
instance
)
{
if
(
!
(
instance
instanceof
WebAssembly
.
Instance
))
{
throw
new
Error
(
"Go.run: WebAssembly.Instance expected"
);
}
this
.
_inst
=
instance
;
this
.
_inst
=
instance
;
this
.
mem
=
new
DataView
(
this
.
_inst
.
exports
.
mem
.
buffer
);
this
.
_values
=
[
this
.
_values
=
[
// JS values that Go currently has references to, indexed by reference id
// JS values that Go currently has references to, indexed by reference id
NaN
,
NaN
,
0
,
0
,
null
,
null
,
true
,
true
,
false
,
false
,
globalThis
,
global
,
this
,
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
.
_goRefCounts
=
[];
// 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
this
.
_ids
=
new
Map
();
// mapping from JS values to reference ids
[
0
,
1
],
[
null
,
2
],
[
true
,
3
],
[
false
,
4
],
[
globalThis
,
5
],
[
this
,
6
],
]);
this
.
_idPool
=
[];
// unused ids that have been garbage collected
this
.
_idPool
=
[];
// unused ids that have been garbage collected
this
.
exited
=
false
;
// whether the Go program has exited
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.
while
(
true
)
{
let
offset
=
4096
;
const
callbackPromise
=
new
Promise
((
resolve
)
=>
{
this
.
_resolveCallbackPromise
=
()
=>
{
const
strPtr
=
(
str
)
=>
{
if
(
this
.
exited
)
{
const
ptr
=
offset
;
throw
new
Error
(
"bad callback: Go program has already exited"
);
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
;
setTimeout
(
resolve
,
0
);
// make sure it is asynchronous
};
};
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
;
});
});
this
.
_inst
.
exports
.
_start
();
// 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
)
{
if
(
this
.
exited
)
{
this
.
_resolveExitPromise
();
break
;
}
await
callbackPromise
;
}
}
await
this
.
_exitPromise
;
}
}
_resume
()
{
_resume
()
{
...
@@ -557,5 +565,22 @@
...
@@ -557,5 +565,22 @@
return
event
.
result
;
return
event
.
result
;
};
};
}
}
};
if
(
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
();
WebAssembly
.
instantiate
(
fs
.
readFileSync
(
process
.
argv
[
2
]),
go
.
importObject
)
.
then
((
result
)
=>
{
return
go
.
run
(
result
.
instance
);
})
.
catch
((
err
)
=>
{
console
.
error
(
err
);
process
.
exit
(
1
);
});
}
}
})();
})();
web/src/main.tsx
View file @
ebcf43c9
...
@@ -17,8 +17,7 @@ import theme from "./theme";
...
@@ -17,8 +17,7 @@ import theme from "./theme";
(
async
()
=>
{
(
async
()
=>
{
const
go
=
new
window
.
Go
();
const
go
=
new
window
.
Go
();
const
responsePromise
=
fetch
(
gomarkWasm
);
const
{
instance
}
=
await
WebAssembly
.
instantiateStreaming
(
fetch
(
gomarkWasm
),
go
.
importObject
);
const
{
instance
}
=
await
WebAssembly
.
instantiateStreaming
(
responsePromise
,
go
.
importObject
);
go
.
run
(
instance
);
go
.
run
(
instance
);
const
container
=
document
.
getElementById
(
"root"
);
const
container
=
document
.
getElementById
(
"root"
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment