OLD | NEW |
---|---|
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/api-natives.h" | 5 #include "src/api-natives.h" |
6 #include "src/api.h" | 6 #include "src/api.h" |
7 #include "src/asmjs/asm-js.h" | 7 #include "src/asmjs/asm-js.h" |
8 #include "src/asmjs/asm-typer.h" | 8 #include "src/asmjs/asm-typer.h" |
9 #include "src/asmjs/asm-wasm-builder.h" | 9 #include "src/asmjs/asm-wasm-builder.h" |
10 #include "src/assert-scope.h" | 10 #include "src/assert-scope.h" |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
61 Local<TypedArray> array = Local<TypedArray>::Cast(source); | 61 Local<TypedArray> array = Local<TypedArray>::Cast(source); |
62 Local<ArrayBuffer> buffer = array->Buffer(); | 62 Local<ArrayBuffer> buffer = array->Buffer(); |
63 | 63 |
64 ArrayBuffer::Contents contents = buffer->GetContents(); | 64 ArrayBuffer::Contents contents = buffer->GetContents(); |
65 | 65 |
66 start = | 66 start = |
67 reinterpret_cast<const byte*>(contents.Data()) + array->ByteOffset(); | 67 reinterpret_cast<const byte*>(contents.Data()) + array->ByteOffset(); |
68 end = start + array->ByteLength(); | 68 end = start + array->ByteLength(); |
69 | 69 |
70 } else { | 70 } else { |
71 thrower->TypeError("Argument 0 must be an ArrayBuffer or Uint8Array"); | 71 thrower->TypeError("Argument 0 must be a buffer source"); |
72 } | 72 } |
73 if (start == nullptr || end == start) { | 73 if (start == nullptr || end == start) { |
74 thrower->CompileError("BufferSource argument is empty"); | 74 thrower->CompileError("BufferSource argument is empty"); |
75 } | 75 } |
76 return {start, end}; | 76 return {start, end}; |
77 } | 77 } |
78 | 78 |
79 static i::MaybeHandle<i::WasmModuleObject> CreateModuleObject( | 79 static i::MaybeHandle<i::WasmModuleObject> CreateModuleObject( |
80 v8::Isolate* isolate, const v8::Local<v8::Value> source, | 80 v8::Isolate* isolate, const v8::Local<v8::Value> source, |
81 ErrorThrower* thrower) { | 81 ErrorThrower* thrower) { |
(...skipping 17 matching lines...) Expand all Loading... | |
99 | 99 |
100 RawBuffer buffer = GetRawBufferSource(source, thrower); | 100 RawBuffer buffer = GetRawBufferSource(source, thrower); |
101 if (buffer.start == nullptr) return false; | 101 if (buffer.start == nullptr) return false; |
102 | 102 |
103 DCHECK(source->IsArrayBuffer() || source->IsTypedArray()); | 103 DCHECK(source->IsArrayBuffer() || source->IsTypedArray()); |
104 return i::wasm::ValidateModuleBytes(i_isolate, buffer.start, buffer.end, | 104 return i::wasm::ValidateModuleBytes(i_isolate, buffer.start, buffer.end, |
105 thrower, | 105 thrower, |
106 i::wasm::ModuleOrigin::kWasmOrigin); | 106 i::wasm::ModuleOrigin::kWasmOrigin); |
107 } | 107 } |
108 | 108 |
109 // TODO(wasm): move brand check to the respective types, and don't throw | |
110 // in it, rather, use a provided ErrorThrower, or let caller handle it. | |
111 static bool BrandCheck(Isolate* isolate, i::Handle<i::Object> value, | |
112 i::Handle<i::Symbol> sym) { | |
113 if (!value->IsJSObject()) return false; | |
114 i::Handle<i::JSObject> object = i::Handle<i::JSObject>::cast(value); | |
115 Maybe<bool> has_brand = i::JSObject::HasOwnProperty(object, sym); | |
116 if (has_brand.IsNothing()) return false; | |
117 return has_brand.ToChecked(); | |
118 } | |
119 | |
109 static bool BrandCheck(Isolate* isolate, i::Handle<i::Object> value, | 120 static bool BrandCheck(Isolate* isolate, i::Handle<i::Object> value, |
110 i::Handle<i::Symbol> sym, const char* msg) { | 121 i::Handle<i::Symbol> sym, const char* msg) { |
111 if (value->IsJSObject()) { | 122 if (value->IsJSObject()) { |
112 i::Handle<i::JSObject> object = i::Handle<i::JSObject>::cast(value); | 123 i::Handle<i::JSObject> object = i::Handle<i::JSObject>::cast(value); |
113 Maybe<bool> has_brand = i::JSObject::HasOwnProperty(object, sym); | 124 Maybe<bool> has_brand = i::JSObject::HasOwnProperty(object, sym); |
114 if (has_brand.IsNothing()) return false; | 125 if (has_brand.IsNothing()) return false; |
115 if (has_brand.ToChecked()) return true; | 126 if (has_brand.ToChecked()) return true; |
116 } | 127 } |
117 v8::Local<v8::Value> e = v8::Exception::TypeError(v8_str(isolate, msg)); | 128 v8::Local<v8::Value> e = v8::Exception::TypeError(v8_str(isolate, msg)); |
118 isolate->ThrowException(e); | 129 isolate->ThrowException(e); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
162 return_value.Set(v8::False(isolate)); | 173 return_value.Set(v8::False(isolate)); |
163 } | 174 } |
164 } | 175 } |
165 | 176 |
166 void WebAssemblyModule(const v8::FunctionCallbackInfo<v8::Value>& args) { | 177 void WebAssemblyModule(const v8::FunctionCallbackInfo<v8::Value>& args) { |
167 v8::Isolate* isolate = args.GetIsolate(); | 178 v8::Isolate* isolate = args.GetIsolate(); |
168 HandleScope scope(isolate); | 179 HandleScope scope(isolate); |
169 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), | 180 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), |
170 "WebAssembly.Module()"); | 181 "WebAssembly.Module()"); |
171 | 182 |
172 if (args.Length() < 1) { | 183 if (args.Length() != 1) { |
rossberg
2017/01/20 09:56:54
JavaScript always allows unused extra arguments, s
Mircea Trofin
2017/01/20 16:29:53
Done.
| |
173 thrower.TypeError("Argument 0 must be a buffer source"); | 184 thrower.TypeError("Argument 0 must be a buffer source"); |
174 return; | 185 return; |
175 } | 186 } |
176 | 187 |
177 if (args.Length() > 2) { | |
178 thrower.LinkError( | |
179 "WebAssembly.instantiate accepts no more than 2 parameters"); | |
180 return; | |
181 } | |
182 i::MaybeHandle<i::JSObject> module_obj = | 188 i::MaybeHandle<i::JSObject> module_obj = |
183 CreateModuleObject(isolate, args[0], &thrower); | 189 CreateModuleObject(isolate, args[0], &thrower); |
184 if (module_obj.is_null()) return; | 190 if (module_obj.is_null()) return; |
185 | 191 |
186 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); | 192 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); |
187 return_value.Set(Utils::ToLocal(module_obj.ToHandleChecked())); | 193 return_value.Set(Utils::ToLocal(module_obj.ToHandleChecked())); |
188 } | 194 } |
189 | 195 |
190 MaybeLocal<Value> InstantiateModuleImpl( | 196 MaybeLocal<Value> InstantiateModuleImpl( |
191 i::Isolate* i_isolate, i::Handle<i::WasmModuleObject> i_module_obj, | 197 i::Isolate* i_isolate, i::Handle<i::WasmModuleObject> i_module_obj, |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
318 } | 324 } |
319 | 325 |
320 void WebAssemblyInstantiate(const v8::FunctionCallbackInfo<v8::Value>& args) { | 326 void WebAssemblyInstantiate(const v8::FunctionCallbackInfo<v8::Value>& args) { |
321 v8::Isolate* isolate = args.GetIsolate(); | 327 v8::Isolate* isolate = args.GetIsolate(); |
322 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 328 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
323 | 329 |
324 HandleScope scope(isolate); | 330 HandleScope scope(isolate); |
325 ErrorThrower thrower(i_isolate, "WebAssembly.compile()"); | 331 ErrorThrower thrower(i_isolate, "WebAssembly.compile()"); |
326 | 332 |
327 Local<Context> context = isolate->GetCurrentContext(); | 333 Local<Context> context = isolate->GetCurrentContext(); |
334 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); | |
335 | |
328 v8::Local<v8::Promise::Resolver> resolver; | 336 v8::Local<v8::Promise::Resolver> resolver; |
329 if (!v8::Promise::Resolver::New(context).ToLocal(&resolver)) return; | 337 if (!v8::Promise::Resolver::New(context).ToLocal(&resolver)) return; |
330 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); | 338 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); |
331 return_value.Set(resolver->GetPromise()); | 339 return_value.Set(resolver->GetPromise()); |
332 | 340 |
333 if (args.Length() < 1) { | 341 if (args.Length() < 1) { |
334 thrower.TypeError("Argument 0 must be a buffer source"); | 342 thrower.TypeError( |
343 "Argument 0 must be provided and must be either a buffer source or a " | |
344 "WebAssembly.Module object"); | |
335 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); | 345 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); |
336 return; | 346 return; |
337 } | 347 } |
338 | 348 |
339 i::MaybeHandle<i::WasmModuleObject> module_obj = | 349 i::Handle<i::Object> first_arg = Utils::OpenHandle(*args[0]); |
340 CreateModuleObject(isolate, args[0], &thrower); | 350 if (!first_arg->IsJSObject()) { |
341 if (module_obj.is_null()) { | 351 thrower.TypeError( |
342 DCHECK(thrower.error()); | 352 "Argument 0 must be a buffer source or a WebAssembly.Module object"); |
343 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); | 353 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); |
344 return; | 354 return; |
345 } | 355 } |
346 | 356 bool want_pair = !BrandCheck( |
347 MaybeLocal<Value> instance = InstantiateModuleImpl( | 357 isolate, first_arg, i::Handle<i::Symbol>(i_context->wasm_module_sym())); |
348 i_isolate, module_obj.ToHandleChecked(), args, &thrower); | 358 i::Handle<i::WasmModuleObject> module_obj; |
359 if (want_pair) { | |
360 i::MaybeHandle<i::WasmModuleObject> maybe_module_obj = | |
361 CreateModuleObject(isolate, args[0], &thrower); | |
362 if (!maybe_module_obj.ToHandle(&module_obj)) { | |
363 DCHECK(thrower.error()); | |
364 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); | |
365 return; | |
366 } | |
367 } else { | |
368 module_obj = i::Handle<i::WasmModuleObject>::cast(first_arg); | |
369 } | |
370 DCHECK(!module_obj.is_null()); | |
371 MaybeLocal<Value> instance = | |
372 InstantiateModuleImpl(i_isolate, module_obj, args, &thrower); | |
349 if (instance.IsEmpty()) { | 373 if (instance.IsEmpty()) { |
350 DCHECK(thrower.error()); | 374 DCHECK(thrower.error()); |
351 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); | 375 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); |
352 } else { | 376 } else { |
353 DCHECK(!thrower.error()); | 377 DCHECK(!thrower.error()); |
354 resolver->Resolve(context, instance.ToLocalChecked()); | 378 Local<Value> retval; |
379 if (want_pair) { | |
380 i::Handle<i::JSFunction> object_function = i::Handle<i::JSFunction>( | |
381 i_isolate->native_context()->object_function(), i_isolate); | |
382 | |
383 i::Handle<i::JSObject> i_retval = | |
384 i_isolate->factory()->NewJSObject(object_function, i::TENURED); | |
385 i::Handle<i::String> module_property_name = | |
386 i_isolate->factory()->InternalizeUtf8String("module"); | |
387 i::Handle<i::String> instance_property_name = | |
388 i_isolate->factory()->InternalizeUtf8String("instance"); | |
389 i::JSObject::AddProperty(i_retval, module_property_name, module_obj, | |
390 i::NONE); | |
391 i::JSObject::AddProperty(i_retval, instance_property_name, | |
392 Utils::OpenHandle(*instance.ToLocalChecked()), | |
393 i::NONE); | |
394 retval = Utils::ToLocal(i_retval); | |
395 } else { | |
396 retval = instance.ToLocalChecked(); | |
397 } | |
398 DCHECK(!retval.IsEmpty()); | |
399 resolver->Resolve(context, retval); | |
355 } | 400 } |
356 } | 401 } |
357 | 402 |
358 bool GetIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower, | 403 bool GetIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower, |
359 Local<Context> context, Local<v8::Object> object, | 404 Local<Context> context, Local<v8::Object> object, |
360 Local<String> property, int* result, | 405 Local<String> property, int* result, |
361 int64_t lower_bound, uint64_t upper_bound) { | 406 int64_t lower_bound, uint64_t upper_bound) { |
362 v8::MaybeLocal<v8::Value> maybe = object->Get(context, property); | 407 v8::MaybeLocal<v8::Value> maybe = object->Get(context, property); |
363 v8::Local<v8::Value> value; | 408 v8::Local<v8::Value> value; |
364 if (maybe.ToLocal(&value)) { | 409 if (maybe.ToLocal(&value)) { |
(...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
903 i::Handle<i::Symbol> symbol(isolate->context()->wasm_memory_sym(), isolate); | 948 i::Handle<i::Symbol> symbol(isolate->context()->wasm_memory_sym(), isolate); |
904 return HasBrand(value, symbol); | 949 return HasBrand(value, symbol); |
905 } | 950 } |
906 | 951 |
907 bool WasmJs::IsWasmTableObject(Isolate* isolate, Handle<Object> value) { | 952 bool WasmJs::IsWasmTableObject(Isolate* isolate, Handle<Object> value) { |
908 i::Handle<i::Symbol> symbol(isolate->context()->wasm_table_sym(), isolate); | 953 i::Handle<i::Symbol> symbol(isolate->context()->wasm_table_sym(), isolate); |
909 return HasBrand(value, symbol); | 954 return HasBrand(value, symbol); |
910 } | 955 } |
911 } // namespace internal | 956 } // namespace internal |
912 } // namespace v8 | 957 } // namespace v8 |
OLD | NEW |