static JSObject* GetDataStoresStructuredCloneCallbacksRead(JSContext* aCx, JSStructuredCloneReader* aReader, uint32_t aTag, uint32_t aData, void* aClosure) { WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx); MOZ_ASSERT(workerPrivate); workerPrivate->AssertIsOnWorkerThread(); if (aTag != WORKER_DATA_STORES_TAG) { MOZ_ASSERT(false, "aTag must be WORKER_DATA_STORES_TAG!"); return nullptr; } NS_ASSERTION(!aData, "aData should be empty"); // Read the holder from the buffer, which points to the data store. nsMainThreadPtrHolder<DataStore>* dataStoreholder; if (!JS_ReadBytes(aReader, &dataStoreholder, sizeof(dataStoreholder))) { MOZ_ASSERT(false, "cannot read bytes for dataStoreholder!"); return nullptr; } // Protect workerStoreObj from moving GC during ~nsRefPtr. JS::Rooted<JSObject*> workerStoreObj(aCx, nullptr); { nsRefPtr<WorkerDataStore> workerStore = new WorkerDataStore(workerPrivate->GlobalScope()); nsMainThreadPtrHandle<DataStore> backingStore(dataStoreholder); // When we're on the worker thread, prepare a DataStoreChangeEventProxy. nsRefPtr<DataStoreChangeEventProxy> eventProxy = new DataStoreChangeEventProxy(workerPrivate, workerStore); // Add the DataStoreChangeEventProxy as an event listener on the main thread. nsRefPtr<DataStoreAddEventListenerRunnable> runnable = new DataStoreAddEventListenerRunnable(workerPrivate, backingStore, eventProxy); runnable->Dispatch(aCx); // Point WorkerDataStore to DataStore. workerStore->SetBackingDataStore(backingStore); JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx)); if (!global) { MOZ_ASSERT(false, "cannot get global!"); } else { workerStoreObj = workerStore->WrapObject(aCx); if (!JS_WrapObject(aCx, &workerStoreObj)) { MOZ_ASSERT(false, "cannot wrap object for workerStoreObj!"); workerStoreObj = nullptr; } } } return workerStoreObj; }
// Helper functions for structured cloning inline bool ReadString(JSStructuredCloneReader* aReader, nsString& aString) { MOZ_ASSERT(aReader); bool read; uint32_t nameLength, zero; read = JS_ReadUint32Pair(aReader, &nameLength, &zero); if (!read) { return false; } MOZ_ASSERT(zero == 0); aString.SetLength(nameLength); size_t charSize = sizeof(nsString::char_type); read = JS_ReadBytes(aReader, (void*) aString.BeginWriting(), nameLength * charSize); if (!read) { return false; } return true; }
bool StructuredCloneBlob::Holder::ReadStructuredCloneInternal( JSContext* aCx, JSStructuredCloneReader* aReader, StructuredCloneHolder* aHolder) { uint32_t length; uint32_t version; if (!JS_ReadUint32Pair(aReader, &length, &version)) { return false; } uint32_t blobOffset; uint32_t blobCount; if (!JS_ReadUint32Pair(aReader, &blobOffset, &blobCount)) { return false; } if (blobCount) { #ifdef FUZZING if (blobOffset >= aHolder->BlobImpls().Length()) { return false; } #endif BlobImpls().AppendElements(&aHolder->BlobImpls()[blobOffset], blobCount); } JSStructuredCloneData data(mStructuredCloneScope); while (length) { size_t size; char* buffer = data.AllocateBytes(length, &size); if (!buffer || !JS_ReadBytes(aReader, buffer, size)) { return false; } length -= size; } mBuffer = MakeUnique<JSAutoStructuredCloneBuffer>( mStructuredCloneScope, &StructuredCloneHolder::sCallbacks, this); mBuffer->adopt(std::move(data), version, &StructuredCloneHolder::sCallbacks); return true; }