Bug 1340474 - Update web-platform-tests to revision eba2c70d536caaeef540966bc8ac7822417ab867, a=testonly

MozReview-Commit-ID: 1GaV7z8d0Xc

--HG--
rename : testing/web-platform/tests/preload/link_header_preload_delay_onload.html.headers => testing/web-platform/tests/preload/link-header-preload-delay-onload.html.headers
rename : testing/web-platform/tests/preload/link_header_preload.html.headers => testing/web-platform/tests/preload/link-header-preload.html.headers
This commit is contained in:
James Graham 2017-02-15 22:30:36 +00:00
Родитель f6b2508a60
Коммит 129682804e
612 изменённых файлов: 16847 добавлений и 7110 удалений

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,2 +1,2 @@
local: 6d8a9012bf2a909aedba28cd25b13f322f7b9a82
upstream: d93247d5cb7d70f80da8b154a171f4e3d50969f4
local: ec3ef9f77a52693e9732ca480df16017af0d9504
upstream: fc4da5233160c1ed5675ae4a7859552cb7e0349f

1
testing/web-platform/tests/.gitignore поставляемый
Просмотреть файл

@ -5,6 +5,7 @@
MANIFEST.json
\#*
_certs
.virtualenv
config.json
node_modules
scratch

Просмотреть файл

@ -1,4 +1,5 @@
dist: trusty
sudo: required
language: python
addons:
hosts:
@ -21,6 +22,10 @@ matrix:
python: "2.7"
env:
- SCRIPT=ci_lint.sh
- os: linux
python: "2.7"
env:
- SCRIPT=ci_built_diff.sh
- os: linux
python: "2.7"
addons:
@ -30,7 +35,7 @@ matrix:
env:
- secure: "YTSXPwI0DyCA1GhYrLT9KMEV6b7QQKuEeaQgeFDP38OTzJ1+cIj3CC4SRNqbnJ/6SJwPGcdqSxLuV8m4e5HFFnyCcQnJe6h8EMsTehZ7W3j/fP9UYrJqYqvGpe3Vj3xblO5pwBYmq7sg3jAmmuCgAgOW6VGf7cRMucrsmFeo7VM="
- SCRIPT=ci_stability.sh
- PRODUCT=firefox
- PRODUCT=firefox:nightly
- os: linux
sudo: required
python: "2.7"
@ -42,10 +47,14 @@ matrix:
env:
- secure: "YTSXPwI0DyCA1GhYrLT9KMEV6b7QQKuEeaQgeFDP38OTzJ1+cIj3CC4SRNqbnJ/6SJwPGcdqSxLuV8m4e5HFFnyCcQnJe6h8EMsTehZ7W3j/fP9UYrJqYqvGpe3Vj3xblO5pwBYmq7sg3jAmmuCgAgOW6VGf7cRMucrsmFeo7VM="
- SCRIPT=ci_stability.sh
- PRODUCT=chrome
- PRODUCT=chrome:unstable
script:
- bash $SCRIPT
cache:
directories:
- $HOME/.cache/pip
notifications:
email:
on_success: never
on_failure: always
webhooks: https://w3c-test.org/prbuildbot.py

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 220 B

После

Ширина:  |  Высота:  |  Размер: 220 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 221 B

После

Ширина:  |  Высота:  |  Размер: 221 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 223 B

После

Ширина:  |  Высота:  |  Размер: 223 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 209 B

После

Ширина:  |  Высота:  |  Размер: 209 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 223 B

После

Ширина:  |  Высота:  |  Размер: 223 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 220 B

После

Ширина:  |  Высота:  |  Размер: 220 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 221 B

После

Ширина:  |  Высота:  |  Размер: 221 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 223 B

После

Ширина:  |  Высота:  |  Размер: 223 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 209 B

После

Ширина:  |  Высота:  |  Размер: 209 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 223 B

После

Ширина:  |  Высота:  |  Размер: 223 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 221 B

После

Ширина:  |  Высота:  |  Размер: 221 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 220 B

После

Ширина:  |  Высота:  |  Размер: 220 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 222 B

После

Ширина:  |  Высота:  |  Размер: 222 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 208 B

После

Ширина:  |  Высота:  |  Размер: 208 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 223 B

После

Ширина:  |  Высота:  |  Размер: 223 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 1.0 KiB

После

Ширина:  |  Высота:  |  Размер: 1.5 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 1.0 KiB

После

Ширина:  |  Высота:  |  Размер: 1.5 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 1.0 KiB

После

Ширина:  |  Высота:  |  Размер: 1.5 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 1.6 KiB

После

Ширина:  |  Высота:  |  Размер: 2.0 KiB

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 222 B

После

Ширина:  |  Высота:  |  Размер: 219 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 222 B

После

Ширина:  |  Высота:  |  Размер: 219 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 401 B

После

Ширина:  |  Высота:  |  Размер: 396 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 262 B

После

Ширина:  |  Высота:  |  Размер: 256 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 253 B

После

Ширина:  |  Высота:  |  Размер: 248 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 231 B

После

Ширина:  |  Высота:  |  Размер: 229 B

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 1.6 KiB

После

Ширина:  |  Высота:  |  Размер: 1.5 KiB

Просмотреть файл

@ -0,0 +1 @@
@gsnedders

Просмотреть файл

@ -45,7 +45,10 @@ import sys
import xml.dom.minidom
from xml.dom.minidom import Node
import cairo
try:
import cairocffi as cairo
except ImportError:
import cairo
try:
import syck as yaml # compatible and lots faster

Просмотреть файл

@ -41,5 +41,6 @@ fallback: "../html/semantics/embedded-content/the-ca
initial: "../html/semantics/embedded-content/the-canvas-element/"
security: "../html/semantics/embedded-content/the-canvas-element/"
size: "../html/semantics/embedded-content/the-canvas-element/"
toBlob: "../html/semantics/embedded-content/the-canvas-element/"
toDataURL: "../html/semantics/embedded-content/the-canvas-element/"
type: "../html/semantics/embedded-content/the-canvas-element/"

Просмотреть файл

@ -448,24 +448,6 @@
- name: toBlob.png
desc: toBlob with image/png returns a PNG Blob
testing:
- toBlob.png
code: |
canvas.toBlob(function(data){
@assert data.type === "image/png";
}, 'image/png');
- name: toBlob.jpeg
desc: toBlob with image/jpeg returns a JPEG Blob
testing:
- toBlob.jpeg
code: |
canvas.toBlob(function(data){
@assert data.type === "image/jpeg";
}, 'image/jpeg');
- name: toDataURL.default
desc: toDataURL with no arguments returns a PNG
testing:
@ -566,9 +548,13 @@
testing:
- toDataURL.noarguments
code: |
var canvas2 = document.createElement('canvas');
var data = canvas2.toDataURL();
@assert data =~ /^data:image\/png[;,]/;
var no_context_data = canvas.toDataURL();
var ctx = canvas.getContext('2d');
ctx.rect(0, 0, 100, 50);
ctx.fillStyle = "rgba(0, 0, 0, 0)";
ctx.fill();
var data = canvas.toDataURL();
assert_equals(no_context_data, data);
- name: toDataURL.zerosize
desc: toDataURL on zero-size canvas returns 'data:,'

Просмотреть файл

@ -58,6 +58,7 @@
reader.onloadend = t.step_func_done(function(event) {
assert_equals(event.target.readyState, FileReader.DONE);
assert_equals(reader.error.code, 8);
assert_true(reader.error instanceof DOMException);
});
}, 'FileReader.error should be NOT_FOUND_ERR if the file is not found when reading');
@ -68,4 +69,4 @@
</script>
</body>
</html>
</html>

Просмотреть файл

@ -1,39 +0,0 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Blob.close</title>
<link rel=help href="http://dev.w3.org/2006/webapi/FileAPI/#dfn-close">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../support/Blob.js"></script>
<div id="log"></div>
<script>
test(function() {
var blob = new Blob(["TEST"]);
var sliced = blob.slice();
blob.close();
async_test(function(t) {
var reader = new FileReader();
reader.onload = t.step_func(function(evt) {
assert_unreached("Should not dispatch the load event");
});
reader.onerror = t.step_func(function(e) {
assert_equals(reader.result, null);
assert_equals(reader.error.code, DOMException.INVALID_STATE_ERR);
t.done();
});
reader.readAsText(blob, "UTF-8");
}, "Closed Blob");
test_blob(function() {
return sliced;
}, {
expected: "TEST",
type: "",
desc: "Slice should still have the data."
});
});
</script>

Просмотреть файл

@ -36,6 +36,18 @@
assert_false(prefixes[i]+'BlobBuilder' in window, prefixes[i]+'BlobBuilder');
}
}, 'BlobBuilder should not be supported.');
test(function() {
assert_false('createFor' in URL);
}, 'createFor method should not be supported');
test(function() {
var b = new Blob();
assert_false('close' in b, 'close in b');
assert_false('close' in Blob.prototype, 'close in Blob.prototype');
assert_false('isClosed' in b, 'isClosed in b');
assert_false('isClosed' in Blob.prototype, 'isClosed in Blob.prototype');
}, 'Blob.close() should not be supported');
</script>
</body>
</html>

Просмотреть файл

@ -55,15 +55,12 @@ interface Blob {
readonly attribute unsigned long long size;
readonly attribute DOMString type;
readonly attribute boolean isClosed;
//slice Blob into byte-ranged chunks
Blob slice([Clamp] optional long long start,
[Clamp] optional long long end,
optional DOMString contentType);
void close();
};
dictionary BlobPropertyBag {
@ -111,7 +108,7 @@ interface FileReader: EventTarget {
// File or Blob data
readonly attribute (DOMString or ArrayBuffer)? result;
readonly attribute DOMError? error;
readonly attribute DOMException? error;
// event handler attributes
attribute EventHandler onloadstart;
@ -136,7 +133,6 @@ interface FileReaderSync {
partial interface URL {
static DOMString createObjectURL(Blob blob);
static DOMString createFor(Blob blob);
static void revokeObjectURL(DOMString url);
};

Просмотреть файл

@ -6,15 +6,12 @@ interface Blob {
readonly attribute unsigned long long size;
readonly attribute DOMString type;
readonly attribute boolean isClosed;
//slice Blob into byte-ranged chunks
Blob slice([Clamp] optional long long start,
[Clamp] optional long long end,
optional DOMString contentType);
void close();
};
dictionary BlobPropertyBag {
@ -64,7 +61,7 @@ interface FileReader: EventTarget {
// File or Blob data
readonly attribute (DOMString or ArrayBuffer)? result;
readonly attribute DOMError? error;
readonly attribute DOMException? error;
// event handler content attributes
attribute EventHandler onloadstart;
@ -89,6 +86,5 @@ interface FileReaderSync {
[Exposed=(Window,DedicatedWorker,SharedWorker)]
partial interface URL {
static DOMString createObjectURL(Blob blob);
static DOMString createFor(Blob blob);
static void revokeObjectURL(DOMString url);
};

Просмотреть файл

@ -69,5 +69,5 @@ async_test(function() {
});
reader.readAsArrayBuffer(blob_1)
assert_equals(reader.readyState, FileReader.LOADING, "readyState Must be LOADING")
}, 'test FileReader no InvalidStateError exception in onloadstart event for readAsArrayBuffer');
}, 'test FileReader no InvalidStateError exception in loadend event handler for readAsArrayBuffer');
</script>

Просмотреть файл

@ -19,28 +19,35 @@
assert_equals(readerNoRead.result, null);
}, "Aborting before read");
async_test(function() {
var blob = new Blob(["TEST THE ABORT METHOD"]);
var readerAbort = new FileReader();
promise_test(t => {
var blob = new Blob(["TEST THE ABORT METHOD"]);
var readerAbort = new FileReader();
readerAbort.onabort = this.step_func(function(evt) {
assert_equals(readerAbort.readyState, readerAbort.DONE);
});
var eventWatcher = new EventWatcher(t, readerAbort,
['abort', 'loadstart', 'loadend', 'error', 'load']);
readerAbort.onloadstart = this.step_func(function(evt) {
assert_equals(readerAbort.readyState, readerAbort.LOADING);
readerAbort.abort();
});
// EventWatcher doesn't let us inspect the state after the abort event,
// so add an extra event handler for that.
readerAbort.addEventListener('abort', t.step_func(e => {
assert_equals(readerAbort.readyState, readerAbort.DONE);
}));
readerAbort.onloadend = this.step_func(function(evt) {
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=24401
assert_equals(readerAbort.result, null);
assert_equals(readerAbort.readyState, readerAbort.DONE);
this.done();
});
readerAbort.readAsText(blob);
}, "Aborting after read");
readerAbort.readAsText(blob);
return eventWatcher.wait_for('loadstart')
.then(() => {
assert_equals(readerAbort.readyState, readerAbort.LOADING);
// 'abort' and 'loadend' events are dispatched synchronously, so
// call wait_for before calling abort.
var nextEvent = eventWatcher.wait_for(['abort', 'loadend']);
readerAbort.abort();
return nextEvent;
})
.then(() => {
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=24401
assert_equals(readerAbort.result, null);
assert_equals(readerAbort.readyState, readerAbort.DONE);
});
}, "Aborting after read");
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,7 @@
<!DOCTYPE html>
<title>Relevant/current/blob source page used as a test helper</title>
<script>
"use strict";
document.domain = "{{host}}";
</script>

