Beispiel #1
0
void JSSynchronousGarbageCollectForDebugging(JSContextRef ctx)
{
    if (!ctx)
        return;

    ExecState* exec = toJS(ctx);
    APIEntryShim entryShim(exec);
    exec->vm().heap.collectAllGarbage();
}
Beispiel #2
0
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());
}
Beispiel #3
0
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);
}
Beispiel #6
0
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;
}
Beispiel #8
0
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;
}
Beispiel #10
0
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))
{
}
Beispiel #11
0
void JSSynchronousGarbageCollectForDebugging(JSContextRef ctx)
{
    if (!ctx)
        return;

    ExecState* exec = toJS(ctx);
    VM& vm = exec->vm();
    JSLockHolder locker(vm);
    vm.heap.collectNow(Sync, CollectionScope::Full);
}
Beispiel #12
0
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;
}
Beispiel #14
0
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")));
}
Beispiel #15
0
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);
}
Beispiel #16
0
JSGlobalContextRef JSGlobalContextRetain(JSGlobalContextRef ctx)
{
    ExecState* exec = toJS(ctx);
    APIEntryShim entryShim(exec);

    VM& vm = exec->vm();
    gcProtect(exec->dynamicGlobalObject());
    vm.ref();
    return ctx;
}
Beispiel #17
0
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)));
}
Beispiel #20
0
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;
}
Beispiel #25
0
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;
}
Beispiel #26
0
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;
}
Beispiel #30
0
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);
}