inline ArrayBuffer* toArrayBufferView(JSValue value) { JSArrayBufferView* wrapper = jsDynamicCast<JSArrayBufferView*>(value); if (!wrapper) return 0; return wrapper->buffer(); }
bool ArrayBuffer::transfer(ArrayBufferContents& result) { Ref<ArrayBuffer> protect(*this); if (!m_contents.m_data) { result.m_data = 0; return false; } bool isNeuterable = !m_pinCount; if (isNeuterable) m_contents.transfer(result); else { m_contents.copyTo(result); if (!result.m_data) return false; } for (size_t i = numberOfIncomingReferences(); i--;) { JSArrayBufferView* view = jsDynamicCast<JSArrayBufferView*>(incomingReferenceAt(i)); if (view) view->neuter(); } return true; }
void JSArrayBufferView::visitChildren(JSCell* cell, SlotVisitor& visitor) { JSArrayBufferView* thisObject = jsCast<JSArrayBufferView*>(cell); if (thisObject->hasArrayBuffer()) { ArrayBuffer* buffer = thisObject->buffer(); RELEASE_ASSERT(buffer); visitor.addOpaqueRoot(buffer); } Base::visitChildren(thisObject, visitor); }
EncodedJSValue JSC_HOST_CALL typedArrayViewPrivateFuncLength(ExecState* exec) { VM& vm = exec->vm(); auto scope = DECLARE_THROW_SCOPE(vm); JSValue argument = exec->argument(0); if (!argument.isCell() || !isTypedView(argument.asCell()->classInfo()->typedArrayStorageType)) return throwVMTypeError(exec, scope, ASCIILiteral("Receiver should be a typed array view")); JSArrayBufferView* thisObject = jsCast<JSArrayBufferView*>(argument); if (thisObject->isNeutered()) return throwVMTypeError(exec, scope, ASCIILiteral("Underlying ArrayBuffer has been detached from the view")); return JSValue::encode(jsNumber(thisObject->length())); }
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); }
bool JSArrayBufferView::getOwnPropertySlot( JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot) { JSArrayBufferView* thisObject = jsCast<JSArrayBufferView*>(object); if (propertyName == exec->propertyNames().byteOffset) { slot.setValue(thisObject, DontDelete | ReadOnly, jsNumber(thisObject->byteOffset())); return true; } if (propertyName == exec->propertyNames().buffer) { slot.setValue( thisObject, DontDelete | ReadOnly, exec->vm().m_typedArrayController->toJS( exec, thisObject->globalObject(), thisObject->buffer())); return true; } return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot); }