Просмотреть файл

@ -0,0 +1,22 @@
<!DOCTYPE html>
<title>Incumbent page used as a test helper</title>
<iframe src="//{{domains[www1]}}:{{location[port]}}/FileAPI/support/document-domain-setter.sub.html" id="c"></iframe>
<iframe src="//{{domains[www2]}}:{{location[port]}}/FileAPI/support/document-domain-setter.sub.html" id="r"></iframe>
<iframe src="//{{domains[élève]}}:{{location[port]}}/FileAPI/support/document-domain-setter.sub.html" id="bs"></iframe>
<script>
"use strict";
document.domain = "{{host}}";
window.createBlobURL = () => {
const current = document.querySelector("#c").contentWindow;
const relevant = document.querySelector("#r").contentWindow;
const blobSource = document.querySelector("#bs").contentWindow;
const blob = new blobSource.Blob(["Test Blob"]);
return current.URL.createObjectURL.call(relevant, blob);
};
</script>

Просмотреть файл

@ -0,0 +1,6 @@
<!DOCTYPE html>
<script>
const blob = new Blob(["Test Blob"]);
const url = URL.createObjectURL(blob);
window.parent.postMessage({url: url}, '*');
</script>

Просмотреть файл

@ -0,0 +1,66 @@
<!doctype html>
<meta charset="utf-8">
<title>FileAPI Test: Creating Blob URL with Blob</title>
<link rel="author" title="Victor Costan" href="mailto:pwnall@chromium.org">
<link rel="help" href="https://w3c.github.io/FileAPI/#originOfBlobURL">
<link rel="help" href="https://html.spec.whatwg.org/multipage/browsers.html#concept-origin">
<link rel="help" href="https://url.spec.whatwg.org/#url-parsing">
<link rel="help" href="https://fetch.spec.whatwg.org/#main-fetch">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style>
iframe { width: 10px; height: 10px; }
</style>
<iframe id="unconstrained-iframe"></iframe>
<iframe id="sandboxed-iframe" sandbox="allow-scripts"></iframe>
<script id="iframe-srcdoc" language="text/html">
<!doctype html>
<script>
'use strict';
window.onload = () => {
const blob = new Blob(['Hello world!']);
const blobUrl = URL.createObjectURL(blob);
fetch(blobUrl).then(response => response.text()).then(text => {
window.parent.postMessage({ blobUrl, text }, '*');
});
};
// The script tag is closed in readBlobFromUrl().
</script>
<script>
// Carries out the test of minting a Blob URL in an iframe, and reading it back.
//
// Returns a promise resolved with an object with properties blobUrl and text
// (the text read back from the Blob URL).
function readBlobFromUrl(t, iframeSelector) {
return new Promise((resolve, reject) => {
window.onmessage = t.step_func((message) => { resolve(message.data); });
const frame = document.querySelector(iframeSelector);
const html = document.querySelector('#iframe-srcdoc').textContent +
'<' + '/script>';
frame.setAttribute('srcdoc', html);
});
}
promise_test(t => readBlobFromUrl(t, '#unconstrained-iframe').then(data => {
assert_true(data.blobUrl.startsWith('blob:'),
"The Blob's URL should use the blob: scheme");
assert_equals(data.text, 'Hello world!',
"The result of reading the Blob's URL should be the Blob's contents");
}), 'reading a Blob URL in an unconstrained iframe');
promise_test(t => readBlobFromUrl(t, '#sandboxed-iframe').then(data => {
assert_true(data.blobUrl.startsWith('blob:'),
"The Blob's URL should use the blob: scheme");
assert_equals(data.text, 'Hello world!',
"The result of reading the Blob's URL should be the Blob's contents");
}), 'reading a Blob URL in a sandboxed iframe without the same-origin flag');
</script>

Просмотреть файл

@ -0,0 +1,25 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>Blob URL serialization (specifically the origin) in multi-global situations</title>
<link rel="help" href="https://w3c.github.io/FileAPI/#unicodeBlobURL">
<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<!-- this page is the entry global -->
<iframe src="//{{domains[www]}}:{{location[port]}}/FileAPI/support/incumbent.sub.html"></iframe>
<script>
"use strict";
document.domain = "{{host}}";
window.onload = () => {
const url = frames[0].createBlobURL();
const desired = "blob:{{location[scheme]}}://www1";
assert_equals(url.substring(0, desired.length), desired,
"Origin should contain www1, from the current settings object");
done();
};
</script>

Просмотреть файл

@ -0,0 +1,31 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>FileAPI Test: Verify origin of Blob URL</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<script>
test(t => {
const blob = new Blob(["Test Blob"]);
const url = URL.createObjectURL(blob);
assert_equals(new URL(url).origin, location.origin);
assert_true(url.includes(location.origin));
assert_true(url.startsWith('blob:{{location[scheme]}}://'));
}, 'Verify origin of Blob URI matches our origin');
async_test(t => {
const frame = document.createElement('iframe');
self.addEventListener('message', t.step_func(e => {
if (e.source != frame.contentWindow) return;
const url = e.data.url;
assert_false(url.includes('天気の良い日'),
'Origin should be ascii rather than unicode');
assert_equals(new URL(url).origin, e.origin,
'Origin of URL should match origin of frame');
assert_true(url.startsWith('blob:{{location[scheme]}}://xn--'));
t.done();
}));
frame.src = '{{location[scheme]}}://{{domains[天気の良い日]}}:{{location[port]}}/FileAPI/support/url-origin.html';
document.body.appendChild(frame);
}, 'Verify serialization of non-ascii origin in Blob URLs');
</script>

Просмотреть файл

@ -16,11 +16,5 @@
assert_equals(typeof testBlob, "string", "Blob URI is typeof string");
assert_equals(testBlob.indexOf("blob"), 0, "Blob URI starts with 'blob'");
}, "Check if the Blob URI starts with 'blob' using createObjectURL()");
test(function() {
var testBlob = window.URL.createFor(blob);
assert_equals(typeof testBlob, "string", "Blob URI is typeof string");
assert_equals(testBlob.indexOf("blob"), 0, "Blob URI starts with 'blob'");
}, "Check if the Blob URI starts with 'blob' using createFor()");
</script>

Просмотреть файл

@ -38,12 +38,6 @@
assert_equals(blobURL.indexOf("blob"), 0, "Blob URL's scheme is blob");
}, "Check if URL.createObjectURL(File) returns a Blob URL");
test(function() {
blobURL = window.URL.createFor(file);
assert_equals(typeof blobURL, "string", "Blob URL is type of string");
assert_equals(blobURL.indexOf("blob"), 0, "Blob URL's scheme is blob");
}, "Check if URL.createFor(File) returns a Blob URL");
t.done();
});
});

Просмотреть файл

@ -1,4 +1,4 @@
@Velmont
@odinho
@inexorabletash
@chunywang
@dumbmatter

Просмотреть файл

@ -0,0 +1,104 @@
<!doctype html>
<meta charset=utf-8>
<title>IndexedDB: ES bindings - Inject a key into a value</title>
<meta name="help" href="https://w3c.github.io/IndexedDB/#inject-key-into-value">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="support.js"></script>
<script>
indexeddb_test(
(t, db) => {
db.createObjectStore('store');
},
(t, db) => {
const tx = db.transaction('store', 'readwrite');
const request = tx.objectStore('store').put(
'value', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'key']);
const setter_called = false;
Object.defineProperty(Object.prototype, '10', {
configurable: true,
set: t.step_func((value) => { setter_called = true; }),
});
request.onerror = t.unreached_func('request should not fail');
request.onsuccess = t.step_func(() => {
const result = request.result;
assert_false(setter_called,
'Setter should not be called for key result.');
assert_true(
result.hasOwnProperty('10'),
'Result should have own-property overriding prototype setter.');
assert_equals(result[10], 'key',
'Result should have expected property.');
delete Object.prototype['10'];
t.done();
});
},
'Returning keys to script should bypass prototype setters'
);
indexeddb_test(
(t, db) => {
db.createObjectStore('store', {autoIncrement: true, keyPath: 'id'});
},
(t, db) => {
const tx = db.transaction('store', 'readwrite');
tx.objectStore('store').put({});
const request = tx.objectStore('store').get(1);
const setter_called = false;
Object.defineProperty(Object.prototype, 'id', {
configurable: true,
set: t.step_func(function(value) { setter_called = true; }),
});
request.onerror = t.unreached_func('request should not fail');
request.onsuccess = t.step_func(function() {
const result = request.result;
assert_false(setter_called,
'Setter should not be called for key result.');
assert_true(
result.hasOwnProperty('id'),
'Result should have own-property overriding prototype setter.');
assert_equals(result.id, 1,
'Own property should match primary key generator value');
delete Object.prototype['id'];
t.done();
});
},
'Returning values to script should bypass prototype setters'
);
indexeddb_test(
(t, db) => {
db.createObjectStore('store', {autoIncrement: true, keyPath: 'a.b.c'});
},
(t, db) => {
const tx = db.transaction('store', 'readwrite');
tx.objectStore('store').put({});
const request = tx.objectStore('store').get(1);
Object.prototype.a = {b: {c: 'on proto'}};
request.onerror = t.unreached_func('request should not fail');
request.onsuccess = t.step_func(function() {
const result = request.result;
assert_true(result.hasOwnProperty('a'),
'Result should have own-properties overriding prototype.');
assert_true(result.a.hasOwnProperty('b'),
'Result should have own-properties overriding prototype.');
assert_true(result.a.b.hasOwnProperty('c'),
'Result should have own-properties overriding prototype.');
assert_equals(result.a.b.c, 1,
'Own property should match primary key generator value');
assert_equals(Object.prototype.a.b.c, 'on proto',
'Prototype should not be modified');
t.done();
});
},
'Returning values to script should bypass prototype chain'
);
</script>

Просмотреть файл

