mirror of
https://github.com/servo/servo.git
synced 2025-08-11 16:35:33 +01:00
Update web-platform-tests to revision d8b8e0b8efe993a37404d6c6fc75e16fdc16b7d8
This commit is contained in:
parent
abc0f50d20
commit
e07315e6af
221 changed files with 7334 additions and 774 deletions
|
@ -71,3 +71,24 @@ function assert_Instance(instance, expected_exports) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
function assert_WebAssemblyInstantiatedSource(actual, expected_exports={}) {
|
||||
assert_equals(Object.getPrototypeOf(actual), Object.prototype,
|
||||
"Prototype");
|
||||
assert_true(Object.isExtensible(actual), "Extensibility");
|
||||
|
||||
const module = Object.getOwnPropertyDescriptor(actual, "module");
|
||||
assert_equals(typeof module, "object", "module: type of descriptor");
|
||||
assert_true(module.writable, "module: writable");
|
||||
assert_true(module.enumerable, "module: enumerable");
|
||||
assert_true(module.configurable, "module: configurable");
|
||||
assert_equals(Object.getPrototypeOf(module.value), WebAssembly.Module.prototype,
|
||||
"module: prototype");
|
||||
|
||||
const instance = Object.getOwnPropertyDescriptor(actual, "instance");
|
||||
assert_equals(typeof instance, "object", "instance: type of descriptor");
|
||||
assert_true(instance.writable, "instance: writable");
|
||||
assert_true(instance.enumerable, "instance: enumerable");
|
||||
assert_true(instance.configurable, "instance: configurable");
|
||||
assert_Instance(instance.value, expected_exports);
|
||||
}
|
||||
|
|
|
@ -62,6 +62,11 @@ test(() => {
|
|||
promise_test(t => {
|
||||
const buffer = new Uint8Array();
|
||||
return promise_rejects(t, new WebAssembly.CompileError(), WebAssembly.compile(buffer));
|
||||
}, "Empty buffer");
|
||||
|
||||
test(() => {
|
||||
const buffer = new Uint8Array(Array.from(emptyModuleBinary).concat([0, 0]));
|
||||
assert_throws(new WebAssembly.CompileError(), () => WebAssembly.compile(buffer));
|
||||
}, "Invalid code");
|
||||
|
||||
promise_test(() => {
|
||||
|
@ -73,7 +78,7 @@ promise_test(() => {
|
|||
}, "Stray argument");
|
||||
|
||||
promise_test(() => {
|
||||
const buffer = new WasmModuleBuilder().toBuffer();
|
||||
const buffer = new Uint8Array(new WasmModuleBuilder().toBuffer());
|
||||
assert_equals(buffer[0], 0);
|
||||
const promise = WebAssembly.compile(buffer);
|
||||
buffer[0] = 1;
|
||||
|
|
|
@ -4,27 +4,6 @@
|
|||
// META: script=/wasm/jsapi/assertions.js
|
||||
// META: script=/wasm/jsapi/instanceTestFactory.js
|
||||
|
||||
function assert_WebAssemblyInstantiatedSource(actual, expected_exports={}) {
|
||||
assert_equals(Object.getPrototypeOf(actual), Object.prototype,
|
||||
"Prototype");
|
||||
assert_true(Object.isExtensible(actual), "Extensibility");
|
||||
|
||||
const module = Object.getOwnPropertyDescriptor(actual, "module");
|
||||
assert_equals(typeof module, "object", "module: type of descriptor");
|
||||
assert_true(module.writable, "module: writable");
|
||||
assert_true(module.enumerable, "module: enumerable");
|
||||
assert_true(module.configurable, "module: configurable");
|
||||
assert_equals(Object.getPrototypeOf(module.value), WebAssembly.Module.prototype,
|
||||
"module: prototype");
|
||||
|
||||
const instance = Object.getOwnPropertyDescriptor(actual, "instance");
|
||||
assert_equals(typeof instance, "object", "instance: type of descriptor");
|
||||
assert_true(instance.writable, "instance: writable");
|
||||
assert_true(instance.enumerable, "instance: enumerable");
|
||||
assert_true(instance.configurable, "instance: configurable");
|
||||
assert_Instance(instance.value, expected_exports);
|
||||
}
|
||||
|
||||
let emptyModuleBinary;
|
||||
setup(() => {
|
||||
emptyModuleBinary = new WasmModuleBuilder().toBuffer();
|
||||
|
@ -100,10 +79,15 @@ for (const [name, fn] of instanceTestFactory) {
|
|||
promise_test(t => {
|
||||
const buffer = new Uint8Array();
|
||||
return promise_rejects(t, new WebAssembly.CompileError(), WebAssembly.instantiate(buffer));
|
||||
}, "Empty buffer");
|
||||
|
||||
promise_test(t => {
|
||||
const buffer = new Uint8Array(Array.from(emptyModuleBinary).concat([0, 0]));
|
||||
return promise_rejects(t, new WebAssembly.CompileError(), WebAssembly.instantiate(buffer));
|
||||
}, "Invalid code");
|
||||
|
||||
promise_test(() => {
|
||||
const buffer = new WasmModuleBuilder().toBuffer();
|
||||
const buffer = new Uint8Array(new WasmModuleBuilder().toBuffer());
|
||||
assert_equals(buffer[0], 0);
|
||||
const promise = WebAssembly.instantiate(buffer);
|
||||
buffer[0] = 1;
|
||||
|
|
|
@ -133,18 +133,14 @@ const instanceTestFactory = [
|
|||
|
||||
builder
|
||||
.addFunction("fn", kSig_v_d)
|
||||
.addBody([
|
||||
kExprEnd
|
||||
])
|
||||
.addBody([])
|
||||
.exportFunc();
|
||||
builder
|
||||
.addFunction("fn2", kSig_v_v)
|
||||
.addBody([
|
||||
kExprEnd
|
||||
])
|
||||
.addBody([])
|
||||
.exportFunc();
|
||||
|
||||
builder.setFunctionTableLength(1);
|
||||
builder.setTableLength(1);
|
||||
builder.addExportOfKind("table", kExternalTable, 0);
|
||||
|
||||
builder.addGlobal(kWasmI32, true)
|
||||
|
@ -190,7 +186,6 @@ const instanceTestFactory = [
|
|||
kExprGetGlobal,
|
||||
index,
|
||||
kExprReturn,
|
||||
kExprEnd,
|
||||
])
|
||||
.exportFunc();
|
||||
|
||||
|
|
|
@ -49,6 +49,11 @@ test(() => {
|
|||
assert_throws(new WebAssembly.CompileError(), () => new WebAssembly.Module(buffer));
|
||||
}, "Empty buffer");
|
||||
|
||||
test(() => {
|
||||
const buffer = new Uint8Array(Array.from(emptyModuleBinary).concat([0, 0]));
|
||||
assert_throws(new WebAssembly.CompileError(), () => new WebAssembly.Module(buffer));
|
||||
}, "Invalid code");
|
||||
|
||||
test(() => {
|
||||
const module = new WebAssembly.Module(emptyModuleBinary);
|
||||
assert_equals(Object.getPrototypeOf(module), WebAssembly.Module.prototype);
|
||||
|
|
|
@ -92,18 +92,14 @@ test(() => {
|
|||
|
||||
builder
|
||||
.addFunction("fn", kSig_v_v)
|
||||
.addBody([
|
||||
kExprEnd
|
||||
])
|
||||
.addBody([])
|
||||
.exportFunc();
|
||||
builder
|
||||
.addFunction("fn2", kSig_v_v)
|
||||
.addBody([
|
||||
kExprEnd
|
||||
])
|
||||
.addBody([])
|
||||
.exportFunc();
|
||||
|
||||
builder.setFunctionTableLength(1);
|
||||
builder.setTableLength(1);
|
||||
builder.addExportOfKind("table", kExternalTable, 0);
|
||||
|
||||
builder.addGlobal(kWasmI32, true)
|
||||
|
|
|
@ -9,15 +9,11 @@ setup(() => {
|
|||
|
||||
builder
|
||||
.addFunction("fn", kSig_v_d)
|
||||
.addBody([
|
||||
kExprEnd
|
||||
])
|
||||
.addBody([])
|
||||
.exportFunc();
|
||||
builder
|
||||
.addFunction("fn2", kSig_v_v)
|
||||
.addBody([
|
||||
kExprEnd
|
||||
])
|
||||
.addBody([])
|
||||
.exportFunc();
|
||||
|
||||
const buffer = builder.toBuffer()
|
||||
|
|
|
@ -21,7 +21,7 @@ var kWasmH1 = 0x61;
|
|||
var kWasmH2 = 0x73;
|
||||
var kWasmH3 = 0x6d;
|
||||
|
||||
var kWasmV0 = 1;
|
||||
var kWasmV0 = 0x1;
|
||||
var kWasmV1 = 0;
|
||||
var kWasmV2 = 0;
|
||||
var kWasmV3 = 0;
|
||||
|
@ -65,10 +65,15 @@ let kCodeSectionCode = 10; // Function code
|
|||
let kDataSectionCode = 11; // Data segments
|
||||
let kNameSectionCode = 12; // Name section (encoded as string)
|
||||
|
||||
// Name section types
|
||||
let kModuleNameCode = 0;
|
||||
let kFunctionNamesCode = 1;
|
||||
let kLocalNamesCode = 2;
|
||||
|
||||
let kWasmFunctionTypeForm = 0x60;
|
||||
let kWasmAnyFunctionTypeForm = 0x70;
|
||||
|
||||
let kResizableMaximumFlag = 1;
|
||||
let kHasMaximumFlag = 1;
|
||||
|
||||
// Function declaration flags
|
||||
let kDeclFunctionName = 0x01;
|
||||
|
@ -82,7 +87,6 @@ let kWasmI32 = 0x7f;
|
|||
let kWasmI64 = 0x7e;
|
||||
let kWasmF32 = 0x7d;
|
||||
let kWasmF64 = 0x7c;
|
||||
let kWasmS128 = 0x7b;
|
||||
|
||||
let kExternalFunction = 0;
|
||||
let kExternalTable = 1;
|
||||
|
@ -104,7 +108,7 @@ let kSig_i_dd = makeSig([kWasmF64, kWasmF64], [kWasmI32]);
|
|||
let kSig_v_v = makeSig([], []);
|
||||
let kSig_i_v = makeSig([], [kWasmI32]);
|
||||
let kSig_l_v = makeSig([], [kWasmI64]);
|
||||
let kSig_f_v = makeSig([], [kWasmF64]);
|
||||
let kSig_f_v = makeSig([], [kWasmF32]);
|
||||
let kSig_d_v = makeSig([], [kWasmF64]);
|
||||
let kSig_v_i = makeSig([kWasmI32], []);
|
||||
let kSig_v_ii = makeSig([kWasmI32, kWasmI32], []);
|
||||
|
@ -113,7 +117,6 @@ let kSig_v_l = makeSig([kWasmI64], []);
|
|||
let kSig_v_d = makeSig([kWasmF64], []);
|
||||
let kSig_v_dd = makeSig([kWasmF64, kWasmF64], []);
|
||||
let kSig_v_ddi = makeSig([kWasmF64, kWasmF64, kWasmI32], []);
|
||||
let kSig_s_v = makeSig([], [kWasmS128]);
|
||||
|
||||
function makeSig(params, results) {
|
||||
return {params: params, results: results};
|
||||
|
@ -191,7 +194,7 @@ let kExprI64StoreMem8 = 0x3c;
|
|||
let kExprI64StoreMem16 = 0x3d;
|
||||
let kExprI64StoreMem32 = 0x3e;
|
||||
let kExprMemorySize = 0x3f;
|
||||
let kExprGrowMemory = 0x40;
|
||||
let kExprMemoryGrow = 0x40;
|
||||
let kExprI32Eqz = 0x45;
|
||||
let kExprI32Eq = 0x46;
|
||||
let kExprI32Ne = 0x47;
|
||||
|
@ -339,36 +342,34 @@ let kTrapMsgs = [
|
|||
];
|
||||
|
||||
function assertTraps(trap, code) {
|
||||
var threwException = true;
|
||||
try {
|
||||
if (typeof code === 'function') {
|
||||
code();
|
||||
} else {
|
||||
eval(code);
|
||||
}
|
||||
threwException = false;
|
||||
} catch (e) {
|
||||
assertEquals("object", typeof e);
|
||||
assertEquals(kTrapMsgs[trap], e.message);
|
||||
// Success.
|
||||
return;
|
||||
try {
|
||||
if (typeof code === 'function') {
|
||||
code();
|
||||
} else {
|
||||
eval(code);
|
||||
}
|
||||
throw new MjsUnitAssertionError("Did not trap, expected: " + kTrapMsgs[trap]);
|
||||
} catch (e) {
|
||||
assertEquals('object', typeof e);
|
||||
assertEquals(kTrapMsgs[trap], e.message);
|
||||
// Success.
|
||||
return;
|
||||
}
|
||||
throw new MjsUnitAssertionError('Did not trap, expected: ' + kTrapMsgs[trap]);
|
||||
}
|
||||
|
||||
function assertWasmThrows(value, code) {
|
||||
assertEquals("number", typeof(value));
|
||||
try {
|
||||
if (typeof code === 'function') {
|
||||
code();
|
||||
} else {
|
||||
eval(code);
|
||||
}
|
||||
} catch (e) {
|
||||
assertEquals("number", typeof e);
|
||||
assertEquals(value, e);
|
||||
// Success.
|
||||
return;
|
||||
assertEquals('number', typeof value);
|
||||
try {
|
||||
if (typeof code === 'function') {
|
||||
code();
|
||||
} else {
|
||||
eval(code);
|
||||
}
|
||||
throw new MjsUnitAssertionError("Did not throw at all, expected: " + value);
|
||||
} catch (e) {
|
||||
assertEquals('number', typeof e);
|
||||
assertEquals(value, e);
|
||||
// Success.
|
||||
return;
|
||||
}
|
||||
throw new MjsUnitAssertionError('Did not throw, expected: ' + value);
|
||||
}
|
||||
|
|
|
@ -69,12 +69,14 @@ class Binary extends Array {
|
|||
// Emit section name.
|
||||
this.emit_u8(section_code);
|
||||
// Emit the section to a temporary buffer: its full length isn't know yet.
|
||||
let section = new Binary;
|
||||
const section = new Binary;
|
||||
content_generator(section);
|
||||
// Emit section length.
|
||||
this.emit_u32v(section.length);
|
||||
// Copy the temporary buffer.
|
||||
this.push(...section);
|
||||
for (const b of section) {
|
||||
this.push(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,6 +88,15 @@ class WasmFunctionBuilder {
|
|||
this.body = [];
|
||||
}
|
||||
|
||||
numLocalNames() {
|
||||
if (this.local_names === undefined) return 0;
|
||||
let num_local_names = 0;
|
||||
for (let loc_name of this.local_names) {
|
||||
if (loc_name !== undefined) ++num_local_names;
|
||||
}
|
||||
return num_local_names;
|
||||
}
|
||||
|
||||
exportAs(name) {
|
||||
this.module.addExport(name, this.index);
|
||||
return this;
|
||||
|
@ -97,12 +108,40 @@ class WasmFunctionBuilder {
|
|||
}
|
||||
|
||||
addBody(body) {
|
||||
for (let b of body) {
|
||||
if (typeof b !== 'number' || (b & (~0xFF)) !== 0 )
|
||||
throw new Error('invalid body (entries must be 8 bit numbers): ' + body);
|
||||
}
|
||||
this.body = body.slice();
|
||||
// Automatically add the end for the function block to the body.
|
||||
this.body.push(kExprEnd);
|
||||
return this;
|
||||
}
|
||||
|
||||
addBodyWithEnd(body) {
|
||||
this.body = body;
|
||||
return this;
|
||||
}
|
||||
|
||||
addLocals(locals) {
|
||||
this.locals = locals;
|
||||
getNumLocals() {
|
||||
let total_locals = 0;
|
||||
for (let l of this.locals || []) {
|
||||
for (let type of ["i32", "i64", "f32", "f64"]) {
|
||||
total_locals += l[type + "_count"] || 0;
|
||||
}
|
||||
}
|
||||
return total_locals;
|
||||
}
|
||||
|
||||
addLocals(locals, names) {
|
||||
const old_num_locals = this.getNumLocals();
|
||||
if (!this.locals) this.locals = []
|
||||
this.locals.push(locals);
|
||||
if (names) {
|
||||
if (!this.local_names) this.local_names = [];
|
||||
const missing_names = old_num_locals - this.local_names.length;
|
||||
this.local_names.push(...new Array(missing_names), ...names);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -133,10 +172,10 @@ class WasmModuleBuilder {
|
|||
this.exports = [];
|
||||
this.globals = [];
|
||||
this.functions = [];
|
||||
this.function_table = [];
|
||||
this.function_table_length = 0;
|
||||
this.function_table_inits = [];
|
||||
this.segments = [];
|
||||
this.table_length_min = 0;
|
||||
this.table_length_max = undefined;
|
||||
this.element_segments = [];
|
||||
this.data_segments = [];
|
||||
this.explicit = [];
|
||||
this.num_imported_funcs = 0;
|
||||
this.num_imported_globals = 0;
|
||||
|
@ -158,6 +197,22 @@ class WasmModuleBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
stringToBytes(name) {
|
||||
var result = new Binary();
|
||||
result.emit_u32v(name.length);
|
||||
for (var i = 0; i < name.length; i++) {
|
||||
result.emit_u8(name.charCodeAt(i));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
addCustomSection(name, bytes) {
|
||||
name = this.stringToBytes(name);
|
||||
var length = new Binary();
|
||||
length.emit_u32v(name.length + bytes.length);
|
||||
this.explicit.push([0, ...length, ...name, ...bytes]);
|
||||
}
|
||||
|
||||
addType(type) {
|
||||
// TODO: canonicalize types?
|
||||
this.types.push(type);
|
||||
|
@ -180,15 +235,21 @@ class WasmModuleBuilder {
|
|||
}
|
||||
|
||||
addImport(module = "", name, type) {
|
||||
if (this.functions.length != 0) {
|
||||
throw new Error('Imported functions must be declared before local ones');
|
||||
}
|
||||
let type_index = (typeof type) == "number" ? type : this.addType(type);
|
||||
this.imports.push({module: module, name: name, kind: kExternalFunction,
|
||||
type: type_index});
|
||||
return this.num_imported_funcs++;
|
||||
}
|
||||
|
||||
addImportedGlobal(module = "", name, type) {
|
||||
addImportedGlobal(module = "", name, type, mutable = false) {
|
||||
if (this.globals.length != 0) {
|
||||
throw new Error('Imported globals must be declared before local ones');
|
||||
}
|
||||
let o = {module: module, name: name, kind: kExternalGlobal, type: type,
|
||||
mutable: false}
|
||||
mutable: mutable};
|
||||
this.imports.push(o);
|
||||
return this.num_imported_globals++;
|
||||
}
|
||||
|
@ -217,32 +278,51 @@ class WasmModuleBuilder {
|
|||
}
|
||||
|
||||
addDataSegment(addr, data, is_global = false) {
|
||||
this.segments.push({addr: addr, data: data, is_global: is_global});
|
||||
return this.segments.length - 1;
|
||||
this.data_segments.push({addr: addr, data: data, is_global: is_global});
|
||||
return this.data_segments.length - 1;
|
||||
}
|
||||
|
||||
exportMemoryAs(name) {
|
||||
this.exports.push({name: name, kind: kExternalMemory, index: 0});
|
||||
}
|
||||
|
||||
addFunctionTableInit(base, is_global, array) {
|
||||
this.function_table_inits.push({base: base, is_global: is_global,
|
||||
addElementSegment(base, is_global, array, is_import = false) {
|
||||
this.element_segments.push({base: base, is_global: is_global,
|
||||
array: array});
|
||||
if (!is_global) {
|
||||
var length = base + array.length;
|
||||
if (length > this.function_table_length) {
|
||||
this.function_table_length = length;
|
||||
if (length > this.table_length_min && !is_import) {
|
||||
this.table_length_min = length;
|
||||
}
|
||||
if (length > this.table_length_max && !is_import) {
|
||||
this.table_length_max = length;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
appendToTable(array) {
|
||||
return this.addFunctionTableInit(this.function_table.length, false, array);
|
||||
for (let n of array) {
|
||||
if (typeof n != 'number')
|
||||
throw new Error('invalid table (entries have to be numbers): ' + array);
|
||||
}
|
||||
return this.addElementSegment(this.table_length_min, false, array);
|
||||
}
|
||||
|
||||
setFunctionTableLength(length) {
|
||||
this.function_table_length = length;
|
||||
setTableBounds(min, max) {
|
||||
this.table_length_min = min;
|
||||
this.table_length_max = max;
|
||||
return this;
|
||||
}
|
||||
|
||||
setTableLength(length) {
|
||||
this.table_length_min = length;
|
||||
this.table_length_max = length;
|
||||
return this;
|
||||
}
|
||||
|
||||
setName(name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -305,40 +385,39 @@ class WasmModuleBuilder {
|
|||
}
|
||||
|
||||
// Add functions declarations
|
||||
let has_names = false;
|
||||
let names = false;
|
||||
if (wasm.functions.length > 0) {
|
||||
if (debug) print("emitting function decls @ " + binary.length);
|
||||
binary.emit_section(kFunctionSectionCode, section => {
|
||||
section.emit_u32v(wasm.functions.length);
|
||||
for (let func of wasm.functions) {
|
||||
has_names = has_names || (func.name != undefined &&
|
||||
func.name.length > 0);
|
||||
section.emit_u32v(func.type_index);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Add function_table.
|
||||
if (wasm.function_table_length > 0) {
|
||||
// Add table section
|
||||
if (wasm.table_length_min > 0) {
|
||||
if (debug) print("emitting table @ " + binary.length);
|
||||
binary.emit_section(kTableSectionCode, section => {
|
||||
section.emit_u8(1); // one table entry
|
||||
section.emit_u8(kWasmAnyFunctionTypeForm);
|
||||
section.emit_u8(1);
|
||||
section.emit_u32v(wasm.function_table_length);
|
||||
section.emit_u32v(wasm.function_table_length);
|
||||
const max = wasm.table_length_max;
|
||||
const has_max = max !== undefined;
|
||||
section.emit_u8(has_max ? kHasMaximumFlag : 0);
|
||||
section.emit_u32v(wasm.table_length_min);
|
||||
if (has_max) section.emit_u32v(max);
|
||||
});
|
||||
}
|
||||
|
||||
// Add memory section
|
||||
if (wasm.memory != undefined) {
|
||||
if (wasm.memory !== undefined) {
|
||||
if (debug) print("emitting memory @ " + binary.length);
|
||||
binary.emit_section(kMemorySectionCode, section => {
|
||||
section.emit_u8(1); // one memory entry
|
||||
section.emit_u32v(kResizableMaximumFlag);
|
||||
const has_max = wasm.memory.max !== undefined;
|
||||
section.emit_u8(has_max ? kHasMaximumFlag : 0);
|
||||
section.emit_u32v(wasm.memory.min);
|
||||
section.emit_u32v(wasm.memory.max);
|
||||
if (has_max) section.emit_u32v(wasm.memory.max);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -359,7 +438,7 @@ class WasmModuleBuilder {
|
|||
break;
|
||||
case kWasmI64:
|
||||
section.emit_u8(kExprI64Const);
|
||||
section.emit_u8(global.init);
|
||||
section.emit_u32v(global.init);
|
||||
break;
|
||||
case kWasmF32:
|
||||
section.emit_u8(kExprF32Const);
|
||||
|
@ -393,7 +472,7 @@ class WasmModuleBuilder {
|
|||
}
|
||||
|
||||
// Add export table.
|
||||
var mem_export = (wasm.memory != undefined && wasm.memory.exp);
|
||||
var mem_export = (wasm.memory !== undefined && wasm.memory.exp);
|
||||
var exports_count = wasm.exports.length + (mem_export ? 1 : 0);
|
||||
if (exports_count > 0) {
|
||||
if (debug) print("emitting exports @ " + binary.length);
|
||||
|
@ -413,22 +492,22 @@ class WasmModuleBuilder {
|
|||
}
|
||||
|
||||
// Add start function section.
|
||||
if (wasm.start_index != undefined) {
|
||||
if (wasm.start_index !== undefined) {
|
||||
if (debug) print("emitting start function @ " + binary.length);
|
||||
binary.emit_section(kStartSectionCode, section => {
|
||||
section.emit_u32v(wasm.start_index);
|
||||
});
|
||||
}
|
||||
|
||||
// Add table elements.
|
||||
if (wasm.function_table_inits.length > 0) {
|
||||
if (debug) print("emitting table @ " + binary.length);
|
||||
// Add element segments
|
||||
if (wasm.element_segments.length > 0) {
|
||||
if (debug) print("emitting element segments @ " + binary.length);
|
||||
binary.emit_section(kElementSectionCode, section => {
|
||||
var inits = wasm.function_table_inits;
|
||||
var inits = wasm.element_segments;
|
||||
section.emit_u32v(inits.length);
|
||||
section.emit_u8(0); // table index
|
||||
|
||||
for (let init of inits) {
|
||||
section.emit_u8(0); // table index
|
||||
if (init.is_global) {
|
||||
section.emit_u8(kExprGetGlobal);
|
||||
} else {
|
||||
|
@ -453,9 +532,7 @@ class WasmModuleBuilder {
|
|||
for (let func of wasm.functions) {
|
||||
// Function body length will be patched later.
|
||||
let local_decls = [];
|
||||
let l = func.locals;
|
||||
if (l != undefined) {
|
||||
let local_decls_count = 0;
|
||||
for (let l of func.locals || []) {
|
||||
if (l.i32_count > 0) {
|
||||
local_decls.push({count: l.i32_count, type: kWasmI32});
|
||||
}
|
||||
|
@ -485,11 +562,11 @@ class WasmModuleBuilder {
|
|||
}
|
||||
|
||||
// Add data segments.
|
||||
if (wasm.segments.length > 0) {
|
||||
if (wasm.data_segments.length > 0) {
|
||||
if (debug) print("emitting data segments @ " + binary.length);
|
||||
binary.emit_section(kDataSectionCode, section => {
|
||||
section.emit_u32v(wasm.segments.length);
|
||||
for (let seg of wasm.segments) {
|
||||
section.emit_u32v(wasm.data_segments.length);
|
||||
for (let seg of wasm.data_segments) {
|
||||
section.emit_u8(0); // linear memory index 0
|
||||
if (seg.is_global) {
|
||||
// initializer is a global variable
|
||||
|
@ -513,21 +590,50 @@ class WasmModuleBuilder {
|
|||
binary.emit_bytes(exp);
|
||||
}
|
||||
|
||||
// Add function names.
|
||||
if (has_names) {
|
||||
if (debug) print("emitting names @ " + binary.length);
|
||||
// Add names.
|
||||
let num_function_names = 0;
|
||||
let num_functions_with_local_names = 0;
|
||||
for (let func of wasm.functions) {
|
||||
if (func.name !== undefined) ++num_function_names;
|
||||
if (func.numLocalNames() > 0) ++num_functions_with_local_names;
|
||||
}
|
||||
if (num_function_names > 0 || num_functions_with_local_names > 0 ||
|
||||
wasm.name !== undefined) {
|
||||
if (debug) print('emitting names @ ' + binary.length);
|
||||
binary.emit_section(kUnknownSectionCode, section => {
|
||||
section.emit_string("name");
|
||||
var count = wasm.functions.length + wasm.num_imported_funcs;
|
||||
section.emit_u32v(count);
|
||||
for (var i = 0; i < wasm.num_imported_funcs; i++) {
|
||||
section.emit_u8(0); // empty string
|
||||
section.emit_u8(0); // local names count == 0
|
||||
section.emit_string('name');
|
||||
// Emit module name.
|
||||
if (wasm.name !== undefined) {
|
||||
section.emit_section(kModuleNameCode, name_section => {
|
||||
name_section.emit_string(wasm.name);
|
||||
});
|
||||
}
|
||||
for (let func of wasm.functions) {
|
||||
var name = func.name == undefined ? "" : func.name;
|
||||
section.emit_string(name);
|
||||
section.emit_u8(0); // local names count == 0
|
||||
// Emit function names.
|
||||
if (num_function_names > 0) {
|
||||
section.emit_section(kFunctionNamesCode, name_section => {
|
||||
name_section.emit_u32v(num_function_names);
|
||||
for (let func of wasm.functions) {
|
||||
if (func.name === undefined) continue;
|
||||
name_section.emit_u32v(func.index);
|
||||
name_section.emit_string(func.name);
|
||||
}
|
||||
});
|
||||
}
|
||||
// Emit local names.
|
||||
if (num_functions_with_local_names > 0) {
|
||||
section.emit_section(kLocalNamesCode, name_section => {
|
||||
name_section.emit_u32v(num_functions_with_local_names);
|
||||
for (let func of wasm.functions) {
|
||||
if (func.numLocalNames() == 0) continue;
|
||||
name_section.emit_u32v(func.index);
|
||||
name_section.emit_u32v(func.numLocalNames());
|
||||
for (let i = 0; i < func.local_names.length; ++i) {
|
||||
if (func.local_names[i] === undefined) continue;
|
||||
name_section.emit_u32v(i);
|
||||
name_section.emit_string(func.local_names[i]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -544,12 +650,21 @@ class WasmModuleBuilder {
|
|||
if ((typeof val) == "string") val = val.charCodeAt(0);
|
||||
view[i] = val | 0;
|
||||
}
|
||||
return new Uint8Array(buffer);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
instantiate(...args) {
|
||||
instantiate(ffi) {
|
||||
let module = new WebAssembly.Module(this.toBuffer());
|
||||
let instance = new WebAssembly.Instance(module, ...args);
|
||||
let instance = new WebAssembly.Instance(module, ffi);
|
||||
return instance;
|
||||
}
|
||||
|
||||
asyncInstantiate(ffi) {
|
||||
return WebAssembly.instantiate(this.toBuffer(), ffi)
|
||||
.then(({module, instance}) => instance);
|
||||
}
|
||||
|
||||
toModule(debug = false) {
|
||||
return new WebAssembly.Module(this.toBuffer(debug));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue