Beispiel #1
0
JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, HTMLCollection* collection)
{
    if (!collection)
        return jsNull();

    JSDOMWrapper* wrapper = getCachedWrapper(currentWorld(exec), collection);

    if (wrapper)
        return wrapper;

    switch (collection->type()) {
        case SelectOptions:
            wrapper = CREATE_DOM_WRAPPER(exec, globalObject, HTMLOptionsCollection, collection);
            break;
        case DocAll:
            wrapper = CREATE_DOM_WRAPPER(exec, globalObject, HTMLAllCollection, collection);
            break;
#if ENABLE(MICRODATA)
        case ItemProperties:
            wrapper = CREATE_DOM_WRAPPER(exec, globalObject, HTMLPropertiesCollection, collection);
            break;
#endif
        default:
            wrapper = CREATE_DOM_WRAPPER(exec, globalObject, HTMLCollection, collection);
            break;
    }

    return wrapper;
}
JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, Document* document)
{
    if (!document)
        return jsNull();

    JSDOMWrapper* wrapper = getCachedWrapper(currentWorld(exec), document);
    if (wrapper)
        return wrapper;

    if (document->isHTMLDocument())
        wrapper = CREATE_DOM_WRAPPER(exec, globalObject, HTMLDocument, document);
#if ENABLE(SVG)
    else if (document->isSVGDocument())
        wrapper = CREATE_DOM_WRAPPER(exec, globalObject, SVGDocument, document);
#endif
    else
        wrapper = CREATE_DOM_WRAPPER(exec, globalObject, Document, document);

    // Make sure the document is kept around by the window object, and works right with the
    // back/forward cache.
    if (!document->frame()) {
        size_t nodeCount = 0;
        for (Node* n = document; n; n = n->traverseNextNode())
            nodeCount++;
        
        exec->heap()->reportExtraMemoryCost(nodeCount * sizeof(Node));
    }

    return wrapper;
}
Beispiel #3
0
JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject* globalObject, TrackBase* track)
{
    if (!track)
        return jsNull();
    
    JSObject* wrapper = getCachedWrapper(globalObject->world(), track);
    if (wrapper)
        return wrapper;
    
    switch (track->type()) {
    case TrackBase::BaseTrack:
        // This should never happen.
        ASSERT_NOT_REACHED();
        break;
        
    case TrackBase::AudioTrack:
        return CREATE_DOM_WRAPPER(globalObject, AudioTrack, track);

    case TrackBase::VideoTrack:
        return CREATE_DOM_WRAPPER(globalObject, VideoTrack, track);

    case TrackBase::TextTrack:
        return CREATE_DOM_WRAPPER(globalObject, TextTrack, track);
    }
    
    return jsNull();
}
Beispiel #4
0
JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, Blob* blob)
{
    if (!blob)
        return jsNull();

    if (blob->isFile())
        return CREATE_DOM_WRAPPER(exec, globalObject, File, blob);

    return CREATE_DOM_WRAPPER(exec, globalObject, Blob, blob);
}
JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject* globalObject, StyleSheet* styleSheet)
{
    if (!styleSheet)
        return JSC::jsNull();

    if (JSC::JSObject* wrapper = getCachedWrapper(globalObject->world(), styleSheet))
        return wrapper;

    if (styleSheet->isCSSStyleSheet())
        return CREATE_DOM_WRAPPER(globalObject, CSSStyleSheet, styleSheet);

    return CREATE_DOM_WRAPPER(globalObject, StyleSheet, styleSheet);
}
Beispiel #6
0
static inline JSValue createNewDocumentWrapper(ExecState& state, JSDOMGlobalObject& globalObject, Ref<Document>&& passedDocument)
{
    auto& document = passedDocument.get();
    JSObject* wrapper;
    if (document.isHTMLDocument())
        wrapper = CREATE_DOM_WRAPPER(&globalObject, HTMLDocument, WTFMove(passedDocument));
    else if (document.isXMLDocument())
        wrapper = CREATE_DOM_WRAPPER(&globalObject, XMLDocument, WTFMove(passedDocument));
    else
        wrapper = CREATE_DOM_WRAPPER(&globalObject, Document, WTFMove(passedDocument));

    reportMemoryForDocumentIfFrameless(state, document);

    return wrapper;
}
Beispiel #7
0
JSValue toJSNewlyCreated(ExecState* exec, JSDOMGlobalObject* globalObject, Touch* touch)
{
    if (!touch)
        return jsNull();

    return CREATE_DOM_WRAPPER(exec, globalObject, Touch, touch);
}
JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, StyleSheet* styleSheet)
{
    if (!styleSheet)
        return jsNull();

    JSObject* wrapper = getCachedWrapper(currentWorld(exec), styleSheet);
    if (wrapper)
        return wrapper;

    if (styleSheet->isCSSStyleSheet())
        wrapper = CREATE_DOM_WRAPPER(exec, globalObject, CSSStyleSheet, styleSheet);
    else
        wrapper = CREATE_DOM_WRAPPER(exec, globalObject, StyleSheet, styleSheet);

    return wrapper;
}
EncodedJSValue JSC_HOST_CALL constructJSRTCPeerConnection(ExecState* exec)
{
    // Spec says that we must have at least one arument, the RTCConfiguration.
    if (exec->argumentCount() < 1)
        return throwVMError(exec, createNotEnoughArgumentsError(exec));

    ExceptionCode ec = 0;
    Dictionary rtcConfiguration(exec, exec->argument(0));
    if (exec->hadException())
        return JSValue::encode(jsUndefined());

    if (!rtcConfiguration.isObject())
        return throwVMError(exec, createTypeError(exec, "RTCPeerConnection argument must be a valid Dictionary"));

    DOMConstructorObject* jsConstructor = jsCast<DOMConstructorObject*>(exec->callee());
    ScriptExecutionContext* scriptExecutionContext = jsConstructor->scriptExecutionContext();
    if (!scriptExecutionContext)
        return throwVMError(exec, createReferenceError(exec, "RTCPeerConnection constructor associated document is unavailable"));

    auto peerConnection = RTCPeerConnection::create(*scriptExecutionContext, rtcConfiguration, ec);
    if (ec == TYPE_MISMATCH_ERR) {
        setDOMException(exec, ec);
        return throwVMError(exec, createTypeError(exec, "Invalid RTCPeerConnection constructor arguments"));
    }

    if (ec) {
        setDOMException(exec, ec);
        return throwVMError(exec, createTypeError(exec, "Error creating RTCPeerConnection"));
    }

    return JSValue::encode(CREATE_DOM_WRAPPER(jsConstructor->globalObject(), RTCPeerConnection, peerConnection.releaseNonNull()));
}
Beispiel #10
0
JSValue toJSNewlyCreated(ExecState*, JSDOMGlobalObject* globalObject, Text* text)
{
    if (!text)
        return jsNull();

    return CREATE_DOM_WRAPPER(globalObject, Text, text);
}
EncodedJSValue JSC_HOST_CALL constructJSRTCSessionDescription(ExecState* exec)
{
    ExceptionCode ec = 0;
    Dictionary sessionInit;
    if (exec->argumentCount() > 0) {
        sessionInit = Dictionary(exec, exec->argument(0));
        if (!sessionInit.isObject())
            return throwVMError(exec, createTypeError(exec, "Optional RTCSessionDescription constructor argument must be a valid Dictionary"));

        if (exec->hadException())
            return JSValue::encode(jsUndefined());
    }

    DOMConstructorObject* jsConstructor = jsCast<DOMConstructorObject*>(exec->callee());
    RefPtr<RTCSessionDescription> sessionDescription = RTCSessionDescription::create(sessionInit, ec);
    if (ec == TYPE_MISMATCH_ERR) {
        setDOMException(exec, ec);
        return throwVMError(exec, createTypeError(exec, "Invalid RTCSessionDescription constructor arguments"));
    }

    if (ec) {
        setDOMException(exec, ec);
        return throwVMError(exec, createTypeError(exec, "Error creating RTCSessionDescription"));
    }

    return JSValue::encode(CREATE_DOM_WRAPPER(jsConstructor->globalObject(), RTCSessionDescription, sessionDescription.get()));
}
EncodedJSValue JSC_HOST_CALL JSAudioContextConstructor::constructJSAudioContext(ExecState* exec)
{
    JSAudioContextConstructor* jsConstructor = jsCast<JSAudioContextConstructor*>(exec->callee());
    if (!jsConstructor)
        return throwVMError(exec, createReferenceError(exec, "AudioContext constructor callee is unavailable"));

    ScriptExecutionContext* scriptExecutionContext = jsConstructor->scriptExecutionContext();
    if (!scriptExecutionContext)
        return throwVMError(exec, createReferenceError(exec, "AudioContext constructor script execution context is unavailable"));
        
    if (!scriptExecutionContext->isDocument())
        return throwVMError(exec, createReferenceError(exec, "AudioContext constructor called in a script execution context which is not a document"));

    Document* document = static_cast<Document*>(scriptExecutionContext);

    RefPtr<AudioContext> audioContext;
    
    if (!exec->argumentCount()) {
        // Constructor for default AudioContext which talks to audio hardware.
        ExceptionCode ec = 0;
        audioContext = AudioContext::create(document, ec);
        if (ec) {
            setDOMException(exec, ec);
            return JSValue::encode(JSValue());
        }
        if (!audioContext.get())
            return throwVMError(exec, createSyntaxError(exec, "audio resources unavailable for AudioContext construction"));
    } else {
        // Constructor for offline (render-target) AudioContext which renders into an AudioBuffer.
        // new AudioContext(in unsigned long numberOfChannels, in unsigned long numberOfFrames, in float sampleRate);
        if (exec->argumentCount() < 3)
            return throwVMError(exec, createNotEnoughArgumentsError(exec));

        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 throwVMError(exec, createSyntaxError(exec, "Invalid number of channels"));

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

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

        ExceptionCode ec = 0;
        audioContext = AudioContext::createOfflineContext(document, numberOfChannels, numberOfFrames, sampleRate, ec);
        if (ec) {
            setDOMException(exec, ec);
            return throwVMError(exec, createSyntaxError(exec, "Error creating OfflineAudioContext"));
        }
    }

    if (!audioContext.get())
        return throwVMError(exec, createReferenceError(exec, "Error creating AudioContext"));

    return JSValue::encode(CREATE_DOM_WRAPPER(exec, jsConstructor->globalObject(), AudioContext, audioContext.get()));
}
Beispiel #13
0
JSValue toJS(ExecState*, JSDOMGlobalObject* globalObject, CSSValue* value)
{
    if (!value)
        return jsNull();

    // Scripts should only ever see cloned CSSValues, never the internal ones.
    ASSERT(value->isCSSOMSafe());

    // If we're here under erroneous circumstances, prefer returning null over a potentially insecure value.
    if (!value->isCSSOMSafe())
        return jsNull();

    JSObject* wrapper = getCachedWrapper(globalObject->world(), value);

    if (wrapper)
        return wrapper;

    if (value->isWebKitCSSTransformValue())
        wrapper = CREATE_DOM_WRAPPER(globalObject, WebKitCSSTransformValue, value);
    else if (value->isWebKitCSSFilterValue())
        wrapper = CREATE_DOM_WRAPPER(globalObject, WebKitCSSFilterValue, value);
    else if (value->isValueList())
        wrapper = CREATE_DOM_WRAPPER(globalObject, CSSValueList, value);
    else if (value->isSVGPaint())
        wrapper = CREATE_DOM_WRAPPER(globalObject, SVGPaint, value);
    else if (value->isSVGColor())
        wrapper = CREATE_DOM_WRAPPER(globalObject, SVGColor, value);
    else if (value->isPrimitiveValue())
        wrapper = CREATE_DOM_WRAPPER(globalObject, CSSPrimitiveValue, value);
    else
        wrapper = CREATE_DOM_WRAPPER(globalObject, CSSValue, value);

    return wrapper;
}
JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, CSSRule* rule)
{
    if (!rule)
        return jsNull();

    JSDOMWrapper* wrapper = getCachedWrapper(currentWorld(exec), rule);
    if (wrapper)
        return wrapper;

    switch (rule->type()) {
        case CSSRule::STYLE_RULE:
            wrapper = CREATE_DOM_WRAPPER(exec, globalObject, CSSStyleRule, rule);
            break;
        case CSSRule::MEDIA_RULE:
            wrapper = CREATE_DOM_WRAPPER(exec, globalObject, CSSMediaRule, rule);
            break;
        case CSSRule::FONT_FACE_RULE:
            wrapper = CREATE_DOM_WRAPPER(exec, globalObject, CSSFontFaceRule, rule);
            break;
        case CSSRule::PAGE_RULE:
            wrapper = CREATE_DOM_WRAPPER(exec, globalObject, CSSPageRule, rule);
            break;
        case CSSRule::IMPORT_RULE:
            wrapper = CREATE_DOM_WRAPPER(exec, globalObject, CSSImportRule, rule);
            break;
        case CSSRule::CHARSET_RULE:
            wrapper = CREATE_DOM_WRAPPER(exec, globalObject, CSSCharsetRule, rule);
            break;
        case CSSRule::WEBKIT_KEYFRAME_RULE:
            wrapper = CREATE_DOM_WRAPPER(exec, globalObject, WebKitCSSKeyframeRule, rule);
            break;
        case CSSRule::WEBKIT_KEYFRAMES_RULE:
            wrapper = CREATE_DOM_WRAPPER(exec, globalObject, WebKitCSSKeyframesRule, rule);
            break;
        case CSSRule::WEBKIT_REGION_RULE:
            wrapper = CREATE_DOM_WRAPPER(exec, globalObject, WebKitCSSRegionRule, rule);
            break;
        default:
            wrapper = CREATE_DOM_WRAPPER(exec, globalObject, CSSRule, rule);
    }

    return wrapper;
}
EncodedJSValue JSC_HOST_CALL JSXMLHttpRequestConstructor::constructJSXMLHttpRequest(ExecState* exec)
{
    JSXMLHttpRequestConstructor* jsConstructor = static_cast<JSXMLHttpRequestConstructor*>(exec->callee());
    ScriptExecutionContext* context = jsConstructor->scriptExecutionContext();
    if (!context)
        return throwVMError(exec, createReferenceError(exec, "XMLHttpRequest constructor associated document is unavailable"));

    RefPtr<XMLHttpRequest> xmlHttpRequest = XMLHttpRequest::create(context);
    return JSValue::encode(CREATE_DOM_WRAPPER(exec, jsConstructor->globalObject(), XMLHttpRequest, xmlHttpRequest.get()));
}
EncodedJSValue JSC_HOST_CALL JSWebKitCSSMatrixConstructor::constructJSWebKitCSSMatrix(ExecState* exec)
{
    JSWebKitCSSMatrixConstructor* jsConstructor = static_cast<JSWebKitCSSMatrixConstructor*>(exec->callee());
    String s;
    if (exec->argumentCount() >= 1)
        s = ustringToString(exec->argument(0).toString(exec));
    
    ExceptionCode ec = 0;
    RefPtr<WebKitCSSMatrix> matrix = WebKitCSSMatrix::create(s, ec);
    setDOMException(exec, ec);
    return JSValue::encode(CREATE_DOM_WRAPPER(exec, jsConstructor->globalObject(), WebKitCSSMatrix, matrix.get()));
}
JSValue toJS(ExecState*, JSDOMGlobalObject* globalObject, TextTrackCue* cue)
{
    if (!cue)
        return jsNull();

    JSObject* wrapper = getCachedWrapper(globalObject->world(), cue);

    if (wrapper)
        return wrapper;

    // This switch will make more sense once we support DataCue
    switch (cue->cueType()) {
    case TextTrackCue::Data:
        return CREATE_DOM_WRAPPER(globalObject, DataCue, cue);
    case TextTrackCue::WebVTT:
    case TextTrackCue::Generic:
        return CREATE_DOM_WRAPPER(globalObject, VTTCue, cue);
    default:
        ASSERT_NOT_REACHED();
        return jsNull();
    }
}
Beispiel #18
0
JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, TextTrack* impl)
{
    if (!impl)
        return jsNull();
    
    JSDOMWrapper* wrapper = getCachedWrapper(currentWorld(exec), impl);
    
    if (wrapper)
        return wrapper;

    switch (impl->trackType()) {
    case TextTrack::LoadableTextTrack:
    case TextTrack::BaseTextTrack:
        return CREATE_DOM_WRAPPER(exec, globalObject, TextTrack, impl);
        break;
    case TextTrack::MutableTextTrack:
        return CREATE_DOM_WRAPPER(exec, globalObject, MutableTextTrack, impl);
        break;
    }
    
    ASSERT_NOT_REACHED();
    return jsNull();
}
JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, HTMLCollection* collection)
{
    if (!collection)
        return jsNull();

    JSDOMWrapper* wrapper = getCachedWrapper(currentWorld(exec), collection);

    if (wrapper)
        return wrapper;

    switch (collection->type()) {
    case FormControls:
        return CREATE_DOM_WRAPPER(exec, globalObject, HTMLFormControlsCollection, collection);
    case SelectOptions:
        return CREATE_DOM_WRAPPER(exec, globalObject, HTMLOptionsCollection, collection);
    case DocAll:
        return CREATE_DOM_WRAPPER(exec, globalObject, HTMLAllCollection, collection);
    default:
        break;
    }

    return CREATE_DOM_WRAPPER(exec, globalObject, HTMLCollection, collection);
}
JSValue JSHTMLTemplateElement::content(ExecState* exec) const
{
    JSLockHolder lock(exec);

    DocumentFragment* content = impl().content();

    JSObject* wrapper = getCachedWrapper(currentWorld(exec), content);
    if (wrapper)
        return wrapper;

    wrapper = CREATE_DOM_WRAPPER(exec, globalObject(), DocumentFragment, content);
    PrivateName propertyName;
    const_cast<JSHTMLTemplateElement*>(this)->putDirect(globalObject()->vm(), propertyName, wrapper);
    return wrapper;
}
Beispiel #21
0
JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, Document* document)
{
    if (!document)
        return jsNull();

    JSObject* wrapper = getCachedWrapper(globalObject->world(), document);
    if (wrapper)
        return wrapper;

    if (DOMWindow* domWindow = document->domWindow()) {
        globalObject = toJSDOMWindow(toJS(exec, domWindow));
        // Creating a wrapper for domWindow might have created a wrapper for document as well.
        wrapper = getCachedWrapper(globalObject->world(), document);
        if (wrapper)
            return wrapper;
    }

    if (document->isHTMLDocument())
        wrapper = CREATE_DOM_WRAPPER(globalObject, HTMLDocument, document);
    else if (document->isSVGDocument())
        wrapper = CREATE_DOM_WRAPPER(globalObject, SVGDocument, document);
    else
        wrapper = CREATE_DOM_WRAPPER(globalObject, Document, document);

    // Make sure the document is kept around by the window object, and works right with the
    // back/forward cache.
    if (!document->frame()) {
        size_t nodeCount = 0;
        for (Node* n = document; n; n = NodeTraversal::next(n))
            nodeCount++;
        
        exec->heap()->reportExtraMemoryCost(nodeCount * sizeof(Node));
    }

    return wrapper;
}
Beispiel #22
0
JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, ImageData* imageData)
{
    if (!imageData)
        return jsNull();
    
    JSDOMWrapper* wrapper = getCachedWrapper(currentWorld(exec), imageData);
    if (wrapper)
        return wrapper;
    
    wrapper = CREATE_DOM_WRAPPER(exec, globalObject, ImageData, imageData);
    Identifier dataName(exec, "data");
    wrapper->putDirect(exec->globalData(), dataName, toJS(exec, globalObject, imageData->data()), DontDelete | ReadOnly);
    exec->heap()->reportExtraMemoryCost(imageData->data()->length());
    
    return wrapper;
}
JSValue toJSNewlyCreated(ExecState*, JSDOMGlobalObject* globalObject, Ref<CSSValue>&& value)
{
    if (value->isWebKitCSSTransformValue())
        return CREATE_DOM_WRAPPER(globalObject, WebKitCSSTransformValue, WTFMove(value));
    if (value->isWebKitCSSFilterValue())
        return CREATE_DOM_WRAPPER(globalObject, WebKitCSSFilterValue, WTFMove(value));
    if (value->isValueList())
        return CREATE_DOM_WRAPPER(globalObject, CSSValueList, WTFMove(value));
    if (value->isSVGPaint())
        return CREATE_DOM_WRAPPER(globalObject, SVGPaint, WTFMove(value));
    if (value->isSVGColor())
        return CREATE_DOM_WRAPPER(globalObject, SVGColor, WTFMove(value));
    if (value->isPrimitiveValue())
        return CREATE_DOM_WRAPPER(globalObject, CSSPrimitiveValue, WTFMove(value));
    return CREATE_DOM_WRAPPER(globalObject, CSSValue, WTFMove(value));
}
Beispiel #24
0
JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, ImageData* imageData)
{
    if (!imageData)
        return jsNull();
    
    JSDOMWrapper* wrapper = getCachedWrapper(currentWorld(exec), imageData);
    if (wrapper)
        return wrapper;
    
    wrapper = CREATE_DOM_WRAPPER(exec, globalObject, ImageData, imageData);
    Identifier dataName(exec, "data");
    static const ClassInfo cpaClassInfo = { "CanvasPixelArray", &JSByteArray::Base::s_info, 0, 0 };
    DEFINE_STATIC_LOCAL(Strong<Structure>, cpaStructure, (exec->globalData(), JSByteArray::createStructure(exec->globalData(), jsNull(), &cpaClassInfo)));
    wrapper->putDirect(exec->globalData(), dataName, new (exec) JSByteArray(exec, cpaStructure.get(), imageData->data()->data()), DontDelete | ReadOnly);
    exec->heap()->reportExtraMemoryCost(imageData->data()->length());
    
    return wrapper;
}
EncodedJSValue JSC_HOST_CALL JSDeprecatedPeerConnectionConstructor::constructJSDeprecatedPeerConnection(ExecState* exec)
{
    JSDeprecatedPeerConnectionConstructor* jsConstructor = static_cast<JSDeprecatedPeerConnectionConstructor*>(exec->callee());
    ScriptExecutionContext* context = jsConstructor->scriptExecutionContext();
    if (!context)
        return throwVMError(exec, createReferenceError(exec, "DeprecatedPeerConnection constructor associated document is unavailable"));

    if (exec->argumentCount() < 2)
        return throwVMError(exec, createTypeError(exec, "Not enough arguments"));

    String serverConfiguration = ustringToString(exec->argument(0).toString(exec)->value(exec));
    if (exec->hadException())
        return JSValue::encode(JSValue());

    RefPtr<SignalingCallback> signalingCallback = createFunctionOnlyCallback<JSSignalingCallback>(exec, static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), exec->argument(1));
    if (exec->hadException())
        return JSValue::encode(JSValue());

    RefPtr<DeprecatedPeerConnection> peerConnection = DeprecatedPeerConnection::create(context, serverConfiguration, signalingCallback.release());
    return JSValue::encode(CREATE_DOM_WRAPPER(exec, jsConstructor->globalObject(), DeprecatedPeerConnection, peerConnection.get()));
}
EncodedJSValue JSC_HOST_CALL JSWebSocketConstructor::constructJSWebSocket(ExecState* exec)
{
    JSWebSocketConstructor* jsConstructor = static_cast<JSWebSocketConstructor*>(exec->callee());
    ScriptExecutionContext* context = jsConstructor->scriptExecutionContext();
    if (!context)
        return throwVMError(exec, createReferenceError(exec, "WebSocket constructor associated document is unavailable"));

    if (!exec->argumentCount())
        return throwVMError(exec, createSyntaxError(exec, "Not enough arguments"));

    String urlString = ustringToString(exec->argument(0).toString(exec)->value(exec));
    if (exec->hadException())
        return throwVMError(exec, createSyntaxError(exec, "wrong URL"));
    RefPtr<WebSocket> webSocket = WebSocket::create(context);
    ExceptionCode ec = 0;
    if (exec->argumentCount() < 2)
        webSocket->connect(urlString, ec);
    else {
        JSValue protocolsValue = exec->argument(1);
        if (isJSArray(protocolsValue)) {
            Vector<String> protocols;
            JSArray* protocolsArray = asArray(protocolsValue);
            for (unsigned i = 0; i < protocolsArray->length(); ++i) {
                String protocol = ustringToString(protocolsArray->getIndex(i).toString(exec)->value(exec));
                if (exec->hadException())
                    return JSValue::encode(JSValue());
                protocols.append(protocol);
            }
            webSocket->connect(urlString, protocols, ec);
        } else {
            String protocol = ustringToString(protocolsValue.toString(exec)->value(exec));
            if (exec->hadException())
                return JSValue::encode(JSValue());
            webSocket->connect(urlString, protocol, ec);
        }
    }
    setDOMException(exec, ec);
    return JSValue::encode(CREATE_DOM_WRAPPER(exec, jsConstructor->globalObject(), WebSocket, webSocket.get()));
}
Beispiel #27
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()));
}
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)));
}
JSValue toJSNewlyCreated(ExecState*, JSDOMGlobalObject* globalObject, Ref<CSSRule>&& rule)
{
    switch (rule->type()) {
    case CSSRule::STYLE_RULE:
        return CREATE_DOM_WRAPPER(globalObject, CSSStyleRule, WTFMove(rule));
    case CSSRule::MEDIA_RULE:
        return CREATE_DOM_WRAPPER(globalObject, CSSMediaRule, WTFMove(rule));
    case CSSRule::FONT_FACE_RULE:
        return CREATE_DOM_WRAPPER(globalObject, CSSFontFaceRule, WTFMove(rule));
    case CSSRule::PAGE_RULE:
        return CREATE_DOM_WRAPPER(globalObject, CSSPageRule, WTFMove(rule));
    case CSSRule::IMPORT_RULE:
        return CREATE_DOM_WRAPPER(globalObject, CSSImportRule, WTFMove(rule));
    case CSSRule::CHARSET_RULE:
        return CREATE_DOM_WRAPPER(globalObject, CSSCharsetRule, WTFMove(rule));
    case CSSRule::KEYFRAME_RULE:
        return CREATE_DOM_WRAPPER(globalObject, CSSKeyframeRule, WTFMove(rule));
    case CSSRule::KEYFRAMES_RULE:
        return CREATE_DOM_WRAPPER(globalObject, CSSKeyframesRule, WTFMove(rule));
    case CSSRule::SUPPORTS_RULE:
        return CREATE_DOM_WRAPPER(globalObject, CSSSupportsRule, WTFMove(rule));
#if ENABLE(CSS_DEVICE_ADAPTATION)
    case CSSRule::WEBKIT_VIEWPORT_RULE:
        return CREATE_DOM_WRAPPER(globalObject, WebKitCSSViewportRule, WTFMove(rule));
#endif
#if ENABLE(CSS_REGIONS)
    case CSSRule::WEBKIT_REGION_RULE:
        return CREATE_DOM_WRAPPER(globalObject, WebKitCSSRegionRule, WTFMove(rule));
#endif
    default:
        return CREATE_DOM_WRAPPER(globalObject, CSSRule, WTFMove(rule));
    }
}
EncodedJSValue JSC_HOST_CALL constructJSAudioContext(ExecState* exec)
{
    DOMConstructorObject* jsConstructor = jsCast<DOMConstructorObject*>(exec->callee());
    if (!jsConstructor)
        return throwVMError(exec, createReferenceError(exec, "AudioContext constructor callee is unavailable"));

    ScriptExecutionContext* scriptExecutionContext = jsConstructor->scriptExecutionContext();
    if (!scriptExecutionContext)
        return throwVMError(exec, createReferenceError(exec, "AudioContext constructor script execution context is unavailable"));
        
    if (!scriptExecutionContext->isDocument())
        return throwVMError(exec, createReferenceError(exec, "AudioContext constructor called in a script execution context which is not a document"));

    Document& document = toDocument(*scriptExecutionContext);

    RefPtr<AudioContext> audioContext;
    
    if (!exec->argumentCount()) {
        // Constructor for default AudioContext which talks to audio hardware.
        ExceptionCode ec = 0;
        audioContext = AudioContext::create(document, ec);
        if (ec) {
            setDOMException(exec, ec);
            return JSValue::encode(JSValue());
        }
        if (!audioContext.get())
            return throwVMError(exec, createSyntaxError(exec, "audio resources unavailable for AudioContext construction"));
    } else {
#if ENABLE(LEGACY_WEB_AUDIO)
        // Constructor for offline (render-target) AudioContext which renders into an AudioBuffer.
        // new AudioContext(in unsigned long numberOfChannels, in unsigned long numberOfFrames, in float sampleRate);
        document.addConsoleMessage(MessageSource::JS, MessageLevel::Warning, ASCIILiteral("Deprecated AudioContext constructor: use OfflineAudioContext instead"));

        if (exec->argumentCount() < 3)
            return throwVMError(exec, createNotEnoughArgumentsError(exec));

        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 throwVMError(exec, createSyntaxError(exec, "Invalid number of channels"));

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

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


        ExceptionCode ec = 0;
        audioContext = OfflineAudioContext::create(document, numberOfChannels, numberOfFrames, sampleRate, ec);
        if (ec) {
            setDOMException(exec, ec);
            return throwVMError(exec, createSyntaxError(exec, "Error creating OfflineAudioContext"));
        }
#else
        return throwVMError(exec, createSyntaxError(exec, "Illegal AudioContext constructor"));
#endif
    }

    if (!audioContext.get())
        return throwVMError(exec, createReferenceError(exec, "Error creating AudioContext"));

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