@ -0,0 +1,135 @@
<!doctype html>
<meta charset=utf-8>
<title>IndexedDB: </title>
<meta name="help" href="https://w3c.github.io/IndexedDB/#dom-idbobjectstore-put">
<meta name="help" href="https://w3c.github.io/IndexedDB/#dom-idbcursor-update">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="support.js"></script>
<script>
function ProbeObject() {
this.id_count = 0;
this.invalid_id_count = 0;
this.prop_count = 0;
Object.defineProperties(this, {
id: {
enumerable: true,
get() {
++this.id_count;
return 1000 + this.id_count;
},
},
invalid_id: {
enumerable: true,
get() {
++this.invalid_id_count;
return {};
},
},
prop: {
enumerable: true,
get() {
++this.prop_count;
return 2000 + this.prop_count;
},
},
});
}
indexeddb_test(
(t, db) => {
db.createObjectStore('store', {keyPath: 'id', autoIncrement: true});
},
(t, db) => {
const tx = db.transaction('store', 'readwrite');
const store = tx.objectStore('store');
const obj = new ProbeObject();
store.put(obj);
assert_equals(
obj.id_count, 1,
'put() operation should access primary key property once');
assert_equals(
obj.prop_count, 1,
'put() operation should access other properties once');
t.done();
}, 'Key generator and key path validity check operates on a clone');
indexeddb_test(
(t, db) => {
db.createObjectStore('store', {keyPath: 'invalid_id', autoIncrement: true});
},
(t, db) => {
const tx = db.transaction('store', 'readwrite');
const store = tx.objectStore('store');
const obj = new ProbeObject();
assert_throws('DataError', () => { store.put(obj); },
'put() should throw if primary key cannot be injected');
assert_equals(
obj.invalid_id_count, 1,
'put() operation should access primary key property once');
assert_equals(
obj.prop_count, 1,
'put() operation should access other properties once');
t.done();
}, 'Failing key path validity check operates on a clone');
indexeddb_test(
(t, db) => {
const store = db.createObjectStore('store');
store.createIndex('index', 'prop');
},
(t, db) => {
const tx = db.transaction('store', 'readwrite');
const store = tx.objectStore('store');
const obj = new ProbeObject();
store.put(obj, 'key');
assert_equals(
obj.prop_count, 1, 'put() should access index key property once');
assert_equals(
obj.id_count, 1,
'put() operation should access other properties once');
t.done();
}, 'Index key path evaluations operate on a clone');
indexeddb_test(
(t, db) => {
const store = db.createObjectStore('store', {keyPath: 'id'});
store.createIndex('index', 'prop');
},
(t, db) => {
const tx = db.transaction('store', 'readwrite');
const store = tx.objectStore('store');
const obj = new ProbeObject();
store.put(obj);
assert_equals(
obj.id_count, 1, 'put() should access primary key property once');
assert_equals(
obj.prop_count, 1, 'put() should access index key property once');
t.done();
}, 'Store and index key path evaluations operate on the same clone');
indexeddb_test(
(t, db) => {
const store = db.createObjectStore('store', {keyPath: 'id'});
store.createIndex('index', 'prop');
},
(t, db) => {
const tx = db.transaction('store', 'readwrite');
const store = tx.objectStore('store');
store.put(new ProbeObject());
store.openCursor().onsuccess = t.step_func((event) => {
const cursor = event.target.result;
const obj = new ProbeObject();
cursor.update(obj);
assert_equals(
obj.id_count, 1, 'put() should access primary key property once');
assert_equals(
obj.prop_count, 1, 'put() should access index key property once');
t.done();
});
}, 'Cursor update checks and keypath evaluations operate on a clone');
</script>

Просмотреть файл

@ -0,0 +1,27 @@
<!doctype html>
<meta charset=utf-8>
<title>IndexedDB: delete requests are processed as a FIFO queue</title>
<link rel="help" href="https://w3c.github.io/IndexedDB/#request-connection-queue">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="support.js"></script>
<script>
let saw;
indexeddb_test(
(t, db) => {
saw = expect(t, ['delete1', 'delete2']);
let r = indexedDB.deleteDatabase(db.name);
r.onerror = t.unreached_func('delete should succeed');
r.onsuccess = t.step_func(e => saw('delete1'));
},
(t, db) => {
let r = indexedDB.deleteDatabase(db.name);
r.onerror = t.unreached_func('delete should succeed');
r.onsuccess = t.step_func(e => saw('delete2'));
db.close();
},
'Deletes are processed in order');
</script>

Просмотреть файл

@ -0,0 +1,51 @@
<!doctype html>
<meta charset=utf-8>
<title>IndexedDB: Detached buffers supplied as binary keys</title>
<meta name="help" href="http://w3c.github.io/IndexedDB/#convert-a-value-to-a-key">
<meta name="help" href="https://heycam.github.io/webidl/#dfn-get-buffer-source-copy">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="support.js"></script>
<script>
indexeddb_test(
(t, db) => { db.createObjectStore('store'); },
(t, db) => {
const tx = db.transaction('store', 'readwrite');
const store = tx.objectStore('store');
const buffer = new Uint8Array([1,2,3,4]).buffer;
assert_equals(buffer.byteLength, 4);
// Detach the ArrayBuffer by transferring it to a worker.
const worker = new Worker(URL.createObjectURL(new Blob([])));
worker.postMessage('', [buffer]);
assert_equals(buffer.byteLength, 0);
assert_throws(new TypeError, () => { store.put('', buffer); });
t.done();
},
'Detached ArrayBuffer'
);
indexeddb_test(
(t, db) => { db.createObjectStore('store'); },
(t, db) => {
const tx = db.transaction('store', 'readwrite');
const store = tx.objectStore('store');
const array = new Uint8Array([1,2,3,4]);
assert_equals(array.length, 4);
// Detach the ArrayBuffer by transferring it to a worker.
const worker = new Worker(URL.createObjectURL(new Blob([])));
worker.postMessage('', [array.buffer]);
assert_equals(array.length, 0);
assert_throws(new TypeError, () => { store.put('', array); });
t.done();
},
'Detached TypedArray'
);
</script>

Просмотреть файл

@ -0,0 +1,115 @@
<!doctype html>
<meta charset=utf-8>
<title>IndexedDB: Binary keys written to a database and read back</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="support.js"></script>
<script>
const sample = [0x44, 0x33, 0x22, 0x11, 0xFF, 0xEE, 0xDD, 0xCC];
const buffer = new Uint8Array(sample).buffer;
function assert_key_valid(a, message) {
assert_equals(indexedDB.cmp(a, a), 0, message);
}
function assert_buffer_equals(a, b, message) {
assert_array_equals(
Array.from(new Uint8Array(a)), Array.from(new Uint8Array(b)), message);
}
// Verifies that a JavaScript value round-trips through IndexedDB as a key.
function check_key_roundtrip_and_done(t, db, key, key_buffer) {
const tx = db.transaction('store', 'readwrite');
const store = tx.objectStore('store');
// Verify put with key
const put_request = store.put('value', key);
put_request.onerror = t.unreached_func('put should succeed');
// Verify get with key
const get_request = store.get(key);
get_request.onerror = t.unreached_func('get should succeed');
get_request.onsuccess = t.step_func(() => {
assert_equals(
get_request.result, 'value',
'get should retrieve the value given to put');
// Verify iteration returning key
const cursor_request = store.openCursor();
cursor_request.onerror = t.unreached_func('openCursor should succeed');
cursor_request.onsuccess = t.step_func(() => {
assert_not_equals(
cursor_request.result, null, 'cursor should be present');
const retrieved_key = cursor_request.result.key;
assert_true(
retrieved_key instanceof ArrayBuffer,
'IndexedDB binary keys should be returned in ArrayBuffer instances');
assert_key_equals(
retrieved_key, key,
'The key returned by IndexedDB should equal the key given to put()');
assert_buffer_equals(
retrieved_key, key_buffer,
'The ArrayBuffer returned by IndexedDB should equal the buffer ' +
'backing the key given to put()');
t.done();
});
});
}
// Checks that IndexedDB handles the given view type for binary keys correctly.
function view_type_test(type) {
indexeddb_test(
(t, db) => { db.createObjectStore('store'); },
(t, db) => {
const key = new self[type](buffer);
assert_key_valid(key, `${type} should be usable as an IndexedDB key`);
assert_key_equals(key, buffer,
'Binary keys with the same data but different view types should be ' +
' equal');
check_key_roundtrip_and_done(t, db, key, buffer);
},
`Binary keys can be supplied using the view type ${type}`,
);
}
[
'Uint8Array',
'Uint8ClampedArray',
'Int8Array',
'Uint16Array',
'Int16Array',
'Uint32Array',
'Int32Array',
'Float32Array',
'Float64Array'
].forEach((type) => { view_type_test(type); });
// Checks that IndexedDB
function value_test(value_description, value, value_buffer) {
indexeddb_test(
(t, db) => { db.createObjectStore('store'); },
(t, db) => {
assert_key_valid(
value, value_description + ' should be usable as an valid key');
check_key_roundtrip_and_done(t, db, value, value_buffer);
},
`${value_description} can be used to supply a binary key`
);
}
value_test('ArrayBuffer', buffer, buffer);
value_test('DataView', new DataView(buffer), buffer);
value_test('DataView with explicit offset', new DataView(buffer, 3),
new Uint8Array([0x11, 0xFF, 0xEE, 0xDD, 0xCC]).buffer);
value_test('DataView with explicit offset and length',
new DataView(buffer, 3, 4),
new Uint8Array([0x11, 0xFF, 0xEE, 0xDD]).buffer);
value_test('Uint8Array with explicit offset', new Uint8Array(buffer, 3),
new Uint8Array([0x11, 0xFF, 0xEE, 0xDD, 0xCC]).buffer);
value_test('Uint8Array with explicit offset and length',
new Uint8Array(buffer, 3, 4),
new Uint8Array([0x11, 0xFF, 0xEE, 0xDD]).buffer);
</script>

Просмотреть файл

