зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1311466 - Part 3: Core changes for WebAssembly module serialization including a test; r=asuth
This commit is contained in:
Родитель
51534c010e
Коммит
00707ba46a
|
@ -27,6 +27,10 @@ enum StructuredCloneTags {
|
||||||
SCTAG_DOM_MUTABLEFILE,
|
SCTAG_DOM_MUTABLEFILE,
|
||||||
SCTAG_DOM_FILE,
|
SCTAG_DOM_FILE,
|
||||||
|
|
||||||
|
SCTAG_DOM_WASM,
|
||||||
|
|
||||||
|
// New IDB tags go here!
|
||||||
|
|
||||||
// These tags are used for both main thread and workers.
|
// These tags are used for both main thread and workers.
|
||||||
SCTAG_DOM_IMAGEDATA,
|
SCTAG_DOM_IMAGEDATA,
|
||||||
SCTAG_DOM_MAP_MESSAGEPORT,
|
SCTAG_DOM_MAP_MESSAGEPORT,
|
||||||
|
@ -56,6 +60,12 @@ enum StructuredCloneTags {
|
||||||
// This tag is used by both main thread and workers.
|
// This tag is used by both main thread and workers.
|
||||||
SCTAG_DOM_URLSEARCHPARAMS,
|
SCTAG_DOM_URLSEARCHPARAMS,
|
||||||
|
|
||||||
|
// When adding a new tag for IDB, please don't add it to the end of the list!
|
||||||
|
// Tags that are supported by IDB must not ever change. See the static assert
|
||||||
|
// in IDBObjectStore.cpp, method CommonStructuredCloneReadCallback.
|
||||||
|
// Adding to the end of the list would make removing of other tags harder in
|
||||||
|
// future.
|
||||||
|
|
||||||
SCTAG_DOM_MAX
|
SCTAG_DOM_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -8237,6 +8237,16 @@ struct ObjectStoreAddOrPutRequestOp::StoredFileInfo final
|
||||||
aText.AppendInt(id);
|
aText.AppendInt(id);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case StructuredCloneFile::eWasmBytecode:
|
||||||
|
aText.Append('/');
|
||||||
|
aText.AppendInt(id);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case StructuredCloneFile::eWasmCompiled:
|
||||||
|
aText.Append('\\');
|
||||||
|
aText.AppendInt(id);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
MOZ_CRASH("Should never get here!");
|
MOZ_CRASH("Should never get here!");
|
||||||
}
|
}
|
||||||
|
@ -15097,6 +15107,22 @@ TransactionBase::VerifyRequestParams(const ObjectStoreAddPutParams& aParams)
|
||||||
}
|
}
|
||||||
|
|
||||||
case StructuredCloneFile::eStructuredClone:
|
case StructuredCloneFile::eStructuredClone:
|
||||||
|
ASSERT_UNLESS_FUZZING();
|
||||||
|
return false;
|
||||||
|
|
||||||
|
case StructuredCloneFile::eWasmBytecode:
|
||||||
|
case StructuredCloneFile::eWasmCompiled:
|
||||||
|
if (NS_WARN_IF(file.type() !=
|
||||||
|
DatabaseOrMutableFile::TPBackgroundIDBDatabaseFileParent)) {
|
||||||
|
ASSERT_UNLESS_FUZZING();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (NS_WARN_IF(!file.get_PBackgroundIDBDatabaseFileParent())) {
|
||||||
|
ASSERT_UNLESS_FUZZING();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case StructuredCloneFile::eEndGuard:
|
case StructuredCloneFile::eEndGuard:
|
||||||
ASSERT_UNLESS_FUZZING();
|
ASSERT_UNLESS_FUZZING();
|
||||||
return false;
|
return false;
|
||||||
|
@ -25545,7 +25571,9 @@ ObjectStoreAddOrPutRequestOp::Init(TransactionBase* aTransaction)
|
||||||
const FileAddInfo& fileAddInfo = fileAddInfos[index];
|
const FileAddInfo& fileAddInfo = fileAddInfos[index];
|
||||||
|
|
||||||
MOZ_ASSERT(fileAddInfo.type() == StructuredCloneFile::eBlob ||
|
MOZ_ASSERT(fileAddInfo.type() == StructuredCloneFile::eBlob ||
|
||||||
fileAddInfo.type() == StructuredCloneFile::eMutableFile);
|
fileAddInfo.type() == StructuredCloneFile::eMutableFile ||
|
||||||
|
fileAddInfo.type() == StructuredCloneFile::eWasmBytecode ||
|
||||||
|
fileAddInfo.type() == StructuredCloneFile::eWasmCompiled);
|
||||||
|
|
||||||
const DatabaseOrMutableFile& file = fileAddInfo.file();
|
const DatabaseOrMutableFile& file = fileAddInfo.file();
|
||||||
|
|
||||||
|
@ -25591,6 +25619,29 @@ ObjectStoreAddOrPutRequestOp::Init(TransactionBase* aTransaction)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case StructuredCloneFile::eWasmBytecode:
|
||||||
|
case StructuredCloneFile::eWasmCompiled: {
|
||||||
|
MOZ_ASSERT(file.type() ==
|
||||||
|
DatabaseOrMutableFile::TPBackgroundIDBDatabaseFileParent);
|
||||||
|
|
||||||
|
storedFileInfo->mFileActor =
|
||||||
|
static_cast<DatabaseFile*>(
|
||||||
|
file.get_PBackgroundIDBDatabaseFileParent());
|
||||||
|
MOZ_ASSERT(storedFileInfo->mFileActor);
|
||||||
|
|
||||||
|
storedFileInfo->mFileInfo = storedFileInfo->mFileActor->GetFileInfo();
|
||||||
|
MOZ_ASSERT(storedFileInfo->mFileInfo);
|
||||||
|
|
||||||
|
storedFileInfo->mInputStream =
|
||||||
|
storedFileInfo->mFileActor->GetInputStream();
|
||||||
|
if (storedFileInfo->mInputStream && !mFileManager) {
|
||||||
|
mFileManager = fileManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
storedFileInfo->mType = fileAddInfo.type();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
MOZ_CRASH("Should never get here!");
|
MOZ_CRASH("Should never get here!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -323,6 +323,56 @@ StructuredCloneWriteCallback(JSContext* aCx,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (JS::IsWasmModuleObject(aObj)) {
|
||||||
|
RefPtr<JS::WasmModule> module = JS::GetWasmModule(aObj);
|
||||||
|
MOZ_ASSERT(module);
|
||||||
|
|
||||||
|
size_t bytecodeSize;
|
||||||
|
size_t compiledSize;
|
||||||
|
module->serializedSize(&bytecodeSize, &compiledSize);
|
||||||
|
|
||||||
|
UniquePtr<uint8_t[]> bytecode(new uint8_t[bytecodeSize]);
|
||||||
|
MOZ_ASSERT(bytecode);
|
||||||
|
|
||||||
|
UniquePtr<uint8_t[]> compiled(new uint8_t[compiledSize]);
|
||||||
|
MOZ_ASSERT(compiled);
|
||||||
|
|
||||||
|
module->serialize(bytecode.get(),
|
||||||
|
bytecodeSize,
|
||||||
|
compiled.get(),
|
||||||
|
compiledSize);
|
||||||
|
|
||||||
|
RefPtr<BlobImpl> blobImpl =
|
||||||
|
new BlobImplMemory(bytecode.release(), bytecodeSize, EmptyString());
|
||||||
|
RefPtr<Blob> bytecodeBlob = Blob::Create(nullptr, blobImpl);
|
||||||
|
|
||||||
|
blobImpl =
|
||||||
|
new BlobImplMemory(compiled.release(), compiledSize, EmptyString());
|
||||||
|
RefPtr<Blob> compiledBlob = Blob::Create(nullptr, blobImpl);
|
||||||
|
|
||||||
|
if (cloneWriteInfo->mFiles.Length() + 1 > size_t(UINT32_MAX)) {
|
||||||
|
MOZ_ASSERT(false, "Fix the structured clone data to use a bigger type!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint32_t index = cloneWriteInfo->mFiles.Length();
|
||||||
|
|
||||||
|
if (!JS_WriteUint32Pair(aWriter, SCTAG_DOM_WASM, /* flags */ 0) ||
|
||||||
|
!JS_WriteUint32Pair(aWriter, index, index + 1)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
StructuredCloneFile* newFile = cloneWriteInfo->mFiles.AppendElement();
|
||||||
|
newFile->mBlob = bytecodeBlob;
|
||||||
|
newFile->mType = StructuredCloneFile::eWasmBytecode;
|
||||||
|
|
||||||
|
newFile = cloneWriteInfo->mFiles.AppendElement();
|
||||||
|
newFile->mBlob = compiledBlob;
|
||||||
|
newFile->mType = StructuredCloneFile::eWasmCompiled;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return StructuredCloneHolder::WriteFullySerializableObjects(aCx, aWriter, aObj);
|
return StructuredCloneHolder::WriteFullySerializableObjects(aCx, aWriter, aObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -797,7 +847,8 @@ CommonStructuredCloneReadCallback(JSContext* aCx,
|
||||||
static_assert(SCTAG_DOM_BLOB == 0xffff8001 &&
|
static_assert(SCTAG_DOM_BLOB == 0xffff8001 &&
|
||||||
SCTAG_DOM_FILE_WITHOUT_LASTMODIFIEDDATE == 0xffff8002 &&
|
SCTAG_DOM_FILE_WITHOUT_LASTMODIFIEDDATE == 0xffff8002 &&
|
||||||
SCTAG_DOM_MUTABLEFILE == 0xffff8004 &&
|
SCTAG_DOM_MUTABLEFILE == 0xffff8004 &&
|
||||||
SCTAG_DOM_FILE == 0xffff8005,
|
SCTAG_DOM_FILE == 0xffff8005 &&
|
||||||
|
SCTAG_DOM_WASM == 0xffff8006,
|
||||||
"You changed our structured clone tag values and just ate "
|
"You changed our structured clone tag values and just ate "
|
||||||
"everyone's IndexedDB data. I hope you are happy.");
|
"everyone's IndexedDB data. I hope you are happy.");
|
||||||
|
|
||||||
|
@ -1320,6 +1371,25 @@ IDBObjectStore::AddOrPut(JSContext* aCx,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case StructuredCloneFile::eWasmBytecode:
|
||||||
|
case StructuredCloneFile::eWasmCompiled: {
|
||||||
|
MOZ_ASSERT(file.mBlob);
|
||||||
|
MOZ_ASSERT(!file.mMutableFile);
|
||||||
|
|
||||||
|
PBackgroundIDBDatabaseFileChild* fileActor =
|
||||||
|
database->GetOrCreateFileActorForBlob(file.mBlob);
|
||||||
|
if (NS_WARN_IF(!fileActor)) {
|
||||||
|
IDB_REPORT_INTERNAL_ERR();
|
||||||
|
aRv = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
fileAddInfo->file() = fileActor;
|
||||||
|
fileAddInfo->type() = file.mType;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
MOZ_CRASH("Should never get here!");
|
MOZ_CRASH("Should never get here!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,8 @@ struct StructuredCloneFile
|
||||||
eBlob,
|
eBlob,
|
||||||
eMutableFile,
|
eMutableFile,
|
||||||
eStructuredClone,
|
eStructuredClone,
|
||||||
|
eWasmBytecode,
|
||||||
|
eWasmCompiled,
|
||||||
eEndGuard
|
eEndGuard
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -85,6 +85,21 @@ function getNullFile(name, size)
|
||||||
return getFile(name, "binary/null", getView(size));
|
return getFile(name, "binary/null", getView(size));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isWasmSupported()
|
||||||
|
{
|
||||||
|
let testingFunctions = SpecialPowers.Cu.getJSTestingFunctions();
|
||||||
|
return testingFunctions.wasmIsSupported();
|
||||||
|
}
|
||||||
|
|
||||||
|
function getWasmModule(text)
|
||||||
|
{
|
||||||
|
let testingFunctions = SpecialPowers.Cu.getJSTestingFunctions();
|
||||||
|
let wasmTextToBinary = SpecialPowers.unwrap(testingFunctions.wasmTextToBinary);
|
||||||
|
let binary = wasmTextToBinary(text);
|
||||||
|
let module = new WebAssembly.Module(binary);
|
||||||
|
return module;
|
||||||
|
}
|
||||||
|
|
||||||
function verifyBuffers(buffer1, buffer2)
|
function verifyBuffers(buffer1, buffer2)
|
||||||
{
|
{
|
||||||
ok(compareBuffers(buffer1, buffer2), "Correct buffer data");
|
ok(compareBuffers(buffer1, buffer2), "Correct buffer data");
|
||||||
|
|
|
@ -113,6 +113,7 @@ support-files =
|
||||||
unit/test_transaction_ordering.js
|
unit/test_transaction_ordering.js
|
||||||
unit/test_unique_index_update.js
|
unit/test_unique_index_update.js
|
||||||
unit/test_view_put_get_values.js
|
unit/test_view_put_get_values.js
|
||||||
|
unit/test_wasm_put_get_values.js
|
||||||
unit/test_writer_starvation.js
|
unit/test_writer_starvation.js
|
||||||
|
|
||||||
[test_abort_deleted_index.html]
|
[test_abort_deleted_index.html]
|
||||||
|
@ -390,5 +391,7 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
|
||||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
|
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
|
||||||
[test_view_put_get_values.html]
|
[test_view_put_get_values.html]
|
||||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
|
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
|
||||||
|
[test_wasm_put_get_values.html]
|
||||||
|
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
|
||||||
[test_serviceworker.html]
|
[test_serviceworker.html]
|
||||||
skip-if = buildapp == 'b2g'
|
skip-if = buildapp == 'b2g'
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
<!--
|
||||||
|
Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
-->
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Indexed Database Property Test</title>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
|
||||||
|
<script type="text/javascript;version=1.7" src="unit/test_wasm_put_get_values.js"></script>
|
||||||
|
<script type="text/javascript;version=1.7" src="file.js"></script>
|
||||||
|
<script type="text/javascript;version=1.7" src="helpers.js"></script>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body onload="runTest();"></body>
|
||||||
|
|
||||||
|
</html>
|
|
@ -0,0 +1,68 @@
|
||||||
|
/**
|
||||||
|
* Any copyright is dedicated to the Public Domain.
|
||||||
|
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
*/
|
||||||
|
|
||||||
|
var disableWorkerTest = "Need a way to set temporary prefs from a worker";
|
||||||
|
|
||||||
|
var testGenerator = testSteps();
|
||||||
|
|
||||||
|
function testSteps()
|
||||||
|
{
|
||||||
|
const name =
|
||||||
|
this.window ? window.location.pathname : "test_wasm_put_get_values.js";
|
||||||
|
|
||||||
|
const objectStoreName = "Wasm";
|
||||||
|
|
||||||
|
const wasmData = { key: 1, wasm: null };
|
||||||
|
|
||||||
|
if (this.window) {
|
||||||
|
SpecialPowers.pushPrefEnv({ "set": [["javascript.options.wasm", true]] },
|
||||||
|
continueToNextStep);
|
||||||
|
yield undefined;
|
||||||
|
} else {
|
||||||
|
enableWasm();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isWasmSupported()) {
|
||||||
|
finishTest();
|
||||||
|
yield undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
info("Opening database");
|
||||||
|
|
||||||
|
let request = indexedDB.open(name);
|
||||||
|
request.onerror = errorHandler;
|
||||||
|
request.onupgradeneeded = continueToNextStepSync;
|
||||||
|
request.onsuccess = unexpectedSuccessHandler;
|
||||||
|
yield undefined;
|
||||||
|
|
||||||
|
// upgradeneeded
|
||||||
|
request.onupgradeneeded = unexpectedSuccessHandler;
|
||||||
|
request.onsuccess = continueToNextStepSync;
|
||||||
|
|
||||||
|
info("Creating objectStore");
|
||||||
|
|
||||||
|
request.result.createObjectStore(objectStoreName);
|
||||||
|
|
||||||
|
yield undefined;
|
||||||
|
|
||||||
|
// success
|
||||||
|
let db = request.result;
|
||||||
|
db.onerror = errorHandler;
|
||||||
|
|
||||||
|
info("Storing wasm");
|
||||||
|
|
||||||
|
wasmData.wasm = getWasmModule('(module (func (nop)))');
|
||||||
|
|
||||||
|
let objectStore = db.transaction([objectStoreName], "readwrite")
|
||||||
|
.objectStore(objectStoreName);
|
||||||
|
request = objectStore.add(wasmData.wasm, wasmData.key);
|
||||||
|
request.onsuccess = continueToNextStepSync;
|
||||||
|
yield undefined;
|
||||||
|
|
||||||
|
is(request.result, wasmData.key, "Got correct key");
|
||||||
|
|
||||||
|
finishTest();
|
||||||
|
yield undefined;
|
||||||
|
}
|
|
@ -209,6 +209,11 @@ function resetTesting()
|
||||||
SpecialPowers.clearUserPref("dom.indexedDB.testing");
|
SpecialPowers.clearUserPref("dom.indexedDB.testing");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function enableWasm()
|
||||||
|
{
|
||||||
|
SpecialPowers.setBoolPref("javascript.options.wasm", true);
|
||||||
|
}
|
||||||
|
|
||||||
function gc()
|
function gc()
|
||||||
{
|
{
|
||||||
Cu.forceGC();
|
Cu.forceGC();
|
||||||
|
@ -363,6 +368,20 @@ function getFile(name, type, str)
|
||||||
return new File([str], name, {type: type});
|
return new File([str], name, {type: type});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isWasmSupported()
|
||||||
|
{
|
||||||
|
let testingFunctions = Cu.getJSTestingFunctions();
|
||||||
|
return testingFunctions.wasmIsSupported();
|
||||||
|
}
|
||||||
|
|
||||||
|
function getWasmModule(text)
|
||||||
|
{
|
||||||
|
let testingFunctions = Cu.getJSTestingFunctions();
|
||||||
|
let binary = testingFunctions.wasmTextToBinary(text);
|
||||||
|
let module = new WebAssembly.Module(binary);
|
||||||
|
return module;
|
||||||
|
}
|
||||||
|
|
||||||
function compareBuffers(buffer1, buffer2)
|
function compareBuffers(buffer1, buffer2)
|
||||||
{
|
{
|
||||||
if (buffer1.byteLength != buffer2.byteLength) {
|
if (buffer1.byteLength != buffer2.byteLength) {
|
||||||
|
|
|
@ -59,3 +59,4 @@ skip-if = true
|
||||||
# bug 951017: intermittent failure on Android x86 emulator
|
# bug 951017: intermittent failure on Android x86 emulator
|
||||||
skip-if = os == "android" && processor == "x86"
|
skip-if = os == "android" && processor == "x86"
|
||||||
[test_view_put_get_values.js]
|
[test_view_put_get_values.js]
|
||||||
|
[test_wasm_put_get_values.js]
|
||||||
|
|
Загрузка…
Ссылка в новой задаче