static EncodedJSValue JSC_HOST_CALL constructJSWebAssemblyModule(ExecState* state) { VM& vm = state->vm(); auto scope = DECLARE_THROW_SCOPE(vm); JSValue val = state->argument(0); // If the given bytes argument is not a BufferSource, a TypeError exception is thrown. JSArrayBuffer* arrayBuffer = val.getObject() ? jsDynamicCast<JSArrayBuffer*>(val.getObject()) : nullptr; JSArrayBufferView* arrayBufferView = val.getObject() ? jsDynamicCast<JSArrayBufferView*>(val.getObject()) : nullptr; if (!(arrayBuffer || arrayBufferView)) return JSValue::encode(throwException(state, scope, createTypeError(state, ASCIILiteral("first argument to WebAssembly.Module must be an ArrayBufferView or an ArrayBuffer"), defaultSourceAppender, runtimeTypeForValue(val)))); if (arrayBufferView ? arrayBufferView->isNeutered() : arrayBuffer->impl()->isNeutered()) return JSValue::encode(throwException(state, scope, createTypeError(state, ASCIILiteral("underlying TypedArray has been detatched from the ArrayBuffer"), defaultSourceAppender, runtimeTypeForValue(val)))); size_t byteOffset = arrayBufferView ? arrayBufferView->byteOffset() : 0; size_t byteSize = arrayBufferView ? arrayBufferView->length() : arrayBuffer->impl()->byteLength(); const auto* base = arrayBufferView ? static_cast<uint8_t*>(arrayBufferView->vector()) : static_cast<uint8_t*>(arrayBuffer->impl()->data()); Wasm::Plan plan(&vm, base + byteOffset, byteSize); // On failure, a new WebAssembly.CompileError is thrown. plan.run(); if (plan.failed()) return JSValue::encode(throwException(state, scope, createWebAssemblyCompileError(state, plan.errorMessage()))); // On success, a new WebAssembly.Module object is returned with [[Module]] set to the validated Ast.module. auto* structure = InternalFunction::createSubclassStructure(state, state->newTarget(), asInternalFunction(state->jsCallee())->globalObject()->WebAssemblyModuleStructure()); RETURN_IF_EXCEPTION(scope, { }); // The export symbol table is the same for all Instances of a Module. SymbolTable* exportSymbolTable = SymbolTable::create(vm); for (auto& exp : plan.exports()) { auto offset = exportSymbolTable->takeNextScopeOffset(NoLockingNecessary); exportSymbolTable->set(NoLockingNecessary, exp.field.impl(), SymbolTableEntry(VarOffset(offset))); } // Only wasm-internal functions have a callee, stubs to JS do not. unsigned calleeCount = plan.internalFunctionCount(); JSWebAssemblyModule* result = JSWebAssemblyModule::create(vm, structure, plan.takeModuleInformation(), plan.takeCallLinkInfos(), plan.takeWasmToJSStubs(), plan.takeFunctionIndexSpace(), exportSymbolTable, calleeCount); plan.initializeCallees(state->jsCallee()->globalObject(), [&] (unsigned calleeIndex, JSWebAssemblyCallee* jsEntrypointCallee, JSWebAssemblyCallee* wasmEntrypointCallee) { result->setJSEntrypointCallee(vm, calleeIndex, jsEntrypointCallee); result->setWasmEntrypointCallee(vm, calleeIndex, wasmEntrypointCallee); }); return JSValue::encode(result); }
JSValue WebAssemblyModuleConstructor::createModule(ExecState* state, Structure* structure) { VM& vm = state->vm(); auto scope = DECLARE_THROW_SCOPE(vm); size_t byteOffset; size_t byteSize; uint8_t* base = getWasmBufferFromValue(state, state->argument(0), byteOffset, byteSize); RETURN_IF_EXCEPTION(scope, { }); Wasm::Plan plan(&vm, base + byteOffset, byteSize); // On failure, a new WebAssembly.CompileError is thrown. plan.run(); if (plan.failed()) return throwException(state, scope, createJSWebAssemblyCompileError(state, vm, plan.errorMessage())); // On success, a new WebAssembly.Module object is returned with [[Module]] set to the validated Ast.module. // The export symbol table is the same for all Instances of a Module. SymbolTable* exportSymbolTable = SymbolTable::create(vm); for (auto& exp : plan.exports()) { auto offset = exportSymbolTable->takeNextScopeOffset(NoLockingNecessary); exportSymbolTable->set(NoLockingNecessary, exp.field.impl(), SymbolTableEntry(VarOffset(offset))); } // Only wasm-internal functions have a callee, stubs to JS do not. unsigned calleeCount = plan.internalFunctionCount(); JSWebAssemblyModule* result = JSWebAssemblyModule::create(vm, structure, plan.takeModuleInformation(), plan.takeCallLinkInfos(), plan.takeWasmExitStubs(), exportSymbolTable, calleeCount); plan.initializeCallees(state->jsCallee()->globalObject(), [&] (unsigned calleeIndex, JSWebAssemblyCallee* jsEntrypointCallee, JSWebAssemblyCallee* wasmEntrypointCallee) { result->setJSEntrypointCallee(vm, calleeIndex, jsEntrypointCallee); result->setWasmEntrypointCallee(vm, calleeIndex, wasmEntrypointCallee); }); return result; }