JSValue JSWebSocket::send(ExecState* exec) { if (!exec->argumentCount()) return throwError(exec, createNotEnoughArgumentsError(exec)); 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(&JSArrayBufferView::s_info)) result = impl()->send(toArrayBufferView(message), ec); else if (message.inherits(&JSBlob::s_info)) result = impl()->send(toBlob(message), ec); else { String stringMessage = 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; 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(); }
EncodedJSValue JSC_HOST_CALL jsCryptoPrototypeFunctionGetRandomValues(ExecState* exec) { JSValue thisValue = exec->hostThisValue(); if (!thisValue.inherits(&JSCrypto::s_info)) return throwVMTypeError(exec); JSCrypto* castedThis = static_cast<JSCrypto*>(asObject(thisValue)); Crypto* imp = static_cast<Crypto*>(castedThis->impl()); ExceptionCode ec = 0; ArrayBufferView* array(toArrayBufferView(exec->argument(0))); if (exec->hadException()) return JSValue::encode(jsUndefined()); imp->getRandomValues(array, ec); setDOMException(exec, ec); return JSValue::encode(jsUndefined()); }
JSValue JSCrypto::getRandomValues(ExecState* exec) { if (exec->argumentCount() < 1) return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec)); JSValue buffer = exec->argument(0); RefPtr<ArrayBufferView> arrayBufferView = toArrayBufferView(buffer); if (!arrayBufferView) return throwTypeError(exec); ExceptionCode ec = 0; impl()->getRandomValues(arrayBufferView.get(), ec); if (ec) { setDOMException(exec, ec); return jsUndefined(); } return buffer; }
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 if (val.inherits(&JSArrayBufferView::s_info)) impl()->send(toArrayBufferView(val), ec); else impl()->send(val.toString(exec)->value(exec), ec); } int signedLineNumber; intptr_t sourceID; String sourceURL; JSValue function; exec->interpreter()->retrieveLastCaller(exec, signedLineNumber, sourceID, sourceURL, function); impl()->setLastSendLineNumber(signedLineNumber >= 0 ? signedLineNumber : 0); impl()->setLastSendURL(sourceURL); setDOMException(exec, ec); return jsUndefined(); }
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))); }
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()); if (!type.containsOnlyASCII()) return throwVMError(exec, createSyntaxError(exec, "type must consist of ASCII characters")); } 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(context, toArrayBuffer(item)); else if (item.inherits(&JSArrayBufferView::s_info)) blobBuilder->append(toArrayBufferView(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 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())); }