@ -1,4 +1,5 @@
<!DOCTYPE html>
<!doctype html>
<meta charset="utf8">
<title>IndexedDB: index renaming support in aborted transactions</title>
<link rel="help"
href="https://w3c.github.io/IndexedDB/#dom-idbindex-name">
@ -7,6 +8,7 @@
<script src="/resources/testharnessreport.js"></script>
<script src="support-promises.js"></script>
<script>
'use strict';
promise_test(testCase => {
const dbName = databaseName(testCase);

Просмотреть файл

@ -1,4 +1,5 @@
<!DOCTYPE html>
<!doctype html>
<meta charset="utf8">
<title>IndexedDB: index renaming error handling</title>
<link rel="help"
href="https://w3c.github.io/IndexedDB/#dom-idbindex-name">
@ -7,6 +8,7 @@
<script src="/resources/testharnessreport.js"></script>
<script src="support-promises.js"></script>
<script>
'use strict';
promise_test(testCase => {
return createDatabase(testCase, (database, transaction) => {

Просмотреть файл

@ -1,4 +1,5 @@
<!DOCTYPE html>
<!doctype html>
<meta charset="utf8">
<meta name="timeout" content="long">
<title>IndexedDB: index renaming support</title>
<link rel="help"
@ -8,6 +9,7 @@
<script src="/resources/testharnessreport.js"></script>
<script src="support-promises.js"></script>
<script>
'use strict';
promise_test(testCase => {
let authorIndex = null, authorIndex2 = null;

Просмотреть файл

@ -1,61 +1,140 @@
<!doctype html>
<meta charset=utf-8>
<title></title>
<title>IndexedDB: IDBKeyRange.includes()</title>
<meta name="help" href="https://w3c.github.io/IndexedDB/#keyrange">
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script>
test(function() {
var closedRange = IDBKeyRange.bound(5, 20);
assert_true(!!closedRange.includes, "IDBKeyRange has a .includes");
assert_true(closedRange.includes(7), "in range");
assert_false(closedRange.includes(1), "below range");
assert_false(closedRange.includes(42), "above range");
assert_true(closedRange.includes(5) && closedRange.includes(20),
"boundary points");
assert_throws("DataError", function() { closedRange.includes({}) },
"invalid key");
}, "IDBKeyRange.includes() with a closed range");
test(function() {
var range = IDBKeyRange.bound(12, 34);
assert_throws(new TypeError, function() { range.includes(); },
'throws if key is not specified');
test(function() {
var openRange = IDBKeyRange.bound(5, 20, true, true);
assert_false(openRange.includes(5) || openRange.includes(20),
"boundary points");
}, "IDBKeyRange.includes() with an open range");
assert_throws('DataError', function() { range.includes(undefined); },
'throws if key is undefined');
assert_throws('DataError', function() { range.includes(null); },
'throws if key is null');
assert_throws('DataError', function() { range.includes({}); },
'throws if key is not valid type');
assert_throws('DataError', function() { range.includes(NaN); },
'throws if key is not valid number');
assert_throws('DataError', function() { range.includes(new Date(NaN)); },
'throws if key is not valid date');
assert_throws('DataError', function() {
var a = []; a[0] = a; range.includes(a);
}, 'throws if key is not valid array');
}, "IDBKeyRange.includes() with invalid input");
test(function() {
var range = IDBKeyRange.only(42);
assert_true(range.includes(42), "in range");
assert_false(range.includes(1), "below range");
assert_false(range.includes(9000), "above range");
}, "IDBKeyRange.includes() with an only range");
test(function() {
var closedRange = IDBKeyRange.bound(5, 20);
assert_true(!!closedRange.includes, "IDBKeyRange has a .includes");
assert_true(closedRange.includes(7), "in range");
assert_false(closedRange.includes(1), "below range");
assert_false(closedRange.includes(42), "above range");
assert_true(closedRange.includes(5.01), "at the lower end of the range");
assert_true(closedRange.includes(19.99), "at the upper end of the range");
assert_false(closedRange.includes(4.99), "right below range");
assert_false(closedRange.includes(21.01), "right above range");
test(function() {
var range = IDBKeyRange.lowerBound(5);
assert_false(range.includes(4), 'value before closed lower bound');
assert_true(range.includes(5), 'value at closed lower bound');
assert_true(range.includes(6), 'value after closed lower bound');
}, "IDBKeyRange.includes() with an closed lower-bounded range");
assert_true(closedRange.includes(5), "lower boundary");
assert_true(closedRange.includes(20), "upper boundary");
}, "IDBKeyRange.includes() with a closed range");
test(function() {
var range = IDBKeyRange.lowerBound(5, true);
assert_false(range.includes(4), 'value before open lower bound');
assert_false(range.includes(5), 'value at open lower bound');
assert_true(range.includes(6), 'value after open lower bound');
}, "IDBKeyRange.includes() with an open lower-bounded range");
test(function() {
var closedRange = IDBKeyRange.bound(5, 20, true, true);
assert_true(closedRange.includes(7), "in range");
assert_false(closedRange.includes(1), "below range");
assert_false(closedRange.includes(42), "above range");
assert_true(closedRange.includes(5.01), "at the lower end of the range");
assert_true(closedRange.includes(19.99), "at the upper end of the range");
assert_false(closedRange.includes(4.99), "right below range");
assert_false(closedRange.includes(21.01), "right above range");
test(function() {
var range = IDBKeyRange.upperBound(5);
assert_true(range.includes(4), 'value before closed upper bound');
assert_true(range.includes(5), 'value at closed upper bound');
assert_false(range.includes(6), 'value after closed upper bound');
}, "IDBKeyRange.includes() with an closed upper-bounded range");
assert_false(closedRange.includes(5), "lower boundary");
assert_false(closedRange.includes(20), "upper boundary");
}, "IDBKeyRange.includes() with an open range");
test(function() {
var range = IDBKeyRange.upperBound(5, true);
assert_true(range.includes(4), 'value before open upper bound');
assert_false(range.includes(5), 'value at open upper bound');
assert_false(range.includes(6), 'value after open upper bound');
}, "IDBKeyRange.includes() with an open upper-bounded range");
test(function() {
var range = IDBKeyRange.bound(5, 20, true);
assert_true(range.includes(7), "in range");
assert_false(range.includes(1), "below range");
assert_false(range.includes(42), "above range");
assert_true(range.includes(5.01), "at the lower end of the range");
assert_true(range.includes(19.99), "at the upper end of the range");
assert_false(range.includes(4.99), "right below range");
assert_false(range.includes(21.01), "right above range");
assert_false(range.includes(5), "lower boundary");
assert_true(range.includes(20), "upper boundary");
}, "IDBKeyRange.includes() with a lower-open upper-closed range");
test(function() {
var range = IDBKeyRange.bound(5, 20, false, true);
assert_true(range.includes(7), "in range");
assert_false(range.includes(1), "below range");
assert_false(range.includes(42), "above range");
assert_true(range.includes(5.01), "at the lower end of the range");
assert_true(range.includes(19.99), "at the upper end of the range");
assert_false(range.includes(4.99), "right below range");
assert_false(range.includes(21.01), "right above range");
assert_true(range.includes(5), "lower boundary");
assert_false(range.includes(20), "upper boundary");
}, "IDBKeyRange.includes() with a lower-closed upper-open range");
test(function() {
var onlyRange = IDBKeyRange.only(42);
assert_true(onlyRange.includes(42), "in range");
assert_false(onlyRange.includes(1), "below range");
assert_false(onlyRange.includes(9000), "above range");
assert_false(onlyRange.includes(41), "right below range");
assert_false(onlyRange.includes(43), "right above range");
}, "IDBKeyRange.includes() with an only range");
test(function() {
var range = IDBKeyRange.lowerBound(5);
assert_false(range.includes(4), 'value before closed lower bound');
assert_true(range.includes(5), 'value at closed lower bound');
assert_true(range.includes(6), 'value after closed lower bound');
assert_true(range.includes(42), 'value way after open lower bound');
}, "IDBKeyRange.includes() with an closed lower-bounded range");
test(function() {
var range = IDBKeyRange.lowerBound(5, true);
assert_false(range.includes(4), 'value before open lower bound');
assert_false(range.includes(5), 'value at open lower bound');
assert_true(range.includes(6), 'value after open lower bound');
assert_true(range.includes(42), 'value way after open lower bound');
}, "IDBKeyRange.includes() with an open lower-bounded range");
test(function() {
var range = IDBKeyRange.upperBound(5);
assert_true(range.includes(-42), 'value way before closed upper bound');
assert_true(range.includes(4), 'value before closed upper bound');
assert_true(range.includes(5), 'value at closed upper bound');
assert_false(range.includes(6), 'value after closed upper bound');
}, "IDBKeyRange.includes() with an closed upper-bounded range");
test(function() {
var range = IDBKeyRange.upperBound(5, true);
assert_true(range.includes(-42), 'value way before closed upper bound');
assert_true(range.includes(4), 'value before open upper bound');
assert_false(range.includes(5), 'value at open upper bound');
assert_false(range.includes(6), 'value after open upper bound');
}, "IDBKeyRange.includes() with an open upper-bounded range");
test(function(t) {
assert_true(IDBKeyRange.bound(new Date(0), new Date())
.includes(new Date(102729600000)));
assert_false(IDBKeyRange.bound(new Date(0), new Date(1e11))
.includes(new Date(1e11 + 1)));
assert_true(IDBKeyRange.bound('a', 'c').includes('b'));
assert_false(IDBKeyRange.bound('a', 'c').includes('d'));
assert_true(IDBKeyRange.bound([], [[], []]).includes([[]]));
assert_false(IDBKeyRange.bound([], [[]]).includes([[[]]]));
}, 'IDBKeyRange.includes() with non-numeric keys');
</script>

Просмотреть файл

@ -1,4 +1,5 @@
<!DOCTYPE html>
<!doctype html>
<meta charset="utf8">
<title>IndexedDB: object store renaming support in aborted transactions</title>
<link rel="help"
href="https://w3c.github.io/IndexedDB/#dom-idbobjectstore-name">
@ -7,6 +8,7 @@
<script src="/resources/testharnessreport.js"></script>
<script src="support-promises.js"></script>
<script>
'use strict';
promise_test(testCase => {
const dbName = databaseName(testCase);

Просмотреть файл

@ -1,4 +1,5 @@
<!DOCTYPE html>
<!doctype html>
<meta charset="utf8">
<title>IndexedDB: object store renaming error handling</title>
<link rel="help"
href="https://w3c.github.io/IndexedDB/#dom-idbobjectstore-name">
@ -7,6 +8,7 @@
<script src="/resources/testharnessreport.js"></script>
<script src="support-promises.js"></script>
<script>
'use strict';
promise_test(testCase => {
return createDatabase(testCase, (database, transaction) => {

Просмотреть файл

@ -1,4 +1,5 @@
<!DOCTYPE html>
<!doctype html>
<meta charset="utf8">
<meta name="timeout" content="long">
<title>IndexedDB: object store renaming support</title>
<link rel="help"
@ -8,6 +9,7 @@
<script src="/resources/testharnessreport.js"></script>
<script src="support-promises.js"></script>
<script>
'use strict';
// Renames the 'books' store to 'renamed_books'.
//

Просмотреть файл

@ -0,0 +1,105 @@
<!doctype html>
<meta charset=utf-8>
<title>IndexedDB: Test IDBObjectStore.getKey()</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
function getkey_test(func, name) {
return async_test(function(t) {
var del = indexedDB.deleteDatabase(name);
del.onerror = t.unreached_func('deleteDatabase failed');
var open = indexedDB.open(name);
open.onerror = t.unreached_func('open failed');
open.onupgradeneeded = t.step_func(function() {
var db = open.result;
var basic = db.createObjectStore('basic');
var key_path_store = db.createObjectStore('key path',
{keyPath: 'id'});
var key_generator_store = db.createObjectStore('key generator',
{autoIncrement: true});
var key_generator_and_path_store = db.createObjectStore(
'key generator and key path',
{autoIncrement: true, key_path: 'id'});
for (var i = 1; i <= 10; ++i) {
basic.put('value: ' + i, i);
key_path_store.put({id: i});
key_generator_store.put('value: ' + i);
key_generator_and_path_store.put({});
}
});
open.onsuccess = t.step_func(function() {
var db = open.result;
func(t, db);
});
}, name);
}
getkey_test(function(t, db) {
var tx = db.transaction('basic');
var store = tx.objectStore('basic');
assert_throws(TypeError(), function() { store.getKey(); });
assert_throws({name: 'DataError'}, function() { store.getKey(null); });
assert_throws({name: 'DataError'}, function() { store.getKey({}); });
t.done();
}, 'IDBObjectStore.getKey() - invalid parameters');
[
'basic',
'key path',
'key generator',
'key generator and key path'
].forEach(function(store_name) {
getkey_test(function(t, db) {
var tx = db.transaction(store_name);
var store = tx.objectStore(store_name);
var request = store.getKey(5);
request.onerror = t.unreached_func('request failed');
request.onsuccess = t.step_func(function() {
assert_equals(request.result, 5);
});
tx.onabort = t.unreached_func('transaction aborted');
tx.oncomplete = t.step_func(function() { t.done(); });
}, 'IDBObjectStore.getKey() - ' + store_name + ' - key');
getkey_test(function(t, db) {
var tx = db.transaction(store_name);
var store = tx.objectStore(store_name);
var request = store.getKey(IDBKeyRange.lowerBound(4.5));
request.onerror = t.unreached_func('request failed');
request.onsuccess = t.step_func(function() {
assert_equals(request.result, 5);
});
tx.onabort = t.unreached_func('transaction aborted');
tx.oncomplete = t.step_func(function() { t.done(); });
}, 'IDBObjectStore.getKey() - ' + store_name + ' - range');
getkey_test(function(t, db) {
var tx = db.transaction(store_name);
var store = tx.objectStore(store_name);
var request = store.getKey(11);
request.onerror = t.unreached_func('request failed');
request.onsuccess = t.step_func(function() {
assert_equals(request.result, undefined);
});
tx.onabort = t.unreached_func('transaction aborted');
tx.oncomplete = t.step_func(function() { t.done(); });
}, 'IDBObjectStore.getKey() - ' + store_name + ' - key - no match');
getkey_test(function(t, db) {
var tx = db.transaction(store_name);
var store = tx.objectStore(store_name);
var request = store.getKey(IDBKeyRange.lowerBound(11));
request.onerror = t.unreached_func('request failed');
request.onsuccess = t.step_func(function() {
assert_equals(request.result, undefined);
});
tx.onabort = t.unreached_func('transaction aborted');
tx.oncomplete = t.step_func(function() { t.done(); });
}, 'IDBObjectStore.getKey() - ' + store_name + ' - range - no match');
});
</script>

Просмотреть файл

@ -0,0 +1,140 @@
<!doctype html>
<meta charset=utf-8>
<title>IndexedDB: UpgradeNeeded Tests</title>
<meta name="help" href="https://w3c.github.io/IndexedDB/#commit-transaction">
<meta name="help" href="https://w3c.github.io/IndexedDB/#dom-idbfactory-open">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
function upgradeneeded_test(upgrade_func, success_func, error_func, description) {
async_test(function(t) {
var dbName = 'db' + self.location.pathname + '-' + description;
var delete_request = indexedDB.deleteDatabase(dbName);
delete_request.onerror = t.unreached_func('deleteDatabase should not fail');
delete_request.onsuccess = t.step_func(function() {
var open_request = indexedDB.open(dbName);
open_request.onupgradeneeded = t.step_func(function() {
upgrade_func(t, open_request);
});
open_request.onsuccess = t.step_func(function() {
success_func(t, open_request);
});
if (error_func) {
open_request.onerror = function() { error_func(t, open_request); };
} else {
open_request.onerror = t.unreached_func('open failed');
}
});
}, description);
}
(function() {
var order = [];
upgradeneeded_test(
function upgrade(t, request) {
order.push('Upgrade');
var db = request.result;
var deleteRequest = indexedDB.deleteDatabase(db.name);
deleteRequest.onsuccess = t.step_func(function() {
assert_array_equals(order, ['Upgrade', 'Open Success']);
t.done();
});
deleteRequest.onerror = t.unreached_func('delete failed');
},
function success(t, request) {
var db = request.result;
db.close();
order.push('Open Success');
},
null,
'indexedDB.delete called from upgradeneeded handler'
);
}());
(function() {
var order = [];
upgradeneeded_test(
function upgrade(t, request) {
order.push('Upgrade');
request.transaction.abort();
order.push('Upgrade Transaction Aborted');
var db = request.result;
var deleteRequest = indexedDB.deleteDatabase(db.name);
deleteRequest.onsuccess = t.step_func(function() {
assert_array_equals(
order, ['Upgrade', 'Upgrade Transaction Aborted', 'Open Error']);
t.done();
});
deleteRequest.onerror = t.unreached_func('delete failed');
},
function success(t, request) {
t.unreached_func('open should not succeed');
},
function error_func(t, request) {
assert_array_equals(order, ['Upgrade', 'Upgrade Transaction Aborted']);
order.push('Open Error');
},
'Abort transaction before deleting database in upgradeneeded handler'
);
}());
(function() {
var order = [];
upgradeneeded_test(
function upgrade(t, request) {
order.push('Upgrade');
var db = request.result;
var deleteRequest = indexedDB.deleteDatabase(db.name);
request.transaction.abort();
order.push('Upgrade Transaction Aborted');
deleteRequest.onsuccess = t.step_func(function() {
assert_array_equals(
order, ['Upgrade', 'Upgrade Transaction Aborted', 'Open Error']);
t.done();
});
deleteRequest.onerror = t.unreached_func('delete failed');
},
function success(t, request) {
t.unreached_func('open should not succeed');
},
function error_func(t, request) {
assert_array_equals(order, ['Upgrade', 'Upgrade Transaction Aborted']);
order.push('Open Error');
},
'Abort transaction after deleting database in upgradeneeded event handler'
);
}());
(function() {
var order = [];
upgradeneeded_test(
function upgrade(t, request) {
order.push('Upgrade');
var db = request.result;
db.createObjectStore('store');
request.transaction.oncomplete = t.step_func(function() {
order.push('Upgrade transaction complete');
var txn = db.transaction('store', 'readwrite');
var store = txn.objectStore('store');
store.put('value', 'key');
txn.oncomplete = t.step_func(function() {
assert_array_equals(
order,
['Upgrade', 'Upgrade transaction complete', 'Open Success']);
t.done();
});
txn.onerror = t.unreached_func('error on transaction');
txn.onabort = t.unreached_func('aborting transaction');
});
},
function success(t, request) {
order.push('Open Success');
},
null,
'transaction oncomplete ordering relative to open request onsuccess'
);
}());
</script>

Просмотреть файл

@ -51,10 +51,28 @@
var deleterq = indexedDB.deleteDatabase('db');
deleterq.onsuccess = t.step_func(function(e) {
assert_equals(e.result, undefined, "result (delete.success for nonexistent db)");
assert_equals(e.oldVersion, 3, "old version (delete.success)");
assert_equals(e.newVersion, null, "new version (delete.success)");
assert_true(e instanceof IDBVersionChangeEvent, "delete.success instanceof IDBVersionChangeEvent");
setTimeout(deleteNonExistentDB, 10);
});
// Errors
deleterq.onerror = fail(t, "delete.error");
deleterq.onblocked = fail(t, "delete.blocked");
}
function deleteNonExistentDB (e) {
var deleterq = indexedDB.deleteDatabase('db-does-not-exist');
deleterq.onsuccess = t.step_func(function(e) {
assert_equals(e.result, undefined, "result (delete.success for nonexistent db)");
assert_equals(e.oldVersion, 0, "old version (delete.success for nonexistent db)");
assert_equals(e.newVersion, null, "new version (delete.success for nonexistent db)");
assert_true(e instanceof IDBVersionChangeEvent, "delete.success instanceof IDBVersionChangeEvent");
setTimeout(function() { t.done(); }, 10);
});

Просмотреть файл

@ -0,0 +1,194 @@
<!doctype html>
<meta charset=utf-8>
<title>IndexedDB: Exceptions thrown during key conversion</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="support.js"></script>
<script>
// Convenience function for tests that only need to run code in onupgradeneeded.
function indexeddb_upgrade_only_test(upgrade_callback, description) {
indexeddb_test(upgrade_callback, t => { t.done(); }, description);
}
// Key that throws during conversion.
function throwing_key(name) {
var throws = [];
throws.length = 1;
Object.defineProperty(throws, '0', {get: function() {
var err = new Error('throwing from getter');
err.name = name;
throw err;
}, enumerable: true});
return throws;
}
var valid_key = [];
var invalid_key = {};
// Calls method on receiver with the specified number of args (default 1)
// and asserts that the method fails appropriately (rethrowing if
// conversion throws, or DataError if not a valid key), and that
// the first argument is fully processed before the second argument
// (if appropriate).
function check_method(receiver, method, args) {
args = args || 1;
if (args < 2) {
assert_throws({name:'getter'}, () => {
receiver[method](throwing_key('getter'));
}, 'key conversion with throwing getter should rethrow');
assert_throws('DataError', () => {
receiver[method](invalid_key);
}, 'key conversion with invalid key should throw DataError');
} else {
assert_throws({name:'getter 1'}, () => {
receiver[method](throwing_key('getter 1'), throwing_key('getter 2'));
}, 'first key conversion with throwing getter should rethrow');
assert_throws('DataError', () => {
receiver[method](invalid_key, throwing_key('getter 2'));
}, 'first key conversion with invalid key should throw DataError');
assert_throws({name:'getter 2'}, () => {
receiver[method](valid_key, throwing_key('getter 2'));
}, 'second key conversion with throwing getter should rethrow');
assert_throws('DataError', () => {
receiver[method](valid_key, invalid_key);
}, 'second key conversion with invalid key should throw DataError');
}
}
// Static key comparison utility on IDBFactory.
test(t => {
check_method(indexedDB, 'cmp', 2);
}, 'IDBFactory cmp() static with throwing/invalid keys');
// Continue methods on IDBCursor.
indexeddb_upgrade_only_test((t, db) => {
var store = db.createObjectStore('store');
store.put('a', 1).onerror = t.unreached_func('put should succeed');
var request = store.openCursor();
request.onerror = t.unreached_func('openCursor should succeed');
request.onsuccess = t.step_func(() => {
var cursor = request.result;
assert_not_equals(cursor, null, 'cursor should find a value');
check_method(cursor, 'continue');
});
}, 'IDBCursor continue() method with throwing/invalid keys');
indexeddb_upgrade_only_test((t, db) => {
var store = db.createObjectStore('store');
var index = store.createIndex('index', 'prop');
store.put({prop: 'a'}, 1).onerror = t.unreached_func('put should succeed');
var request = index.openCursor();
request.onerror = t.unreached_func('openCursor should succeed');
request.onsuccess = t.step_func(() => {
var cursor = request.result;
assert_not_equals(cursor, null, 'cursor should find a value');
check_method(cursor, 'continuePrimaryKey', 2);
});
}, null, 'IDBCursor continuePrimaryKey() method with throwing/invalid keys');
// Mutation methods on IDBCursor.
indexeddb_upgrade_only_test((t, db) => {
var store = db.createObjectStore('store', {keyPath: 'prop'});
store.put({prop: 1}).onerror = t.unreached_func('put should succeed');
var request = store.openCursor();
request.onerror = t.unreached_func('openCursor should succeed');
request.onsuccess = t.step_func(() => {
var cursor = request.result;
assert_not_equals(cursor, null, 'cursor should find a value');
var value = {};
value.prop = throwing_key('getter');
assert_throws({name: 'getter'}, () => {
cursor.update(value);
}, 'throwing getter should rethrow during clone');
// Throwing from the getter during key conversion is
// not possible since (1) a clone is used, (2) only own
// properties are cloned, and (3) only own properties
// are used for key path evaluation.
value.prop = invalid_key;
assert_throws('DataError', () => {
cursor.update(value);
}, 'key conversion with invalid key should throw DataError');
});
}, 'IDBCursor update() method with throwing/invalid keys');
// Static constructors on IDBKeyRange
['only', 'lowerBound', 'upperBound'].forEach(method => {
test(t => {
check_method(IDBKeyRange, method);
}, 'IDBKeyRange ' + method + '() static with throwing/invalid keys');
});
test(t => {
check_method(IDBKeyRange, 'bound', 2);
}, 'IDBKeyRange bound() static with throwing/invalid keys');
// Insertion methods on IDBObjectStore.
['add', 'put'].forEach(method => {
indexeddb_upgrade_only_test((t, db) => {
var out_of_line = db.createObjectStore('out-of-line keys');
var in_line = db.createObjectStore('in-line keys', {keyPath: 'prop'});
assert_throws({name:'getter'}, () => {
out_of_line[method]('value', throwing_key('getter'));
}, 'key conversion with throwing getter should rethrow');
assert_throws('DataError', () => {
out_of_line[method]('value', invalid_key);
}, 'key conversion with invalid key should throw DataError');
var value = {};
value.prop = throwing_key('getter');
assert_throws({name:'getter'}, () => {
in_line[method](value);
}, 'throwing getter should rethrow during clone');
// Throwing from the getter during key conversion is
// not possible since (1) a clone is used, (2) only own
// properties are cloned, and (3) only own properties
// are used for key path evaluation.
value.prop = invalid_key;
assert_throws('DataError', () => {
in_line[method](value);
}, 'key conversion with invalid key should throw DataError');
}, `IDBObjectStore ${method}() method with throwing/invalid keys`);
});
// Generic (key-or-key-path) methods on IDBObjectStore.
[
'delete', 'get', 'getKey', 'getAll', 'getAllKeys', 'count', 'openCursor',
'openKeyCursor'
].forEach(method => {
indexeddb_upgrade_only_test((t, db) => {
var store = db.createObjectStore('store');
check_method(store, method);
}, `IDBObjectStore ${method}() method with throwing/invalid keys`);
});
// Generic (key-or-key-path) methods on IDBIndex.
[
'get', 'getKey', 'getAll', 'getAllKeys', 'count', 'openCursor',
'openKeyCursor'
].forEach(method => {
indexeddb_upgrade_only_test((t, db) => {
var store = db.createObjectStore('store');
var index = store.createIndex('index', 'keyPath');
check_method(index, method);
}, `IDBIndex ${method}() method with throwing/invalid keys`);
});
</script>

Просмотреть файл

@ -0,0 +1,272 @@
<!doctype html>
<meta charset=utf-8>
<title>IndexedDB: Exceptions in extracting keys from values (ES bindings)</title>
<meta name="help" href="https://w3c.github.io/IndexedDB/#extract-key-from-value">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="support.js"></script>
<script>
indexeddb_test(
(t, db) => {
db.createObjectStore('store', {autoIncrement: true, keyPath: 'a.b.c'});
},
(t, db) => {
const tx = db.transaction('store', 'readwrite');
assert_throws({name: 'DataError'}, () => {
tx.objectStore('store').put({a: {b: "foo"}});
}, 'Put should throw if key can not be inserted at key path location.');
t.done();
},
'The last element of keypath is validated'
);
function throws(name) {
return () => {
const err = Error();
err.name = name;
throw err;
};
}
indexeddb_test(
function(t, db) {
const o = {};
Object.defineProperty(o, 'throws', {get: throws('getter'),
enumerable: false, configurable: true});
// Value should be cloned before key path is evaluated,
// and non-enumerable getter will be ignored. The clone
// will have no such property, so key path evaluation
// will fail.
const s1 = db.createObjectStore('s1', {keyPath: 'throws'});
assert_throws('DataError', () => {
s1.put(o);
}, 'Key path failing to resolve should throw');
// Value should be cloned before key path is evaluated,
// and non-enumerable getter will be ignored. The clone
// will have no such property, so key path evaluation
// will fail.
const s2 = db.createObjectStore('s2', {keyPath: 'throws.x'});
assert_throws('DataError', () => {
s2.put(o);
}, 'Key path failing to resolve should throw');
// Value should be cloned before key path is evaluated,
// and non-enumerable getter will be ignored. The clone
// will have no such property, so generated key can be
// inserted.
const s3 = db.createObjectStore('s3',
{keyPath: 'throws', autoIncrement: true});
assert_class_string(s3.put(o), 'IDBRequest',
'Key injectability test at throwing getter should succeed');
// Value should be cloned before key path is evaluated,
// and non-enumerable getter will be ignored. The clone
// will have no such property, so intermediate object
// and generated key can be inserted.
const s4 = db.createObjectStore('s4',
{keyPath: 'throws.x', autoIncrement: true});
assert_class_string(s4.put(o), 'IDBRequest',
'Key injectability test past throwing getter should succeed');
},
(t, db) => {
t.done();
},
'Key path evaluation: Exceptions from non-enumerable getters'
);
indexeddb_test(
function(t, db) {
const o = {};
Object.defineProperty(o, 'throws', {get: throws('getter'),
enumerable: true, configurable: true});
// Value should be cloned before key path is evaluated,
// and enumerable getter will rethrow.
const s1 = db.createObjectStore('s1', {keyPath: 'throws'});
assert_throws({name: 'getter'}, () => {
s1.put(o);
}, 'Key path resolving to throwing getter rethrows');
// Value should be cloned before key path is evaluated,
// and enumerable getter will rethrow.
const s2 = db.createObjectStore('s2', {keyPath: 'throws.x'});
assert_throws({name: 'getter'}, () => {
s2.put(o);
}, 'Key path resolving past throwing getter rethrows');
// Value should be cloned before key path is evaluated,
// and enumerable getter will rethrow.
const s3 = db.createObjectStore('s3',
{keyPath: 'throws', autoIncrement: true});
assert_throws({name: 'getter'}, () => {
s3.put(o);
}, 'Key injectability test at throwing getter should rethrow');
// Value should be cloned before key path is evaluated,
// and enumerable getter will rethrow.
const s4 = db.createObjectStore('s4',
{keyPath: 'throws.x', autoIncrement: true});
assert_throws({name: 'getter'}, () => {
s4.put(o);
}, 'Key injectability test past throwing getter should rethrow');
},
(t, db) => {
t.done();
},
'Key path evaluation: Exceptions from enumerable getters'
);
indexeddb_test(
(t, db) => {
// Implemented as function wrapper to clean up
// immediately after use, otherwise it may
// interfere with the test harness.
function with_proto_getter(f) {
return function() {
Object.defineProperty(Object.prototype, 'throws', {
get: throws('getter'),
enumerable: false, configurable: true
});
try {
f();
} finally {
delete Object.prototype['throws'];
}
};
}
// Value should be cloned before key path is evaluated,
// and non-enumerable getter will be ignored. The clone
// will have no own property, so key path evaluation will
// fail and DataError should be thrown.
const s1 = db.createObjectStore('s1', {keyPath: 'throws'});
assert_throws('DataError', with_proto_getter(function() {
s1.put({});
}), 'Key path resolving to no own property throws DataError');
// Value should be cloned before key path is evaluated,
// and non-enumerable getter will be ignored. The clone
// will have no own property, so key path evaluation will
// fail and DataError should be thrown.
const s2 = db.createObjectStore('s2', {keyPath: 'throws.x'});
assert_throws('DataError', with_proto_getter(function() {
s2.put({});
}), 'Key path resolving past no own property throws DataError');
// Value should be cloned before key path is evaluated,
// and non-enumerable getter will be ignored. The clone
// will have no own property, so key path evaluation will
// fail and injection can succeed.
const s3 = db.createObjectStore('s3',
{keyPath: 'throws', autoIncrement: true});
assert_equals(s3.put({}).readyState, 'pending',
'put should not throw due to inherited property');
// Value should be cloned before key path is evaluated,
// and non-enumerable getter will be ignored. The clone
// will have no own property, so key path evaluation will
// fail and injection can succeed.
const s4 = db.createObjectStore('s4',
{keyPath: 'throws.x', autoIncrement: true});
assert_equals(s4.put({}).readyState, 'pending',
'put should not throw due to inherited property');
},
(t, db) => {
t.done();
},
'Key path evaluation: Exceptions from non-enumerable getters on prototype'
);
indexeddb_test(
(t, db) => {
// Implemented as function wrapper to clean up
// immediately after use, otherwise it may
// interfere with the test harness.
function with_proto_getter(f) {
return () => {
Object.defineProperty(Object.prototype, 'throws', {
get: throws('getter'),
enumerable: true, configurable: true
});
try {
f();
} finally {
delete Object.prototype['throws'];
}
};
}
// Value should be cloned before key path is evaluated.
// The clone will have no own property, so key path
// evaluation will fail and DataError should be thrown.
const s1 = db.createObjectStore('s1', {keyPath: 'throws'});
assert_throws('DataError', with_proto_getter(function() {
s1.put({});
}), 'Key path resolving to no own property throws DataError');
// Value should be cloned before key path is evaluated.
// The clone will have no own property, so key path
// evaluation will fail and DataError should be thrown.
const s2 = db.createObjectStore('s2', {keyPath: 'throws.x'});
assert_throws('DataError', with_proto_getter(function() {
s2.put({});
}), 'Key path resolving past throwing getter rethrows');
// Value should be cloned before key path is evaluated.
// The clone will have no own property, so key path
// evaluation will fail and injection can succeed.
var s3 = db.createObjectStore('s3',
{keyPath: 'throws', autoIncrement: true});
assert_equals(s3.put({}).readyState, 'pending',
'put should not throw due to inherited property');
// Value should be cloned before key path is evaluated.
// The clone will have no own property, so key path
// evaluation will fail and injection can succeed.
var s4 = db.createObjectStore('s4',
{keyPath: 'throws.x', autoIncrement: true});
assert_equals(s4.put({}).readyState, 'pending',
'put should not throw due to inherited property');
},
(t, db) => {
t.done();
},
'Key path evaluation: Exceptions from enumerable getters on prototype'
);
indexeddb_test(
(t, db) => {
const store = db.createObjectStore('store');
store.createIndex('index', 'index0');
},
(t, db) => {
const tx = db.transaction('store', 'readwrite');
const array = [];
array[99] = 1;
const getter_called = 0;
const prop = '50';
Object.defineProperty(Object.prototype, prop, {
enumerable: true, configurable: true,
get: () => {
++getter_called;
return 'foo';
},
});
const request = tx.objectStore('store').put({index0: array}, 'key');
request.onerror = t.unreached_func('put should not fail');
request.onsuccess = t.step_func(function() {
assert_equals(getter_called, 0, 'Prototype getter should not be called');
delete Object.prototype[prop];
t.done();
});
},
'Array key conversion should not invoke prototype getters'
);
</script>

Просмотреть файл

@ -0,0 +1,69 @@
<!doctype html>
<meta charset=utf-8>
<title>IndexedDB: Special-cased identifiers in extracting keys from values (ES bindings)</title>
<meta name="help" href="https://w3c.github.io/IndexedDB/#extract-key-from-value">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="support.js"></script>
<script>
[
{
type: 'String',
property: 'length',
instance: 'abc',
},
{
type: 'Array',
property: 'length',
instance: ['a', 'b', 'c'],
},
{
type: 'Blob',
property: 'size',
instance: new Blob(['abc']),
},
{
type: 'Blob',
property: 'type',
instance: new Blob([''], {type:'foo/bar'}),
},
{
type: 'File',
property: 'name',
instance: new File([''], 'foo'),
},
{
type: 'File',
property: 'lastModified',
instance: new File([''], '', {lastModified: 123}),
},
{
type: 'File',
property: 'lastModifiedDate',
instance: new File([''], '', {lastModified: 123}),
},
].forEach(function(testcase) {
indexeddb_test(
(t, db) => {
db.createObjectStore(
'store', {autoIncrement: true, keyPath: testcase.property});
},
(t, db) => {
const key = testcase.instance[testcase.property];
const tx = db.transaction('store', 'readwrite');
tx.objectStore('store').put(testcase.instance);
const request = tx.objectStore('store').get(key);
request.onerror = t.unreached_func('request should not fail');
request.onsuccess = t.step_func(function() {
const result = request.result;
assert_key_equals(result[testcase.property], key,
'Property should be used as key');
t.done();
});
},
'Type: ' + testcase.type + ', identifier: ' + testcase.property
);
});
</script>

Просмотреть файл

@ -1,4 +1,4 @@
<!DOCTYPE html>
<!doctype html>
<meta charset="utf-8">
<title>
IndexedDB: scoping for database / object store / index names, and index keys

Просмотреть файл

@ -1,42 +1,46 @@
// Returns an IndexedDB database name likely to be unique to the test case.
const databaseName = (testCase) => {
'use strict';
// Returns an IndexedDB database name that is unique to the test case.
function databaseName(testCase) {
return 'db' + self.location.pathname + '-' + testCase.name;
};
}
// Creates an EventWatcher covering all the events that can be issued by
// IndexedDB requests and transactions.
const requestWatcher = (testCase, request) => {
function requestWatcher(testCase, request) {
return new EventWatcher(testCase, request,
['error', 'success', 'upgradeneeded']);
};
['abort', 'blocked', 'complete', 'error', 'success', 'upgradeneeded']);
}
// Migrates an IndexedDB database whose name is unique for the test case.
//
// newVersion must be greater than the database's current version.
//
// migrationCallback will be called during a versionchange transaction and will
// be given the created database and the versionchange transaction.
// given the created database, the versionchange transaction, and the database
// open request.
//
// Returns a promise. If the versionchange transaction goes through, the promise
// resolves to an IndexedDB database that must be closed by the caller. If the
// versionchange transaction is aborted, the promise resolves to an error.
const migrateDatabase = (testCase, newVersion, migrationCallback) => {
function migrateDatabase(testCase, newVersion, migrationCallback) {
return migrateNamedDatabase(
testCase, databaseName(testCase), newVersion, migrationCallback);
};
}
// Migrates an IndexedDB database.
//
// newVersion must be greater than the database's current version.
//
// migrationCallback will be called during a versionchange transaction and will
// be given the created database and the versionchange transaction.
// given the created database, the versionchange transaction, and the database
// open request.
//
// Returns a promise. If the versionchange transaction goes through, the promise
// resolves to an IndexedDB database that must be closed by the caller. If the
// versionchange transaction is aborted, the promise resolves to an error.
const migrateNamedDatabase =
(testCase, databaseName, newVersion, migrationCallback) => {
function migrateNamedDatabase(
testCase, databaseName, newVersion, migrationCallback) {
// We cannot use eventWatcher.wait_for('upgradeneeded') here, because
// the versionchange transaction auto-commits before the Promise's then
// callback gets called.
@ -45,62 +49,78 @@ const migrateNamedDatabase =
request.onupgradeneeded = testCase.step_func(event => {
const database = event.target.result;
const transaction = event.target.transaction;
let abortCalled = false;
let shouldBeAborted = false;
let requestEventPromise = null;
// We wrap IDBTransaction.abort so we can set up the correct event
// listeners and expectations if the test chooses to abort the
// versionchange transaction.
const transactionAbort = transaction.abort.bind(transaction);
transaction.abort = () => {
request.onerror = event => {
event.preventDefault();
resolve(event);
};
request.onsuccess = () => reject(new Error(
'indexedDB.open should not succeed after the versionchange ' +
'transaction is aborted'));
transaction._willBeAborted();
transactionAbort();
abortCalled = true;
}
transaction._willBeAborted = () => {
requestEventPromise = new Promise((resolve, reject) => {
request.onerror = event => {
event.preventDefault();
resolve(event);
};
request.onsuccess = () => reject(new Error(
'indexedDB.open should not succeed for an aborted ' +
'versionchange transaction'));
});
shouldBeAborted = true;
}
migrationCallback(database, transaction);
if (!abortCalled) {
// If migration callback returns a promise, we'll wait for it to resolve.
// This simplifies some tests.
const callbackResult = migrationCallback(database, transaction, request);
if (!shouldBeAborted) {
request.onerror = null;
request.onsuccess = null;
resolve(requestWatcher(testCase, request).wait_for('success'));
requestEventPromise =
requestWatcher(testCase, request).wait_for('success');
}
// requestEventPromise needs to be the last promise in the chain, because
// we want the event that it resolves to.
resolve(Promise.resolve(callbackResult).then(() => requestEventPromise));
});
request.onerror = event => reject(event.target.error);
request.onsuccess = () => reject(new Error(
'indexedDB.open should not succeed without creating a ' +
'versionchange transaction'));
}).then(event => event.target.result || event.target.error);
};
}
// Creates an IndexedDB database whose name is unique for the test case.
//
// setupCallback will be called during a versionchange transaction, and will be
// given the created database and the versionchange transaction.
// given the created database, the versionchange transaction, and the database
// open request.
//
// Returns a promise that resolves to an IndexedDB database. The caller must
// close the database.
const createDatabase = (testCase, setupCallback) => {
function createDatabase(testCase, setupCallback) {
return createNamedDatabase(testCase, databaseName(testCase), setupCallback);
};
}
// Creates an IndexedDB database.
//
// setupCallback will be called during a versionchange transaction, and will be
// given the created database and the versionchange transaction.
// given the created database, the versionchange transaction, and the database
// open request.
//
// Returns a promise that resolves to an IndexedDB database. The caller must
// close the database.
const createNamedDatabase = (testCase, databaseName, setupCallback) => {
function createNamedDatabase(testCase, databaseName, setupCallback) {
const request = indexedDB.deleteDatabase(databaseName);
const eventWatcher = requestWatcher(testCase, request);
return eventWatcher.wait_for('success').then(event =>
migrateNamedDatabase(testCase, databaseName, 1, setupCallback));
};
}
// Opens an IndexedDB database without performing schema changes.
//
@ -108,7 +128,7 @@ const createNamedDatabase = (testCase, databaseName, setupCallback) => {
//
// Returns a promise that resolves to an IndexedDB database. The caller must
// close the database.
const openDatabase = (testCase, version) => {
function openDatabase(testCase, version) {
return openNamedDatabase(testCase, databaseName(testCase), version);
}
@ -118,7 +138,7 @@ const openDatabase = (testCase, version) => {
//
// Returns a promise that resolves to an IndexedDB database. The caller must
// close the database.
const openNamedDatabase = (testCase, databaseName, version) => {
function openNamedDatabase(testCase, databaseName, version) {
const request = indexedDB.open(databaseName, version);
const eventWatcher = requestWatcher(testCase, request);
return eventWatcher.wait_for('success').then(event => event.target.result);
@ -142,16 +162,16 @@ const createBooksStore = (testCase, database) => {
for (let record of BOOKS_RECORD_DATA)
store.put(record);
return store;
};
}
// Creates a 'not_books' object store used to test renaming into existing or
// deleted store names.
const createNotBooksStore = (testCase, database) => {
const store = database.createObjectStore('not_books');
store.createIndex('not_by_author', 'author');
store.createIndex('not_by_title', 'title', { unique: true });
return store;
};
function createNotBooksStore(testCase, database) {
const store = database.createObjectStore('not_books');
store.createIndex('not_by_author', 'author');
store.createIndex('not_by_title', 'title', { unique: true });
return store;
}
// Verifies that an object store's indexes match the indexes used to create the
// books store in the test database's version 1.
@ -159,7 +179,7 @@ const createNotBooksStore = (testCase, database) => {
// The errorMessage is used if the assertions fail. It can state that the
// IndexedDB implementation being tested is incorrect, or that the testing code
// is using it incorrectly.
const checkStoreIndexes = (testCase, store, errorMessage) => {
function checkStoreIndexes (testCase, store, errorMessage) {
assert_array_equals(
store.indexNames, ['by_author', 'by_title'], errorMessage);
const authorIndex = store.index('by_author');
@ -168,7 +188,7 @@ const checkStoreIndexes = (testCase, store, errorMessage) => {
checkAuthorIndexContents(testCase, authorIndex, errorMessage),
checkTitleIndexContents(testCase, titleIndex, errorMessage),
]);
};
}
// Verifies that an object store's key generator is in the same state as the
// key generator created for the books store in the test database's version 1.
@ -176,7 +196,7 @@ const checkStoreIndexes = (testCase, store, errorMessage) => {
// The errorMessage is used if the assertions fail. It can state that the
// IndexedDB implementation being tested is incorrect, or that the testing code
// is using it incorrectly.
const checkStoreGenerator = (testCase, store, expectedKey, errorMessage) => {
function checkStoreGenerator(testCase, store, expectedKey, errorMessage) {
const request = store.put(
{ title: 'Bedrock Nights ' + expectedKey, author: 'Barney' });
const eventWatcher = requestWatcher(testCase, request);
@ -184,7 +204,7 @@ const checkStoreGenerator = (testCase, store, expectedKey, errorMessage) => {
const result = request.result;
assert_equals(result, expectedKey, errorMessage);
});
};
}
// Verifies that an object store's contents matches the contents used to create
// the books store in the test database's version 1.
@ -192,7 +212,7 @@ const checkStoreGenerator = (testCase, store, expectedKey, errorMessage) => {
// The errorMessage is used if the assertions fail. It can state that the
// IndexedDB implementation being tested is incorrect, or that the testing code
// is using it incorrectly.
const checkStoreContents = (testCase, store, errorMessage) => {
function checkStoreContents(testCase, store, errorMessage) {
const request = store.get(123456);
const eventWatcher = requestWatcher(testCase, request);
return eventWatcher.wait_for('success').then(() => {
@ -201,7 +221,7 @@ const checkStoreContents = (testCase, store, errorMessage) => {
assert_equals(result.author, BOOKS_RECORD_DATA[0].author, errorMessage);
assert_equals(result.title, BOOKS_RECORD_DATA[0].title, errorMessage);
});
};
}
// Verifies that index matches the 'by_author' index used to create the
// by_author books store in the test database's version 1.
@ -209,7 +229,7 @@ const checkStoreContents = (testCase, store, errorMessage) => {
// The errorMessage is used if the assertions fail. It can state that the
// IndexedDB implementation being tested is incorrect, or that the testing code
// is using it incorrectly.
const checkAuthorIndexContents = (testCase, index, errorMessage) => {
function checkAuthorIndexContents(testCase, index, errorMessage) {
const request = index.get(BOOKS_RECORD_DATA[2].author);
const eventWatcher = requestWatcher(testCase, request);
return eventWatcher.wait_for('success').then(() => {
@ -217,7 +237,7 @@ const checkAuthorIndexContents = (testCase, index, errorMessage) => {
assert_equals(result.isbn, BOOKS_RECORD_DATA[2].isbn, errorMessage);
assert_equals(result.title, BOOKS_RECORD_DATA[2].title, errorMessage);
});
};
}
// Verifies that an index matches the 'by_title' index used to create the books
// store in the test database's version 1.
@ -225,7 +245,7 @@ const checkAuthorIndexContents = (testCase, index, errorMessage) => {
// The errorMessage is used if the assertions fail. It can state that the
// IndexedDB implementation being tested is incorrect, or that the testing code
// is using it incorrectly.
const checkTitleIndexContents = (testCase, index, errorMessage) => {
function checkTitleIndexContents(testCase, index, errorMessage) {
const request = index.get(BOOKS_RECORD_DATA[2].title);
const eventWatcher = requestWatcher(testCase, request);
return eventWatcher.wait_for('success').then(() => {
@ -233,4 +253,4 @@ const checkTitleIndexContents = (testCase, index, errorMessage) => {
assert_equals(result.isbn, BOOKS_RECORD_DATA[2].isbn, errorMessage);
assert_equals(result.author, BOOKS_RECORD_DATA[2].author, errorMessage);
});
};
}

Просмотреть файл

@ -62,12 +62,14 @@ function createdb_for_multiple_tests(dbname, version) {
assert_unreached("unexpected open." + evt + " event");
}
if (e.target.result + "" == "[object IDBDatabase]" && !this.db) {
this.db = e.target.result;
if (e.target.result + '' == '[object IDBDatabase]' &&
!this.db) {
this.db = e.target.result;
this.db.onerror = fail(test, "unexpected db.error");
this.db.onabort = fail(test, "unexpected db.abort");
this.db.onversionchange = fail(test, "unexpected db.versionchange");
this.db.onerror = fail(test, 'unexpected db.error');
this.db.onabort = fail(test, 'unexpected db.abort');
this.db.onversionchange =
fail(test, 'unexpected db.versionchange');
}
})
})
@ -80,7 +82,7 @@ function createdb_for_multiple_tests(dbname, version) {
})
}
// add a .setTest method to the DB object
// add a .setTest method to the IDBOpenDBRequest object
Object.defineProperty(rq_open, 'setTest', {
enumerable: false,
value: function(t) {
@ -99,25 +101,45 @@ function createdb_for_multiple_tests(dbname, version) {
}
function assert_key_equals(actual, expected, description) {
assert_equals(indexedDB.cmp(actual, expected), 0, description);
assert_equals(indexedDB.cmp(actual, expected), 0, description);
}
function indexeddb_test(upgrade_func, open_func, description) {
async_test(function(t) {
var dbname = document.location + '-' + t.name;
var del = indexedDB.deleteDatabase(dbname);
del.onerror = t.unreached_func('deleteDatabase should succeed');
var open = indexedDB.open(dbname, 1);
open.onerror = t.unreached_func('open should succeed');
open.onupgradeneeded = t.step_func(function() {
var db = open.result;
var tx = open.transaction;
upgrade_func(t, db, tx);
});
open.onsuccess = t.step_func(function() {
var db = open.result;
if (open_func)
open_func(t, db);
});
}, description);
function indexeddb_test(upgrade_func, open_func, description, options) {
async_test(function(t) {
var options = Object.assign({upgrade_will_abort: false}, options);
var dbname = document.location + '-' + t.name;
var del = indexedDB.deleteDatabase(dbname);
del.onerror = t.unreached_func('deleteDatabase should succeed');
var open = indexedDB.open(dbname, 1);
if (!options.upgrade_will_abort) {
open.onsuccess = t.unreached_func('open should not succeed');
} else {
open.onerror = t.unreached_func('open should succeed');
}
open.onupgradeneeded = t.step_func(function() {
var db = open.result;
var tx = open.transaction;
upgrade_func(t, db, tx);
});
open.onsuccess = t.step_func(function() {
var db = open.result;
if (open_func)
open_func(t, db);
});
}, description);
}
// Call with a Test and an array of expected results in order. Returns
// a function; call the function when a result arrives and when the
// expected number appear the order will be asserted and test
// completed.
function expect(t, expected) {
var results = [];
return result => {
results.push(result);
if (results.length === expected.length) {
assert_array_equals(results, expected);
t.done();
}
};
}

Просмотреть файл

@ -1,4 +1,5 @@
<!DOCTYPE html>
<!doctype html>
<meta charset="utf8">
<title>IndexedDB: aborting transactions reverts an object store's key generator state</title>
<link rel="help" href="https://w3c.github.io/IndexedDB/#abort-transaction">
<link rel="author" href="pwnall@chromium.org" title="Victor Costan">
@ -6,6 +7,7 @@
<script src="/resources/testharnessreport.js"></script>
<script src="support-promises.js"></script>
<script>
'use strict';
promise_test(testCase => {
return createDatabase(testCase, (database, transaction) => {

Просмотреть файл

@ -1,4 +1,5 @@
<!DOCTYPE html>
<!doctype html>
<meta charset="utf8">
<title>IndexedDB: aborting transactions reverts index metadata</title>
<link rel="help" href="https://w3c.github.io/IndexedDB/#abort-transaction">
<link rel="author" href="pwnall@chromium.org" title="Victor Costan">
@ -6,6 +7,7 @@
<script src="/resources/testharnessreport.js"></script>
<script src="support-promises.js"></script>
<script>
'use strict';
promise_test(testCase => {
let store = null, index = null;

Просмотреть файл

@ -1,4 +1,5 @@
<!DOCTYPE html>
<!doctype html>
<meta charset="utf8">
<title>IndexedDB: aborting transactions reverts multiple operations on the same metadata</title>
<link rel="help" href="https://w3c.github.io/IndexedDB/#abort-transaction">
<link rel="author" href="pwnall@chromium.org" title="Victor Costan">
@ -6,6 +7,7 @@
<script src="/resources/testharnessreport.js"></script>
<script src="support-promises.js"></script>
<script>
'use strict';
promise_test(testCase => {
let store = null, index = null;

Просмотреть файл

@ -1,4 +1,5 @@
<!DOCTYPE html>
<!doctype html>
<meta charset="utf8">
<title>IndexedDB: aborting transactions reverts object store metadata</title>
<link rel="help" href="https://w3c.github.io/IndexedDB/#abort-transaction">
<link rel="author" href="pwnall@chromium.org" title="Victor Costan">
@ -6,6 +7,7 @@
<script src="/resources/testharnessreport.js"></script>
<script src="support-promises.js"></script>
<script>
'use strict';
promise_test(testCase => {
let store = null, migrationTransaction = null, migrationDatabase = null;

Просмотреть файл

@ -1,7 +1,7 @@
The Web Platform Tests Project [![IRC chat](https://goo.gl/6nCIks)](http://irc.w3.org/?channels=testing)
The web-platform-tests Project [![IRC chat](https://goo.gl/6nCIks)](http://irc.w3.org/?channels=testing)
==============================
The Web Platform Tests Project is a W3C-coordinated attempt to build a
The web-platform-tests Project is a W3C-coordinated attempt to build a
cross-browser testsuite for the Web-platform stack. However, for mainly
historic reasons, the CSS WG testsuite is in a separate repository,
[csswg-test](https://github.com/w3c/csswg-test). Writing tests in a way
@ -39,6 +39,9 @@ following entries are required:
0.0.0.0 nonexistent-origin.web-platform.test
```
If you are behind a proxy, you also need to make sure the domains above are
excluded from your proxy lookups.
Because web-platform-tests uses git submodules, you must ensure that
these are up to date. In the root of your checkout, run:
@ -111,7 +114,7 @@ Test Runner
===========
There is a test runner that is designed to provide a
convenient way to run the web-platform tests in-browser. It will run
convenient way to run the web-platform-tests in-browser. It will run
testharness.js tests automatically but requires manual work for
reftests and manual tests.
@ -131,8 +134,10 @@ Publication
The master branch is automatically synced to http://w3c-test.org/.
Pull requests that have been checked are automatically mirrored to
http://w3c-test.org/submissions/.
Pull requests are automatically mirrored to
http://w3c-test.org/submissions/ a few minutes after someone with merge
access has added a comment with "LGTM" (or "w3c-test:mirror") to indicate
the PR has been checked.
Finding Things
==============

Просмотреть файл

@ -1,4 +1,4 @@
// <meta> timeout=long
// META: timeout=long
importScripts("/resources/testharness.js");
importScripts("pbkdf2_vectors.js");
importScripts("pbkdf2.js");

Просмотреть файл

@ -1,4 +1,4 @@
// <meta> timeout=long
// META: timeout=long
importScripts("/resources/testharness.js");
importScripts("../util/helpers.js");
importScripts("failures.js");

Просмотреть файл

@ -1,4 +1,4 @@
// <meta> timeout=long
// META: timeout=long
importScripts("/resources/testharness.js");
importScripts("../util/helpers.js");
importScripts("failures.js");

Просмотреть файл

@ -1,4 +1,4 @@
// <meta> timeout=long
// META: timeout=long
importScripts("/resources/testharness.js");
importScripts("../util/helpers.js");
importScripts("failures.js");

Просмотреть файл

@ -1,4 +1,4 @@
// <meta> timeout=long
// META: timeout=long
importScripts("/resources/testharness.js");
importScripts("../util/helpers.js");
importScripts("failures.js");

Просмотреть файл

@ -1,4 +1,4 @@
// <meta> timeout=long
// META: timeout=long
importScripts("/resources/testharness.js");
importScripts("../util/helpers.js");
importScripts("failures.js");

Просмотреть файл

@ -1,4 +1,4 @@
// <meta> timeout=long
// META: timeout=long
importScripts("/resources/testharness.js");
importScripts("../util/helpers.js");
importScripts("failures.js");

Просмотреть файл

@ -1,4 +1,4 @@
// <meta> timeout=long
// META: timeout=long
importScripts("/resources/testharness.js");
importScripts("../util/helpers.js");
importScripts("failures.js");

Просмотреть файл

@ -1,4 +1,4 @@
// <meta> timeout=long
// META: timeout=long
importScripts("/resources/testharness.js");
importScripts("../util/helpers.js");
importScripts("failures.js");

Просмотреть файл

@ -1,4 +1,4 @@
// <meta> timeout=long
// META: timeout=long
importScripts("/resources/testharness.js");
importScripts("../util/helpers.js");
importScripts("failures.js");

Просмотреть файл

@ -1,4 +1,4 @@
// <meta> timeout=long
// META: timeout=long
importScripts("/resources/testharness.js");
importScripts("../util/helpers.js");
importScripts("failures.js");

Просмотреть файл

@ -1,4 +1,4 @@
// <meta> timeout=long
// META: timeout=long
importScripts("/resources/testharness.js");
importScripts("../util/helpers.js");
importScripts("successes.js");

Просмотреть файл

@ -1,4 +1,4 @@
// <meta> timeout=long
// META: timeout=long
importScripts("/resources/testharness.js");
importScripts("../util/helpers.js");
importScripts("successes.js");

Просмотреть файл

@ -1,4 +1,4 @@
// <meta> timeout=long
// META: timeout=long
importScripts("/resources/testharness.js");
importScripts("../util/helpers.js");
importScripts("successes.js");

Просмотреть файл

@ -1,4 +1,4 @@
// <meta> timeout=long
// META: timeout=long
importScripts("/resources/testharness.js");
importScripts("../util/helpers.js");
importScripts("successes.js");

Просмотреть файл

@ -1,4 +1,4 @@
// <meta> timeout=long
// META: timeout=long
importScripts("/resources/testharness.js");
importScripts("../util/helpers.js");
importScripts("successes.js");

Просмотреть файл

@ -1,4 +1,4 @@
// <meta> timeout=long
// META: timeout=long
importScripts("/resources/testharness.js");
importScripts("../util/helpers.js");
importScripts("successes.js");

Просмотреть файл

@ -1,4 +1,4 @@
// <meta> timeout=long
// META: timeout=long
importScripts("/resources/testharness.js");
importScripts("../util/helpers.js");
importScripts("successes.js");

Просмотреть файл

@ -1,4 +1,4 @@
// <meta> timeout=long
// META: timeout=long
importScripts("/resources/testharness.js");
importScripts("../util/helpers.js");
importScripts("successes.js");

Просмотреть файл

@ -1,4 +1,4 @@
// <meta> timeout=long
// META: timeout=long
importScripts("/resources/testharness.js");
importScripts("../util/helpers.js");
importScripts("successes.js");

Просмотреть файл

@ -1,4 +1,4 @@
// <meta> timeout=long
// META: timeout=long
importScripts("/resources/testharness.js");
importScripts("../util/helpers.js");
importScripts("successes.js");

Просмотреть файл

@ -48,7 +48,7 @@ run_test([%s]);
</script>
"""
successes_worker = """// <meta> timeout=long
successes_worker = """// META: timeout=long
importScripts("/resources/testharness.js");
importScripts("../util/helpers.js");
importScripts("successes.js");
@ -56,7 +56,7 @@ importScripts("successes.js");
run_test([%s]);
done();"""
failures_worker = """// <meta> timeout=long
failures_worker = """// META: timeout=long
importScripts("/resources/testharness.js");
importScripts("../util/helpers.js");
importScripts("failures.js");

Просмотреть файл

@ -1,4 +1,4 @@
// <meta> timeout=long
// META: timeout=long
importScripts("/resources/testharness.js");
importScripts("wrapKey_unwrapKey.js");

Просмотреть файл

@ -22,8 +22,14 @@
client.open("GET", "resources/well-formed.xml", false)
client.send(null)
assert_equals(client.readyState, 4)
assert_equals(client.status, 200)
assert_equals(client.responseXML.documentElement.localName, "html")
client.abort()
assert_equals(client.readyState, 0)
assert_equals(client.status, 0)
assert_equals(client.statusText, "")
assert_equals(client.responseXML, null)
assert_equals(client.getAllResponseHeaders(), "")
assert_array_equals(result, expected)
test.done()
})

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше