vendor: 5,084 bytes, lines 1-204
1// Copyright 2018 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5'use strict'; 6 7(() => { 8 const enosys = () => { 9 const err = new Error('not implemented'); 10 err.code = 'ENOSYS'; 11 return err; 12 }; 13 14 if (!globalThis.fs) { 15 let outputBuf = ''; 16 globalThis.fs = { 17 constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1, O_DIRECTORY: -1 }, // unused 18 writeSync(fd, buf) { 19 outputBuf += decoder.decode(buf); 20 const nl = outputBuf.lastIndexOf('\n'); 21 if (nl != -1) { 22 console.log(outputBuf.substring(0, nl)); 23 outputBuf = outputBuf.substring(nl + 1); 24 } 25 return buf.length; 26 }, 27 write(fd, buf, offset, length, position, callback) { 28 if (offset !== 0 || length !== buf.length || position !== null) { 29 callback(enosys()); 30 return; 31 } 32 const n = this.writeSync(fd, buf); 33 callback(null, n); 34 }, 35 chmod(path, mode, callback) { 36 callback(enosys()); 37 }, 38 chown(path, uid, gid, callback) { 39 callback(enosys()); 40 }, 41 close(fd, callback) { 42 callback(enosys()); 43 }, 44 fchmod(fd, mode, callback) { 45 callback(enosys()); 46 }, 47 fchown(fd, uid, gid, callback) { 48 callback(enosys()); 49 }, 50 fstat(fd, callback) { 51 callback(enosys()); 52 }, 53 fsync(fd, callback) { 54 callback(null); 55 }, 56 ftruncate(fd, length, callback) { 57 callback(enosys()); 58 }, 59 lchown(path, uid, gid, callback) { 60 callback(enosys()); 61 }, 62 link(path, link, callback) { 63 callback(enosys()); 64 }, 65 lstat(path, callback) { 66 callback(enosys()); 67 }, 68 mkdir(path, perm, callback) { 69 callback(enosys()); 70 }, 71 open(path, flags, mode, callback) { 72 callback(enosys()); 73 }, 74 read(fd, buffer, offset, length, position, callback) { 75 callback(enosys()); 76 }, 77 readdir(path, callback) { 78 callback(enosys()); 79 }, 80 readlink(path, callback) { 81 callback(enosys()); 82 }, 83 rename(from, to, callback) { 84 callback(enosys()); 85 }, 86 rmdir(path, callback) { 87 callback(enosys()); 88 }, 89 stat(path, callback) { 90 callback(enosys()); 91 }, 92 symlink(path, link, callback) { 93 callback(enosys()); 94 }, 95 truncate(path, length, callback) { 96 callback(enosys()); 97 }, 98 unlink(path, callback) { 99 callback(enosys()); 100 }, 101 utimes(path, atime, mtime, callback) { 102 callback(enosys()); 103 }, 104 }; 105 } 106 107 if (!globalThis.process) { 108 globalThis.process = { 109 getuid() { 110 return -1; 111 }, 112 getgid() { 113 return -1; 114 }, 115 geteuid() { 116 return -1; 117 }, 118 getegid() { 119 return -1; 120 }, 121 getgroups() { 122 throw enosys(); 123 }, 124 pid: -1, 125 ppid: -1, 126 umask() { 127 throw enosys(); 128 }, 129 cwd() { 130 throw enosys(); 131 }, 132 chdir() { 133 throw enosys(); 134 }, 135 }; 136 } 137 138 if (!globalThis.path) { 139 globalThis.path = { 140 resolve(...pathSegments) { 141 return pathSegments.join('/'); 142 }, 143 }; 144 } 145 146 if (!globalThis.crypto) { 147 throw new Error('globalThis.crypto is not available, polyfill required (crypto.getRandomValues only)'); 148 } 149 150 if (!globalThis.performance) { 151 throw new Error('globalThis.performance is not available, polyfill required (performance.now only)'); 152 } 153 154 if (!globalThis.TextEncoder) { 155 throw new Error('globalThis.TextEncoder is not available, polyfill required'); 156 } 157 158 if (!globalThis.TextDecoder) { 159 throw new Error('globalThis.TextDecoder is not available, polyfill required'); 160 } 161 162 const encoder = new TextEncoder('utf-8'); 163 const decoder = new TextDecoder('utf-8'); 164 165 globalThis.Go = class { 166 constructor() { 167 this.argv = ['js']; 168 this.env = {}; 169 this.exit = (code) => { 170 if (code !== 0) { 171 console.warn('exit code:', code); 172 } 173 }; 174 this._exitPromise = new Promise((resolve) => { 175 this._resolveExitPromise = resolve; 176 }); 177 this._pendingEvent = null; 178 this._scheduledTimeouts = new Map(); 179 this._nextCallbackTimeoutID = 1; 180 181 const setInt64 = (addr, v) => { 182 this.mem.setUint32(addr + 0, v, true); 183 this.mem.setUint32(addr + 4, Math.floor(v / 4294967296), true); 184 }; 185 186 const getInt64 = (addr) => { 187 const low = this.mem.getUint32(addr + 0, true); 188 const high = this.mem.getInt32(addr + 4, true); 189 return low + high * 4294967296; 190 }; 191 192 const loadValue = (addr) => { 193 const f = this.mem.getFloat64(addr, true); 194 if (f === 0) { 195 return undefined; 196 } 197 if (!isNaN(f)) { 198 return f; 199 } 200 201 const id = this.mem.getUint32(addr, true); 202 return this._values[id]; 203 }; 204
205 const storeValue = (addr, v) => { 206 const nanHead = 0x7ff80000; 207 208 if (typeof v === 'number' && v !== 0) { 209 if (isNaN(v)) { 210 this.mem.setUint32(addr + 4, nanHead, true); 211 this.mem.setUint32(addr, 0, true); 212 return; 213 } 214 this.mem.setFloat64(addr, v, true); 215 return; 216 } 217 218 if (v === undefined) { 219 this.mem.setFloat64(addr, 0, true); 220 return; 221 } 222 223 let id = this._ids.get(v); 224 if (id === undefined) { 225 id = this._idPool.pop(); 226 if (id === undefined) { 227 id = this._values.length; 228 } 229 this._values[id] = v; 230 this._goRefCounts[id] = 0; 231 this._ids.set(v, id); 232 } 233 this._goRefCounts[id]++; 234 let typeFlag = 0; 235 switch (typeof v) { 236 case 'object': 237 if (v !== null) { 238 typeFlag = 1; 239 } 240 break; 241 case 'string': 242 typeFlag = 2; 243 break; 244 case 'symbol': 245 typeFlag = 3; 246 break; 247 case 'function': 248 typeFlag = 4; 249 break; 250 } 251 this.mem.setUint32(addr + 4, nanHead | typeFlag, true); 252 this.mem.setUint32(addr, id, true); 253 }; 254 255 const loadSlice = (addr) => { 256 const array = getInt64(addr + 0); 257 const len = getInt64(addr + 8); 258 return new Uint8Array(this._inst.exports.mem.buffer, array, len); 259 }; 260 261 const loadSliceOfValues = (addr) => { 262 const array = getInt64(addr + 0); 263 const len = getInt64(addr + 8); 264 const a = new Array(len); 265 for (let i = 0; i < len; i++) { 266 a[i] = loadValue(array + i * 8); 267 } 268 return a; 269 }; 270 271 const loadString = (addr) => { 272 const saddr = getInt64(addr + 0); 273 const len = getInt64(addr + 8); 274 return decoder.decode(new DataView(this._inst.exports.mem.buffer, saddr, len)); 275 }; 276 277 const testCallExport = (a, b) => { 278 this._inst.exports.testExport0(); 279 return this._inst.exports.testExport(a, b); 280 }; 281 282 const timeOrigin = Date.now() - performance.now(); 283 this.importObject = { 284 _gotest: { 285 add: (a, b) => a + b, 286 callExport: testCallExport, 287 }, 288 gojs: { 289 // Go's SP does not change as long as no Go code is running. Some operations (e.g. calls, getters and setters) 290 // may synchronously trigger a Go event handler. This makes Go code get executed in the middle of the imported 291 // function. A goroutine can switch to a new stack if the current stack is too small (see morestack function). 292 // This changes the SP, thus we have to update the SP used by the imported function. 293 294 // func wasmExit(code int32) 295 'runtime.wasmExit': (sp) => { 296 sp >>>= 0; 297 const code = this.mem.getInt32(sp + 8, true); 298 this.exited = true; 299 delete this._inst; 300 delete this._values; 301 delete this._goRefCounts; 302 delete this._ids; 303 delete this._idPool; 304 this.exit(code); 305 }, 306 307 // func wasmWrite(fd uintptr, p unsafe.Pointer, n int32) 308 'runtime.wasmWrite': (sp) => { 309 sp >>>= 0; 310 const fd = getInt64(sp + 8); 311 const p = getInt64(sp + 16); 312 const n = this.mem.getInt32(sp + 24, true); 313 fs.writeSync(fd, new Uint8Array(this._inst.exports.mem.buffer, p, n)); 314 }, 315 316 // func resetMemoryDataView() 317 'runtime.resetMemoryDataView': () => { 318 this.mem = new DataView(this._inst.exports.mem.buffer); 319 }, 320 321 // func nanotime1() int64 322 'runtime.nanotime1': (sp) => { 323 sp >>>= 0; 324 setInt64(sp + 8, (timeOrigin + performance.now()) * 1000000); 325 }, 326 327 // func walltime() (sec int64, nsec int32) 328 'runtime.walltime': (sp) => { 329 sp >>>= 0; 330 const msec = new Date().getTime(); 331 setInt64(sp + 8, msec / 1000); 332 this.mem.setInt32(sp + 16, (msec % 1000) * 1000000, true); 333 }, 334 335 // func scheduleTimeoutEvent(delay int64) int32 336 'runtime.scheduleTimeoutEvent': (sp) => { 337 sp >>>= 0; 338 const id = this._nextCallbackTimeoutID; 339 this._nextCallbackTimeoutID++; 340 this._scheduledTimeouts.set( 341 id, 342 setTimeout( 343 () => { 344 this._resume(); 345 while (this._scheduledTimeouts.has(id)) { 346 // for some reason Go failed to register the timeout event, log and try again 347 // (temporary workaround for https://github.com/golang/go/issues/28975) 348 console.warn('scheduleTimeoutEvent: missed timeout event'); 349 this._resume(); 350 } 351 }, 352 getInt64(sp + 8) 353 ) 354 ); 355 this.mem.setInt32(sp + 16, id, true); 356 }, 357 358 // func clearTimeoutEvent(id int32) 359 'runtime.clearTimeoutEvent': (sp) => { 360 sp >>>= 0; 361 const id = this.mem.getInt32(sp + 8, true); 362 clearTimeout(this._scheduledTimeouts.get(id)); 363 this._scheduledTimeouts.delete(id); 364 }, 365 366 // func getRandomData(r []byte) 367 'runtime.getRandomData': (sp) => { 368 sp >>>= 0; 369 crypto.getRandomValues(loadSlice(sp + 8)); 370 }, 371 372 // func finalizeRef(v ref) 373 'syscall/js.finalizeRef': (sp) => { 374 sp >>>= 0; 375 const id = this.mem.getUint32(sp + 8, true); 376 this._goRefCounts[id]--; 377 if (this._goRefCounts[id] === 0) { 378 const v = this._values[id]; 379 this._values[id] = null; 380 this._ids.delete(v);
vendor: 8,694 bytes, lines 381-639
381 this._idPool.push(id); 382 } 383 }, 384 385 // func stringVal(value string) ref 386 'syscall/js.stringVal': (sp) => { 387 sp >>>= 0; 388 storeValue(sp + 24, loadString(sp + 8)); 389 }, 390 391 // func valueGet(v ref, p string) ref 392 'syscall/js.valueGet': (sp) => { 393 sp >>>= 0; 394 const result = Reflect.get(loadValue(sp + 8), loadString(sp + 16)); 395 sp = this._inst.exports.getsp() >>> 0; // see comment above 396 storeValue(sp + 32, result); 397 }, 398 399 // func valueSet(v ref, p string, x ref) 400 'syscall/js.valueSet': (sp) => { 401 sp >>>= 0; 402 Reflect.set(loadValue(sp + 8), loadString(sp + 16), loadValue(sp + 32)); 403 }, 404 405 // func valueDelete(v ref, p string) 406 'syscall/js.valueDelete': (sp) => { 407 sp >>>= 0; 408 Reflect.deleteProperty(loadValue(sp + 8), loadString(sp + 16)); 409 }, 410 411 // func valueIndex(v ref, i int) ref 412 'syscall/js.valueIndex': (sp) => { 413 sp >>>= 0; 414 storeValue(sp + 24, Reflect.get(loadValue(sp + 8), getInt64(sp + 16))); 415 }, 416 417 // valueSetIndex(v ref, i int, x ref) 418 'syscall/js.valueSetIndex': (sp) => { 419 sp >>>= 0; 420 Reflect.set(loadValue(sp + 8), getInt64(sp + 16), loadValue(sp + 24)); 421 }, 422 423 // func valueCall(v ref, m string, args []ref) (ref, bool) 424 'syscall/js.valueCall': (sp) => { 425 sp >>>= 0; 426 try { 427 const v = loadValue(sp + 8); 428 const m = Reflect.get(v, loadString(sp + 16)); 429 const args = loadSliceOfValues(sp + 32); 430 const result = Reflect.apply(m, v, args); 431 sp = this._inst.exports.getsp() >>> 0; // see comment above 432 storeValue(sp + 56, result); 433 this.mem.setUint8(sp + 64, 1); 434 } catch (err) { 435 sp = this._inst.exports.getsp() >>> 0; // see comment above 436 storeValue(sp + 56, err); 437 this.mem.setUint8(sp + 64, 0); 438 } 439 }, 440 441 // func valueInvoke(v ref, args []ref) (ref, bool) 442 'syscall/js.valueInvoke': (sp) => { 443 sp >>>= 0; 444 try { 445 const v = loadValue(sp + 8); 446 const args = loadSliceOfValues(sp + 16); 447 const result = Reflect.apply(v, undefined, args); 448 sp = this._inst.exports.getsp() >>> 0; // see comment above 449 storeValue(sp + 40, result); 450 this.mem.setUint8(sp + 48, 1); 451 } catch (err) { 452 sp = this._inst.exports.getsp() >>> 0; // see comment above 453 storeValue(sp + 40, err); 454 this.mem.setUint8(sp + 48, 0); 455 } 456 }, 457 458 // func valueNew(v ref, args []ref) (ref, bool) 459 'syscall/js.valueNew': (sp) => { 460 sp >>>= 0; 461 try { 462 const v = loadValue(sp + 8); 463 const args = loadSliceOfValues(sp + 16); 464 const result = Reflect.construct(v, args); 465 sp = this._inst.exports.getsp() >>> 0; // see comment above 466 storeValue(sp + 40, result); 467 this.mem.setUint8(sp + 48, 1); 468 } catch (err) { 469 sp = this._inst.exports.getsp() >>> 0; // see comment above 470 storeValue(sp + 40, err); 471 this.mem.setUint8(sp + 48, 0); 472 } 473 }, 474 475 // func valueLength(v ref) int 476 'syscall/js.valueLength': (sp) => { 477 sp >>>= 0; 478 setInt64(sp + 16, parseInt(loadValue(sp + 8).length)); 479 }, 480 481 // valuePrepareString(v ref) (ref, int) 482 'syscall/js.valuePrepareString': (sp) => { 483 sp >>>= 0; 484 const str = encoder.encode(String(loadValue(sp + 8))); 485 storeValue(sp + 16, str); 486 setInt64(sp + 24, str.length); 487 }, 488 489 // valueLoadString(v ref, b []byte) 490 'syscall/js.valueLoadString': (sp) => { 491 sp >>>= 0; 492 const str = loadValue(sp + 8); 493 loadSlice(sp + 16).set(str); 494 }, 495 496 // func valueInstanceOf(v ref, t ref) bool 497 'syscall/js.valueInstanceOf': (sp) => { 498 sp >>>= 0; 499 this.mem.setUint8(sp + 24, loadValue(sp + 8) instanceof loadValue(sp + 16) ? 1 : 0); 500 }, 501 502 // func copyBytesToGo(dst []byte, src ref) (int, bool) 503 'syscall/js.copyBytesToGo': (sp) => { 504 sp >>>= 0; 505 const dst = loadSlice(sp + 8); 506 const src = loadValue(sp + 32); 507 if (!(src instanceof Uint8Array || src instanceof Uint8ClampedArray)) { 508 this.mem.setUint8(sp + 48, 0); 509 return; 510 } 511 const toCopy = src.subarray(0, dst.length); 512 dst.set(toCopy); 513 setInt64(sp + 40, toCopy.length); 514 this.mem.setUint8(sp + 48, 1); 515 }, 516 517 // func copyBytesToJS(dst ref, src []byte) (int, bool) 518 'syscall/js.copyBytesToJS': (sp) => { 519 sp >>>= 0; 520 const dst = loadValue(sp + 8); 521 const src = loadSlice(sp + 16); 522 if (!(dst instanceof Uint8Array || dst instanceof Uint8ClampedArray)) { 523 this.mem.setUint8(sp + 48, 0); 524 return; 525 } 526 const toCopy = src.subarray(0, dst.length); 527 dst.set(toCopy); 528 setInt64(sp + 40, toCopy.length); 529 this.mem.setUint8(sp + 48, 1); 530 }, 531 532 debug: (value) => { 533 console.log(value); 534 }, 535 }, 536 }; 537 } 538 539 async run(instance) { 540 if (!(instance instanceof WebAssembly.Instance)) { 541 throw new Error('Go.run: WebAssembly.Instance expected'); 542 } 543 this._inst = instance; 544 this.mem = new DataView(this._inst.exports.mem.buffer); 545 this._values = [ 546 // JS values that Go currently has references to, indexed by reference id 547 NaN, 548 0, 549 null, 550 true, 551 false, 552 globalThis, 553 this, 554 ]; 555 this._goRefCounts = new Array(this._values.length).fill(Infinity); // number of references that Go has to a JS value, indexed by reference id 556 this._ids = new Map([ 557 // mapping from JS values to reference ids 558 [0, 1], 559 [null, 2], 560 [true, 3], 561 [false, 4], 562 [globalThis, 5], 563 [this, 6], 564 ]); 565 this._idPool = []; // unused ids that have been garbage collected 566 this.exited = false; // whether the Go program has exited 567 568 // Pass command line arguments and environment variables to WebAssembly by writing them to the linear memory. 569 let offset = 4096; 570 571 const strPtr = (str) => { 572 const ptr = offset; 573 const bytes = encoder.encode(str + '\0'); 574 new Uint8Array(this.mem.buffer, offset, bytes.length).set(bytes); 575 offset += bytes.length; 576 if (offset % 8 !== 0) { 577 offset += 8 - (offset % 8); 578 } 579 return ptr; 580 }; 581 582 const argc = this.argv.length; 583 584 const argvPtrs = []; 585 this.argv.forEach((arg) => { 586 argvPtrs.push(strPtr(arg)); 587 }); 588 argvPtrs.push(0); 589 590 const keys = Object.keys(this.env).sort(); 591 keys.forEach((key) => { 592 argvPtrs.push(strPtr(`${key}=${this.env[key]}`)); 593 }); 594 argvPtrs.push(0); 595 596 const argv = offset; 597 argvPtrs.forEach((ptr) => { 598 this.mem.setUint32(offset, ptr, true); 599 this.mem.setUint32(offset + 4, 0, true); 600 offset += 8; 601 }); 602 603 // The linker guarantees global data starts from at least wasmMinDataAddr. 604 // Keep in sync with cmd/link/internal/ld/data.go:wasmMinDataAddr. 605 const wasmMinDataAddr = 4096 + 8192; 606 if (offset >= wasmMinDataAddr) { 607 throw new Error('total length of command line and environment variables exceeds limit'); 608 } 609 610 this._inst.exports.run(argc, argv); 611 if (this.exited) { 612 this._resolveExitPromise(); 613 } 614 await this._exitPromise; 615 } 616 617 _resume() { 618 if (this.exited) { 619 throw new Error('Go program has already exited'); 620 } 621 this._inst.exports.resume(); 622 if (this.exited) { 623 this._resolveExitPromise(); 624 } 625 } 626 627 _makeFuncWrapper(id) { 628 // eslint-disable-next-line @typescript-eslint/no-this-alias 629 const go = this; 630 631 return function () { 632 const event = { id: id, this: this, args: arguments }; 633 go._pendingEvent = event; 634 go._resume(); 635 return event.result; 636 }; 637 } 638 }; 639})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.