Index: src/wasm/wasm-js.cc |
diff --git a/src/wasm/wasm-js.cc b/src/wasm/wasm-js.cc |
index d07ff013f32ec377bfa58d0a972359496c8e3e8f..9d14de522355eaf81708522d3c34f663a37accda 100644 |
--- a/src/wasm/wasm-js.cc |
+++ b/src/wasm/wasm-js.cc |
@@ -68,7 +68,7 @@ RawBuffer GetRawBufferSource( |
end = start + array->ByteLength(); |
} else { |
- thrower->TypeError("Argument 0 must be an ArrayBuffer or Uint8Array"); |
+ thrower->TypeError("Argument 0 must be a buffer source"); |
} |
if (start == nullptr || end == start) { |
thrower->CompileError("BufferSource argument is empty"); |
@@ -106,6 +106,17 @@ static bool ValidateModule(v8::Isolate* isolate, |
i::wasm::ModuleOrigin::kWasmOrigin); |
} |
+// TODO(wasm): move brand check to the respective types, and don't throw |
+// in it, rather, use a provided ErrorThrower, or let caller handle it. |
+static bool BrandCheck(Isolate* isolate, i::Handle<i::Object> value, |
+ i::Handle<i::Symbol> sym) { |
+ if (!value->IsJSObject()) return false; |
+ i::Handle<i::JSObject> object = i::Handle<i::JSObject>::cast(value); |
+ Maybe<bool> has_brand = i::JSObject::HasOwnProperty(object, sym); |
+ if (has_brand.IsNothing()) return false; |
+ return has_brand.ToChecked(); |
+} |
+ |
static bool BrandCheck(Isolate* isolate, i::Handle<i::Object> value, |
i::Handle<i::Symbol> sym, const char* msg) { |
if (value->IsJSObject()) { |
@@ -177,11 +188,6 @@ void WebAssemblyModule(const v8::FunctionCallbackInfo<v8::Value>& args) { |
return; |
} |
- if (args.Length() > 2) { |
- thrower.LinkError( |
- "WebAssembly.instantiate accepts no more than 2 parameters"); |
- return; |
- } |
i::MaybeHandle<i::JSObject> module_obj = |
CreateModuleObject(isolate, args[0], &thrower); |
if (module_obj.is_null()) return; |
@@ -328,33 +334,72 @@ void WebAssemblyInstantiate(const v8::FunctionCallbackInfo<v8::Value>& args) { |
ErrorThrower thrower(i_isolate, "WebAssembly.compile()"); |
Local<Context> context = isolate->GetCurrentContext(); |
+ i::Handle<i::Context> i_context = Utils::OpenHandle(*context); |
+ |
v8::Local<v8::Promise::Resolver> resolver; |
if (!v8::Promise::Resolver::New(context).ToLocal(&resolver)) return; |
v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); |
return_value.Set(resolver->GetPromise()); |
if (args.Length() < 1) { |
- thrower.TypeError("Argument 0 must be a buffer source"); |
+ thrower.TypeError( |
+ "Argument 0 must be provided and must be either a buffer source or a " |
+ "WebAssembly.Module object"); |
resolver->Reject(context, Utils::ToLocal(thrower.Reify())); |
return; |
} |
- i::MaybeHandle<i::WasmModuleObject> module_obj = |
- CreateModuleObject(isolate, args[0], &thrower); |
- if (module_obj.is_null()) { |
- DCHECK(thrower.error()); |
+ i::Handle<i::Object> first_arg = Utils::OpenHandle(*args[0]); |
+ if (!first_arg->IsJSObject()) { |
+ thrower.TypeError( |
+ "Argument 0 must be a buffer source or a WebAssembly.Module object"); |
resolver->Reject(context, Utils::ToLocal(thrower.Reify())); |
return; |
} |
- |
- MaybeLocal<Value> instance = InstantiateModuleImpl( |
- i_isolate, module_obj.ToHandleChecked(), args, &thrower); |
+ bool want_pair = !BrandCheck( |
+ isolate, first_arg, i::Handle<i::Symbol>(i_context->wasm_module_sym())); |
+ i::Handle<i::WasmModuleObject> module_obj; |
+ if (want_pair) { |
+ i::MaybeHandle<i::WasmModuleObject> maybe_module_obj = |
+ CreateModuleObject(isolate, args[0], &thrower); |
+ if (!maybe_module_obj.ToHandle(&module_obj)) { |
+ DCHECK(thrower.error()); |
+ resolver->Reject(context, Utils::ToLocal(thrower.Reify())); |
+ return; |
+ } |
+ } else { |
+ module_obj = i::Handle<i::WasmModuleObject>::cast(first_arg); |
+ } |
+ DCHECK(!module_obj.is_null()); |
+ MaybeLocal<Value> instance = |
+ InstantiateModuleImpl(i_isolate, module_obj, args, &thrower); |
if (instance.IsEmpty()) { |
DCHECK(thrower.error()); |
resolver->Reject(context, Utils::ToLocal(thrower.Reify())); |
} else { |
DCHECK(!thrower.error()); |
- resolver->Resolve(context, instance.ToLocalChecked()); |
+ Local<Value> retval; |
+ if (want_pair) { |
+ i::Handle<i::JSFunction> object_function = i::Handle<i::JSFunction>( |
+ i_isolate->native_context()->object_function(), i_isolate); |
+ |
+ i::Handle<i::JSObject> i_retval = |
+ i_isolate->factory()->NewJSObject(object_function, i::TENURED); |
+ i::Handle<i::String> module_property_name = |
+ i_isolate->factory()->InternalizeUtf8String("module"); |
+ i::Handle<i::String> instance_property_name = |
+ i_isolate->factory()->InternalizeUtf8String("instance"); |
+ i::JSObject::AddProperty(i_retval, module_property_name, module_obj, |
+ i::NONE); |
+ i::JSObject::AddProperty(i_retval, instance_property_name, |
+ Utils::OpenHandle(*instance.ToLocalChecked()), |
+ i::NONE); |
+ retval = Utils::ToLocal(i_retval); |
+ } else { |
+ retval = instance.ToLocalChecked(); |
+ } |
+ DCHECK(!retval.IsEmpty()); |
+ resolver->Resolve(context, retval); |
} |
} |