diff --git a/lib/loader/index.js b/lib/loader/index.js index 31edb71f..224c674d 100644 --- a/lib/loader/index.js +++ b/lib/loader/index.js @@ -23,17 +23,24 @@ function getStringImpl(U32, U16, ptr) { function preInstantiate(imports) { var baseModule = {}; - // add the internal abort function that is called when an assertion fails or an error is thrown - if (!imports.env) imports.env = {}; - if (!imports.env.abort) imports.env.abort = function abort(mesg, file, line, colm) { - var memory = baseModule.memory || imports.env.memory; // prefer exported, otherwise try imported - function getString(memory, ptr) { - if (!memory) return ""; - var buffer = memory.buffer; - return getStringImpl(new Uint32Array(buffer), new Uint16Array(buffer), ptr); - } + function getString(memory, ptr) { + if (!memory) return ""; + var buffer = memory.buffer; + return getStringImpl(new Uint32Array(buffer), new Uint16Array(buffer), ptr); + } + + // add common imports used by stdlib for convenience + var env = (imports.env = imports.env || {}); + env.abort = env.abort || function abort(mesg, file, line, colm) { + var memory = baseModule.memory || env.memory; // prefer exported, otherwise try imported throw Error("abort: " + getString(memory, mesg) + " at " + getString(memory, file) + ":" + line + ":" + colm); } + env.trace = env.trace || function trace(mesg, n) { + var memory = baseModule.memory || env.memory; + console.log("trace: " + getString(memory, mesg) + (n ? " " : "") + Array.prototype.slice.call(arguments, 2, 2 + n).join(", ")); + } + imports.Math = imports.Math || Math; + imports.Date = imports.Date || Date; return baseModule; } @@ -176,6 +183,10 @@ function postInstantiate(baseModule, instance) { baseModule.getFunction = getFunction; + // Pull basic exports to baseModule so code in preInstantiate can use them + baseModule.memory = baseModule.memory || memory; + baseModule.table = baseModule.table || table; + // Demangle exports and provide the usual utility on the prototype return demangle(rawExports, Object.defineProperties(baseModule, { I8: { get: function() { checkMem(); return I8; } }, diff --git a/lib/loader/tests/assembly/index.ts b/lib/loader/tests/assembly/index.ts index 98a26f59..1c60c327 100644 --- a/lib/loader/tests/assembly/index.ts +++ b/lib/loader/tests/assembly/index.ts @@ -60,3 +60,7 @@ export const varadd_ptr = varadd; export function calladd(fn: (a: i32, b: i32) => i32, a: i32, b: i32): i32 { return fn(a, b); } + +export function dotrace(num: f64): void { + trace("The answer is", 1, num); +} diff --git a/lib/loader/tests/build/untouched.wasm b/lib/loader/tests/build/untouched.wasm index 18ec0b8e..656568df 100644 Binary files a/lib/loader/tests/build/untouched.wasm and b/lib/loader/tests/build/untouched.wasm differ diff --git a/lib/loader/tests/index.js b/lib/loader/tests/index.js index b85fafe1..917668ef 100644 --- a/lib/loader/tests/index.js +++ b/lib/loader/tests/index.js @@ -59,3 +59,6 @@ assert.strictEqual(fn(2), 4); // should be able to create a new function and call it from WASM ptr = module.newFunction(module.varadd); assert.strictEqual(module.calladd(ptr, 2, 3), 5); + +// should be able to use trace +module.dotrace(42);