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