Пример #1
0
void JSModuleNamespaceObject::put(JSCell*, ExecState* exec, PropertyName, JSValue, PutPropertySlot& slot)
{
    // http://www.ecma-international.org/ecma-262/6.0/#sec-module-namespace-exotic-objects-set-p-v-receiver
    if (slot.isStrictMode())
        throwTypeError(exec, ASCIILiteral(StrictModeReadonlyPropertyWriteError));
}
static JSC::JSValue dataFunctionf(DataFunctionToCall f, JSC::ExecState* exec, WebGLRenderingContextBase& context)
{
    if (exec->argumentCount() != 2)
        return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
    
    WebGLUniformLocation* location = 0;
    long index = -1;
    
    if (functionForUniform(f)) {
        location = JSWebGLUniformLocation::toWrapped(exec->uncheckedArgument(0));
        if (!location && !exec->uncheckedArgument(0).isUndefinedOrNull())
            return throwTypeError(exec);
    } else
        index = exec->uncheckedArgument(0).toInt32(exec);
    
    if (exec->hadException())
        return jsUndefined();
    
    RefPtr<Float32Array> webGLArray = toFloat32Array(exec->uncheckedArgument(1));
    if (exec->hadException())    
        return jsUndefined();
    
    ExceptionCode ec = 0;
    if (webGLArray) {
        switch (f) {
        case f_uniform1v:
            context.uniform1fv(location, webGLArray.get(), ec);
            break;
        case f_uniform2v:
            context.uniform2fv(location, webGLArray.get(), ec);
            break;
        case f_uniform3v:
            context.uniform3fv(location, webGLArray.get(), ec);
            break;
        case f_uniform4v:
            context.uniform4fv(location, webGLArray.get(), ec);
            break;
        case f_vertexAttrib1v:
            context.vertexAttrib1fv(index, webGLArray.get());
            break;
        case f_vertexAttrib2v:
            context.vertexAttrib2fv(index, webGLArray.get());
            break;
        case f_vertexAttrib3v:
            context.vertexAttrib3fv(index, webGLArray.get());
            break;
        case f_vertexAttrib4v:
            context.vertexAttrib4fv(index, webGLArray.get());
            break;
        }
        
        setDOMException(exec, ec);
        return jsUndefined();
    }
    
    Vector<float, 64> array;
    if (!toVector(exec, exec->uncheckedArgument(1), array))
        return throwTypeError(exec);
    
    switch (f) {
    case f_uniform1v:
        context.uniform1fv(location, array.data(), array.size(), ec);
        break;
    case f_uniform2v:
        context.uniform2fv(location, array.data(), array.size(), ec);
        break;
    case f_uniform3v:
        context.uniform3fv(location, array.data(), array.size(), ec);
        break;
    case f_uniform4v:
        context.uniform4fv(location, array.data(), array.size(), ec);
        break;
    case f_vertexAttrib1v:
        context.vertexAttrib1fv(index, array.data(), array.size());
        break;
    case f_vertexAttrib2v:
        context.vertexAttrib2fv(index, array.data(), array.size());
        break;
    case f_vertexAttrib3v:
        context.vertexAttrib3fv(index, array.data(), array.size());
        break;
    case f_vertexAttrib4v:
        context.vertexAttrib4fv(index, array.data(), array.size());
        break;
    }
    
    setDOMException(exec, ec);
    return jsUndefined();
}
Пример #3
0
JSValue JSSubtleCrypto::wrapKey(ExecState* exec)
{
    if (exec->argumentCount() < 4)
        return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));

    CryptoKeyFormat keyFormat;
    if (!cryptoKeyFormatFromJSValue(exec, exec->argument(0), keyFormat)) {
        ASSERT(exec->hadException());
        return jsUndefined();
    }

    RefPtr<CryptoKey> key = JSCryptoKey::toWrapped(exec->uncheckedArgument(1));
    if (!key)
        return throwTypeError(exec);

    RefPtr<CryptoKey> wrappingKey = JSCryptoKey::toWrapped(exec->uncheckedArgument(2));
    if (!key)
        return throwTypeError(exec);

    if (!wrappingKey->allows(CryptoKeyUsageWrapKey)) {
        m_impl->document()->addConsoleMessage(MessageSource::JS, MessageLevel::Error, ASCIILiteral("Key usages do not include 'wrapKey'"));
        setDOMException(exec, NOT_SUPPORTED_ERR);
        return jsUndefined();
    }

    auto algorithm = createAlgorithmFromJSValue(exec, exec->uncheckedArgument(3));
    if (!algorithm) {
        ASSERT(exec->hadException());
        return jsUndefined();
    }

    auto parameters = JSCryptoAlgorithmDictionary::createParametersForEncrypt(exec, algorithm->identifier(), exec->uncheckedArgument(3));
    if (!parameters) {
        ASSERT(exec->hadException());
        return jsUndefined();
    }

    JSPromiseDeferred* promiseDeferred = JSPromiseDeferred::create(exec, globalObject());
    DeferredWrapper wrapper(exec, globalObject(), promiseDeferred);

    CryptoAlgorithm* algorithmPtr = algorithm.release();
    CryptoAlgorithmParameters* parametersPtr = parameters.release();

    auto exportSuccessCallback = [keyFormat, algorithmPtr, parametersPtr, wrappingKey, wrapper](const Vector<uint8_t>& exportedKeyData) mutable {
        auto encryptSuccessCallback = [wrapper, algorithmPtr, parametersPtr](const Vector<uint8_t>& encryptedData) mutable {
            delete algorithmPtr;
            delete parametersPtr;
            wrapper.resolve(encryptedData);
        };
        auto encryptFailureCallback = [wrapper, algorithmPtr, parametersPtr]() mutable {
            delete algorithmPtr;
            delete parametersPtr;
            wrapper.reject(nullptr);
        };
        ExceptionCode ec = 0;
        algorithmPtr->encryptForWrapKey(*parametersPtr, *wrappingKey, std::make_pair(exportedKeyData.data(), exportedKeyData.size()), WTF::move(encryptSuccessCallback), WTF::move(encryptFailureCallback), ec);
        if (ec) {
            // 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.
            encryptFailureCallback();
        }
    };

    auto exportFailureCallback = [wrapper, algorithmPtr, parametersPtr]() mutable {
        delete algorithmPtr;
        delete parametersPtr;
        wrapper.reject(nullptr);
    };

    ExceptionCode ec = 0;
    WebCore::exportKey(exec, keyFormat, *key, WTF::move(exportSuccessCallback), WTF::move(exportFailureCallback));
    if (ec) {
        delete algorithmPtr;
        delete parametersPtr;
        setDOMException(exec, ec);
        return jsUndefined();
    }

    return promiseDeferred->promise();
}
Пример #4
0
void JSCryptoKeySerializationJWK::addJWKAlgorithmToJSON(ExecState* exec, JSObject* json, const CryptoKey& key)
{
    String jwkAlgorithm;
    switch (key.algorithmIdentifier()) {
    case CryptoAlgorithmIdentifier::HMAC:
        switch (toCryptoKeyHMAC(key).hashAlgorithmIdentifier()) {
        case CryptoAlgorithmIdentifier::SHA_256:
            if (toCryptoKeyHMAC(key).key().size() * 8 >= 256)
                jwkAlgorithm = "HS256";
            break;
        case CryptoAlgorithmIdentifier::SHA_384:
            if (toCryptoKeyHMAC(key).key().size() * 8 >= 384)
                jwkAlgorithm = "HS384";
            break;
        case CryptoAlgorithmIdentifier::SHA_512:
            if (toCryptoKeyHMAC(key).key().size() * 8 >= 512)
                jwkAlgorithm = "HS512";
            break;
        default:
            break;
        }
        break;
    case CryptoAlgorithmIdentifier::AES_CBC:
        switch (toCryptoKeyAES(key).key().size() * 8) {
        case 128:
            jwkAlgorithm = "A128CBC";
            break;
        case 192:
            jwkAlgorithm = "A192CBC";
            break;
        case 256:
            jwkAlgorithm = "A256CBC";
            break;
        }
        break;
    case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5: {
        const CryptoKeyRSA& rsaKey = toCryptoKeyRSA(key);
        CryptoAlgorithmIdentifier hash;
        if (!rsaKey.isRestrictedToHash(hash))
            break;
        if (rsaKey.keySizeInBits() < 2048)
            break;
        switch (hash) {
        case CryptoAlgorithmIdentifier::SHA_256:
            jwkAlgorithm = "RS256";
            break;
        case CryptoAlgorithmIdentifier::SHA_384:
            jwkAlgorithm = "RS384";
            break;
        case CryptoAlgorithmIdentifier::SHA_512:
            jwkAlgorithm = "RS512";
            break;
        default:
            break;
        }
        break;
    }
    default:
        break;
    }

    if (jwkAlgorithm.isNull()) {
        // The spec doesn't currently tell whether export should fail, or just skip "alg" (which is an optional key in JWK).
        // Perhaps this should depend on whether the key is extractable?
        throwTypeError(exec, "Key algorithm and size do not map to any JWK algorithm identifier");
        return;
    }

    addToJSON(exec, json, "alg", jwkAlgorithm);
}
Пример #5
0
JSValue IntlNumberFormat::formatToParts(ExecState& exec, double value)
{
    VM& vm = exec.vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    // FormatNumberToParts (ECMA-402)
    // https://tc39.github.io/ecma402/#sec-formatnumbertoparts
    // https://tc39.github.io/ecma402/#sec-partitionnumberpattern

    if (!m_initializedNumberFormat)
        return throwTypeError(&exec, scope, "Intl.NumberFormat.prototype.formatToParts called on value that's not an object initialized as a NumberFormat"_s);

    UErrorCode status = U_ZERO_ERROR;
    auto fieldItr = std::unique_ptr<UFieldPositionIterator, UFieldPositionIteratorDeleter>(ufieldpositer_open(&status));
    if (U_FAILURE(status))
        return throwTypeError(&exec, scope, "failed to open field position iterator"_s);

    status = U_ZERO_ERROR;
    Vector<UChar, 32> result(32);
    auto resultLength = unum_formatDoubleForFields(m_numberFormat.get(), value, result.data(), result.size(), fieldItr.get(), &status);
    if (status == U_BUFFER_OVERFLOW_ERROR) {
        status = U_ZERO_ERROR;
        result.grow(resultLength);
        unum_formatDoubleForFields(m_numberFormat.get(), value, result.data(), resultLength, fieldItr.get(), &status);
    }
    if (U_FAILURE(status))
        return throwTypeError(&exec, scope, "failed to format a number."_s);

    int32_t literalFieldType = -1;
    auto literalField = IntlNumberFormatField(literalFieldType, resultLength);
    Vector<IntlNumberFormatField> fields(resultLength, literalField);
    int32_t beginIndex = 0;
    int32_t endIndex = 0;
    auto fieldType = ufieldpositer_next(fieldItr.get(), &beginIndex, &endIndex);
    while (fieldType >= 0) {
        auto size = endIndex - beginIndex;
        for (auto i = beginIndex; i < endIndex; ++i) {
            // Only override previous value if new value is more specific.
            if (fields[i].size >= size)
                fields[i] = IntlNumberFormatField(fieldType, size);
        }
        fieldType = ufieldpositer_next(fieldItr.get(), &beginIndex, &endIndex);
    }

    JSGlobalObject* globalObject = exec.jsCallee()->globalObject(vm);
    JSArray* parts = JSArray::tryCreate(vm, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous), 0);
    if (!parts)
        return throwOutOfMemoryError(&exec, scope);
    unsigned index = 0;

    auto resultString = String(result.data(), resultLength);
    auto typePropertyName = Identifier::fromString(&vm, "type");
    auto literalString = jsString(&exec, "literal"_s);

    int32_t currentIndex = 0;
    while (currentIndex < resultLength) {
        auto startIndex = currentIndex;
        auto fieldType = fields[currentIndex].type;
        while (currentIndex < resultLength && fields[currentIndex].type == fieldType)
            ++currentIndex;
        auto partType = fieldType == literalFieldType ? literalString : jsString(&exec, partTypeString(UNumberFormatFields(fieldType), value));
        auto partValue = jsSubstring(&vm, resultString, startIndex, currentIndex - startIndex);
        JSObject* part = constructEmptyObject(&exec);
        part->putDirect(vm, typePropertyName, partType);
        part->putDirect(vm, vm.propertyNames->value, partValue);
        parts->putDirectIndex(&exec, index++, part);
        RETURN_IF_EXCEPTION(scope, { });
    }

    return parts;
}
Пример #6
0
Handle<Value>
DNSServiceResolve(Arguments const& args) {
    HandleScope scope;

    if (argumentCountMismatch(args, 8)) {
        return throwArgumentCountMismatchException(args, 8);
    }

    if ( ! ServiceRef::HasInstance(args[0])) {
        return throwTypeError("argument 1 must be a DNSServiceRef (sdRef)");
    }
    ServiceRef * serviceRef = ObjectWrap::Unwrap<ServiceRef>(args[0]->ToObject());
    if (serviceRef->IsInitialized()) {
        return throwError("DNSServiceRef is already initialized");
    }

    if ( ! args[1]->IsInt32()) {
        return throwError("argument 2 must be an integer (DNSServiceFlags)");
    }
    DNSServiceFlags flags = args[1]->ToInteger()->Int32Value();

    if ( ! args[2]->IsInt32()) {
        return throwTypeError("argument 3 must be an integer (interfaceIndex)");
    }
    uint32_t interfaceIndex = args[2]->ToInteger()->Int32Value();

    if ( ! args[3]->IsString()) {
        return throwTypeError("argument 4 must be a string (name)");
    }
    String::Utf8Value name(args[3]->ToString());

    if ( ! args[4]->IsString()) {
        return throwTypeError("argument 5 must be a string (service type)");
    }
    String::Utf8Value serviceType(args[4]->ToString());

    if ( ! args[5]->IsString()) {
        return throwTypeError("argument 6 must be a string (domain)");
    }
    String::Utf8Value domain(args[5]->ToString());

    if ( ! args[6]->IsFunction()) {
        return throwTypeError("argument 7 must be a function (callBack)");
    }
    serviceRef->SetCallback(Local<Function>::Cast(args[6]));

    if ( ! args[7]->IsNull() && ! args[7]->IsUndefined()) {
        serviceRef->SetContext(args[7]);
    }

    DNSServiceErrorType error = DNSServiceResolve( & serviceRef->GetServiceRef(),
            flags, interfaceIndex, *name, *serviceType, *domain, OnResolve, serviceRef);

    if (error != kDNSServiceErr_NoError) {
        return throwMdnsError("DNSServiceResolve()", error);
    }
    if ( ! serviceRef->SetSocketFlags()) {
        return throwError("Failed to set socket flags (O_NONBLOCK, FD_CLOEXEC)");
    }

    return Undefined();
}
Пример #7
0
bool JSCryptoKeySerializationJWK::reconcileAlgorithm(std::unique_ptr<CryptoAlgorithm>& suggestedAlgorithm, std::unique_ptr<CryptoAlgorithmParameters>& suggestedParameters) const
{
    if (!getStringFromJSON(m_exec, m_json.get(), "alg", m_jwkAlgorithmName)) {
        // Algorithm is optional in JWK.
        return true;
    }

    std::unique_ptr<CryptoAlgorithm> algorithm;
    std::unique_ptr<CryptoAlgorithmParameters> parameters;
    if (m_jwkAlgorithmName == "HS256") {
        algorithm = CryptoAlgorithmRegistry::shared().create(CryptoAlgorithmIdentifier::HMAC);
        parameters = createHMACParameters(CryptoAlgorithmIdentifier::SHA_256);
    } else if (m_jwkAlgorithmName == "HS384") {
        algorithm = CryptoAlgorithmRegistry::shared().create(CryptoAlgorithmIdentifier::HMAC);
        parameters = createHMACParameters(CryptoAlgorithmIdentifier::SHA_384);
    } else if (m_jwkAlgorithmName == "HS512") {
        algorithm = CryptoAlgorithmRegistry::shared().create(CryptoAlgorithmIdentifier::HMAC);
        parameters = createHMACParameters(CryptoAlgorithmIdentifier::SHA_512);
    } else if (m_jwkAlgorithmName == "RS256") {
        algorithm = CryptoAlgorithmRegistry::shared().create(CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5);
        parameters = createRSASSAKeyParameters(CryptoAlgorithmIdentifier::SHA_256);
    } else if (m_jwkAlgorithmName == "RS384") {
        algorithm = CryptoAlgorithmRegistry::shared().create(CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5);
        parameters = createRSASSAKeyParameters(CryptoAlgorithmIdentifier::SHA_384);
    } else if (m_jwkAlgorithmName == "RS512") {
        algorithm = CryptoAlgorithmRegistry::shared().create(CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5);
        parameters = createRSASSAKeyParameters(CryptoAlgorithmIdentifier::SHA_512);
    } else if (m_jwkAlgorithmName == "A128CBC") {
        algorithm = CryptoAlgorithmRegistry::shared().create(CryptoAlgorithmIdentifier::AES_CBC);
        parameters = std::make_unique<CryptoAlgorithmParameters>();
    } else if (m_jwkAlgorithmName == "A192CBC") {
        algorithm = CryptoAlgorithmRegistry::shared().create(CryptoAlgorithmIdentifier::AES_CBC);
        parameters = std::make_unique<CryptoAlgorithmParameters>();
    } else if (m_jwkAlgorithmName == "A256CBC") {
        algorithm = CryptoAlgorithmRegistry::shared().create(CryptoAlgorithmIdentifier::AES_CBC);
        parameters = std::make_unique<CryptoAlgorithmParameters>();
    } else {
        throwTypeError(m_exec, "Unsupported JWK algorithm " + m_jwkAlgorithmName);
        return false;
    }

    if (!suggestedAlgorithm) {
        suggestedAlgorithm = std::move(algorithm);
        suggestedParameters =  std::move(parameters);
        return true;
    }

    if (!algorithm)
        return true;

    if (algorithm->identifier() != suggestedAlgorithm->identifier())
        return false;

    if (algorithm->identifier() == CryptoAlgorithmIdentifier::HMAC)
        return toCryptoAlgorithmHmacParams(*parameters).hash == toCryptoAlgorithmHmacParams(*suggestedParameters).hash;
    if (algorithm->identifier() == CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5) {
        CryptoAlgorithmRsaSsaKeyParams& rsaSSAParameters = toCryptoAlgorithmRsaSsaKeyParams(*parameters);
        CryptoAlgorithmRsaSsaKeyParams& suggestedRSASSAParameters = toCryptoAlgorithmRsaSsaKeyParams(*suggestedParameters);
        ASSERT(rsaSSAParameters.hasHash);
        if (suggestedRSASSAParameters.hasHash)
            return suggestedRSASSAParameters.hash == rsaSSAParameters.hash;
        suggestedRSASSAParameters.hasHash = true;
        suggestedRSASSAParameters.hash = rsaSSAParameters.hash;
    }

    // Other algorithms don't have parameters.
    return true;
}
Пример #8
0
double Symbol::toNumber(ExecState* exec) const
{
    throwTypeError(exec, "Cannot convert a symbol to a number");
    return 0.0;
}
Пример #9
0
static void performPromiseRaceLoop(ExecState* exec, JSValue iterator, JSPromiseDeferred* deferred, JSValue C)
{
    // 6. Repeat
    do {
        // i. Let 'next' be the result of calling IteratorStep(iterator).
        JSValue next = iteratorStep(exec, iterator);

        // ii. RejectIfAbrupt(next, deferred).
        if (exec->hadException())
            return;

        // iii. If 'next' is false, return deferred.[[Promise]].
        if (next.isFalse())
            return;

        // iv. Let 'nextValue' be the result of calling IteratorValue(next).
        // v. RejectIfAbrupt(nextValue, deferred).
        JSValue nextValue = iteratorValue(exec, next);
        if (exec->hadException())
            return;

        // vi. Let 'nextPromise' be the result of calling Invoke(C, "resolve", (nextValue)).
        JSValue resolveFunction = C.get(exec, exec->vm().propertyNames->resolve);
        if (exec->hadException())
            return;

        CallData resolveFunctionCallData;
        CallType resolveFunctionCallType = getCallData(resolveFunction, resolveFunctionCallData);
        if (resolveFunctionCallType == CallTypeNone) {
            throwTypeError(exec);
            return;
        }

        MarkedArgumentBuffer resolveFunctionArguments;
        resolveFunctionArguments.append(nextValue);
        JSValue nextPromise = call(exec, resolveFunction, resolveFunctionCallType, resolveFunctionCallData, C, resolveFunctionArguments);

        // vii. RejectIfAbrupt(nextPromise, deferred).
        if (exec->hadException())
            return;

        // viii. Let 'result' be the result of calling Invoke(nextPromise, "then", (deferred.[[Resolve]], deferred.[[Reject]])).
        JSValue thenFunction = nextPromise.get(exec, exec->vm().propertyNames->then);
        if (exec->hadException())
            return;

        CallData thenFunctionCallData;
        CallType thenFunctionCallType = getCallData(thenFunction, thenFunctionCallData);
        if (thenFunctionCallType == CallTypeNone) {
            throwTypeError(exec);
            return;
        }

        MarkedArgumentBuffer thenFunctionArguments;
        thenFunctionArguments.append(deferred->resolve());
        thenFunctionArguments.append(deferred->reject());

        call(exec, thenFunction, thenFunctionCallType, thenFunctionCallData, nextPromise, thenFunctionArguments);

        // ix. RejectIfAbrupt(result, deferred).
        if (exec->hadException())
            return;
    } while (true);
}
Пример #10
0
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));

    CryptoKeyFormat keyFormat;
    auto success = cryptoKeyFormatFromJSValue(state, state.argument(0), keyFormat);
    ASSERT(scope.exception() || success);
    if (!success)
        return jsUndefined();

    RefPtr<CryptoKey> key = JSCryptoKey::toWrapped(state.uncheckedArgument(1));
    if (!key)
        return throwTypeError(&state, scope);

    RefPtr<CryptoKey> wrappingKey = JSCryptoKey::toWrapped(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'"));
        setDOMException(&state, NOT_SUPPORTED_ERR);
        return jsUndefined();
    }

    auto algorithm = createAlgorithmFromJSValue(state, state.uncheckedArgument(3));
    ASSERT(scope.exception() || algorithm);
    if (!algorithm)
        return jsUndefined();

    auto parameters = JSCryptoAlgorithmDictionary::createParametersForEncrypt(&state, algorithm->identifier(), state.uncheckedArgument(3));
    ASSERT(scope.exception() || parameters);
    if (!parameters)
        return jsUndefined();

    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(nullptr);
        };
        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(nullptr);
        }
    };

    auto exportFailureCallback = [wrapper]() mutable {
        wrapper->reject(nullptr);
    };

    WebCore::exportKey(state, keyFormat, *key, WTFMove(exportSuccessCallback), WTFMove(exportFailureCallback));

    return promise;
}
static void addJWKAlgorithmToJSON(ExecState* exec, JSObject* json, const CryptoKey& key)
{
    String jwkAlgorithm;
    switch (key.algorithmIdentifier()) {
    case CryptoAlgorithmIdentifier::HMAC:
        switch (toCryptoKeyHMAC(key).hashAlgorithmIdentifier()) {
        case CryptoAlgorithmIdentifier::SHA_256:
            if (toCryptoKeyHMAC(key).key().size() * 8 >= 256)
                jwkAlgorithm = "HS256";
            break;
        case CryptoAlgorithmIdentifier::SHA_384:
            if (toCryptoKeyHMAC(key).key().size() * 8 >= 384)
                jwkAlgorithm = "HS384";
            break;
        case CryptoAlgorithmIdentifier::SHA_512:
            if (toCryptoKeyHMAC(key).key().size() * 8 >= 512)
                jwkAlgorithm = "HS512";
            break;
        default:
            break;
        }
        break;
    case CryptoAlgorithmIdentifier::AES_CBC:
        switch (toCryptoKeyAES(key).key().size() * 8) {
        case 128:
            jwkAlgorithm = "A128CBC";
            break;
        case 192:
            jwkAlgorithm = "A192CBC";
            break;
        case 256:
            jwkAlgorithm = "A256CBC";
            break;
        }
        break;
    case CryptoAlgorithmIdentifier::AES_KW:
        switch (toCryptoKeyAES(key).key().size() * 8) {
        case 128:
            jwkAlgorithm = "A128KW";
            break;
        case 192:
            jwkAlgorithm = "A192KW";
            break;
        case 256:
            jwkAlgorithm = "A256KW";
            break;
        }
        break;
    case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5: {
        const CryptoKeyRSA& rsaKey = toCryptoKeyRSA(key);
        CryptoAlgorithmIdentifier hash;
        if (!rsaKey.isRestrictedToHash(hash))
            break;
        if (rsaKey.keySizeInBits() < 2048)
            break;
        switch (hash) {
        case CryptoAlgorithmIdentifier::SHA_256:
            jwkAlgorithm = "RS256";
            break;
        case CryptoAlgorithmIdentifier::SHA_384:
            jwkAlgorithm = "RS384";
            break;
        case CryptoAlgorithmIdentifier::SHA_512:
            jwkAlgorithm = "RS512";
            break;
        default:
            break;
        }
        break;
    }
    case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5: {
        const CryptoKeyRSA& rsaKey = toCryptoKeyRSA(key);
        if (rsaKey.keySizeInBits() < 2048)
            break;
        jwkAlgorithm = "RSA1_5";
        break;
    }
    case CryptoAlgorithmIdentifier::RSA_OAEP: {
        const CryptoKeyRSA& rsaKey = toCryptoKeyRSA(key);
        CryptoAlgorithmIdentifier hash;
        // WebCrypto RSA-OAEP keys are not tied to any particular hash, unless previously imported from JWK, which only supports SHA-1.
        if (rsaKey.isRestrictedToHash(hash) && hash != CryptoAlgorithmIdentifier::SHA_1)
            break;
        if (rsaKey.keySizeInBits() < 2048)
            break;
        jwkAlgorithm = "RSA-OAEP";
        break;
    }
    default:
        break;
    }

    if (jwkAlgorithm.isNull()) {
        // The spec doesn't currently tell whether export should fail, or just skip "alg" (which is an optional key in JWK).
        throwTypeError(exec, "Key algorithm and size do not map to any JWK algorithm identifier");
        return;
    }

    addToJSON(exec, json, "alg", jwkAlgorithm);
}
Handle<Value>
DNSServiceRegister(Arguments const& args) {
    HandleScope scope;
    if (argumentCountMismatch(args, 11)) {
        return throwArgumentCountMismatchException(args, 11);
    }

    if ( ! ServiceRef::HasInstance(args[0])) {
        return throwTypeError("argument 1 must be a DNSServiceRef (sdRef)");
    }
    ServiceRef * serviceRef = ObjectWrap::Unwrap<ServiceRef>(args[0]->ToObject());
    if (serviceRef->IsInitialized()) {
        return throwError("DNSServiceRef is already initialized");
    }

    if ( ! args[1]->IsInt32()) {
        return throwError("argument 2 must be an integer (DNSServiceFlags)");
    }
    DNSServiceFlags flags = args[1]->ToInteger()->Int32Value();

    if ( ! args[2]->IsInt32()) {
        return throwTypeError("argument 3 must be an integer (interfaceIndex)");
    }
    uint32_t interfaceIndex = args[2]->ToInteger()->Int32Value();

    bool has_name = false;
    if ( ! args[3]->IsNull() && ! args[3]->IsUndefined()) {
        if ( ! args[3]->IsString()) {
            return throwTypeError("argument 4 must be a string (name)");
        }
        has_name = true;
    }
    String::Utf8Value name(args[3]);

    if ( ! args[4]->IsString()) {
        return throwTypeError("argument 5 must be a string (service type)");
    }
    String::Utf8Value serviceType(args[4]->ToString());

    bool has_domain = false;
    if ( ! args[5]->IsNull() && ! args[5]->IsUndefined()) {
        if ( ! args[5]->IsString()) {
            return throwTypeError("argument 6 must be a string (domain)");
        }
        has_domain = true;
    }
    String::Utf8Value domain(args[5]);

    bool has_host = false;
    if ( ! args[6]->IsNull() && ! args[6]->IsUndefined()) {
        if ( ! args[6]->IsString()) {
            return throwTypeError("argument 7 must be a string (host)");
        }
        has_host = true;
    }
    String::Utf8Value host(args[6]);

    if ( ! args[7]->IsInt32()) {
        return throwTypeError("argument 8 must be an integer (port)");
    }
    int raw_port = args[7]->ToInteger()->Int32Value();
    if (raw_port > std::numeric_limits<uint16_t>::max() || raw_port < 0) {
        return throwError("argument 8: port number is out of bounds.");
    }
    uint16_t port = static_cast<uint16_t>(raw_port);

    uint16_t txtLen(0);
    const void * txtRecord(NULL);
    if ( ! args[8]->IsNull() && ! args[8]->IsUndefined()) {
        if (Buffer::HasInstance(args[8])) {
            Local<Object> bufferObject = args[8]->ToObject();
            txtRecord = Buffer::Data(bufferObject);
            txtLen = Buffer::Length(bufferObject);
        } else if (TxtRecordRef::HasInstance(args[8])) {
            TxtRecordRef * ref = ObjectWrap::Unwrap<TxtRecordRef>(args[8]->ToObject());
            txtLen = TXTRecordGetLength( & ref->GetTxtRecordRef());
            txtRecord = TXTRecordGetBytesPtr( & ref->GetTxtRecordRef());
        } else {
            return throwTypeError("argument 9 must be a buffer or a dns_sd.TXTRecordRef");
        }
    }

    if ( ! args[9]->IsNull() && ! args[9]->IsUndefined()) {
        if ( ! args[9]->IsFunction()) {
            return throwTypeError("argument 10 must be a function (callBack)");
        }
        serviceRef->SetCallback(Local<Function>::Cast(args[9]));
    }

    if ( ! args[10]->IsNull() && ! args[10]->IsUndefined()) {
        serviceRef->SetContext(args[10]);
    }

    // eleven arguments ... srsly?
    DNSServiceErrorType error = DNSServiceRegister(
                                    & serviceRef->GetServiceRef(),
                                    flags,
                                    interfaceIndex,
                                    has_name ? * name : NULL,
                                    *serviceType,
                                    has_domain ? * domain : NULL,
                                    has_host ? * host : NULL,
                                    htons(port),
                                    txtLen,
                                    txtRecord,
                                    args[9]->IsFunction() ? OnServiceRegistered : NULL,
                                    serviceRef);
    if (error != kDNSServiceErr_NoError) {
        return throwMdnsError("DNSServiceRegister()", error);
    }
    if ( ! serviceRef->SetSocketFlags()) {
        return throwError("Failed to set socket flags (O_NONBLOCK, FD_CLOEXEC)");
    }
    return Undefined();
}
Пример #13
0
 static EncodedTiValue JSC_HOST_CALL callThrowTypeError(TiExcState* exec)
 {
     throwTypeError(exec, static_cast<StrictModeTypeErrorFunction*>(exec->callee())->m_message);
     return TiValue::encode(jsNull());
 }
Пример #14
0
void JSModuleNamespaceObject::putByIndex(JSCell*, ExecState* exec, unsigned, JSValue, bool shouldThrow)
{
    if (shouldThrow)
        throwTypeError(exec, ASCIILiteral(StrictModeReadonlyPropertyWriteError));
}
Пример #15
0
void IntlDateTimeFormat::initializeDateTimeFormat(ExecState& exec, JSValue locales, JSValue originalOptions)
{
    VM& vm = exec.vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    // 12.1.1 InitializeDateTimeFormat (dateTimeFormat, locales, options) (ECMA-402 2.0)
    // 1. If dateTimeFormat.[[initializedIntlObject]] is true, throw a TypeError exception.
    // 2. Set dateTimeFormat.[[initializedIntlObject]] to true.

    // 3. Let requestedLocales be CanonicalizeLocaleList(locales).
    Vector<String> requestedLocales = canonicalizeLocaleList(exec, locales);
    // 4. ReturnIfAbrupt(requestedLocales),
    RETURN_IF_EXCEPTION(scope, void());

    // 5. Let options be ToDateTimeOptions(options, "any", "date").
    JSObject* options = toDateTimeOptionsAnyDate(exec, originalOptions);
    // 6. ReturnIfAbrupt(options).
    RETURN_IF_EXCEPTION(scope, void());

    // 7. Let opt be a new Record.
    HashMap<String, String> localeOpt;

    // 8. Let matcher be GetOption(options, "localeMatcher", "string", «"lookup", "best fit"», "best fit").
    String localeMatcher = intlStringOption(exec, options, vm.propertyNames->localeMatcher, { "lookup", "best fit" }, "localeMatcher must be either \"lookup\" or \"best fit\"", "best fit");
    // 9. ReturnIfAbrupt(matcher).
    RETURN_IF_EXCEPTION(scope, void());
    // 10. Set opt.[[localeMatcher]] to matcher.
    localeOpt.add(vm.propertyNames->localeMatcher.string(), localeMatcher);

    // 11. Let localeData be the value of %DateTimeFormat%.[[localeData]].
    // 12. Let r be ResolveLocale( %DateTimeFormat%.[[availableLocales]], requestedLocales, opt, %DateTimeFormat%.[[relevantExtensionKeys]], localeData).
    const HashSet<String> availableLocales = exec.jsCallee()->globalObject()->intlDateTimeFormatAvailableLocales();
    HashMap<String, String> resolved = resolveLocale(exec, availableLocales, requestedLocales, localeOpt, relevantExtensionKeys, WTF_ARRAY_LENGTH(relevantExtensionKeys), localeData);

    // 13. Set dateTimeFormat.[[locale]] to the value of r.[[locale]].
    m_locale = resolved.get(vm.propertyNames->locale.string());
    if (m_locale.isEmpty()) {
        throwTypeError(&exec, scope, ASCIILiteral("failed to initialize DateTimeFormat due to invalid locale"));
        return;
    }
    // 14. Set dateTimeFormat.[[calendar]] to the value of r.[[ca]].
    m_calendar = resolved.get(ASCIILiteral("ca"));
    // Switch to preferred aliases.
    if (m_calendar == "gregory")
        m_calendar = ASCIILiteral("gregorian");
    else if (m_calendar == "islamicc")
        m_calendar = ASCIILiteral("islamic-civil");
    else if (m_calendar == "ethioaa")
        m_calendar = ASCIILiteral("ethiopic-amete-alem");
    // 15. Set dateTimeFormat.[[numberingSystem]] to the value of r.[[nu]].
    m_numberingSystem = resolved.get(ASCIILiteral("nu"));
    // 16. Let dataLocale be the value of r.[[dataLocale]].
    String dataLocale = resolved.get(ASCIILiteral("dataLocale"));

    // 17. Let tz be Get(options, "timeZone").
    JSValue tzValue = options->get(&exec, vm.propertyNames->timeZone);
    // 18. ReturnIfAbrupt(tz).
    RETURN_IF_EXCEPTION(scope, void());

    // 19. If tz is not undefined, then
    String tz;
    if (!tzValue.isUndefined()) {
        // a. Let tz be ToString(tz).
        String originalTz = tzValue.toWTFString(&exec);
        // b. ReturnIfAbrupt(tz).
        RETURN_IF_EXCEPTION(scope, void());
        // c. If the result of IsValidTimeZoneName(tz) is false, then i. Throw a RangeError exception.
        // d. Let tz be CanonicalizeTimeZoneName(tz).
        tz = canonicalizeTimeZoneName(originalTz);
        if (tz.isNull()) {
            throwRangeError(&exec, scope, String::format("invalid time zone: %s", originalTz.utf8().data()));
            return;
        }
    } else {
        // 20. Else,
        // a. Let tz be DefaultTimeZone().
        tz = defaultTimeZone();
    }

    // 21. Set dateTimeFormat.[[timeZone]] to tz.
    m_timeZone = tz;

    // 22. Let opt be a new Record.
    // Rather than building a record, build the skeleton pattern.
    StringBuilder skeletonBuilder;

    // 23. For each row of Table 3, except the header row, do:
    // a. Let prop be the name given in the Property column of the row.
    // b. Let value be GetOption(options, prop, "string", «the strings given in the Values column of the row», undefined).
    // c. ReturnIfAbrupt(value).
    // d. Set opt.[[<prop>]] to value.
    auto narrowShortLong = { "narrow", "short", "long" };
    auto twoDigitNumeric = { "2-digit", "numeric" };
    auto twoDigitNumericNarrowShortLong = { "2-digit", "numeric", "narrow", "short", "long" };
    auto shortLong = { "short", "long" };

    String weekday = intlStringOption(exec, options, vm.propertyNames->weekday, narrowShortLong, "weekday must be \"narrow\", \"short\", or \"long\"", nullptr);
    RETURN_IF_EXCEPTION(scope, void());
    if (!weekday.isNull()) {
        if (weekday == "narrow")
            skeletonBuilder.appendLiteral("EEEEE");
        else if (weekday == "short")
            skeletonBuilder.appendLiteral("EEE");
        else if (weekday == "long")
            skeletonBuilder.appendLiteral("EEEE");
    }

    String era = intlStringOption(exec, options, vm.propertyNames->era, narrowShortLong, "era must be \"narrow\", \"short\", or \"long\"", nullptr);
    RETURN_IF_EXCEPTION(scope, void());
    if (!era.isNull()) {
        if (era == "narrow")
            skeletonBuilder.appendLiteral("GGGGG");
        else if (era == "short")
            skeletonBuilder.appendLiteral("GGG");
        else if (era == "long")
            skeletonBuilder.appendLiteral("GGGG");
    }

    String year = intlStringOption(exec, options, vm.propertyNames->year, twoDigitNumeric, "year must be \"2-digit\" or \"numeric\"", nullptr);
    RETURN_IF_EXCEPTION(scope, void());
    if (!year.isNull()) {
        if (year == "2-digit")
            skeletonBuilder.appendLiteral("yy");
        else if (year == "numeric")
            skeletonBuilder.append('y');
    }

    String month = intlStringOption(exec, options, vm.propertyNames->month, twoDigitNumericNarrowShortLong, "month must be \"2-digit\", \"numeric\", \"narrow\", \"short\", or \"long\"", nullptr);
    RETURN_IF_EXCEPTION(scope, void());
    if (!month.isNull()) {
        if (month == "2-digit")
            skeletonBuilder.appendLiteral("MM");
        else if (month == "numeric")
            skeletonBuilder.append('M');
        else if (month == "narrow")
            skeletonBuilder.appendLiteral("MMMMM");
        else if (month == "short")
            skeletonBuilder.appendLiteral("MMM");
        else if (month == "long")
            skeletonBuilder.appendLiteral("MMMM");
    }

    String day = intlStringOption(exec, options, vm.propertyNames->day, twoDigitNumeric, "day must be \"2-digit\" or \"numeric\"", nullptr);
    RETURN_IF_EXCEPTION(scope, void());
    if (!day.isNull()) {
        if (day == "2-digit")
            skeletonBuilder.appendLiteral("dd");
        else if (day == "numeric")
            skeletonBuilder.append('d');
    }

    String hour = intlStringOption(exec, options, vm.propertyNames->hour, twoDigitNumeric, "hour must be \"2-digit\" or \"numeric\"", nullptr);
    RETURN_IF_EXCEPTION(scope, void());

    // We need hour12 to make the hour skeleton pattern decision, so do this early.
    // 32. Let hr12 be GetOption(options, "hour12", "boolean", undefined, undefined).
    bool isHour12Undefined;
    bool hr12 = intlBooleanOption(exec, options, vm.propertyNames->hour12, isHour12Undefined);
    // 33. ReturnIfAbrupt(hr12).
    RETURN_IF_EXCEPTION(scope, void());

    if (!hour.isNull()) {
        if (isHour12Undefined) {
            if (hour == "2-digit")
                skeletonBuilder.appendLiteral("jj");
            else if (hour == "numeric")
                skeletonBuilder.append('j');
        } else if (hr12) {
            if (hour == "2-digit")
                skeletonBuilder.appendLiteral("hh");
            else if (hour == "numeric")
                skeletonBuilder.append('h');
        } else {
            if (hour == "2-digit")
                skeletonBuilder.appendLiteral("HH");
            else if (hour == "numeric")
                skeletonBuilder.append('H');
        }
    }

    String minute = intlStringOption(exec, options, vm.propertyNames->minute, twoDigitNumeric, "minute must be \"2-digit\" or \"numeric\"", nullptr);
    RETURN_IF_EXCEPTION(scope, void());
    if (!minute.isNull()) {
        if (minute == "2-digit")
            skeletonBuilder.appendLiteral("mm");
        else if (minute == "numeric")
            skeletonBuilder.append('m');
    }

    String second = intlStringOption(exec, options, vm.propertyNames->second, twoDigitNumeric, "second must be \"2-digit\" or \"numeric\"", nullptr);
    RETURN_IF_EXCEPTION(scope, void());
    if (!second.isNull()) {
        if (second == "2-digit")
            skeletonBuilder.appendLiteral("ss");
        else if (second == "numeric")
            skeletonBuilder.append('s');
    }

    String timeZoneName = intlStringOption(exec, options, vm.propertyNames->timeZoneName, shortLong, "timeZoneName must be \"short\" or \"long\"", nullptr);
    RETURN_IF_EXCEPTION(scope, void());
    if (!timeZoneName.isNull()) {
        if (timeZoneName == "short")
            skeletonBuilder.append('z');
        else if (timeZoneName == "long")
            skeletonBuilder.appendLiteral("zzzz");
    }

    // 24. Let dataLocaleData be Get(localeData, dataLocale).
    // 25. Let formats be Get(dataLocaleData, "formats").
    // 26. Let matcher be GetOption(options, "formatMatcher", "string", «"basic", "best fit"», "best fit").
    intlStringOption(exec, options, vm.propertyNames->formatMatcher, { "basic", "best fit" }, "formatMatcher must be either \"basic\" or \"best fit\"", "best fit");
    // 27. ReturnIfAbrupt(matcher).
    RETURN_IF_EXCEPTION(scope, void());

    // Always use ICU date format generator, rather than our own pattern list and matcher.
    // Covers steps 28-36.
    UErrorCode status = U_ZERO_ERROR;
    UDateTimePatternGenerator* generator = udatpg_open(dataLocale.utf8().data(), &status);
    if (U_FAILURE(status)) {
        throwTypeError(&exec, scope, ASCIILiteral("failed to initialize DateTimeFormat"));
        return;
    }

    String skeleton = skeletonBuilder.toString();
    StringView skeletonView(skeleton);
    Vector<UChar, 32> patternBuffer(32);
    status = U_ZERO_ERROR;
    auto patternLength = udatpg_getBestPattern(generator, skeletonView.upconvertedCharacters(), skeletonView.length(), patternBuffer.data(), patternBuffer.size(), &status);
    if (status == U_BUFFER_OVERFLOW_ERROR) {
        status = U_ZERO_ERROR;
        patternBuffer.grow(patternLength);
        udatpg_getBestPattern(generator, skeletonView.upconvertedCharacters(), skeletonView.length(), patternBuffer.data(), patternLength, &status);
    }
    udatpg_close(generator);
    if (U_FAILURE(status)) {
        throwTypeError(&exec, scope, ASCIILiteral("failed to initialize DateTimeFormat"));
        return;
    }

    StringView pattern(patternBuffer.data(), patternLength);
    setFormatsFromPattern(pattern);

    status = U_ZERO_ERROR;
    StringView timeZoneView(m_timeZone);
    m_dateFormat = std::unique_ptr<UDateFormat, UDateFormatDeleter>(udat_open(UDAT_PATTERN, UDAT_PATTERN, m_locale.utf8().data(), timeZoneView.upconvertedCharacters(), timeZoneView.length(), pattern.upconvertedCharacters(), pattern.length(), &status));
    if (U_FAILURE(status)) {
        throwTypeError(&exec, scope, ASCIILiteral("failed to initialize DateTimeFormat"));
        return;
    }

    // 37. Set dateTimeFormat.[[boundFormat]] to undefined.
    // Already undefined.

    // 38. Set dateTimeFormat.[[initializedDateTimeFormat]] to true.
    m_initializedDateTimeFormat = true;

    // 39. Return dateTimeFormat.
}
Пример #16
0
static JSValue performPromiseAll(ExecState* exec, JSValue iterator, JSValue C, JSPromiseDeferred* deferred)
{
    JSObject* thisObject = asObject(C);
    VM& vm = exec->vm();

    // 6. Let 'values' be the result of calling ArrayCreate(0).
    JSArray* values = constructEmptyArray(exec, nullptr, thisObject->globalObject());

    // 7. Let 'countdownHolder' be Record { [[Countdown]]: 0 }.
    NumberObject* countdownHolder = constructNumber(exec, thisObject->globalObject(), JSValue(0));

    // 8. Let 'index' be 0.
    unsigned index = 0;

    // 9. Repeat.
    do {
        // i. Let 'next' be the result of calling IteratorStep(iterator).
        JSValue next = iteratorStep(exec, iterator);
        if (exec->hadException())
            return jsUndefined();

        // iii. If 'next' is false,
        if (next.isFalse()) {
            // a. If 'index' is 0,
            if (!index) {
                // a. Let 'resolveResult' be the result of calling the [[Call]] internal method
                //    of deferred.[[Resolve]] with undefined as thisArgument and a List containing
                //    values as argumentsList.
                performDeferredResolve(exec, deferred, values);

                // b. ReturnIfAbrupt(resolveResult).
                if (exec->hadException())
                    return jsUndefined();
            }

            // b. Return deferred.[[Promise]].
            return deferred->promise();
        }

        // iv. Let 'nextValue' be the result of calling IteratorValue(next).
        // v. RejectIfAbrupt(nextValue, deferred).
        JSValue nextValue = iteratorValue(exec, next);
        if (exec->hadException())
            return jsUndefined();

        values->push(exec, jsUndefined());

        // vi. Let 'nextPromise' be the result of calling Invoke(C, "resolve", (nextValue)).
        JSValue resolveFunction = C.get(exec, vm.propertyNames->resolve);
        if (exec->hadException())
            return jsUndefined();

        CallData resolveFunctionCallData;
        CallType resolveFunctionCallType = getCallData(resolveFunction, resolveFunctionCallData);
        if (resolveFunctionCallType == CallTypeNone) {
            throwTypeError(exec);
            return jsUndefined();
        }

        MarkedArgumentBuffer resolveFunctionArguments;
        resolveFunctionArguments.append(nextValue);
        JSValue nextPromise = call(exec, resolveFunction, resolveFunctionCallType, resolveFunctionCallData, C, resolveFunctionArguments);

        // vii. RejectIfAbrupt(nextPromise, deferred).
        if (exec->hadException())
            return jsUndefined();

        // viii. Let 'countdownFunction' be a new built-in function object as defined in Promise.all Countdown Functions.
        JSFunction* countdownFunction = createPromiseAllCountdownFunction(vm, thisObject->globalObject());

        // ix. Set the [[Index]] internal slot of 'countdownFunction' to 'index'.
        countdownFunction->putDirect(vm, vm.propertyNames->indexPrivateName, JSValue(index));

        // x. Set the [[Values]] internal slot of 'countdownFunction' to 'values'.
        countdownFunction->putDirect(vm, vm.propertyNames->valuesPrivateName, values);

        // xi. Set the [[Deferred]] internal slot of 'countdownFunction' to 'deferred'.
        countdownFunction->putDirect(vm, vm.propertyNames->deferredPrivateName, deferred);

        // xii. Set the [[CountdownHolder]] internal slot of 'countdownFunction' to 'countdownHolder'.
        countdownFunction->putDirect(vm, vm.propertyNames->countdownHolderPrivateName, countdownHolder);

        // xiii. Let 'result' be the result of calling Invoke(nextPromise, "then", (countdownFunction, deferred.[[Reject]])).
        JSValue thenFunction = nextPromise.get(exec, vm.propertyNames->then);
        if (exec->hadException())
            return jsUndefined();

        CallData thenFunctionCallData;
        CallType thenFunctionCallType = getCallData(thenFunction, thenFunctionCallData);
        if (thenFunctionCallType == CallTypeNone) {
            throwTypeError(exec);
            return jsUndefined();
        }

        MarkedArgumentBuffer thenFunctionArguments;
        thenFunctionArguments.append(countdownFunction);
        thenFunctionArguments.append(deferred->reject());

        call(exec, thenFunction, thenFunctionCallType, thenFunctionCallData, nextPromise, thenFunctionArguments);

        // xiv. RejectIfAbrupt(result, deferred).
        if (exec->hadException())
            return jsUndefined();

        // xv. Set index to index + 1.
        index++;

        // xvi. Set countdownHolder.[[Countdown]] to countdownHolder.[[Countdown]] + 1.
        uint32_t newCountdownValue = countdownHolder->internalValue().asUInt32() + 1;
        countdownHolder->setInternalValue(vm, JSValue(newCountdownValue));
    } while (true);
    ASSERT_NOT_REACHED();
    return jsUndefined();
}
Пример #17
0
JSValue JSWebKitSubtleCrypto::unwrapKey(ExecState& state)
{
    VM& vm = state.vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    if (state.argumentCount() < 5)
        return throwException(&state, scope, createNotEnoughArgumentsError(&state));

    auto keyFormat = cryptoKeyFormatFromJSValue(state, scope, state.uncheckedArgument(0));
    RETURN_IF_EXCEPTION(scope, { });

    auto wrappedKeyData = cryptoOperationDataFromJSValue(state, scope, state.uncheckedArgument(1));
    RETURN_IF_EXCEPTION(scope, { });

    RefPtr<CryptoKey> unwrappingKey = JSCryptoKey::toWrapped(vm, state.uncheckedArgument(2));
    if (!unwrappingKey)
        return throwTypeError(&state, scope);

    if (!unwrappingKey->allows(CryptoKeyUsageUnwrapKey)) {
        wrapped().document()->addConsoleMessage(MessageSource::JS, MessageLevel::Error, ASCIILiteral("Key usages do not include 'unwrapKey'"));
        throwNotSupportedError(state, scope);
        return jsUndefined();
    }

    auto unwrapAlgorithm = createAlgorithmFromJSValue(state, scope, state.uncheckedArgument(3));
    RETURN_IF_EXCEPTION(scope, { });

    auto unwrapAlgorithmParameters = JSCryptoAlgorithmDictionary::createParametersForDecrypt(state, scope, unwrapAlgorithm->identifier(), state.uncheckedArgument(3));
    RETURN_IF_EXCEPTION(scope, { });

    RefPtr<CryptoAlgorithm> unwrappedKeyAlgorithm;
    RefPtr<CryptoAlgorithmParametersDeprecated> unwrappedKeyAlgorithmParameters;
    if (!state.uncheckedArgument(4).isNull()) {
        unwrappedKeyAlgorithm = createAlgorithmFromJSValue(state, scope, state.uncheckedArgument(4));
        RETURN_IF_EXCEPTION(scope, { });

        unwrappedKeyAlgorithmParameters = JSCryptoAlgorithmDictionary::createParametersForImportKey(state, scope, unwrappedKeyAlgorithm->identifier(), state.uncheckedArgument(4));
        RETURN_IF_EXCEPTION(scope, { });
    }

    bool extractable = state.argument(5).toBoolean(&state);
    RETURN_IF_EXCEPTION(scope, { });

    CryptoKeyUsageBitmap keyUsages = 0;
    if (state.argumentCount() >= 7) {
        keyUsages = cryptoKeyUsagesFromJSValue(state, scope, state.uncheckedArgument(6));
        RETURN_IF_EXCEPTION(scope, { });
    }

    RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow());
    auto promise = wrapper->promise();
    Strong<JSDOMGlobalObject> domGlobalObject(state.vm(), globalObject());

    auto decryptSuccessCallback = [domGlobalObject, keyFormat, unwrappedKeyAlgorithm, unwrappedKeyAlgorithmParameters, extractable, keyUsages, wrapper](const Vector<uint8_t>& result) mutable {
        auto importSuccessCallback = [wrapper](CryptoKey& key) mutable {
            wrapper->resolve<IDLInterface<CryptoKey>>(key);
        };
        auto importFailureCallback = [wrapper]() mutable {
            wrapper->reject(); // FIXME: This should reject with an Exception.
        };

        VM& vm = domGlobalObject->vm();
        auto scope = DECLARE_CATCH_SCOPE(vm);

        ExecState& state = *domGlobalObject->globalExec();
        WebCore::importKey(state, keyFormat, std::make_pair(result.data(), result.size()), unwrappedKeyAlgorithm, unwrappedKeyAlgorithmParameters, extractable, keyUsages, WTFMove(importSuccessCallback), WTFMove(importFailureCallback));
        if (UNLIKELY(scope.exception())) {
            // FIXME: Report exception details to console, and possibly to calling script once there is a standardized way to pass errors to WebCrypto promise reject functions.
            scope.clearException();
            wrapper->reject(); // FIXME: This should reject with an Exception.
        }
    };

    auto decryptFailureCallback = [wrapper]() mutable {
        wrapper->reject(); // FIXME: This should reject with an Exception.
    };

    auto result = unwrapAlgorithm->decryptForUnwrapKey(*unwrapAlgorithmParameters, *unwrappingKey, wrappedKeyData, WTFMove(decryptSuccessCallback), WTFMove(decryptFailureCallback));
    if (result.hasException()) {
        propagateException(state, scope, result.releaseException());
        return { };
    }

    return promise;
}
Пример #18
0
static EncodedJSValue JSC_HOST_CALL callWeakSet(ExecState* exec)
{
    return JSValue::encode(throwTypeError(exec, ASCIILiteral("WeakSet cannot be called as a function")));
}
static JSC::JSValue dataFunctioni(DataFunctionToCall f, JSC::ExecState* exec, WebGLRenderingContext* context)
{
    if (exec->argumentCount() != 2)
        return throwSyntaxError(exec);

    if (exec->argumentCount() > 0 && !exec->argument(0).isUndefinedOrNull() && !exec->argument(0).inherits(&JSWebGLUniformLocation::s_info))
        return throwTypeError(exec);
    WebGLUniformLocation* location = toWebGLUniformLocation(exec->argument(0));
  
    if (exec->hadException())
        return jsUndefined();
        
    RefPtr<Int32Array> webGLArray = toInt32Array(exec->argument(1));
    if (exec->hadException())    
        return jsUndefined();
        
    ExceptionCode ec = 0;
    if (webGLArray) {
        switch (f) {
        case f_uniform1v:
            context->uniform1iv(location, webGLArray.get(), ec);
            break;
        case f_uniform2v:
            context->uniform2iv(location, webGLArray.get(), ec);
            break;
        case f_uniform3v:
            context->uniform3iv(location, webGLArray.get(), ec);
            break;
        case f_uniform4v:
            context->uniform4iv(location, webGLArray.get(), ec);
            break;
        default:
            break;
        }
        
        setDOMException(exec, ec);
        return jsUndefined();
    }


    Vector<int, 64> array;
    if (!toVector(exec, exec->argument(1), array))
        return throwTypeError(exec);

    switch (f) {
    case f_uniform1v:
        context->uniform1iv(location, array.data(), array.size(), ec);
        break;
    case f_uniform2v:
        context->uniform2iv(location, array.data(), array.size(), ec);
        break;
    case f_uniform3v:
        context->uniform3iv(location, array.data(), array.size(), ec);
        break;
    case f_uniform4v:
        context->uniform4iv(location, array.data(), array.size(), ec);
        break;
    default:
        break;
    }
    
    setDOMException(exec, ec);
    return jsUndefined();
}
static JSC::JSValue dataFunctionf(DataFunctionToCall f, JSC::ExecState* exec, WebGLRenderingContext* context)
{
    if (exec->argumentCount() != 2)
        return throwSyntaxError(exec);
    
    WebGLUniformLocation* location = 0;
    long index = -1;
    
    if (functionForUniform(f)) {
        if (exec->argumentCount() > 0 && !exec->argument(0).isUndefinedOrNull() && !exec->argument(0).inherits(&JSWebGLUniformLocation::s_info))
            return throwTypeError(exec);
        location = toWebGLUniformLocation(exec->argument(0));
    } else
        index = exec->argument(0).toInt32(exec);

    if (exec->hadException())
        return jsUndefined();
        
    RefPtr<Float32Array> float32Array = toFloat32Array(exec->argument(1));
    if (exec->hadException())    
        return jsUndefined();
        
    ExceptionCode ec = 0;
    if (float32Array) {
        switch (f) {
        case f_uniform1v:
            context->uniform1fv(location, float32Array.get(), ec);
            break;
        case f_uniform2v:
            context->uniform2fv(location, float32Array.get(), ec);
            break;
        case f_uniform3v:
            context->uniform3fv(location, float32Array.get(), ec);
            break;
        case f_uniform4v:
            context->uniform4fv(location, float32Array.get(), ec);
            break;
        case f_vertexAttrib1v:
            context->vertexAttrib1fv(index, float32Array.get());
            break;
        case f_vertexAttrib2v:
            context->vertexAttrib2fv(index, float32Array.get());
            break;
        case f_vertexAttrib3v:
            context->vertexAttrib3fv(index, float32Array.get());
            break;
        case f_vertexAttrib4v:
            context->vertexAttrib4fv(index, float32Array.get());
            break;
        }
        
        setDOMException(exec, ec);
        return jsUndefined();
    }

    Vector<float, 64> array;
    if (!toVector(exec, exec->argument(1), array))
        return throwTypeError(exec);

    switch (f) {
    case f_uniform1v:
        context->uniform1fv(location, array.data(), array.size(), ec);
        break;
    case f_uniform2v:
        context->uniform2fv(location, array.data(), array.size(), ec);
        break;
    case f_uniform3v:
        context->uniform3fv(location, array.data(), array.size(), ec);
        break;
    case f_uniform4v:
        context->uniform4fv(location, array.data(), array.size(), ec);
        break;
    case f_vertexAttrib1v:
        context->vertexAttrib1fv(index, array.data(), array.size());
        break;
    case f_vertexAttrib2v:
        context->vertexAttrib2fv(index, array.data(), array.size());
        break;
    case f_vertexAttrib3v:
        context->vertexAttrib3fv(index, array.data(), array.size());
        break;
    case f_vertexAttrib4v:
        context->vertexAttrib4fv(index, array.data(), array.size());
        break;
    }
    
    setDOMException(exec, ec);
    return jsUndefined();
}
Пример #21
0
std::unique_ptr<CryptoKeyData> JSCryptoKeySerializationJWK::keyDataRSAComponents() const
{
    Vector<uint8_t> modulus;
    Vector<uint8_t> exponent;
    Vector<uint8_t> privateExponent;

    if (!getBigIntegerVectorFromJSON(m_exec, m_json.get(), "n", modulus)) {
        if (!m_exec->hadException())
            throwTypeError(m_exec, "Required JWK \"n\" member is missing");
        return nullptr;
    }

    if (!keySizeIsValid(modulus.size() * 8)) {
        throwTypeError(m_exec, "Key size is not valid for " + m_jwkAlgorithmName);
        return nullptr;
    }

    if (!getBigIntegerVectorFromJSON(m_exec, m_json.get(), "e", exponent)) {
        if (!m_exec->hadException())
            throwTypeError(m_exec, "Required JWK \"e\" member is missing");
        return nullptr;
    }

    if (!getBigIntegerVectorFromJSON(m_exec, m_json.get(), "d", modulus)) {
        if (m_exec->hadException())
            return nullptr;
        return CryptoKeyDataRSAComponents::createPublic(modulus, exponent);
    }

    CryptoKeyDataRSAComponents::PrimeInfo firstPrimeInfo;
    CryptoKeyDataRSAComponents::PrimeInfo secondPrimeInfo;
    Vector<CryptoKeyDataRSAComponents::PrimeInfo> otherPrimeInfos;
    if (!getBigIntegerVectorFromJSON(m_exec, m_json.get(), "p", firstPrimeInfo.primeFactor)) {
        if (m_exec->hadException())
            return nullptr;
        return CryptoKeyDataRSAComponents::createPrivate(modulus, exponent, privateExponent);
    }

    if (!getBigIntegerVectorFromJSON(m_exec, m_json.get(), "dp", firstPrimeInfo.factorCRTExponent)) {
        if (m_exec->hadException())
            return nullptr;
        return CryptoKeyDataRSAComponents::createPrivate(modulus, exponent, privateExponent);
    }

    if (!getBigIntegerVectorFromJSON(m_exec, m_json.get(), "q", secondPrimeInfo.primeFactor)) {
        if (m_exec->hadException())
            return nullptr;
        return CryptoKeyDataRSAComponents::createPrivate(modulus, exponent, privateExponent);
    }

    if (!getBigIntegerVectorFromJSON(m_exec, m_json.get(), "dq", secondPrimeInfo.factorCRTExponent)) {
        if (m_exec->hadException())
            return nullptr;
        return CryptoKeyDataRSAComponents::createPrivate(modulus, exponent, privateExponent);
    }

    if (!getBigIntegerVectorFromJSON(m_exec, m_json.get(), "qi", secondPrimeInfo.factorCRTCoefficient)) {
        if (m_exec->hadException())
            return nullptr;
        return CryptoKeyDataRSAComponents::createPrivate(modulus, exponent, privateExponent);
    }

    JSArray* otherPrimeInfoJSArray;
    if (!getJSArrayFromJSON(m_exec, m_json.get(), "oth", otherPrimeInfoJSArray)) {
        if (m_exec->hadException())
            return nullptr;
        return CryptoKeyDataRSAComponents::createPrivateWithAdditionalData(modulus, exponent, privateExponent, firstPrimeInfo, secondPrimeInfo, otherPrimeInfos);
    }

    for (size_t i = 0; i < otherPrimeInfoJSArray->length(); ++i) {
        CryptoKeyDataRSAComponents::PrimeInfo info;
        JSValue element = otherPrimeInfoJSArray->getIndex(m_exec, i);
        if (m_exec->hadException())
            return nullptr;
        if (!element.isObject()) {
            throwTypeError(m_exec, "JWK \"oth\" array member is not an object");
            return nullptr;
        }
        if (!getBigIntegerVectorFromJSON(m_exec, asObject(element), "r", info.primeFactor)) {
            if (!m_exec->hadException())
                throwTypeError(m_exec, "Cannot get prime factor for a prime in \"oth\" dictionary");
            return nullptr;
        }
        if (!getBigIntegerVectorFromJSON(m_exec, asObject(element), "d", info.factorCRTExponent)) {
            if (!m_exec->hadException())
                throwTypeError(m_exec, "Cannot get factor CRT exponent for a prime in \"oth\" dictionary");
            return nullptr;
        }
        if (!getBigIntegerVectorFromJSON(m_exec, asObject(element), "t", info.factorCRTCoefficient)) {
            if (!m_exec->hadException())
                throwTypeError(m_exec, "Cannot get factor CRT coefficient for a prime in \"oth\" dictionary");
            return nullptr;
        }
        otherPrimeInfos.append(info);
    }

    return CryptoKeyDataRSAComponents::createPrivateWithAdditionalData(modulus, exponent, privateExponent, firstPrimeInfo, secondPrimeInfo, otherPrimeInfos);
}
Пример #22
0
Matrix& Matrix::conj(rflag tp){
  throwTypeError(tp);
  return *this;
}
Пример #23
0
void IntlNumberFormat::initializeNumberFormat(ExecState& state, JSValue locales, JSValue optionsValue)
{
    VM& vm = state.vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    // 11.1.2 InitializeNumberFormat (numberFormat, locales, options) (ECMA-402)
    // https://tc39.github.io/ecma402/#sec-initializenumberformat

    auto requestedLocales = canonicalizeLocaleList(state, locales);
    RETURN_IF_EXCEPTION(scope, void());

    JSObject* options;
    if (optionsValue.isUndefined())
        options = constructEmptyObject(&state, state.lexicalGlobalObject()->nullPrototypeObjectStructure());
    else {
        options = optionsValue.toObject(&state);
        RETURN_IF_EXCEPTION(scope, void());
    }

    HashMap<String, String> opt;

    String matcher = intlStringOption(state, options, vm.propertyNames->localeMatcher, { "lookup", "best fit" }, "localeMatcher must be either \"lookup\" or \"best fit\"", "best fit");
    RETURN_IF_EXCEPTION(scope, void());
    opt.add("localeMatcher"_s, matcher);

    auto& availableLocales = state.jsCallee()->globalObject(vm)->intlNumberFormatAvailableLocales();
    auto result = resolveLocale(state, availableLocales, requestedLocales, opt, relevantNumberExtensionKeys, WTF_ARRAY_LENGTH(relevantNumberExtensionKeys), IntlNFInternal::localeData);

    m_locale = result.get("locale"_s);
    if (m_locale.isEmpty()) {
        throwTypeError(&state, scope, "failed to initialize NumberFormat due to invalid locale"_s);
        return;
    }

    m_numberingSystem = result.get("nu"_s);

    String styleString = intlStringOption(state, options, Identifier::fromString(&vm, "style"), { "decimal", "percent", "currency" }, "style must be either \"decimal\", \"percent\", or \"currency\"", "decimal");
    RETURN_IF_EXCEPTION(scope, void());
    if (styleString == "decimal")
        m_style = Style::Decimal;
    else if (styleString == "percent")
        m_style = Style::Percent;
    else if (styleString == "currency")
        m_style = Style::Currency;
    else
        ASSERT_NOT_REACHED();

    String currency = intlStringOption(state, options, Identifier::fromString(&vm, "currency"), { }, nullptr, nullptr);
    RETURN_IF_EXCEPTION(scope, void());
    if (!currency.isNull()) {
        if (currency.length() != 3 || !currency.isAllSpecialCharacters<isASCIIAlpha>()) {
            throwException(&state, scope, createRangeError(&state, "currency is not a well-formed currency code"_s));
            return;
        }
    }

    unsigned currencyDigits = 0;
    if (m_style == Style::Currency) {
        if (currency.isNull()) {
            throwTypeError(&state, scope, "currency must be a string"_s);
            return;
        }

        currency = currency.convertToASCIIUppercase();
        m_currency = currency;
        currencyDigits = computeCurrencyDigits(currency);
    }

    String currencyDisplayString = intlStringOption(state, options, Identifier::fromString(&vm, "currencyDisplay"), { "code", "symbol", "name" }, "currencyDisplay must be either \"code\", \"symbol\", or \"name\"", "symbol");
    RETURN_IF_EXCEPTION(scope, void());
    if (m_style == Style::Currency) {
        if (currencyDisplayString == "code")
            m_currencyDisplay = CurrencyDisplay::Code;
        else if (currencyDisplayString == "symbol")
            m_currencyDisplay = CurrencyDisplay::Symbol;
        else if (currencyDisplayString == "name")
            m_currencyDisplay = CurrencyDisplay::Name;
        else
            ASSERT_NOT_REACHED();
    }

    unsigned minimumIntegerDigits = intlNumberOption(state, options, Identifier::fromString(&vm, "minimumIntegerDigits"), 1, 21, 1);
    RETURN_IF_EXCEPTION(scope, void());
    m_minimumIntegerDigits = minimumIntegerDigits;

    unsigned minimumFractionDigitsDefault = (m_style == Style::Currency) ? currencyDigits : 0;

    unsigned minimumFractionDigits = intlNumberOption(state, options, Identifier::fromString(&vm, "minimumFractionDigits"), 0, 20, minimumFractionDigitsDefault);
    RETURN_IF_EXCEPTION(scope, void());
    m_minimumFractionDigits = minimumFractionDigits;

    unsigned maximumFractionDigitsDefault;
    if (m_style == Style::Currency)
        maximumFractionDigitsDefault = std::max(minimumFractionDigits, currencyDigits);
    else if (m_style == Style::Percent)
        maximumFractionDigitsDefault = minimumFractionDigits;
    else
        maximumFractionDigitsDefault = std::max(minimumFractionDigits, 3u);

    unsigned maximumFractionDigits = intlNumberOption(state, options, Identifier::fromString(&vm, "maximumFractionDigits"), minimumFractionDigits, 20, maximumFractionDigitsDefault);
    RETURN_IF_EXCEPTION(scope, void());
    m_maximumFractionDigits = maximumFractionDigits;

    JSValue minimumSignificantDigitsValue = options->get(&state, Identifier::fromString(&vm, "minimumSignificantDigits"));
    RETURN_IF_EXCEPTION(scope, void());

    JSValue maximumSignificantDigitsValue = options->get(&state, Identifier::fromString(&vm, "maximumSignificantDigits"));
    RETURN_IF_EXCEPTION(scope, void());

    if (!minimumSignificantDigitsValue.isUndefined() || !maximumSignificantDigitsValue.isUndefined()) {
        unsigned minimumSignificantDigits = intlDefaultNumberOption(state, minimumSignificantDigitsValue, Identifier::fromString(&vm, "minimumSignificantDigits"), 1, 21, 1);
        RETURN_IF_EXCEPTION(scope, void());
        unsigned maximumSignificantDigits = intlDefaultNumberOption(state, maximumSignificantDigitsValue, Identifier::fromString(&vm, "maximumSignificantDigits"), minimumSignificantDigits, 21, 21);
        RETURN_IF_EXCEPTION(scope, void());
        m_minimumSignificantDigits = minimumSignificantDigits;
        m_maximumSignificantDigits = maximumSignificantDigits;
    }

    bool usesFallback;
    bool useGrouping = intlBooleanOption(state, options, Identifier::fromString(&vm, "useGrouping"), usesFallback);
    if (usesFallback)
        useGrouping = true;
    RETURN_IF_EXCEPTION(scope, void());
    m_useGrouping = useGrouping;

    UNumberFormatStyle style = UNUM_DEFAULT;
    switch (m_style) {
    case Style::Decimal:
        style = UNUM_DECIMAL;
        break;
    case Style::Percent:
        style = UNUM_PERCENT;
        break;
    case Style::Currency:
        switch (m_currencyDisplay) {
        case CurrencyDisplay::Code:
            style = UNUM_CURRENCY_ISO;
            break;
        case CurrencyDisplay::Symbol:
            style = UNUM_CURRENCY;
            break;
        case CurrencyDisplay::Name:
            style = UNUM_CURRENCY_PLURAL;
            break;
        default:
            ASSERT_NOT_REACHED();
        }
        break;
    default:
        ASSERT_NOT_REACHED();
    }

    UErrorCode status = U_ZERO_ERROR;
    m_numberFormat = std::unique_ptr<UNumberFormat, UNumberFormatDeleter>(unum_open(style, nullptr, 0, m_locale.utf8().data(), nullptr, &status));
    if (U_FAILURE(status)) {
        throwTypeError(&state, scope, "failed to initialize NumberFormat"_s);
        return;
    }

    if (m_style == Style::Currency) {
        unum_setTextAttribute(m_numberFormat.get(), UNUM_CURRENCY_CODE, StringView(m_currency).upconvertedCharacters(), m_currency.length(), &status);
        if (U_FAILURE(status)) {
            throwTypeError(&state, scope, "failed to initialize NumberFormat"_s);
            return;
        }
    }
    if (!m_minimumSignificantDigits) {
        unum_setAttribute(m_numberFormat.get(), UNUM_MIN_INTEGER_DIGITS, m_minimumIntegerDigits);
        unum_setAttribute(m_numberFormat.get(), UNUM_MIN_FRACTION_DIGITS, m_minimumFractionDigits);
        unum_setAttribute(m_numberFormat.get(), UNUM_MAX_FRACTION_DIGITS, m_maximumFractionDigits);
    } else {
        unum_setAttribute(m_numberFormat.get(), UNUM_SIGNIFICANT_DIGITS_USED, true);
        unum_setAttribute(m_numberFormat.get(), UNUM_MIN_SIGNIFICANT_DIGITS, m_minimumSignificantDigits);
        unum_setAttribute(m_numberFormat.get(), UNUM_MAX_SIGNIFICANT_DIGITS, m_maximumSignificantDigits);
    }
    unum_setAttribute(m_numberFormat.get(), UNUM_GROUPING_USED, m_useGrouping);
    unum_setAttribute(m_numberFormat.get(), UNUM_ROUNDING_MODE, UNUM_ROUND_HALFUP);

    m_initializedNumberFormat = true;
}
Пример #24
0
bool Matrix::toGPU(rflag tp){
  throwTypeError(tp);
  if(!ongpu)
    m_elem = (Real*)mvGPU(m_elem, elemNum() * sizeof(Real), ongpu);
  return ongpu;
}
Пример #25
0
v8::Handle<v8::Value> V8Blob::constructorCustom(const v8::Arguments& args)
{
    if (!args.Length()) {
        RefPtr<Blob> blob = Blob::create();
        return toV8(blob.get(), args.Holder(), args.GetIsolate());
    }

    v8::Local<v8::Value> firstArg = args[0];
    if (!firstArg->IsArray())
        return throwTypeError("First argument of the constructor is not of type Array", args.GetIsolate());

    String type;
    String endings = ASCIILiteral("transparent");

    if (args.Length() > 1) {
        if (!args[1]->IsObject())
            return throwTypeError("Second argument of the constructor is not of type Object", args.GetIsolate());

        V8TRYCATCH(Dictionary, dictionary, Dictionary(args[1], args.GetIsolate()));

        V8TRYCATCH(bool, containsEndings, dictionary.get("endings", endings));
        if (containsEndings) {
            if (endings != "transparent" && endings != "native")
                return throwTypeError("The endings property must be either \"transparent\" or \"native\"", args.GetIsolate());
        }

        V8TRYCATCH(bool, containsType, dictionary.get("type", type));
        UNUSED_PARAM(containsType);
        if (!type.containsOnlyASCII())
            return throwError(v8SyntaxError, "type must consist of ASCII characters", args.GetIsolate());
        type.makeLower();
    }

    ASSERT(endings == "transparent" || endings == "native");

    BlobBuilder blobBuilder;

    V8TRYCATCH(v8::Local<v8::Array>, blobParts, v8::Local<v8::Array>::Cast(firstArg));
    uint32_t length = blobParts->Length();

    for (uint32_t i = 0; i < length; ++i) {
        v8::Local<v8::Value> item = blobParts->Get(v8::Uint32::New(i));
        ASSERT(!item.IsEmpty());
#if ENABLE(BLOB)
        if (V8ArrayBuffer::HasInstance(item, args.GetIsolate(), worldType(args.GetIsolate()))) {
            ArrayBuffer* arrayBuffer = V8ArrayBuffer::toNative(v8::Handle<v8::Object>::Cast(item));
            ASSERT(arrayBuffer);
            blobBuilder.append(arrayBuffer);
        } else if (V8ArrayBufferView::HasInstance(item, args.GetIsolate(), worldType(args.GetIsolate()))) {
            ArrayBufferView* arrayBufferView = V8ArrayBufferView::toNative(v8::Handle<v8::Object>::Cast(item));
            ASSERT(arrayBufferView);
            blobBuilder.append(arrayBufferView);
        } else
#endif
        if (V8Blob::HasInstance(item, args.GetIsolate(), worldType(args.GetIsolate()))) {
            Blob* blob = V8Blob::toNative(v8::Handle<v8::Object>::Cast(item));
            ASSERT(blob);
            blobBuilder.append(blob);
        } else {
            V8TRYCATCH(String, stringValue, toWebCoreString(item));
            blobBuilder.append(stringValue, endings);
        }
    }

    RefPtr<Blob> blob = blobBuilder.getBlob(type);
    return toV8(blob.get(), args.Holder(), args.GetIsolate());
}
Пример #26
0
void IntlCollator::initializeCollator(ExecState& state, JSValue locales, JSValue optionsValue)
{
    VM& vm = state.vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    // 10.1.1 InitializeCollator (collator, locales, options) (ECMA-402 2.0)
    // 1. If collator has an [[initializedIntlObject]] internal slot with value true, throw a TypeError exception.
    // 2. Set collator.[[initializedIntlObject]] to true.

    // 3. Let requestedLocales be CanonicalizeLocaleList(locales).
    auto requestedLocales = canonicalizeLocaleList(state, locales);
    // 4. ReturnIfAbrupt(requestedLocales).
    RETURN_IF_EXCEPTION(scope, void());

    // 5. If options is undefined, then
    JSObject* options;
    if (optionsValue.isUndefined()) {
        // a. Let options be ObjectCreate(%ObjectPrototype%).
        options = constructEmptyObject(&state);
    } else { // 6. Else
        // a. Let options be ToObject(options).
        options = optionsValue.toObject(&state);
        // b. ReturnIfAbrupt(options).
        RETURN_IF_EXCEPTION(scope, void());
    }

    // 7. Let u be GetOption(options, "usage", "string", «"sort", "search"», "sort").
    String usageString = intlStringOption(state, options, vm.propertyNames->usage, { "sort", "search" }, "usage must be either \"sort\" or \"search\"", "sort");
    // 8. ReturnIfAbrupt(u).
    RETURN_IF_EXCEPTION(scope, void());
    // 9. Set collator.[[usage]] to u.
    if (usageString == "sort")
        m_usage = Usage::Sort;
    else if (usageString == "search")
        m_usage = Usage::Search;
    else
        ASSERT_NOT_REACHED();

    // 10. If u is "sort", then
    // a. Let localeData be the value of %Collator%.[[sortLocaleData]];
    // 11. Else
    // a. Let localeData be the value of %Collator%.[[searchLocaleData]].
    Vector<String> (*localeData)(const String&, size_t);
    if (m_usage == Usage::Sort)
        localeData = sortLocaleData;
    else
        localeData = searchLocaleData;

    // 12. Let opt be a new Record.
    HashMap<String, String> opt;

    // 13. Let matcher be GetOption(options, "localeMatcher", "string", «"lookup", "best fit"», "best fit").
    String matcher = intlStringOption(state, options, vm.propertyNames->localeMatcher, { "lookup", "best fit" }, "localeMatcher must be either \"lookup\" or \"best fit\"", "best fit");
    // 14. ReturnIfAbrupt(matcher).
    RETURN_IF_EXCEPTION(scope, void());
    // 15. Set opt.[[localeMatcher]] to matcher.
    opt.add(ASCIILiteral("localeMatcher"), matcher);

    // 16. For each row in Table 1, except the header row, do:
    // a. Let key be the name given in the Key column of the row.
    // b. Let prop be the name given in the Property column of the row.
    // c. Let type be the string given in the Type column of the row.
    // d. Let list be a List containing the Strings given in the Values column of the row, or undefined if no strings are given.
    // e. Let value be GetOption(options, prop, type, list, undefined).
    // f. ReturnIfAbrupt(value).
    // g. If the string given in the Type column of the row is "boolean" and value is not undefined, then
    //    i. Let value be ToString(value).
    //    ii. ReturnIfAbrupt(value).
    // h. Set opt.[[<key>]] to value.
    {
        String numericString;
        bool usesFallback;
        bool numeric = intlBooleanOption(state, options, vm.propertyNames->numeric, usesFallback);
        RETURN_IF_EXCEPTION(scope, void());
        if (!usesFallback)
            numericString = ASCIILiteral(numeric ? "true" : "false");
        opt.add(ASCIILiteral("kn"), numericString);
    }
    {
        String caseFirst = intlStringOption(state, options, vm.propertyNames->caseFirst, { "upper", "lower", "false" }, "caseFirst must be either \"upper\", \"lower\", or \"false\"", nullptr);
        RETURN_IF_EXCEPTION(scope, void());
        opt.add(ASCIILiteral("kf"), caseFirst);
    }

    // 17. Let relevantExtensionKeys be the value of %Collator%.[[relevantExtensionKeys]].
    // 18. Let r be ResolveLocale(%Collator%.[[availableLocales]], requestedLocales, opt, relevantExtensionKeys, localeData).
    auto& availableLocales = state.callee()->globalObject()->intlCollatorAvailableLocales();
    auto result = resolveLocale(state, availableLocales, requestedLocales, opt, relevantExtensionKeys, WTF_ARRAY_LENGTH(relevantExtensionKeys), localeData);

    // 19. Set collator.[[locale]] to the value of r.[[locale]].
    m_locale = result.get(ASCIILiteral("locale"));
    if (m_locale.isEmpty()) {
        throwTypeError(&state, scope, ASCIILiteral("failed to initialize Collator due to invalid locale"));
        return;
    }

    // 20. Let k be 0.
    // 21. Let lenValue be Get(relevantExtensionKeys, "length").
    // 22. Let len be ToLength(lenValue).
    // 23. Repeat while k < len:
    // a. Let Pk be ToString(k).
    // b. Let key be Get(relevantExtensionKeys, Pk).
    // c. ReturnIfAbrupt(key).
    // d. If key is "co", then
    //    i. Let property be "collation".
    //    ii. Let value be the value of r.[[co]].
    //    iii. If value is null, let value be "default".
    // e. Else use the row of Table 1 that contains the value of key in the Key column:
    //    i. Let property be the name given in the Property column of the row.
    //    ii. Let value be the value of r.[[<key>]].
    //    iii. If the name given in the Type column of the row is "boolean", let value be the result of comparing value with "true".
    // f. Set collator.[[<property>]] to value.
    // g. Increase k by 1.
    const String& collation = result.get(ASCIILiteral("co"));
    m_collation = collation.isNull() ? ASCIILiteral("default") : collation;
    m_numeric = (result.get(ASCIILiteral("kn")) == "true");

    // 24. Let s be GetOption(options, "sensitivity", "string", «"base", "accent", "case", "variant"», undefined).
    String sensitivityString = intlStringOption(state, options, vm.propertyNames->sensitivity, { "base", "accent", "case", "variant" }, "sensitivity must be either \"base\", \"accent\", \"case\", or \"variant\"", nullptr);
    // 25. ReturnIfAbrupt(s).
    RETURN_IF_EXCEPTION(scope, void());
    // 26. If s is undefined, then
    // a. If u is "sort", then let s be "variant".
    // b. Else
    //    i. Let dataLocale be the value of r.[[dataLocale]].
    //    ii. Let dataLocaleData be Get(localeData, dataLocale).
    //    iii. Let s be Get(dataLocaleData, "sensitivity").
    //    10.2.3 "[[searchLocaleData]][locale] must have a sensitivity property with a String value equal to "base", "accent", "case", or "variant" for all locale values."
    // 27. Set collator.[[sensitivity]] to s.
    if (sensitivityString == "base")
        m_sensitivity = Sensitivity::Base;
    else if (sensitivityString == "accent")
        m_sensitivity = Sensitivity::Accent;
    else if (sensitivityString == "case")
        m_sensitivity = Sensitivity::Case;
    else
        m_sensitivity = Sensitivity::Variant;

    // 28. Let ip be GetOption(options, "ignorePunctuation", "boolean", undefined, false).
    bool usesFallback;
    bool ignorePunctuation = intlBooleanOption(state, options, vm.propertyNames->ignorePunctuation, usesFallback);
    if (usesFallback)
        ignorePunctuation = false;
    // 29. ReturnIfAbrupt(ip).
    RETURN_IF_EXCEPTION(scope, void());
    // 30. Set collator.[[ignorePunctuation]] to ip.
    m_ignorePunctuation = ignorePunctuation;

    // 31. Set collator.[[boundCompare]] to undefined.
    // 32. Set collator.[[initializedCollator]] to true.
    m_initializedCollator = true;

    // 33. Return collator.
}
static bool reject(ExecState* exec, bool throwException, const char* message)
{
    if (throwException)
        throwTypeError(exec, ASCIILiteral(message));
    return false;
}
Пример #28
0
JSObject *
GlobalObject::initFunctionAndObjectClasses(JSContext *cx)
{
    Rooted<GlobalObject*> self(cx, this);

    JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
    JS_ASSERT(isNative());

    /*
     * Calling a function from a cleared global triggers this (yeah, I know).
     * Uncomment this once bug 470510 is fixed (if that bug doesn't remove
     * isCleared entirely).
     */
    // JS_ASSERT(!isCleared());

    /* If cx has no global object, make this the global object. */
    if (!cx->globalObject)
        JS_SetGlobalObject(cx, self);

    RootedObject objectProto(cx);

    /*
     * Create |Object.prototype| first, mirroring CreateBlankProto but for the
     * prototype of the created object.
     */
    objectProto = NewObjectWithGivenProto(cx, &ObjectClass, NULL, self);
    if (!objectProto || !objectProto->setSingletonType(cx))
        return NULL;

    /*
     * The default 'new' type of Object.prototype is required by type inference
     * to have unknown properties, to simplify handling of e.g. heterogenous
     * objects in JSON and script literals.
     */
    if (!objectProto->setNewTypeUnknown(cx))
        return NULL;

    /* Create |Function.prototype| next so we can create other functions. */
    RootedFunction functionProto(cx);
    {
        JSObject *functionProto_ = NewObjectWithGivenProto(cx, &FunctionClass, objectProto, self);
        if (!functionProto_)
            return NULL;
        functionProto = functionProto_->toFunction();

        /*
         * Bizarrely, |Function.prototype| must be an interpreted function, so
         * give it the guts to be one.
         */
        JSObject *proto = js_NewFunction(cx, functionProto,
                                         NULL, 0, JSFUN_INTERPRETED, self, NULL);
        if (!proto)
            return NULL;
        JS_ASSERT(proto == functionProto);
        functionProto->flags |= JSFUN_PROTOTYPE;

        const char *rawSource = "() {\n}";
        size_t sourceLen = strlen(rawSource);
        jschar *source = InflateString(cx, rawSource, &sourceLen);
        if (!source)
            return NULL;
        ScriptSource *ss = cx->new_<ScriptSource>();
        if (!ss) {
            cx->free_(source);
            return NULL;
        }
        ScriptSourceHolder ssh(cx->runtime, ss);
        ss->setSource(source, sourceLen);

        CompileOptions options(cx);
        options.setNoScriptRval(true)
               .setVersion(JSVERSION_DEFAULT);
        Rooted<JSScript*> script(cx, JSScript::Create(cx,
                                                      /* enclosingScope = */ NullPtr(),
                                                      /* savedCallerFun = */ false,
                                                      options,
                                                      /* staticLevel = */ 0,
                                                      ss,
                                                      0,
                                                      ss->length()));
        if (!script || !JSScript::fullyInitTrivial(cx, script))
            return NULL;

        functionProto->initScript(script);
        functionProto->getType(cx)->interpretedFunction = functionProto;
        script->setFunction(functionProto);

        if (!functionProto->setSingletonType(cx))
            return NULL;

        /*
         * The default 'new' type of Function.prototype is required by type
         * inference to have unknown properties, to simplify handling of e.g.
         * CloneFunctionObject.
         */
        if (!functionProto->setNewTypeUnknown(cx))
            return NULL;
    }

    /* Create the Object function now that we have a [[Prototype]] for it. */
    RootedFunction objectCtor(cx);
    {
        JSObject *ctor = NewObjectWithGivenProto(cx, &FunctionClass, functionProto, self);
        if (!ctor)
            return NULL;
        objectCtor = js_NewFunction(cx, ctor, js_Object, 1, JSFUN_CONSTRUCTOR, self,
                                    CLASS_NAME(cx, Object));
        if (!objectCtor)
            return NULL;
    }

    /*
     * Install |Object| and |Object.prototype| for the benefit of subsequent
     * code that looks for them.
     */
    self->setObjectClassDetails(objectCtor, objectProto);

    /* Create |Function| so it and |Function.prototype| can be installed. */
    RootedFunction functionCtor(cx);
    {
        // Note that ctor is rooted purely for the JS_ASSERT at the end
        RootedObject ctor(cx, NewObjectWithGivenProto(cx, &FunctionClass, functionProto, self));
        if (!ctor)
            return NULL;
        functionCtor = js_NewFunction(cx, ctor, Function, 1, JSFUN_CONSTRUCTOR, self,
                                      CLASS_NAME(cx, Function));
        if (!functionCtor)
            return NULL;
        JS_ASSERT(ctor == functionCtor);
    }

    /*
     * Install |Function| and |Function.prototype| so that we can freely create
     * functions and objects without special effort.
     */
    self->setFunctionClassDetails(functionCtor, functionProto);

    /*
     * The hard part's done: now go back and add all the properties these
     * primordial values have.
     */
    if (!LinkConstructorAndPrototype(cx, objectCtor, objectProto) ||
        !DefinePropertiesAndBrand(cx, objectProto, NULL, object_methods))
    {
        return NULL;
    }

    /*
     * Add an Object.prototype.__proto__ accessor property to implement that
     * extension (if it's actually enabled).  Cache the getter for this
     * function so that cross-compartment [[Prototype]]-getting is implemented
     * in one place.
     */
    Rooted<JSFunction*> getter(cx, js_NewFunction(cx, NULL, ProtoGetter, 0, 0, self, NULL));
    if (!getter)
        return NULL;
#if JS_HAS_OBJ_PROTO_PROP
    Rooted<JSFunction*> setter(cx, js_NewFunction(cx, NULL, ProtoSetter, 0, 0, self, NULL));
    if (!setter)
        return NULL;
    RootedValue undefinedValue(cx, UndefinedValue());
    if (!objectProto->defineProperty(cx, cx->runtime->atomState.protoAtom, undefinedValue,
                                     JS_DATA_TO_FUNC_PTR(PropertyOp, getter.get()),
                                     JS_DATA_TO_FUNC_PTR(StrictPropertyOp, setter.get()),
                                     JSPROP_GETTER | JSPROP_SETTER | JSPROP_SHARED))
    {
        return NULL;
    }
#endif /* JS_HAS_OBJ_PROTO_PROP */
    self->setProtoGetter(getter);


    if (!DefinePropertiesAndBrand(cx, objectCtor, NULL, object_static_methods) ||
        !LinkConstructorAndPrototype(cx, functionCtor, functionProto) ||
        !DefinePropertiesAndBrand(cx, functionProto, NULL, function_methods) ||
        !DefinePropertiesAndBrand(cx, functionCtor, NULL, NULL))
    {
        return NULL;
    }

    /* Add the global Function and Object properties now. */
    jsid objectId = NameToId(CLASS_NAME(cx, Object));
    if (!self->addDataProperty(cx, objectId, JSProto_Object + JSProto_LIMIT * 2, 0))
        return NULL;
    jsid functionId = NameToId(CLASS_NAME(cx, Function));
    if (!self->addDataProperty(cx, functionId, JSProto_Function + JSProto_LIMIT * 2, 0))
        return NULL;

    /* Heavy lifting done, but lingering tasks remain. */

    /* ES5 15.1.2.1. */
    RootedId id(cx, NameToId(cx->runtime->atomState.evalAtom));
    JSObject *evalobj = js_DefineFunction(cx, self, id, IndirectEval, 1, JSFUN_STUB_GSOPS);
    if (!evalobj)
        return NULL;
    self->setOriginalEval(evalobj);

    /* ES5 13.2.3: Construct the unique [[ThrowTypeError]] function object. */
    RootedFunction throwTypeError(cx, js_NewFunction(cx, NULL, ThrowTypeError, 0, 0, self, NULL));
    if (!throwTypeError)
        return NULL;
    if (!throwTypeError->preventExtensions(cx))
        return NULL;
    self->setThrowTypeError(throwTypeError);

    RootedObject intrinsicsHolder(cx, JS_NewObject(cx, NULL, NULL, self));
    if (!intrinsicsHolder)
        return NULL;
    self->setIntrinsicsHolder(intrinsicsHolder);
    if (!JS_DefineFunctions(cx, intrinsicsHolder, intrinsic_functions))
        return NULL;

    /*
     * The global object should have |Object.prototype| as its [[Prototype]].
     * Eventually we'd like to have standard classes be there from the start,
     * and thus we would know we were always setting what had previously been a
     * null [[Prototype]], but right now some code assumes it can set the
     * [[Prototype]] before standard classes have been initialized.  For now,
     * only set the [[Prototype]] if it hasn't already been set.
     */
    if (self->shouldSplicePrototype(cx) && !self->splicePrototype(cx, objectProto))
        return NULL;

    /*
     * Notify any debuggers about the creation of the script for
     * |Function.prototype| -- after all initialization, for simplicity.
     */
    js_CallNewScriptHook(cx, functionProto->script(), functionProto);
    return functionProto;
}
Пример #29
0
JSValue JSSubtleCrypto::unwrapKey(ExecState* exec)
{
    if (exec->argumentCount() < 5)
        return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));

    CryptoKeyFormat keyFormat;
    if (!cryptoKeyFormatFromJSValue(exec, exec->argument(0), keyFormat)) {
        ASSERT(exec->hadException());
        return jsUndefined();
    }

    CryptoOperationData wrappedKeyData;
    if (!cryptoOperationDataFromJSValue(exec, exec->uncheckedArgument(1), wrappedKeyData)) {
        ASSERT(exec->hadException());
        return jsUndefined();
    }

    RefPtr<CryptoKey> unwrappingKey = JSCryptoKey::toWrapped(exec->uncheckedArgument(2));
    if (!unwrappingKey)
        return throwTypeError(exec);

    if (!unwrappingKey->allows(CryptoKeyUsageUnwrapKey)) {
        m_impl->document()->addConsoleMessage(MessageSource::JS, MessageLevel::Error, ASCIILiteral("Key usages do not include 'unwrapKey'"));
        setDOMException(exec, NOT_SUPPORTED_ERR);
        return jsUndefined();
    }

    std::unique_ptr<CryptoAlgorithm> unwrapAlgorithm;
    std::unique_ptr<CryptoAlgorithmParameters> unwrapAlgorithmParameters;
    unwrapAlgorithm = createAlgorithmFromJSValue(exec, exec->uncheckedArgument(3));
    if (!unwrapAlgorithm) {
        ASSERT(exec->hadException());
        return jsUndefined();
    }
    unwrapAlgorithmParameters = JSCryptoAlgorithmDictionary::createParametersForDecrypt(exec, unwrapAlgorithm->identifier(), exec->uncheckedArgument(3));
    if (!unwrapAlgorithmParameters) {
        ASSERT(exec->hadException());
        return jsUndefined();
    }

    std::unique_ptr<CryptoAlgorithm> unwrappedKeyAlgorithm;
    std::unique_ptr<CryptoAlgorithmParameters> unwrappedKeyAlgorithmParameters;
    if (!exec->uncheckedArgument(4).isNull()) {
        unwrappedKeyAlgorithm = createAlgorithmFromJSValue(exec, exec->uncheckedArgument(4));
        if (!unwrappedKeyAlgorithm) {
            ASSERT(exec->hadException());
            return jsUndefined();
        }
        unwrappedKeyAlgorithmParameters = JSCryptoAlgorithmDictionary::createParametersForImportKey(exec, unwrappedKeyAlgorithm->identifier(), exec->uncheckedArgument(4));
        if (!unwrappedKeyAlgorithmParameters) {
            ASSERT(exec->hadException());
            return jsUndefined();
        }
    }

    bool extractable = false;
    if (exec->argumentCount() >= 6) {
        extractable = exec->uncheckedArgument(5).toBoolean(exec);
        if (exec->hadException())
            return jsUndefined();
    }

    CryptoKeyUsage keyUsages = 0;
    if (exec->argumentCount() >= 7) {
        if (!cryptoKeyUsagesFromJSValue(exec, exec->argument(6), keyUsages)) {
            ASSERT(exec->hadException());
            return jsUndefined();
        }
    }

    JSPromiseDeferred* promiseDeferred = JSPromiseDeferred::create(exec, globalObject());
    DeferredWrapper wrapper(exec, globalObject(), promiseDeferred);
    Strong<JSDOMGlobalObject> domGlobalObject(exec->vm(), globalObject());

    CryptoAlgorithm* unwrappedKeyAlgorithmPtr = unwrappedKeyAlgorithm.release();
    CryptoAlgorithmParameters* unwrappedKeyAlgorithmParametersPtr = unwrappedKeyAlgorithmParameters.release();

    auto decryptSuccessCallback = [domGlobalObject, keyFormat, unwrappedKeyAlgorithmPtr, unwrappedKeyAlgorithmParametersPtr, extractable, keyUsages, wrapper](const Vector<uint8_t>& result) mutable {
        auto importSuccessCallback = [wrapper](CryptoKey& key) mutable {
            wrapper.resolve(&key);
        };
        auto importFailureCallback = [wrapper]() mutable {
            wrapper.reject(nullptr);
        };
        ExecState* exec = domGlobalObject->globalExec();
        WebCore::importKey(exec, keyFormat, std::make_pair(result.data(), result.size()), std::unique_ptr<CryptoAlgorithm>(unwrappedKeyAlgorithmPtr), std::unique_ptr<CryptoAlgorithmParameters>(unwrappedKeyAlgorithmParametersPtr), extractable, keyUsages, WTF::move(importSuccessCallback), WTF::move(importFailureCallback));
        if (exec->hadException()) {
            // FIXME: Report exception details to console, and possibly to calling script once there is a standardized way to pass errors to WebCrypto promise reject functions.
            exec->clearException();
            importFailureCallback();
        }
    };

    auto decryptFailureCallback = [wrapper, unwrappedKeyAlgorithmPtr, unwrappedKeyAlgorithmParametersPtr]() mutable {
        delete unwrappedKeyAlgorithmPtr;
        delete unwrappedKeyAlgorithmParametersPtr;
        wrapper.reject(nullptr);
    };

    ExceptionCode ec = 0;
    unwrapAlgorithm->decryptForUnwrapKey(*unwrapAlgorithmParameters, *unwrappingKey, wrappedKeyData, WTF::move(decryptSuccessCallback), WTF::move(decryptFailureCallback), ec);
    if (ec) {
        delete unwrappedKeyAlgorithmPtr;
        delete unwrappedKeyAlgorithmParametersPtr;
        setDOMException(exec, ec);
        return jsUndefined();
    }

    return promiseDeferred->promise();
}
static EncodedJSValue JSC_HOST_CALL promiseResolutionHandlerFunction(ExecState* exec)
{
    JSValue x = exec->argument(0);
    VM& vm = exec->vm();
    JSObject* F = exec->callee();

    // 1. Let 'promise' be the value of F's [[Promise]] internal slot
    JSPromise* promise = jsCast<JSPromise*>(F->get(exec, vm.propertyNames->promisePrivateName));

    // 2. Let 'fulfillmentHandler' be the value of F's [[FulfillmentHandler]] internal slot.
    JSValue fulfillmentHandler = F->get(exec, vm.propertyNames->fulfillmentHandlerPrivateName);
    
    // 3. Let 'rejectionHandler' be the value of F's [[RejectionHandler]] internal slot.
    JSValue rejectionHandler = F->get(exec, vm.propertyNames->rejectionHandlerPrivateName);
    
    // 4. If SameValue(x, promise) is true,
    if (sameValue(exec, x, promise)) {
        // i. Let 'selfResolutionError' be a newly-created TypeError object.
        JSObject* selfResolutionError = createTypeError(exec, ASCIILiteral("Resolve a promise with itself"));
        // ii. Return the result of calling the [[Call]] internal method of rejectionHandler with
        //     undefined as thisArgument and a List containing selfResolutionError as argumentsList.
        CallData rejectCallData;
        CallType rejectCallType = getCallData(rejectionHandler, rejectCallData);
        ASSERT(rejectCallType != CallTypeNone);

        MarkedArgumentBuffer rejectArguments;
        rejectArguments.append(selfResolutionError);

        return JSValue::encode(call(exec, rejectionHandler, rejectCallType, rejectCallData, jsUndefined(), rejectArguments));
    }

    // 5. Let 'C' be the value of promise's [[PromiseConstructor]] internal slot.
    JSValue C = promise->constructor();

    // 6. Let 'deferred' be the result of calling GetDeferred(C)
    JSValue deferredValue = createJSPromiseDeferredFromConstructor(exec, C);

    // 7. ReturnIfAbrupt(deferred).
    if (exec->hadException())
        return JSValue::encode(jsUndefined());

    JSPromiseDeferred* deferred = jsCast<JSPromiseDeferred*>(deferredValue);

    // 8. Let 'updateResult' be the result of calling UpdateDeferredFromPotentialThenable(x, deferred).
    ThenableStatus updateResult = updateDeferredFromPotentialThenable(exec, x, deferred);

    // 9. ReturnIfAbrupt(updateResult).
    if (exec->hadException())
        return JSValue::encode(jsUndefined());

    // 10. If 'updateResult' is not "not a thenable", return the result of calling
    //     Invoke(deferred.[[Promise]], "then", (fulfillmentHandler, rejectionHandler)).
    // NOTE: Invoke does not seem to be defined anywhere, so I am guessing here.
    if (updateResult != NotAThenable) {
        JSObject* deferredPromise = deferred->promise();
    
        JSValue thenValue = deferredPromise->get(exec, exec->vm().propertyNames->then);
        if (exec->hadException())
            return JSValue::encode(jsUndefined());

        CallData thenCallData;
        CallType thenCallType = getCallData(thenValue, thenCallData);
        if (thenCallType == CallTypeNone)
            return JSValue::encode(throwTypeError(exec));

        MarkedArgumentBuffer arguments;
        arguments.append(fulfillmentHandler);
        arguments.append(rejectionHandler);

        return JSValue::encode(call(exec, thenValue, thenCallType, thenCallData, deferredPromise, arguments));
    }
    
    // 11. Return the result of calling the [[Call]] internal method of fulfillmentHandler
    //     with undefined as thisArgument and a List containing x as argumentsList.
    CallData fulfillmentHandlerCallData;
    CallType fulfillmentHandlerCallType = getCallData(fulfillmentHandler, fulfillmentHandlerCallData);
    ASSERT(fulfillmentHandlerCallType != CallTypeNone);
    
    MarkedArgumentBuffer fulfillmentHandlerArguments;
    fulfillmentHandlerArguments.append(x);

    return JSValue::encode(call(exec, fulfillmentHandler, fulfillmentHandlerCallType, fulfillmentHandlerCallData, jsUndefined(), fulfillmentHandlerArguments));
}