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
|
@ -1,2 +1,2 @@
|
|||
local: 6d8a9012bf2a909aedba28cd25b13f322f7b9a82
|
||||
upstream: d93247d5cb7d70f80da8b154a171f4e3d50969f4
|
||||
local: ec3ef9f77a52693e9732ca480df16017af0d9504
|
||||
upstream: fc4da5233160c1ed5675ae4a7859552cb7e0349f
|
||||
|
|
|
@ -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()
|
||||
})
|
||||
|
|