From d64ba9b67d1489f0ac780559c308434cab015a80 Mon Sep 17 00:00:00 2001 From: Wink Saville Date: Fri, 31 Mar 2017 23:32:37 -0700 Subject: [PATCH] This now compiles and runs if node v8.0.0 is used. Node v8.0.0 is not yet released and must be downloaded or compiled from source. My testing was with node tip of tree master at --- .gitignore | 3 + README.md | 11 ++++ package.json | 9 ++- test/addTwo.tbs | 3 + test/addTwo.wasm | Bin 0 -> 924 bytes test/wasm.js | 153 ++++++++++++++++++++++++++++++++++----------- test/wasm.ts | 157 +++++++++++++++++++++++++++++++++++------------ yarn.lock | 15 +++++ 8 files changed, 274 insertions(+), 77 deletions(-) create mode 100644 .gitignore create mode 100755 test/addTwo.tbs create mode 100644 test/addTwo.wasm create mode 100644 yarn.lock diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..5cbb9a79 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +node_modules/ +*.swp +*.log diff --git a/README.md b/README.md index ee3b7afe..02cc0ea6 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,13 @@ # WebAssembly Types Typescript declaration for WebAssembly JS API + +NOTE: Node.js v8.0.0 is the first version that will +support WebAssembly MVP. Since it's not yet released +we assume its been downloaded or compiled locally +and the executable is ../node/node. According to +[this](https://github.com/nodejs/node/issues/12090#issuecomment-289755110) +v8.0.0 should be released by end of April 2017. + +I tested by compiling [node](https://github.com/nodejs/node) +from sources on master branch at sha1 +[c68da89694b1ff4682131ed6b825e596188cc4ed](https://github.com/nodejs/node/commit/c68da89694b1ff4682131ed6b825e596188cc4ed) diff --git a/package.json b/package.json index 0057103e..7cf46620 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,13 @@ { "scripts": { "pretest": "tsc -p test/tsconfig.json", - "test": "node --expose-wasm test/wasm.js" + "test": "../node/node --expose_wasm test/wasm.js" + }, + "devDependencies": { + "@types/node": "^7.0.12", + "typescript": "^2.2.2" + }, + "dependencies": { + "node": "^0.0.0" } } diff --git a/test/addTwo.tbs b/test/addTwo.tbs new file mode 100755 index 00000000..4d571586 --- /dev/null +++ b/test/addTwo.tbs @@ -0,0 +1,3 @@ +export function addTwo1(a:int32, b:int32): int32 { + return a + b; +} diff --git a/test/addTwo.wasm b/test/addTwo.wasm new file mode 100644 index 0000000000000000000000000000000000000000..ce8d8ffd0f460519c97d36c4c51f943f50e8a445 GIT binary patch literal 924 zcmZ`%!EVz)5S^Lz+96IFtI8orIm`+P<;o@JtPrIjAvhq;jcBOqB!r}uD3|&R_>A8A zM_l+6-mGgO5F}df?Cg6pZ=Oxdt1S}|KlW$baDxY(5q4=1;K7X>9T6ZRLe4Q$<{c9k zABudt+U^eDg!1ijv)O$l%03-dE8_me>iTrG{POPlK-mz76QtiHF!^Jg-ySY6Eq*Z8v+{RO;Z7%<7P94q{Jp9IAdgJc^_q$GKF%pfngEmxWv4+Mm7{GSD;^ zN~Dkvs4O)bmET!RX{5kdqEw~+(?};K2vtFvwxY(S7l;9b<3i>##u(58>P)nop*^8h z${L?akJ*s7ums0~wlr7*P@+H`FRUPFX3JmqR&ZmVBgdChEA#>+A6sC@p1X~vxfPG+O; zOEcT}$*t5VQI%&xfz5fV(Mvt6E*N*gzyd`{V2%-_Fcy2|gW30_YYh+ZHq)$ literal 0 HcmV?d00001 diff --git a/test/wasm.js b/test/wasm.js index e205405b..1de64425 100644 --- a/test/wasm.js +++ b/test/wasm.js @@ -2,57 +2,138 @@ * Created by Nidin Vinayakan on 31/03/17. */ /// -let source = new Uint8Array(1); -//Table +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const fs = require("fs"); +function displayModExports(prompt, mod) { + let exports = WebAssembly.Module.exports(mod); + console.log(`${prompt} length=${exports.length}`); + for (let i in exports) { + let v = exports[i]; + console.log(`${prompt}[${i}] name=${v.name} kind=${v.kind}`); + } +} +function displayModImports(prompt, mod) { + let imports = WebAssembly.Module.imports(mod); + console.log(`${prompt} length=${imports.length}`); + for (let i in imports) { + let v = imports[i]; + console.log(`${prompt}[${i}] name=${v.name} kind=${v.kind}`); + } +} +function readFileAsync(filePath) { + return new Promise((resolve, reject) => { + fs.readFile(filePath, (err, data) => { + if (err) { + return reject(err); + } + else { + return resolve(new Uint8Array(data)); + } + }); + }); +} +// Table let table = new WebAssembly.Table({ element: "anyfunc", initial: 1, maximum: 10 }); console.log(`table.length=${table.length}`); console.log(`table.get(0)=${table.get(0)}`); -table.set(0, function () { -}); +//table.set(0, function () { +//}); table.grow(1); -//Memory -let memory = new WebAssembly.Memory({ initial: 2, maximum: 4 }); -console.log(`memory.grow(8)=${memory.grow(8)}`); +// Memory +let memory = new WebAssembly.Memory({ initial: 2, maximum: 8 }); +console.log(`memory.grow(6)=${memory.grow(6)}`); let u8 = new Uint8Array(memory.buffer); u8[0] = 1; u8[1] = 2; console.log(`u8[0]=${u8[0]}`); console.log(`u8[1]=${u8[1]}`); -//Module -let wasmModule = new WebAssembly.Module(source); -//customSections +let data = fs.readFileSync('./test/addTwo.wasm'); +let wasmDataU8 = new Uint8Array(data); +console.log(`data.buffer.byteLength=${data.buffer.byteLength}`); +console.log(`wasmDataU8.length=${wasmDataU8.length}`); +console.log(`wasmDataU8[0]=${wasmDataU8[0].toString(16)}`); +console.log(`wasmDataU8[1]=${wasmDataU8[1].toString(16)}`); +console.log(`wasmDataU8[2]=${wasmDataU8[2].toString(16)}`); +console.log(`wasmDataU8[3]=${wasmDataU8[3].toString(16)}`); +console.log(`wasmDataU8[4]=${wasmDataU8[4].toString(16)}`); +console.log(`wasmDataU8[5]=${wasmDataU8[5].toString(16)}`); +console.log(`wasmDataU8[6]=${wasmDataU8[6].toString(16)}`); +console.log(`wasmDataU8[7]=${wasmDataU8[7].toString(16)}`); +// Validate +let valid = WebAssembly.validate(wasmDataU8); +console.log("wasmDataU8 is " + (valid ? "" : "not ") + "a valid wasm wasmModule"); +// Module +let wasmModule = new WebAssembly.Module(wasmDataU8); +console.log(`wasmModule=${wasmModule}`); +// CustomSections let nameSections = WebAssembly.Module.customSections(wasmModule, "name"); +console.log(`Module contains ${nameSections.length} name sections`); if (nameSections.length != 0) { console.log("Module contains a name section"); console.log(nameSections[0]); } -//exports -console.log(WebAssembly.Module.exports(wasmModule).length); -console.log(WebAssembly.Module.exports(wasmModule)[0].name); -console.log(WebAssembly.Module.exports(wasmModule)[0].kind); -//imports -console.log(WebAssembly.Module.imports(wasmModule).length); -console.log(WebAssembly.Module.imports(wasmModule)[0].module); -console.log(WebAssembly.Module.imports(wasmModule)[0].name); -console.log(WebAssembly.Module.imports(wasmModule)[0].kind); -//Instance +// Display Exports +displayModExports('wasmModule.exports', wasmModule); +// Display Imports +displayModImports('wasmModule.imports', wasmModule); +// Instance let instance = new WebAssembly.Instance(wasmModule); -console.log(instance.exports.exported_func()); -let bytes = new ArrayBuffer(1); //dummy bytes -//validate -let valid = WebAssembly.validate(bytes); -console.log("The given bytes are " + (valid ? "" : "not ") + "a valid wasm wasmModule"); -//compile -WebAssembly.compile(bytes).then((module) => { - console.log(wasmModule); +console.log(`instance=${instance}`); +console.log(`instance.exports=${instance.exports}`); +//displayExports('instance.exports', instance.exports); +console.log(`addTwo1(1,2)=${instance.exports.addTwo1(1, 2)}`); +// Instantiate +// Primary overload — taking wasm binary code +WebAssembly.instantiate(wasmDataU8).then((result) => { + console.log(`Primary overload mod=${result.module}`); + console.log(`Primary overload inst=${result.instance}`); + console.log(`Primary exec instance.exports..addTwo1(-1,1)=${result.instance.exports.addTwo1(-1, 1)}`); }); -//instantiate -//Primary overload — taking wasm binary code -WebAssembly.instantiate(bytes).then((result) => { - console.log(result.module); - console.log(result.instance); -}); -//Secondary overload — taking a wasmModule object instance +// Instantiate +// Secondary overload — taking a Module object WebAssembly.instantiate(wasmModule).then((instance) => { - console.log(instance); + console.log(`Secondary overload instance=${instance}`); + console.log(`Secondary exec instance.exports..addTwo1(0,-1)=${instance.exports.addTwo1(0, -1)}`); +}); +function instantiateFile(filePath) { + return __awaiter(this, void 0, void 0, function* () { + console.log("instantiateFile:+ readFile"); + let instance = yield readFileAsync("./test/addTwo.wasm") + .then(data => { + console.log("instantiateFile fileRead:"); + console.log(`data.length=${data.length}`); + console.log(`data[0]=${data[0].toString(16)}`); + console.log(`data[1]=${data[1].toString(16)}`); + console.log(`data[2]=${data[2].toString(16)}`); + console.log(`data[3]=${data[3].toString(16)}`); + console.log(`data[4]=${data[4].toString(16)}`); + console.log(`data[5]=${data[5].toString(16)}`); + console.log(`data[6]=${data[6].toString(16)}`); + console.log(`data[7]=${data[7].toString(16)}`); + // Compile + console.log("instantiateFile compile:"); + return Promise.resolve(WebAssembly.compile(data)); + }) + .then(mod => { + console.log("instantiateFile compiled return Module:"); + return Promise.resolve(WebAssembly.instantiate(mod)); + }); + console.log("instantiateFile:-"); + return instance; + }); +} +// Use instantiateFile +console.log("call instantiateFile"); +instantiateFile("./test/addTwo.wasm").then(inst => { + console.log(`done instantiateFile inst=${inst}`); + console.log(`exec inst.exports..addTwo1(0,0)=${inst.exports.addTwo1(0, 0)}`); }); diff --git a/test/wasm.ts b/test/wasm.ts index 4ae6e94b..194e3a8b 100644 --- a/test/wasm.ts +++ b/test/wasm.ts @@ -3,65 +3,142 @@ */ /// -let source: Uint8Array = new Uint8Array(1); +import * as fs from "fs"; -//Table +function displayModExports(prompt: string, mod: WebAssembly.Module) { + let exports = WebAssembly.Module.exports(mod); + console.log(`${prompt} length=${exports.length}`); + for (let i in exports) { + let v = exports[i]; + console.log(`${prompt}[${i}] name=${v.name} kind=${v.kind}`); + } +} + +function displayModImports(prompt: string, mod: WebAssembly.Module) { + let imports = WebAssembly.Module.imports(mod); + console.log(`${prompt} length=${imports.length}`); + for (let i in imports) { + let v = imports[i]; + console.log(`${prompt}[${i}] name=${v.name} kind=${v.kind}`); + } +} + +function readFileAsync(filePath: string): Promise { + return new Promise((resolve, reject) => { + fs.readFile(filePath, (err, data) => { + if (err) { + return reject(err); + } else { + return resolve(new Uint8Array(data)); + } + }); + }); +} + +// Table let table = new WebAssembly.Table({element: "anyfunc", initial: 1, maximum: 10}); console.log(`table.length=${table.length}`); console.log(`table.get(0)=${table.get(0)}`); -table.set(0, function () { -}); +//table.set(0, function () { +//}); table.grow(1); -//Memory -let memory = new WebAssembly.Memory({initial: 2, maximum: 4}); -console.log(`memory.grow(8)=${memory.grow(8)}`); +// Memory +let memory = new WebAssembly.Memory({initial: 2, maximum: 8}); +console.log(`memory.grow(6)=${memory.grow(6)}`); let u8 = new Uint8Array(memory.buffer); u8[0] = 1; u8[1] = 2; console.log(`u8[0]=${u8[0]}`); console.log(`u8[1]=${u8[1]}`); -//Module -let wasmModule = new WebAssembly.Module(source); -//customSections +let data = fs.readFileSync('./test/addTwo.wasm'); +let wasmDataU8 = new Uint8Array(data); +console.log(`data.buffer.byteLength=${data.buffer.byteLength}`); +console.log(`wasmDataU8.length=${wasmDataU8.length}`); +console.log(`wasmDataU8[0]=${wasmDataU8[0].toString(16)}`); +console.log(`wasmDataU8[1]=${wasmDataU8[1].toString(16)}`); +console.log(`wasmDataU8[2]=${wasmDataU8[2].toString(16)}`); +console.log(`wasmDataU8[3]=${wasmDataU8[3].toString(16)}`); +console.log(`wasmDataU8[4]=${wasmDataU8[4].toString(16)}`); +console.log(`wasmDataU8[5]=${wasmDataU8[5].toString(16)}`); +console.log(`wasmDataU8[6]=${wasmDataU8[6].toString(16)}`); +console.log(`wasmDataU8[7]=${wasmDataU8[7].toString(16)}`); + +// Validate +let valid = WebAssembly.validate(wasmDataU8); +console.log("wasmDataU8 is " + (valid ? "" : "not ") + "a valid wasm wasmModule"); + +// Module +let wasmModule = new WebAssembly.Module(wasmDataU8); +console.log(`wasmModule=${wasmModule}`); + +// CustomSections let nameSections = WebAssembly.Module.customSections(wasmModule, "name"); +console.log(`Module contains ${nameSections.length} name sections`); if (nameSections.length != 0) { - console.log("Module contains a name section"); - console.log(nameSections[0]); + console.log("Module contains a name section"); + console.log(nameSections[0]); } -//exports -console.log(WebAssembly.Module.exports(wasmModule).length); -console.log(WebAssembly.Module.exports(wasmModule)[0].name); -console.log(WebAssembly.Module.exports(wasmModule)[0].kind); -//imports -console.log(WebAssembly.Module.imports(wasmModule).length); -console.log(WebAssembly.Module.imports(wasmModule)[0].module); -console.log(WebAssembly.Module.imports(wasmModule)[0].name); -console.log(WebAssembly.Module.imports(wasmModule)[0].kind); - -//Instance -let instance = new WebAssembly.Instance(wasmModule); -console.log(instance.exports.exported_func()); +// Display Exports +displayModExports('wasmModule.exports', wasmModule); -let bytes = new ArrayBuffer(1);//dummy bytes -//validate -let valid = WebAssembly.validate(bytes); -console.log("The given bytes are " + (valid ? "" : "not ") + "a valid wasm wasmModule"); +// Display Imports +displayModImports('wasmModule.imports', wasmModule); -//compile -WebAssembly.compile(bytes).then((module: WebAssembly.Module) => { - console.log(wasmModule); -}); +// Instance +let instance = new WebAssembly.Instance(wasmModule); +console.log(`instance=${instance}`); +console.log(`instance.exports=${instance.exports}`); +//displayExports('instance.exports', instance.exports); +console.log(`addTwo1(1,2)=${instance.exports.addTwo1(1,2)}`); -//instantiate -//Primary overload — taking wasm binary code -WebAssembly.instantiate(bytes).then((result: WebAssembly.ResultObject) => { - console.log(result.module); - console.log(result.instance); +// Instantiate +// Primary overload — taking wasm binary code +WebAssembly.instantiate(wasmDataU8).then((result: WebAssembly.ResultObject) => { + console.log(`Primary overload mod=${result.module}`); + console.log(`Primary overload inst=${result.instance}`); + console.log(`Primary exec instance.exports..addTwo1(-1,1)=${result.instance.exports.addTwo1(-1,1)}`); }); -//Secondary overload — taking a wasmModule object instance + +// Instantiate +// Secondary overload — taking a Module object WebAssembly.instantiate(wasmModule).then((instance: WebAssembly.Instance) => { - console.log(instance); + console.log(`Secondary overload instance=${instance}`); + console.log(`Secondary exec instance.exports..addTwo1(0,-1)=${instance.exports.addTwo1(0,-1)}`); +}); + +async function instantiateFile(filePath: string): Promise { + console.log("instantiateFile:+ readFile"); + let instance = await readFileAsync("./test/addTwo.wasm") + .then(data => { + console.log("instantiateFile fileRead:"); + console.log(`data.length=${data.length}`); + console.log(`data[0]=${data[0].toString(16)}`); + console.log(`data[1]=${data[1].toString(16)}`); + console.log(`data[2]=${data[2].toString(16)}`); + console.log(`data[3]=${data[3].toString(16)}`); + console.log(`data[4]=${data[4].toString(16)}`); + console.log(`data[5]=${data[5].toString(16)}`); + console.log(`data[6]=${data[6].toString(16)}`); + console.log(`data[7]=${data[7].toString(16)}`); + + // Compile + console.log("instantiateFile compile:"); + return Promise.resolve(WebAssembly.compile(data)); + }) + .then(mod => { + console.log("instantiateFile compiled return Module:"); + return Promise.resolve(WebAssembly.instantiate(mod)); + }); + console.log("instantiateFile:-"); + return instance; +} + +// Use instantiateFile +console.log("call instantiateFile"); +instantiateFile("./test/addTwo.wasm").then(inst => { + console.log(`done instantiateFile inst=${inst}`) + console.log(`exec inst.exports..addTwo1(0,0)=${inst.exports.addTwo1(0,0)}`); }); diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 00000000..747c0607 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,15 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@types/node@^7.0.12": + version "7.0.12" + resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.12.tgz#ae5f67a19c15f752148004db07cbbb372e69efc9" + +node@^0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/node/-/node-0.0.0.tgz#288d62f90530c763eff8d4831ee7343ab3d60793" + +typescript@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.2.2.tgz#606022508479b55ffa368b58fee963a03dfd7b0c" -- 2.30.2