Public
Edited
Jun 3
Insert cell
Insert cell
TSGO_VERSION = '2025.6.2'
Insert cell
mutable wasmInitCache = Object.create(null)
Insert cell
createTsgoInstance = async () => {
if (wasmInitCache[TSGO_VERSION]) {
// an instantiated module can only be run once
return WebAssembly.instantiate(wasmInitCache[TSGO_VERSION].module, go.importObject)
}
const inst = await WebAssembly.instantiateStreaming(
fetch(`https://unpkg.com/tsgo-wasm@${TSGO_VERSION}/tsgo.wasm`), go.importObject)
mutable wasmInitCache[TSGO_VERSION] = inst
return inst.instance
}
Insert cell
wasmexec = fetch('https://cdn.jsdelivr.net/gh/golang/go/lib/wasm/wasm_exec.js')
.then(x => x.text()).then(s => {
const body = s.trimEnd().match(/\(\(\)\s*=>\s*{([^]+)}\)\(\);$/)[1]
const fn = new Function(/*'globalThis', */body)
for (let k of ['Go', 'fs', 'process', 'path']) {
delete globalThis[k]
}
fn()
globalThis.process.cwd = () => '/'
const outbufs = {}
const decoder = new TextDecoder('utf-8')
let exitCode = null
globalThis.fs.writeSync = (fd, buf) => {
console.warn('writeSync', fd, buf)
if (!(fd in outbufs)) {
outbufs[fd] = []
}
const dest = outbufs[fd]
dest.push(decoder.decode(buf))
return buf.length
}

const fdtable = [null, null, null]

// copied from wasm-exec
function enosys() {
const err = new Error('unimp')
err.code = 'ENOSYS'
return err
}
globalThis.fs.open = (path, flags, mode, callback) => {
const desc = {path, flags, mode}
const fd = fdtable.length
fdtable.push(desc)
// hack!
if (path == '/XXX.ts') {
desc.content = new TextEncoder().encode(TS_SOURCE)
}
// console.log('open', desc, '-> fd', fd)
callback(null, fd)
}
globalThis.fs.read = (fd, buffer, offset, length, position, callback) => {
// console.log('read', fd, buffer, offset, length, position)
if (fdtable[fd]?.content) {
fdtable[fd].offset ??= 0
const slice = fdtable[fd].content.slice(fdtable[fd].offset, fdtable[fd].offset + length)
buffer.set(slice, offset)
fdtable[fd].offset += slice.length
return callback(null, slice.length)
}
callback(enosys())
}
return {
Go: globalThis.Go,
outbufs,
fdtable,
init: () => { fdtable.length = 3; delete outbufs[1]; delete outbufs[2]; delete outbufs[4] },
}

// isolating the environment seems not working... Go's wasm runtime assumes a global environment
// const inKeys = ['crypto', 'performance', 'TextEncoder', 'TextDecoder']
// const win = {}
// for (const k of inKeys) {
// win[k] = globalThis[k]
// }
// fn(win)
// const outKeys = ['Go', 'fs', 'process', 'path']
// for (const k of outKeys) {
// globalThis[k] = win[k]
// }
// return win
})
Insert cell
go = {
wasmexec
const go = new wasmexec.Go()
go.exitCode = null
go.exit = function(code) {
return this.exitCode = code
}
return go
}
Insert cell
TS_SOURCE = `enum E {
AAA = 101,
BBB,
}`
Insert cell
{
try {
go.argv = ['tsc', '--pretty', 'false', 'XXX.ts']
const tsgo = await createTsgoInstance()
wasmexec.init()

const ts0 = Date.now()
await go.run(tsgo)
const ts1 = Date.now()
if (wasmexec.outbufs[1]) {
console.info('stdout', wasmexec.outbufs[2].join(''))
}
if (wasmexec.outbufs[2]) {
console.warn('stderr', wasmexec.outbufs[2].join(''))
}
return (wasmexec.outbufs[4] ?? []).join('') + `\n=== Exit code = ${go.exitCode}; time elapsed = ${ts1 - ts0}ms ===`
} catch (err) {
console.error(err)
return err
}
}
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more