Commit bbf00d80 authored by titzer's avatar titzer Committed by Commit bot

[wasm] Implement WebAssembly.Module.exports function.

R=rossberg@chromium.org
BUG=v8:5814,chromium:575167

Review-Url: https://codereview.chromium.org/2623183002
Cr-Commit-Position: refs/heads/master@{#42233}
parent 7374a16d
...@@ -262,6 +262,36 @@ void WebAssemblyModuleImports(const v8::FunctionCallbackInfo<v8::Value>& args) { ...@@ -262,6 +262,36 @@ void WebAssemblyModuleImports(const v8::FunctionCallbackInfo<v8::Value>& args) {
return_value.Set(Utils::ToLocal(imports)); return_value.Set(Utils::ToLocal(imports));
} }
void WebAssemblyModuleExports(const v8::FunctionCallbackInfo<v8::Value>& args) {
HandleScope scope(args.GetIsolate());
v8::Isolate* isolate = args.GetIsolate();
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
ErrorThrower thrower(i_isolate, "WebAssembly.Module.exports()");
if (args.Length() < 1) {
thrower.TypeError("Argument 0 must be a WebAssembly.Module");
return;
}
Local<Context> context = isolate->GetCurrentContext();
i::Handle<i::Context> i_context = Utils::OpenHandle(*context);
if (!BrandCheck(isolate, Utils::OpenHandle(*args[0]),
i::Handle<i::Symbol>(i_context->wasm_module_sym()),
"Argument 0 must be a WebAssembly.Module")) {
return;
}
Local<Object> module_obj = Local<Object>::Cast(args[0]);
i::Handle<i::WasmModuleObject> i_module_obj =
i::Handle<i::WasmModuleObject>::cast(v8::Utils::OpenHandle(*module_obj));
i::Handle<i::JSArray> exports = i::wasm::GetExports(i_isolate, i_module_obj);
v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
return_value.Set(Utils::ToLocal(exports));
}
void WebAssemblyInstanceCtor(const v8::FunctionCallbackInfo<v8::Value>& args) { void WebAssemblyInstanceCtor(const v8::FunctionCallbackInfo<v8::Value>& args) {
HandleScope scope(args.GetIsolate()); HandleScope scope(args.GetIsolate());
v8::Isolate* isolate = args.GetIsolate(); v8::Isolate* isolate = args.GetIsolate();
...@@ -753,6 +783,8 @@ void WasmJs::InstallWasmConstructors(Isolate* isolate, ...@@ -753,6 +783,8 @@ void WasmJs::InstallWasmConstructors(Isolate* isolate,
module_constructor, DONT_ENUM); module_constructor, DONT_ENUM);
InstallFunc(isolate, module_constructor, "imports", WebAssemblyModuleImports, InstallFunc(isolate, module_constructor, "imports", WebAssemblyModuleImports,
1); 1);
InstallFunc(isolate, module_constructor, "exports", WebAssemblyModuleExports,
1);
// Setup Instance // Setup Instance
Handle<JSFunction> instance_constructor = Handle<JSFunction> instance_constructor =
......
...@@ -2402,3 +2402,66 @@ Handle<JSArray> wasm::GetImports(Isolate* isolate, ...@@ -2402,3 +2402,66 @@ Handle<JSArray> wasm::GetImports(Isolate* isolate,
return array_object; return array_object;
} }
Handle<JSArray> wasm::GetExports(Isolate* isolate,
Handle<WasmModuleObject> module_object) {
Handle<WasmCompiledModule> compiled_module(module_object->compiled_module(),
isolate);
Factory* factory = isolate->factory();
Handle<String> name_string = factory->InternalizeUtf8String("name");
Handle<String> kind_string = factory->InternalizeUtf8String("kind");
Handle<String> function_string = factory->InternalizeUtf8String("function");
Handle<String> table_string = factory->InternalizeUtf8String("table");
Handle<String> memory_string = factory->InternalizeUtf8String("memory");
Handle<String> global_string = factory->InternalizeUtf8String("global");
// Create the result array.
WasmModule* module = compiled_module->module();
int num_exports = static_cast<int>(module->export_table.size());
Handle<JSArray> array_object = factory->NewJSArray(FAST_ELEMENTS, 0, 0);
Handle<FixedArray> storage = factory->NewFixedArray(num_exports);
JSArray::SetContent(array_object, storage);
array_object->set_length(Smi::FromInt(num_exports));
Handle<JSFunction> object_function =
Handle<JSFunction>(isolate->native_context()->object_function(), isolate);
// Populate the result array.
for (int index = 0; index < num_exports; ++index) {
WasmExport& exp = module->export_table[index];
Handle<JSObject> entry = factory->NewJSObject(object_function, TENURED);
Handle<String> export_kind;
switch (exp.kind) {
case kExternalFunction:
export_kind = function_string;
break;
case kExternalTable:
export_kind = table_string;
break;
case kExternalMemory:
export_kind = memory_string;
break;
case kExternalGlobal:
export_kind = global_string;
break;
default:
UNREACHABLE();
}
MaybeHandle<String> export_name =
WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
isolate, compiled_module, exp.name_offset, exp.name_length);
JSObject::AddProperty(entry, name_string, export_name.ToHandleChecked(),
NONE);
JSObject::AddProperty(entry, kind_string, export_kind, NONE);
storage->set(index, *entry);
}
return array_object;
}
...@@ -399,6 +399,9 @@ V8_EXPORT_PRIVATE MaybeHandle<WasmModuleObject> CreateModuleObjectFromBytes( ...@@ -399,6 +399,9 @@ V8_EXPORT_PRIVATE MaybeHandle<WasmModuleObject> CreateModuleObjectFromBytes(
V8_EXPORT_PRIVATE Handle<JSArray> GetImports(Isolate* isolate, V8_EXPORT_PRIVATE Handle<JSArray> GetImports(Isolate* isolate,
Handle<WasmModuleObject> module); Handle<WasmModuleObject> module);
V8_EXPORT_PRIVATE Handle<JSArray> GetExports(Isolate* isolate,
Handle<WasmModuleObject> module);
V8_EXPORT_PRIVATE bool ValidateModuleBytes(Isolate* isolate, const byte* start, V8_EXPORT_PRIVATE bool ValidateModuleBytes(Isolate* isolate, const byte* start,
const byte* end, const byte* end,
ErrorThrower* thrower, ErrorThrower* thrower,
......
...@@ -194,7 +194,6 @@ assertEq(arr[3].kind, "global"); ...@@ -194,7 +194,6 @@ assertEq(arr[3].kind, "global");
assertEq(arr[3].module, "g"); assertEq(arr[3].module, "g");
assertEq(arr[3].name, "x"); assertEq(arr[3].name, "x");
if (false) { // TODO: Module.exports property
// 'WebAssembly.Module.exports' data property // 'WebAssembly.Module.exports' data property
let moduleExportsDesc = Object.getOwnPropertyDescriptor(Module, 'exports'); let moduleExportsDesc = Object.getOwnPropertyDescriptor(Module, 'exports');
assertEq(typeof moduleExportsDesc.value, "function"); assertEq(typeof moduleExportsDesc.value, "function");
...@@ -211,7 +210,22 @@ assertErrorMessage(() => moduleExports({}), TypeError, /first argument must be a ...@@ -211,7 +210,22 @@ assertErrorMessage(() => moduleExports({}), TypeError, /first argument must be a
var arr = moduleExports(emptyModule); var arr = moduleExports(emptyModule);
assertEq(arr instanceof Array, true); assertEq(arr instanceof Array, true);
assertEq(arr.length, 0); assertEq(arr.length, 0);
var arr = moduleExports(new Module(wasmTextToBinary('(module (func (export "a")) (memory (export "b") 1) (table (export "c") 1 anyfunc) (global (export "⚡") i32 (i32.const 0)))'))); let exportingModuleBinary2 = (() => {
var text =
'(module (func (export "a")) (memory (export "b") 1) (table (export "c") 1 anyfunc) (global (export "⚡") i32 (i32.const 0)))';
let builder = new WasmModuleBuilder();
builder.addFunction("foo", kSig_v_v)
.addBody([])
.exportAs("a");
builder.addMemory(1, 1, false);
builder.exportMemoryAs("b");
builder.setFunctionTableLength(1);
builder.addExportOfKind("c", kExternalTable, 0);
var o = builder.addGlobal(kWasmI32, false)
.exportAs("x");
return new Int8Array(builder.toBuffer());
})();
var arr = moduleExports(new Module(exportingModuleBinary2));
assertEq(arr instanceof Array, true); assertEq(arr instanceof Array, true);
assertEq(arr.length, 4); assertEq(arr.length, 4);
assertEq(arr[0].kind, "function"); assertEq(arr[0].kind, "function");
...@@ -221,8 +235,7 @@ assertEq(arr[1].name, "b"); ...@@ -221,8 +235,7 @@ assertEq(arr[1].name, "b");
assertEq(arr[2].kind, "table"); assertEq(arr[2].kind, "table");
assertEq(arr[2].name, "c"); assertEq(arr[2].name, "c");
assertEq(arr[3].kind, "global"); assertEq(arr[3].kind, "global");
assertEq(arr[3].name, "⚡"); assertEq(arr[3].name, "x");
}
// 'WebAssembly.Instance' data property // 'WebAssembly.Instance' data property
let instanceDesc = Object.getOwnPropertyDescriptor(WebAssembly, 'Instance'); let instanceDesc = Object.getOwnPropertyDescriptor(WebAssembly, 'Instance');
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment