Пример #1
0
JSValue JSXMLHttpRequest::send(ExecState* exec)
{
    InspectorInstrumentation::willSendXMLHttpRequest(impl().scriptExecutionContext(), impl().url());

    ExceptionCode ec = 0;
    JSValue val = exec->argument(0);
    if (val.isUndefinedOrNull())
        impl().send(ec);
    else if (val.inherits(JSDocument::info()))
        impl().send(toDocument(val), ec);
    else if (val.inherits(JSBlob::info()))
        impl().send(toBlob(val), ec);
    else if (val.inherits(JSDOMFormData::info()))
        impl().send(toDOMFormData(val), ec);
    else if (val.inherits(JSArrayBuffer::info()))
        impl().send(toArrayBuffer(val), ec);
    else if (val.inherits(JSArrayBufferView::info())) {
        RefPtr<ArrayBufferView> view = toArrayBufferView(val);
        impl().send(view.get(), ec);
    } else
        impl().send(val.toString(exec)->value(exec), ec);

    SendFunctor functor;
    exec->iterate(functor);
    impl().setLastSendLineNumber(functor.line());
    impl().setLastSendURL(functor.url());
    setDOMException(exec, ec);
    return jsUndefined();
}
JSValue JSWebSocket::send(ExecState* exec)
{
    if (!exec->argumentCount())
        return throwError(exec, createSyntaxError(exec, "Not enough arguments"));

    JSValue message = exec->argument(0);
    ExceptionCode ec = 0;
    bool result;
    if (message.inherits(&JSArrayBuffer::s_info))
        result = impl()->send(toArrayBuffer(message), ec);
    else if (message.inherits(&JSBlob::s_info))
        result = impl()->send(toBlob(message), ec);
    else {
        String stringMessage = ustringToString(message.toString(exec)->value(exec));
        if (exec->hadException())
            return jsUndefined();
        result = impl()->send(stringMessage, ec);
    }
    if (ec) {
        setDOMException(exec, ec);
        return jsUndefined();
    }

    return jsBoolean(result);
}
JSValue JSXMLHttpRequest::send(ExecState& state)
{
    InspectorInstrumentation::willSendXMLHttpRequest(wrapped().scriptExecutionContext(), wrapped().url());

    ExceptionCode ec = 0;
    JSValue val = state.argument(0);
    if (val.isUndefinedOrNull())
        wrapped().send(ec);
    else if (val.inherits(JSDocument::info()))
        wrapped().send(JSDocument::toWrapped(val), ec);
    else if (val.inherits(JSBlob::info()))
        wrapped().send(JSBlob::toWrapped(val), ec);
    else if (val.inherits(JSDOMFormData::info()))
        wrapped().send(JSDOMFormData::toWrapped(val), ec);
    else if (val.inherits(JSArrayBuffer::info()))
        wrapped().send(toArrayBuffer(val), ec);
    else if (val.inherits(JSArrayBufferView::info())) {
        RefPtr<ArrayBufferView> view = toArrayBufferView(val);
        wrapped().send(view.get(), ec);
    } else
        wrapped().send(val.toString(&state)->value(&state), ec);

    // FIXME: This should probably use ShadowChicken so that we get the right frame even when it did
    // a tail call.
    // https://bugs.webkit.org/show_bug.cgi?id=155688
    SendFunctor functor;
    state.iterate(functor);
    wrapped().setLastSendLineAndColumnNumber(functor.line(), functor.column());
    wrapped().setLastSendURL(functor.url());
    setDOMException(&state, ec);
    return jsUndefined();
}
JSValue JSXMLHttpRequest::send(ExecState* exec)
{
    InspectorInstrumentation::willSendXMLHttpRequest(impl()->scriptExecutionContext(), impl()->url());

    ExceptionCode ec = 0;
    if (!exec->argumentCount())
        impl()->send(ec);
    else {
        JSValue val = exec->argument(0);
        if (val.isUndefinedOrNull())
            impl()->send(ec);
        else if (val.inherits(&JSDocument::s_info))
            impl()->send(toDocument(val), ec);
        else if (val.inherits(&JSBlob::s_info))
            impl()->send(toBlob(val), ec);
        else if (val.inherits(&JSDOMFormData::s_info))
            impl()->send(toDOMFormData(val), ec);
        else if (val.inherits(&JSArrayBuffer::s_info))
            impl()->send(toArrayBuffer(val), ec);
        else
            impl()->send(ustringToString(val.toString(exec)->value(exec)), ec);
    }

    int signedLineNumber;
    intptr_t sourceID;
    UString sourceURL;
    JSValue function;
    exec->interpreter()->retrieveLastCaller(exec, signedLineNumber, sourceID, sourceURL, function);
    impl()->setLastSendLineNumber(signedLineNumber >= 0 ? signedLineNumber : 0);
    impl()->setLastSendURL(ustringToString(sourceURL));

    setDOMException(exec, ec);
    return jsUndefined();
}
Пример #5
0
EncodedJSValue JSC_HOST_CALL constructJSDataCue(ExecState* exec)
{
    DOMConstructorObject* castedThis = jsCast<DOMConstructorObject*>(exec->callee());
    if (exec->argumentCount() < 3)
        return throwVMError(exec, createNotEnoughArgumentsError(exec));

    ExceptionCode ec = 0;
    double startTime(exec->argument(0).toNumber(exec));
    if (UNLIKELY(exec->hadException()))
        return JSValue::encode(jsUndefined());

    double endTime(exec->argument(1).toNumber(exec));
    if (UNLIKELY(exec->hadException()))
        return JSValue::encode(jsUndefined());

    ScriptExecutionContext* context = castedThis->scriptExecutionContext();
    if (!context)
        return throwConstructorDocumentUnavailableError(*exec, "DataCue");

    String type;
#if ENABLE(DATACUE_VALUE)
    if (exec->argumentCount() > 3) {
        if (!exec->argument(3).isString())
            return throwVMError(exec, createTypeError(exec, "Second argument of the constructor is not of type String"));
        type = exec->argument(3).getString(exec);
    }
#endif

    JSValue valueArgument = exec->argument(2);
    if (valueArgument.isUndefinedOrNull()) {
        setDOMException(exec, TypeError);
        return JSValue::encode(JSValue());
    }

    RefPtr<DataCue> object;
    if (valueArgument.isCell() && valueArgument.asCell()->inherits(std::remove_pointer<JSArrayBuffer*>::type::info())) {

        ArrayBuffer* data(toArrayBuffer(valueArgument));
        if (UNLIKELY(exec->hadException()))
            return JSValue::encode(jsUndefined());

        object = DataCue::create(*context, startTime, endTime, data, type, ec);
        if (ec) {
            setDOMException(exec, ec);
            return JSValue::encode(JSValue());
        }

        return JSValue::encode(asObject(toJS(exec, castedThis->globalObject(), object.get())));
    }

#if !ENABLE(DATACUE_VALUE)
    return JSValue::encode(jsUndefined());
#else
    object = DataCue::create(*context, startTime, endTime, valueArgument, type);
    return JSValue::encode(asObject(toJS(exec, castedThis->globalObject(), object.get())));
#endif
}
Пример #6
0
EncodedJSValue JSC_HOST_CALL structuredCloneArrayBuffer(ExecState* execState)
{
    ASSERT(execState);
    ASSERT(execState->argumentCount());
    ASSERT(execState->lexicalGlobalObject());

    ArrayBuffer* buffer = toArrayBuffer(execState->uncheckedArgument(0));
    if (!buffer) {
        setDOMException(execState, DATA_CLONE_ERR);
        return JSValue::encode(jsUndefined());
    }

    return JSValue::encode(JSArrayBuffer::create(execState->vm(), execState->lexicalGlobalObject()->arrayBufferStructure(), ArrayBuffer::tryCreate(buffer->data(), buffer->byteLength())));
}
void fillMessagePortArray(JSC::ExecState* exec, JSC::JSValue value, MessagePortArray& portArray, ArrayBufferArray& arrayBuffers)
{
    // Convert from the passed-in JS array-like object to a MessagePortArray.
    // Also validates the elements per sections 4.1.13 and 4.1.15 of the WebIDL spec and section 8.3.3 of the HTML5 spec.
    if (value.isUndefinedOrNull()) {
        portArray.resize(0);
        arrayBuffers.resize(0);
        return;
    }

    // Validation of sequence types, per WebIDL spec 4.1.13.
    unsigned length = 0;
    JSObject* object = toJSSequence(exec, value, length);
    if (exec->hadException())
        return;

    for (unsigned i = 0 ; i < length; ++i) {
        JSValue value = object->get(exec, i);
        if (exec->hadException())
            return;
        // Validation of non-null objects, per HTML5 spec 10.3.3.
        if (value.isUndefinedOrNull()) {
            setDOMException(exec, INVALID_STATE_ERR);
            return;
        }

        // Validation of Objects implementing an interface, per WebIDL spec 4.1.15.
        RefPtr<MessagePort> port = toMessagePort(value);
        if (port) {
            // Check for duplicate ports.
            if (portArray.contains(port)) {
#if MODIFY(ENGINE) //[2014.03.05][infraware][jungong16] : fix to issue. http://www.w3.org/TR/webmessaging/#dom-window-postmessage
                setDOMException(exec, DATA_CLONE_ERR);
#else
                setDOMException(exec, INVALID_STATE_ERR);
#endif
                return;
            }
            portArray.append(port.release());
        } else {
            RefPtr<ArrayBuffer> arrayBuffer = toArrayBuffer(value);
            if (arrayBuffer)
                arrayBuffers.append(arrayBuffer);
            else {
                throwTypeError(exec);
                return;
            }
        }
    }
}
JSValue JSAudioContext::createBuffer(ExecState* exec)
{
    if (exec->argumentCount() < 2)
        return throwError(exec, createSyntaxError(exec, "Not enough arguments"));

    AudioContext* audioContext = static_cast<AudioContext*>(impl());
    ASSERT(audioContext);

    // AudioBuffer createBuffer(in ArrayBuffer buffer, in boolean mixToMono);
    JSValue val = exec->argument(0);
    if (val.inherits(&JSArrayBuffer::s_info)) {
        ArrayBuffer* arrayBuffer = toArrayBuffer(val);
        ASSERT(arrayBuffer);
        if (arrayBuffer) {
            bool mixToMono = exec->argument(1).toBoolean(exec);

            RefPtr<AudioBuffer> audioBuffer = audioContext->createBuffer(arrayBuffer, mixToMono);
            if (!audioBuffer.get())
                return throwError(exec, createSyntaxError(exec, "Error decoding audio file data"));

            return toJS(exec, globalObject(), audioBuffer.get());
        }

        return jsUndefined();
    }
    
    // AudioBuffer createBuffer(in unsigned long numberOfChannels, in unsigned long numberOfFrames, in float sampleRate);
    if (exec->argumentCount() < 3)
        return throwError(exec, createSyntaxError(exec, "Not enough arguments"));
    
    int32_t numberOfChannels = exec->argument(0).toInt32(exec);
    int32_t numberOfFrames = exec->argument(1).toInt32(exec);
    float sampleRate = exec->argument(2).toFloat(exec);

    if (numberOfChannels <= 0 || numberOfChannels > 10)
        return throwError(exec, createSyntaxError(exec, "Invalid number of channels"));

    if (numberOfFrames <= 0)
        return throwError(exec, createSyntaxError(exec, "Invalid number of frames"));

    if (sampleRate <= 0)
        return throwError(exec, createSyntaxError(exec, "Invalid sample rate"));

    RefPtr<AudioBuffer> audioBuffer = audioContext->createBuffer(numberOfChannels, numberOfFrames, sampleRate);
    if (!audioBuffer.get())
        return throwError(exec, createSyntaxError(exec, "Error creating AudioBuffer"));

    return toJS(exec, globalObject(), audioBuffer.get());
}
void fillMessagePortArray(JSC::ExecState* exec, JSC::JSValue value, MessagePortArray& portArray, ArrayBufferArray& arrayBuffers)
{
    // Convert from the passed-in JS array-like object to a MessagePortArray.
    // Also validates the elements per sections 4.1.13 and 4.1.15 of the WebIDL spec and section 8.3.3 of the HTML5 spec.
    if (value.isUndefinedOrNull()) {
        portArray.resize(0);
        arrayBuffers.resize(0);
        return;
    }

    // Validation of sequence types, per WebIDL spec 4.1.13.
    unsigned length = 0;
    JSObject* object = toJSSequence(exec, value, length);
    if (exec->hadException())
        return;

    for (unsigned i = 0 ; i < length; ++i) {
        JSValue value = object->get(exec, i);
        if (exec->hadException())
            return;
        // Validation of non-null objects, per HTML5 spec 10.3.3.
        if (value.isUndefinedOrNull()) {
            setDOMException(exec, INVALID_STATE_ERR);
            return;
        }

        // Validation of Objects implementing an interface, per WebIDL spec 4.1.15.
        RefPtr<MessagePort> port = JSMessagePort::toWrapped(value);
        if (port) {
            // Check for duplicate ports.
            if (portArray.contains(port)) {
                setDOMException(exec, INVALID_STATE_ERR);
                return;
            }
            portArray.append(port.release());
        } else {
            RefPtr<ArrayBuffer> arrayBuffer = toArrayBuffer(value);
            if (arrayBuffer)
                arrayBuffers.append(arrayBuffer);
            else {
                throwTypeError(exec);
                return;
            }
        }
    }
}
Пример #10
0
EncodedJSValue JSC_HOST_CALL JSBlobConstructor::constructJSBlob(ExecState* exec)
{
    JSBlobConstructor* jsConstructor = jsCast<JSBlobConstructor*>(exec->callee());
    ScriptExecutionContext* context = jsConstructor->scriptExecutionContext();
    if (!context)
        return throwVMError(exec, createReferenceError(exec, "Blob constructor associated document is unavailable"));

    if (!exec->argumentCount()) {
        RefPtr<Blob> blob = Blob::create();
        return JSValue::encode(CREATE_DOM_WRAPPER(exec, jsConstructor->globalObject(), Blob, blob.get()));
    }

    JSValue firstArg = exec->argument(0);
    if (!isJSArray(firstArg))
        return throwVMError(exec, createTypeError(exec, "First argument of the constructor is not of type Array"));

    String type;
    String endings = "transparent";

    if (exec->argumentCount() > 1) {
        JSValue blobPropertyBagValue = exec->argument(1);

        if (!blobPropertyBagValue.isObject())
            return throwVMError(exec, createTypeError(exec, "Second argument of the constructor is not of type Object"));

        // Given the above test, this will always yield an object.
        JSObject* blobPropertyBagObject = blobPropertyBagValue.toObject(exec);

        // Create the dictionary wrapper from the initializer object.
        JSDictionary dictionary(exec, blobPropertyBagObject);

        // Attempt to get the endings property and validate it.
        bool containsEndings = dictionary.get("endings", endings);
        if (exec->hadException())
            return JSValue::encode(jsUndefined());

        if (containsEndings) {
            if (endings != "transparent" && endings != "native")
                return throwVMError(exec, createTypeError(exec, "The endings property must be either \"transparent\" or \"native\""));
        }

        // Attempt to get the type property.
        dictionary.get("type", type);
        if (exec->hadException())
            return JSValue::encode(jsUndefined());
    }

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

    // FIXME: this would be better if the WebKitBlobBuilder were a stack object to avoid the allocation.
    RefPtr<WebKitBlobBuilder> blobBuilder = WebKitBlobBuilder::create();

    JSArray* array = asArray(firstArg);
    unsigned length = array->length();

    for (unsigned i = 0; i < length; ++i) {
        JSValue item = array->getIndex(i);
#if ENABLE(BLOB)
        if (item.inherits(&JSArrayBuffer::s_info))
            blobBuilder->append(toArrayBuffer(item));
        else
#endif
        if (item.inherits(&JSBlob::s_info))
            blobBuilder->append(toBlob(item));
        else {
            String string = ustringToString(item.toString(exec)->value(exec));
            if (exec->hadException())
                return JSValue::encode(jsUndefined());
            blobBuilder->append(string, endings, ASSERT_NO_EXCEPTION);
        }
    }

    RefPtr<Blob> blob = blobBuilder->getBlob(type);
    return JSValue::encode(CREATE_DOM_WRAPPER(exec, jsConstructor->globalObject(), Blob, blob.get()));
}
Пример #11
0
EncodedJSValue JSC_HOST_CALL constructJSFile(ExecState& exec)
{
    auto* constructor = jsCast<DOMConstructorObject*>(exec.callee());
    ScriptExecutionContext* context = constructor->scriptExecutionContext();
    if (!context)
        return throwVMError(&exec, createReferenceError(&exec, "File constructor associated document is unavailable"));

    JSValue arg = exec.argument(0);
    if (arg.isUndefinedOrNull())
        return throwVMTypeError(&exec, ASCIILiteral("First argument to File constructor must be a valid sequence, was undefined or null"));

    unsigned blobPartsLength = 0;
    JSObject* blobParts = toJSSequence(exec, arg, blobPartsLength);
    if (exec.hadException())
        return JSValue::encode(jsUndefined());
    ASSERT(blobParts);

    arg = exec.argument(1);
    if (arg.isUndefined())
        return throwVMTypeError(&exec, ASCIILiteral("Second argument to File constructor must be a valid string, was undefined"));

    String filename = arg.toWTFString(&exec).replace('/', ':');
    if (exec.hadException())
        return JSValue::encode(jsUndefined());

    String normalizedType;
    Optional<int64_t> lastModified;

    arg = exec.argument(2);
    if (!arg.isUndefinedOrNull()) {
        JSObject* filePropertyBagObject = arg.getObject();
        if (!filePropertyBagObject)
            return throwVMTypeError(&exec, ASCIILiteral("Third argument of the constructor is not of type Object"));

        // Create the dictionary wrapper from the initializer object.
        JSDictionary dictionary(&exec, filePropertyBagObject);

        // Attempt to get the type property.
        String type;
        dictionary.get("type", type);
        if (exec.hadException())
            return JSValue::encode(jsUndefined());

        normalizedType = Blob::normalizedContentType(type);

        // Only try to parse the lastModified date if there was not an invalid type argument.
        if (type.isEmpty() ||  !normalizedType.isEmpty()) {
            dictionary.get("lastModified", lastModified);
            if (exec.hadException())
                return JSValue::encode(jsUndefined());
        }
    }

    if (!lastModified)
        lastModified = currentTimeMS();

    BlobBuilder blobBuilder;

    for (unsigned i = 0; i < blobPartsLength; ++i) {
        JSValue item = blobParts->get(&exec, i);
        if (exec.hadException())
            return JSValue::encode(jsUndefined());

        if (ArrayBuffer* arrayBuffer = toArrayBuffer(item))
            blobBuilder.append(arrayBuffer);
        else if (RefPtr<ArrayBufferView> arrayBufferView = toArrayBufferView(item))
            blobBuilder.append(WTFMove(arrayBufferView));
        else if (Blob* blob = JSBlob::toWrapped(item))
            blobBuilder.append(blob);
        else {
            String string = item.toWTFString(&exec);
            if (exec.hadException())
                return JSValue::encode(jsUndefined());
            blobBuilder.append(string, ASCIILiteral("transparent"));
        }
    }

    auto file = File::create(blobBuilder.finalize(), filename, normalizedType, lastModified.value());
    return JSValue::encode(CREATE_DOM_WRAPPER(constructor->globalObject(), File, WTFMove(file)));
}
Пример #12
0
EncodedJSValue JSC_HOST_CALL JSBlobConstructor::constructJSBlob(ExecState* exec)
{
    JSBlobConstructor* jsConstructor = jsCast<JSBlobConstructor*>(exec->callee());
    ScriptExecutionContext* context = jsConstructor->scriptExecutionContext();
    if (!context)
        return throwVMError(exec, createReferenceError(exec, "Blob constructor associated document is unavailable"));

    if (!exec->argumentCount()) {
        RefPtr<Blob> blob = Blob::create();
        return JSValue::encode(CREATE_DOM_WRAPPER(jsConstructor->globalObject(), Blob, blob.get()));
    }

    unsigned blobPartsLength = 0;
    JSObject* blobParts = toJSSequence(exec, exec->argument(0), blobPartsLength);
    if (exec->hadException())
        return JSValue::encode(jsUndefined());
    ASSERT(blobParts);

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

    if (exec->argumentCount() > 1) {
        JSValue blobPropertyBagValue = exec->argument(1);

        if (!blobPropertyBagValue.isObject())
            return throwVMError(exec, createTypeError(exec, "Second argument of the constructor is not of type Object"));

        // Given the above test, this will always yield an object.
        JSObject* blobPropertyBagObject = blobPropertyBagValue.toObject(exec);

        // Create the dictionary wrapper from the initializer object.
        JSDictionary dictionary(exec, blobPropertyBagObject);

        // Attempt to get the endings property and validate it.
        bool containsEndings = dictionary.get("endings", endings);
        if (exec->hadException())
            return JSValue::encode(jsUndefined());

        if (containsEndings) {
            if (endings != "transparent" && endings != "native")
                return throwVMError(exec, createTypeError(exec, "The endings property must be either \"transparent\" or \"native\""));
        }

        // Attempt to get the type property.
        dictionary.get("type", type);
        if (exec->hadException())
            return JSValue::encode(jsUndefined());
    }

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

    BlobBuilder blobBuilder;

    for (unsigned i = 0; i < blobPartsLength; ++i) {
        JSValue item = blobParts->get(exec, i);
        if (exec->hadException())
            return JSValue::encode(jsUndefined());

#if ENABLE(BLOB)
        if (ArrayBuffer* arrayBuffer = toArrayBuffer(item))
            blobBuilder.append(arrayBuffer);
        else if (RefPtr<ArrayBufferView> arrayBufferView = toArrayBufferView(item))
            blobBuilder.append(arrayBufferView.release());
        else
#endif
        if (Blob* blob = toBlob(item))
            blobBuilder.append(blob);
        else {
            String string = item.toString(exec)->value(exec);
            if (exec->hadException())
                return JSValue::encode(jsUndefined());
            blobBuilder.append(string, endings);
        }
    }

    RefPtr<Blob> blob = Blob::create(blobBuilder.finalize(), Blob::normalizedContentType(type));

    return JSValue::encode(CREATE_DOM_WRAPPER(jsConstructor->globalObject(), Blob, blob.get()));
}