void JSSynchronousGarbageCollectForDebugging(JSContextRef ctx) { if (!ctx) return; ExecState* exec = toJS(ctx); APIEntryShim entryShim(exec); exec->vm().heap.collectAllGarbage(); }
JSValue JSHTMLDocument::all(ExecState& state) const { // If "all" has been overwritten, return the overwritten value JSValue v = getDirect(state.vm(), Identifier::fromString(&state, "all")); if (v) return v; return toJS(&state, globalObject(), wrapped().all()); }
void JSSynchronousGarbageCollectForDebugging(JSContextRef ctx) { if (!ctx) return; ExecState* exec = toJS(ctx); JSLockHolder locker(exec); exec->vm().heap.collectAllGarbage(); }
JSValue JSWebKitSubtleCrypto::verify(ExecState& state) { VM& vm = state.vm(); auto scope = DECLARE_THROW_SCOPE(vm); if (state.argumentCount() < 4) return throwException(&state, scope, createNotEnoughArgumentsError(&state)); auto algorithm = createAlgorithmFromJSValue(state, state.uncheckedArgument(0)); ASSERT(scope.exception() || algorithm); if (!algorithm) return jsUndefined(); auto parameters = JSCryptoAlgorithmDictionary::createParametersForVerify(&state, algorithm->identifier(), state.uncheckedArgument(0)); ASSERT(scope.exception() || parameters); if (!parameters) return jsUndefined(); RefPtr<CryptoKey> key = JSCryptoKey::toWrapped(state.uncheckedArgument(1)); if (!key) return throwTypeError(&state, scope); if (!key->allows(CryptoKeyUsageVerify)) { wrapped().document()->addConsoleMessage(MessageSource::JS, MessageLevel::Error, ASCIILiteral("Key usages do not include 'verify'")); setDOMException(&state, NOT_SUPPORTED_ERR); return jsUndefined(); } CryptoOperationData signature; auto success = cryptoOperationDataFromJSValue(&state, state.uncheckedArgument(2), signature); ASSERT(scope.exception() || success); if (!success) return jsUndefined(); CryptoOperationData data; success = cryptoOperationDataFromJSValue(&state, state.uncheckedArgument(3), data); ASSERT(scope.exception() || success); if (!success) return jsUndefined(); RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow()); auto promise = wrapper->promise(); auto successCallback = [wrapper](bool result) mutable { wrapper->resolve(result); }; auto failureCallback = [wrapper]() mutable { wrapper->reject(nullptr); }; auto result = algorithm->verify(*parameters, *key, signature, data, WTFMove(successCallback), WTFMove(failureCallback)); if (result.hasException()) { propagateException(state, scope, result.releaseException()); return { }; } return promise; }
bool JSObjectIsConstructor(JSContextRef ctx, JSObjectRef object) { ExecState* exec = toJS(ctx); VM& vm = exec->vm(); JSLockHolder locker(vm); if (!object) return false; return toJS(object)->isConstructor(vm); }
JSContextGroupRef JSContextGetGroup(JSContextRef ctx) { if (!ctx) { ASSERT_NOT_REACHED(); return 0; } ExecState* exec = toJS(ctx); return toRef(&exec->vm()); }
template<> DictionaryImplName convertDictionary<DictionaryImplName>(ExecState& state, JSValue value) { VM& vm = state.vm(); auto throwScope = DECLARE_THROW_SCOPE(vm); bool isNullOrUndefined = value.isUndefinedOrNull(); auto* object = isNullOrUndefined ? nullptr : value.getObject(); if (UNLIKELY(!isNullOrUndefined && !object)) { throwTypeError(&state, throwScope); return { }; } DictionaryImplName result; JSValue boolMemberValue; if (isNullOrUndefined) boolMemberValue = jsUndefined(); else { boolMemberValue = object->get(&state, Identifier::fromString(&state, "boolMember")); RETURN_IF_EXCEPTION(throwScope, { }); } if (!boolMemberValue.isUndefined()) { result.boolMember = convert<IDLBoolean>(state, boolMemberValue); RETURN_IF_EXCEPTION(throwScope, { }); } JSValue callbackMemberValue; if (isNullOrUndefined) callbackMemberValue = jsUndefined(); else { callbackMemberValue = object->get(&state, Identifier::fromString(&state, "callbackMember")); RETURN_IF_EXCEPTION(throwScope, { }); } if (!callbackMemberValue.isUndefined()) { result.callbackMember = convert<IDLCallbackFunction<JSVoidCallback>>(state, callbackMemberValue, *jsCast<JSDOMGlobalObject*>(state.lexicalGlobalObject())); RETURN_IF_EXCEPTION(throwScope, { }); } JSValue enumMemberValue; if (isNullOrUndefined) enumMemberValue = jsUndefined(); else { enumMemberValue = object->get(&state, Identifier::fromString(&state, "enumMember")); RETURN_IF_EXCEPTION(throwScope, { }); } if (!enumMemberValue.isUndefined()) { result.enumMember = convert<IDLEnumeration<TestStandaloneDictionary::EnumInStandaloneDictionaryFile>>(state, enumMemberValue); RETURN_IF_EXCEPTION(throwScope, { }); } JSValue stringMemberValue; if (isNullOrUndefined) stringMemberValue = jsUndefined(); else { stringMemberValue = object->get(&state, Identifier::fromString(&state, "stringMember")); RETURN_IF_EXCEPTION(throwScope, { }); } if (!stringMemberValue.isUndefined()) { result.stringMember = convert<IDLDOMString>(state, stringMemberValue); RETURN_IF_EXCEPTION(throwScope, { }); } return result; }
void JSSynchronousEdenCollectForDebugging(JSContextRef ctx) { if (!ctx) return; ExecState* exec = toJS(ctx); JSLockHolder locker(exec); exec->vm().heap.collectSync(CollectionScope::Eden); }
JSValue JSWebKitSubtleCrypto::wrapKey(ExecState& state) { VM& vm = state.vm(); auto scope = DECLARE_THROW_SCOPE(vm); if (state.argumentCount() < 4) return throwException(&state, scope, createNotEnoughArgumentsError(&state)); auto keyFormat = cryptoKeyFormatFromJSValue(state, scope, state.uncheckedArgument(0)); RETURN_IF_EXCEPTION(scope, { }); RefPtr<CryptoKey> key = JSCryptoKey::toWrapped(vm, state.uncheckedArgument(1)); if (!key) return throwTypeError(&state, scope); RefPtr<CryptoKey> wrappingKey = JSCryptoKey::toWrapped(vm, state.uncheckedArgument(2)); if (!key) return throwTypeError(&state, scope); if (!wrappingKey->allows(CryptoKeyUsageWrapKey)) { wrapped().document()->addConsoleMessage(MessageSource::JS, MessageLevel::Error, ASCIILiteral("Key usages do not include 'wrapKey'")); throwNotSupportedError(state, scope); return jsUndefined(); } auto algorithm = createAlgorithmFromJSValue(state, scope, state.uncheckedArgument(3)); RETURN_IF_EXCEPTION(scope, { }); auto parameters = JSCryptoAlgorithmDictionary::createParametersForEncrypt(state, scope, algorithm->identifier(), state.uncheckedArgument(3)); RETURN_IF_EXCEPTION(scope, { }); RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow()); auto promise = wrapper->promise(); auto exportSuccessCallback = [keyFormat, algorithm, parameters, wrappingKey, wrapper](const Vector<uint8_t>& exportedKeyData) mutable { auto encryptSuccessCallback = [wrapper](const Vector<uint8_t>& encryptedData) mutable { fulfillPromiseWithArrayBuffer(wrapper.releaseNonNull(), encryptedData.data(), encryptedData.size()); }; auto encryptFailureCallback = [wrapper]() mutable { wrapper->reject(); // FIXME: This should reject with an Exception. }; auto result = algorithm->encryptForWrapKey(*parameters, *wrappingKey, std::make_pair(exportedKeyData.data(), exportedKeyData.size()), WTFMove(encryptSuccessCallback), WTFMove(encryptFailureCallback)); if (result.hasException()) { // FIXME: Report failure details to console, and possibly to calling script once there is a standardized way to pass errors to WebCrypto promise reject functions. wrapper->reject(); // FIXME: This should reject with an Exception. } }; auto exportFailureCallback = [wrapper]() mutable { wrapper->reject(); // FIXME: This should reject with an Exception. }; WebCore::exportKey(state, keyFormat, *key, WTFMove(exportSuccessCallback), WTFMove(exportFailureCallback)); return promise; }
inline MessageEvent::MessageEvent(ExecState& state, const AtomicString& type, Init&& initializer, IsTrusted isTrusted) : Event(type, initializer, isTrusted) , m_dataType(DataTypeScriptValue) , m_dataAsScriptValue(state.vm(), initializer.data) , m_origin(initializer.origin) , m_lastEventId(initializer.lastEventId) , m_source(WTFMove(initializer.source)) , m_ports(WTFMove(initializer.ports)) { }
void JSSynchronousGarbageCollectForDebugging(JSContextRef ctx) { if (!ctx) return; ExecState* exec = toJS(ctx); VM& vm = exec->vm(); JSLockHolder locker(vm); vm.heap.collectNow(Sync, CollectionScope::Full); }
void JSReportExtraMemoryCost(JSContextRef ctx, size_t size) { if (!ctx) { ASSERT_NOT_REACHED(); return; } ExecState* exec = toJS(ctx); APIEntryShim entryShim(exec); exec->vm().heap.reportExtraMemoryCost(size); }
JSGlobalContextRef JSGlobalContextRetain(JSGlobalContextRef ctx) { ExecState* exec = toJS(ctx); JSLockHolder locker(exec); VM& vm = exec->vm(); gcProtect(exec->vmEntryGlobalObject()); vm.ref(); return ctx; }
JSObjectRef JSObjectMakeFunctionWithCallback(JSContextRef ctx, JSStringRef name, JSObjectCallAsFunctionCallback callAsFunction) { if (!ctx) { ASSERT_NOT_REACHED(); return 0; } ExecState* exec = toJS(ctx); JSLockHolder locker(exec); return toRef(JSCallbackFunction::create(exec->vm(), exec->lexicalGlobalObject(), callAsFunction, name ? name->string() : ASCIILiteral("anonymous"))); }
void JSReportExtraMemoryCost(JSContextRef ctx, size_t size) { if (!ctx) { ASSERT_NOT_REACHED(); return; } ExecState* exec = toJS(ctx); JSLockHolder locker(exec); exec->vm().heap.reportExtraMemoryCost(size); }
JSGlobalContextRef JSGlobalContextRetain(JSGlobalContextRef ctx) { ExecState* exec = toJS(ctx); APIEntryShim entryShim(exec); VM& vm = exec->vm(); gcProtect(exec->dynamicGlobalObject()); vm.ref(); return ctx; }
inline JSValue DialogHandler::returnValue() const { JSDOMWindow* globalObject = toJSDOMWindow(m_frame.get(), normalWorld(m_exec->vm())); if (!globalObject) return jsUndefined(); Identifier identifier(m_exec, "returnValue"); PropertySlot slot(globalObject); if (!JSGlobalObject::getOwnPropertySlot(globalObject, m_exec, identifier, slot)) return jsUndefined(); return slot.getValue(m_exec, identifier); }
JSValue JSWebKitSubtleCrypto::generateKey(ExecState& state) { VM& vm = state.vm(); auto scope = DECLARE_THROW_SCOPE(vm); if (state.argumentCount() < 1) return throwException(&state, scope, createNotEnoughArgumentsError(&state)); auto algorithm = createAlgorithmFromJSValue(state, state.uncheckedArgument(0)); ASSERT(scope.exception() || algorithm); if (!algorithm) return jsUndefined(); auto parameters = JSCryptoAlgorithmDictionary::createParametersForGenerateKey(&state, algorithm->identifier(), state.uncheckedArgument(0)); ASSERT(scope.exception() || parameters); if (!parameters) return jsUndefined(); bool extractable = false; if (state.argumentCount() >= 2) { extractable = state.uncheckedArgument(1).toBoolean(&state); RETURN_IF_EXCEPTION(scope, JSValue()); } CryptoKeyUsageBitmap keyUsages = 0; if (state.argumentCount() >= 3) { auto success = cryptoKeyUsagesFromJSValue(state, state.argument(2), keyUsages); ASSERT(scope.exception() || success); if (!success) return jsUndefined(); } RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow()); auto promise = wrapper->promise(); auto successCallback = [wrapper](CryptoKey* key, CryptoKeyPair* keyPair) mutable { ASSERT(key || keyPair); ASSERT(!key || !keyPair); if (key) wrapper->resolve(key); else wrapper->resolve(keyPair); }; auto failureCallback = [wrapper]() mutable { wrapper->reject(nullptr); }; auto result = algorithm->generateKey(*parameters, extractable, keyUsages, WTFMove(successCallback), WTFMove(failureCallback), *scriptExecutionContextFromExecState(&state)); if (result.hasException()) { propagateException(state, scope, result.releaseException()); return { }; } return promise; }
static void importKey(ExecState& state, CryptoKeyFormat keyFormat, CryptoOperationData data, RefPtr<CryptoAlgorithm> algorithm, RefPtr<CryptoAlgorithmParametersDeprecated> parameters, bool extractable, CryptoKeyUsageBitmap keyUsages, CryptoAlgorithm::KeyCallback callback, CryptoAlgorithm::VoidCallback failureCallback) { VM& vm = state.vm(); auto scope = DECLARE_THROW_SCOPE(vm); std::unique_ptr<CryptoKeySerialization> keySerialization; switch (keyFormat) { case CryptoKeyFormat::Raw: keySerialization = CryptoKeySerializationRaw::create(data); break; case CryptoKeyFormat::JWK: { String jwkString = String::fromUTF8(data.first, data.second); if (jwkString.isNull()) { throwTypeError(&state, scope, ASCIILiteral("JWK JSON serialization is not valid UTF-8")); return; } keySerialization = std::make_unique<JSCryptoKeySerializationJWK>(&state, jwkString); RETURN_IF_EXCEPTION(scope, void()); break; } default: throwTypeError(&state, scope, ASCIILiteral("Unsupported key format for import")); return; } ASSERT(keySerialization); std::optional<CryptoAlgorithmPair> reconciledResult = keySerialization->reconcileAlgorithm(algorithm.get(), parameters.get()); if (!reconciledResult) { if (!scope.exception()) throwTypeError(&state, scope, ASCIILiteral("Algorithm specified in key is not compatible with one passed to importKey as argument")); return; } RETURN_IF_EXCEPTION(scope, void()); algorithm = reconciledResult->algorithm; parameters = reconciledResult->parameters; if (!algorithm) { throwTypeError(&state, scope, ASCIILiteral("Neither key nor function argument has crypto algorithm specified")); return; } ASSERT(parameters); keySerialization->reconcileExtractable(extractable); RETURN_IF_EXCEPTION(scope, void()); keySerialization->reconcileUsages(keyUsages); RETURN_IF_EXCEPTION(scope, void()); auto keyData = keySerialization->keyData(); RETURN_IF_EXCEPTION(scope, void()); propagateException(state, scope, algorithm->importKey(*parameters, *keyData, extractable, keyUsages, WTFMove(callback), WTFMove(failureCallback))); }
ExceptionOr<Ref<JSCustomXPathNSResolver>> JSCustomXPathNSResolver::create(ExecState& state, JSValue value) { if (value.isUndefinedOrNull()) return Exception { TypeError }; auto* resolverObject = value.getObject(); if (!resolverObject) return Exception { TYPE_MISMATCH_ERR }; return adoptRef(*new JSCustomXPathNSResolver(state.vm(), resolverObject, asJSDOMWindow(state.vmEntryGlobalObject()))); }
Deprecated::ScriptValue deserializeIDBValue(DOMRequestState* requestState, PassRefPtr<SerializedScriptValue> prpValue) { ExecState* exec = requestState->exec(); RefPtr<SerializedScriptValue> serializedValue = prpValue; JSValue result; if (serializedValue) result = serializedValue->deserialize(exec, exec->lexicalGlobalObject(), 0); else result = jsNull(); return Deprecated::ScriptValue(exec->vm(), result); }
void JSGlobalContextRelease(JSGlobalContextRef ctx) { ExecState* exec = toJS(ctx); JSLockHolder locker(exec); VM& vm = exec->vm(); bool protectCountIsZero = Heap::heap(exec->vmEntryGlobalObject())->unprotect(exec->vmEntryGlobalObject()); if (protectCountIsZero) vm.heap.reportAbandonedObjectGraph(); vm.deref(); }
bool JSObjectIsFunction(JSContextRef ctx, JSObjectRef object) { if (!object) return false; ExecState* exec = toJS(ctx); VM& vm = exec->vm(); JSLockHolder locker(vm); CallData callData; JSCell* cell = toJS(object); return cell->methodTable(vm)->getCallData(cell, callData) != CallType::None; }
static inline JSValue jsTestSerializedScriptValueInterfaceCachedReadonlyValueGetter(ExecState& state, JSTestSerializedScriptValueInterface& thisObject, ThrowScope& throwScope) { UNUSED_PARAM(throwScope); UNUSED_PARAM(state); if (JSValue cachedValue = thisObject.m_cachedReadonlyValue.get()) return cachedValue; auto& impl = thisObject.wrapped(); JSValue result = impl.cachedReadonlyValue() ? impl.cachedReadonlyValue()->deserialize(state, thisObject.globalObject()) : jsNull(); thisObject.m_cachedReadonlyValue.set(state.vm(), &thisObject, result); return result; }
RefPtr<ReadableJSStream> ReadableJSStream::create(ExecState& state, ScriptExecutionContext& scriptExecutionContext) { // FIXME: We should consider reducing the binding code herei (using Dictionary/regular binding constructor and/or improving the IDL generator). JSObject* jsSource; JSValue value = state.argument(0); if (value.isObject()) jsSource = value.getObject(); else if (!value.isUndefined()) { throwVMError(&state, createTypeError(&state, ASCIILiteral("First argument, if any, should be an object"))); return nullptr; } else jsSource = JSFinalObject::create(state.vm(), JSFinalObject::createStructure(state.vm(), state.callee()->globalObject(), jsNull(), 1)); double highWaterMark = 1; JSFunction* sizeFunction = nullptr; value = state.argument(1); if (value.isObject()) { JSObject& strategyObject = *value.getObject(); highWaterMark = normalizeHighWaterMark(state, strategyObject); if (state.hadException()) return nullptr; if (!(sizeFunction = jsDynamicCast<JSFunction*>(getPropertyFromObject(state, strategyObject, "size")))) { if (!state.hadException()) throwVMError(&state, createTypeError(&state, ASCIILiteral("size parameter should be a function"))); return nullptr; } } else if (!value.isUndefined()) { throwVMError(&state, createTypeError(&state, ASCIILiteral("Second argument, if any, should be an object"))); return nullptr; } RefPtr<ReadableJSStream> readableStream = adoptRef(*new ReadableJSStream(scriptExecutionContext, state, jsSource, highWaterMark, sizeFunction)); readableStream->doStart(state); if (state.hadException()) return nullptr; return readableStream; }
void JSReportExtraMemoryCost(JSContextRef ctx, size_t size) { if (!ctx) { ASSERT_NOT_REACHED(); return; } ExecState* exec = toJS(ctx); VM& vm = exec->vm(); JSLockHolder locker(vm); vm.heap.deprecatedReportExtraMemory(size); }
static JSValue deserializeIDBValueToJSValue(ExecState& state, JSC::JSGlobalObject& globalObject, const IDBValue& value) { // FIXME: I think it's peculiar to use undefined to mean "null data" and null to mean "empty data". // But I am not changing this at the moment because at least some callers are specifically checking isUndefined. if (!value.data().data()) return jsUndefined(); auto& data = *value.data().data(); if (data.isEmpty()) return jsNull(); auto serializedValue = SerializedScriptValue::createFromWireBytes(Vector<uint8_t>(data)); state.vm().apiLock().lock(); Vector<RefPtr<MessagePort>> messagePorts; JSValue result = serializedValue->deserialize(state, &globalObject, messagePorts, value.blobURLs(), value.sessionID(), value.blobFilePaths(), SerializationErrorMode::NonThrowing); state.vm().apiLock().unlock(); return result; }
JSValue JSWebGLRenderingContextBase::getExtension(ExecState& state) { if (state.argumentCount() < 1) return state.vm().throwException(&state, createNotEnoughArgumentsError(&state)); WebGLRenderingContextBase& context = wrapped(); const String name = state.uncheckedArgument(0).toString(&state)->value(&state); if (state.hadException()) return jsUndefined(); WebGLExtension* extension = context.getExtension(name); return toJS(&state, globalObject(), extension); }
JSValue iteratorMethod(ExecState& state, JSObject* object) { auto& vm = state.vm(); auto scope = DECLARE_THROW_SCOPE(vm); CallData callData; CallType callType; JSValue method = object->getMethod(&state, callData, callType, vm.propertyNames->iteratorSymbol, "Symbol.iterator property should be callable"_s); RETURN_IF_EXCEPTION(scope, jsUndefined()); return method; }
static void thenPromise(ExecState& state, JSPromise* deferredPromise, JSValue fullfilFunction, JSValue rejectFunction) { JSValue thenValue = deferredPromise->get(&state, state.vm().propertyNames->then); if (state.hadException()) return; MarkedArgumentBuffer arguments; arguments.append(fullfilFunction); arguments.append(rejectFunction); callFunction(state, thenValue, deferredPromise, arguments); }