summaryrefslogtreecommitdiffstats
path: root/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-21 20:56:19 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-21 20:56:19 +0000
commit0b6210cd37b68b94252cb798598b12974a20e1c1 (patch)
treee371686554a877842d95aa94f100bee552ff2a8e /test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources
parentInitial commit. (diff)
downloadnode-undici-upstream.tar.xz
node-undici-upstream.zip
Adding upstream version 5.28.2+dfsg1+~cs23.11.12.3.upstream/5.28.2+dfsg1+_cs23.11.12.3upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources')
-rw-r--r--test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/close-worker.js5
-rw-r--r--test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/error-worker.js12
-rw-r--r--test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/extendable-message-event-constructor-worker.js197
-rw-r--r--test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/extendable-message-event-loopback-worker.js36
-rw-r--r--test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/extendable-message-event-ping-worker.js23
-rw-r--r--test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/extendable-message-event-pong-worker.js18
-rw-r--r--test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/extendable-message-event-utils.js78
-rw-r--r--test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/extendable-message-event-worker.js5
-rw-r--r--test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/postmessage-loopback-worker.js15
-rw-r--r--test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/postmessage-ping-worker.js15
-rw-r--r--test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/postmessage-pong-worker.js4
-rw-r--r--test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/registration-attribute-newer-worker.js33
-rw-r--r--test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/registration-attribute-worker.js139
-rw-r--r--test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/unregister-controlling-worker.html0
-rw-r--r--test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/unregister-worker.js25
-rw-r--r--test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/update-worker.js22
-rw-r--r--test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/update-worker.py16
17 files changed, 643 insertions, 0 deletions
diff --git a/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/close-worker.js b/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/close-worker.js
new file mode 100644
index 0000000..41a8bc0
--- /dev/null
+++ b/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/close-worker.js
@@ -0,0 +1,5 @@
+importScripts('../../resources/worker-testharness.js');
+
+test(function() {
+ assert_false('close' in self);
+}, 'ServiceWorkerGlobalScope close operation');
diff --git a/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/error-worker.js b/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/error-worker.js
new file mode 100644
index 0000000..f6838ff
--- /dev/null
+++ b/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/error-worker.js
@@ -0,0 +1,12 @@
+var source;
+
+self.addEventListener('message', function(e) {
+ source = e.source;
+ throw 'testError';
+});
+
+self.addEventListener('error', function(e) {
+ source.postMessage({
+ error: e.error, filename: e.filename, message: e.message, lineno: e.lineno,
+ colno: e.colno});
+});
diff --git a/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/extendable-message-event-constructor-worker.js b/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/extendable-message-event-constructor-worker.js
new file mode 100644
index 0000000..42da582
--- /dev/null
+++ b/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/extendable-message-event-constructor-worker.js
@@ -0,0 +1,197 @@
+importScripts('/resources/testharness.js');
+
+const TEST_OBJECT = { wanwan: 123 };
+const CHANNEL1 = new MessageChannel();
+const CHANNEL2 = new MessageChannel();
+const PORTS = [CHANNEL1.port1, CHANNEL1.port2, CHANNEL2.port1];
+function createEvent(initializer) {
+ if (initializer === undefined)
+ return new ExtendableMessageEvent('type');
+ return new ExtendableMessageEvent('type', initializer);
+}
+
+// These test cases are mostly copied from the following file in the Chromium
+// project (as of commit 848ad70823991e0f12b437d789943a4ab24d65bb):
+// third_party/WebKit/LayoutTests/fast/events/constructors/message-event-constructor.html
+
+test(function() {
+ assert_false(createEvent().bubbles);
+ assert_false(createEvent().cancelable);
+ assert_equals(createEvent().data, null);
+ assert_equals(createEvent().origin, '');
+ assert_equals(createEvent().lastEventId, '');
+ assert_equals(createEvent().source, null);
+ assert_array_equals(createEvent().ports, []);
+}, 'no initializer specified');
+
+test(function() {
+ assert_false(createEvent({ bubbles: false }).bubbles);
+ assert_true(createEvent({ bubbles: true }).bubbles);
+}, '`bubbles` is specified');
+
+test(function() {
+ assert_false(createEvent({ cancelable: false }).cancelable);
+ assert_true(createEvent({ cancelable: true }).cancelable);
+}, '`cancelable` is specified');
+
+test(function() {
+ assert_equals(createEvent({ data: TEST_OBJECT }).data, TEST_OBJECT);
+ assert_equals(createEvent({ data: undefined }).data, null);
+ assert_equals(createEvent({ data: null }).data, null);
+ assert_equals(createEvent({ data: false }).data, false);
+ assert_equals(createEvent({ data: true }).data, true);
+ assert_equals(createEvent({ data: '' }).data, '');
+ assert_equals(createEvent({ data: 'chocolate' }).data, 'chocolate');
+ assert_equals(createEvent({ data: 12345 }).data, 12345);
+ assert_equals(createEvent({ data: 18446744073709551615 }).data,
+ 18446744073709552000);
+ assert_equals(createEvent({ data: NaN }).data, NaN);
+ // Note that valueOf() is not called, when the left hand side is
+ // evaluated.
+ assert_false(
+ createEvent({ data: {
+ valueOf: function() { return TEST_OBJECT; } } }).data ==
+ TEST_OBJECT);
+ assert_equals(createEvent({ get data(){ return 123; } }).data, 123);
+ let thrown = { name: 'Error' };
+ assert_throws_exactly(thrown, function() {
+ createEvent({ get data() { throw thrown; } }); });
+}, '`data` is specified');
+
+test(function() {
+ assert_equals(createEvent({ origin: 'melancholy' }).origin, 'melancholy');
+ assert_equals(createEvent({ origin: '' }).origin, '');
+ assert_equals(createEvent({ origin: null }).origin, 'null');
+ assert_equals(createEvent({ origin: false }).origin, 'false');
+ assert_equals(createEvent({ origin: true }).origin, 'true');
+ assert_equals(createEvent({ origin: 12345 }).origin, '12345');
+ assert_equals(
+ createEvent({ origin: 18446744073709551615 }).origin,
+ '18446744073709552000');
+ assert_equals(createEvent({ origin: NaN }).origin, 'NaN');
+ assert_equals(createEvent({ origin: [] }).origin, '');
+ assert_equals(createEvent({ origin: [1, 2, 3] }).origin, '1,2,3');
+ assert_equals(
+ createEvent({ origin: { melancholy: 12345 } }).origin,
+ '[object Object]');
+ // Note that valueOf() is not called, when the left hand side is
+ // evaluated.
+ assert_equals(
+ createEvent({ origin: {
+ valueOf: function() { return 'melancholy'; } } }).origin,
+ '[object Object]');
+ assert_equals(
+ createEvent({ get origin() { return 123; } }).origin, '123');
+ let thrown = { name: 'Error' };
+ assert_throws_exactly(thrown, function() {
+ createEvent({ get origin() { throw thrown; } }); });
+}, '`origin` is specified');
+
+test(function() {
+ assert_equals(
+ createEvent({ lastEventId: 'melancholy' }).lastEventId, 'melancholy');
+ assert_equals(createEvent({ lastEventId: '' }).lastEventId, '');
+ assert_equals(createEvent({ lastEventId: null }).lastEventId, 'null');
+ assert_equals(createEvent({ lastEventId: false }).lastEventId, 'false');
+ assert_equals(createEvent({ lastEventId: true }).lastEventId, 'true');
+ assert_equals(createEvent({ lastEventId: 12345 }).lastEventId, '12345');
+ assert_equals(
+ createEvent({ lastEventId: 18446744073709551615 }).lastEventId,
+ '18446744073709552000');
+ assert_equals(createEvent({ lastEventId: NaN }).lastEventId, 'NaN');
+ assert_equals(createEvent({ lastEventId: [] }).lastEventId, '');
+ assert_equals(
+ createEvent({ lastEventId: [1, 2, 3] }).lastEventId, '1,2,3');
+ assert_equals(
+ createEvent({ lastEventId: { melancholy: 12345 } }).lastEventId,
+ '[object Object]');
+ // Note that valueOf() is not called, when the left hand side is
+ // evaluated.
+ assert_equals(
+ createEvent({ lastEventId: {
+ valueOf: function() { return 'melancholy'; } } }).lastEventId,
+ '[object Object]');
+ assert_equals(
+ createEvent({ get lastEventId() { return 123; } }).lastEventId,
+ '123');
+ let thrown = { name: 'Error' };
+ assert_throws_exactly(thrown, function() {
+ createEvent({ get lastEventId() { throw thrown; } }); });
+}, '`lastEventId` is specified');
+
+test(function() {
+ assert_equals(createEvent({ source: CHANNEL1.port1 }).source, CHANNEL1.port1);
+ assert_equals(
+ createEvent({ source: self.registration.active }).source,
+ self.registration.active);
+ assert_equals(
+ createEvent({ source: CHANNEL1.port1 }).source, CHANNEL1.port1);
+ assert_throws_js(
+ TypeError, function() { createEvent({ source: this }); },
+ 'source should be Client or ServiceWorker or MessagePort');
+}, '`source` is specified');
+
+test(function() {
+ // Valid message ports.
+ var passed_ports = createEvent({ ports: PORTS}).ports;
+ assert_equals(passed_ports[0], CHANNEL1.port1);
+ assert_equals(passed_ports[1], CHANNEL1.port2);
+ assert_equals(passed_ports[2], CHANNEL2.port1);
+ assert_array_equals(createEvent({ ports: [] }).ports, []);
+ assert_array_equals(createEvent({ ports: undefined }).ports, []);
+
+ // Invalid message ports.
+ assert_throws_js(TypeError,
+ function() { createEvent({ ports: [1, 2, 3] }); });
+ assert_throws_js(TypeError,
+ function() { createEvent({ ports: TEST_OBJECT }); });
+ assert_throws_js(TypeError,
+ function() { createEvent({ ports: null }); });
+ assert_throws_js(TypeError,
+ function() { createEvent({ ports: this }); });
+ assert_throws_js(TypeError,
+ function() { createEvent({ ports: false }); });
+ assert_throws_js(TypeError,
+ function() { createEvent({ ports: true }); });
+ assert_throws_js(TypeError,
+ function() { createEvent({ ports: '' }); });
+ assert_throws_js(TypeError,
+ function() { createEvent({ ports: 'chocolate' }); });
+ assert_throws_js(TypeError,
+ function() { createEvent({ ports: 12345 }); });
+ assert_throws_js(TypeError,
+ function() { createEvent({ ports: 18446744073709551615 }); });
+ assert_throws_js(TypeError,
+ function() { createEvent({ ports: NaN }); });
+ assert_throws_js(TypeError,
+ function() { createEvent({ get ports() { return 123; } }); });
+ let thrown = { name: 'Error' };
+ assert_throws_exactly(thrown, function() {
+ createEvent({ get ports() { throw thrown; } }); });
+ // Note that valueOf() is not called, when the left hand side is
+ // evaluated.
+ var valueOf = function() { return PORTS; };
+ assert_throws_js(TypeError, function() {
+ createEvent({ ports: { valueOf: valueOf } }); });
+}, '`ports` is specified');
+
+test(function() {
+ var initializers = {
+ bubbles: true,
+ cancelable: true,
+ data: TEST_OBJECT,
+ origin: 'wonderful',
+ lastEventId: 'excellent',
+ source: CHANNEL1.port1,
+ ports: PORTS
+ };
+ assert_equals(createEvent(initializers).bubbles, true);
+ assert_equals(createEvent(initializers).cancelable, true);
+ assert_equals(createEvent(initializers).data, TEST_OBJECT);
+ assert_equals(createEvent(initializers).origin, 'wonderful');
+ assert_equals(createEvent(initializers).lastEventId, 'excellent');
+ assert_equals(createEvent(initializers).source, CHANNEL1.port1);
+ assert_equals(createEvent(initializers).ports[0], PORTS[0]);
+ assert_equals(createEvent(initializers).ports[1], PORTS[1]);
+ assert_equals(createEvent(initializers).ports[2], PORTS[2]);
+}, 'all initial values are specified');
diff --git a/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/extendable-message-event-loopback-worker.js b/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/extendable-message-event-loopback-worker.js
new file mode 100644
index 0000000..13cae88
--- /dev/null
+++ b/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/extendable-message-event-loopback-worker.js
@@ -0,0 +1,36 @@
+importScripts('./extendable-message-event-utils.js');
+
+self.addEventListener('message', function(event) {
+ switch (event.data.type) {
+ case 'start':
+ self.registration.active.postMessage(
+ {type: '1st', client_id: event.source.id});
+ break;
+ case '1st':
+ // 1st loopback message via ServiceWorkerRegistration.active.
+ var results = {
+ trial: 1,
+ event: ExtendableMessageEventUtils.serialize(event)
+ };
+ var client_id = event.data.client_id;
+ event.source.postMessage({type: '2nd', client_id: client_id});
+ event.waitUntil(clients.get(client_id)
+ .then(function(client) {
+ client.postMessage({type: 'record', results: results});
+ }));
+ break;
+ case '2nd':
+ // 2nd loopback message via ExtendableMessageEvent.source.
+ var results = {
+ trial: 2,
+ event: ExtendableMessageEventUtils.serialize(event)
+ };
+ var client_id = event.data.client_id;
+ event.waitUntil(clients.get(client_id)
+ .then(function(client) {
+ client.postMessage({type: 'record', results: results});
+ client.postMessage({type: 'finish'});
+ }));
+ break;
+ }
+ });
diff --git a/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/extendable-message-event-ping-worker.js b/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/extendable-message-event-ping-worker.js
new file mode 100644
index 0000000..d07b229
--- /dev/null
+++ b/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/extendable-message-event-ping-worker.js
@@ -0,0 +1,23 @@
+importScripts('./extendable-message-event-utils.js');
+
+self.addEventListener('message', function(event) {
+ switch (event.data.type) {
+ case 'start':
+ // Send a ping message to another service worker.
+ self.registration.waiting.postMessage(
+ {type: 'ping', client_id: event.source.id});
+ break;
+ case 'pong':
+ var results = {
+ pingOrPong: 'pong',
+ event: ExtendableMessageEventUtils.serialize(event)
+ };
+ var client_id = event.data.client_id;
+ event.waitUntil(clients.get(client_id)
+ .then(function(client) {
+ client.postMessage({type: 'record', results: results});
+ client.postMessage({type: 'finish'});
+ }));
+ break;
+ }
+ });
diff --git a/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/extendable-message-event-pong-worker.js b/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/extendable-message-event-pong-worker.js
new file mode 100644
index 0000000..5e9669e
--- /dev/null
+++ b/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/extendable-message-event-pong-worker.js
@@ -0,0 +1,18 @@
+importScripts('./extendable-message-event-utils.js');
+
+self.addEventListener('message', function(event) {
+ switch (event.data.type) {
+ case 'ping':
+ var results = {
+ pingOrPong: 'ping',
+ event: ExtendableMessageEventUtils.serialize(event)
+ };
+ var client_id = event.data.client_id;
+ event.waitUntil(clients.get(client_id)
+ .then(function(client) {
+ client.postMessage({type: 'record', results: results});
+ event.source.postMessage({type: 'pong', client_id: client_id});
+ }));
+ break;
+ }
+ });
diff --git a/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/extendable-message-event-utils.js b/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/extendable-message-event-utils.js
new file mode 100644
index 0000000..d6a3b48
--- /dev/null
+++ b/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/extendable-message-event-utils.js
@@ -0,0 +1,78 @@
+var ExtendableMessageEventUtils = {};
+
+// Create a representation of a given ExtendableMessageEvent that is suitable
+// for transmission via the `postMessage` API.
+ExtendableMessageEventUtils.serialize = function(event) {
+ var ports = event.ports.map(function(port) {
+ return { constructor: { name: port.constructor.name } };
+ });
+ return {
+ constructor: {
+ name: event.constructor.name
+ },
+ origin: event.origin,
+ lastEventId: event.lastEventId,
+ source: {
+ constructor: {
+ name: event.source.constructor.name
+ },
+ url: event.source.url,
+ frameType: event.source.frameType,
+ visibilityState: event.source.visibilityState,
+ focused: event.source.focused
+ },
+ ports: ports
+ };
+};
+
+// Compare the actual and expected values of an ExtendableMessageEvent that has
+// been transformed using the `serialize` function defined in this file.
+ExtendableMessageEventUtils.assert_equals = function(actual, expected) {
+ assert_equals(
+ actual.constructor.name, expected.constructor.name, 'event constructor'
+ );
+ assert_equals(actual.origin, expected.origin, 'event `origin` property');
+ assert_equals(
+ actual.lastEventId,
+ expected.lastEventId,
+ 'event `lastEventId` property'
+ );
+
+ assert_equals(
+ actual.source.constructor.name,
+ expected.source.constructor.name,
+ 'event `source` property constructor'
+ );
+ assert_equals(
+ actual.source.url, expected.source.url, 'event `source` property `url`'
+ );
+ assert_equals(
+ actual.source.frameType,
+ expected.source.frameType,
+ 'event `source` property `frameType`'
+ );
+ assert_equals(
+ actual.source.visibilityState,
+ expected.source.visibilityState,
+ 'event `source` property `visibilityState`'
+ );
+ assert_equals(
+ actual.source.focused,
+ expected.source.focused,
+ 'event `source` property `focused`'
+ );
+
+ assert_equals(
+ actual.ports.length,
+ expected.ports.length,
+ 'event `ports` property length'
+ );
+
+ for (var idx = 0; idx < expected.ports.length; ++idx) {
+ assert_equals(
+ actual.ports[idx].constructor.name,
+ expected.ports[idx].constructor.name,
+ 'MessagePort #' + idx + ' constructor'
+ );
+ }
+};
diff --git a/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/extendable-message-event-worker.js b/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/extendable-message-event-worker.js
new file mode 100644
index 0000000..f5e7647
--- /dev/null
+++ b/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/extendable-message-event-worker.js
@@ -0,0 +1,5 @@
+importScripts('./extendable-message-event-utils.js');
+
+self.addEventListener('message', function(event) {
+ event.source.postMessage(ExtendableMessageEventUtils.serialize(event));
+ });
diff --git a/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/postmessage-loopback-worker.js b/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/postmessage-loopback-worker.js
new file mode 100644
index 0000000..083e9aa
--- /dev/null
+++ b/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/postmessage-loopback-worker.js
@@ -0,0 +1,15 @@
+self.addEventListener('message', function(event) {
+ if ('port' in event.data) {
+ var port = event.data.port;
+
+ var channel = new MessageChannel();
+ channel.port1.onmessage = function(event) {
+ if ('pong' in event.data)
+ port.postMessage(event.data.pong);
+ };
+ self.registration.active.postMessage({ping: channel.port2},
+ [channel.port2]);
+ } else if ('ping' in event.data) {
+ event.data.ping.postMessage({pong: 'OK'});
+ }
+ });
diff --git a/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/postmessage-ping-worker.js b/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/postmessage-ping-worker.js
new file mode 100644
index 0000000..ebb1ecc
--- /dev/null
+++ b/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/postmessage-ping-worker.js
@@ -0,0 +1,15 @@
+self.addEventListener('message', function(event) {
+ if ('port' in event.data) {
+ var port = event.data.port;
+
+ var channel = new MessageChannel();
+ channel.port1.onmessage = function(event) {
+ if ('pong' in event.data)
+ port.postMessage(event.data.pong);
+ };
+
+ // Send a ping message to another service worker.
+ self.registration.waiting.postMessage({ping: channel.port2},
+ [channel.port2]);
+ }
+ });
diff --git a/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/postmessage-pong-worker.js b/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/postmessage-pong-worker.js
new file mode 100644
index 0000000..4a0d90b
--- /dev/null
+++ b/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/postmessage-pong-worker.js
@@ -0,0 +1,4 @@
+self.addEventListener('message', function(event) {
+ if ('ping' in event.data)
+ event.data.ping.postMessage({pong: 'OK'});
+ });
diff --git a/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/registration-attribute-newer-worker.js b/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/registration-attribute-newer-worker.js
new file mode 100644
index 0000000..44f3e2e
--- /dev/null
+++ b/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/registration-attribute-newer-worker.js
@@ -0,0 +1,33 @@
+// TODO(nhiroki): stop using global states because service workers can be killed
+// at any point. Instead, we could post a message to the page on each event via
+// Client object (http://crbug.com/558244).
+var results = [];
+
+function stringify(worker) {
+ return worker ? worker.scriptURL : 'empty';
+}
+
+function record(event_name) {
+ results.push(event_name);
+ results.push(' installing: ' + stringify(self.registration.installing));
+ results.push(' waiting: ' + stringify(self.registration.waiting));
+ results.push(' active: ' + stringify(self.registration.active));
+}
+
+record('evaluate');
+
+self.registration.addEventListener('updatefound', function() {
+ record('updatefound');
+ var worker = self.registration.installing;
+ self.registration.installing.addEventListener('statechange', function() {
+ record('statechange(' + worker.state + ')');
+ });
+ });
+
+self.addEventListener('install', function(e) { record('install'); });
+
+self.addEventListener('activate', function(e) { record('activate'); });
+
+self.addEventListener('message', function(e) {
+ e.data.port.postMessage(results);
+ });
diff --git a/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/registration-attribute-worker.js b/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/registration-attribute-worker.js
new file mode 100644
index 0000000..315f437
--- /dev/null
+++ b/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/registration-attribute-worker.js
@@ -0,0 +1,139 @@
+importScripts('../../resources/test-helpers.sub.js');
+importScripts('../../resources/worker-testharness.js');
+
+// TODO(nhiroki): stop using global states because service workers can be killed
+// at any point. Instead, we could post a message to the page on each event via
+// Client object (http://crbug.com/558244).
+var events_seen = [];
+
+// TODO(nhiroki): Move these assertions to registration-attribute.html because
+// an assertion failure on the worker is not shown on the result page and
+// handled as timeout. See registration-attribute-newer-worker.js for example.
+
+assert_equals(
+ self.registration.scope,
+ normalizeURL('scope/registration-attribute'),
+ 'On worker script evaluation, registration attribute should be set');
+assert_equals(
+ self.registration.installing,
+ null,
+ 'On worker script evaluation, installing worker should be null');
+assert_equals(
+ self.registration.waiting,
+ null,
+ 'On worker script evaluation, waiting worker should be null');
+assert_equals(
+ self.registration.active,
+ null,
+ 'On worker script evaluation, active worker should be null');
+
+self.registration.addEventListener('updatefound', function() {
+ events_seen.push('updatefound');
+
+ assert_equals(
+ self.registration.scope,
+ normalizeURL('scope/registration-attribute'),
+ 'On updatefound event, registration attribute should be set');
+ assert_equals(
+ self.registration.installing.scriptURL,
+ normalizeURL('registration-attribute-worker.js'),
+ 'On updatefound event, installing worker should be set');
+ assert_equals(
+ self.registration.waiting,
+ null,
+ 'On updatefound event, waiting worker should be null');
+ assert_equals(
+ self.registration.active,
+ null,
+ 'On updatefound event, active worker should be null');
+
+ assert_equals(
+ self.registration.installing.state,
+ 'installing',
+ 'On updatefound event, worker should be in the installing state');
+
+ var worker = self.registration.installing;
+ self.registration.installing.addEventListener('statechange', function() {
+ events_seen.push('statechange(' + worker.state + ')');
+ });
+ });
+
+self.addEventListener('install', function(e) {
+ events_seen.push('install');
+
+ assert_equals(
+ self.registration.scope,
+ normalizeURL('scope/registration-attribute'),
+ 'On install event, registration attribute should be set');
+ assert_equals(
+ self.registration.installing.scriptURL,
+ normalizeURL('registration-attribute-worker.js'),
+ 'On install event, installing worker should be set');
+ assert_equals(
+ self.registration.waiting,
+ null,
+ 'On install event, waiting worker should be null');
+ assert_equals(
+ self.registration.active,
+ null,
+ 'On install event, active worker should be null');
+
+ assert_equals(
+ self.registration.installing.state,
+ 'installing',
+ 'On install event, worker should be in the installing state');
+ });
+
+self.addEventListener('activate', function(e) {
+ events_seen.push('activate');
+
+ assert_equals(
+ self.registration.scope,
+ normalizeURL('scope/registration-attribute'),
+ 'On activate event, registration attribute should be set');
+ assert_equals(
+ self.registration.installing,
+ null,
+ 'On activate event, installing worker should be null');
+ assert_equals(
+ self.registration.waiting,
+ null,
+ 'On activate event, waiting worker should be null');
+ assert_equals(
+ self.registration.active.scriptURL,
+ normalizeURL('registration-attribute-worker.js'),
+ 'On activate event, active worker should be set');
+
+ assert_equals(
+ self.registration.active.state,
+ 'activating',
+ 'On activate event, worker should be in the activating state');
+ });
+
+self.addEventListener('fetch', function(e) {
+ events_seen.push('fetch');
+
+ assert_equals(
+ self.registration.scope,
+ normalizeURL('scope/registration-attribute'),
+ 'On fetch event, registration attribute should be set');
+ assert_equals(
+ self.registration.installing,
+ null,
+ 'On fetch event, installing worker should be null');
+ assert_equals(
+ self.registration.waiting,
+ null,
+ 'On fetch event, waiting worker should be null');
+ assert_equals(
+ self.registration.active.scriptURL,
+ normalizeURL('registration-attribute-worker.js'),
+ 'On fetch event, active worker should be set');
+
+ assert_equals(
+ self.registration.active.state,
+ 'activated',
+ 'On fetch event, worker should be in the activated state');
+
+ e.respondWith(new Response(events_seen));
+ });
diff --git a/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/unregister-controlling-worker.html b/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/unregister-controlling-worker.html
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/unregister-controlling-worker.html
diff --git a/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/unregister-worker.js b/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/unregister-worker.js
new file mode 100644
index 0000000..6da397d
--- /dev/null
+++ b/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/unregister-worker.js
@@ -0,0 +1,25 @@
+function matchQuery(query) {
+ return self.location.href.indexOf(query) != -1;
+}
+
+if (matchQuery('?evaluation'))
+ self.registration.unregister();
+
+self.addEventListener('install', function(e) {
+ if (matchQuery('?install')) {
+ // Don't do waitUntil(unregister()) as that would deadlock as specified.
+ self.registration.unregister();
+ }
+ });
+
+self.addEventListener('activate', function(e) {
+ if (matchQuery('?activate'))
+ e.waitUntil(self.registration.unregister());
+ });
+
+self.addEventListener('message', function(e) {
+ e.waitUntil(self.registration.unregister()
+ .then(function(result) {
+ e.data.port.postMessage({result: result});
+ }));
+ });
diff --git a/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/update-worker.js b/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/update-worker.js
new file mode 100644
index 0000000..8be8a1f
--- /dev/null
+++ b/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/update-worker.js
@@ -0,0 +1,22 @@
+var events_seen = [];
+
+self.registration.addEventListener('updatefound', function() {
+ events_seen.push('updatefound');
+ });
+
+self.addEventListener('activate', function(e) {
+ events_seen.push('activate');
+ });
+
+self.addEventListener('fetch', function(e) {
+ events_seen.push('fetch');
+ e.respondWith(new Response(events_seen));
+ });
+
+self.addEventListener('message', function(e) {
+ events_seen.push('message');
+ self.registration.update();
+ });
+
+// update() during the script evaluation should be ignored.
+self.registration.update();
diff --git a/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/update-worker.py b/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/update-worker.py
new file mode 100644
index 0000000..8a87e1b
--- /dev/null
+++ b/test/wpt/tests/service-workers/service-worker/ServiceWorkerGlobalScope/resources/update-worker.py
@@ -0,0 +1,16 @@
+import os
+import time
+
+from wptserve.utils import isomorphic_decode
+
+def main(request, response):
+ # update() does not bypass cache so set the max-age to 0 such that update()
+ # can find a new version in the network.
+ headers = [(b'Cache-Control', b'max-age: 0'),
+ (b'Content-Type', b'application/javascript')]
+ with open(os.path.join(os.path.dirname(isomorphic_decode(__file__)),
+ u'update-worker.js'), u'r') as file:
+ script = file.read()
+ # Return a different script for each access.
+ return headers, u'// %s\n%s' % (time.time(), script)
+