зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to autoland. a=merge CLOSED TREE
This commit is contained in:
Коммит
f713c5d75e
|
@ -429,11 +429,15 @@ DownloadsPlacesView.prototype = {
|
|||
xblFields.set(key, value);
|
||||
}
|
||||
|
||||
let oldActiveElement = document.activeElement;
|
||||
let parentNode = this._richlistbox.parentNode;
|
||||
let nextSibling = this._richlistbox.nextSibling;
|
||||
parentNode.removeChild(this._richlistbox);
|
||||
this._richlistbox.prepend(this.batchFragment);
|
||||
parentNode.insertBefore(this._richlistbox, nextSibling);
|
||||
if (oldActiveElement && oldActiveElement != document.activeElement) {
|
||||
oldActiveElement.focus();
|
||||
}
|
||||
|
||||
for (let [key, value] of xblFields) {
|
||||
this._richlistbox[key] = value;
|
||||
|
|
|
@ -202,7 +202,6 @@ def old_configure_options(*options):
|
|||
'--enable-nfc',
|
||||
'--enable-nspr-build',
|
||||
'--enable-official-branding',
|
||||
'--enable-oom-breakpoint',
|
||||
'--enable-parental-controls',
|
||||
'--enable-pie',
|
||||
'--enable-posix-nspr-emulation',
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
This is the debugger.html project output.
|
||||
See https://github.com/devtools-html/debugger.html
|
||||
|
||||
Version v11.0
|
||||
Comparison: https://github.com/devtools-html/debugger.html/compare/release-10...release-11
|
||||
Commit: https://github.com/devtools-html/debugger.html/commit/4ef9b879ef7b51430e4acdadfd24a8d7e9f64c82
|
||||
Version 12.0
|
||||
Comparison: https://github.com/devtools-html/debugger.html/compare/release-11...release-12
|
||||
Commit: https://github.com/devtools-html/debugger.html/commit/5f7ecfe
|
||||
|
||||
Packages:
|
||||
- babel-plugin-transform-es2015-modules-commonjs @6.26.0
|
||||
|
|
|
@ -1122,6 +1122,95 @@ html[dir="rtl"] .managed-tree .tree .node > div {
|
|||
.managed-tree .tree-node button {
|
||||
position: fixed;
|
||||
}
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
.tree {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.tree.inline {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.tree.nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tree.noselect {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
-o-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.tree button {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.tree .tree-node {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.tree .tree-node:not(.focused):hover {
|
||||
background-color: var(--theme-selection-background-hover);
|
||||
}
|
||||
|
||||
.tree-indent {
|
||||
display: inline-block;
|
||||
width: 12px;
|
||||
margin-inline-start: 5px;
|
||||
border-inline-start: 1px solid #A2D1FF;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Align with expandables siblings (where we have the arrow) */
|
||||
.tree-node[data-expandable="false"] .tree-indent:last-of-type {
|
||||
margin-inline-end: 15px;
|
||||
}
|
||||
|
||||
/* For non expandable root nodes, we don't have .tree-indent elements, so we declare
|
||||
the margin on the start of the node */
|
||||
.tree-node[data-expandable="false"][aria-level="0"] {
|
||||
padding-inline-start: 15px
|
||||
}
|
||||
|
||||
.tree .tree-node[data-expandable="true"] {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.tree .tree-node.focused {
|
||||
color: white;
|
||||
background-color: var(--theme-selection-background, #0a84ff);
|
||||
}
|
||||
|
||||
.tree-node.focused .arrow svg {
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
.tree-node:hover img {
|
||||
background-color: var(--theme-content-color3);
|
||||
}
|
||||
|
||||
.arrow svg {
|
||||
fill: var(--theme-splitter-color, #9B9B9B);
|
||||
transition: transform 0.125s ease;
|
||||
width: 10px;
|
||||
margin-inline-end: 5px;
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
|
||||
html[dir="rtl"] .arrow svg,
|
||||
.arrow svg:dir(rtl),
|
||||
.arrow svg:-moz-locale-dir(rtl) {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.arrow.expanded.expanded svg {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
@ -1409,6 +1498,10 @@ html[dir="rtl"] .managed-tree .tree .node > div {
|
|||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.sources-list .tree:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.sources-list .managed-tree {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
|
@ -2060,6 +2153,13 @@ html .toggle-button.end.vertical svg {
|
|||
color: var(--theme-body-color);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* Length bubble for arraylikes and maplikes */
|
||||
|
||||
.objectLengthBubble {
|
||||
color: var(--null-color);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
.objectLeftBrace,
|
||||
|
@ -2070,7 +2170,7 @@ html .toggle-button.end.vertical svg {
|
|||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* Cycle reference*/
|
||||
/* Cycle reference */
|
||||
|
||||
.objectBox-Reference {
|
||||
font-weight: bold;
|
||||
|
@ -2149,91 +2249,6 @@ html .toggle-button.end.vertical svg {
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
.tree {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.tree.inline {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.tree.nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tree.noselect {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
-o-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.tree button {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.tree .tree-node {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.tree-indent {
|
||||
display: inline-block;
|
||||
width: 12px;
|
||||
margin-inline-start: 5px;
|
||||
border-inline-start: 1px solid #A2D1FF;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Align with expandables siblings (where we have the arrow) */
|
||||
.tree-node[data-expandable="false"] .tree-indent:last-of-type {
|
||||
margin-inline-end: 15px;
|
||||
}
|
||||
|
||||
/* For non expandable root nodes, we don't have .tree-indent elements, so we declare
|
||||
the margin on the start of the node */
|
||||
.tree-node[data-expandable="false"][aria-level="0"] {
|
||||
padding-inline-start: 15px
|
||||
}
|
||||
|
||||
.tree .tree-node[data-expandable="true"] {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.tree .tree-node:not(.focused):hover {
|
||||
background-color: #F0F9FE;
|
||||
}
|
||||
|
||||
.tree .tree-node.focused {
|
||||
color: white;
|
||||
background-color: var(--theme-selection-background, #0a84ff);
|
||||
}
|
||||
|
||||
.tree-node.focused .arrow svg {
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
.arrow svg {
|
||||
fill: var(--theme-splitter-color, #9B9B9B);
|
||||
transition: transform 0.125s ease;
|
||||
width: 10px;
|
||||
margin-inline-end: 5px;
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
|
||||
html[dir="rtl"] .arrow svg,
|
||||
.arrow svg:dir(rtl),
|
||||
.arrow svg:-moz-locale-dir(rtl) {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.arrow.expanded.expanded svg {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
.tree.object-inspector .node.object-node {
|
||||
display: inline-block;
|
||||
}
|
||||
|
@ -3025,6 +3040,10 @@ html .breakpoints-list .breakpoint.paused {
|
|||
.expression-input {
|
||||
max-width: 50%;
|
||||
}
|
||||
|
||||
.expressions-list .tree:focus {
|
||||
outline: none;
|
||||
}
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
@ -3614,6 +3633,10 @@ img.ignore-exceptions {
|
|||
padding-inline-start: 4px;
|
||||
}
|
||||
|
||||
.scopes-list .tree:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.scopes-list .function-signature {
|
||||
display: inline-block;
|
||||
}
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -15,6 +15,14 @@ support-files =
|
|||
examples/sourcemaps3/bundle.js.map
|
||||
examples/sourcemaps3/sorted.js
|
||||
examples/sourcemaps3/test.js
|
||||
examples/sourcemaps-reload/v1.bundle.js
|
||||
examples/sourcemaps-reload/v1.bundle.js.map
|
||||
examples/sourcemaps-reload/v2.bundle.js
|
||||
examples/sourcemaps-reload/v2.bundle.js.map
|
||||
examples/sourcemaps-reload/v3.bundle.js
|
||||
examples/sourcemaps-reload/v3.bundle.js.map
|
||||
examples/sourcemaps-reload/doc-sourcemaps-reload.html
|
||||
examples/sourcemaps-reload/sjs_code_reload.sjs
|
||||
examples/wasm-sourcemaps/average.js
|
||||
examples/wasm-sourcemaps/average.wasm
|
||||
examples/wasm-sourcemaps/average.wasm.map
|
||||
|
@ -25,7 +33,8 @@ support-files =
|
|||
examples/sum/sum.min.js.map
|
||||
examples/reload/code_reload_1.js
|
||||
examples/reload/code_reload_2.js
|
||||
examples/reload/doc_reload.html
|
||||
examples/reload/doc-reload.html
|
||||
examples/reload/sjs_code_reload.sjs
|
||||
examples/doc-async.html
|
||||
examples/doc-asm.html
|
||||
examples/doc-content-script-sources.html
|
||||
|
@ -63,7 +72,6 @@ support-files =
|
|||
examples/script-switching-02.js
|
||||
examples/script-switching-01.js
|
||||
examples/times2.js
|
||||
examples/reload/sjs_code_reload.sjs
|
||||
|
||||
[browser_dbg-asm.js]
|
||||
[browser_dbg-async-stepping.js]
|
||||
|
@ -115,6 +123,7 @@ skip-if = os == "win" # Bug 1393121
|
|||
skip-if = true # regular failures during release in Bug 1415300
|
||||
[browser_dbg-search-project.js]
|
||||
[browser_dbg-sourcemaps.js]
|
||||
[browser_dbg-sourcemaps-reload.js]
|
||||
[browser_dbg-sourcemaps-reloading.js]
|
||||
[browser_dbg-sourcemaps2.js]
|
||||
[browser_dbg-sourcemaps3.js]
|
||||
|
|
|
@ -18,10 +18,11 @@ async function waitForBreakpoint(dbg, location) {
|
|||
}
|
||||
|
||||
add_task(async function() {
|
||||
const dbg = await initDebugger("reload/doc_reload.html", "sjs_code_reload");
|
||||
|
||||
const dbg = await initDebugger("reload/doc-reload.html");
|
||||
await waitForSource(dbg, "sjs_code_reload");
|
||||
await selectSource(dbg, "sjs_code_reload");
|
||||
await waitForSelectedSource(dbg, "sjs_code_reload");
|
||||
|
||||
await addBreakpoint(dbg, "sjs_code_reload", 2);
|
||||
|
||||
await reload(dbg, "sjs_code_reload");
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*
|
||||
* Test reloading:
|
||||
* 1. reload the source
|
||||
* 2. re-sync breakpoints
|
||||
*/
|
||||
|
||||
async function waitForBreakpoint(dbg, location) {
|
||||
return waitForState(
|
||||
dbg,
|
||||
state => {
|
||||
return dbg.selectors.getBreakpoint(dbg.getState(), location);
|
||||
},
|
||||
"Waiting for breakpoint"
|
||||
);
|
||||
}
|
||||
|
||||
function getBreakpoints(dbg) {
|
||||
const breakpoints = dbg.selectors.getBreakpoints(dbg.getState());
|
||||
return breakpoints.valueSeq().toJS();
|
||||
}
|
||||
|
||||
add_task(async function() {
|
||||
const dbg = await initDebugger("doc-minified.html");
|
||||
|
||||
await navigate(dbg, "sourcemaps-reload/doc-sourcemaps-reload.html", "v1");
|
||||
|
||||
await waitForSource(dbg, "v1");
|
||||
await selectSource(dbg, "v1");
|
||||
|
||||
await addBreakpoint(dbg, "v1", 6);
|
||||
let breakpoint = getBreakpoints(dbg)[0];
|
||||
is(breakpoint.location.line, 6);
|
||||
|
||||
let syncBp = waitForDispatch(dbg, "SYNC_BREAKPOINT");
|
||||
await reload(dbg);
|
||||
|
||||
await waitForPaused(dbg);
|
||||
await syncBp;
|
||||
assertDebugLine(dbg, 72);
|
||||
breakpoint = getBreakpoints(dbg)[0];
|
||||
|
||||
is(breakpoint.location.line, 9);
|
||||
is(breakpoint.generatedLocation.line, 73);
|
||||
|
||||
await resume(dbg);
|
||||
syncBp = waitForDispatch(dbg, "SYNC_BREAKPOINT", 2);
|
||||
await selectSource(dbg, "v1");
|
||||
await addBreakpoint(dbg, "v1", 13);
|
||||
|
||||
await reload(dbg);
|
||||
await waitForSource(dbg, "v1");
|
||||
await syncBp;
|
||||
await waitForSelectedSource(dbg, "v1");
|
||||
|
||||
is(getBreakpoints(dbg).length, 0, "No breakpoints");
|
||||
});
|
|
@ -1,6 +1,10 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
async function waitForBreakpointCount(dbg, count) {
|
||||
return waitForState(dbg, state => dbg.selectors.getBreakpoints(state).size === count)
|
||||
}
|
||||
|
||||
add_task(async function() {
|
||||
// NOTE: the CORS call makes the test run times inconsistent
|
||||
requestLongerTimeout(2);
|
||||
|
@ -22,12 +26,14 @@ add_task(async function() {
|
|||
// should not move anywhere.
|
||||
await addBreakpoint(dbg, entrySrc, 13);
|
||||
is(getBreakpoints(getState()).size, 1, "One breakpoint exists");
|
||||
|
||||
ok(
|
||||
getBreakpoint(getState(), { sourceId: entrySrc.id, line: 13 }),
|
||||
"Breakpoint has correct line"
|
||||
);
|
||||
|
||||
await addBreakpoint(dbg, entrySrc, 5);
|
||||
|
||||
await addBreakpoint(dbg, entrySrc, 15);
|
||||
await disableBreakpoint(dbg, entrySrc, 15);
|
||||
|
||||
|
@ -38,6 +44,7 @@ add_task(async function() {
|
|||
await waitForPaused(dbg);
|
||||
assertPausedLocation(dbg);
|
||||
|
||||
await waitForBreakpointCount(dbg, 3);
|
||||
is(getBreakpoints(getState()).size, 3, "Three breakpoints exist");
|
||||
|
||||
ok(
|
||||
|
|
|
@ -12,7 +12,9 @@ async function waitForSourceCount(dbg, i) {
|
|||
}
|
||||
|
||||
function getLabel(dbg, index) {
|
||||
return findElement(dbg, "sourceNode", index).textContent.trim();
|
||||
return findElement(dbg, "sourceNode", index)
|
||||
.textContent.trim()
|
||||
.replace(/^[\s\u200b]*/g, "");
|
||||
}
|
||||
|
||||
add_task(async function() {
|
||||
|
@ -27,5 +29,5 @@ add_task(async function() {
|
|||
|
||||
await waitForSourceCount(dbg, 3);
|
||||
|
||||
is(getLabel(dbg, 3), "evaled.js", "the eval script exists");
|
||||
is(getLabel(dbg, 3), "evaled.js", "evaled exists");
|
||||
});
|
||||
|
|
|
@ -17,7 +17,9 @@ async function assertSourceCount(dbg, count) {
|
|||
}
|
||||
|
||||
function getLabel(dbg, index) {
|
||||
return findElement(dbg, "sourceNode", index).textContent.trim();
|
||||
return findElement(dbg, "sourceNode", index)
|
||||
.textContent.trim()
|
||||
.replace(/^[\s\u200b]*/g, "");
|
||||
}
|
||||
|
||||
add_task(async function() {
|
||||
|
@ -62,5 +64,9 @@ add_task(async function() {
|
|||
});
|
||||
|
||||
await waitForSourceCount(dbg, 9);
|
||||
is(getLabel(dbg, 7), "math.min.js", "The dynamic script exists");
|
||||
is(
|
||||
getLabel(dbg, 7),
|
||||
"math.min.js",
|
||||
"math.min.js - The dynamic script exists"
|
||||
);
|
||||
});
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"plugins": ["transform-async-to-generator"]
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
### Steps to Rebuild
|
||||
|
||||
1. make changes to v1.js, v2.js, v3.js
|
||||
2. run `yarn` to install webpack & babel
|
||||
3. run `webpack`
|
||||
4. change `sources` reference in `v2.bundle.js.map` to `v1.js`
|
||||
5. change `sources` reference in `v3.bundle.js.map` to `v1.js`
|
|
@ -0,0 +1,15 @@
|
|||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<!doctype html>
|
||||
|
||||
<html>
|
||||
<script src="sjs_code_reload.sjs?foo"></script>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Empty test page 1</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"name": "sourcemaps-reload",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "sorted.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"babel-core": "^6.26.0",
|
||||
"babel-loader": "^7.1.2",
|
||||
"babel-preset-es2015": "^6.24.1",
|
||||
"webpack": "^3.7.1"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/* globals getState, setState */
|
||||
/* exported handleRequest */
|
||||
|
||||
"use strict";
|
||||
|
||||
const NUM_FILES = 3;
|
||||
|
||||
function _getUrl(request, counter) {
|
||||
const { scheme, host, path } = request;
|
||||
|
||||
const index = Math.ceil(counter / 2);
|
||||
const showMap = false ;//(counter % 2) === 1
|
||||
const newPath = path.substr(0, path.lastIndexOf("/") + 1);
|
||||
const url = `${scheme}://${host}${newPath}/v${index}.bundle.js${showMap ? '.map' : ''}`;
|
||||
return url
|
||||
}
|
||||
|
||||
function handleRequest(request, response) {
|
||||
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||
response.setHeader("Pragma", "no-cache");
|
||||
response.setHeader("Expires", "0");
|
||||
response.setHeader("Access-Control-Allow-Origin", "*", false);
|
||||
response.setHeader("Content-Type", "text/javascript", false);
|
||||
|
||||
// Redirect to a different file each time.
|
||||
let counter = (+getState("counter") || 1) % ( 2 * NUM_FILES + 1);
|
||||
|
||||
const newUrl = _getUrl(request, counter);
|
||||
|
||||
response.setStatusLine(request.httpVersion, 302, "Found");
|
||||
response.setHeader("Location", newUrl);
|
||||
setState("counter", "" + ++counter);
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
/******/ (function(modules) { // webpackBootstrap
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/
|
||||
/******/ // Check if module is in cache
|
||||
/******/ if(installedModules[moduleId]) {
|
||||
/******/ return installedModules[moduleId].exports;
|
||||
/******/ }
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = installedModules[moduleId] = {
|
||||
/******/ i: moduleId,
|
||||
/******/ l: false,
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Flag the module as loaded
|
||||
/******/ module.l = true;
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
/******/
|
||||
/******/
|
||||
/******/ // expose the modules object (__webpack_modules__)
|
||||
/******/ __webpack_require__.m = modules;
|
||||
/******/
|
||||
/******/ // expose the module cache
|
||||
/******/ __webpack_require__.c = installedModules;
|
||||
/******/
|
||||
/******/ // define getter function for harmony exports
|
||||
/******/ __webpack_require__.d = function(exports, name, getter) {
|
||||
/******/ if(!__webpack_require__.o(exports, name)) {
|
||||
/******/ Object.defineProperty(exports, name, {
|
||||
/******/ configurable: false,
|
||||
/******/ enumerable: true,
|
||||
/******/ get: getter
|
||||
/******/ });
|
||||
/******/ }
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
||||
/******/ __webpack_require__.n = function(module) {
|
||||
/******/ var getter = module && module.__esModule ?
|
||||
/******/ function getDefault() { return module['default']; } :
|
||||
/******/ function getModuleExports() { return module; };
|
||||
/******/ __webpack_require__.d(getter, 'a', getter);
|
||||
/******/ return getter;
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Object.prototype.hasOwnProperty.call
|
||||
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
||||
/******/
|
||||
/******/ // __webpack_public_path__
|
||||
/******/ __webpack_require__.p = "";
|
||||
/******/
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(__webpack_require__.s = 0);
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ([
|
||||
/* 0 */
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
let foo = (() => {
|
||||
var _ref = _asyncToGenerator(function* () {
|
||||
yield bar();
|
||||
console.log("YO");
|
||||
});
|
||||
|
||||
return function foo() {
|
||||
return _ref.apply(this, arguments);
|
||||
};
|
||||
})();
|
||||
|
||||
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
|
||||
|
||||
function bar() {
|
||||
return new Promise(resolve => setTimeout(resolve, 100));
|
||||
}
|
||||
|
||||
/***/ })
|
||||
/******/ ]);
|
||||
//# sourceMappingURL=v1.bundle.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["webpack:///webpack/bootstrap 8bcf0d04c821a99f6859","webpack:///./v1.js"],"names":["bar","console","log","foo","Promise","resolve","setTimeout"],"mappings":";AAAA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,mCAA2B,0BAA0B,EAAE;AACvD,yCAAiC,eAAe;AAChD;AACA;AACA;;AAEA;AACA,8DAAsD,+DAA+D;;AAErH;AACA;;AAEA;AACA;;;;;;;;+BCzDA,aAAqB;AACnB,UAAMA,KAAN;AACAC,YAAQC,GAAR,CAAY,IAAZ;AACD,G;;kBAHcC,G;;;;;;;AAJf,SAASH,GAAT,GAAe;AACb,SAAO,IAAII,OAAJ,CAAYC,WAAWC,WAAWD,OAAX,EAAoB,GAApB,CAAvB,CAAP;AACD,C","file":"v1.bundle.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 8bcf0d04c821a99f6859","function bar() {\n return new Promise(resolve => setTimeout(resolve, 100))\n}\n\nasync function foo() {\n await bar();\n console.log(\"YO\")\n}\n\n\n\n// WEBPACK FOOTER //\n// ./v1.js"],"sourceRoot":""}
|
|
@ -0,0 +1,8 @@
|
|||
function bar() {
|
||||
return new Promise(resolve => setTimeout(resolve, 100))
|
||||
}
|
||||
|
||||
async function foo() {
|
||||
await bar();
|
||||
console.log("YO")
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
/******/ (function(modules) { // webpackBootstrap
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/
|
||||
/******/ // Check if module is in cache
|
||||
/******/ if(installedModules[moduleId]) {
|
||||
/******/ return installedModules[moduleId].exports;
|
||||
/******/ }
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = installedModules[moduleId] = {
|
||||
/******/ i: moduleId,
|
||||
/******/ l: false,
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Flag the module as loaded
|
||||
/******/ module.l = true;
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
/******/
|
||||
/******/
|
||||
/******/ // expose the modules object (__webpack_modules__)
|
||||
/******/ __webpack_require__.m = modules;
|
||||
/******/
|
||||
/******/ // expose the module cache
|
||||
/******/ __webpack_require__.c = installedModules;
|
||||
/******/
|
||||
/******/ // define getter function for harmony exports
|
||||
/******/ __webpack_require__.d = function(exports, name, getter) {
|
||||
/******/ if(!__webpack_require__.o(exports, name)) {
|
||||
/******/ Object.defineProperty(exports, name, {
|
||||
/******/ configurable: false,
|
||||
/******/ enumerable: true,
|
||||
/******/ get: getter
|
||||
/******/ });
|
||||
/******/ }
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
||||
/******/ __webpack_require__.n = function(module) {
|
||||
/******/ var getter = module && module.__esModule ?
|
||||
/******/ function getDefault() { return module['default']; } :
|
||||
/******/ function getModuleExports() { return module; };
|
||||
/******/ __webpack_require__.d(getter, 'a', getter);
|
||||
/******/ return getter;
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Object.prototype.hasOwnProperty.call
|
||||
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
||||
/******/
|
||||
/******/ // __webpack_public_path__
|
||||
/******/ __webpack_require__.p = "";
|
||||
/******/
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(__webpack_require__.s = 1);
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ([
|
||||
/* 0 */,
|
||||
/* 1 */
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
let foo = (() => {
|
||||
var _ref = _asyncToGenerator(function* () {
|
||||
yield bar();
|
||||
console.log("YO");
|
||||
});
|
||||
|
||||
return function foo() {
|
||||
return _ref.apply(this, arguments);
|
||||
};
|
||||
})();
|
||||
|
||||
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
|
||||
|
||||
function bar() {
|
||||
return new Promise(resolve => setTimeout(resolve, 100));
|
||||
}
|
||||
|
||||
console.log("HEY");
|
||||
|
||||
/***/ })
|
||||
/******/ ]);
|
||||
//# sourceMappingURL=v2.bundle.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["webpack:///webpack/bootstrap 8bcf0d04c821a99f6859","webpack:///./v1.js"],"names":["bar","console","log","foo","Promise","resolve","setTimeout"],"mappings":";AAAA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,mCAA2B,0BAA0B,EAAE;AACvD,yCAAiC,eAAe;AAChD;AACA;AACA;;AAEA;AACA,8DAAsD,+DAA+D;;AAErH;AACA;;AAEA;AACA;;;;;;;;;+BCtDA,aAAqB;AACnB,UAAMA,KAAN;AACAC,YAAQC,GAAR,CAAY,IAAZ;AACD,G;;kBAHcC,G;;;;;;;AAPf,SAASH,GAAT,GAAe;AACb,SAAO,IAAII,OAAJ,CAAYC,WAAWC,WAAWD,OAAX,EAAoB,GAApB,CAAvB,CAAP;AACD;;AAUDJ,QAAQC,GAAR,CAAY,KAAZ,E","file":"v2.bundle.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 1);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 8bcf0d04c821a99f6859","function bar() {\n return new Promise(resolve => setTimeout(resolve, 100))\n}\n\n\n\n\nasync function foo() {\n await bar();\n console.log(\"YO\")\n}\n\nconsole.log(\"HEY\")\n\n\n\n// WEBPACK FOOTER //\n// ./v2.js"],"sourceRoot":""}
|
|
@ -0,0 +1,13 @@
|
|||
function bar() {
|
||||
return new Promise(resolve => setTimeout(resolve, 100))
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
async function foo() {
|
||||
await bar();
|
||||
console.log("YO")
|
||||
}
|
||||
|
||||
console.log("HEY")
|
|
@ -0,0 +1,78 @@
|
|||
/******/ (function(modules) { // webpackBootstrap
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/
|
||||
/******/ // Check if module is in cache
|
||||
/******/ if(installedModules[moduleId]) {
|
||||
/******/ return installedModules[moduleId].exports;
|
||||
/******/ }
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = installedModules[moduleId] = {
|
||||
/******/ i: moduleId,
|
||||
/******/ l: false,
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Flag the module as loaded
|
||||
/******/ module.l = true;
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
/******/
|
||||
/******/
|
||||
/******/ // expose the modules object (__webpack_modules__)
|
||||
/******/ __webpack_require__.m = modules;
|
||||
/******/
|
||||
/******/ // expose the module cache
|
||||
/******/ __webpack_require__.c = installedModules;
|
||||
/******/
|
||||
/******/ // define getter function for harmony exports
|
||||
/******/ __webpack_require__.d = function(exports, name, getter) {
|
||||
/******/ if(!__webpack_require__.o(exports, name)) {
|
||||
/******/ Object.defineProperty(exports, name, {
|
||||
/******/ configurable: false,
|
||||
/******/ enumerable: true,
|
||||
/******/ get: getter
|
||||
/******/ });
|
||||
/******/ }
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
||||
/******/ __webpack_require__.n = function(module) {
|
||||
/******/ var getter = module && module.__esModule ?
|
||||
/******/ function getDefault() { return module['default']; } :
|
||||
/******/ function getModuleExports() { return module; };
|
||||
/******/ __webpack_require__.d(getter, 'a', getter);
|
||||
/******/ return getter;
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Object.prototype.hasOwnProperty.call
|
||||
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
||||
/******/
|
||||
/******/ // __webpack_public_path__
|
||||
/******/ __webpack_require__.p = "";
|
||||
/******/
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(__webpack_require__.s = 2);
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ({
|
||||
|
||||
/***/ 2:
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
function bar() {
|
||||
return new Promise(resolve => setTimeout(resolve, 100));
|
||||
}
|
||||
|
||||
/***/ })
|
||||
|
||||
/******/ });
|
||||
//# sourceMappingURL=v3.bundle.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sources":["webpack:///webpack/bootstrap 8bcf0d04c821a99f6859","webpack:///./v1.js"],"names":["bar","Promise","resolve","setTimeout"],"mappings":";AAAA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,mCAA2B,0BAA0B,EAAE;AACvD,yCAAiC,eAAe;AAChD;AACA;AACA;;AAEA;AACA,8DAAsD,+DAA+D;;AAErH;AACA;;AAEA;AACA;;;;;;;;AC7DA,SAASA,GAAT,GAAe;AACb,SAAO,IAAIC,OAAJ,CAAYC,WAAWC,WAAWD,OAAX,EAAoB,GAApB,CAAvB,CAAP;AACD,C","file":"v3.bundle.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 2);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 8bcf0d04c821a99f6859","function bar() {\n return new Promise(resolve => setTimeout(resolve, 100))\n}\n\n\n\n// WEBPACK FOOTER //\n// ./v3.js"],"sourceRoot":""}
|
|
@ -0,0 +1,3 @@
|
|||
function bar() {
|
||||
return new Promise(resolve => setTimeout(resolve, 100))
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
const path = require("path");
|
||||
const webpack = require("webpack");
|
||||
|
||||
module.exports = {
|
||||
entry: {
|
||||
v1: "./v1.js",
|
||||
v2: "./v2.js",
|
||||
v3: "./v3.js"
|
||||
},
|
||||
output: {
|
||||
path: __dirname,
|
||||
filename: "[name].bundle.js"
|
||||
},
|
||||
devtool: "sourcemap",
|
||||
module: {
|
||||
loaders: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
exclude: /node_modules/,
|
||||
loader: "babel-loader"
|
||||
}
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
]
|
||||
};
|
|
@ -29,6 +29,10 @@ copySourceUri2.accesskey=u
|
|||
setDirectoryRoot.label=Set directory root
|
||||
setDirectoryRoot.accesskey=r
|
||||
|
||||
# LOCALIZATION NOTE (removeDirectoryRoot): This is the text that appears in the
|
||||
# context menu to remove a directory as root directory
|
||||
removeDirectoryRoot.label=Remove directory root
|
||||
|
||||
# LOCALIZATION NOTE (copyFunction): This is the text that appears in the
|
||||
# context menu to copy the function the user selected
|
||||
copyFunction.label=Copy function
|
||||
|
|
|
@ -246,6 +246,7 @@
|
|||
#include "mozilla/dom/NavigatorBinding.h"
|
||||
#include "mozilla/dom/ImageBitmap.h"
|
||||
#include "mozilla/dom/ImageBitmapBinding.h"
|
||||
#include "mozilla/dom/ServiceWorker.h"
|
||||
#include "mozilla/dom/ServiceWorkerRegistration.h"
|
||||
#include "mozilla/dom/U2F.h"
|
||||
#include "mozilla/dom/WebIDLGlobalNameHash.h"
|
||||
|
@ -2395,6 +2396,12 @@ nsPIDOMWindowInner::GetController() const
|
|||
return Move(nsGlobalWindowInner::Cast(this)->GetController());
|
||||
}
|
||||
|
||||
RefPtr<mozilla::dom::ServiceWorker>
|
||||
nsPIDOMWindowInner::GetOrCreateServiceWorker(const mozilla::dom::ServiceWorkerDescriptor& aDescriptor)
|
||||
{
|
||||
return Move(nsGlobalWindowInner::Cast(this)->GetOrCreateServiceWorker(aDescriptor));
|
||||
}
|
||||
|
||||
void
|
||||
nsPIDOMWindowInner::NoteCalledRegisterForServiceWorkerScope(const nsACString& aScope)
|
||||
{
|
||||
|
@ -6371,6 +6378,39 @@ nsGlobalWindowInner::GetController() const
|
|||
return Move(controller);
|
||||
}
|
||||
|
||||
RefPtr<ServiceWorker>
|
||||
nsGlobalWindowInner::GetOrCreateServiceWorker(const ServiceWorkerDescriptor& aDescriptor)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
RefPtr<ServiceWorker> ref;
|
||||
for (auto sw : mServiceWorkerList) {
|
||||
if (sw->MatchesDescriptor(aDescriptor)) {
|
||||
ref = sw;
|
||||
return ref.forget();
|
||||
}
|
||||
}
|
||||
ref = ServiceWorker::Create(this, aDescriptor);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
void
|
||||
nsGlobalWindowInner::AddServiceWorker(ServiceWorker* aServiceWorker)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_DIAGNOSTIC_ASSERT(aServiceWorker);
|
||||
MOZ_ASSERT(!mServiceWorkerList.Contains(aServiceWorker));
|
||||
mServiceWorkerList.AppendElement(aServiceWorker);
|
||||
}
|
||||
|
||||
void
|
||||
nsGlobalWindowInner::RemoveServiceWorker(ServiceWorker* aServiceWorker)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_DIAGNOSTIC_ASSERT(aServiceWorker);
|
||||
MOZ_ASSERT(mServiceWorkerList.Contains(aServiceWorker));
|
||||
mServiceWorkerList.RemoveElement(aServiceWorker);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGlobalWindowInner::FireDelayedDOMEvents()
|
||||
{
|
||||
|
|
|
@ -351,6 +351,15 @@ public:
|
|||
mozilla::Maybe<mozilla::dom::ClientState> GetClientState() const;
|
||||
mozilla::Maybe<mozilla::dom::ServiceWorkerDescriptor> GetController() const override;
|
||||
|
||||
virtual RefPtr<mozilla::dom::ServiceWorker>
|
||||
GetOrCreateServiceWorker(const mozilla::dom::ServiceWorkerDescriptor& aDescriptor) override;
|
||||
|
||||
virtual void
|
||||
AddServiceWorker(mozilla::dom::ServiceWorker* aServiceWorker) override;
|
||||
|
||||
virtual void
|
||||
RemoveServiceWorker(mozilla::dom::ServiceWorker* aServiceWorker) override;
|
||||
|
||||
void NoteCalledRegisterForServiceWorkerScope(const nsACString& aScope);
|
||||
|
||||
virtual nsresult FireDelayedDOMEvents() override;
|
||||
|
@ -1442,6 +1451,10 @@ protected:
|
|||
|
||||
mozilla::UniquePtr<mozilla::dom::ClientSource> mClientSource;
|
||||
|
||||
// Weak references added by AddServiceWorker() and cleared by
|
||||
// RemoveServiceWorker() when the ServiceWorker is destroyed.
|
||||
nsTArray<mozilla::dom::ServiceWorker*> mServiceWorkerList;
|
||||
|
||||
nsTArray<RefPtr<mozilla::dom::Promise>> mPendingPromises;
|
||||
|
||||
static InnerWindowByIdTable* sInnerWindowsById;
|
||||
|
|
|
@ -5,12 +5,15 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsIGlobalObject.h"
|
||||
|
||||
#include "mozilla/dom/ServiceWorker.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsHostObjectProtocolHandler.h"
|
||||
|
||||
using mozilla::Maybe;
|
||||
using mozilla::dom::ClientInfo;
|
||||
using mozilla::dom::ServiceWorker;
|
||||
using mozilla::dom::ServiceWorkerDescriptor;
|
||||
|
||||
nsIGlobalObject::~nsIGlobalObject()
|
||||
|
@ -132,3 +135,22 @@ nsIGlobalObject::GetController() const
|
|||
// window and worker globals can currently be controlled as a client.
|
||||
return Maybe<ServiceWorkerDescriptor>();
|
||||
}
|
||||
|
||||
RefPtr<ServiceWorker>
|
||||
nsIGlobalObject::GetOrCreateServiceWorker(const ServiceWorkerDescriptor& aDescriptor)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(false, "this global should not have any service workers");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
nsIGlobalObject::AddServiceWorker(ServiceWorker* aServiceWorker)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(false, "this global should not have any service workers");
|
||||
}
|
||||
|
||||
void
|
||||
nsIGlobalObject::RemoveServiceWorker(ServiceWorker* aServiceWorker)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(false, "this global should not have any service workers");
|
||||
}
|
||||
|
|
|
@ -24,6 +24,12 @@
|
|||
class nsCycleCollectionTraversalCallback;
|
||||
class nsIPrincipal;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class ServiceWorker;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
class nsIGlobalObject : public nsISupports,
|
||||
public mozilla::dom::DispatcherTrait
|
||||
{
|
||||
|
@ -86,6 +92,21 @@ public:
|
|||
virtual mozilla::Maybe<mozilla::dom::ServiceWorkerDescriptor>
|
||||
GetController() const;
|
||||
|
||||
// Get the DOM object for the given descriptor or attempt to create one.
|
||||
// Creation can still fail and return nullptr during shutdown, etc.
|
||||
virtual RefPtr<mozilla::dom::ServiceWorker>
|
||||
GetOrCreateServiceWorker(const mozilla::dom::ServiceWorkerDescriptor& aDescriptor);
|
||||
|
||||
// These methods allow the ServiceWorker instances to note their existence
|
||||
// so that the global can use weak references to them. The global should
|
||||
// not hold a strong reference to the ServiceWorker.
|
||||
virtual void
|
||||
AddServiceWorker(mozilla::dom::ServiceWorker* aServiceWorker);
|
||||
|
||||
// This method must be called by the ServiceWorker before it is destroyed.
|
||||
virtual void
|
||||
RemoveServiceWorker(mozilla::dom::ServiceWorker* aServiceWorker);
|
||||
|
||||
protected:
|
||||
virtual ~nsIGlobalObject();
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ class TabGroup;
|
|||
class Element;
|
||||
class Navigator;
|
||||
class Performance;
|
||||
class ServiceWorker;
|
||||
class ServiceWorkerDescriptor;
|
||||
class ServiceWorkerRegistration;
|
||||
class Timeout;
|
||||
|
@ -334,6 +335,9 @@ public:
|
|||
mozilla::Maybe<mozilla::dom::ClientState> GetClientState() const;
|
||||
mozilla::Maybe<mozilla::dom::ServiceWorkerDescriptor> GetController() const;
|
||||
|
||||
RefPtr<mozilla::dom::ServiceWorker>
|
||||
GetOrCreateServiceWorker(const mozilla::dom::ServiceWorkerDescriptor& aDescriptor);
|
||||
|
||||
void NoteCalledRegisterForServiceWorkerScope(const nsACString& aScope);
|
||||
|
||||
mozilla::dom::TabGroup* TabGroup();
|
||||
|
|
|
@ -572,8 +572,9 @@ ClientSource::PostMessage(const ClientPostMessageArgs& aArgs)
|
|||
if (reg) {
|
||||
RefPtr<ServiceWorkerInfo> serviceWorker = reg->GetByID(source.Id());
|
||||
if (serviceWorker) {
|
||||
init.mSource.SetValue().SetAsServiceWorker() =
|
||||
serviceWorker->GetOrCreateInstance(GetInnerWindow());
|
||||
RefPtr<ServiceWorker> instance =
|
||||
globalObject->GetOrCreateServiceWorker(source);
|
||||
init.mSource.SetValue().SetAsServiceWorker() = instance;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ struct IPCServiceWorkerDescriptor
|
|||
uint64_t id;
|
||||
PrincipalInfo principalInfo;
|
||||
nsCString scope;
|
||||
nsCString scriptURL;
|
||||
ServiceWorkerState state;
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
include PBackgroundSharedTypes;
|
||||
include IPCServiceWorkerDescriptor;
|
||||
|
||||
using ServiceWorkerUpdateViaCache from "mozilla/dom/ServiceWorkerIPCUtils.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
// IPC type with enough information to create a ServiceWorker DOM object
|
||||
// in a child process. Note that the state may be slightly out-of-sync
|
||||
// with the parent and should be updated dynamically if necessary.
|
||||
struct IPCServiceWorkerRegistrationDescriptor
|
||||
{
|
||||
// These values should match the principal and scope in each
|
||||
// associated worker. It may be possible to optimize in the future,
|
||||
// but for now we duplicate the information here to ensure correctness.
|
||||
// Its possible we may need to reference a registration before the
|
||||
// worker is installed yet, etc.
|
||||
PrincipalInfo principalInfo;
|
||||
nsCString scope;
|
||||
|
||||
ServiceWorkerUpdateViaCache updateViaCache;
|
||||
|
||||
OptionalIPCServiceWorkerDescriptor installing;
|
||||
OptionalIPCServiceWorkerDescriptor waiting;
|
||||
OptionalIPCServiceWorkerDescriptor active;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -38,22 +38,58 @@ ServiceWorkerVisible(JSContext* aCx, JSObject* aObj)
|
|||
return IS_INSTANCE_OF(ServiceWorkerGlobalScope, aObj);
|
||||
}
|
||||
|
||||
ServiceWorker::ServiceWorker(nsPIDOMWindowInner* aWindow,
|
||||
ServiceWorkerInfo* aInfo)
|
||||
: DOMEventTargetHelper(aWindow),
|
||||
mInfo(aInfo)
|
||||
// static
|
||||
already_AddRefed<ServiceWorker>
|
||||
ServiceWorker::Create(nsIGlobalObject* aOwner,
|
||||
const ServiceWorkerDescriptor& aDescriptor)
|
||||
{
|
||||
RefPtr<ServiceWorker> ref;
|
||||
|
||||
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
if (!swm) {
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
RefPtr<ServiceWorkerRegistrationInfo> reg =
|
||||
swm->GetRegistration(aDescriptor.PrincipalInfo(), aDescriptor.Scope());
|
||||
if (!reg) {
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
RefPtr<ServiceWorkerInfo> info = reg->GetByID(aDescriptor.Id());
|
||||
if (!info) {
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
ref = new ServiceWorker(aOwner, aDescriptor, info);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
ServiceWorker::ServiceWorker(nsIGlobalObject* aGlobal,
|
||||
const ServiceWorkerDescriptor& aDescriptor,
|
||||
ServiceWorker::Inner* aInner)
|
||||
: DOMEventTargetHelper(aGlobal)
|
||||
, mDescriptor(aDescriptor)
|
||||
, mInner(aInner)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aInfo);
|
||||
MOZ_DIAGNOSTIC_ASSERT(aGlobal);
|
||||
MOZ_DIAGNOSTIC_ASSERT(mInner);
|
||||
|
||||
aGlobal->AddServiceWorker(this);
|
||||
|
||||
// This will update our state too.
|
||||
mInfo->AppendWorker(this);
|
||||
mInner->AddServiceWorker(this);
|
||||
}
|
||||
|
||||
ServiceWorker::~ServiceWorker()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mInfo->RemoveWorker(this);
|
||||
mInner->RemoveServiceWorker(this);
|
||||
nsIGlobalObject* global = GetParentObject();
|
||||
if (global) {
|
||||
global->RemoveServiceWorker(this);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(ServiceWorker, DOMEventTargetHelper)
|
||||
|
@ -70,10 +106,26 @@ ServiceWorker::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
|||
return ServiceWorkerBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
ServiceWorkerState
|
||||
ServiceWorker::State() const
|
||||
{
|
||||
return mDescriptor.State();
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorker::SetState(ServiceWorkerState aState)
|
||||
{
|
||||
ServiceWorkerState oldState = mDescriptor.State();
|
||||
mDescriptor.SetState(aState);
|
||||
if (oldState != aState) {
|
||||
DOMEventTargetHelper::DispatchTrustedEvent(NS_LITERAL_STRING("statechange"));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorker::GetScriptURL(nsString& aURL) const
|
||||
{
|
||||
CopyUTF8toUTF16(mInfo->ScriptSpec(), aURL);
|
||||
CopyUTF8toUTF16(mDescriptor.ScriptURL(), aURL);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -86,33 +138,28 @@ ServiceWorker::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
|||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(GetParentObject());
|
||||
if (!window || !window->GetExtantDoc()) {
|
||||
NS_WARNING("Trying to call post message from an invalid dom object.");
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
mInner->PostMessage(GetParentObject(), aCx, aMessage, aTransferable, aRv);
|
||||
}
|
||||
|
||||
auto storageAllowed = nsContentUtils::StorageAllowedForWindow(window);
|
||||
if (storageAllowed != nsContentUtils::StorageAccess::eAllow) {
|
||||
ServiceWorkerManager::LocalizeAndReportToAllClients(
|
||||
mInfo->Scope(), "ServiceWorkerPostMessageStorageError",
|
||||
nsTArray<nsString> { NS_ConvertUTF8toUTF16(mInfo->Scope()) });
|
||||
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return;
|
||||
}
|
||||
bool
|
||||
ServiceWorker::MatchesDescriptor(const ServiceWorkerDescriptor& aDescriptor) const
|
||||
{
|
||||
// Compare everything in the descriptor except the state. That is mutable
|
||||
// and may not exactly match.
|
||||
return mDescriptor.PrincipalInfo() == aDescriptor.PrincipalInfo() &&
|
||||
mDescriptor.Scope() == aDescriptor.Scope() &&
|
||||
mDescriptor.ScriptURL() == aDescriptor.ScriptURL() &&
|
||||
mDescriptor.Id() == aDescriptor.Id();
|
||||
}
|
||||
|
||||
Maybe<ClientInfo> clientInfo = window->GetClientInfo();
|
||||
Maybe<ClientState> clientState = window->GetClientState();
|
||||
if (clientInfo.isNothing() || clientState.isNothing()) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
void
|
||||
ServiceWorker::DisconnectFromOwner()
|
||||
{
|
||||
nsIGlobalObject* global = GetParentObject();
|
||||
if (global) {
|
||||
global->RemoveServiceWorker(this);
|
||||
}
|
||||
|
||||
ServiceWorkerPrivate* workerPrivate = mInfo->WorkerPrivate();
|
||||
aRv = workerPrivate->SendMessageEvent(aCx, aMessage, aTransferable,
|
||||
ClientInfoAndState(clientInfo.ref().ToIPC(),
|
||||
clientState.ref().ToIPC()));
|
||||
DOMEventTargetHelper::DisconnectFromOwner();
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -9,70 +9,96 @@
|
|||
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/dom/ServiceWorkerBinding.h" // For ServiceWorkerState.
|
||||
#include "mozilla/dom/ServiceWorkerDescriptor.h"
|
||||
|
||||
class nsPIDOMWindowInner;
|
||||
#ifdef XP_WIN
|
||||
#undef PostMessage
|
||||
#endif
|
||||
|
||||
class nsIGlobalObject;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class ServiceWorkerInfo;
|
||||
class ServiceWorkerManager;
|
||||
class SharedWorker;
|
||||
|
||||
bool
|
||||
ServiceWorkerVisible(JSContext* aCx, JSObject* aObj);
|
||||
|
||||
class ServiceWorker final : public DOMEventTargetHelper
|
||||
{
|
||||
friend class ServiceWorkerInfo;
|
||||
public:
|
||||
// Abstract interface for the internal representation of the
|
||||
// ServiceWorker object.
|
||||
class Inner
|
||||
{
|
||||
public:
|
||||
// This will be called when a DOM ServiceWorker object is
|
||||
// created and takes a strong ref to the Inner object.
|
||||
// RemoveServiceWorker() is guaranteed to be called on the
|
||||
// current thread before the ServiceWorker is destroyed.
|
||||
//
|
||||
// In addition, the Inner object should check to see if
|
||||
// the ServiceWorker's state is correct. If not, it should
|
||||
// be updated automatically by calling SetState(). This is
|
||||
// necessary to handle race conditions where the DOM
|
||||
// ServiceWorker object is created while the state is being
|
||||
// updated in another process.
|
||||
virtual void
|
||||
AddServiceWorker(ServiceWorker* aWorker) = 0;
|
||||
|
||||
// This is called when the DOM ServiceWorker object is
|
||||
// destroyed and drops its ref to the Inner object.
|
||||
virtual void
|
||||
RemoveServiceWorker(ServiceWorker* aWorker) = 0;
|
||||
|
||||
virtual void
|
||||
PostMessage(nsIGlobalObject* aGlobal,
|
||||
JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
ErrorResult& aRv) = 0;
|
||||
|
||||
NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
|
||||
};
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
IMPL_EVENT_HANDLER(statechange)
|
||||
IMPL_EVENT_HANDLER(error)
|
||||
|
||||
static already_AddRefed<ServiceWorker>
|
||||
Create(nsIGlobalObject* aOwner, const ServiceWorkerDescriptor& aDescriptor);
|
||||
|
||||
virtual JSObject*
|
||||
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
ServiceWorkerState
|
||||
State() const
|
||||
{
|
||||
return mState;
|
||||
}
|
||||
State() const;
|
||||
|
||||
void
|
||||
SetState(ServiceWorkerState aState)
|
||||
{
|
||||
mState = aState;
|
||||
}
|
||||
SetState(ServiceWorkerState aState);
|
||||
|
||||
void
|
||||
GetScriptURL(nsString& aURL) const;
|
||||
|
||||
void
|
||||
DispatchStateChange(ServiceWorkerState aState)
|
||||
{
|
||||
DOMEventTargetHelper::DispatchTrustedEvent(NS_LITERAL_STRING("statechange"));
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
#undef PostMessage
|
||||
#endif
|
||||
|
||||
void
|
||||
PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Sequence<JSObject*>& aTransferable, ErrorResult& aRv);
|
||||
|
||||
bool
|
||||
MatchesDescriptor(const ServiceWorkerDescriptor& aDescriptor) const;
|
||||
|
||||
void
|
||||
DisconnectFromOwner() override;
|
||||
|
||||
private:
|
||||
// This class can only be created from ServiceWorkerInfo::GetOrCreateInstance().
|
||||
ServiceWorker(nsPIDOMWindowInner* aWindow, ServiceWorkerInfo* aInfo);
|
||||
ServiceWorker(nsIGlobalObject* aWindow,
|
||||
const ServiceWorkerDescriptor& aDescriptor,
|
||||
Inner* aInner);
|
||||
|
||||
// This class is reference-counted and will be destroyed from Release().
|
||||
~ServiceWorker();
|
||||
|
||||
ServiceWorkerState mState;
|
||||
const RefPtr<ServiceWorkerInfo> mInfo;
|
||||
ServiceWorkerDescriptor mDescriptor;
|
||||
const RefPtr<Inner> mInner;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -251,7 +251,7 @@ ServiceWorkerContainer::GetController()
|
|||
// Right now we only know how to create ServiceWorker DOM objects on
|
||||
// the main thread with a window. In the future this should operate
|
||||
// on only nsIGlobalObject somehow.
|
||||
mControllerWorker = info->GetOrCreateInstance(inner);
|
||||
mControllerWorker = inner->GetOrCreateServiceWorker(info->Descriptor());
|
||||
}
|
||||
|
||||
RefPtr<ServiceWorker> ref = mControllerWorker;
|
||||
|
|
|
@ -15,6 +15,7 @@ namespace dom {
|
|||
ServiceWorkerDescriptor::ServiceWorkerDescriptor(uint64_t aId,
|
||||
nsIPrincipal* aPrincipal,
|
||||
const nsACString& aScope,
|
||||
const nsACString& aScriptURL,
|
||||
ServiceWorkerState aState)
|
||||
: mData(MakeUnique<IPCServiceWorkerDescriptor>())
|
||||
{
|
||||
|
@ -23,14 +24,17 @@ ServiceWorkerDescriptor::ServiceWorkerDescriptor(uint64_t aId,
|
|||
|
||||
mData->id() = aId;
|
||||
mData->scope() = aScope;
|
||||
mData->scriptURL() = aScriptURL;
|
||||
mData->state() = aState;
|
||||
}
|
||||
|
||||
ServiceWorkerDescriptor::ServiceWorkerDescriptor(uint64_t aId,
|
||||
const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
|
||||
const nsACString& aScope,
|
||||
const nsACString& aScriptURL,
|
||||
ServiceWorkerState aState)
|
||||
: mData(MakeUnique<IPCServiceWorkerDescriptor>(aId, aPrincipalInfo,
|
||||
nsCString(aScriptURL),
|
||||
nsCString(aScope), aState))
|
||||
{
|
||||
}
|
||||
|
@ -94,6 +98,12 @@ ServiceWorkerDescriptor::Scope() const
|
|||
return mData->scope();
|
||||
}
|
||||
|
||||
const nsCString&
|
||||
ServiceWorkerDescriptor::ScriptURL() const
|
||||
{
|
||||
return mData->scriptURL();
|
||||
}
|
||||
|
||||
ServiceWorkerState
|
||||
ServiceWorkerDescriptor::State() const
|
||||
{
|
||||
|
|
|
@ -25,7 +25,7 @@ enum class ServiceWorkerState : uint8_t;
|
|||
// accurate. Currently the only variable field is the ServiceWorkerState.
|
||||
class ServiceWorkerDescriptor final
|
||||
{
|
||||
// This class is largely a wrapper wround an IPDL generated struct. We
|
||||
// This class is largely a wrapper around an IPDL generated struct. We
|
||||
// need the wrapper class since IPDL generated code includes windows.h
|
||||
// which is in turn incompatible with bindings code.
|
||||
UniquePtr<IPCServiceWorkerDescriptor> mData;
|
||||
|
@ -34,11 +34,13 @@ public:
|
|||
ServiceWorkerDescriptor(uint64_t aId,
|
||||
nsIPrincipal* aPrincipal,
|
||||
const nsACString& aScope,
|
||||
const nsACString& aScriptURL,
|
||||
ServiceWorkerState aState);
|
||||
|
||||
ServiceWorkerDescriptor(uint64_t aId,
|
||||
const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
|
||||
const nsACString& aScope,
|
||||
const nsACString& aScriptURL,
|
||||
ServiceWorkerState aState);
|
||||
|
||||
explicit ServiceWorkerDescriptor(const IPCServiceWorkerDescriptor& aDescriptor);
|
||||
|
@ -67,6 +69,9 @@ public:
|
|||
const nsCString&
|
||||
Scope() const;
|
||||
|
||||
const nsCString&
|
||||
ScriptURL() const;
|
||||
|
||||
ServiceWorkerState
|
||||
State() const;
|
||||
|
||||
|
|
|
@ -7,7 +7,12 @@
|
|||
#define _mozilla_dom_ServiceWorkerIPCUtils_h
|
||||
|
||||
#include "ipc/IPCMessageUtils.h"
|
||||
|
||||
// Undo X11/X.h's definition of None
|
||||
#undef None
|
||||
|
||||
#include "mozilla/dom/ServiceWorkerBinding.h"
|
||||
#include "mozilla/dom/ServiceWorkerRegistrationBinding.h"
|
||||
|
||||
namespace IPC {
|
||||
|
||||
|
@ -18,6 +23,13 @@ namespace IPC {
|
|||
mozilla::dom::ServiceWorkerState::EndGuard_>
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<mozilla::dom::ServiceWorkerUpdateViaCache> :
|
||||
public ContiguousEnumSerializer<mozilla::dom::ServiceWorkerUpdateViaCache,
|
||||
mozilla::dom::ServiceWorkerUpdateViaCache::Imports,
|
||||
mozilla::dom::ServiceWorkerUpdateViaCache::EndGuard_>
|
||||
{};
|
||||
|
||||
} // namespace IPC
|
||||
|
||||
#endif // _mozilla_dom_ServiceWorkerIPCUtils_h
|
||||
|
|
|
@ -34,7 +34,7 @@ NS_IMETHODIMP
|
|||
ServiceWorkerInfo::GetScriptSpec(nsAString& aScriptSpec)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
CopyUTF8toUTF16(mScriptSpec, aScriptSpec);
|
||||
CopyUTF8toUTF16(mDescriptor.ScriptURL(), aScriptSpec);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -113,35 +113,6 @@ ServiceWorkerInfo::DetachDebugger()
|
|||
return mServiceWorkerPrivate->DetachDebugger();
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerInfo::AppendWorker(ServiceWorker* aWorker)
|
||||
{
|
||||
MOZ_ASSERT(aWorker);
|
||||
#ifdef DEBUG
|
||||
nsAutoString workerURL;
|
||||
aWorker->GetScriptURL(workerURL);
|
||||
MOZ_ASSERT(workerURL.Equals(NS_ConvertUTF8toUTF16(mScriptSpec)));
|
||||
#endif
|
||||
MOZ_ASSERT(!mInstances.Contains(aWorker));
|
||||
|
||||
mInstances.AppendElement(aWorker);
|
||||
aWorker->SetState(State());
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerInfo::RemoveWorker(ServiceWorker* aWorker)
|
||||
{
|
||||
MOZ_ASSERT(aWorker);
|
||||
#ifdef DEBUG
|
||||
nsAutoString workerURL;
|
||||
aWorker->GetScriptURL(workerURL);
|
||||
MOZ_ASSERT(workerURL.Equals(NS_ConvertUTF8toUTF16(mScriptSpec)));
|
||||
#endif
|
||||
MOZ_ASSERT(mInstances.Contains(aWorker));
|
||||
|
||||
mInstances.RemoveElement(aWorker);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class ChangeStateUpdater final : public Runnable
|
||||
|
@ -159,16 +130,9 @@ public:
|
|||
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
// We need to update the state of all instances atomically before notifying
|
||||
// them to make sure that the observed state for all instances inside
|
||||
// statechange event handlers is correct.
|
||||
for (size_t i = 0; i < mInstances.Length(); ++i) {
|
||||
mInstances[i]->SetState(mState);
|
||||
}
|
||||
for (size_t i = 0; i < mInstances.Length(); ++i) {
|
||||
mInstances[i]->DispatchStateChange(mState);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -221,8 +185,8 @@ ServiceWorkerInfo::ServiceWorkerInfo(nsIPrincipal* aPrincipal,
|
|||
const nsAString& aCacheName,
|
||||
nsLoadFlags aImportsLoadFlags)
|
||||
: mPrincipal(aPrincipal)
|
||||
, mDescriptor(GetNextID(), aPrincipal, aScope, ServiceWorkerState::Parsed)
|
||||
, mScriptSpec(aScriptSpec)
|
||||
, mDescriptor(GetNextID(), aPrincipal, aScope, aScriptSpec,
|
||||
ServiceWorkerState::Parsed)
|
||||
, mCacheName(aCacheName)
|
||||
, mImportsLoadFlags(aImportsLoadFlags)
|
||||
, mCreationTime(PR_Now())
|
||||
|
@ -237,7 +201,7 @@ ServiceWorkerInfo::ServiceWorkerInfo(nsIPrincipal* aPrincipal,
|
|||
MOZ_ASSERT(mPrincipal);
|
||||
// cache origin attributes so we can use them off main thread
|
||||
mOriginAttributes = mPrincipal->OriginAttributesRef();
|
||||
MOZ_ASSERT(!mScriptSpec.IsEmpty());
|
||||
MOZ_ASSERT(!mDescriptor.ScriptURL().IsEmpty());
|
||||
MOZ_ASSERT(!mCacheName.IsEmpty());
|
||||
|
||||
// Scripts of a service worker should always be loaded bypass service workers.
|
||||
|
@ -260,27 +224,70 @@ ServiceWorkerInfo::GetNextID() const
|
|||
return ++gServiceWorkerInfoCurrentID;
|
||||
}
|
||||
|
||||
already_AddRefed<ServiceWorker>
|
||||
ServiceWorkerInfo::GetOrCreateInstance(nsPIDOMWindowInner* aWindow)
|
||||
void
|
||||
ServiceWorkerInfo::AddServiceWorker(ServiceWorker* aWorker)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(aWorker);
|
||||
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
||||
nsAutoString workerURL;
|
||||
aWorker->GetScriptURL(workerURL);
|
||||
MOZ_DIAGNOSTIC_ASSERT(
|
||||
workerURL.Equals(NS_ConvertUTF8toUTF16(mDescriptor.ScriptURL())));
|
||||
#endif
|
||||
MOZ_ASSERT(!mInstances.Contains(aWorker));
|
||||
|
||||
mInstances.AppendElement(aWorker);
|
||||
aWorker->SetState(State());
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerInfo::RemoveServiceWorker(ServiceWorker* aWorker)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(aWorker);
|
||||
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
||||
nsAutoString workerURL;
|
||||
aWorker->GetScriptURL(workerURL);
|
||||
MOZ_DIAGNOSTIC_ASSERT(
|
||||
workerURL.Equals(NS_ConvertUTF8toUTF16(mDescriptor.ScriptURL())));
|
||||
#endif
|
||||
MOZ_ASSERT(mInstances.Contains(aWorker));
|
||||
|
||||
mInstances.RemoveElement(aWorker);
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerInfo::PostMessage(nsIGlobalObject* aGlobal,
|
||||
JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aWindow);
|
||||
|
||||
RefPtr<ServiceWorker> ref;
|
||||
|
||||
for (uint32_t i = 0; i < mInstances.Length(); ++i) {
|
||||
MOZ_ASSERT(mInstances[i]);
|
||||
if (mInstances[i]->GetOwner() == aWindow) {
|
||||
ref = mInstances[i];
|
||||
break;
|
||||
}
|
||||
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal);
|
||||
if (NS_WARN_IF(!window || !window->GetExtantDoc())) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ref) {
|
||||
ref = new ServiceWorker(aWindow, this);
|
||||
auto storageAllowed = nsContentUtils::StorageAllowedForWindow(window);
|
||||
if (storageAllowed != nsContentUtils::StorageAccess::eAllow) {
|
||||
ServiceWorkerManager::LocalizeAndReportToAllClients(
|
||||
Scope(), "ServiceWorkerPostMessageStorageError",
|
||||
nsTArray<nsString> { NS_ConvertUTF8toUTF16(Scope()) });
|
||||
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
return ref.forget();
|
||||
Maybe<ClientInfo> clientInfo = window->GetClientInfo();
|
||||
Maybe<ClientState> clientState = window->GetClientState();
|
||||
if (NS_WARN_IF(clientInfo.isNothing() || clientState.isNothing())) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
aRv = mServiceWorkerPrivate->SendMessageEvent(aCx, aMessage, aTransferable,
|
||||
ClientInfoAndState(clientInfo.ref().ToIPC(),
|
||||
clientState.ref().ToIPC()));
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -12,11 +12,11 @@
|
|||
#include "mozilla/dom/WorkerCommon.h"
|
||||
#include "mozilla/OriginAttributes.h"
|
||||
#include "nsIServiceWorkerManager.h"
|
||||
#include "ServiceWorker.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class ServiceWorker;
|
||||
class ServiceWorkerPrivate;
|
||||
|
||||
/*
|
||||
|
@ -26,11 +26,11 @@ class ServiceWorkerPrivate;
|
|||
* by this class and spawn a ServiceWorker in the right global when required.
|
||||
*/
|
||||
class ServiceWorkerInfo final : public nsIServiceWorkerInfo
|
||||
, public ServiceWorker::Inner
|
||||
{
|
||||
private:
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
ServiceWorkerDescriptor mDescriptor;
|
||||
const nsCString mScriptSpec;
|
||||
const nsString mCacheName;
|
||||
OriginAttributes mOriginAttributes;
|
||||
|
||||
|
@ -76,6 +76,19 @@ private:
|
|||
uint64_t
|
||||
GetNextID() const;
|
||||
|
||||
// ServiceWorker::Inner implementation
|
||||
virtual void
|
||||
AddServiceWorker(ServiceWorker* aWorker) override;
|
||||
|
||||
virtual void
|
||||
RemoveServiceWorker(ServiceWorker* aWorker) override;
|
||||
|
||||
virtual void
|
||||
PostMessage(nsIGlobalObject* aGlobal,
|
||||
JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Sequence<JSObject*>& aTransferable,
|
||||
ErrorResult& aRv) override;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISERVICEWORKERINFO
|
||||
|
@ -96,7 +109,7 @@ public:
|
|||
const nsCString&
|
||||
ScriptSpec() const
|
||||
{
|
||||
return mScriptSpec;
|
||||
return mDescriptor.ScriptURL();
|
||||
}
|
||||
|
||||
const nsCString&
|
||||
|
@ -186,15 +199,6 @@ public:
|
|||
return mHandlesFetch != Disabled;
|
||||
}
|
||||
|
||||
void
|
||||
AppendWorker(ServiceWorker* aWorker);
|
||||
|
||||
void
|
||||
RemoveWorker(ServiceWorker* aWorker);
|
||||
|
||||
already_AddRefed<ServiceWorker>
|
||||
GetOrCreateInstance(nsPIDOMWindowInner* aWindow);
|
||||
|
||||
void
|
||||
UpdateInstalledTime();
|
||||
|
||||
|
|
|
@ -192,7 +192,7 @@ PopulateRegistrationData(nsIPrincipal* aPrincipal,
|
|||
return rv;
|
||||
}
|
||||
|
||||
aData.scope() = aRegistration->mScope;
|
||||
aData.scope() = aRegistration->Scope();
|
||||
|
||||
RefPtr<ServiceWorkerInfo> newest = aRegistration->Newest();
|
||||
if (NS_WARN_IF(!newest)) {
|
||||
|
@ -465,7 +465,7 @@ class ServiceWorkerResolveWindowPromiseOnRegisterCallback final : public Service
|
|||
RefPtr<ServiceWorkerRegistrationInfo> reg = registerJob->GetRegistration();
|
||||
|
||||
RefPtr<ServiceWorkerRegistration> swr =
|
||||
window->GetServiceWorkerRegistration(NS_ConvertUTF8toUTF16(reg->mScope));
|
||||
window->GetServiceWorkerRegistration(NS_ConvertUTF8toUTF16(reg->Scope()));
|
||||
promise->MaybeResolve(swr);
|
||||
}
|
||||
|
||||
|
@ -1003,7 +1003,7 @@ public:
|
|||
for (uint32_t i = 0; i < data->mOrderedScopes.Length(); ++i) {
|
||||
RefPtr<ServiceWorkerRegistrationInfo> info =
|
||||
data->mInfos.GetWeak(data->mOrderedScopes[i]);
|
||||
if (info->mPendingUninstall) {
|
||||
if (info->IsPendingUninstall()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1146,7 +1146,7 @@ public:
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_ConvertUTF8toUTF16 scope(registration->mScope);
|
||||
NS_ConvertUTF8toUTF16 scope(registration->Scope());
|
||||
RefPtr<ServiceWorkerRegistration> swr =
|
||||
mWindow->GetServiceWorkerRegistration(scope);
|
||||
mPromise->MaybeResolve(swr);
|
||||
|
@ -1463,7 +1463,7 @@ ServiceWorkerManager::CheckReadyPromise(nsPIDOMWindowInner* aWindow,
|
|||
GetServiceWorkerRegistrationInfo(principal, aURI);
|
||||
|
||||
if (registration && registration->GetActive()) {
|
||||
NS_ConvertUTF8toUTF16 scope(registration->mScope);
|
||||
NS_ConvertUTF8toUTF16 scope(registration->Scope());
|
||||
RefPtr<ServiceWorkerRegistration> swr =
|
||||
aWindow->GetServiceWorkerRegistration(scope);
|
||||
aPromise->MaybeResolve(swr);
|
||||
|
@ -1651,7 +1651,7 @@ ServiceWorkerManager::WorkerIsIdle(ServiceWorkerInfo* aWorker)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!reg->IsControllingClients() && reg->mPendingUninstall) {
|
||||
if (!reg->IsControllingClients() && reg->IsPendingUninstall()) {
|
||||
RemoveRegistration(reg);
|
||||
return;
|
||||
}
|
||||
|
@ -1840,8 +1840,8 @@ ServiceWorkerManager::LoadRegistration(
|
|||
const nsCString& currentWorkerURL = aRegistration.currentWorkerURL();
|
||||
if (!currentWorkerURL.IsEmpty()) {
|
||||
registration->SetActive(
|
||||
new ServiceWorkerInfo(registration->mPrincipal,
|
||||
registration->mScope,
|
||||
new ServiceWorkerInfo(registration->Principal(),
|
||||
registration->Scope(),
|
||||
currentWorkerURL,
|
||||
aRegistration.cacheName(),
|
||||
importsLoadFlags));
|
||||
|
@ -1962,12 +1962,12 @@ ServiceWorkerManager::GetServiceWorkerRegistrationInfo(const nsACString& aScopeK
|
|||
|
||||
#ifdef DEBUG
|
||||
nsAutoCString origin;
|
||||
rv = registration->mPrincipal->GetOrigin(origin);
|
||||
rv = registration->Principal()->GetOrigin(origin);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
MOZ_ASSERT(origin.Equals(aScopeKey));
|
||||
#endif
|
||||
|
||||
if (registration->mPendingUninstall) {
|
||||
if (registration->IsPendingUninstall()) {
|
||||
return nullptr;
|
||||
}
|
||||
return registration.forget();
|
||||
|
@ -2015,7 +2015,7 @@ ServiceWorkerManager::AddScopeAndRegistration(const nsACString& aScope,
|
|||
ServiceWorkerRegistrationInfo* aInfo)
|
||||
{
|
||||
MOZ_ASSERT(aInfo);
|
||||
MOZ_ASSERT(aInfo->mPrincipal);
|
||||
MOZ_ASSERT(aInfo->Principal());
|
||||
|
||||
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
if (!swm) {
|
||||
|
@ -2024,7 +2024,7 @@ ServiceWorkerManager::AddScopeAndRegistration(const nsACString& aScope,
|
|||
}
|
||||
|
||||
nsAutoCString scopeKey;
|
||||
nsresult rv = swm->PrincipalToScopeKey(aInfo->mPrincipal, scopeKey);
|
||||
nsresult rv = swm->PrincipalToScopeKey(aInfo->Principal(), scopeKey);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
|
@ -2118,7 +2118,7 @@ ServiceWorkerManager::RemoveScopeAndRegistration(ServiceWorkerRegistrationInfo*
|
|||
}
|
||||
|
||||
nsAutoCString scopeKey;
|
||||
nsresult rv = swm->PrincipalToScopeKey(aRegistration->mPrincipal, scopeKey);
|
||||
nsresult rv = swm->PrincipalToScopeKey(aRegistration->Principal(), scopeKey);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
|
@ -2128,7 +2128,7 @@ ServiceWorkerManager::RemoveScopeAndRegistration(ServiceWorkerRegistrationInfo*
|
|||
return;
|
||||
}
|
||||
|
||||
if (auto entry = data->mUpdateTimers.Lookup(aRegistration->mScope)) {
|
||||
if (auto entry = data->mUpdateTimers.Lookup(aRegistration->Scope())) {
|
||||
entry.Data()->Cancel();
|
||||
entry.Remove();
|
||||
}
|
||||
|
@ -2136,8 +2136,8 @@ ServiceWorkerManager::RemoveScopeAndRegistration(ServiceWorkerRegistrationInfo*
|
|||
// Verify there are no controlled clients for the purged registration.
|
||||
for (auto iter = swm->mControlledClients.Iter(); !iter.Done(); iter.Next()) {
|
||||
auto& reg = iter.UserData()->mRegistrationInfo;
|
||||
if (reg->mScope.Equals(aRegistration->mScope) &&
|
||||
reg->mPrincipal->Equals(aRegistration->mPrincipal)) {
|
||||
if (reg->Scope().Equals(aRegistration->Scope()) &&
|
||||
reg->Principal()->Equals(aRegistration->Principal())) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(false,
|
||||
"controlled client when removing registration");
|
||||
iter.Remove();
|
||||
|
@ -2146,8 +2146,8 @@ ServiceWorkerManager::RemoveScopeAndRegistration(ServiceWorkerRegistrationInfo*
|
|||
}
|
||||
|
||||
RefPtr<ServiceWorkerRegistrationInfo> info;
|
||||
data->mInfos.Remove(aRegistration->mScope, getter_AddRefs(info));
|
||||
data->mOrderedScopes.RemoveElement(aRegistration->mScope);
|
||||
data->mInfos.Remove(aRegistration->Scope(), getter_AddRefs(info));
|
||||
data->mOrderedScopes.RemoveElement(aRegistration->Scope());
|
||||
swm->NotifyListenersOnUnregister(info);
|
||||
|
||||
swm->MaybeRemoveRegistrationInfo(scopeKey);
|
||||
|
@ -2216,7 +2216,7 @@ ServiceWorkerManager::StopControllingRegistration(ServiceWorkerRegistrationInfo*
|
|||
return;
|
||||
}
|
||||
|
||||
if (aRegistration->mPendingUninstall) {
|
||||
if (aRegistration->IsPendingUninstall()) {
|
||||
RemoveRegistration(aRegistration);
|
||||
return;
|
||||
}
|
||||
|
@ -2246,7 +2246,7 @@ ServiceWorkerManager::GetScopeForUrl(nsIPrincipal* aPrincipal,
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
aScope = NS_ConvertUTF8toUTF16(r->mScope);
|
||||
aScope = NS_ConvertUTF8toUTF16(r->Scope());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2302,7 +2302,7 @@ ServiceWorkerManager::FireUpdateFoundOnServiceWorkerRegistrations(
|
|||
MOZ_ASSERT(!regScope.IsEmpty());
|
||||
|
||||
NS_ConvertUTF16toUTF8 utf8Scope(regScope);
|
||||
if (utf8Scope.Equals(aRegistration->mScope)) {
|
||||
if (utf8Scope.Equals(aRegistration->Scope())) {
|
||||
target->UpdateFound();
|
||||
}
|
||||
}
|
||||
|
@ -2366,7 +2366,8 @@ ServiceWorkerManager::GetServiceWorkerForScope(nsPIDOMWindowInner* aWindow,
|
|||
return NS_ERROR_DOM_NOT_FOUND_ERR;
|
||||
}
|
||||
|
||||
RefPtr<ServiceWorker> serviceWorker = info->GetOrCreateInstance(aWindow);
|
||||
RefPtr<ServiceWorker> serviceWorker =
|
||||
aWindow->GetOrCreateServiceWorker(info->Descriptor());
|
||||
|
||||
serviceWorker->SetState(info->State());
|
||||
serviceWorker.forget(aServiceWorker);
|
||||
|
@ -2669,7 +2670,7 @@ ServiceWorkerManager::TransitionServiceWorkerRegistrationWorker(ServiceWorkerReg
|
|||
|
||||
NS_ConvertUTF16toUTF8 utf8Scope(regScope);
|
||||
|
||||
if (utf8Scope.Equals(aRegistration->mScope)) {
|
||||
if (utf8Scope.Equals(aRegistration->Scope())) {
|
||||
target->TransitionWorker(aWhichOne);
|
||||
}
|
||||
}
|
||||
|
@ -2689,7 +2690,7 @@ ServiceWorkerManager::InvalidateServiceWorkerRegistrationWorker(ServiceWorkerReg
|
|||
|
||||
NS_ConvertUTF16toUTF8 utf8Scope(regScope);
|
||||
|
||||
if (utf8Scope.Equals(aRegistration->mScope)) {
|
||||
if (utf8Scope.Equals(aRegistration->Scope())) {
|
||||
target->InvalidateWorkers(aWhichOnes);
|
||||
}
|
||||
}
|
||||
|
@ -2708,7 +2709,7 @@ ServiceWorkerManager::NotifyServiceWorkerRegistrationRemoved(ServiceWorkerRegist
|
|||
|
||||
NS_ConvertUTF16toUTF8 utf8Scope(regScope);
|
||||
|
||||
if (utf8Scope.Equals(aRegistration->mScope)) {
|
||||
if (utf8Scope.Equals(aRegistration->Scope())) {
|
||||
target->RegistrationRemoved();
|
||||
}
|
||||
}
|
||||
|
@ -2816,7 +2817,7 @@ ServiceWorkerManager::SoftUpdateInternal(const OriginAttributes& aOriginAttribut
|
|||
}
|
||||
|
||||
// "If registration's uninstalling flag is set, abort these steps."
|
||||
if (registration->mPendingUninstall) {
|
||||
if (registration->IsPendingUninstall()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2841,7 +2842,7 @@ ServiceWorkerManager::SoftUpdateInternal(const OriginAttributes& aOriginAttribut
|
|||
aScope);
|
||||
|
||||
RefPtr<ServiceWorkerUpdateJob> job =
|
||||
new ServiceWorkerUpdateJob(principal, registration->mScope,
|
||||
new ServiceWorkerUpdateJob(principal, registration->Scope(),
|
||||
newest->ScriptSpec(), nullptr,
|
||||
registration->GetUpdateViaCache());
|
||||
|
||||
|
@ -2916,7 +2917,7 @@ ServiceWorkerManager::UpdateInternal(nsIPrincipal* aPrincipal,
|
|||
// "Invoke Update algorithm, or its equivalent, with client, registration as
|
||||
// its argument."
|
||||
RefPtr<ServiceWorkerUpdateJob> job =
|
||||
new ServiceWorkerUpdateJob(aPrincipal, registration->mScope,
|
||||
new ServiceWorkerUpdateJob(aPrincipal, registration->Scope(),
|
||||
newest->ScriptSpec(), nullptr,
|
||||
registration->GetUpdateViaCache());
|
||||
|
||||
|
@ -2936,7 +2937,7 @@ ServiceWorkerManager::MaybeClaimClient(nsIDocument* aDocument,
|
|||
RefPtr<GenericPromise> ref;
|
||||
|
||||
// Same origin check
|
||||
if (!aWorkerRegistration->mPrincipal->Equals(aDocument->NodePrincipal())) {
|
||||
if (!aWorkerRegistration->Principal()->Equals(aDocument->NodePrincipal())) {
|
||||
ref = GenericPromise::CreateAndReject(NS_ERROR_DOM_SECURITY_ERR, __func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
@ -3144,7 +3145,7 @@ ServiceWorkerManager::MaybeRemoveRegistration(ServiceWorkerRegistrationInfo* aRe
|
|||
{
|
||||
MOZ_ASSERT(aRegistration);
|
||||
RefPtr<ServiceWorkerInfo> newest = aRegistration->Newest();
|
||||
if (!newest && HasScope(aRegistration->mPrincipal, aRegistration->mScope)) {
|
||||
if (!newest && HasScope(aRegistration->Principal(), aRegistration->Scope())) {
|
||||
RemoveRegistration(aRegistration);
|
||||
}
|
||||
}
|
||||
|
@ -3165,10 +3166,10 @@ ServiceWorkerManager::RemoveRegistration(ServiceWorkerRegistrationInfo* aRegistr
|
|||
// null workers (case 3).
|
||||
#ifdef DEBUG
|
||||
RefPtr<ServiceWorkerInfo> newest = aRegistration->Newest();
|
||||
MOZ_ASSERT(aRegistration->mPendingUninstall || !newest);
|
||||
MOZ_ASSERT(aRegistration->IsPendingUninstall() || !newest);
|
||||
#endif
|
||||
|
||||
MOZ_ASSERT(HasScope(aRegistration->mPrincipal, aRegistration->mScope));
|
||||
MOZ_ASSERT(HasScope(aRegistration->Principal(), aRegistration->Scope()));
|
||||
|
||||
// When a registration is removed, we must clear its contents since the DOM
|
||||
// object may be held by content script.
|
||||
|
@ -3236,7 +3237,7 @@ ServiceWorkerManager::GetAllRegistrations(nsIArray** aResult)
|
|||
ServiceWorkerRegistrationInfo* reg = it2.UserData();
|
||||
MOZ_ASSERT(reg);
|
||||
|
||||
if (reg->mPendingUninstall) {
|
||||
if (reg->IsPendingUninstall()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -3257,18 +3258,18 @@ ServiceWorkerManager::ForceUnregister(RegistrationDataPerPrincipal* aRegistratio
|
|||
MOZ_ASSERT(aRegistration);
|
||||
|
||||
RefPtr<ServiceWorkerJobQueue> queue;
|
||||
aRegistrationData->mJobQueues.Get(aRegistration->mScope, getter_AddRefs(queue));
|
||||
aRegistrationData->mJobQueues.Get(aRegistration->Scope(), getter_AddRefs(queue));
|
||||
if (queue) {
|
||||
queue->CancelAll();
|
||||
}
|
||||
|
||||
if (auto entry = aRegistrationData->mUpdateTimers.Lookup(aRegistration->mScope)) {
|
||||
if (auto entry = aRegistrationData->mUpdateTimers.Lookup(aRegistration->Scope())) {
|
||||
entry.Data()->Cancel();
|
||||
entry.Remove();
|
||||
}
|
||||
|
||||
// Since Unregister is async, it is ok to call it in an enumeration.
|
||||
Unregister(aRegistration->mPrincipal, nullptr, NS_ConvertUTF8toUTF16(aRegistration->mScope));
|
||||
Unregister(aRegistration->Principal(), nullptr, NS_ConvertUTF8toUTF16(aRegistration->Scope()));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -3345,10 +3346,10 @@ ServiceWorkerManager::RemoveAllRegistrations(OriginAttributesPattern* aPattern)
|
|||
ServiceWorkerRegistrationInfo* reg = it2.UserData();
|
||||
|
||||
MOZ_ASSERT(reg);
|
||||
MOZ_ASSERT(reg->mPrincipal);
|
||||
MOZ_ASSERT(reg->Principal());
|
||||
|
||||
bool matches =
|
||||
aPattern->Matches(reg->mPrincipal->OriginAttributesRef());
|
||||
aPattern->Matches(reg->Principal()->OriginAttributesRef());
|
||||
if (!matches) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -1854,10 +1854,7 @@ ServiceWorkerPrivate::SpawnWorkerIfNeeded(WakeUpReason aWhy,
|
|||
rv = PrincipalToPrincipalInfo(mInfo->Principal(), &principalInfo);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
info.mServiceWorkerDescriptor.emplace(ServiceWorkerDescriptor(mInfo->ID(),
|
||||
principalInfo,
|
||||
mInfo->Scope(),
|
||||
mInfo->State()));
|
||||
info.mServiceWorkerDescriptor.emplace(mInfo->Descriptor());
|
||||
|
||||
info.mLoadGroup = aLoadGroup;
|
||||
info.mLoadFailedAsyncRunnable = aLoadFailedRunnable;
|
||||
|
|
|
@ -44,8 +44,8 @@ ServiceWorkerRegisterJob::AsyncExecute()
|
|||
// it to disk again. We preemptively removed it earlier during
|
||||
// unregister so that closing the window by shutting down the browser
|
||||
// results in the registration being gone on restart.
|
||||
if (registration->mPendingUninstall) {
|
||||
registration->mPendingUninstall = false;
|
||||
if (registration->IsPendingUninstall()) {
|
||||
registration->ClearPendingUninstall();
|
||||
swm->StoreRegistration(mPrincipal, registration);
|
||||
// Its possible that a ready promise is created between when the
|
||||
// uninstalling flag is set and when we resurrect the registration
|
||||
|
|
|
@ -0,0 +1,269 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/ServiceWorkerRegistrationDescriptor.h"
|
||||
#include "mozilla/ipc/PBackgroundSharedTypes.h"
|
||||
#include "ServiceWorkerInfo.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
Maybe<IPCServiceWorkerDescriptor>
|
||||
ServiceWorkerRegistrationDescriptor::NewestInternal() const
|
||||
{
|
||||
Maybe<IPCServiceWorkerDescriptor> result;
|
||||
if (mData->installing().type() != OptionalIPCServiceWorkerDescriptor::Tvoid_t) {
|
||||
result.emplace(mData->installing().get_IPCServiceWorkerDescriptor());
|
||||
} else if (mData->waiting().type() != OptionalIPCServiceWorkerDescriptor::Tvoid_t) {
|
||||
result.emplace(mData->waiting().get_IPCServiceWorkerDescriptor());
|
||||
} else if (mData->active().type() != OptionalIPCServiceWorkerDescriptor::Tvoid_t) {
|
||||
result.emplace(mData->active().get_IPCServiceWorkerDescriptor());
|
||||
}
|
||||
return Move(result);
|
||||
}
|
||||
|
||||
ServiceWorkerRegistrationDescriptor::ServiceWorkerRegistrationDescriptor(
|
||||
nsIPrincipal* aPrincipal,
|
||||
const nsACString& aScope,
|
||||
ServiceWorkerUpdateViaCache aUpdateViaCache)
|
||||
: mData(MakeUnique<IPCServiceWorkerRegistrationDescriptor>())
|
||||
{
|
||||
MOZ_ALWAYS_SUCCEEDS(
|
||||
PrincipalToPrincipalInfo(aPrincipal, &mData->principalInfo()));
|
||||
|
||||
mData->scope() = aScope;
|
||||
mData->updateViaCache() = aUpdateViaCache;
|
||||
mData->installing() = void_t();
|
||||
mData->waiting() = void_t();
|
||||
mData->active() = void_t();
|
||||
}
|
||||
|
||||
ServiceWorkerRegistrationDescriptor::ServiceWorkerRegistrationDescriptor(
|
||||
const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
|
||||
const nsACString& aScope,
|
||||
ServiceWorkerUpdateViaCache aUpdateViaCache)
|
||||
: mData(MakeUnique<IPCServiceWorkerRegistrationDescriptor>(aPrincipalInfo,
|
||||
nsCString(aScope),
|
||||
aUpdateViaCache,
|
||||
void_t(),
|
||||
void_t(),
|
||||
void_t()))
|
||||
{
|
||||
}
|
||||
|
||||
ServiceWorkerRegistrationDescriptor::ServiceWorkerRegistrationDescriptor(const IPCServiceWorkerRegistrationDescriptor& aDescriptor)
|
||||
: mData(MakeUnique<IPCServiceWorkerRegistrationDescriptor>(aDescriptor))
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(IsValid());
|
||||
}
|
||||
|
||||
ServiceWorkerRegistrationDescriptor::ServiceWorkerRegistrationDescriptor(const ServiceWorkerRegistrationDescriptor& aRight)
|
||||
{
|
||||
// UniquePtr doesn't have a default copy constructor, so we can't rely
|
||||
// on default copy construction. Use the assignment operator to
|
||||
// minimize duplication.
|
||||
operator=(aRight);
|
||||
}
|
||||
|
||||
ServiceWorkerRegistrationDescriptor&
|
||||
ServiceWorkerRegistrationDescriptor::operator=(const ServiceWorkerRegistrationDescriptor& aRight)
|
||||
{
|
||||
mData.reset();
|
||||
mData = MakeUnique<IPCServiceWorkerRegistrationDescriptor>(*aRight.mData);
|
||||
MOZ_DIAGNOSTIC_ASSERT(IsValid());
|
||||
return *this;
|
||||
}
|
||||
|
||||
ServiceWorkerRegistrationDescriptor::ServiceWorkerRegistrationDescriptor(ServiceWorkerRegistrationDescriptor&& aRight)
|
||||
: mData(Move(aRight.mData))
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(IsValid());
|
||||
}
|
||||
|
||||
ServiceWorkerRegistrationDescriptor&
|
||||
ServiceWorkerRegistrationDescriptor::operator=(ServiceWorkerRegistrationDescriptor&& aRight)
|
||||
{
|
||||
mData.reset();
|
||||
mData = Move(aRight.mData);
|
||||
MOZ_DIAGNOSTIC_ASSERT(IsValid());
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
ServiceWorkerRegistrationDescriptor::operator==(const ServiceWorkerRegistrationDescriptor& aRight) const
|
||||
{
|
||||
return *mData == *aRight.mData;
|
||||
}
|
||||
|
||||
ServiceWorkerUpdateViaCache
|
||||
ServiceWorkerRegistrationDescriptor::UpdateViaCache() const
|
||||
{
|
||||
return mData->updateViaCache();
|
||||
}
|
||||
|
||||
const mozilla::ipc::PrincipalInfo&
|
||||
ServiceWorkerRegistrationDescriptor::PrincipalInfo() const
|
||||
{
|
||||
return mData->principalInfo();
|
||||
}
|
||||
|
||||
const nsCString&
|
||||
ServiceWorkerRegistrationDescriptor::Scope() const
|
||||
{
|
||||
return mData->scope();
|
||||
}
|
||||
|
||||
Maybe<ServiceWorkerDescriptor>
|
||||
ServiceWorkerRegistrationDescriptor::GetInstalling() const
|
||||
{
|
||||
Maybe<ServiceWorkerDescriptor> result;
|
||||
|
||||
if (mData->installing().type() != OptionalIPCServiceWorkerDescriptor::Tvoid_t) {
|
||||
result.emplace(ServiceWorkerDescriptor(
|
||||
mData->installing().get_IPCServiceWorkerDescriptor()));
|
||||
}
|
||||
|
||||
return Move(result);
|
||||
}
|
||||
|
||||
Maybe<ServiceWorkerDescriptor>
|
||||
ServiceWorkerRegistrationDescriptor::GetWaiting() const
|
||||
{
|
||||
Maybe<ServiceWorkerDescriptor> result;
|
||||
|
||||
if (mData->waiting().type() != OptionalIPCServiceWorkerDescriptor::Tvoid_t) {
|
||||
result.emplace(ServiceWorkerDescriptor(
|
||||
mData->waiting().get_IPCServiceWorkerDescriptor()));
|
||||
}
|
||||
|
||||
return Move(result);
|
||||
}
|
||||
|
||||
Maybe<ServiceWorkerDescriptor>
|
||||
ServiceWorkerRegistrationDescriptor::GetActive() const
|
||||
{
|
||||
Maybe<ServiceWorkerDescriptor> result;
|
||||
|
||||
if (mData->active().type() != OptionalIPCServiceWorkerDescriptor::Tvoid_t) {
|
||||
result.emplace(ServiceWorkerDescriptor(
|
||||
mData->active().get_IPCServiceWorkerDescriptor()));
|
||||
}
|
||||
|
||||
return Move(result);
|
||||
}
|
||||
|
||||
Maybe<ServiceWorkerDescriptor>
|
||||
ServiceWorkerRegistrationDescriptor::Newest() const
|
||||
{
|
||||
Maybe<ServiceWorkerDescriptor> result;
|
||||
Maybe<IPCServiceWorkerDescriptor> newest(NewestInternal());
|
||||
if (newest.isSome()) {
|
||||
result.emplace(ServiceWorkerDescriptor(newest.ref()));
|
||||
}
|
||||
return Move(result);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
bool
|
||||
IsValidWorker(const OptionalIPCServiceWorkerDescriptor& aWorker,
|
||||
const nsACString& aScope,
|
||||
const mozilla::ipc::ContentPrincipalInfo& aContentPrincipal)
|
||||
{
|
||||
if (aWorker.type() == OptionalIPCServiceWorkerDescriptor::Tvoid_t) {
|
||||
return true;
|
||||
}
|
||||
|
||||
auto& worker = aWorker.get_IPCServiceWorkerDescriptor();
|
||||
if (worker.scope() != aScope) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto& principalInfo = worker.principalInfo();
|
||||
if (principalInfo.type() != mozilla::ipc::PrincipalInfo::TContentPrincipalInfo) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto& contentPrincipal = principalInfo.get_ContentPrincipalInfo();
|
||||
if (contentPrincipal.originNoSuffix() != aContentPrincipal.originNoSuffix() ||
|
||||
contentPrincipal.attrs() != aContentPrincipal.attrs()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
bool
|
||||
ServiceWorkerRegistrationDescriptor::IsValid() const
|
||||
{
|
||||
auto& principalInfo = PrincipalInfo();
|
||||
if (principalInfo.type() != mozilla::ipc::PrincipalInfo::TContentPrincipalInfo) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto& contentPrincipal = principalInfo.get_ContentPrincipalInfo();
|
||||
if (!IsValidWorker(mData->installing(), Scope(), contentPrincipal) ||
|
||||
!IsValidWorker(mData->waiting(), Scope(), contentPrincipal) ||
|
||||
!IsValidWorker(mData->active(), Scope(), contentPrincipal)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerRegistrationDescriptor::SetUpdateViaCache(ServiceWorkerUpdateViaCache aUpdateViaCache)
|
||||
{
|
||||
mData->updateViaCache() = aUpdateViaCache;
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerRegistrationDescriptor::SetWorkers(ServiceWorkerInfo* aInstalling,
|
||||
ServiceWorkerInfo* aWaiting,
|
||||
ServiceWorkerInfo* aActive)
|
||||
{
|
||||
if (aInstalling) {
|
||||
mData->installing() = aInstalling->Descriptor().ToIPC();
|
||||
} else {
|
||||
mData->installing() = void_t();
|
||||
}
|
||||
|
||||
if (aWaiting) {
|
||||
mData->waiting() = aWaiting->Descriptor().ToIPC();
|
||||
} else {
|
||||
mData->waiting() = void_t();
|
||||
}
|
||||
|
||||
if (aActive) {
|
||||
mData->active() = aActive->Descriptor().ToIPC();
|
||||
} else {
|
||||
mData->active() = void_t();
|
||||
}
|
||||
|
||||
MOZ_DIAGNOSTIC_ASSERT(IsValid());
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerRegistrationDescriptor::SetWorkers(OptionalIPCServiceWorkerDescriptor& aInstalling,
|
||||
OptionalIPCServiceWorkerDescriptor& aWaiting,
|
||||
OptionalIPCServiceWorkerDescriptor& aActive)
|
||||
{
|
||||
mData->installing() = aInstalling;
|
||||
mData->waiting() = aWaiting;
|
||||
mData->active() = aActive;
|
||||
MOZ_DIAGNOSTIC_ASSERT(IsValid());
|
||||
}
|
||||
|
||||
const IPCServiceWorkerRegistrationDescriptor&
|
||||
ServiceWorkerRegistrationDescriptor::ToIPC() const
|
||||
{
|
||||
return *mData;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,110 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#ifndef _mozilla_dom_ServiceWorkerRegistrationDescriptor_h
|
||||
#define _mozilla_dom_ServiceWorkerRegistrationDescriptor_h
|
||||
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/dom/IPCServiceWorkerRegistrationDescriptor.h"
|
||||
#include "mozilla/dom/ServiceWorkerDescriptor.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace ipc {
|
||||
class PrincipalInfo;
|
||||
} // namespace ipc
|
||||
|
||||
namespace dom {
|
||||
|
||||
class IPCServiceWorkerRegistrationDescriptor;
|
||||
class ServiceWorkerInfo;
|
||||
enum class ServiceWorkerUpdateViaCache : uint8_t;
|
||||
|
||||
// This class represents a snapshot of a particular
|
||||
// ServiceWorkerRegistrationInfo object. It is threadsafe and can be
|
||||
// transferred across processes.
|
||||
class ServiceWorkerRegistrationDescriptor final
|
||||
{
|
||||
// This class is largely a wrapper wround an IPDL generated struct. We
|
||||
// need the wrapper class since IPDL generated code includes windows.h
|
||||
// which is in turn incompatible with bindings code.
|
||||
UniquePtr<IPCServiceWorkerRegistrationDescriptor> mData;
|
||||
|
||||
Maybe<IPCServiceWorkerDescriptor>
|
||||
NewestInternal() const;
|
||||
|
||||
public:
|
||||
ServiceWorkerRegistrationDescriptor(nsIPrincipal* aPrincipal,
|
||||
const nsACString& aScope,
|
||||
ServiceWorkerUpdateViaCache aUpdateViaCache);
|
||||
|
||||
ServiceWorkerRegistrationDescriptor(const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
|
||||
const nsACString& aScope,
|
||||
ServiceWorkerUpdateViaCache aUpdateViaCache);
|
||||
|
||||
explicit ServiceWorkerRegistrationDescriptor(const IPCServiceWorkerRegistrationDescriptor& aDescriptor);
|
||||
|
||||
ServiceWorkerRegistrationDescriptor(const ServiceWorkerRegistrationDescriptor& aRight);
|
||||
|
||||
ServiceWorkerRegistrationDescriptor&
|
||||
operator=(const ServiceWorkerRegistrationDescriptor& aRight);
|
||||
|
||||
ServiceWorkerRegistrationDescriptor(ServiceWorkerRegistrationDescriptor&& aRight);
|
||||
|
||||
ServiceWorkerRegistrationDescriptor&
|
||||
operator=(ServiceWorkerRegistrationDescriptor&& aRight);
|
||||
|
||||
~ServiceWorkerRegistrationDescriptor() = default;
|
||||
|
||||
bool
|
||||
operator==(const ServiceWorkerRegistrationDescriptor& aRight) const;
|
||||
|
||||
ServiceWorkerUpdateViaCache
|
||||
UpdateViaCache() const;
|
||||
|
||||
const mozilla::ipc::PrincipalInfo&
|
||||
PrincipalInfo() const;
|
||||
|
||||
const nsCString&
|
||||
Scope() const;
|
||||
|
||||
Maybe<ServiceWorkerDescriptor>
|
||||
GetInstalling() const;
|
||||
|
||||
Maybe<ServiceWorkerDescriptor>
|
||||
GetWaiting() const;
|
||||
|
||||
Maybe<ServiceWorkerDescriptor>
|
||||
GetActive() const;
|
||||
|
||||
Maybe<ServiceWorkerDescriptor>
|
||||
Newest() const;
|
||||
|
||||
bool
|
||||
IsValid() const;
|
||||
|
||||
void
|
||||
SetUpdateViaCache(ServiceWorkerUpdateViaCache aUpdateViaCache);
|
||||
|
||||
void
|
||||
SetWorkers(ServiceWorkerInfo* aInstalling,
|
||||
ServiceWorkerInfo* aWaiting,
|
||||
ServiceWorkerInfo* aActive);
|
||||
|
||||
void
|
||||
SetWorkers(OptionalIPCServiceWorkerDescriptor& aInstalling,
|
||||
OptionalIPCServiceWorkerDescriptor& aWaiting,
|
||||
OptionalIPCServiceWorkerDescriptor& aActive);
|
||||
|
||||
// Expose the underlying IPC type so that it can be passed via IPC.
|
||||
const IPCServiceWorkerRegistrationDescriptor&
|
||||
ToIPC() const;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // _mozilla_dom_ServiceWorkerRegistrationDescriptor_h
|
|
@ -78,6 +78,8 @@ ServiceWorkerRegistrationInfo::Clear()
|
|||
mActiveWorker = nullptr;
|
||||
}
|
||||
|
||||
mDescriptor.SetWorkers(mInstallingWorker, mWaitingWorker, mActiveWorker);
|
||||
|
||||
NotifyChromeRegistrationListeners();
|
||||
}
|
||||
|
||||
|
@ -85,14 +87,13 @@ ServiceWorkerRegistrationInfo::ServiceWorkerRegistrationInfo(
|
|||
const nsACString& aScope,
|
||||
nsIPrincipal* aPrincipal,
|
||||
ServiceWorkerUpdateViaCache aUpdateViaCache)
|
||||
: mControlledClientsCounter(0)
|
||||
: mPrincipal(aPrincipal)
|
||||
, mDescriptor(aPrincipal, aScope, aUpdateViaCache)
|
||||
, mControlledClientsCounter(0)
|
||||
, mUpdateState(NoUpdate)
|
||||
, mCreationTime(PR_Now())
|
||||
, mCreationTimeStamp(TimeStamp::Now())
|
||||
, mLastUpdateTime(0)
|
||||
, mUpdateViaCache(aUpdateViaCache)
|
||||
, mScope(aScope)
|
||||
, mPrincipal(aPrincipal)
|
||||
, mPendingUninstall(false)
|
||||
{}
|
||||
|
||||
|
@ -101,6 +102,36 @@ ServiceWorkerRegistrationInfo::~ServiceWorkerRegistrationInfo()
|
|||
MOZ_DIAGNOSTIC_ASSERT(!IsControllingClients());
|
||||
}
|
||||
|
||||
const nsCString&
|
||||
ServiceWorkerRegistrationInfo::Scope() const
|
||||
{
|
||||
return mDescriptor.Scope();
|
||||
}
|
||||
|
||||
nsIPrincipal*
|
||||
ServiceWorkerRegistrationInfo::Principal() const
|
||||
{
|
||||
return mPrincipal;
|
||||
}
|
||||
|
||||
bool
|
||||
ServiceWorkerRegistrationInfo::IsPendingUninstall() const
|
||||
{
|
||||
return mPendingUninstall;
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerRegistrationInfo::SetPendingUninstall()
|
||||
{
|
||||
mPendingUninstall = true;
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerRegistrationInfo::ClearPendingUninstall()
|
||||
{
|
||||
mPendingUninstall = false;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(ServiceWorkerRegistrationInfo, nsIServiceWorkerRegistrationInfo)
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -115,7 +146,7 @@ NS_IMETHODIMP
|
|||
ServiceWorkerRegistrationInfo::GetScope(nsAString& aScope)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
CopyUTF8toUTF16(mScope, aScope);
|
||||
CopyUTF8toUTF16(Scope(), aScope);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -311,6 +342,9 @@ ServiceWorkerRegistrationInfo::FinishActivate(bool aSuccess)
|
|||
// Activation never fails, so aSuccess is ignored.
|
||||
mActiveWorker->UpdateState(ServiceWorkerState::Activated);
|
||||
mActiveWorker->UpdateActivatedTime();
|
||||
|
||||
mDescriptor.SetWorkers(mInstallingWorker, mWaitingWorker, mActiveWorker);
|
||||
|
||||
NotifyChromeRegistrationListeners();
|
||||
|
||||
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
|
@ -420,7 +454,7 @@ ServiceWorkerRegistrationInfo::MaybeScheduleTimeCheckAndUpdate()
|
|||
mUpdateState = NeedTimeCheckAndUpdate;
|
||||
}
|
||||
|
||||
swm->ScheduleUpdateTimer(mPrincipal, mScope);
|
||||
swm->ScheduleUpdateTimer(mPrincipal, Scope());
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -436,7 +470,7 @@ ServiceWorkerRegistrationInfo::MaybeScheduleUpdate()
|
|||
|
||||
mUpdateState = NeedUpdate;
|
||||
|
||||
swm->ScheduleUpdateTimer(mPrincipal, mScope);
|
||||
swm->ScheduleUpdateTimer(mPrincipal, Scope());
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -542,6 +576,8 @@ ServiceWorkerRegistrationInfo::ClearInstalling()
|
|||
mInstallingWorker->UpdateRedundantTime();
|
||||
mInstallingWorker = nullptr;
|
||||
|
||||
mDescriptor.SetWorkers(mInstallingWorker, mWaitingWorker, mActiveWorker);
|
||||
|
||||
NotifyChromeRegistrationListeners();
|
||||
}
|
||||
|
||||
|
@ -554,6 +590,9 @@ ServiceWorkerRegistrationInfo::TransitionEvaluatingToInstalling()
|
|||
|
||||
mInstallingWorker = mEvaluatingWorker.forget();
|
||||
mInstallingWorker->UpdateState(ServiceWorkerState::Installing);
|
||||
|
||||
mDescriptor.SetWorkers(mInstallingWorker, mWaitingWorker, mActiveWorker);
|
||||
|
||||
NotifyChromeRegistrationListeners();
|
||||
}
|
||||
|
||||
|
@ -574,6 +613,9 @@ ServiceWorkerRegistrationInfo::TransitionInstallingToWaiting()
|
|||
TransitionToNextState);
|
||||
mWaitingWorker->UpdateState(ServiceWorkerState::Installed);
|
||||
mWaitingWorker->UpdateInstalledTime();
|
||||
|
||||
mDescriptor.SetWorkers(mInstallingWorker, mWaitingWorker, mActiveWorker);
|
||||
|
||||
NotifyChromeRegistrationListeners();
|
||||
|
||||
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||
|
@ -612,6 +654,9 @@ ServiceWorkerRegistrationInfo::SetActive(ServiceWorkerInfo* aServiceWorker)
|
|||
// We don't need to update activated time when we load registration from
|
||||
// registrar.
|
||||
UpdateRegistrationStateProperties(WhichServiceWorker::ACTIVE_WORKER, Invalidate);
|
||||
|
||||
mDescriptor.SetWorkers(mInstallingWorker, mWaitingWorker, mActiveWorker);
|
||||
|
||||
NotifyChromeRegistrationListeners();
|
||||
}
|
||||
|
||||
|
@ -633,6 +678,9 @@ ServiceWorkerRegistrationInfo::TransitionWaitingToActive()
|
|||
UpdateRegistrationStateProperties(WhichServiceWorker::WAITING_WORKER,
|
||||
TransitionToNextState);
|
||||
mActiveWorker->UpdateState(ServiceWorkerState::Activating);
|
||||
|
||||
mDescriptor.SetWorkers(mInstallingWorker, mWaitingWorker, mActiveWorker);
|
||||
|
||||
NotifyChromeRegistrationListeners();
|
||||
}
|
||||
|
||||
|
@ -645,14 +693,14 @@ ServiceWorkerRegistrationInfo::IsIdle() const
|
|||
ServiceWorkerUpdateViaCache
|
||||
ServiceWorkerRegistrationInfo::GetUpdateViaCache() const
|
||||
{
|
||||
return mUpdateViaCache;
|
||||
return mDescriptor.UpdateViaCache();
|
||||
}
|
||||
|
||||
void
|
||||
ServiceWorkerRegistrationInfo::SetUpdateViaCache(
|
||||
ServiceWorkerUpdateViaCache aUpdateViaCache)
|
||||
{
|
||||
mUpdateViaCache = aUpdateViaCache;
|
||||
mDescriptor.SetUpdateViaCache(aUpdateViaCache);
|
||||
}
|
||||
|
||||
int64_t
|
||||
|
@ -671,5 +719,11 @@ ServiceWorkerRegistrationInfo::SetLastUpdateTime(const int64_t aTime)
|
|||
mLastUpdateTime = aTime;
|
||||
}
|
||||
|
||||
const ServiceWorkerRegistrationDescriptor&
|
||||
ServiceWorkerRegistrationInfo::Descriptor() const
|
||||
{
|
||||
return mDescriptor;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "mozilla/dom/ServiceWorkerInfo.h"
|
||||
#include "mozilla/dom/ServiceWorkerCommon.h"
|
||||
#include "mozilla/dom/ServiceWorkerRegistrationBinding.h"
|
||||
#include "mozilla/dom/ServiceWorkerRegistrationDescriptor.h"
|
||||
#include "nsProxyRelease.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -18,6 +19,10 @@ namespace dom {
|
|||
class ServiceWorkerRegistrationInfo final
|
||||
: public nsIServiceWorkerRegistrationInfo
|
||||
{
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
ServiceWorkerRegistrationDescriptor mDescriptor;
|
||||
nsTArray<nsCOMPtr<nsIServiceWorkerRegistrationInfoListener>> mListeners;
|
||||
|
||||
uint32_t mControlledClientsCounter;
|
||||
|
||||
enum
|
||||
|
@ -33,8 +38,6 @@ class ServiceWorkerRegistrationInfo final
|
|||
// The time of update is 0, if SWR've never been updated yet.
|
||||
PRTime mLastUpdateTime;
|
||||
|
||||
ServiceWorkerUpdateViaCache mUpdateViaCache;
|
||||
|
||||
RefPtr<ServiceWorkerInfo> mEvaluatingWorker;
|
||||
RefPtr<ServiceWorkerInfo> mActiveWorker;
|
||||
RefPtr<ServiceWorkerInfo> mWaitingWorker;
|
||||
|
@ -42,25 +45,34 @@ class ServiceWorkerRegistrationInfo final
|
|||
|
||||
virtual ~ServiceWorkerRegistrationInfo();
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISERVICEWORKERREGISTRATIONINFO
|
||||
|
||||
const nsCString mScope;
|
||||
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
|
||||
nsTArray<nsCOMPtr<nsIServiceWorkerRegistrationInfoListener>> mListeners;
|
||||
|
||||
// When unregister() is called on a registration, it is not immediately
|
||||
// removed since documents may be controlled. It is marked as
|
||||
// pendingUninstall and when all controlling documents go away, removed.
|
||||
bool mPendingUninstall;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISERVICEWORKERREGISTRATIONINFO
|
||||
|
||||
ServiceWorkerRegistrationInfo(const nsACString& aScope,
|
||||
nsIPrincipal* aPrincipal,
|
||||
ServiceWorkerUpdateViaCache aUpdateViaCache);
|
||||
|
||||
const nsCString&
|
||||
Scope() const;
|
||||
|
||||
nsIPrincipal*
|
||||
Principal() const;
|
||||
|
||||
bool
|
||||
IsPendingUninstall() const;
|
||||
|
||||
void
|
||||
SetPendingUninstall();
|
||||
|
||||
void
|
||||
ClearPendingUninstall();
|
||||
|
||||
already_AddRefed<ServiceWorkerInfo>
|
||||
Newest() const
|
||||
{
|
||||
|
@ -197,6 +209,9 @@ public:
|
|||
void
|
||||
SetLastUpdateTime(const int64_t aTime);
|
||||
|
||||
const ServiceWorkerRegistrationDescriptor&
|
||||
Descriptor() const;
|
||||
|
||||
private:
|
||||
enum TransitionType {
|
||||
TransitionToNextState = 0,
|
||||
|
|
|
@ -981,8 +981,8 @@ CompareNetwork::OnStreamComplete(nsIStreamLoader* aLoader, nsISupports* aContext
|
|||
statusAsText.AppendInt(status);
|
||||
|
||||
ServiceWorkerManager::LocalizeAndReportToAllClients(
|
||||
mRegistration->mScope, "ServiceWorkerRegisterNetworkError",
|
||||
nsTArray<nsString> { NS_ConvertUTF8toUTF16(mRegistration->mScope),
|
||||
mRegistration->Scope(), "ServiceWorkerRegisterNetworkError",
|
||||
nsTArray<nsString> { NS_ConvertUTF8toUTF16(mRegistration->Scope()),
|
||||
statusAsText, mURL });
|
||||
|
||||
rv = NS_ERROR_FAILURE;
|
||||
|
@ -1016,8 +1016,8 @@ CompareNetwork::OnStreamComplete(nsIStreamLoader* aLoader, nsISupports* aContext
|
|||
!mimeType.LowerCaseEqualsLiteral("application/x-javascript") &&
|
||||
!mimeType.LowerCaseEqualsLiteral("application/javascript")) {
|
||||
ServiceWorkerManager::LocalizeAndReportToAllClients(
|
||||
mRegistration->mScope, "ServiceWorkerRegisterMimeTypeError",
|
||||
nsTArray<nsString> { NS_ConvertUTF8toUTF16(mRegistration->mScope),
|
||||
mRegistration->Scope(), "ServiceWorkerRegisterMimeTypeError",
|
||||
nsTArray<nsString> { NS_ConvertUTF8toUTF16(mRegistration->Scope()),
|
||||
NS_ConvertUTF8toUTF16(mimeType), mURL });
|
||||
rv = NS_ERROR_DOM_SECURITY_ERR;
|
||||
return rv;
|
||||
|
|
|
@ -120,17 +120,17 @@ ServiceWorkerUnregisterJob::Unregister()
|
|||
}
|
||||
|
||||
// Note, we send the message to remove the registration from disk now even
|
||||
// though we may only set the mPendingUninstall flag below. This is
|
||||
// though we may only set the pending uninstall flag below. This is
|
||||
// necessary to ensure the registration is removed if the controlled
|
||||
// clients are closed by shutting down the browser. If the registration
|
||||
// is resurrected by clearing mPendingUninstall then it should be saved
|
||||
// is resurrected by clearing pending uninstall then it should be saved
|
||||
// to disk again.
|
||||
if (mSendToParent && !registration->mPendingUninstall) {
|
||||
if (mSendToParent && !registration->IsPendingUninstall()) {
|
||||
swm->MaybeSendUnregister(mPrincipal, mScope);
|
||||
}
|
||||
|
||||
// "Set registration's uninstalling flag."
|
||||
registration->mPendingUninstall = true;
|
||||
registration->SetPendingUninstall();
|
||||
|
||||
// "Resolve promise with true"
|
||||
mResult = true;
|
||||
|
|
|
@ -260,7 +260,7 @@ ServiceWorkerUpdateJob::AsyncExecute()
|
|||
RefPtr<ServiceWorkerRegistrationInfo> registration =
|
||||
swm->GetRegistration(mPrincipal, mScope);
|
||||
|
||||
if (!registration || registration->mPendingUninstall) {
|
||||
if (!registration || registration->IsPendingUninstall()) {
|
||||
ErrorResult rv;
|
||||
rv.ThrowTypeError<MSG_SW_UPDATE_BAD_REGISTRATION>(NS_ConvertUTF8toUTF16(mScope),
|
||||
NS_LITERAL_STRING("uninstalled"));
|
||||
|
@ -399,9 +399,9 @@ ServiceWorkerUpdateJob::ComparisonResult(nsresult aStatus,
|
|||
}
|
||||
}
|
||||
|
||||
if (!StringBeginsWith(mRegistration->mScope, maxPrefix)) {
|
||||
if (!StringBeginsWith(mRegistration->Scope(), maxPrefix)) {
|
||||
nsAutoString message;
|
||||
NS_ConvertUTF8toUTF16 reportScope(mRegistration->mScope);
|
||||
NS_ConvertUTF8toUTF16 reportScope(mRegistration->Scope());
|
||||
NS_ConvertUTF8toUTF16 reportMaxPrefix(maxPrefix);
|
||||
const char16_t* params[] = { reportScope.get(), reportMaxPrefix.get() };
|
||||
|
||||
|
@ -434,8 +434,8 @@ ServiceWorkerUpdateJob::ComparisonResult(nsresult aStatus,
|
|||
}
|
||||
|
||||
RefPtr<ServiceWorkerInfo> sw =
|
||||
new ServiceWorkerInfo(mRegistration->mPrincipal,
|
||||
mRegistration->mScope,
|
||||
new ServiceWorkerInfo(mRegistration->Principal(),
|
||||
mRegistration->Scope(),
|
||||
mScriptSpec,
|
||||
aNewCacheName,
|
||||
flags);
|
||||
|
@ -475,7 +475,7 @@ ServiceWorkerUpdateJob::ContinueUpdateAfterScriptEval(bool aScriptEvaluationResu
|
|||
ErrorResult error;
|
||||
|
||||
NS_ConvertUTF8toUTF16 scriptSpec(mScriptSpec);
|
||||
NS_ConvertUTF8toUTF16 scope(mRegistration->mScope);
|
||||
NS_ConvertUTF8toUTF16 scope(mRegistration->Scope());
|
||||
error.ThrowTypeError<MSG_SW_SCRIPT_THREW>(scriptSpec, scope);
|
||||
FailUpdateJob(error);
|
||||
return;
|
||||
|
|
|
@ -22,6 +22,7 @@ EXPORTS.mozilla.dom += [
|
|||
'ServiceWorkerManagerParent.h',
|
||||
'ServiceWorkerRegistrar.h',
|
||||
'ServiceWorkerRegistration.h',
|
||||
'ServiceWorkerRegistrationDescriptor.h',
|
||||
'ServiceWorkerRegistrationInfo.h',
|
||||
'ServiceWorkerUtils.h',
|
||||
]
|
||||
|
@ -43,6 +44,7 @@ UNIFIED_SOURCES += [
|
|||
'ServiceWorkerRegisterJob.cpp',
|
||||
'ServiceWorkerRegistrar.cpp',
|
||||
'ServiceWorkerRegistration.cpp',
|
||||
'ServiceWorkerRegistrationDescriptor.cpp',
|
||||
'ServiceWorkerRegistrationInfo.cpp',
|
||||
'ServiceWorkerScriptCache.cpp',
|
||||
'ServiceWorkerUnregisterJob.cpp',
|
||||
|
@ -54,6 +56,7 @@ UNIFIED_SOURCES += [
|
|||
|
||||
IPDL_SOURCES += [
|
||||
'IPCServiceWorkerDescriptor.ipdlh',
|
||||
'IPCServiceWorkerRegistrationDescriptor.ipdlh',
|
||||
'PServiceWorkerManager.ipdl',
|
||||
'PServiceWorkerUpdater.ipdl',
|
||||
'ServiceWorkerRegistrarTypes.ipdlh',
|
||||
|
|
|
@ -320,6 +320,15 @@ set_define('JS_TRACE_LOGGING',
|
|||
depends_if('--enable-trace-logging')(lambda x: True))
|
||||
|
||||
|
||||
# Enable breakpoint for artificial OOMs
|
||||
# =======================================================
|
||||
js_option('--enable-oom-breakpoint',
|
||||
help='Enable a breakpoint function for artificial OOMs')
|
||||
|
||||
set_define('JS_OOM_BREAKPOINT',
|
||||
depends_if('--enable-oom-breakpoint')(lambda _: True))
|
||||
|
||||
|
||||
js_option('--enable-perf', env='JS_ION_PERF',
|
||||
help='Enable Linux perf integration')
|
||||
|
||||
|
|
|
@ -1988,7 +1988,7 @@ static const JSFunctionSpec object_static_methods[] = {
|
|||
JS_FN("keys", obj_keys, 1, 0),
|
||||
JS_FN("values", obj_values, 1, 0),
|
||||
JS_FN("entries", obj_entries, 1, 0),
|
||||
JS_FN("is", obj_is, 2, 0),
|
||||
JS_INLINABLE_FN("is", obj_is, 2, 0, ObjectIs),
|
||||
JS_SELF_HOSTED_FN("defineProperty", "ObjectDefineProperty", 3, 0),
|
||||
JS_FN("defineProperties", obj_defineProperties, 2, 0),
|
||||
JS_INLINABLE_FN("create", obj_create, 2, 0, ObjectCreate),
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
function SameValue(x, y) {
|
||||
if (x === y) {
|
||||
return (x !== 0) || (1 / x === 1 / y);
|
||||
}
|
||||
return (x !== x && y !== y);
|
||||
}
|
||||
|
||||
function* cartesian(a, b = a) {
|
||||
for (var pa of a) {
|
||||
for (var pb of b) {
|
||||
yield [pa, pb];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var testValues = {
|
||||
Double: `[-0.0, +0.0, 1.0, NaN]`,
|
||||
Int32: `[-1, 0, 1, 2]`,
|
||||
Value: `[-0.0, +0.0, "", NaN]`,
|
||||
};
|
||||
|
||||
for (var [xs, ys] of cartesian(Object.values(testValues))) {
|
||||
var fn = Function(`
|
||||
var xs = ${xs};
|
||||
var ys = ${ys};
|
||||
assertEq(xs.length, 4);
|
||||
assertEq(ys.length, 4);
|
||||
|
||||
// Compare each entry in xs with each entry in ys and ensure Object.is
|
||||
// computes the same result as SameValue.
|
||||
var actual = 0, expected = 0;
|
||||
for (var i = 0; i < 1000; ++i) {
|
||||
// 0 1 2 3
|
||||
var xi = i & 3;
|
||||
|
||||
// 0 1 2 3 1 2 3 0 2 3 0 1 3 0 1 2
|
||||
var yi = (i + ((i >> 2) & 3)) & 3;
|
||||
|
||||
actual += Object.is(xs[xi], ys[yi]) ? 1 : 0;
|
||||
expected += SameValue(xs[xi], ys[yi]) ? 1 : 0;
|
||||
}
|
||||
assertEq(actual, expected);
|
||||
`);
|
||||
for (var i = 0; i < 3; ++i) {
|
||||
fn();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
var success = 0;
|
||||
var expected_bool = 0;
|
||||
var expected_int = 0;
|
||||
var expected_double = 0;
|
||||
var expected_string = 0;
|
||||
var expected_object = 0;
|
||||
var expected_symbol = 0;
|
||||
|
||||
function test_type_stable_ic() {
|
||||
// Initialize as falsy where possible.
|
||||
var a = undefined; // No Change, never succeeds
|
||||
var b = null; // No Change, never succeeds
|
||||
var c = false; // Alternate between true and false.
|
||||
var d = 0; // Int32 cache checker, change int values
|
||||
var e = ""; // String cache checker, change string values
|
||||
var f = Symbol(); // No change, always succeed, no cache.
|
||||
var g = {}; // Change objects, always succeed.
|
||||
var h = -0; // Double cache checker, change double values.
|
||||
|
||||
for (var i =0; i < 30; i++) {
|
||||
// Switch between values to ensure the caches fire.
|
||||
switch (i % 3) {
|
||||
case 0:
|
||||
d = 0;
|
||||
e = "hi"; expected_string++;
|
||||
c = true; expected_bool++;
|
||||
h = 0;
|
||||
break;
|
||||
case 1:
|
||||
d = 1; expected_int++;
|
||||
e = "";
|
||||
c = false;
|
||||
h = NaN;
|
||||
break;
|
||||
case 2:
|
||||
d = 2; expected_int++;
|
||||
h = 1.234; expected_double++;
|
||||
g = {};
|
||||
break;
|
||||
}
|
||||
|
||||
if (a) { success++; }
|
||||
if (b) { success++; }
|
||||
if (c) { success++; }
|
||||
if (d) { success++; }
|
||||
if (e) { success++; }
|
||||
if (f) { success++; } expected_symbol++; // Symbol succeed
|
||||
if (g) { success++; } expected_object++; // Object success
|
||||
if (h) { success++; }
|
||||
}
|
||||
}
|
||||
|
||||
test_type_stable_ic();
|
||||
|
||||
assertEq(success, expected_bool + expected_double + expected_int + expected_object + expected_string + expected_symbol);
|
||||
|
||||
|
||||
// Test cache failures.
|
||||
function helper(fun, arg, n)
|
||||
{
|
||||
var r = 0;
|
||||
for (var i = 0; i < n; i++) {
|
||||
r = fun(arg);
|
||||
}
|
||||
return r ? 1 : 0;
|
||||
}
|
||||
|
||||
function test_transition(fun, load, test, before, after) {
|
||||
var a = helper(fun, load, 30);
|
||||
var x = helper(fun, test, 5)
|
||||
assertEq(a, before);
|
||||
assertEq(x, after)
|
||||
}
|
||||
|
||||
var fun1 = (x) => { if (x) return true; else return false; };
|
||||
var fun2 = (x) => { if (x) return true; else return false; };
|
||||
var fun3 = (x) => { if (x) return true; else return false; };
|
||||
var fun4 = (x) => { if (x) return true; else return false; };
|
||||
var fun5 = (x) => { if (x) return true; else return false; };
|
||||
var fun6 = (x) => { if (x) return true; else return false; };
|
||||
var fun7 = (x) => { if (x) return true; else return false; };
|
||||
var fun8 = (x) => { if (x) return true; else return false; };
|
||||
|
||||
// NaN -> Int32
|
||||
test_transition(fun1, NaN, 1, 0, 1);
|
||||
test_transition(fun2, 1, NaN, 1, 0);
|
||||
// NaN -> Object / Object -> NaN
|
||||
test_transition(fun3, NaN, {}, 0, 1);
|
||||
test_transition(fun4, {}, NaN, 1, 0);
|
||||
// Object -> null / null -> Object
|
||||
test_transition(fun5, {}, null, 1, 0);
|
||||
test_transition(fun6, null, {}, 0, 1);
|
||||
// Symbol -> null, null -> Symbol
|
||||
test_transition(fun7, Symbol('hi'), null, 1, 0);
|
||||
test_transition(fun8, null, Symbol('lo'), 0, 1);
|
|
@ -0,0 +1,6 @@
|
|||
// |jit-test| --spectre-mitigations=on
|
||||
function f() {
|
||||
return arguments[arguments.length];
|
||||
}
|
||||
for (var i = 0; i < 10; i++)
|
||||
assertEq(f(), undefined);
|
|
@ -2095,6 +2095,7 @@ BaselineCacheIRCompiler::init(CacheKind kind)
|
|||
case CacheKind::GetProp:
|
||||
case CacheKind::TypeOf:
|
||||
case CacheKind::GetIterator:
|
||||
case CacheKind::ToBool:
|
||||
MOZ_ASSERT(numInputs == 1);
|
||||
allocator.initInputLocation(0, R0);
|
||||
break;
|
||||
|
|
|
@ -461,74 +461,33 @@ DoToBoolFallback(JSContext* cx, BaselineFrame* frame, ICToBool_Fallback* stub, H
|
|||
{
|
||||
FallbackICSpew(cx, stub, "ToBool");
|
||||
|
||||
bool cond = ToBoolean(arg);
|
||||
ret.setBoolean(cond);
|
||||
|
||||
// Check to see if a new stub should be generated.
|
||||
if (stub->numOptimizedStubs() >= ICToBool_Fallback::MAX_OPTIMIZED_STUBS) {
|
||||
// TODO: Discard all stubs in this IC and replace with inert megamorphic stub.
|
||||
// But for now we just bail.
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!arg.isBoolean());
|
||||
|
||||
JSScript* script = frame->script();
|
||||
if (stub->state().maybeTransition())
|
||||
stub->discardStubs(cx);
|
||||
|
||||
// Try to generate new stubs.
|
||||
if (arg.isInt32()) {
|
||||
JitSpew(JitSpew_BaselineIC, " Generating ToBool(Int32) stub.");
|
||||
ICToBool_Int32::Compiler compiler(cx);
|
||||
ICStub* int32Stub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!int32Stub)
|
||||
return false;
|
||||
if (stub->state().canAttachStub()) {
|
||||
|
||||
stub->addNewStub(int32Stub);
|
||||
return true;
|
||||
RootedScript script(cx, frame->script());
|
||||
jsbytecode* pc = stub->icEntry()->pc(script);
|
||||
|
||||
ICStubEngine engine = ICStubEngine::Baseline;
|
||||
ToBoolIRGenerator gen(cx, script, pc, stub->state().mode(),
|
||||
arg);
|
||||
bool attached = false;
|
||||
if (gen.tryAttachStub()) {
|
||||
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
|
||||
BaselineCacheIRStubKind::Regular,
|
||||
engine, script, stub, &attached);
|
||||
if (newStub)
|
||||
JitSpew(JitSpew_BaselineIC, " Attached ToBool CacheIR stub, attached is now %d", attached);
|
||||
}
|
||||
if (!attached)
|
||||
stub->state().trackNotAttached();
|
||||
}
|
||||
|
||||
if (arg.isDouble() && cx->runtime()->jitSupportsFloatingPoint) {
|
||||
JitSpew(JitSpew_BaselineIC, " Generating ToBool(Double) stub.");
|
||||
ICToBool_Double::Compiler compiler(cx);
|
||||
ICStub* doubleStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!doubleStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(doubleStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (arg.isString()) {
|
||||
JitSpew(JitSpew_BaselineIC, " Generating ToBool(String) stub");
|
||||
ICToBool_String::Compiler compiler(cx);
|
||||
ICStub* stringStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!stringStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(stringStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (arg.isNull() || arg.isUndefined()) {
|
||||
ICToBool_NullUndefined::Compiler compiler(cx);
|
||||
ICStub* nilStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!nilStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(nilStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (arg.isObject()) {
|
||||
JitSpew(JitSpew_BaselineIC, " Generating ToBool(Object) stub.");
|
||||
ICToBool_Object::Compiler compiler(cx);
|
||||
ICStub* objStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!objStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(objStub);
|
||||
return true;
|
||||
}
|
||||
bool cond = ToBoolean(arg);
|
||||
ret.setBoolean(cond);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -554,150 +513,6 @@ ICToBool_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
|
|||
return tailCallVM(fun, masm);
|
||||
}
|
||||
|
||||
//
|
||||
// ToBool_Int32
|
||||
//
|
||||
|
||||
bool
|
||||
ICToBool_Int32::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
{
|
||||
MOZ_ASSERT(engine_ == Engine::Baseline);
|
||||
|
||||
Label failure;
|
||||
masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
|
||||
|
||||
Label ifFalse;
|
||||
masm.branchTestInt32Truthy(false, R0, &ifFalse);
|
||||
|
||||
masm.moveValue(BooleanValue(true), R0);
|
||||
EmitReturnFromIC(masm);
|
||||
|
||||
masm.bind(&ifFalse);
|
||||
masm.moveValue(BooleanValue(false), R0);
|
||||
EmitReturnFromIC(masm);
|
||||
|
||||
// Failure case - jump to next stub
|
||||
masm.bind(&failure);
|
||||
EmitStubGuardFailure(masm);
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// ToBool_String
|
||||
//
|
||||
|
||||
bool
|
||||
ICToBool_String::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
{
|
||||
MOZ_ASSERT(engine_ == Engine::Baseline);
|
||||
|
||||
Label failure;
|
||||
masm.branchTestString(Assembler::NotEqual, R0, &failure);
|
||||
|
||||
Label ifFalse;
|
||||
masm.branchTestStringTruthy(false, R0, &ifFalse);
|
||||
|
||||
masm.moveValue(BooleanValue(true), R0);
|
||||
EmitReturnFromIC(masm);
|
||||
|
||||
masm.bind(&ifFalse);
|
||||
masm.moveValue(BooleanValue(false), R0);
|
||||
EmitReturnFromIC(masm);
|
||||
|
||||
// Failure case - jump to next stub
|
||||
masm.bind(&failure);
|
||||
EmitStubGuardFailure(masm);
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// ToBool_NullUndefined
|
||||
//
|
||||
|
||||
bool
|
||||
ICToBool_NullUndefined::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
{
|
||||
MOZ_ASSERT(engine_ == Engine::Baseline);
|
||||
|
||||
Label failure, ifFalse;
|
||||
masm.branchTestNull(Assembler::Equal, R0, &ifFalse);
|
||||
masm.branchTestUndefined(Assembler::NotEqual, R0, &failure);
|
||||
|
||||
masm.bind(&ifFalse);
|
||||
masm.moveValue(BooleanValue(false), R0);
|
||||
EmitReturnFromIC(masm);
|
||||
|
||||
// Failure case - jump to next stub
|
||||
masm.bind(&failure);
|
||||
EmitStubGuardFailure(masm);
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// ToBool_Double
|
||||
//
|
||||
|
||||
bool
|
||||
ICToBool_Double::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
{
|
||||
MOZ_ASSERT(engine_ == Engine::Baseline);
|
||||
|
||||
Label failure, ifTrue;
|
||||
masm.branchTestDouble(Assembler::NotEqual, R0, &failure);
|
||||
masm.unboxDouble(R0, FloatReg0);
|
||||
masm.branchTestDoubleTruthy(true, FloatReg0, &ifTrue);
|
||||
|
||||
masm.moveValue(BooleanValue(false), R0);
|
||||
EmitReturnFromIC(masm);
|
||||
|
||||
masm.bind(&ifTrue);
|
||||
masm.moveValue(BooleanValue(true), R0);
|
||||
EmitReturnFromIC(masm);
|
||||
|
||||
// Failure case - jump to next stub
|
||||
masm.bind(&failure);
|
||||
EmitStubGuardFailure(masm);
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// ToBool_Object
|
||||
//
|
||||
|
||||
bool
|
||||
ICToBool_Object::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
{
|
||||
MOZ_ASSERT(engine_ == Engine::Baseline);
|
||||
|
||||
Label failure, emulatesUndefined, slowPath;
|
||||
masm.branchTestObject(Assembler::NotEqual, R0, &failure);
|
||||
|
||||
Register objReg = masm.extractObject(R0, ExtractTemp0);
|
||||
Register scratch = R1.scratchReg();
|
||||
masm.branchIfObjectEmulatesUndefined(objReg, scratch, &slowPath, &emulatesUndefined);
|
||||
|
||||
// If object doesn't emulate undefined, it evaulates to true.
|
||||
masm.moveValue(BooleanValue(true), R0);
|
||||
EmitReturnFromIC(masm);
|
||||
|
||||
masm.bind(&emulatesUndefined);
|
||||
masm.moveValue(BooleanValue(false), R0);
|
||||
EmitReturnFromIC(masm);
|
||||
|
||||
masm.bind(&slowPath);
|
||||
masm.setupUnalignedABICall(scratch);
|
||||
masm.passABIArg(objReg);
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, js::EmulatesUndefined));
|
||||
masm.convertBoolToInt32(ReturnReg, ReturnReg);
|
||||
masm.xor32(Imm32(1), ReturnReg);
|
||||
masm.tagValue(JSVAL_TYPE_BOOLEAN, ReturnReg, R0);
|
||||
EmitReturnFromIC(masm);
|
||||
|
||||
// Failure case - jump to next stub
|
||||
masm.bind(&failure);
|
||||
EmitStubGuardFailure(masm);
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// ToNumber_Fallback
|
||||
|
|
|
@ -242,121 +242,6 @@ class ICToBool_Fallback : public ICFallbackStub
|
|||
};
|
||||
};
|
||||
|
||||
class ICToBool_Int32 : public ICStub
|
||||
{
|
||||
friend class ICStubSpace;
|
||||
|
||||
explicit ICToBool_Int32(JitCode* stubCode)
|
||||
: ICStub(ICStub::ToBool_Int32, stubCode) {}
|
||||
|
||||
public:
|
||||
// Compiler for this stub kind.
|
||||
class Compiler : public ICStubCompiler {
|
||||
protected:
|
||||
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
|
||||
|
||||
public:
|
||||
explicit Compiler(JSContext* cx)
|
||||
: ICStubCompiler(cx, ICStub::ToBool_Int32, Engine::Baseline) {}
|
||||
|
||||
ICStub* getStub(ICStubSpace* space) override {
|
||||
return newStub<ICToBool_Int32>(space, getStubCode());
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class ICToBool_String : public ICStub
|
||||
{
|
||||
friend class ICStubSpace;
|
||||
|
||||
explicit ICToBool_String(JitCode* stubCode)
|
||||
: ICStub(ICStub::ToBool_String, stubCode) {}
|
||||
|
||||
public:
|
||||
// Compiler for this stub kind.
|
||||
class Compiler : public ICStubCompiler {
|
||||
protected:
|
||||
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
|
||||
|
||||
public:
|
||||
explicit Compiler(JSContext* cx)
|
||||
: ICStubCompiler(cx, ICStub::ToBool_String, Engine::Baseline) {}
|
||||
|
||||
ICStub* getStub(ICStubSpace* space) override {
|
||||
return newStub<ICToBool_String>(space, getStubCode());
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class ICToBool_NullUndefined : public ICStub
|
||||
{
|
||||
friend class ICStubSpace;
|
||||
|
||||
explicit ICToBool_NullUndefined(JitCode* stubCode)
|
||||
: ICStub(ICStub::ToBool_NullUndefined, stubCode) {}
|
||||
|
||||
public:
|
||||
// Compiler for this stub kind.
|
||||
class Compiler : public ICStubCompiler {
|
||||
protected:
|
||||
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
|
||||
|
||||
public:
|
||||
explicit Compiler(JSContext* cx)
|
||||
: ICStubCompiler(cx, ICStub::ToBool_NullUndefined, Engine::Baseline) {}
|
||||
|
||||
ICStub* getStub(ICStubSpace* space) override {
|
||||
return newStub<ICToBool_NullUndefined>(space, getStubCode());
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class ICToBool_Double : public ICStub
|
||||
{
|
||||
friend class ICStubSpace;
|
||||
|
||||
explicit ICToBool_Double(JitCode* stubCode)
|
||||
: ICStub(ICStub::ToBool_Double, stubCode) {}
|
||||
|
||||
public:
|
||||
// Compiler for this stub kind.
|
||||
class Compiler : public ICStubCompiler {
|
||||
protected:
|
||||
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
|
||||
|
||||
public:
|
||||
explicit Compiler(JSContext* cx)
|
||||
: ICStubCompiler(cx, ICStub::ToBool_Double, Engine::Baseline) {}
|
||||
|
||||
ICStub* getStub(ICStubSpace* space) override {
|
||||
return newStub<ICToBool_Double>(space, getStubCode());
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class ICToBool_Object : public ICStub
|
||||
{
|
||||
friend class ICStubSpace;
|
||||
|
||||
explicit ICToBool_Object(JitCode* stubCode)
|
||||
: ICStub(ICStub::ToBool_Object, stubCode) {}
|
||||
|
||||
public:
|
||||
// Compiler for this stub kind.
|
||||
class Compiler : public ICStubCompiler {
|
||||
protected:
|
||||
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
|
||||
|
||||
public:
|
||||
explicit Compiler(JSContext* cx)
|
||||
: ICStubCompiler(cx, ICStub::ToBool_Object, Engine::Baseline) {}
|
||||
|
||||
ICStub* getStub(ICStubSpace* space) override {
|
||||
return newStub<ICToBool_Object>(space, getStubCode());
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// ToNumber
|
||||
// JSOP_POS
|
||||
|
||||
|
|
|
@ -31,11 +31,6 @@ namespace jit {
|
|||
_(NewObject_WithTemplate) \
|
||||
\
|
||||
_(ToBool_Fallback) \
|
||||
_(ToBool_Int32) \
|
||||
_(ToBool_String) \
|
||||
_(ToBool_NullUndefined) \
|
||||
_(ToBool_Double) \
|
||||
_(ToBool_Object) \
|
||||
\
|
||||
_(ToNumber_Fallback) \
|
||||
\
|
||||
|
|
|
@ -4143,7 +4143,11 @@ TypeOfIRGenerator::tryAttachPrimitive(ValOperandId valId)
|
|||
if (!val_.isPrimitive())
|
||||
return false;
|
||||
|
||||
writer.guardType(valId, val_.isNumber() ? JSVAL_TYPE_DOUBLE : val_.extractNonDoubleType());
|
||||
if (val_.isNumber())
|
||||
writer.guardIsNumber(valId);
|
||||
else
|
||||
writer.guardType(valId, val_.extractNonDoubleType());
|
||||
|
||||
writer.loadStringResult(TypeName(js::TypeOfValue(val_), cx_->names()));
|
||||
writer.returnFromIC();
|
||||
|
||||
|
@ -4682,3 +4686,144 @@ CompareIRGenerator::trackNotAttached()
|
|||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
ToBoolIRGenerator::ToBoolIRGenerator(JSContext* cx, HandleScript script, jsbytecode* pc, ICState::Mode mode,
|
||||
HandleValue val)
|
||||
: IRGenerator(cx, script, pc, CacheKind::ToBool, mode),
|
||||
val_(val)
|
||||
{}
|
||||
|
||||
void
|
||||
ToBoolIRGenerator::trackAttached(const char* name)
|
||||
{
|
||||
#ifdef JS_CACHEIR_SPEW
|
||||
CacheIRSpewer& sp = CacheIRSpewer::singleton();
|
||||
if (sp.enabled()) {
|
||||
LockGuard<Mutex> guard(sp.lock());
|
||||
sp.beginCache(guard, *this);
|
||||
sp.valueProperty(guard, "val", val_);
|
||||
sp.attached(guard, name);
|
||||
sp.endCache(guard);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
ToBoolIRGenerator::trackNotAttached()
|
||||
{
|
||||
#ifdef JS_CACHEIR_SPEW
|
||||
CacheIRSpewer& sp = CacheIRSpewer::singleton();
|
||||
if (sp.enabled()) {
|
||||
LockGuard<Mutex> guard(sp.lock());
|
||||
sp.beginCache(guard, *this);
|
||||
sp.valueProperty(guard, "val", val_);
|
||||
sp.endCache(guard);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
ToBoolIRGenerator::tryAttachStub()
|
||||
{
|
||||
AutoAssertNoPendingException aanpe(cx_);
|
||||
|
||||
if (tryAttachInt32())
|
||||
return true;
|
||||
if (tryAttachDouble())
|
||||
return true;
|
||||
if (tryAttachString())
|
||||
return true;
|
||||
if (tryAttachNullOrUndefined())
|
||||
return true;
|
||||
if (tryAttachObject())
|
||||
return true;
|
||||
if (tryAttachSymbol())
|
||||
return true;
|
||||
|
||||
trackNotAttached();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ToBoolIRGenerator::tryAttachInt32()
|
||||
{
|
||||
if (!val_.isInt32())
|
||||
return false;
|
||||
|
||||
ValOperandId valId(writer.setInputOperandId(0));
|
||||
writer.guardType(valId, JSVAL_TYPE_INT32);
|
||||
writer.loadInt32TruthyResult(valId);
|
||||
writer.returnFromIC();
|
||||
trackAttached("ToBoolInt32");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ToBoolIRGenerator::tryAttachDouble()
|
||||
{
|
||||
if (!val_.isDouble() || !cx_->runtime()->jitSupportsFloatingPoint)
|
||||
return false;
|
||||
|
||||
ValOperandId valId(writer.setInputOperandId(0));
|
||||
writer.guardType(valId, JSVAL_TYPE_DOUBLE);
|
||||
writer.loadDoubleTruthyResult(valId);
|
||||
writer.returnFromIC();
|
||||
trackAttached("ToBoolDouble");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ToBoolIRGenerator::tryAttachSymbol()
|
||||
{
|
||||
if (!val_.isSymbol())
|
||||
return false;
|
||||
|
||||
ValOperandId valId(writer.setInputOperandId(0));
|
||||
writer.guardType(valId, JSVAL_TYPE_SYMBOL);
|
||||
writer.loadBooleanResult(true);
|
||||
writer.returnFromIC();
|
||||
trackAttached("ToBoolSymbol");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ToBoolIRGenerator::tryAttachString()
|
||||
{
|
||||
if (!val_.isString())
|
||||
return false;
|
||||
|
||||
ValOperandId valId(writer.setInputOperandId(0));
|
||||
StringOperandId strId = writer.guardIsString(valId);
|
||||
writer.loadStringTruthyResult(strId);
|
||||
writer.returnFromIC();
|
||||
trackAttached("ToBoolString");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ToBoolIRGenerator::tryAttachNullOrUndefined()
|
||||
{
|
||||
if (!val_.isNullOrUndefined())
|
||||
return false;
|
||||
|
||||
ValOperandId valId(writer.setInputOperandId(0));
|
||||
writer.guardIsNullOrUndefined(valId);
|
||||
writer.loadBooleanResult(false);
|
||||
writer.returnFromIC();
|
||||
trackAttached("ToBoolNullOrUndefined");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ToBoolIRGenerator::tryAttachObject()
|
||||
{
|
||||
if (!val_.isObject())
|
||||
return false;
|
||||
|
||||
ValOperandId valId(writer.setInputOperandId(0));
|
||||
ObjOperandId objId = writer.guardIsObject(valId);
|
||||
writer.loadObjectTruthyResult(objId);
|
||||
writer.returnFromIC();
|
||||
trackAttached("ToBoolObject");
|
||||
return true;
|
||||
}
|
|
@ -151,6 +151,7 @@ class TypedOperandId : public OperandId
|
|||
_(InstanceOf) \
|
||||
_(GetIterator) \
|
||||
_(Compare) \
|
||||
_(ToBool) \
|
||||
_(Call)
|
||||
|
||||
enum class CacheKind : uint8_t
|
||||
|
@ -165,8 +166,10 @@ extern const char* CacheKindNames[];
|
|||
#define CACHE_IR_OPS(_) \
|
||||
_(GuardIsObject) \
|
||||
_(GuardIsObjectOrNull) \
|
||||
_(GuardIsNullOrUndefined) \
|
||||
_(GuardIsString) \
|
||||
_(GuardIsSymbol) \
|
||||
_(GuardIsNumber) \
|
||||
_(GuardIsInt32Index) \
|
||||
_(GuardType) \
|
||||
_(GuardShape) \
|
||||
|
@ -268,6 +271,10 @@ extern const char* CacheKindNames[];
|
|||
_(LoadStringResult) \
|
||||
_(LoadInstanceOfObjectResult) \
|
||||
_(LoadTypeOfObjectResult) \
|
||||
_(LoadInt32TruthyResult) \
|
||||
_(LoadDoubleTruthyResult) \
|
||||
_(LoadStringTruthyResult) \
|
||||
_(LoadObjectTruthyResult) \
|
||||
\
|
||||
_(CallStringSplitResult) \
|
||||
\
|
||||
|
@ -520,6 +527,9 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter
|
|||
writeOperandId(res);
|
||||
return res;
|
||||
}
|
||||
void guardIsNumber(ValOperandId val) {
|
||||
writeOpWithOperandId(CacheOp::GuardIsNumber, val);
|
||||
}
|
||||
void guardType(ValOperandId val, JSValueType type) {
|
||||
writeOpWithOperandId(CacheOp::GuardType, val);
|
||||
static_assert(sizeof(type) == sizeof(uint8_t), "JSValueType should fit in a byte");
|
||||
|
@ -528,6 +538,9 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter
|
|||
void guardIsObjectOrNull(ValOperandId val) {
|
||||
writeOpWithOperandId(CacheOp::GuardIsObjectOrNull, val);
|
||||
}
|
||||
void guardIsNullOrUndefined(ValOperandId val) {
|
||||
writeOpWithOperandId(CacheOp::GuardIsNullOrUndefined, val);
|
||||
}
|
||||
void guardShape(ObjOperandId obj, Shape* shape) {
|
||||
writeOpWithOperandId(CacheOp::GuardShape, obj);
|
||||
addStubField(uintptr_t(shape), StubField::Type::Shape);
|
||||
|
@ -1009,6 +1022,18 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter
|
|||
void loadTypeOfObjectResult(ObjOperandId obj) {
|
||||
writeOpWithOperandId(CacheOp::LoadTypeOfObjectResult, obj);
|
||||
}
|
||||
void loadInt32TruthyResult(ValOperandId integer) {
|
||||
writeOpWithOperandId(CacheOp::LoadInt32TruthyResult, integer);
|
||||
}
|
||||
void loadDoubleTruthyResult(ValOperandId dbl) {
|
||||
writeOpWithOperandId(CacheOp::LoadDoubleTruthyResult, dbl);
|
||||
}
|
||||
void loadStringTruthyResult(StringOperandId str) {
|
||||
writeOpWithOperandId(CacheOp::LoadStringTruthyResult, str);
|
||||
}
|
||||
void loadObjectTruthyResult(ObjOperandId obj) {
|
||||
writeOpWithOperandId(CacheOp::LoadObjectTruthyResult, obj);
|
||||
}
|
||||
void callStringSplitResult(StringOperandId str, StringOperandId sep, ObjectGroup* group) {
|
||||
writeOp(CacheOp::CallStringSplitResult);
|
||||
writeOperandId(str);
|
||||
|
@ -1596,6 +1621,27 @@ class MOZ_RAII CompareIRGenerator : public IRGenerator
|
|||
bool tryAttachStub();
|
||||
};
|
||||
|
||||
class MOZ_RAII ToBoolIRGenerator : public IRGenerator
|
||||
{
|
||||
HandleValue val_;
|
||||
|
||||
bool tryAttachInt32();
|
||||
bool tryAttachDouble();
|
||||
bool tryAttachString();
|
||||
bool tryAttachSymbol();
|
||||
bool tryAttachNullOrUndefined();
|
||||
bool tryAttachObject();
|
||||
|
||||
void trackAttached(const char* name);
|
||||
void trackNotAttached();
|
||||
|
||||
public:
|
||||
ToBoolIRGenerator(JSContext* cx, HandleScript, jsbytecode* pc, ICState::Mode mode,
|
||||
HandleValue val);
|
||||
|
||||
bool tryAttachStub();
|
||||
};
|
||||
|
||||
} // namespace jit
|
||||
} // namespace js
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "jit/IonIC.h"
|
||||
#include "jit/SharedICHelpers.h"
|
||||
|
||||
#include "jsboolinlines.h"
|
||||
#include "jscompartmentinlines.h"
|
||||
|
||||
#include "jit/MacroAssembler-inl.h"
|
||||
|
@ -1205,6 +1206,25 @@ CacheIRCompiler::emitFailurePath(size_t index)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CacheIRCompiler::emitGuardIsNumber()
|
||||
{
|
||||
ValOperandId inputId = reader.valOperandId();
|
||||
JSValueType knownType = allocator.knownType(inputId);
|
||||
|
||||
// Doubles and ints are numbers!
|
||||
if (knownType == JSVAL_TYPE_DOUBLE || knownType == JSVAL_TYPE_INT32)
|
||||
return true;
|
||||
|
||||
ValueOperand input = allocator.useValueRegister(masm, inputId);
|
||||
FailurePath* failure;
|
||||
if (!addFailurePath(&failure))
|
||||
return false;
|
||||
|
||||
masm.branchTestNumber(Assembler::NotEqual, input, failure->label());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CacheIRCompiler::emitGuardIsObject()
|
||||
{
|
||||
|
@ -1220,6 +1240,27 @@ CacheIRCompiler::emitGuardIsObject()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CacheIRCompiler::emitGuardIsNullOrUndefined()
|
||||
{
|
||||
ValOperandId inputId = reader.valOperandId();
|
||||
JSValueType knownType = allocator.knownType(inputId);
|
||||
if (knownType == JSVAL_TYPE_UNDEFINED || knownType == JSVAL_TYPE_NULL)
|
||||
return true;
|
||||
|
||||
ValueOperand input = allocator.useValueRegister(masm, inputId);
|
||||
FailurePath* failure;
|
||||
if (!addFailurePath(&failure))
|
||||
return false;
|
||||
|
||||
Label success;
|
||||
masm.branchTestNull(Assembler::Equal, input, &success);
|
||||
masm.branchTestUndefined(Assembler::NotEqual, input, failure->label());
|
||||
|
||||
masm.bind(&success);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CacheIRCompiler::emitGuardIsObjectOrNull()
|
||||
{
|
||||
|
@ -1350,7 +1391,7 @@ CacheIRCompiler::emitGuardType()
|
|||
masm.branchTestInt32(Assembler::NotEqual, input, failure->label());
|
||||
break;
|
||||
case JSVAL_TYPE_DOUBLE:
|
||||
masm.branchTestNumber(Assembler::NotEqual, input, failure->label());
|
||||
masm.branchTestDouble(Assembler::NotEqual, input, failure->label());
|
||||
break;
|
||||
case JSVAL_TYPE_BOOLEAN:
|
||||
masm.branchTestBoolean(Assembler::NotEqual, input, failure->label());
|
||||
|
@ -1842,7 +1883,7 @@ CacheIRCompiler::emitLoadStringCharResult()
|
|||
// Bounds check, load string char.
|
||||
masm.boundsCheck32ForLoad(index, Address(str, JSString::offsetOfLength()), scratch1,
|
||||
failure->label());
|
||||
masm.loadStringChar(str, index, scratch1, failure->label());
|
||||
masm.loadStringChar(str, index, scratch1, scratch2, failure->label());
|
||||
|
||||
// Load StaticString for this char.
|
||||
masm.boundsCheck32PowerOfTwo(scratch1, StaticStrings::UNIT_STATIC_LIMIT, failure->label());
|
||||
|
@ -2273,6 +2314,98 @@ CacheIRCompiler::emitLoadTypeOfObjectResult()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CacheIRCompiler::emitLoadInt32TruthyResult()
|
||||
{
|
||||
AutoOutputRegister output(*this);
|
||||
ValueOperand val = allocator.useValueRegister(masm, reader.valOperandId());
|
||||
|
||||
Label ifFalse, done;
|
||||
masm.branchTestInt32Truthy(false, val, &ifFalse);
|
||||
masm.moveValue(BooleanValue(true), output.valueReg());
|
||||
masm.jump(&done);
|
||||
|
||||
masm.bind(&ifFalse);
|
||||
masm.moveValue(BooleanValue(false), output.valueReg());
|
||||
|
||||
masm.bind(&done);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CacheIRCompiler::emitLoadStringTruthyResult()
|
||||
{
|
||||
AutoOutputRegister output(*this);
|
||||
Register str = allocator.useRegister(masm, reader.stringOperandId());
|
||||
|
||||
Label ifFalse, done;
|
||||
masm.branch32(Assembler::Equal, Address(str, JSString::offsetOfLength()), Imm32(0), &ifFalse);
|
||||
masm.moveValue(BooleanValue(true), output.valueReg());
|
||||
masm.jump(&done);
|
||||
|
||||
masm.bind(&ifFalse);
|
||||
masm.moveValue(BooleanValue(false), output.valueReg());
|
||||
|
||||
masm.bind(&done);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CacheIRCompiler::emitLoadDoubleTruthyResult()
|
||||
{
|
||||
AutoOutputRegister output(*this);
|
||||
ValueOperand val = allocator.useValueRegister(masm, reader.valOperandId());
|
||||
|
||||
Label ifFalse, done, failurePopReg;
|
||||
|
||||
// If we're compiling a Baseline IC, FloatReg0 is always available.
|
||||
if (mode_ != Mode::Baseline)
|
||||
masm.push(FloatReg0);
|
||||
|
||||
masm.unboxDouble(val, FloatReg0);
|
||||
|
||||
masm.branchTestDoubleTruthy(false, FloatReg0, &ifFalse);
|
||||
masm.moveValue(BooleanValue(true), output.valueReg());
|
||||
masm.jump(&done);
|
||||
|
||||
masm.bind(&ifFalse);
|
||||
masm.moveValue(BooleanValue(false), output.valueReg());
|
||||
|
||||
if (mode_ != Mode::Baseline)
|
||||
masm.pop(FloatReg0);
|
||||
masm.bind(&done);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CacheIRCompiler::emitLoadObjectTruthyResult()
|
||||
{
|
||||
AutoOutputRegister output(*this);
|
||||
Register obj = allocator.useRegister(masm, reader.objOperandId());
|
||||
AutoScratchRegisterMaybeOutput scratch(allocator, masm, output);
|
||||
|
||||
|
||||
Label emulatesUndefined, slowPath, done;
|
||||
masm.branchIfObjectEmulatesUndefined(obj, scratch, &slowPath, &emulatesUndefined);
|
||||
masm.moveValue(BooleanValue(true), output.valueReg());
|
||||
masm.jump(&done);
|
||||
|
||||
masm.bind(&emulatesUndefined);
|
||||
masm.moveValue(BooleanValue(false), output.valueReg());
|
||||
masm.jump(&done);
|
||||
|
||||
masm.bind(&slowPath);
|
||||
masm.setupUnalignedABICall(scratch);
|
||||
masm.passABIArg(obj);
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, js::EmulatesUndefined));
|
||||
masm.convertBoolToInt32(ReturnReg, ReturnReg);
|
||||
masm.xor32(Imm32(1), ReturnReg);
|
||||
masm.tagValue(JSVAL_TYPE_BOOLEAN, ReturnReg, output.valueReg());
|
||||
|
||||
masm.bind(&done);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CacheIRCompiler::emitCompareStringResult()
|
||||
{
|
||||
|
@ -2684,4 +2817,4 @@ CacheIRCompiler::emitLoadInstanceOfObjectResult()
|
|||
//fallthrough
|
||||
masm.bind(&done);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,9 +16,11 @@ namespace jit {
|
|||
// BaselineCacheIRCompiler and IonCacheIRCompiler.
|
||||
#define CACHE_IR_SHARED_OPS(_) \
|
||||
_(GuardIsObject) \
|
||||
_(GuardIsNullOrUndefined) \
|
||||
_(GuardIsObjectOrNull) \
|
||||
_(GuardIsString) \
|
||||
_(GuardIsSymbol) \
|
||||
_(GuardIsNumber) \
|
||||
_(GuardIsInt32Index) \
|
||||
_(GuardType) \
|
||||
_(GuardClass) \
|
||||
|
@ -56,6 +58,10 @@ namespace jit {
|
|||
_(LoadTypedElementResult) \
|
||||
_(LoadObjectResult) \
|
||||
_(LoadTypeOfObjectResult) \
|
||||
_(LoadInt32TruthyResult) \
|
||||
_(LoadDoubleTruthyResult) \
|
||||
_(LoadStringTruthyResult) \
|
||||
_(LoadObjectTruthyResult) \
|
||||
_(CompareStringResult) \
|
||||
_(CompareObjectResult) \
|
||||
_(CompareSymbolResult) \
|
||||
|
|
|
@ -358,6 +358,7 @@ CodeGenerator::visitOutOfLineICFallback(OutOfLineICFallback* ool)
|
|||
case CacheKind::Call:
|
||||
case CacheKind::Compare:
|
||||
case CacheKind::TypeOf:
|
||||
case CacheKind::ToBool:
|
||||
MOZ_CRASH("Unsupported IC");
|
||||
}
|
||||
MOZ_CRASH();
|
||||
|
@ -7603,6 +7604,93 @@ CodeGenerator::visitIsNullOrLikeUndefinedAndBranchT(LIsNullOrLikeUndefinedAndBra
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
CodeGenerator::emitSameValue(FloatRegister left, FloatRegister right, FloatRegister temp,
|
||||
Register output)
|
||||
{
|
||||
Label nonEqual, isSameValue, isNotSameValue;
|
||||
masm.branchDouble(Assembler::DoubleNotEqualOrUnordered, left, right, &nonEqual);
|
||||
{
|
||||
// First, test for being equal to 0.0, which also includes -0.0.
|
||||
masm.loadConstantDouble(0.0, temp);
|
||||
masm.branchDouble(Assembler::DoubleNotEqual, left, temp, &isSameValue);
|
||||
|
||||
// The easiest way to distinguish -0.0 from 0.0 is that 1.0/-0.0
|
||||
// is -Infinity instead of Infinity.
|
||||
Label isNegInf;
|
||||
masm.loadConstantDouble(1.0, temp);
|
||||
masm.divDouble(left, temp);
|
||||
masm.branchDouble(Assembler::DoubleLessThan, temp, left, &isNegInf);
|
||||
{
|
||||
masm.loadConstantDouble(1.0, temp);
|
||||
masm.divDouble(right, temp);
|
||||
masm.branchDouble(Assembler::DoubleGreaterThan, temp, right, &isSameValue);
|
||||
masm.jump(&isNotSameValue);
|
||||
}
|
||||
masm.bind(&isNegInf);
|
||||
{
|
||||
masm.loadConstantDouble(1.0, temp);
|
||||
masm.divDouble(right, temp);
|
||||
masm.branchDouble(Assembler::DoubleLessThan, temp, right, &isSameValue);
|
||||
masm.jump(&isNotSameValue);
|
||||
}
|
||||
}
|
||||
masm.bind(&nonEqual);
|
||||
{
|
||||
// Test if both values are NaN.
|
||||
masm.branchDouble(Assembler::DoubleOrdered, left, left, &isNotSameValue);
|
||||
masm.branchDouble(Assembler::DoubleOrdered, right, right, &isNotSameValue);
|
||||
}
|
||||
|
||||
Label done;
|
||||
masm.bind(&isSameValue);
|
||||
masm.move32(Imm32(1), output);
|
||||
masm.jump(&done);
|
||||
|
||||
masm.bind(&isNotSameValue);
|
||||
masm.move32(Imm32(0), output);
|
||||
|
||||
masm.bind(&done);
|
||||
}
|
||||
|
||||
void
|
||||
CodeGenerator::visitSameValueD(LSameValueD* lir)
|
||||
{
|
||||
FloatRegister left = ToFloatRegister(lir->left());
|
||||
FloatRegister right = ToFloatRegister(lir->right());
|
||||
FloatRegister temp = ToFloatRegister(lir->tempFloat());
|
||||
Register output = ToRegister(lir->output());
|
||||
|
||||
emitSameValue(left, right, temp, output);
|
||||
}
|
||||
|
||||
void
|
||||
CodeGenerator::visitSameValueV(LSameValueV* lir)
|
||||
{
|
||||
ValueOperand left = ToValue(lir, LSameValueV::LhsInput);
|
||||
FloatRegister right = ToFloatRegister(lir->right());
|
||||
FloatRegister temp1 = ToFloatRegister(lir->tempFloat1());
|
||||
FloatRegister temp2 = ToFloatRegister(lir->tempFloat2());
|
||||
Register output = ToRegister(lir->output());
|
||||
|
||||
Label nonDouble;
|
||||
masm.move32(Imm32(0), output);
|
||||
masm.ensureDouble(left, temp1, &nonDouble);
|
||||
emitSameValue(temp1, right, temp2, output);
|
||||
masm.bind(&nonDouble);
|
||||
}
|
||||
|
||||
typedef bool (*SameValueFn)(JSContext*, HandleValue, HandleValue, bool*);
|
||||
static const VMFunction SameValueInfo = FunctionInfo<SameValueFn>(js::SameValue, "SameValue");
|
||||
|
||||
void
|
||||
CodeGenerator::visitSameValueVM(LSameValueVM* lir)
|
||||
{
|
||||
pushArg(ToValue(lir, LSameValueVM::RhsInput));
|
||||
pushArg(ToValue(lir, LSameValueVM::LhsInput));
|
||||
callVM(SameValueInfo, lir);
|
||||
}
|
||||
|
||||
typedef JSString* (*ConcatStringsFn)(JSContext*, HandleString, HandleString);
|
||||
static const VMFunction ConcatStringsInfo =
|
||||
FunctionInfo<ConcatStringsFn>(ConcatStrings<CanGC>, "ConcatStrings");
|
||||
|
@ -8167,9 +8255,10 @@ CodeGenerator::visitCharCodeAt(LCharCodeAt* lir)
|
|||
Register str = ToRegister(lir->str());
|
||||
Register index = ToRegister(lir->index());
|
||||
Register output = ToRegister(lir->output());
|
||||
Register temp = ToRegister(lir->temp());
|
||||
|
||||
OutOfLineCode* ool = oolCallVM(CharCodeAtInfo, lir, ArgList(str, index), StoreRegisterTo(output));
|
||||
masm.loadStringChar(str, index, output, ool->entry());
|
||||
masm.loadStringChar(str, index, output, temp, ool->entry());
|
||||
masm.bind(ool->rejoin());
|
||||
}
|
||||
|
||||
|
|
|
@ -284,6 +284,11 @@ class CodeGenerator final : public CodeGeneratorSpecific
|
|||
void visitIsNullOrLikeUndefinedT(LIsNullOrLikeUndefinedT* lir) override;
|
||||
void visitIsNullOrLikeUndefinedAndBranchV(LIsNullOrLikeUndefinedAndBranchV* lir) override;
|
||||
void visitIsNullOrLikeUndefinedAndBranchT(LIsNullOrLikeUndefinedAndBranchT* lir) override;
|
||||
void emitSameValue(FloatRegister left, FloatRegister right, FloatRegister temp,
|
||||
Register output);
|
||||
void visitSameValueD(LSameValueD* lir) override;
|
||||
void visitSameValueV(LSameValueV* lir) override;
|
||||
void visitSameValueVM(LSameValueVM* lir) override;
|
||||
void emitConcat(LInstruction* lir, Register lhs, Register rhs, Register output);
|
||||
void visitConcat(LConcat* lir) override;
|
||||
void visitCharCodeAt(LCharCodeAt* lir) override;
|
||||
|
|
|
@ -94,6 +94,7 @@
|
|||
\
|
||||
_(Object) \
|
||||
_(ObjectCreate) \
|
||||
_(ObjectIs) \
|
||||
_(ObjectToString) \
|
||||
\
|
||||
_(SimdInt32x4) \
|
||||
|
|
|
@ -5736,7 +5736,7 @@ IonBuilder::jsop_compare(JSOp op, MDefinition* left, MDefinition* right)
|
|||
startTrackingOptimizations();
|
||||
|
||||
if (!forceInlineCaches()) {
|
||||
MOZ_TRY(compareTrySpecialized(&emitted, op, left, right));
|
||||
MOZ_TRY(compareTrySpecialized(&emitted, op, left, right, true));
|
||||
if (emitted)
|
||||
return Ok();
|
||||
MOZ_TRY(compareTryBitwise(&emitted, op, left, right));
|
||||
|
@ -5779,16 +5779,19 @@ ObjectOrSimplePrimitive(MDefinition* op)
|
|||
}
|
||||
|
||||
AbortReasonOr<Ok>
|
||||
IonBuilder::compareTrySpecialized(bool* emitted, JSOp op, MDefinition* left, MDefinition* right)
|
||||
IonBuilder::compareTrySpecialized(bool* emitted, JSOp op, MDefinition* left, MDefinition* right,
|
||||
bool canTrackOptimization)
|
||||
{
|
||||
MOZ_ASSERT(*emitted == false);
|
||||
trackOptimizationAttempt(TrackedStrategy::Compare_SpecializedTypes);
|
||||
if (canTrackOptimization)
|
||||
trackOptimizationAttempt(TrackedStrategy::Compare_SpecializedTypes);
|
||||
|
||||
// Try to emit an compare based on the input types.
|
||||
|
||||
MCompare::CompareType type = MCompare::determineCompareType(op, left, right);
|
||||
if (type == MCompare::Compare_Unknown) {
|
||||
trackOptimizationOutcome(TrackedOutcome::SpeculationOnInputTypesFailed);
|
||||
if (canTrackOptimization)
|
||||
trackOptimizationOutcome(TrackedOutcome::SpeculationOnInputTypesFailed);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
|
@ -5815,7 +5818,8 @@ IonBuilder::compareTrySpecialized(bool* emitted, JSOp op, MDefinition* left, MDe
|
|||
current->push(ins);
|
||||
|
||||
MOZ_ASSERT(!ins->isEffectful());
|
||||
trackOptimizationSuccess();
|
||||
if (canTrackOptimization)
|
||||
trackOptimizationSuccess();
|
||||
*emitted = true;
|
||||
return Ok();
|
||||
}
|
||||
|
|
|
@ -328,7 +328,7 @@ class IonBuilder
|
|||
|
||||
// jsop_compare helpers.
|
||||
AbortReasonOr<Ok> compareTrySpecialized(bool* emitted, JSOp op, MDefinition* left,
|
||||
MDefinition* right);
|
||||
MDefinition* right, bool canTrackOptimization);
|
||||
AbortReasonOr<Ok> compareTryBitwise(bool* emitted, JSOp op, MDefinition* left,
|
||||
MDefinition* right);
|
||||
AbortReasonOr<Ok> compareTrySpecializedOnBaselineInspector(bool* emitted, JSOp op,
|
||||
|
@ -697,6 +697,7 @@ class IonBuilder
|
|||
// Object natives and intrinsics.
|
||||
InliningResult inlineObject(CallInfo& callInfo);
|
||||
InliningResult inlineObjectCreate(CallInfo& callInfo);
|
||||
InliningResult inlineObjectIs(CallInfo& callInfo);
|
||||
InliningResult inlineObjectToString(CallInfo& callInfo);
|
||||
InliningResult inlineDefineDataProperty(CallInfo& callInfo);
|
||||
|
||||
|
|
|
@ -546,6 +546,7 @@ IonCacheIRCompiler::init()
|
|||
case CacheKind::Call:
|
||||
case CacheKind::Compare:
|
||||
case CacheKind::TypeOf:
|
||||
case CacheKind::ToBool:
|
||||
MOZ_CRASH("Unsupported IC");
|
||||
}
|
||||
|
||||
|
|
|
@ -63,6 +63,7 @@ IonIC::scratchRegisterForEntryJump()
|
|||
case CacheKind::Call:
|
||||
case CacheKind::Compare:
|
||||
case CacheKind::TypeOf:
|
||||
case CacheKind::ToBool:
|
||||
MOZ_CRASH("Unsupported IC");
|
||||
}
|
||||
|
||||
|
|
|
@ -1167,6 +1167,33 @@ LIRGenerator::visitCompare(MCompare* comp)
|
|||
MOZ_CRASH("Unrecognized compare type.");
|
||||
}
|
||||
|
||||
void
|
||||
LIRGenerator::visitSameValue(MSameValue* ins)
|
||||
{
|
||||
MDefinition* lhs = ins->lhs();
|
||||
MDefinition* rhs = ins->rhs();
|
||||
|
||||
if (lhs->type() == MIRType::Double && rhs->type() == MIRType::Double) {
|
||||
auto* lir = new(alloc()) LSameValueD(useRegister(lhs), useRegister(rhs), tempDouble());
|
||||
define(lir, ins);
|
||||
return;
|
||||
}
|
||||
|
||||
if (lhs->type() == MIRType::Value && rhs->type() == MIRType::Double) {
|
||||
auto* lir = new(alloc()) LSameValueV(useBox(lhs), useRegister(rhs), tempDouble(),
|
||||
tempDouble());
|
||||
define(lir, ins);
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(lhs->type() == MIRType::Value);
|
||||
MOZ_ASSERT(rhs->type() == MIRType::Value);
|
||||
|
||||
auto* lir = new(alloc()) LSameValueVM(useBoxAtStart(lhs), useBoxAtStart(rhs));
|
||||
defineReturn(lir, ins);
|
||||
assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
void
|
||||
LIRGenerator::lowerBitOp(JSOp op, MInstruction* ins)
|
||||
{
|
||||
|
@ -1971,7 +1998,7 @@ LIRGenerator::visitCharCodeAt(MCharCodeAt* ins)
|
|||
MOZ_ASSERT(str->type() == MIRType::String);
|
||||
MOZ_ASSERT(idx->type() == MIRType::Int32);
|
||||
|
||||
LCharCodeAt* lir = new(alloc()) LCharCodeAt(useRegister(str), useRegister(idx));
|
||||
LCharCodeAt* lir = new(alloc()) LCharCodeAt(useRegister(str), useRegister(idx), temp());
|
||||
define(lir, ins);
|
||||
assignSafepoint(lir, ins);
|
||||
}
|
||||
|
|
|
@ -120,6 +120,7 @@ class LIRGenerator : public LIRGeneratorSpecific
|
|||
void visitFunctionDispatch(MFunctionDispatch* ins) override;
|
||||
void visitObjectGroupDispatch(MObjectGroupDispatch* ins) override;
|
||||
void visitCompare(MCompare* comp) override;
|
||||
void visitSameValue(MSameValue* comp) override;
|
||||
void visitTypeOf(MTypeOf* ins) override;
|
||||
void visitToAsync(MToAsync* ins) override;
|
||||
void visitToAsyncGen(MToAsyncGen* ins) override;
|
||||
|
|
|
@ -252,6 +252,8 @@ IonBuilder::inlineNativeCall(CallInfo& callInfo, JSFunction* target)
|
|||
return inlineObject(callInfo);
|
||||
case InlinableNative::ObjectCreate:
|
||||
return inlineObjectCreate(callInfo);
|
||||
case InlinableNative::ObjectIs:
|
||||
return inlineObjectIs(callInfo);
|
||||
case InlinableNative::ObjectToString:
|
||||
return inlineObjectToString(callInfo);
|
||||
|
||||
|
@ -2381,6 +2383,68 @@ IonBuilder::inlineObjectCreate(CallInfo& callInfo)
|
|||
return InliningStatus_Inlined;
|
||||
}
|
||||
|
||||
IonBuilder::InliningResult
|
||||
IonBuilder::inlineObjectIs(CallInfo& callInfo)
|
||||
{
|
||||
if (callInfo.argc() < 2 || callInfo.constructing())
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
if (getInlineReturnType() != MIRType::Boolean)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
MDefinition* left = callInfo.getArg(0);
|
||||
MDefinition* right = callInfo.getArg(1);
|
||||
MIRType leftType = left->type();
|
||||
MIRType rightType = right->type();
|
||||
|
||||
bool strictEq;
|
||||
bool incompatibleTypes = false;
|
||||
if (leftType == rightType) {
|
||||
// We can only compare the arguments with strict-equals semantics if
|
||||
// they aren't floating-point types or values. Otherwise we need to
|
||||
// use MSameValue.
|
||||
strictEq = !(IsFloatingPointType(leftType) || leftType == MIRType::Value);
|
||||
} else if (leftType == MIRType::Value) {
|
||||
// Also use strict-equals when comparing a value with a non-number.
|
||||
strictEq = !IsNumberType(rightType);
|
||||
} else if (rightType == MIRType::Value) {
|
||||
// Dual case to the previous one, only with reversed operands.
|
||||
strictEq = !IsNumberType(leftType);
|
||||
} else if (IsNumberType(leftType) && IsNumberType(rightType)) {
|
||||
// Both arguments are numbers, but with different representations. We
|
||||
// can't use strict-equals semantics to compare the operands, but
|
||||
// instead need to use MSameValue.
|
||||
strictEq = false;
|
||||
} else {
|
||||
incompatibleTypes = true;
|
||||
}
|
||||
|
||||
if (incompatibleTypes) {
|
||||
// The result is always |false| when comparing incompatible types.
|
||||
pushConstant(BooleanValue(false));
|
||||
} else {
|
||||
bool emitted = false;
|
||||
if (strictEq) {
|
||||
// Specialize |Object.is(lhs, rhs)| as |lhs === rhs|.
|
||||
MOZ_TRY(compareTrySpecialized(&emitted, JSOP_STRICTEQ, left, right, false));
|
||||
}
|
||||
|
||||
if (!emitted) {
|
||||
MSameValue* ins = MSameValue::New(alloc(), left, right);
|
||||
|
||||
// The more specific operand is expected to be in the rhs.
|
||||
if (IsNumberType(leftType) && rightType == MIRType::Value)
|
||||
ins->swapOperands();
|
||||
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
}
|
||||
}
|
||||
|
||||
callInfo.setImplicitlyUsedUnchecked();
|
||||
return InliningStatus_Inlined;
|
||||
}
|
||||
|
||||
IonBuilder::InliningResult
|
||||
IonBuilder::inlineObjectToString(CallInfo& callInfo)
|
||||
{
|
||||
|
|
|
@ -4811,6 +4811,31 @@ class MCompare
|
|||
}
|
||||
};
|
||||
|
||||
class MSameValue
|
||||
: public MBinaryInstruction,
|
||||
public SameValuePolicy::Data
|
||||
{
|
||||
MSameValue(MDefinition* left, MDefinition* right)
|
||||
: MBinaryInstruction(classOpcode, left, right)
|
||||
{
|
||||
setResultType(MIRType::Boolean);
|
||||
setMovable();
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(SameValue)
|
||||
TRIVIAL_NEW_WRAPPERS
|
||||
|
||||
bool congruentTo(const MDefinition* ins) const override {
|
||||
return congruentIfOperandsEqual(ins);
|
||||
}
|
||||
AliasSet getAliasSet() const override {
|
||||
return AliasSet::None();
|
||||
}
|
||||
|
||||
ALLOW_CLONE(MSameValue)
|
||||
};
|
||||
|
||||
// Takes a typed value and returns an untyped value.
|
||||
class MBox
|
||||
: public MUnaryInstruction,
|
||||
|
|
|
@ -44,6 +44,7 @@ namespace jit {
|
|||
_(ObjectGroupDispatch) \
|
||||
_(FunctionDispatch) \
|
||||
_(Compare) \
|
||||
_(SameValue) \
|
||||
_(Phi) \
|
||||
_(Beta) \
|
||||
_(NaNToZero) \
|
||||
|
|
|
@ -1383,11 +1383,13 @@ MacroAssembler::loadStringChars(Register str, Register dest)
|
|||
}
|
||||
|
||||
void
|
||||
MacroAssembler::loadStringChar(Register str, Register index, Register output, Label* fail)
|
||||
MacroAssembler::loadStringChar(Register str, Register index, Register output, Register scratch,
|
||||
Label* fail)
|
||||
{
|
||||
MOZ_ASSERT(str != output);
|
||||
MOZ_ASSERT(str != index);
|
||||
MOZ_ASSERT(index != output);
|
||||
MOZ_ASSERT(output != scratch);
|
||||
|
||||
movePtr(str, output);
|
||||
|
||||
|
@ -1400,17 +1402,7 @@ MacroAssembler::loadStringChar(Register str, Register index, Register output, La
|
|||
|
||||
// Check if the index is contained in the leftChild.
|
||||
// Todo: Handle index in the rightChild.
|
||||
Label failPopStr, inLeft;
|
||||
push(str);
|
||||
boundsCheck32ForLoad(index, Address(output, JSString::offsetOfLength()), str, &failPopStr);
|
||||
pop(str);
|
||||
jump(&inLeft);
|
||||
|
||||
bind(&failPopStr);
|
||||
pop(str);
|
||||
jump(fail);
|
||||
|
||||
bind(&inLeft);
|
||||
boundsCheck32ForLoad(index, Address(output, JSString::offsetOfLength()), scratch, fail);
|
||||
|
||||
// If the left side is another rope, give up.
|
||||
branchIfRope(output, fail);
|
||||
|
@ -3468,7 +3460,6 @@ void
|
|||
MacroAssembler::computeSpectreIndexMask(Register index, Register length, Register output)
|
||||
{
|
||||
MOZ_ASSERT(JitOptions.spectreIndexMasking);
|
||||
MOZ_ASSERT(index != length);
|
||||
MOZ_ASSERT(length != output);
|
||||
MOZ_ASSERT(index != output);
|
||||
|
||||
|
@ -3513,7 +3504,6 @@ MacroAssembler::spectreMaskIndex(int32_t index, const Address& length, Register
|
|||
void
|
||||
MacroAssembler::spectreMaskIndex(Register index, Register length, Register output)
|
||||
{
|
||||
MOZ_ASSERT(index != length);
|
||||
MOZ_ASSERT(length != output);
|
||||
MOZ_ASSERT(index != output);
|
||||
|
||||
|
|
|
@ -1834,7 +1834,8 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
}
|
||||
|
||||
void loadStringChars(Register str, Register dest);
|
||||
void loadStringChar(Register str, Register index, Register output, Label* fail);
|
||||
void loadStringChar(Register str, Register index, Register output, Register scratch,
|
||||
Label* fail);
|
||||
|
||||
void loadStringIndexValue(Register str, Register dest, Label* fail);
|
||||
|
||||
|
|
|
@ -99,7 +99,7 @@ ArithPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
|
|||
}
|
||||
|
||||
bool
|
||||
AllDoublePolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
|
||||
AllDoublePolicy::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins)
|
||||
{
|
||||
for (size_t i = 0, e = ins->numOperands(); i < e; i++) {
|
||||
MDefinition* in = ins->getOperand(i);
|
||||
|
@ -268,6 +268,37 @@ ComparePolicy::adjustInputs(TempAllocator& alloc, MInstruction* def)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SameValuePolicy::adjustInputs(TempAllocator& alloc, MInstruction* def)
|
||||
{
|
||||
MOZ_ASSERT(def->isSameValue());
|
||||
MSameValue* sameValue = def->toSameValue();
|
||||
MIRType lhsType = sameValue->lhs()->type();
|
||||
MIRType rhsType = sameValue->rhs()->type();
|
||||
|
||||
// If both operands are numbers, convert them to doubles.
|
||||
if (IsNumberType(lhsType) && IsNumberType(rhsType))
|
||||
return AllDoublePolicy::staticAdjustInputs(alloc, def);
|
||||
|
||||
// SameValue(Anything, Double) is specialized, so convert the rhs if it's
|
||||
// not already a double.
|
||||
if (lhsType == MIRType::Value && IsNumberType(rhsType)) {
|
||||
if (rhsType != MIRType::Double) {
|
||||
MInstruction* replace = MToDouble::New(alloc, sameValue->rhs());
|
||||
def->block()->insertBefore(def, replace);
|
||||
def->replaceOperand(1, replace);
|
||||
|
||||
if (!replace->typePolicy()->adjustInputs(alloc, replace))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise box both operands.
|
||||
return BoxInputsPolicy::staticAdjustInputs(alloc, def);
|
||||
}
|
||||
|
||||
bool
|
||||
TypeBarrierPolicy::adjustInputs(TempAllocator& alloc, MInstruction* def)
|
||||
{
|
||||
|
@ -1204,6 +1235,7 @@ FilterTypeSetPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
|
|||
_(FilterTypeSetPolicy) \
|
||||
_(InstanceOfPolicy) \
|
||||
_(PowPolicy) \
|
||||
_(SameValuePolicy) \
|
||||
_(SimdAllPolicy) \
|
||||
_(SimdSelectPolicy) \
|
||||
_(SimdShufflePolicy) \
|
||||
|
|
|
@ -99,7 +99,10 @@ class AllDoublePolicy final : public TypePolicy
|
|||
{
|
||||
public:
|
||||
EMPTY_DATA_;
|
||||
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) override;
|
||||
static MOZ_MUST_USE bool staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
|
||||
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) override {
|
||||
return staticAdjustInputs(alloc, def);
|
||||
}
|
||||
};
|
||||
|
||||
class BitwisePolicy final : public TypePolicy
|
||||
|
@ -116,6 +119,13 @@ class ComparePolicy final : public TypePolicy
|
|||
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) override;
|
||||
};
|
||||
|
||||
class SameValuePolicy final : public TypePolicy
|
||||
{
|
||||
public:
|
||||
EMPTY_DATA_;
|
||||
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) override;
|
||||
};
|
||||
|
||||
// Policy for MTest instructions.
|
||||
class TestPolicy final : public TypePolicy
|
||||
{
|
||||
|
|
|
@ -105,23 +105,6 @@ EmitBaselineLeaveStubFrame(MacroAssembler& masm, bool calledIntoIon = false)
|
|||
masm.Pop(scratch);
|
||||
}
|
||||
|
||||
inline void
|
||||
EmitStowICValues(MacroAssembler& masm, int values)
|
||||
{
|
||||
MOZ_ASSERT(values >= 0 && values <= 2);
|
||||
switch(values) {
|
||||
case 1:
|
||||
// Stow R0.
|
||||
masm.Push(R0);
|
||||
break;
|
||||
case 2:
|
||||
// Stow R0 and R1.
|
||||
masm.Push(R0);
|
||||
masm.Push(R1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename AddrType>
|
||||
inline void
|
||||
EmitPreBarrier(MacroAssembler& masm, const AddrType& addr, MIRType type)
|
||||
|
|
|
@ -103,24 +103,6 @@ EmitBaselineLeaveStubFrame(MacroAssembler& masm, bool calledIntoIon = false)
|
|||
masm.checkStackAlignment();
|
||||
}
|
||||
|
||||
inline void
|
||||
EmitStowICValues(MacroAssembler& masm, int values)
|
||||
{
|
||||
switch (values) {
|
||||
case 1:
|
||||
// Stow R0.
|
||||
masm.Push(R0);
|
||||
break;
|
||||
case 2:
|
||||
// Stow R0 and R1.
|
||||
masm.Push(R0.valueReg());
|
||||
masm.Push(R1.valueReg());
|
||||
break;
|
||||
default:
|
||||
MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Expected 1 or 2 values");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename AddrType>
|
||||
inline void
|
||||
EmitPreBarrier(MacroAssembler& masm, const AddrType& addr, MIRType type)
|
||||
|
|
|
@ -117,22 +117,6 @@ EmitBaselineLeaveStubFrame(MacroAssembler& masm, bool calledIntoIon = false)
|
|||
masm.addPtr(Imm32(STUB_FRAME_SIZE), StackPointer);
|
||||
}
|
||||
|
||||
inline void
|
||||
EmitStowICValues(MacroAssembler& masm, int values)
|
||||
{
|
||||
MOZ_ASSERT(values >= 0 && values <= 2);
|
||||
switch(values) {
|
||||
case 1:
|
||||
// Stow R0
|
||||
masm.Push(R0);
|
||||
break;
|
||||
case 2:
|
||||
// Stow R0 and R1
|
||||
masm.Push(R0);
|
||||
masm.Push(R1);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename AddrType>
|
||||
inline void
|
||||
EmitPreBarrier(MacroAssembler& masm, const AddrType& addr, MIRType type)
|
||||
|
|
|
@ -19,7 +19,6 @@ inline void EmitEnterTypeMonitorIC(MacroAssembler&, size_t v = 0) { MOZ_CRASH();
|
|||
inline void EmitReturnFromIC(MacroAssembler&) { MOZ_CRASH(); }
|
||||
inline void EmitChangeICReturnAddress(MacroAssembler&, Register) { MOZ_CRASH(); }
|
||||
inline void EmitBaselineLeaveStubFrame(MacroAssembler&, bool v = false) { MOZ_CRASH(); }
|
||||
inline void EmitStowICValues(MacroAssembler&, int) { MOZ_CRASH(); }
|
||||
inline void EmitStubGuardFailure(MacroAssembler&) { MOZ_CRASH(); }
|
||||
|
||||
template <typename T> inline void EmitPreBarrier(MacroAssembler&, T, MIRType) { MOZ_CRASH(); }
|
||||
|
|
|
@ -3132,6 +3132,68 @@ class LIsNullOrLikeUndefinedAndBranchT : public LControlInstructionHelper<2, 1,
|
|||
}
|
||||
};
|
||||
|
||||
class LSameValueD : public LInstructionHelper<1, 2, 1>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(SameValueD)
|
||||
LSameValueD(const LAllocation& left, const LAllocation& right, const LDefinition& temp) {
|
||||
setOperand(0, left);
|
||||
setOperand(1, right);
|
||||
setTemp(0, temp);
|
||||
}
|
||||
|
||||
const LAllocation* left() {
|
||||
return getOperand(0);
|
||||
}
|
||||
const LAllocation* right() {
|
||||
return getOperand(1);
|
||||
}
|
||||
const LDefinition* tempFloat() {
|
||||
return getTemp(0);
|
||||
}
|
||||
};
|
||||
|
||||
class LSameValueV : public LInstructionHelper<1, BOX_PIECES + 1, 2>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(SameValueV)
|
||||
|
||||
static const size_t LhsInput = 0;
|
||||
|
||||
LSameValueV(const LBoxAllocation& left, const LAllocation& right, const LDefinition& temp1,
|
||||
const LDefinition& temp2)
|
||||
{
|
||||
setBoxOperand(LhsInput, left);
|
||||
setOperand(BOX_PIECES, right);
|
||||
setTemp(0, temp1);
|
||||
setTemp(1, temp2);
|
||||
}
|
||||
|
||||
const LAllocation* right() {
|
||||
return getOperand(BOX_PIECES);
|
||||
}
|
||||
const LDefinition* tempFloat1() {
|
||||
return getTemp(0);
|
||||
}
|
||||
const LDefinition* tempFloat2() {
|
||||
return getTemp(1);
|
||||
}
|
||||
};
|
||||
|
||||
class LSameValueVM : public LCallInstructionHelper<1, 2 * BOX_PIECES, 0>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(SameValueVM)
|
||||
|
||||
static const size_t LhsInput = 0;
|
||||
static const size_t RhsInput = BOX_PIECES;
|
||||
|
||||
LSameValueVM(const LBoxAllocation& left, const LBoxAllocation& right) {
|
||||
setBoxOperand(LhsInput, left);
|
||||
setBoxOperand(RhsInput, right);
|
||||
}
|
||||
};
|
||||
|
||||
// Not operation on an integer.
|
||||
class LNotI : public LInstructionHelper<1, 1, 0>
|
||||
{
|
||||
|
@ -4084,14 +4146,15 @@ class LConcat : public LInstructionHelper<1, 2, 5>
|
|||
};
|
||||
|
||||
// Get uint16 character code from a string.
|
||||
class LCharCodeAt : public LInstructionHelper<1, 2, 0>
|
||||
class LCharCodeAt : public LInstructionHelper<1, 2, 1>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(CharCodeAt)
|
||||
|
||||
LCharCodeAt(const LAllocation& str, const LAllocation& index) {
|
||||
LCharCodeAt(const LAllocation& str, const LAllocation& index, const LDefinition& temp) {
|
||||
setOperand(0, str);
|
||||
setOperand(1, index);
|
||||
setTemp(0, temp);
|
||||
}
|
||||
|
||||
const LAllocation* str() {
|
||||
|
@ -4100,6 +4163,9 @@ class LCharCodeAt : public LInstructionHelper<1, 2, 0>
|
|||
const LAllocation* index() {
|
||||
return this->getOperand(1);
|
||||
}
|
||||
const LDefinition* temp() {
|
||||
return getTemp(0);
|
||||
}
|
||||
};
|
||||
|
||||
// Convert uint16 character code to a string.
|
||||
|
|
|
@ -147,6 +147,9 @@
|
|||
_(IsNullOrLikeUndefinedT) \
|
||||
_(IsNullOrLikeUndefinedAndBranchV)\
|
||||
_(IsNullOrLikeUndefinedAndBranchT)\
|
||||
_(SameValueD) \
|
||||
_(SameValueV) \
|
||||
_(SameValueVM) \
|
||||
_(MinMaxI) \
|
||||
_(MinMaxD) \
|
||||
_(MinMaxF) \
|
||||
|
|
|
@ -95,27 +95,6 @@ EmitBaselineLeaveStubFrame(MacroAssembler& masm, bool calledIntoIon = false)
|
|||
masm.Pop(Operand(BaselineStackReg, 0));
|
||||
}
|
||||
|
||||
inline void
|
||||
EmitStowICValues(MacroAssembler& masm, int values)
|
||||
{
|
||||
MOZ_ASSERT(values >= 0 && values <= 2);
|
||||
switch(values) {
|
||||
case 1:
|
||||
// Stow R0
|
||||
masm.pop(ICTailCallReg);
|
||||
masm.Push(R0);
|
||||
masm.push(ICTailCallReg);
|
||||
break;
|
||||
case 2:
|
||||
// Stow R0 and R1
|
||||
masm.pop(ICTailCallReg);
|
||||
masm.Push(R0);
|
||||
masm.Push(R1);
|
||||
masm.push(ICTailCallReg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename AddrType>
|
||||
inline void
|
||||
EmitPreBarrier(MacroAssembler& masm, const AddrType& addr, MIRType type)
|
||||
|
|
|
@ -96,27 +96,6 @@ EmitBaselineLeaveStubFrame(MacroAssembler& masm, bool calledIntoIon = false)
|
|||
masm.Pop(Operand(BaselineStackReg, 0));
|
||||
}
|
||||
|
||||
inline void
|
||||
EmitStowICValues(MacroAssembler& masm, int values)
|
||||
{
|
||||
MOZ_ASSERT(values >= 0 && values <= 2);
|
||||
switch(values) {
|
||||
case 1:
|
||||
// Stow R0
|
||||
masm.pop(ICTailCallReg);
|
||||
masm.Push(R0);
|
||||
masm.push(ICTailCallReg);
|
||||
break;
|
||||
case 2:
|
||||
// Stow R0 and R1
|
||||
masm.pop(ICTailCallReg);
|
||||
masm.Push(R0);
|
||||
masm.Push(R1);
|
||||
masm.push(ICTailCallReg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename AddrType>
|
||||
inline void
|
||||
EmitPreBarrier(MacroAssembler& masm, const AddrType& addr, MIRType type)
|
||||
|
|
|
@ -311,6 +311,12 @@ AtomIsPinnedInRuntime(JSRuntime* rt, JSAtom* atom)
|
|||
|
||||
#endif // DEBUG
|
||||
|
||||
template <typename CharT>
|
||||
MOZ_ALWAYS_INLINE
|
||||
static JSAtom*
|
||||
AtomizeAndCopyCharsInner(JSContext* cx, const CharT* tbchars, size_t length, PinningBehavior pin,
|
||||
const Maybe<uint32_t>& indexValue, const AtomHasher::Lookup& lookup);
|
||||
|
||||
/* |tbchars| must not point into an inline or short string. */
|
||||
template <typename CharT>
|
||||
MOZ_ALWAYS_INLINE
|
||||
|
@ -361,6 +367,24 @@ AtomizeAndCopyChars(JSContext* cx, const CharT* tbchars, size_t length, PinningB
|
|||
if (MOZ_UNLIKELY(!JSString::validateLength(cx, length)))
|
||||
return nullptr;
|
||||
|
||||
JSAtom* atom = AtomizeAndCopyCharsInner(cx, tbchars, length, pin, indexValue, lookup);
|
||||
if (!atom)
|
||||
return nullptr;
|
||||
|
||||
cx->atomMarking().inlinedMarkAtom(cx, atom);
|
||||
|
||||
if (zonePtr)
|
||||
mozilla::Unused << zone->atomCache().add(*zonePtr, AtomStateEntry(atom, false));
|
||||
|
||||
return atom;
|
||||
}
|
||||
|
||||
template <typename CharT>
|
||||
MOZ_ALWAYS_INLINE
|
||||
static JSAtom*
|
||||
AtomizeAndCopyCharsInner(JSContext* cx, const CharT* tbchars, size_t length, PinningBehavior pin,
|
||||
const Maybe<uint32_t>& indexValue, const AtomHasher::Lookup& lookup)
|
||||
{
|
||||
AutoLockForExclusiveAccess lock(cx);
|
||||
|
||||
JSRuntime* rt = cx->runtime();
|
||||
|
@ -390,9 +414,6 @@ AtomizeAndCopyChars(JSContext* cx, const CharT* tbchars, size_t length, PinningB
|
|||
if (p) {
|
||||
JSAtom* atom = p->asPtr(cx);
|
||||
p->setPinned(bool(pin));
|
||||
cx->atomMarking().inlinedMarkAtom(cx, atom);
|
||||
if (zonePtr)
|
||||
mozilla::Unused << zone->atomCache().add(*zonePtr, AtomStateEntry(atom, false));
|
||||
return atom;
|
||||
}
|
||||
|
||||
|
@ -425,9 +446,6 @@ AtomizeAndCopyChars(JSContext* cx, const CharT* tbchars, size_t length, PinningB
|
|||
}
|
||||
}
|
||||
|
||||
cx->atomMarking().inlinedMarkAtom(cx, atom);
|
||||
if (zonePtr)
|
||||
mozilla::Unused << zone->atomCache().add(*zonePtr, AtomStateEntry(atom, false));
|
||||
return atom;
|
||||
}
|
||||
|
||||
|
|
|
@ -1495,18 +1495,6 @@ if test -n "$MOZ_DEBUG"; then
|
|||
AC_DEFINE(JS_DEBUG)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl Enable breakpoint for artificial OOMs
|
||||
dnl ========================================================
|
||||
MOZ_ARG_ENABLE_BOOL(oom-breakpoint,
|
||||
[ --enable-oom-breakpoint
|
||||
Enable a breakpoint function for artificial OOMs],
|
||||
JS_OOM_BREAKPOINT=1,
|
||||
JS_OOM_BREAKPOINT= )
|
||||
if test -n "$JS_OOM_BREAKPOINT"; then
|
||||
AC_DEFINE(JS_OOM_BREAKPOINT)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Enable using the clang plugin to build
|
||||
dnl ========================================================
|
||||
|
|
|
@ -1162,4 +1162,4 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
|
|||
|
||||
static const int32_t kUnknownId = -1;
|
||||
|
||||
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1525832557448000);
|
||||
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1525893971751000);
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -8,7 +8,7 @@
|
|||
/*****************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
const PRTime gPreloadListExpirationTime = INT64_C(1528251745082000);
|
||||
const PRTime gPreloadListExpirationTime = INT64_C(1528313159661000);
|
||||
%%
|
||||
0-1.party, 1
|
||||
0.me.uk, 1
|
||||
|
@ -734,7 +734,6 @@ academicexperts.us, 1
|
|||
academie-de-police.ch, 1
|
||||
academy4.net, 1
|
||||
academytv.com.au, 1
|
||||
acadianapatios.com, 1
|
||||
acampar.com.br, 1
|
||||
acaonegocios.com.br, 1
|
||||
acara-yoga.de, 1
|
||||
|
@ -1570,7 +1569,6 @@ alumni-kusa.jp, 1
|
|||
alunonaescola.com.br, 1
|
||||
alupferd.de, 1
|
||||
aluroof.eu, 1
|
||||
alvcs.com, 1
|
||||
alviano.com, 1
|
||||
alvicom.hu, 1
|
||||
alvosec.com, 1
|
||||
|
@ -2253,7 +2251,6 @@ arkaic.dyndns.org, 1
|
|||
arkbyte.com, 1
|
||||
arknodejs.com, 1
|
||||
arksan.com.tr, 1
|
||||
arlatools.com, 1
|
||||
arlen.tv, 1
|
||||
arlenarmageddon.com, 1
|
||||
arlet.click, 1
|
||||
|
@ -3535,7 +3532,6 @@ beoordelingen.be, 1
|
|||
beranovi.com, 1
|
||||
berasavocate.com, 1
|
||||
beraten-entwickeln-steuern.de, 1
|
||||
berdaguermontes.eu, 1
|
||||
berduri.com, 1
|
||||
bergenhave.nl, 1
|
||||
bergevoet-fa.nl, 1
|
||||
|
@ -3643,6 +3639,7 @@ betecnet.de, 1
|
|||
betformular.com, 1
|
||||
betgo9.cc, 1
|
||||
betkoo.com, 1
|
||||
betobaccofree.gov, 1
|
||||
betonmoney.com, 1
|
||||
betpamm.com, 1
|
||||
bets.gg, 1
|
||||
|
@ -4198,6 +4195,7 @@ blogom.at, 1
|
|||
blogpentrusuflet.ro, 1
|
||||
blogreen.org, 1
|
||||
blogtroterzy.pl, 1
|
||||
blok56.nl, 1
|
||||
blokuhaka.fr, 1
|
||||
bloodsports.org, 1
|
||||
bloodyexcellent.com, 1
|
||||
|
@ -6386,6 +6384,7 @@ closeli.com, 0
|
|||
closelinksecurity.co.uk, 1
|
||||
closelinksecurity.com, 1
|
||||
closetemail.com, 1
|
||||
closient.com, 0
|
||||
closingholding.com, 1
|
||||
cloturea.fr, 1
|
||||
cloud-surfer.net, 1
|
||||
|
@ -6887,6 +6886,7 @@ consumerfiles.com, 1
|
|||
consumersentinel.gov, 1
|
||||
consumidor.gov, 1
|
||||
consuwijzer.nl, 1
|
||||
contactsingapore.sg, 1
|
||||
content-api-dev.azurewebsites.net, 0
|
||||
contentcoms.co.uk, 1
|
||||
contentdesign.de, 1
|
||||
|
@ -7576,7 +7576,6 @@ d.nr, 1
|
|||
d00d.de, 1
|
||||
d0g.cc, 1
|
||||
d0xq.net, 1
|
||||
d2s.uk, 1
|
||||
d3njjcbhbojbot.cloudfront.net, 1
|
||||
d3x.pw, 1
|
||||
d3xt3r01.tk, 1
|
||||
|
@ -8801,6 +8800,7 @@ dogan.ch, 0
|
|||
dogcontrol.ca, 1
|
||||
dogcratereview.info, 1
|
||||
dogear.ch, 1
|
||||
dogfi.sh, 1
|
||||
dogft.com, 1
|
||||
doggroomingcourse.com, 1
|
||||
dogmap.jp, 1
|
||||
|
@ -9735,7 +9735,6 @@ electricgatemotorgermiston.co.za, 1
|
|||
electronic-ignition-system.com, 1
|
||||
electronicafacil.net, 1
|
||||
electronicfasteners.com, 1
|
||||
electrostatics.com, 1
|
||||
eled.io, 1
|
||||
elefantevoador.com, 1
|
||||
eleicoes2014.com.br, 1
|
||||
|
@ -10008,7 +10007,6 @@ engelundlicht.ch, 1
|
|||
engg.ca, 1
|
||||
engineowning.com, 1
|
||||
enginepit.com, 1
|
||||
enginx.cn, 1
|
||||
enginx.net, 1
|
||||
englerts.de, 1
|
||||
englishbulgaria.net, 1
|
||||
|
@ -10893,6 +10891,7 @@ fakturoid.cz, 1
|
|||
falaowang.com, 1
|
||||
falbros.com, 1
|
||||
falcibiosystems.org, 1
|
||||
falconfrag.com, 1
|
||||
falconvintners.com, 1
|
||||
falcoz.co, 1
|
||||
faldoria.de, 0
|
||||
|
@ -11025,7 +11024,6 @@ fathers4equalrights.org, 1
|
|||
fatidique.com, 1
|
||||
fatimamoldes.com.br, 1
|
||||
fatowltees.com, 1
|
||||
fatox.de, 1
|
||||
faucetbox.com, 0
|
||||
faui2k17.de, 1
|
||||
faulty.equipment, 1
|
||||
|
@ -11465,7 +11463,6 @@ flipneus.net, 1
|
|||
fliptable.org, 1
|
||||
flirt-norden.de, 1
|
||||
flirtfaces.de, 1
|
||||
flirtycourts.com, 1
|
||||
flmortgagebank.com, 1
|
||||
floaternet.com, 1
|
||||
flocktofedora.org, 1
|
||||
|
@ -11476,7 +11473,6 @@ flood.io, 1
|
|||
flooringnightmares.com, 1
|
||||
floort.net, 0
|
||||
flopix.net, 0
|
||||
flopy.club, 1
|
||||
florence.uk.net, 1
|
||||
florenceapp.co.uk, 1
|
||||
florent-tatard.fr, 1
|
||||
|
@ -12552,7 +12548,7 @@ gers-authentique.com, 1
|
|||
gerum.dynv6.net, 1
|
||||
gerwinvanderkamp.nl, 1
|
||||
ges-bo.de, 1
|
||||
geschenkly.de, 0
|
||||
geschenkly.de, 1
|
||||
geschmacksache.online, 1
|
||||
geschmackspiloten.de, 1
|
||||
geschwinder.net, 1
|
||||
|
@ -12795,7 +12791,6 @@ glenhuntlyapartments.com.au, 1
|
|||
glidingshop.cz, 1
|
||||
glidingshop.de, 1
|
||||
glidingshop.eu, 1
|
||||
glittersjabloon.nl, 1
|
||||
glloq.org, 1
|
||||
glob-coin.com, 1
|
||||
global-lights.ma, 1
|
||||
|
@ -13657,6 +13652,7 @@ hash.works, 1
|
|||
hashcat.net, 1
|
||||
hashes.org, 1
|
||||
hashi.dk, 1
|
||||
hashiconf.com, 1
|
||||
hashiconf.eu, 1
|
||||
hashicorp.com, 1
|
||||
hashimah.ca, 1
|
||||
|
@ -14837,7 +14833,6 @@ idrinktoomuch.coffee, 1
|
|||
idrissi.eu, 1
|
||||
idrycleaningi.com, 1
|
||||
idsafe.co.za, 1
|
||||
idsoccer.com, 1
|
||||
idtechnowizard.com, 1
|
||||
idtheft.gov, 1
|
||||
idubaj.cz, 1
|
||||
|
@ -15083,7 +15078,7 @@ impulsionsa.com, 1
|
|||
impyus.com, 1
|
||||
imququ.com, 1
|
||||
imreh.net, 1
|
||||
imrejonk.nl, 0
|
||||
imrejonk.nl, 1
|
||||
imrunner.com, 1
|
||||
imrunner.ru, 1
|
||||
ims-sargans.ch, 1
|
||||
|
@ -17100,7 +17095,6 @@ kibriscicek.net, 1
|
|||
kick-in.nl, 1
|
||||
kickasscanadians.ca, 1
|
||||
kickedmycat.com, 1
|
||||
kickerplaza.nl, 1
|
||||
kidbacker.com, 1
|
||||
kiddyboom.ua, 1
|
||||
kids-at-home.ch, 1
|
||||
|
@ -17224,7 +17218,6 @@ kirstin-peters.de, 1
|
|||
kirwandigital.com, 1
|
||||
kis-toitoidixi.de, 1
|
||||
kisallatorvos.hu, 1
|
||||
kisiselveri.com, 1
|
||||
kissesb.com, 1
|
||||
kissesb.net, 1
|
||||
kissflow.com, 1
|
||||
|
@ -17362,7 +17355,6 @@ knownsec.cf, 1
|
|||
knthost.com, 1
|
||||
knurps.de, 1
|
||||
knutur.is, 1
|
||||
knygos.lt, 1
|
||||
ko-sys.com, 1
|
||||
ko.si, 1
|
||||
koalapress.fr, 1
|
||||
|
@ -17480,7 +17472,6 @@ korobi.io, 1
|
|||
korobkovsky.ru, 1
|
||||
korono.de, 1
|
||||
korosiprogram.hu, 1
|
||||
korp.fr, 1
|
||||
korrelzout.nl, 1
|
||||
kortgebyr.dk, 1
|
||||
koryfi.com, 1
|
||||
|
@ -17879,7 +17870,7 @@ lancork.net, 1
|
|||
lancyvbc.ch, 1
|
||||
land.nrw, 0
|
||||
landell.ml, 1
|
||||
landflair-magazin.de, 1
|
||||
landflair-magazin.de, 0
|
||||
landhaus-christmann.de, 1
|
||||
landinfo.no, 1
|
||||
landofelves.net, 1
|
||||
|
@ -18320,12 +18311,12 @@ letsgowhilewereyoung.com, 1
|
|||
letspartyrugby.co.uk, 1
|
||||
letstalkcounseling.com, 1
|
||||
letterbox-online.de, 1
|
||||
letterdance.de, 1
|
||||
letteringinstitute.com, 1
|
||||
lettersblogatory.com, 1
|
||||
lettland-firma.com, 1
|
||||
lettori.club, 1
|
||||
leu.to, 0
|
||||
leuenhagen.com, 1
|
||||
leuthardtfamily.com, 1
|
||||
levans.fr, 1
|
||||
levanscatering.com, 1
|
||||
|
@ -18447,6 +18438,7 @@ liduan.net, 1
|
|||
liebel.org, 1
|
||||
lieblingsholz.de, 1
|
||||
lied8.eu, 1
|
||||
liehuojun.com, 1
|
||||
lieuu.com, 1
|
||||
lifanov.com, 1
|
||||
lifebetweenlives.com.au, 1
|
||||
|
@ -19099,7 +19091,6 @@ lunidea.com, 1
|
|||
lunight.ml, 1
|
||||
lunis.net, 1
|
||||
lunix.io, 1
|
||||
lunorian.is, 0
|
||||
luoe.me, 1
|
||||
luoh.cc, 1
|
||||
luoh.me, 1
|
||||
|
@ -19936,7 +19927,6 @@ mdek.at, 1
|
|||
mdewendt.de, 1
|
||||
mdf-bis.com, 1
|
||||
mdiv.pl, 1
|
||||
mdkr.nl, 1
|
||||
mdlayher.com, 1
|
||||
mdma.net, 1
|
||||
mdmed.clinic, 1
|
||||
|
@ -21033,6 +21023,7 @@ mpc-hc.org, 1
|
|||
mpcompliance.com, 1
|
||||
mpe.org, 1
|
||||
mpetroff.net, 1
|
||||
mpg-universal.com, 1
|
||||
mpg.ovh, 1
|
||||
mpi-sa.fr, 1
|
||||
mpintaamalabanna.it, 1
|
||||
|
@ -24258,6 +24249,7 @@ pitfire.io, 1
|
|||
pitot-rs.org, 1
|
||||
pitsstop.nu, 1
|
||||
pittaya.com, 1
|
||||
pittmantraffic.co.uk, 1
|
||||
pivotaltracker.com, 1
|
||||
pivotanimation.org, 1
|
||||
piwko.co, 1
|
||||
|
@ -24835,7 +24827,6 @@ primordialsnooze.com, 1
|
|||
primotilesandbathrooms.co.uk, 1
|
||||
princeagency.com, 1
|
||||
princeofwhales.com, 1
|
||||
princesparktouch.com, 1
|
||||
princessbackpack.de, 1
|
||||
princessmargaretlotto.com, 1
|
||||
principalstest.com, 1
|
||||
|
@ -25605,6 +25596,7 @@ rattenkot.io, 1
|
|||
raucris.ro, 1
|
||||
raulrivero.es, 1
|
||||
raumzeitlabor.de, 0
|
||||
rauros.net, 1
|
||||
rautermods.net, 1
|
||||
ravchat.com, 1
|
||||
raven.dog, 1
|
||||
|
@ -27756,7 +27748,6 @@ shaken110.com, 1
|
|||
shakepeers.org, 0
|
||||
shakes4u.com, 1
|
||||
shakespearesolutions.com.au, 0
|
||||
shakespearevet.com, 1
|
||||
shalott.org, 1
|
||||
shamara.info, 1
|
||||
shamariki.ru, 1
|
||||
|
@ -28218,7 +28209,6 @@ sirburton.com, 1
|
|||
sirena.co.jp, 1
|
||||
sirenslove.com, 1
|
||||
siriuspup.com, 1
|
||||
siroop.ch, 1
|
||||
sirtaptap.com, 1
|
||||
sirtuins.com, 1
|
||||
sistel.es, 1
|
||||
|
@ -28710,7 +28700,6 @@ solsocog.de, 1
|
|||
soluphant.de, 1
|
||||
solus-project.com, 1
|
||||
solutionhoisthire.com.au, 1
|
||||
solve-it.se, 1
|
||||
solved.tips, 1
|
||||
solvemethod.com, 1
|
||||
solvingproblems.com.au, 1
|
||||
|
@ -30993,6 +30982,7 @@ tintencenter.com, 1
|
|||
tintenfix.net, 1
|
||||
tintenfux.de, 1
|
||||
tintenland.de, 1
|
||||
tintenprofi.de, 1
|
||||
tiny.ee, 1
|
||||
tinyhousefinance.com.au, 1
|
||||
tinylan.com, 1
|
||||
|
@ -31047,7 +31037,6 @@ tkn.tokyo, 1
|
|||
tkts.cl, 1
|
||||
tkusano.jp, 1
|
||||
tkw01536.de, 1
|
||||
tlach.cz, 1
|
||||
tlca.org, 1
|
||||
tlcnet.info, 1
|
||||
tlehseasyads.com, 1
|
||||
|
@ -32141,7 +32130,6 @@ unli.xyz, 1
|
|||
unlockboot.com, 0
|
||||
unlocken.nl, 1
|
||||
unmanaged.space, 1
|
||||
unmonito.red, 1
|
||||
uno-pizza.ru, 1
|
||||
uno.fi, 1
|
||||
unobrindes.com.br, 1
|
||||
|
@ -32224,6 +32212,7 @@ urbanmelbourne.info, 1
|
|||
urbanmic.com, 1
|
||||
urbannewsservice.com, 1
|
||||
urbansparrow.in, 1
|
||||
urbanstylestaging.com, 1
|
||||
urbanwildlifealliance.org, 1
|
||||
urbexdk.nl, 1
|
||||
urcentral.com, 1
|
||||
|
@ -32664,7 +32653,7 @@ vicyu.com, 1
|
|||
vid-immobilien.de, 1
|
||||
vida-it.com, 1
|
||||
vida.es, 1
|
||||
vidadu.com, 1
|
||||
vidb.me, 1
|
||||
vidbooster.com, 1
|
||||
vide-dressing.org, 0
|
||||
vide-greniers.org, 0
|
||||
|
@ -33163,7 +33152,6 @@ wasema.com, 1
|
|||
wasfestes.de, 1
|
||||
washingtonregisteredagent.io, 1
|
||||
washingtonviews.com, 1
|
||||
wasi-net.de, 1
|
||||
wasielewski.com.de, 1
|
||||
wasil.org, 1
|
||||
waslh.com, 1
|
||||
|
@ -33188,7 +33176,6 @@ waterschaplimburg.nl, 1
|
|||
watertrails.io, 1
|
||||
waterworkscondos.com, 1
|
||||
watsonwork.me, 1
|
||||
wattechweb.com, 1
|
||||
wave-ola.es, 1
|
||||
wavesboardshop.com, 1
|
||||
wavesoftime.com, 1
|
||||
|
@ -33829,6 +33816,7 @@ withyoutube.com, 1
|
|||
witneywaterpolo.org.uk, 1
|
||||
witt-international.co.uk, 1
|
||||
wittepapaver.nl, 1
|
||||
witting.co, 1
|
||||
witway.nl, 0
|
||||
wivoc.nl, 1
|
||||
wiz.at, 1
|
||||
|
@ -34731,7 +34719,6 @@ yoitsu.moe, 1
|
|||
yokohama-legaloffice.jp, 1
|
||||
yolo.jetzt, 1
|
||||
yolobert.de, 1
|
||||
yolocelebs.com, 0
|
||||
yolops.net, 1
|
||||
yombo.net, 1
|
||||
yomena.in, 1
|
||||
|
@ -34911,6 +34898,7 @@ yzcloud.me, 1
|
|||
yzimroni.net, 1
|
||||
z-coder.com, 1
|
||||
z-konzept-nutrition.ru, 1
|
||||
z-latko.info, 1
|
||||
z-vector.com, 1
|
||||
z.ai, 1
|
||||
z0rro.net, 1
|
||||
|
@ -35029,7 +35017,7 @@ zenvideocloud.com, 1
|
|||
zenycosta.com, 1
|
||||
zepect.com, 1
|
||||
zeplin.io, 1
|
||||
zer0-day.pw, 0
|
||||
zer0-day.pw, 1
|
||||
zer0.de, 1
|
||||
zero-sum.xyz, 1
|
||||
zero-x-baadf00d.com, 1
|
||||
|
@ -35066,6 +35054,7 @@ zh.search.yahoo.com, 0
|
|||
zhang-hao.com, 1
|
||||
zhang.nz, 1
|
||||
zhangfangzhou.com, 1
|
||||
zhangge.net, 1
|
||||
zhanghao.me, 1
|
||||
zhangsidan.com, 1
|
||||
zhangsir.net, 1
|
||||
|
@ -35129,7 +35118,6 @@ zlatakus.cz, 1
|
|||
zlatosnadno.cz, 1
|
||||
zlavomat.sk, 1
|
||||
zlc1994.com, 1
|
||||
zlima12.com, 1
|
||||
zmk.fr, 1
|
||||
znation.nl, 1
|
||||
zning.net.cn, 1
|
||||
|
|
|
@ -27,3 +27,18 @@ only-for-build-platforms:
|
|||
- macosx64-devedition-nightly/opt
|
||||
- win32-devedition-nightly/opt
|
||||
- win64-devedition-nightly/opt
|
||||
|
||||
job-template:
|
||||
mozharness:
|
||||
config:
|
||||
by-build-platform:
|
||||
linux-.*:
|
||||
- repackage/linux32_signed.py
|
||||
linux64-.*:
|
||||
- repackage/linux64_signed.py
|
||||
macosx64-.*:
|
||||
- repackage/osx_signed.py
|
||||
win32-.*:
|
||||
- repackage/win32_signed.py
|
||||
win64-.*:
|
||||
- repackage/win64_signed.py
|
||||
|
|
|
@ -27,3 +27,18 @@ only-for-build-platforms:
|
|||
- win32-devedition-nightly/opt
|
||||
- win64-nightly/opt
|
||||
- win64-devedition-nightly/opt
|
||||
|
||||
job-template:
|
||||
mozharness:
|
||||
config:
|
||||
by-build-platform:
|
||||
linux-.*:
|
||||
- repackage/linux32_signed.py
|
||||
linux64-.*:
|
||||
- repackage/linux64_signed.py
|
||||
macosx64-.*:
|
||||
- repackage/osx_signed.py
|
||||
win32-.*:
|
||||
- repackage/win32_signed.py
|
||||
win64-.*:
|
||||
- repackage/win64_signed.py
|
||||
|
|
|
@ -14,6 +14,7 @@ echo "running as" $(id)
|
|||
|
||||
: MOZHARNESS_SCRIPT ${MOZHARNESS_SCRIPT}
|
||||
: MOZHARNESS_CONFIG ${MOZHARNESS_CONFIG}
|
||||
: MOZHARNESS_CONFIG_PATHS ${MOZHARNESS_CONFIG_PATHS}
|
||||
: MOZHARNESS_ACTIONS ${MOZHARNESS_ACTIONS}
|
||||
: MOZHARNESS_OPTIONS ${MOZHARNESS_OPTIONS}
|
||||
|
||||
|
@ -60,6 +61,11 @@ fi
|
|||
# entirely effective.
|
||||
export TOOLTOOL_CACHE
|
||||
|
||||
config_path_cmds=""
|
||||
for path in ${MOZHARNESS_CONFIG_PATHS}; do
|
||||
config_path_cmds="${config_path_cmds} --extra-config-path ${WORKSPACE}/build/src/${path}"
|
||||
done
|
||||
|
||||
# support multiple, space delimited, config files
|
||||
config_cmds=""
|
||||
for cfg in $MOZHARNESS_CONFIG; do
|
||||
|
@ -86,7 +92,9 @@ fi
|
|||
|
||||
cd /builds/worker
|
||||
|
||||
python2.7 $WORKSPACE/build/src/testing/${MOZHARNESS_SCRIPT} ${config_cmds} \
|
||||
python2.7 $WORKSPACE/build/src/testing/${MOZHARNESS_SCRIPT} \
|
||||
${config_path_cmds} \
|
||||
${config_cmds} \
|
||||
$actions \
|
||||
$options \
|
||||
--log-level=debug \
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче