v8::Handle<v8::Value> V8Blob::constructorCustom(const v8::Arguments& args) { if (!args.Length()) { RefPtr<Blob> blob = Blob::create(); return toV8(blob.get(), args.Holder(), args.GetIsolate()); } v8::Local<v8::Value> firstArg = args[0]; if (!firstArg->IsArray()) return throwTypeError("First argument of the constructor is not of type Array", args.GetIsolate()); String type; String endings = ASCIILiteral("transparent"); if (args.Length() > 1) { if (!args[1]->IsObject()) return throwTypeError("Second argument of the constructor is not of type Object", args.GetIsolate()); V8TRYCATCH(Dictionary, dictionary, Dictionary(args[1], args.GetIsolate())); V8TRYCATCH(bool, containsEndings, dictionary.get("endings", endings)); if (containsEndings) { if (endings != "transparent" && endings != "native") return throwTypeError("The endings property must be either \"transparent\" or \"native\"", args.GetIsolate()); } V8TRYCATCH(bool, containsType, dictionary.get("type", type)); UNUSED_PARAM(containsType); if (!type.containsOnlyASCII()) return throwError(v8SyntaxError, "type must consist of ASCII characters", args.GetIsolate()); type.makeLower(); } ASSERT(endings == "transparent" || endings == "native"); BlobBuilder blobBuilder; V8TRYCATCH(v8::Local<v8::Array>, blobParts, v8::Local<v8::Array>::Cast(firstArg)); uint32_t length = blobParts->Length(); for (uint32_t i = 0; i < length; ++i) { v8::Local<v8::Value> item = blobParts->Get(v8::Uint32::New(i)); ASSERT(!item.IsEmpty()); #if ENABLE(BLOB) if (V8ArrayBuffer::HasInstance(item, args.GetIsolate(), worldType(args.GetIsolate()))) { ArrayBuffer* arrayBuffer = V8ArrayBuffer::toNative(v8::Handle<v8::Object>::Cast(item)); ASSERT(arrayBuffer); blobBuilder.append(arrayBuffer); } else if (V8ArrayBufferView::HasInstance(item, args.GetIsolate(), worldType(args.GetIsolate()))) { ArrayBufferView* arrayBufferView = V8ArrayBufferView::toNative(v8::Handle<v8::Object>::Cast(item)); ASSERT(arrayBufferView); blobBuilder.append(arrayBufferView); } else #endif if (V8Blob::HasInstance(item, args.GetIsolate(), worldType(args.GetIsolate()))) { Blob* blob = V8Blob::toNative(v8::Handle<v8::Object>::Cast(item)); ASSERT(blob); blobBuilder.append(blob); } else { V8TRYCATCH(String, stringValue, toWebCoreString(item)); blobBuilder.append(stringValue, endings); } } RefPtr<Blob> blob = blobBuilder.getBlob(type); return toV8(blob.get(), args.Holder(), args.GetIsolate()); }
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())); } 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 = blobBuilder.getBlob(type); return JSValue::encode(CREATE_DOM_WRAPPER(exec, jsConstructor->globalObject(), Blob, blob.get())); }