mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 15:23:51 +00:00
merge mozilla-inbound to mozilla-central a=merge
This commit is contained in:
commit
d6850a3a86
2
CLOBBER
2
CLOBBER
@ -22,4 +22,4 @@
|
||||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Bug 1261019 - Clobber on OS X to fix bustage caused by removed files
|
||||
Bug 1306438 and bug 1304815 - Rust update and related changes require clobber
|
||||
|
@ -480,8 +480,6 @@ EXTRA_JS_MODULES.commonjs.sdk.system += [
|
||||
|
||||
EXTRA_JS_MODULES.commonjs.sdk.system.child_process += [
|
||||
'source/lib/sdk/system/child_process/subprocess.js',
|
||||
'source/lib/sdk/system/child_process/subprocess_worker_unix.js',
|
||||
'source/lib/sdk/system/child_process/subprocess_worker_win.js',
|
||||
]
|
||||
|
||||
EXTRA_JS_MODULES.commonjs.sdk.tab += [
|
||||
|
8
addon-sdk/source/app-extension/bootstrap.js
vendored
8
addon-sdk/source/app-extension/bootstrap.js
vendored
@ -298,8 +298,11 @@ function loadSandbox(uri) {
|
||||
}
|
||||
|
||||
function unloadSandbox(sandbox) {
|
||||
if ("nukeSandbox" in Cu)
|
||||
Cu.nukeSandbox(sandbox);
|
||||
if ("nukeSandbox" in Cu) {
|
||||
try {
|
||||
Cu.nukeSandbox(sandbox);
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
|
||||
function setTimeout(callback, delay) {
|
||||
@ -346,6 +349,7 @@ function nukeModules() {
|
||||
// Bug 775067: From FF17 we can kill all CCW from a given sandbox
|
||||
unloadSandbox(sandbox);
|
||||
}
|
||||
unloadSandbox(loader.sharedGlobalSandbox);
|
||||
loader = null;
|
||||
|
||||
// both `toolkit/loader` and `system/xul-app` are loaded as JSM's via
|
||||
|
12
addon-sdk/source/lib/sdk/addon/bootstrap.js
vendored
12
addon-sdk/source/lib/sdk/addon/bootstrap.js
vendored
@ -157,11 +157,21 @@ Bootstrap.prototype = {
|
||||
|
||||
setTimeout(() => {
|
||||
for (let uri of Object.keys(loader.sandboxes)) {
|
||||
Cu.nukeSandbox(loader.sandboxes[uri]);
|
||||
try {
|
||||
Cu.nukeSandbox(loader.sandboxes[uri]);
|
||||
} catch (e) {
|
||||
// This will throw for shared sandboxes.
|
||||
}
|
||||
delete loader.sandboxes[uri];
|
||||
delete loader.modules[uri];
|
||||
}
|
||||
|
||||
try {
|
||||
Cu.nukeSandbox(loader.sharedGlobalSandbox);
|
||||
} catch (e) {
|
||||
Cu.reportError(e);
|
||||
}
|
||||
|
||||
resolve();
|
||||
}, 1000);
|
||||
}
|
||||
|
@ -61,7 +61,10 @@ var Child = Class({
|
||||
stream.write(data);
|
||||
}
|
||||
},
|
||||
done: function (result) {
|
||||
done: function (result, error) {
|
||||
if (error)
|
||||
return handleError(error);
|
||||
|
||||
// Only emit if child is not killed; otherwise,
|
||||
// the `kill` method will handle this
|
||||
if (!child.killed) {
|
||||
@ -170,7 +173,7 @@ function exec (cmd, ...args) {
|
||||
|
||||
if (isWindows) {
|
||||
file = 'C:\\Windows\\System32\\cmd.exe';
|
||||
cmdArgs = ['/s', '/c', (cmd || '').split(' ')];
|
||||
cmdArgs = ['/S/C', cmd || ''];
|
||||
}
|
||||
else {
|
||||
file = '/bin/sh';
|
||||
|
@ -1,36 +0,0 @@
|
||||
<!-- ***** BEGIN LICENSE BLOCK *****
|
||||
- Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
-
|
||||
- The contents of this file are subject to the Mozilla Public License Version
|
||||
- 1.1 (the "License"); you may not use this file except in compliance with
|
||||
- the License. You may obtain a copy of the License at
|
||||
- http://www.mozilla.org/MPL/
|
||||
-
|
||||
- Software distributed under the License is distributed on an "AS IS" basis,
|
||||
- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
- for the specific language governing rights and limitations under the
|
||||
- License.
|
||||
-
|
||||
- The Original Code is subprocess.jsm.
|
||||
-
|
||||
- The Initial Developer of this code is Jan Gerber.
|
||||
- Portions created by Jan Gerber <j@mailb.org>
|
||||
- are Copyright (C) 2011 Jan Gerber.
|
||||
- All Rights Reserved.
|
||||
-
|
||||
-
|
||||
- Contributor(s):
|
||||
-
|
||||
- Alternatively, the contents of this file may be used under the terms of
|
||||
- either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
- the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
- in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
- of those above. If you wish to allow use of your version of this file only
|
||||
- under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
- use your version of this file under the terms of the MPL, indicate your
|
||||
- decision by deleting the provisions above and replace them with the notice
|
||||
- and other provisions required by the LGPL or the GPL. If you do not delete
|
||||
- the provisions above, a recipient may use your version of this file under
|
||||
- the terms of any one of the MPL, the GPL or the LGPL.
|
||||
-
|
||||
- ***** END LICENSE BLOCK ***** -->
|
@ -1,129 +0,0 @@
|
||||
# subprocess
|
||||
|
||||
|
||||
Created by [Jan Gerber](j@mailb.org), with contributions from [Patrick Brunschwig](patrick@enigmail.net), subprocess.jsm is used as the underlying library, supporting the Addon-SDK's implementation of Node's `child-process` API.
|
||||
|
||||
`subprocess.jsm` is originally from [http://hg.mozilla.org/ipccode/](http://hg.mozilla.org/ipccode/).
|
||||
|
||||
How to Use subprocess.jsm in your Add-on
|
||||
----------------------------------------
|
||||
|
||||
1. copy subprocess.jsm and subprocess_worker_*.js into the modules/ directory
|
||||
of your add-on.
|
||||
|
||||
2. add this line to chrome.manifest:
|
||||
resource EXTENSION modules/
|
||||
|
||||
3. import it where needed:
|
||||
Components.utils.import("resource://EXTENSION/subprocess.jsm");
|
||||
|
||||
This object allows to start a process, and read/write data to/from it
|
||||
using stdin/stdout/stderr streams.
|
||||
|
||||
Usage example:
|
||||
|
||||
var p = subprocess.call({
|
||||
command: '/bin/foo',
|
||||
arguments: ['-v', 'foo'],
|
||||
environment: [ "XYZ=abc", "MYVAR=def" ],
|
||||
charset: 'UTF-8',
|
||||
workdir: '/home/foo',
|
||||
//stdin: "some value to write to stdin\nfoobar",
|
||||
stdin: function(stdin) {
|
||||
stdin.write("some value to write to stdin\nfoobar");
|
||||
stdin.close();
|
||||
},
|
||||
stdout: function(data) {
|
||||
dump("got data on stdout:" + data + "\n");
|
||||
},
|
||||
stderr: function(data) {
|
||||
dump("got data on stderr:" + data + "\n");
|
||||
},
|
||||
done: function(result) {
|
||||
dump("process terminated with " + result.exitCode + "\n");
|
||||
},
|
||||
mergeStderr: false
|
||||
});
|
||||
|
||||
p.wait(); // wait for the subprocess to terminate,
|
||||
// this will block the main thread,
|
||||
// only do if you can wait that long
|
||||
|
||||
|
||||
Description of subprocess.call(...) Parameters
|
||||
----------------------------------------------
|
||||
Apart from <command>, all arguments are optional.
|
||||
|
||||
command: either a |nsIFile| object pointing to an executable file or a
|
||||
String containing the platform-dependent path to an executable
|
||||
file.
|
||||
|
||||
arguments: optional string array containing the arguments to the command.
|
||||
|
||||
environment: optional string array containing environment variables to pass
|
||||
to the command. The array elements must have the form
|
||||
"VAR=data". Please note that if environment is defined, it
|
||||
replaces any existing environment variables for the subprocess.
|
||||
|
||||
charset: Output is decoded with given charset and a string is returned.
|
||||
If charset is undefined, "UTF-8" is used as default.
|
||||
To get binary data, set this to null and the returned string
|
||||
is not decoded in any way.
|
||||
|
||||
workdir: Optional; either a |nsIFile| object or string containing the
|
||||
platform-dependent path to a directory to become the current
|
||||
working directory of the subprocess.
|
||||
|
||||
stdin: Optional input data for the process to be passed on standard
|
||||
input. stdin can either be a string or a function.
|
||||
A |string| gets written to stdin and stdin gets closed;
|
||||
A |function| gets passed an object with write and close function.
|
||||
Please note that the write() function will return almost immediately;
|
||||
data is always written asynchronously on a separate thread.
|
||||
|
||||
stdout: An optional function that can receive output data from the
|
||||
process. The stdout-function is called asynchronously; it can be
|
||||
called mutliple times during the execution of a process.
|
||||
At a minimum at each occurance of \n or \r.
|
||||
Please note that null-characters might need to be escaped
|
||||
with something like 'data.replace(/\0/g, "\\0");'.
|
||||
|
||||
stderr: An optional function that can receive stderr data from the
|
||||
process. The stderr-function is called asynchronously; it can be
|
||||
called mutliple times during the execution of a process. Please
|
||||
note that null-characters might need to be escaped with
|
||||
something like 'data.replace(/\0/g, "\\0");'.
|
||||
(on windows it only gets called once right now)
|
||||
|
||||
done: Optional function that is called when the process has terminated.
|
||||
The exit code from the process available via result.exitCode. If
|
||||
stdout is not defined, then the output from stdout is available
|
||||
via result.stdout. stderr data is in result.stderr
|
||||
|
||||
mergeStderr: Optional boolean value. If true, stderr is merged with stdout;
|
||||
no data will be provided to stderr.
|
||||
|
||||
|
||||
Description of object returned by subprocess.call(...)
|
||||
------------------------------------------------------
|
||||
The object returned by subprocess.call offers a few methods that can be
|
||||
executed:
|
||||
|
||||
wait(): waits for the subprocess to terminate. It is not required to use
|
||||
wait; done will be called in any case when the subprocess terminated.
|
||||
|
||||
kill(): kill the subprocess. Any open pipes will be closed and
|
||||
done will be called.
|
||||
|
||||
|
||||
Other methods exported by subprocess
|
||||
------------------------------------
|
||||
The following functions help debugging and provide logging facilities.
|
||||
|
||||
registerDebugHandler(functionRef): register a handler that is called to get
|
||||
debugging information
|
||||
registerLogHandler(functionRef): register a handler that is called to get error
|
||||
messages
|
||||
|
||||
example:
|
||||
subprocess.registerLogHandler( function(s) { dump(s); } );
|
File diff suppressed because it is too large
Load Diff
@ -1,278 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "MPL"); you may not use this file
|
||||
* except in compliance with the MPL. You may obtain a copy of
|
||||
* the MPL at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the MPL is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the MPL for the specific language governing
|
||||
* rights and limitations under the MPL.
|
||||
*
|
||||
* The Original Code is subprocess.jsm.
|
||||
*
|
||||
* The Initial Developer of this code is Patrick Brunschwig.
|
||||
* Portions created by Patrick Brunschwig <patrick@enigmail.net>
|
||||
* are Copyright (C) 2011 Patrick Brunschwig.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jan Gerber <j@mailb.org>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* ChromeWorker Object subprocess.jsm on Unix-like systems (Linux, Mac OS X, ...)
|
||||
* to process stdin/stdout/stderr on separate threads.
|
||||
*
|
||||
*/
|
||||
|
||||
// Being a ChromeWorker object, implicitly uses the following:
|
||||
// Cu.import("resource://gre/modules/ctypes.jsm");
|
||||
|
||||
'use strict';
|
||||
|
||||
const BufferSize = 1024;
|
||||
|
||||
var libc = null;
|
||||
var libcFunc = {};
|
||||
|
||||
|
||||
/*
|
||||
struct pollfd {
|
||||
int fd; // file descriptor
|
||||
short events; // events to look for
|
||||
short revents; // events returned
|
||||
};
|
||||
*/
|
||||
|
||||
var pollfd = new ctypes.StructType("pollfd",
|
||||
[ {'fd': ctypes.int},
|
||||
{'events': ctypes.short},
|
||||
{'revents': ctypes.short}
|
||||
]);
|
||||
|
||||
var WriteBuffer = ctypes.uint8_t.array(BufferSize);
|
||||
var ReadBuffer = ctypes.char.array(BufferSize);
|
||||
|
||||
|
||||
const POLLIN = 0x0001;
|
||||
const POLLOUT = 0x0004;
|
||||
|
||||
const POLLERR = 0x0008; // some poll error occurred
|
||||
const POLLHUP = 0x0010; // file descriptor was "hung up"
|
||||
const POLLNVAL = 0x0020; // requested events "invalid"
|
||||
|
||||
const WNOHANG = 0x01;
|
||||
|
||||
const pid_t = ctypes.int32_t;
|
||||
|
||||
const INDEFINITE = -1;
|
||||
const NOWAIT = 0;
|
||||
const WAITTIME = 200 // wait time for poll() in ms
|
||||
|
||||
function initLibc(libName) {
|
||||
postMessage({msg: "debug", data: "initialising library with "+ libName});
|
||||
|
||||
libc = ctypes.open(libName);
|
||||
|
||||
libcFunc.pollFds = pollfd.array(1);
|
||||
|
||||
// int poll(struct pollfd fds[], nfds_t nfds, int timeout);
|
||||
libcFunc.poll = libc.declare("poll",
|
||||
ctypes.default_abi,
|
||||
ctypes.int,
|
||||
libcFunc.pollFds,
|
||||
ctypes.unsigned_int,
|
||||
ctypes.int);
|
||||
|
||||
//ssize_t write(int fd, const void *buf, size_t count);
|
||||
// NOTE: buf is declared as array of unsigned int8 instead of char to avoid
|
||||
// implicit charset conversion
|
||||
libcFunc.write = libc.declare("write",
|
||||
ctypes.default_abi,
|
||||
ctypes.int,
|
||||
ctypes.int,
|
||||
WriteBuffer,
|
||||
ctypes.int);
|
||||
|
||||
//int read(int fd, void *buf, size_t count);
|
||||
libcFunc.read = libc.declare("read",
|
||||
ctypes.default_abi,
|
||||
ctypes.int,
|
||||
ctypes.int,
|
||||
ReadBuffer,
|
||||
ctypes.int);
|
||||
|
||||
//int pipe(int pipefd[2]);
|
||||
libcFunc.pipefd = ctypes.int.array(2);
|
||||
|
||||
//int close(int fd);
|
||||
libcFunc.close = libc.declare("close",
|
||||
ctypes.default_abi,
|
||||
ctypes.int,
|
||||
ctypes.int);
|
||||
|
||||
//pid_t waitpid(pid_t pid, int *status, int options);
|
||||
libcFunc.waitpid = libc.declare("waitpid",
|
||||
ctypes.default_abi,
|
||||
pid_t,
|
||||
pid_t,
|
||||
ctypes.int.ptr,
|
||||
ctypes.int);
|
||||
}
|
||||
|
||||
function closePipe(pipe) {
|
||||
libcFunc.close(pipe);
|
||||
}
|
||||
|
||||
function writePipe(pipe, data) {
|
||||
|
||||
postMessage({msg: "debug", data: "trying to write to "+pipe});
|
||||
|
||||
let numChunks = Math.floor(data.length / BufferSize);
|
||||
let pData = new WriteBuffer();
|
||||
|
||||
for (var chunk = 0; chunk <= numChunks; chunk ++) {
|
||||
let numBytes = chunk < numChunks ? BufferSize : data.length - chunk * BufferSize;
|
||||
for (var i=0; i < numBytes; i++) {
|
||||
pData[i] = data.charCodeAt(chunk * BufferSize + i) % 256;
|
||||
}
|
||||
|
||||
let bytesWritten = libcFunc.write(pipe, pData, numBytes);
|
||||
if (bytesWritten != numBytes) {
|
||||
closePipe(pipe);
|
||||
postMessage({ msg: "error", data: "error: wrote "+bytesWritten+" instead of "+numBytes+" bytes"});
|
||||
close();
|
||||
}
|
||||
}
|
||||
postMessage({msg: "info", data: "wrote "+data.length+" bytes of data"});
|
||||
}
|
||||
|
||||
|
||||
function readString(data, length, charset) {
|
||||
var string = '', bytes = [];
|
||||
for(var i = 0;i < length; i++) {
|
||||
if(data[i] == 0 && charset != "null") // stop on NULL character for non-binary data
|
||||
break;
|
||||
|
||||
bytes.push(data[i]);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
function readPipe(pipe, charset, pid) {
|
||||
var p = new libcFunc.pollFds;
|
||||
p[0].fd = pipe;
|
||||
p[0].events = POLLIN | POLLERR | POLLHUP;
|
||||
p[0].revents = 0;
|
||||
var pollTimeout = WAITTIME;
|
||||
var exitCode = -1;
|
||||
var readCount = 0;
|
||||
var result, status = ctypes.int();
|
||||
result = 0;
|
||||
|
||||
|
||||
const i=0;
|
||||
while (true) {
|
||||
if (result == 0) {
|
||||
result = libcFunc.waitpid(pid, status.address(), WNOHANG);
|
||||
if (result > 0) {
|
||||
pollTimeout = NOWAIT;
|
||||
exitCode = parseInt(status.value);
|
||||
postMessage({msg: "debug", data: "waitpid signaled subprocess stop, exitcode="+status.value });
|
||||
}
|
||||
}
|
||||
var r = libcFunc.poll(p, 1, pollTimeout);
|
||||
if (r > 0) {
|
||||
if (p[i].revents & POLLIN) {
|
||||
postMessage({msg: "debug", data: "reading next chunk"});
|
||||
readCount = readPolledFd(p[i].fd, charset);
|
||||
if (readCount == 0) break;
|
||||
}
|
||||
|
||||
if (p[i].revents & POLLHUP) {
|
||||
postMessage({msg: "debug", data: "poll returned HUP"});
|
||||
break;
|
||||
}
|
||||
else if (p[i].revents & POLLERR) {
|
||||
postMessage({msg: "error", data: "poll returned error"});
|
||||
break;
|
||||
}
|
||||
else if (p[i].revents != POLLIN) {
|
||||
postMessage({msg: "error", data: "poll returned "+p[i]});
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (pollTimeout == 0 || r < 0) break;
|
||||
}
|
||||
|
||||
// continue reading until the buffer is empty
|
||||
while (readCount > 0) {
|
||||
readCount = readPolledFd(pipe, charset);
|
||||
}
|
||||
|
||||
libcFunc.close(pipe);
|
||||
postMessage({msg: "done", data: exitCode });
|
||||
libc.close();
|
||||
close();
|
||||
}
|
||||
|
||||
function readPolledFd(pipe, charset) {
|
||||
var line = new ReadBuffer();
|
||||
var r = libcFunc.read(pipe, line, BufferSize);
|
||||
|
||||
if (r > 0) {
|
||||
var c = readString(line, r, charset);
|
||||
postMessage({msg: "data", data: c, count: c.length});
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
onmessage = function (event) {
|
||||
switch (event.data.msg) {
|
||||
case "init":
|
||||
initLibc(event.data.libc);
|
||||
break;
|
||||
case "read":
|
||||
initLibc(event.data.libc);
|
||||
readPipe(event.data.pipe, event.data.charset, event.data.pid);
|
||||
break;
|
||||
case "write":
|
||||
// data contents:
|
||||
// msg: 'write'
|
||||
// data: the data (string) to write
|
||||
// pipe: ptr to pipe
|
||||
writePipe(event.data.pipe, event.data.data);
|
||||
postMessage({msg: "info", data: "WriteOK"});
|
||||
break;
|
||||
case "close":
|
||||
postMessage({msg: "debug", data: "closing stdin\n"});
|
||||
|
||||
closePipe(event.data.pipe);
|
||||
postMessage({msg: "info", data: "ClosedOK"});
|
||||
break;
|
||||
case "stop":
|
||||
libc.close(); // do not use libc after this point
|
||||
close();
|
||||
break;
|
||||
default:
|
||||
throw("error: Unknown command"+event.data.msg+"\n");
|
||||
}
|
||||
return;
|
||||
};
|
@ -1,237 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public
|
||||
* License Version 1.1 (the "MPL"); you may not use this file
|
||||
* except in compliance with the MPL. You may obtain a copy of
|
||||
* the MPL at http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the MPL is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the MPL for the specific language governing
|
||||
* rights and limitations under the MPL.
|
||||
*
|
||||
* The Original Code is subprocess.jsm.
|
||||
*
|
||||
* The Initial Developer of this code is Patrick Brunschwig.
|
||||
* Portions created by Patrick Brunschwig <patrick@enigmail.net>
|
||||
* are Copyright (C) 2011 Patrick Brunschwig.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jan Gerber <j@mailb.org>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* ChromeWorker Object subprocess.jsm on Windows to process stdin/stdout/stderr
|
||||
* on separate threads.
|
||||
*
|
||||
*/
|
||||
|
||||
// Being a ChromeWorker object, implicitly uses the following:
|
||||
// Cu.import("resource://gre/modules/ctypes.jsm");
|
||||
|
||||
'use strict';
|
||||
|
||||
const BufferSize = 1024;
|
||||
|
||||
const BOOL = ctypes.bool;
|
||||
const HANDLE = ctypes.size_t;
|
||||
const DWORD = ctypes.uint32_t;
|
||||
const LPDWORD = DWORD.ptr;
|
||||
const PVOID = ctypes.voidptr_t;
|
||||
const LPVOID = PVOID;
|
||||
|
||||
/*
|
||||
typedef struct _OVERLAPPED {
|
||||
ULONG_PTR Internal;
|
||||
ULONG_PTR InternalHigh;
|
||||
union {
|
||||
struct {
|
||||
DWORD Offset;
|
||||
DWORD OffsetHigh;
|
||||
};
|
||||
PVOID Pointer;
|
||||
};
|
||||
HANDLE hEvent;
|
||||
} OVERLAPPED, *LPOVERLAPPED;
|
||||
*/
|
||||
const OVERLAPPED = new ctypes.StructType("OVERLAPPED");
|
||||
|
||||
var ReadFileBuffer = ctypes.char.array(BufferSize);
|
||||
var WriteFileBuffer = ctypes.uint8_t.array(BufferSize);
|
||||
|
||||
var kernel32dll = null;
|
||||
var libFunc = {};
|
||||
|
||||
function initLib(libName) {
|
||||
if (ctypes.size_t.size == 8) {
|
||||
var WinABI = ctypes.default_abi;
|
||||
} else {
|
||||
var WinABI = ctypes.winapi_abi;
|
||||
}
|
||||
|
||||
kernel32dll = ctypes.open(libName);
|
||||
|
||||
/*
|
||||
BOOL WINAPI WriteFile(
|
||||
__in HANDLE hFile,
|
||||
__in LPCVOID lpBuffer,
|
||||
__in DWORD nNumberOfBytesToWrite,
|
||||
__out_opt LPDWORD lpNumberOfBytesWritten,
|
||||
__inout_opt LPOVERLAPPED lpOverlapped
|
||||
);
|
||||
|
||||
NOTE: lpBuffer is declared as array of unsigned int8 instead of char to avoid
|
||||
implicit charset conversion
|
||||
*/
|
||||
libFunc.WriteFile = kernel32dll.declare("WriteFile",
|
||||
WinABI,
|
||||
BOOL,
|
||||
HANDLE,
|
||||
WriteFileBuffer,
|
||||
DWORD,
|
||||
LPDWORD,
|
||||
OVERLAPPED.ptr
|
||||
);
|
||||
|
||||
/*
|
||||
BOOL WINAPI ReadFile(
|
||||
__in HANDLE hFile,
|
||||
__out LPVOID ReadFileBuffer,
|
||||
__in DWORD nNumberOfBytesToRead,
|
||||
__out_opt LPDWORD lpNumberOfBytesRead,
|
||||
__inout_opt LPOVERLAPPED lpOverlapped
|
||||
);
|
||||
*/
|
||||
libFunc.ReadFile = kernel32dll.declare("ReadFile",
|
||||
WinABI,
|
||||
BOOL,
|
||||
HANDLE,
|
||||
ReadFileBuffer,
|
||||
DWORD,
|
||||
LPDWORD,
|
||||
OVERLAPPED.ptr
|
||||
);
|
||||
|
||||
/*
|
||||
BOOL WINAPI CloseHandle(
|
||||
__in HANDLE hObject
|
||||
);
|
||||
*/
|
||||
libFunc.CloseHandle = kernel32dll.declare("CloseHandle",
|
||||
WinABI,
|
||||
BOOL,
|
||||
HANDLE
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function writePipe(pipe, data) {
|
||||
var bytesWritten = DWORD(0);
|
||||
|
||||
var pData = new WriteFileBuffer();
|
||||
|
||||
var numChunks = Math.floor(data.length / BufferSize);
|
||||
for (var chunk = 0; chunk <= numChunks; chunk ++) {
|
||||
var numBytes = chunk < numChunks ? BufferSize : data.length - chunk * BufferSize;
|
||||
for (var i=0; i < numBytes; i++) {
|
||||
pData[i] = data.charCodeAt(chunk * BufferSize + i) % 256;
|
||||
}
|
||||
|
||||
var r = libFunc.WriteFile(pipe, pData, numBytes, bytesWritten.address(), null);
|
||||
if (bytesWritten.value != numBytes)
|
||||
throw("error: wrote "+bytesWritten.value+" instead of "+numBytes+" bytes");
|
||||
}
|
||||
postMessage("wrote "+data.length+" bytes of data");
|
||||
}
|
||||
|
||||
function readString(data, length, charset) {
|
||||
var string = '', bytes = [];
|
||||
for(var i = 0;i < length; i++) {
|
||||
if(data[i] == 0 && charset != "null") // stop on NULL character for non-binary data
|
||||
break;
|
||||
|
||||
bytes.push(data[i]);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
function readPipe(pipe, charset) {
|
||||
while (true) {
|
||||
var bytesRead = DWORD(0);
|
||||
var line = new ReadFileBuffer();
|
||||
var r = libFunc.ReadFile(pipe, line, BufferSize, bytesRead.address(), null);
|
||||
|
||||
if (!r) {
|
||||
// stop if we get an error (such as EOF reached)
|
||||
postMessage({msg: "info", data: "ReadFile failed"});
|
||||
break;
|
||||
}
|
||||
|
||||
if (bytesRead.value > 0) {
|
||||
var c = readString(line, bytesRead.value, charset);
|
||||
postMessage({msg: "data", data: c, count: c.length});
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
libFunc.CloseHandle(pipe);
|
||||
postMessage({msg: "done"});
|
||||
kernel32dll.close();
|
||||
close();
|
||||
}
|
||||
|
||||
onmessage = function (event) {
|
||||
let pipePtr;
|
||||
switch (event.data.msg) {
|
||||
case "init":
|
||||
initLib(event.data.libc);
|
||||
break;
|
||||
case "write":
|
||||
// data contents:
|
||||
// msg: 'write'
|
||||
// data: the data (string) to write
|
||||
// pipe: ptr to pipe
|
||||
pipePtr = HANDLE.ptr(event.data.pipe);
|
||||
writePipe(pipePtr.contents, event.data.data);
|
||||
postMessage("WriteOK");
|
||||
break;
|
||||
case "read":
|
||||
initLib(event.data.libc);
|
||||
pipePtr = HANDLE.ptr(event.data.pipe);
|
||||
readPipe(pipePtr.contents, event.data.charset);
|
||||
break;
|
||||
case "close":
|
||||
pipePtr = HANDLE.ptr(event.data.pipe);
|
||||
postMessage("closing stdin\n");
|
||||
|
||||
if (libFunc.CloseHandle(pipePtr.contents)) {
|
||||
postMessage("ClosedOK");
|
||||
}
|
||||
else
|
||||
postMessage("Could not close stdin handle");
|
||||
break;
|
||||
case "stop":
|
||||
kernel32dll.close();
|
||||
close();
|
||||
break;
|
||||
default:
|
||||
throw("error: Unknown command"+event.data.msg+"\n");
|
||||
}
|
||||
return;
|
||||
};
|
@ -35,5 +35,12 @@ Object.defineProperty(exports, 'define', {
|
||||
factory = Array.slice(arguments).pop();
|
||||
factory.call(sandbox, sandbox.require, sandbox.exports, sandbox.module);
|
||||
}
|
||||
}
|
||||
},
|
||||
set: function(value) {
|
||||
Object.defineProperty(this, 'define', {
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
value,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
@ -36,21 +36,55 @@ const { join: pathJoin, normalize, dirname } = Cu.import("resource://gre/modules
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "XulApp", () => {
|
||||
let xulappURI = module.uri.replace("toolkit/loader.js",
|
||||
"sdk/system/xul-app.jsm");
|
||||
"sdk/system/xul-app.jsm");
|
||||
return Cu.import(xulappURI, {});
|
||||
});
|
||||
|
||||
// Define some shortcuts.
|
||||
const bind = Function.call.bind(Function.bind);
|
||||
const getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
|
||||
const define = Object.defineProperties;
|
||||
const prototypeOf = Object.getPrototypeOf;
|
||||
const create = Object.create;
|
||||
const keys = Object.keys;
|
||||
const getOwnIdentifiers = x => [...Object.getOwnPropertyNames(x),
|
||||
...Object.getOwnPropertySymbols(x)];
|
||||
|
||||
const NODE_MODULES = ["assert", "buffer_ieee754", "buffer", "child_process", "cluster", "console", "constants", "crypto", "_debugger", "dgram", "dns", "domain", "events", "freelist", "fs", "http", "https", "_linklist", "module", "net", "os", "path", "punycode", "querystring", "readline", "repl", "stream", "string_decoder", "sys", "timers", "tls", "tty", "url", "util", "vm", "zlib"];
|
||||
const NODE_MODULES = new Set([
|
||||
"assert",
|
||||
"buffer_ieee754",
|
||||
"buffer",
|
||||
"child_process",
|
||||
"cluster",
|
||||
"console",
|
||||
"constants",
|
||||
"crypto",
|
||||
"_debugger",
|
||||
"dgram",
|
||||
"dns",
|
||||
"domain",
|
||||
"events",
|
||||
"freelist",
|
||||
"fs",
|
||||
"http",
|
||||
"https",
|
||||
"_linklist",
|
||||
"module",
|
||||
"net",
|
||||
"os",
|
||||
"path",
|
||||
"punycode",
|
||||
"querystring",
|
||||
"readline",
|
||||
"repl",
|
||||
"stream",
|
||||
"string_decoder",
|
||||
"sys",
|
||||
"timers",
|
||||
"tls",
|
||||
"tty",
|
||||
"url",
|
||||
"util",
|
||||
"vm",
|
||||
"zlib",
|
||||
]);
|
||||
|
||||
const COMPONENT_ERROR = '`Components` is not available in this context.\n' +
|
||||
'Functionality provided by Components may be available in an SDK\n' +
|
||||
@ -122,7 +156,7 @@ const override = iced(function override(target, source) {
|
||||
getOwnIdentifiers(extension).forEach(function(name) {
|
||||
properties[name] = extension[name];
|
||||
});
|
||||
return define({}, properties);
|
||||
return Object.defineProperties({}, properties);
|
||||
});
|
||||
Loader.override = override;
|
||||
|
||||
@ -193,7 +227,7 @@ function readURI(uri) {
|
||||
}
|
||||
|
||||
// Combines all arguments into a resolved, normalized path
|
||||
function join (...paths) {
|
||||
function join(...paths) {
|
||||
let joined = pathJoin(...paths);
|
||||
let resolved = normalize(joined);
|
||||
|
||||
@ -301,7 +335,7 @@ const load = iced(function load(loader, module) {
|
||||
});
|
||||
|
||||
let sandbox;
|
||||
if (loader.sharedGlobalSandbox &&
|
||||
if ((loader.useSharedGlobalSandbox || isSystemURI(module.uri)) &&
|
||||
loader.sharedGlobalBlocklist.indexOf(module.id) == -1) {
|
||||
// Create a new object in this sandbox, that will be used as
|
||||
// the scope object for this particular module
|
||||
@ -309,13 +343,14 @@ const load = iced(function load(loader, module) {
|
||||
// Inject all expected globals in the scope object
|
||||
getOwnIdentifiers(globals).forEach(function(name) {
|
||||
descriptors[name] = getOwnPropertyDescriptor(globals, name)
|
||||
descriptors[name].configurable = true;
|
||||
});
|
||||
define(sandbox, descriptors);
|
||||
Object.defineProperties(sandbox, descriptors);
|
||||
}
|
||||
else {
|
||||
sandbox = Sandbox({
|
||||
name: module.uri,
|
||||
prototype: create(globals, descriptors),
|
||||
prototype: Object.create(globals, descriptors),
|
||||
wantXrays: false,
|
||||
wantGlobalProperties: module.id == "sdk/indexed-db" ? ["indexedDB"] : [],
|
||||
invisibleToDebugger: loader.invisibleToDebugger,
|
||||
@ -359,7 +394,7 @@ const load = iced(function load(loader, module) {
|
||||
let prototype = typeof(error) === "object" ? error.constructor.prototype :
|
||||
Error.prototype;
|
||||
|
||||
throw create(prototype, {
|
||||
throw Object.create(prototype, {
|
||||
message: { value: message, writable: true, configurable: true },
|
||||
fileName: { value: fileName, writable: true, configurable: true },
|
||||
lineNumber: { value: lineNumber, writable: true, configurable: true },
|
||||
@ -368,7 +403,7 @@ const load = iced(function load(loader, module) {
|
||||
});
|
||||
}
|
||||
|
||||
if(loadModuleHook) {
|
||||
if (loadModuleHook) {
|
||||
module = loadModuleHook(module, require);
|
||||
}
|
||||
|
||||
@ -387,7 +422,7 @@ const load = iced(function load(loader, module) {
|
||||
Loader.load = load;
|
||||
|
||||
// Utility function to normalize module `uri`s so they have `.js` extension.
|
||||
function normalizeExt (uri) {
|
||||
function normalizeExt(uri) {
|
||||
return isJSURI(uri) ? uri :
|
||||
isJSONURI(uri) ? uri :
|
||||
isJSMURI(uri) ? uri :
|
||||
@ -396,7 +431,7 @@ function normalizeExt (uri) {
|
||||
|
||||
// Strips `rootURI` from `string` -- used to remove absolute resourceURI
|
||||
// from a relative path
|
||||
function stripBase (rootURI, string) {
|
||||
function stripBase(rootURI, string) {
|
||||
return string.replace(rootURI, './');
|
||||
}
|
||||
|
||||
@ -404,15 +439,14 @@ function stripBase (rootURI, string) {
|
||||
// `requirer.uri` but in some cases it may be `baseURI`. In order to
|
||||
// avoid complexity we require `baseURI` with a trailing `/`.
|
||||
const resolve = iced(function resolve(id, base) {
|
||||
if (!isRelative(id)) return id;
|
||||
let basePaths = base.split('/');
|
||||
// Pop the last element in the `base`, because it is from a
|
||||
// relative file
|
||||
// '../mod.js' from '/path/to/file.js' should resolve to '/path/mod.js'
|
||||
basePaths.pop();
|
||||
if (!basePaths.length)
|
||||
if (!isRelative(id))
|
||||
return id;
|
||||
|
||||
let baseDir = dirname(base);
|
||||
if (!baseDir)
|
||||
return normalize(id);
|
||||
let resolved = join(basePaths.join('/'), id);
|
||||
|
||||
let resolved = join(baseDir, id);
|
||||
|
||||
// Joining and normalizing removes the './' from relative files.
|
||||
// We need to ensure the resolution still has the root
|
||||
@ -423,6 +457,78 @@ const resolve = iced(function resolve(id, base) {
|
||||
});
|
||||
Loader.resolve = resolve;
|
||||
|
||||
// Attempts to load `path` and then `path.js`
|
||||
// Returns `path` with valid file, or `undefined` otherwise
|
||||
function resolveAsFile(path) {
|
||||
let found;
|
||||
|
||||
// As per node's loader spec,
|
||||
// we first should try and load 'path' (with no extension)
|
||||
// before trying 'path.js'. We will not support this feature
|
||||
// due to performance, but may add it if necessary for adoption.
|
||||
try {
|
||||
// Append '.js' to path name unless it's another support filetype
|
||||
path = normalizeExt(path);
|
||||
readURI(path);
|
||||
found = path;
|
||||
} catch (e) {}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
// Attempts to load `path/package.json`'s `main` entry,
|
||||
// followed by `path/index.js`, or `undefined` otherwise
|
||||
function resolveAsDirectory(path) {
|
||||
try {
|
||||
// If `path/package.json` exists, parse the `main` entry
|
||||
// and attempt to load that
|
||||
let main = getManifestMain(JSON.parse(readURI(path + '/package.json')));
|
||||
if (main != null) {
|
||||
let tmpPath = join(path, main);
|
||||
let found = resolveAsFile(tmpPath);
|
||||
if (found)
|
||||
return found
|
||||
}
|
||||
} catch (e) {}
|
||||
|
||||
try {
|
||||
let tmpPath = path + '/index.js';
|
||||
readURI(tmpPath);
|
||||
return tmpPath;
|
||||
} catch (e) {}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function resolveRelative(rootURI, modulesDir, id) {
|
||||
let fullId = join(rootURI, modulesDir, id);
|
||||
let resolvedPath;
|
||||
|
||||
if ((resolvedPath = resolveAsFile(fullId)))
|
||||
return stripBase(rootURI, resolvedPath);
|
||||
|
||||
if ((resolvedPath = resolveAsDirectory(fullId)))
|
||||
return stripBase(rootURI, resolvedPath);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// From `resolve` module
|
||||
// https://github.com/substack/node-resolve/blob/master/lib/node-modules-paths.js
|
||||
function* getNodeModulePaths(start) {
|
||||
// Configurable in node -- do we need this to be configurable?
|
||||
let moduleDir = 'node_modules';
|
||||
|
||||
let parts = start.split('/');
|
||||
while (parts.length) {
|
||||
let leaf = parts.pop();
|
||||
if (leaf !== moduleDir)
|
||||
yield join(...parts, leaf, moduleDir);
|
||||
}
|
||||
|
||||
yield moduleDir;
|
||||
}
|
||||
|
||||
// Node-style module lookup
|
||||
// Takes an id and path and attempts to load a file using node's resolving
|
||||
// algorithm.
|
||||
@ -434,39 +540,31 @@ const nodeResolve = iced(function nodeResolve(id, requirer, { rootURI }) {
|
||||
|
||||
// If this is already an absolute URI then there is no resolution to do
|
||||
if (isAbsoluteURI(id))
|
||||
return void 0;
|
||||
return null;
|
||||
|
||||
// we assume that extensions are correct, i.e., a directory doesnt't have '.js'
|
||||
// and a js file isn't named 'file.json.js'
|
||||
let fullId = join(rootURI, id);
|
||||
let resolvedPath;
|
||||
|
||||
if ((resolvedPath = loadAsFile(fullId)))
|
||||
return stripBase(rootURI, resolvedPath);
|
||||
|
||||
if ((resolvedPath = loadAsDirectory(fullId)))
|
||||
return stripBase(rootURI, resolvedPath);
|
||||
if ((resolvedPath = resolveRelative(rootURI, "", id)))
|
||||
return resolvedPath;
|
||||
|
||||
// If the requirer is an absolute URI then the node module resolution below
|
||||
// won't work correctly as we prefix everything with rootURI
|
||||
if (isAbsoluteURI(requirer))
|
||||
return void 0;
|
||||
return null;
|
||||
|
||||
// If manifest has dependencies, attempt to look up node modules
|
||||
// in the `dependencies` list
|
||||
let dirs = getNodeModulePaths(dirname(requirer)).map(dir => join(rootURI, dir, id));
|
||||
for (let i = 0; i < dirs.length; i++) {
|
||||
if ((resolvedPath = loadAsFile(dirs[i])))
|
||||
return stripBase(rootURI, resolvedPath);
|
||||
|
||||
if ((resolvedPath = loadAsDirectory(dirs[i])))
|
||||
return stripBase(rootURI, resolvedPath);
|
||||
for (let modulesDir of getNodeModulePaths(dirname(requirer))) {
|
||||
if ((resolvedPath = resolveRelative(rootURI, modulesDir, id)))
|
||||
return resolvedPath;
|
||||
}
|
||||
|
||||
// We would not find lookup for things like `sdk/tabs`, as that's part of
|
||||
// the alias mapping. If during `generateMap`, the runtime lookup resolves
|
||||
// with `resolveURI` -- if during runtime, then `resolve` will throw.
|
||||
return void 0;
|
||||
return null;
|
||||
});
|
||||
|
||||
// String (`${rootURI}:${requirer}:${id}`) -> resolvedPath
|
||||
@ -488,100 +586,18 @@ const nodeResolveWithCache = iced(function cacheNodeResolutions(id, requirer, {
|
||||
});
|
||||
Loader.nodeResolve = nodeResolveWithCache;
|
||||
|
||||
// Attempts to load `path` and then `path.js`
|
||||
// Returns `path` with valid file, or `undefined` otherwise
|
||||
function loadAsFile (path) {
|
||||
let found;
|
||||
|
||||
// As per node's loader spec,
|
||||
// we first should try and load 'path' (with no extension)
|
||||
// before trying 'path.js'. We will not support this feature
|
||||
// due to performance, but may add it if necessary for adoption.
|
||||
try {
|
||||
// Append '.js' to path name unless it's another support filetype
|
||||
path = normalizeExt(path);
|
||||
readURI(path);
|
||||
found = path;
|
||||
} catch (e) {}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
// Attempts to load `path/package.json`'s `main` entry,
|
||||
// followed by `path/index.js`, or `undefined` otherwise
|
||||
function loadAsDirectory (path) {
|
||||
try {
|
||||
// If `path/package.json` exists, parse the `main` entry
|
||||
// and attempt to load that
|
||||
let main = getManifestMain(JSON.parse(readURI(path + '/package.json')));
|
||||
if (main != null) {
|
||||
let tmpPath = join(path, main);
|
||||
let found = loadAsFile(tmpPath);
|
||||
if (found)
|
||||
return found
|
||||
}
|
||||
try {
|
||||
let tmpPath = path + '/index.js';
|
||||
readURI(tmpPath);
|
||||
return tmpPath;
|
||||
} catch (e) {}
|
||||
} catch (e) {
|
||||
try {
|
||||
let tmpPath = path + '/index.js';
|
||||
readURI(tmpPath);
|
||||
return tmpPath;
|
||||
} catch (e) {}
|
||||
}
|
||||
return void 0;
|
||||
}
|
||||
|
||||
// From `resolve` module
|
||||
// https://github.com/substack/node-resolve/blob/master/lib/node-modules-paths.js
|
||||
function getNodeModulePaths (start) {
|
||||
// Configurable in node -- do we need this to be configurable?
|
||||
let moduleDir = 'node_modules';
|
||||
|
||||
let parts = start.split('/');
|
||||
let dirs = [];
|
||||
for (let i = parts.length - 1; i >= 0; i--) {
|
||||
if (parts[i] === moduleDir) continue;
|
||||
let dir = join(parts.slice(0, i + 1).join('/'), moduleDir);
|
||||
dirs.push(dir);
|
||||
}
|
||||
dirs.push(moduleDir);
|
||||
return dirs;
|
||||
}
|
||||
|
||||
|
||||
function addTrailingSlash (path) {
|
||||
return !path ? null : !path.endsWith('/') ? path + '/' : path;
|
||||
}
|
||||
|
||||
// Utility function to determine of module id `name` is a built in
|
||||
// module in node (fs, path, etc.);
|
||||
function isNodeModule (name) {
|
||||
return !!~NODE_MODULES.indexOf(name);
|
||||
}
|
||||
|
||||
// Make mapping array that is sorted from longest path to shortest path
|
||||
// to allow overlays. Used by `resolveURI`, returns an array
|
||||
function sortPaths (paths) {
|
||||
return keys(paths).
|
||||
sort((a, b) => (b.length - a.length)).
|
||||
map((path) => [ path, paths[path] ]);
|
||||
function addTrailingSlash(path) {
|
||||
return path.replace(/\/*$/, "/");
|
||||
}
|
||||
|
||||
const resolveURI = iced(function resolveURI(id, mapping) {
|
||||
let count = mapping.length, index = 0;
|
||||
|
||||
// Do not resolve if already a resource URI
|
||||
if (isAbsoluteURI(id)) return normalizeExt(id);
|
||||
|
||||
while (index < count) {
|
||||
let [ path, uri ] = mapping[index++];
|
||||
if (isAbsoluteURI(id))
|
||||
return normalizeExt(id);
|
||||
|
||||
for (let [path, uri] of mapping) {
|
||||
// Strip off any trailing slashes to make comparisons simpler
|
||||
let stripped = path.endsWith('/') ? path.slice(0, -1) : path;
|
||||
let stripped = path.replace(/\/+$/, "");
|
||||
|
||||
// We only want to match path segments explicitly. Examples:
|
||||
// * "foo/bar" matches for "foo/bar"
|
||||
@ -592,13 +608,11 @@ const resolveURI = iced(function resolveURI(id, mapping) {
|
||||
//
|
||||
// Check for an empty path, an exact match, or a substring match
|
||||
// with the next character being a forward slash.
|
||||
if(stripped === "" ||
|
||||
(id.indexOf(stripped) === 0 &&
|
||||
(id.length === path.length || id[stripped.length] === '/'))) {
|
||||
if(stripped === "" || id === stripped || id.startsWith(stripped + "/")) {
|
||||
return normalizeExt(id.replace(path, uri));
|
||||
}
|
||||
}
|
||||
return void 0; // otherwise we raise a warning, see bug 910304
|
||||
return null;
|
||||
});
|
||||
Loader.resolveURI = resolveURI;
|
||||
|
||||
@ -613,6 +627,14 @@ const Require = iced(function Require(loader, requirer) {
|
||||
requireHook
|
||||
} = loader;
|
||||
|
||||
if (isSystemURI(requirer.uri)) {
|
||||
// Built-in modules don't require the expensive module resolution
|
||||
// algorithm used by SDK add-ons, so give them the more efficient standard
|
||||
// resolve instead.
|
||||
isNative = false;
|
||||
loaderResolve = Loader.resolve;
|
||||
}
|
||||
|
||||
function require(id) {
|
||||
if (!id) // Throw if `id` is not passed.
|
||||
throw Error('You must provide a module name when calling require() from '
|
||||
@ -704,19 +726,16 @@ const Require = iced(function Require(loader, requirer) {
|
||||
let { overrides } = manifest.jetpack;
|
||||
for (let key in overrides) {
|
||||
// ignore any overrides using relative keys
|
||||
if (/^[\.\/]/.test(key)) {
|
||||
if (/^[.\/]/.test(key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the override is for x -> y,
|
||||
// then using require("x/lib/z") to get reqire("y/lib/z")
|
||||
// should also work
|
||||
if (id == key || (id.substr(0, key.length + 1) == (key + "/"))) {
|
||||
if (id == key || id.startsWith(key + "/")) {
|
||||
id = overrides[key] + id.substr(key.length);
|
||||
id = id.replace(/^[\.\/]+/, "./");
|
||||
if (id.substr(0, 2) == "./") {
|
||||
id = "" + id.substr(2);
|
||||
}
|
||||
id = id.replace(/^[.\/]+/, "");
|
||||
}
|
||||
}
|
||||
|
||||
@ -728,7 +747,7 @@ const Require = iced(function Require(loader, requirer) {
|
||||
|
||||
// If no requireMap was provided, or resolution not found in
|
||||
// the requireMap, and not a npm dependency, attempt a runtime lookup
|
||||
if (!requirement && !isNodeModule(id)) {
|
||||
if (!requirement && !NODE_MODULES.has(id)) {
|
||||
// If `isNative` defined, this is using the new, native-style
|
||||
// loader, not cuddlefish, so lets resolve using node's algorithm
|
||||
// and get back a path that needs to be resolved via paths mapping
|
||||
@ -747,9 +766,15 @@ const Require = iced(function Require(loader, requirer) {
|
||||
requirement = isRelative(id) ? Loader.resolve(id, requirer.id) : id;
|
||||
}
|
||||
}
|
||||
else {
|
||||
else if (modules[id]) {
|
||||
uri = requirement = id;
|
||||
}
|
||||
else if (requirer) {
|
||||
// Resolve `id` to its requirer if it's relative.
|
||||
requirement = requirer ? loaderResolve(id, requirer.id) : id;
|
||||
requirement = loaderResolve(id, requirer.id);
|
||||
}
|
||||
else {
|
||||
requirement = id;
|
||||
}
|
||||
|
||||
// Resolves `uri` of module using loaders resolve function.
|
||||
@ -790,9 +815,9 @@ Loader.main = main;
|
||||
// Makes module object that is made available to CommonJS modules when they
|
||||
// are evaluated, along with `exports` and `require`.
|
||||
const Module = iced(function Module(id, uri) {
|
||||
return create(null, {
|
||||
return Object.create(null, {
|
||||
id: { enumerable: true, value: id },
|
||||
exports: { enumerable: true, writable: true, value: create(null),
|
||||
exports: { enumerable: true, writable: true, value: Object.create(null),
|
||||
configurable: true },
|
||||
uri: { value: uri }
|
||||
});
|
||||
@ -878,9 +903,12 @@ function Loader(options) {
|
||||
// which loader is unloaded. Please note that we intentionally don't
|
||||
// use `loader` as subject to prevent a loader access leakage through
|
||||
// observer notifications.
|
||||
let destructor = freeze(create(null));
|
||||
let destructor = freeze(Object.create(null));
|
||||
|
||||
let mapping = sortPaths(paths);
|
||||
// Make mapping array that is sorted from longest path to shortest path.
|
||||
let mapping = Object.keys(paths)
|
||||
.sort((a, b) => b.length - a.length)
|
||||
.map(path => [path, paths[path]]);
|
||||
|
||||
// Define pseudo modules.
|
||||
modules = override({
|
||||
@ -895,7 +923,8 @@ function Loader(options) {
|
||||
}, modules);
|
||||
|
||||
const builtinModuleExports = modules;
|
||||
modules = keys(modules).reduce(function(result, id) {
|
||||
modules = {};
|
||||
for (let id of Object.keys(builtinModuleExports)) {
|
||||
// We resolve `uri` from `id` since modules are cached by `uri`.
|
||||
let uri = resolveURI(id, mapping);
|
||||
// In native loader, the mapping will not contain values for
|
||||
@ -913,29 +942,25 @@ function Loader(options) {
|
||||
}
|
||||
});
|
||||
|
||||
result[uri] = freeze(module);
|
||||
return result;
|
||||
}, {});
|
||||
|
||||
let sharedGlobalSandbox;
|
||||
if (sharedGlobal) {
|
||||
// Create the unique sandbox we will be using for all modules,
|
||||
// so that we prevent creating a new comportment per module.
|
||||
// The side effect is that all modules will share the same
|
||||
// global objects.
|
||||
sharedGlobalSandbox = Sandbox({
|
||||
name: "Addon-SDK",
|
||||
wantXrays: false,
|
||||
wantGlobalProperties: [],
|
||||
invisibleToDebugger: options.invisibleToDebugger || false,
|
||||
metadata: {
|
||||
addonID: options.id,
|
||||
URI: "Addon-SDK"
|
||||
},
|
||||
prototype: options.sandboxPrototype || {}
|
||||
});
|
||||
modules[uri] = freeze(module);
|
||||
}
|
||||
|
||||
// Create the unique sandbox we will be using for all modules,
|
||||
// so that we prevent creating a new comportment per module.
|
||||
// The side effect is that all modules will share the same
|
||||
// global objects.
|
||||
let sharedGlobalSandbox = Sandbox({
|
||||
name: "Addon-SDK",
|
||||
wantXrays: false,
|
||||
wantGlobalProperties: [],
|
||||
invisibleToDebugger: options.invisibleToDebugger || false,
|
||||
metadata: {
|
||||
addonID: options.id,
|
||||
URI: "Addon-SDK"
|
||||
},
|
||||
prototype: options.sandboxPrototype || {}
|
||||
});
|
||||
|
||||
// Loader object is just a representation of a environment
|
||||
// state. We freeze it and mark make it's properties non-enumerable
|
||||
// as they are pure implementation detail that no one should rely upon.
|
||||
@ -946,6 +971,7 @@ function Loader(options) {
|
||||
// Map of module objects indexed by module URIs.
|
||||
modules: { enumerable: false, value: modules },
|
||||
metadata: { enumerable: false, value: metadata },
|
||||
useSharedGlobalSandbox: { enumerable: false, value: !!sharedGlobal },
|
||||
sharedGlobalSandbox: { enumerable: false, value: sharedGlobalSandbox },
|
||||
sharedGlobalBlocklist: { enumerable: false, value: sharedGlobalBlocklist },
|
||||
sharedGlobalBlacklist: { enumerable: false, value: sharedGlobalBlocklist },
|
||||
@ -981,151 +1007,26 @@ function Loader(options) {
|
||||
returnObj.rootURI = { enumerable: false, value: addTrailingSlash(rootURI) };
|
||||
}
|
||||
|
||||
return freeze(create(null, returnObj));
|
||||
return freeze(Object.create(null, returnObj));
|
||||
};
|
||||
Loader.Loader = Loader;
|
||||
|
||||
var isJSONURI = uri => uri.substr(-5) === '.json';
|
||||
var isJSMURI = uri => uri.substr(-4) === '.jsm';
|
||||
var isJSURI = uri => uri.substr(-3) === '.js';
|
||||
var isAbsoluteURI = uri => uri.indexOf("resource://") >= 0 ||
|
||||
uri.indexOf("chrome://") >= 0 ||
|
||||
uri.indexOf("file://") >= 0
|
||||
var isRelative = id => id[0] === '.'
|
||||
var isSystemURI = uri => /^resource:\/\/(gre|devtools|testing-common)\//.test(uri);
|
||||
|
||||
const generateMap = iced(function generateMap(options, callback) {
|
||||
let { rootURI, resolve, paths } = override({
|
||||
paths: {},
|
||||
resolve: Loader.nodeResolve
|
||||
}, options);
|
||||
|
||||
rootURI = addTrailingSlash(rootURI);
|
||||
|
||||
let manifest;
|
||||
let manifestURI = join(rootURI, 'package.json');
|
||||
|
||||
if (rootURI)
|
||||
manifest = JSON.parse(readURI(manifestURI));
|
||||
else
|
||||
throw new Error('No `rootURI` given to generate map');
|
||||
|
||||
let main = getManifestMain(manifest);
|
||||
|
||||
findAllModuleIncludes(main, {
|
||||
resolve: resolve,
|
||||
manifest: manifest,
|
||||
rootURI: rootURI
|
||||
}, {}, callback);
|
||||
|
||||
});
|
||||
Loader.generateMap = generateMap;
|
||||
var isJSONURI = uri => uri.endsWith('.json');
|
||||
var isJSMURI = uri => uri.endsWith('.jsm');
|
||||
var isJSURI = uri => uri.endsWith('.js');
|
||||
var isAbsoluteURI = uri => uri.startsWith("resource://") ||
|
||||
uri.startsWith("chrome://") ||
|
||||
uri.startsWith("file://");
|
||||
var isRelative = id => id.startsWith(".");
|
||||
|
||||
// Default `main` entry to './index.js' and ensure is relative,
|
||||
// since node allows 'lib/index.js' without relative `./`
|
||||
function getManifestMain (manifest) {
|
||||
function getManifestMain(manifest) {
|
||||
let main = manifest.main || './index.js';
|
||||
return isRelative(main) ? main : './' + main;
|
||||
}
|
||||
|
||||
function findAllModuleIncludes (uri, options, results, callback) {
|
||||
let { resolve, manifest, rootURI } = options;
|
||||
results = results || {};
|
||||
|
||||
// Abort if JSON or JSM
|
||||
if (isJSONURI(uri) || isJSMURI(uri)) {
|
||||
callback(results);
|
||||
return;
|
||||
}
|
||||
|
||||
findModuleIncludes(join(rootURI, uri), modules => {
|
||||
// If no modules are included in the file, just call callback immediately
|
||||
if (!modules.length) {
|
||||
callback(results);
|
||||
return;
|
||||
}
|
||||
|
||||
results[uri] = modules.reduce((agg, mod) => {
|
||||
let resolved = resolve(mod, uri, { manifest: manifest, rootURI: rootURI });
|
||||
|
||||
// If resolution found, store the resolution; otherwise,
|
||||
// skip storing it as runtime lookup will handle this
|
||||
if (!resolved)
|
||||
return agg;
|
||||
agg[mod] = resolved;
|
||||
return agg;
|
||||
}, {});
|
||||
|
||||
let includes = keys(results[uri]);
|
||||
let count = 0;
|
||||
let subcallback = () => { if (++count >= includes.length) callback(results) };
|
||||
includes.map(id => {
|
||||
let moduleURI = results[uri][id];
|
||||
if (!results[moduleURI])
|
||||
findAllModuleIncludes(moduleURI, options, results, subcallback);
|
||||
else
|
||||
subcallback();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// From Substack's detector
|
||||
// https://github.com/substack/node-detective
|
||||
//
|
||||
// Given a resource URI or source, return an array of strings passed into
|
||||
// the require statements from the source
|
||||
function findModuleIncludes (uri, callback) {
|
||||
let src = isAbsoluteURI(uri) ? readURI(uri) : uri;
|
||||
let modules = [];
|
||||
|
||||
walk(src, function (node) {
|
||||
if (isRequire(node))
|
||||
modules.push(node.arguments[0].value);
|
||||
});
|
||||
|
||||
callback(modules);
|
||||
}
|
||||
|
||||
function walk (src, callback) {
|
||||
// Import Reflect.jsm from here to prevent loading it until someone uses it
|
||||
let { Reflect } = Cu.import("resource://gre/modules/reflect.jsm", {});
|
||||
let nodes = Reflect.parse(src);
|
||||
traverse(nodes, callback);
|
||||
}
|
||||
|
||||
function traverse (node, cb) {
|
||||
if (Array.isArray(node)) {
|
||||
node.map(x => {
|
||||
if (x != null) {
|
||||
x.parent = node;
|
||||
traverse(x, cb);
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (node && typeof node === 'object') {
|
||||
cb(node);
|
||||
keys(node).map(key => {
|
||||
if (key === 'parent' || !node[key]) return;
|
||||
if (typeof node[key] === "object")
|
||||
node[key].parent = node;
|
||||
traverse(node[key], cb);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// From Substack's detector
|
||||
// https://github.com/substack/node-detective
|
||||
// Check an AST node to see if its a require statement.
|
||||
// A modification added to only evaluate to true if it actually
|
||||
// has a value being passed in as an argument
|
||||
function isRequire (node) {
|
||||
var c = node.callee;
|
||||
return c
|
||||
&& node.type === 'CallExpression'
|
||||
&& c.type === 'Identifier'
|
||||
&& c.name === 'require'
|
||||
&& node.arguments.length
|
||||
&& node.arguments[0].type === 'Literal';
|
||||
}
|
||||
|
||||
module.exports = iced(Loader);
|
||||
});
|
||||
|
@ -22,7 +22,7 @@ if (app.is("Firefox")) {
|
||||
exec(isWindows ? "DIR /A-D" : "ls -al", {
|
||||
cwd: PROFILE_DIR
|
||||
}, (err, stdout, stderr) => {
|
||||
assert.ok(!err, "no errors");
|
||||
assert.equal(err, null, "no errors");
|
||||
assert.equal(stderr, "", "stderr is empty");
|
||||
assert.ok(/extensions\.ini/.test(stdout), "stdout output of `ls -al` finds files");
|
||||
|
||||
|
@ -121,8 +121,8 @@ exports.testExecFileCallbackSuccess = function (assert, done) {
|
||||
|
||||
exports.testExecFileCallbackError = function (assert, done) {
|
||||
execFile('not-real-command', { cwd: PROFILE_DIR }, function (err, stdout, stderr) {
|
||||
assert.ok(/NS_ERROR_FILE_UNRECOGNIZED_PATH/.test(err.message),
|
||||
'error contains error message');
|
||||
assert.ok(/Executable not found/.test(err.message),
|
||||
`error '${err.message}' contains error message`);
|
||||
assert.ok(err.lineNumber >= 0, 'error contains lineNumber');
|
||||
assert.ok(/resource:\/\//.test(err.fileName), 'error contains fileName');
|
||||
assert.equal(stdout, '', 'stdout is empty');
|
||||
|
@ -66,12 +66,7 @@ exports["test dead object errors"] = function(assert, done) {
|
||||
|
||||
loader.unload();
|
||||
|
||||
// in order to get a dead object error on this module, we need to nuke
|
||||
// the relative sandbox; unload the loader is not enough
|
||||
let url = Object.keys(loader.sandboxes).
|
||||
find(url => url.endsWith("/sdk/content/events.js"));
|
||||
|
||||
nuke(loader.sandboxes[url]);
|
||||
nuke(loader.sharedGlobalSandbox);
|
||||
|
||||
system.on("console-api-log-event", onMessage, true);
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
'use strict';
|
||||
|
||||
var {
|
||||
Loader, main, unload, parseStack, generateMap, resolve, join,
|
||||
Loader, main, unload, parseStack, resolve, join,
|
||||
Require, Module
|
||||
} = require('toolkit/loader');
|
||||
var { readURI } = require('sdk/net/url');
|
||||
|
@ -4,7 +4,7 @@
|
||||
'use strict';
|
||||
|
||||
var {
|
||||
Loader, main, unload, parseStack, generateMap, resolve, nodeResolve
|
||||
Loader, main, unload, parseStack, resolve, nodeResolve
|
||||
} = require('toolkit/loader');
|
||||
var { readURI } = require('sdk/net/url');
|
||||
var { all } = require('sdk/core/promise');
|
||||
@ -70,19 +70,6 @@ exports['test bundle'] = function (assert, done) {
|
||||
};
|
||||
*/
|
||||
|
||||
exports['test generateMap()'] = function (assert, done) {
|
||||
getJSON('/fixtures/native-addon-test/expectedmap.json').then(expected => {
|
||||
generateMap({
|
||||
rootURI: root + '/fixtures/native-addon-test/'
|
||||
}, map => {
|
||||
assert.deepEqual(map, expected, 'generateMap returns expected mappings');
|
||||
assert.equal(map['./index.js']['./dir/a'], './dir/a.js',
|
||||
'sanity check on correct mappings');
|
||||
done();
|
||||
});
|
||||
}).then(null, (reason) => console.error(reason));
|
||||
};
|
||||
|
||||
exports['test JSM loading'] = function (assert, done) {
|
||||
getJSON('/fixtures/jsm-package/package.json').then(manifest => {
|
||||
let rootURI = root + '/fixtures/jsm-package/';
|
||||
|
@ -24,9 +24,9 @@
|
||||
"size" : 12072532
|
||||
},
|
||||
{
|
||||
"version": "rustc 1.11.0 (9b21dcd6a 2016-08-15) repack",
|
||||
"size": 131489924,
|
||||
"digest": "59f7463a0da38f324daa4ffc2678d78afb4fe0df13248c1d215bcb996ec05e8521155563cde9a8b719a9b98c5feeaf97cc9e8d52c9b95f6b44728870d908d5b6",
|
||||
"version": "rustc 1.12.0 (3191fbae9 2016-09-23) repack",
|
||||
"size": 102403884,
|
||||
"digest": "a7c1512d955d3030bcc1ebddfbf512f7b11b66e31634726deab78d0403fc0ceadd603d32b08c1a5025d3e9ee4ff48ddcf5eaba33468bb2161cfb9fb1a557affa",
|
||||
"algorithm": "sha512",
|
||||
"filename": "rustc.tar.xz",
|
||||
"unpack": true
|
||||
|
@ -16,9 +16,9 @@
|
||||
"unpack": true
|
||||
},
|
||||
{
|
||||
"version": "rustc 1.11.0 (9b21dcd6a 2016-08-15) repack",
|
||||
"size": 131489924,
|
||||
"digest": "59f7463a0da38f324daa4ffc2678d78afb4fe0df13248c1d215bcb996ec05e8521155563cde9a8b719a9b98c5feeaf97cc9e8d52c9b95f6b44728870d908d5b6",
|
||||
"version": "rustc 1.12.0 (3191fbae9 2016-09-23) repack",
|
||||
"size": 102403884,
|
||||
"digest": "a7c1512d955d3030bcc1ebddfbf512f7b11b66e31634726deab78d0403fc0ceadd603d32b08c1a5025d3e9ee4ff48ddcf5eaba33468bb2161cfb9fb1a557affa",
|
||||
"algorithm": "sha512",
|
||||
"filename": "rustc.tar.xz",
|
||||
"unpack": true
|
||||
|
@ -16,9 +16,9 @@
|
||||
"unpack": true
|
||||
},
|
||||
{
|
||||
"version": "gecko rustc 1.11.0 (9b21dcd6a 2016-08-15) x86_64+i586",
|
||||
"size": 99378568,
|
||||
"digest": "ea5ae0a37ab8c583ef3f9a97c45baf0644feed95f1e6191a4456fd42bbd45b218fe4bc528747a63af55ce67c4b6155bd50f312746628b30e41c421f4d54e5417",
|
||||
"version": "rustc 1.12.0 (3191fbae9 2016-09-23) repack x86_64+i586",
|
||||
"size": 102403884,
|
||||
"digest": "a7c1512d955d3030bcc1ebddfbf512f7b11b66e31634726deab78d0403fc0ceadd603d32b08c1a5025d3e9ee4ff48ddcf5eaba33468bb2161cfb9fb1a557affa",
|
||||
"algorithm": "sha512",
|
||||
"filename": "rustc.tar.xz",
|
||||
"unpack": true
|
||||
|
@ -24,9 +24,9 @@
|
||||
"size" : 12072532
|
||||
},
|
||||
{
|
||||
"version": "rustc 1.11.0 (9b21dcd6a 2016-08-15) repack",
|
||||
"size": 131489924,
|
||||
"digest": "59f7463a0da38f324daa4ffc2678d78afb4fe0df13248c1d215bcb996ec05e8521155563cde9a8b719a9b98c5feeaf97cc9e8d52c9b95f6b44728870d908d5b6",
|
||||
"version": "rustc 1.12.0 (3191fbae9 2016-09-23) repack",
|
||||
"size": 102403884,
|
||||
"digest": "a7c1512d955d3030bcc1ebddfbf512f7b11b66e31634726deab78d0403fc0ceadd603d32b08c1a5025d3e9ee4ff48ddcf5eaba33468bb2161cfb9fb1a557affa",
|
||||
"algorithm": "sha512",
|
||||
"filename": "rustc.tar.xz",
|
||||
"unpack": true
|
||||
|
@ -16,9 +16,9 @@
|
||||
"unpack": true
|
||||
},
|
||||
{
|
||||
"version": "rustc 1.11.0 (9b21dcd6a 2016-08-15) repack",
|
||||
"size": 131489924,
|
||||
"digest": "59f7463a0da38f324daa4ffc2678d78afb4fe0df13248c1d215bcb996ec05e8521155563cde9a8b719a9b98c5feeaf97cc9e8d52c9b95f6b44728870d908d5b6",
|
||||
"version": "rustc 1.12.0 (3191fbae9 2016-09-23) repack",
|
||||
"size": 102403884,
|
||||
"digest": "a7c1512d955d3030bcc1ebddfbf512f7b11b66e31634726deab78d0403fc0ceadd603d32b08c1a5025d3e9ee4ff48ddcf5eaba33468bb2161cfb9fb1a557affa",
|
||||
"algorithm": "sha512",
|
||||
"filename": "rustc.tar.xz",
|
||||
"unpack": true
|
||||
|
@ -55,9 +55,9 @@
|
||||
"filename": "genisoimage.tar.xz"
|
||||
},
|
||||
{
|
||||
"version": "rustc 1.11.0 (9b21dcd6a 2016-08-15) repack",
|
||||
"size": 171059204,
|
||||
"digest": "7554ac993f55818827c80dab90135209e57db70c7c9131bef4309aff3b8d7452c4c0de663df7e8c46bd5702455c36292ade6c7a8007e567c4588c7f91aa88b57",
|
||||
"version": "rustc 1.12.0 (3191fbae9 2016-09-23) repack",
|
||||
"size": 179757256,
|
||||
"digest": "26bbd6a34beab36620634f7eafe63281e3398ae4673b3a4d49e1da4eae0467bc6efc2471ef842682db527ad137e702b74c68f278025c60c8bb69d244cff1e6b6",
|
||||
"algorithm": "sha512",
|
||||
"filename": "rustc.tar.xz",
|
||||
"unpack": true
|
||||
|
@ -8,9 +8,9 @@
|
||||
"unpack": true
|
||||
},
|
||||
{
|
||||
"version": "rustc 1.11.0 (9b21dcd6a 2016-08-15) repack",
|
||||
"size": 146060042,
|
||||
"digest": "c7c5556af0dea1f97a737e4634496d407a5e0f7d14a7013746ad41ef188bab03be60cea59ed63d733dcb03bf11b05d8bf637dc0261f15cd5b0ab46d1199243cf",
|
||||
"version": "rustc 1.12.0 (3191fbae9 2016-09-23) repack",
|
||||
"size": 152905062,
|
||||
"digest": "1fb64d68ad41e5ca444a5a91f752efec154957d22bdf078adbc7b6a1cdbeefbadbc618de96cc46540a33849d43ac95a520a463d4f852e1a5a1f636d7079d969f",
|
||||
"algorithm": "sha512",
|
||||
"filename": "rustc.tar.bz2",
|
||||
"unpack": true
|
||||
|
@ -6,9 +6,9 @@
|
||||
"filename": "mozmake.exe"
|
||||
},
|
||||
{
|
||||
"version": "rustc 1.11.0 (9b21dcd6a 2016-08-15) repack",
|
||||
"size": 86199150,
|
||||
"digest": "fec209dc85a098817c892655fbfda2bd6961199b1c28422994a50daddcb219608673b87dde30b3380555400cf4484863a12d431a6a25ef01cb9b1b32bef48f8b",
|
||||
"version": "rustc 1.12.0 (3191fbae9 2016-09-23) repack",
|
||||
"size": 89434100,
|
||||
"digest": "4da0efd2c36c77f29846f328d9f3c095a7b7e0dfd94f76b3159d441aae02b25007a475a979fb5bf313cf8fecb22fec81684871809effcb6b514419bc3854f398",
|
||||
"algorithm": "sha512",
|
||||
"filename": "rustc.tar.bz2",
|
||||
"unpack": true
|
||||
|
@ -6,9 +6,9 @@
|
||||
"filename": "mozmake.exe"
|
||||
},
|
||||
{
|
||||
"version": "rustc 1.11.0 (9b21dcd6a 2016-08-15) repack",
|
||||
"size": 86199150,
|
||||
"digest": "fec209dc85a098817c892655fbfda2bd6961199b1c28422994a50daddcb219608673b87dde30b3380555400cf4484863a12d431a6a25ef01cb9b1b32bef48f8b",
|
||||
"version": "rustc 1.12.0 (3191fbae9 2016-09-23) repack",
|
||||
"size": 89434100,
|
||||
"digest": "4da0efd2c36c77f29846f328d9f3c095a7b7e0dfd94f76b3159d441aae02b25007a475a979fb5bf313cf8fecb22fec81684871809effcb6b514419bc3854f398",
|
||||
"algorithm": "sha512",
|
||||
"filename": "rustc.tar.bz2",
|
||||
"unpack": true
|
||||
|
@ -6,9 +6,9 @@
|
||||
"filename": "mozmake.exe"
|
||||
},
|
||||
{
|
||||
"version": "rustc 1.11.0 (9b21dcd6a 2016-08-15) repack",
|
||||
"size": 91329933,
|
||||
"digest": "db97f0186db432c57698e287798940abb5946c8903f990b087ea977fb938e83f2f9ca1bf90377bc575563af3144d429cc897a36750a1978a288a42b132c3d25d",
|
||||
"version": "rustc 1.12.0 (3191fbae9 2016-09-23) repack",
|
||||
"size": 94812923,
|
||||
"digest": "f8ff01a44caf38711c352e49c06e8ef6bbac7836bed1050bb043f89ba70f70a11c88001f453baec0cbc56a013efb0fd6b16d612923d07e29b5d8d4512dbaab07",
|
||||
"algorithm": "sha512",
|
||||
"visibility": "public",
|
||||
"filename": "rustc.tar.bz2",
|
||||
|
@ -6,9 +6,9 @@
|
||||
"filename": "mozmake.exe"
|
||||
},
|
||||
{
|
||||
"version": "rustc 1.11.0 (9b21dcd6a 2016-08-15) repack",
|
||||
"size": 91329933,
|
||||
"digest": "db97f0186db432c57698e287798940abb5946c8903f990b087ea977fb938e83f2f9ca1bf90377bc575563af3144d429cc897a36750a1978a288a42b132c3d25d",
|
||||
"version": "rustc 1.12.0 (3191fbae9 2016-09-23) repack",
|
||||
"size": 94812923,
|
||||
"digest": "f8ff01a44caf38711c352e49c06e8ef6bbac7836bed1050bb043f89ba70f70a11c88001f453baec0cbc56a013efb0fd6b16d612923d07e29b5d8d4512dbaab07",
|
||||
"algorithm": "sha512",
|
||||
"visibility": "public",
|
||||
"filename": "rustc.tar.bz2",
|
||||
|
@ -73,10 +73,10 @@ this.ContentWebRTC = {
|
||||
let devices = contentWindow.pendingGetUserMediaRequests.get(callID);
|
||||
forgetGUMRequest(contentWindow, callID);
|
||||
|
||||
let allowedDevices = Cc["@mozilla.org/supports-array;1"]
|
||||
.createInstance(Ci.nsISupportsArray);
|
||||
let allowedDevices = Cc["@mozilla.org/array;1"]
|
||||
.createInstance(Ci.nsIMutableArray);
|
||||
for (let deviceIndex of aMessage.data.devices)
|
||||
allowedDevices.AppendElement(devices[deviceIndex]);
|
||||
allowedDevices.appendElement(devices[deviceIndex], /*weak =*/ false);
|
||||
|
||||
Services.obs.notifyObservers(allowedDevices, "getUserMedia:response:allow", callID);
|
||||
break;
|
||||
@ -261,8 +261,8 @@ function forgetPendingListsEventually(aContentWindow) {
|
||||
}
|
||||
|
||||
function updateIndicators() {
|
||||
let contentWindowSupportsArray = MediaManagerService.activeMediaCaptureWindows;
|
||||
let count = contentWindowSupportsArray.Count();
|
||||
let contentWindowArray = MediaManagerService.activeMediaCaptureWindows;
|
||||
let count = contentWindowArray.length;
|
||||
|
||||
let state = {
|
||||
showGlobalIndicator: count > 0,
|
||||
@ -280,7 +280,7 @@ function updateIndicators() {
|
||||
// sending duplicate notifications.
|
||||
let contentWindows = new Set();
|
||||
for (let i = 0; i < count; ++i) {
|
||||
contentWindows.add(contentWindowSupportsArray.GetElementAt(i).top);
|
||||
contentWindows.add(contentWindowArray.queryElementAt(i, Ci.nsISupports).top);
|
||||
}
|
||||
|
||||
for (let contentWindow of contentWindows) {
|
||||
|
@ -87,7 +87,7 @@ browser.jar:
|
||||
skin/classic/browser/places/autocomplete-star.png (places/autocomplete-star.png)
|
||||
skin/classic/browser/places/autocomplete-star@2x.png (places/autocomplete-star@2x.png)
|
||||
* skin/classic/browser/places/places.css (places/places.css)
|
||||
* skin/classic/browser/places/organizer.css (places/organizer.css)
|
||||
skin/classic/browser/places/organizer.css (places/organizer.css)
|
||||
skin/classic/browser/places/query.png (places/query.png)
|
||||
skin/classic/browser/places/query@2x.png (places/query@2x.png)
|
||||
skin/classic/browser/places/bookmarksMenu.png (places/bookmarksMenu.png)
|
||||
|
@ -2,8 +2,6 @@
|
||||
* 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 ../shared.inc
|
||||
|
||||
/* Places Organizer Sidebars */
|
||||
|
||||
#placesList > treechildren::-moz-tree-row {
|
||||
@ -19,27 +17,11 @@
|
||||
}
|
||||
|
||||
#placesList > treechildren::-moz-tree-row(selected) {
|
||||
background: @sidebarItemBackground@;
|
||||
border-top: @sidebarItemBorderTop@;
|
||||
border-bottom: @sidebarItemBorderBottom@;
|
||||
-moz-appearance: -moz-mac-source-list-selection;
|
||||
}
|
||||
|
||||
#placesList > treechildren::-moz-tree-row(selected,focus) {
|
||||
background: @sidebarItemFocusedBackground@;
|
||||
border-top: @sidebarItemFocusedBorderTop@;
|
||||
border-bottom: @sidebarItemFocusedBorderBottom@;
|
||||
}
|
||||
|
||||
#placesList:-moz-system-metric(mac-graphite-theme) > treechildren::-moz-tree-row(selected) {
|
||||
background: @sidebarItemGraphiteBackground@;
|
||||
border-top: @sidebarItemGraphiteBorderTop@;
|
||||
border-bottom: @sidebarItemGraphiteBorderBottom@;
|
||||
}
|
||||
|
||||
#placesList:-moz-system-metric(mac-graphite-theme) > treechildren::-moz-tree-row(selected,focus) {
|
||||
background: @sidebarItemGraphiteFocusedBackground@;
|
||||
border-top: @sidebarItemGraphiteFocusedBorderTop@;
|
||||
border-bottom: @sidebarItemGraphiteFocusedBorderBottom@;
|
||||
-moz-appearance: -moz-mac-active-source-list-selection;
|
||||
}
|
||||
|
||||
#placesList > treechildren::-moz-tree-row(History),
|
||||
@ -80,30 +62,6 @@
|
||||
}
|
||||
|
||||
@media (-moz-mac-yosemite-theme) {
|
||||
#placesList > treechildren::-moz-tree-row(selected) {
|
||||
background: @sidebarItemBackgroundYosemite@;
|
||||
border-top: none;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
#placesList > treechildren::-moz-tree-row(selected,focus) {
|
||||
background: @sidebarItemFocusedBackgroundYosemite@;
|
||||
border-top: none;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
#placesList > treechildren:-moz-system-metric(mac-graphite-theme)::-moz-tree-row(selected) {
|
||||
background: @sidebarItemGraphiteBackgroundYosemite@;
|
||||
border-top: none;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
#placesList > treechildren:-moz-system-metric(mac-graphite-theme)::-moz-tree-row(selected,focus) {
|
||||
background: @sidebarItemGraphiteFocusedBackgroundYosemite@;
|
||||
border-top: none;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
#placesList > treechildren::-moz-tree-cell-text(selected) {
|
||||
color: -moz-dialogtext;
|
||||
font-weight: 500;
|
||||
|
@ -17,47 +17,35 @@
|
||||
|
||||
.sidebar-placesTree,
|
||||
.sidebar-placesTreechildren::-moz-tree-row {
|
||||
background-color: transparent;
|
||||
border-color: transparent;
|
||||
padding-bottom: 1px;
|
||||
-moz-appearance: none;
|
||||
margin: 0;
|
||||
height: 24px;
|
||||
border: none;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.sidebar-placesTree {
|
||||
-moz-appearance: -moz-mac-source-list;
|
||||
}
|
||||
|
||||
.sidebar-placesTreechildren {
|
||||
border-top: 1px solid #bebebe;
|
||||
}
|
||||
|
||||
.sidebar-placesTreechildren::-moz-tree-separator {
|
||||
border-top: 1px solid #505d6d;
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
.sidebar-placesTree {
|
||||
border-top: 1px solid #bebebe;
|
||||
.sidebar-placesTreechildren::-moz-tree-row {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.sidebar-placesTreechildren::-moz-tree-row(selected) {
|
||||
background: @sidebarItemBackground@;
|
||||
border-top: @sidebarItemBorderTop@;
|
||||
border-bottom: @sidebarItemBorderBottom@;
|
||||
-moz-appearance: -moz-mac-source-list-selection;
|
||||
}
|
||||
|
||||
.sidebar-placesTreechildren::-moz-tree-row(selected,focus) {
|
||||
background: @sidebarItemFocusedBackground@;
|
||||
border-top: @sidebarItemFocusedBorderTop@;
|
||||
border-bottom: @sidebarItemFocusedBorderBottom@;
|
||||
}
|
||||
|
||||
.sidebar-placesTreechildren:-moz-system-metric(mac-graphite-theme)::-moz-tree-row(selected) {
|
||||
background: @sidebarItemGraphiteBackground@;
|
||||
border-top: @sidebarItemGraphiteBorderTop@;
|
||||
border-bottom: @sidebarItemGraphiteBorderBottom@;
|
||||
}
|
||||
|
||||
.sidebar-placesTreechildren:-moz-system-metric(mac-graphite-theme)::-moz-tree-row(selected,focus) {
|
||||
background: @sidebarItemGraphiteFocusedBackground@;
|
||||
border-top: @sidebarItemGraphiteFocusedBorderTop@;
|
||||
border-bottom: @sidebarItemGraphiteFocusedBorderBottom@;
|
||||
-moz-appearance: -moz-mac-active-source-list-selection;
|
||||
}
|
||||
|
||||
.sidebar-placesTreechildren::-moz-tree-cell-text {
|
||||
@ -92,30 +80,6 @@
|
||||
}
|
||||
|
||||
@media (-moz-mac-yosemite-theme) {
|
||||
.sidebar-placesTreechildren::-moz-tree-row(selected) {
|
||||
background: @sidebarItemBackgroundYosemite@;
|
||||
border-top: none;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.sidebar-placesTreechildren::-moz-tree-row(selected,focus) {
|
||||
background: @sidebarItemFocusedBackgroundYosemite@;
|
||||
border-top: none;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.sidebar-placesTreechildren:-moz-system-metric(mac-graphite-theme)::-moz-tree-row(selected) {
|
||||
background: @sidebarItemGraphiteBackgroundYosemite@;
|
||||
border-top: none;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.sidebar-placesTreechildren:-moz-system-metric(mac-graphite-theme)::-moz-tree-row(selected,focus) {
|
||||
background: @sidebarItemGraphiteFocusedBackgroundYosemite@;
|
||||
border-top: none;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.sidebar-placesTreechildren::-moz-tree-cell-text(selected) {
|
||||
color: -moz-dialogtext;
|
||||
font-weight: 500;
|
||||
|
@ -2,12 +2,12 @@
|
||||
* 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 ../shared.inc
|
||||
%include ../../shared/syncedtabs/sidebar.inc.css
|
||||
|
||||
/* These styles are intended to mimic XUL trees and the XUL search box. */
|
||||
|
||||
html {
|
||||
.content-container {
|
||||
-moz-appearance: -moz-mac-source-list;
|
||||
}
|
||||
|
||||
.item {
|
||||
@ -27,15 +27,11 @@ html {
|
||||
}
|
||||
|
||||
.item.selected > .item-title-container {
|
||||
background: @sidebarItemBackground@;
|
||||
border-top: @sidebarItemBorderTop@;
|
||||
border-bottom: @sidebarItemBorderBottom@;
|
||||
-moz-appearance: -moz-mac-source-list-selection;
|
||||
}
|
||||
|
||||
.item.selected:focus > .item-title-container {
|
||||
background: @sidebarItemFocusedBackground@;
|
||||
border-top: @sidebarItemFocusedBorderTop@;
|
||||
border-bottom: @sidebarItemFocusedBorderBottom@;
|
||||
-moz-appearance: -moz-mac-active-source-list-selection;
|
||||
}
|
||||
|
||||
.item.client .item-twisty-container {
|
||||
@ -57,38 +53,6 @@ html {
|
||||
}
|
||||
|
||||
@media (-moz-mac-yosemite-theme) {
|
||||
.item.selected > .item-title-container {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.item.selected > .item-title-container {
|
||||
background-image: none;
|
||||
background-color: @sidebarItemBackgroundYosemite@;
|
||||
border-top: none;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.item.selected:focus > .item-title-container {
|
||||
background-image: none;
|
||||
background-color: @sidebarItemFocusedBackgroundYosemite@;
|
||||
border-top: none;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.item.selected:-moz-system-metric(mac-graphite-theme) > .item-title-container {
|
||||
background-image: none;
|
||||
background-color: @sidebarItemGraphiteBackgroundYosemite@;
|
||||
border-top: none;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.item.selected:focus:-moz-system-metric(mac-graphite-theme) > .item-title-container {
|
||||
background-image: none;
|
||||
background-color: @sidebarItemGraphiteFocusedBackgroundYosemite@;
|
||||
border-top: none;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.item.selected > .item-title-container {
|
||||
color: -moz-dialogtext;
|
||||
font-weight: 500;
|
||||
@ -99,7 +63,6 @@ html {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.sidebar-search-container {
|
||||
border-bottom: 1px solid #bdbdbd;
|
||||
}
|
||||
|
@ -21,11 +21,6 @@ def generate(args):
|
||||
else:
|
||||
raise Exception("File not found: %s" % arg)
|
||||
elif os.path.splitext(arg)[1] == conf.LIB_SUFFIX:
|
||||
# We want to skip static libraries with the name foo-rs-prelink
|
||||
# as they are individually linked for every final library, and
|
||||
# thus should not be included in the descriptor file
|
||||
if '-rs-prelink' in os.path.basename(arg):
|
||||
continue
|
||||
if os.path.exists(arg) or os.path.exists(arg + conf.LIBS_DESC_SUFFIX):
|
||||
desc['LIBS'].append(os.path.abspath(arg))
|
||||
else:
|
||||
|
@ -796,7 +796,7 @@ endif
|
||||
# symlinks back to the originals. The symlinks are a no-op for stabs debugging,
|
||||
# so no need to conditionalize on OS version or debugging format.
|
||||
|
||||
$(SHARED_LIBRARY): $(OBJS) $(RESFILE) $(STATIC_LIBS_DEPS) $(EXTRA_DEPS) $(GLOBAL_DEPS)
|
||||
$(SHARED_LIBRARY): $(OBJS) $(RESFILE) $(RUST_STATIC_LIB_FOR_SHARED_LIB) $(STATIC_LIBS_DEPS) $(EXTRA_DEPS) $(GLOBAL_DEPS)
|
||||
$(REPORT_BUILD)
|
||||
ifndef INCREMENTAL_LINKER
|
||||
$(RM) $@
|
||||
@ -805,10 +805,10 @@ ifdef DTRACE_LIB_DEPENDENT
|
||||
ifndef XP_MACOSX
|
||||
dtrace -x nolibs -G -C -s $(MOZILLA_DTRACE_SRC) -o $(DTRACE_PROBE_OBJ) $(shell $(EXPAND_LIBS) $(MOZILLA_PROBE_LIBS))
|
||||
endif
|
||||
$(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(SUB_SHLOBJS) $(DTRACE_PROBE_OBJ) $(MOZILLA_PROBE_LIBS) $(RESFILE) $(LDFLAGS) $(WRAP_LDFLAGS) $(STATIC_LIBS) $(SHARED_LIBS) $(EXTRA_DSO_LDOPTS) $(MOZ_GLUE_LDFLAGS) $(EXTRA_LIBS) $(OS_LIBS) $(SHLIB_LDENDFILE)
|
||||
$(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(SUB_SHLOBJS) $(DTRACE_PROBE_OBJ) $(MOZILLA_PROBE_LIBS) $(RESFILE) $(LDFLAGS) $(WRAP_LDFLAGS) $(STATIC_LIBS) $(RUST_STATIC_LIB_FOR_SHARED_LIB) $(SHARED_LIBS) $(EXTRA_DSO_LDOPTS) $(MOZ_GLUE_LDFLAGS) $(EXTRA_LIBS) $(OS_LIBS) $(SHLIB_LDENDFILE)
|
||||
@$(RM) $(DTRACE_PROBE_OBJ)
|
||||
else # ! DTRACE_LIB_DEPENDENT
|
||||
$(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(SUB_SHLOBJS) $(RESFILE) $(LDFLAGS) $(WRAP_LDFLAGS) $(STATIC_LIBS) $(SHARED_LIBS) $(EXTRA_DSO_LDOPTS) $(MOZ_GLUE_LDFLAGS) $(EXTRA_LIBS) $(OS_LIBS) $(SHLIB_LDENDFILE)
|
||||
$(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(SUB_SHLOBJS) $(RESFILE) $(LDFLAGS) $(WRAP_LDFLAGS) $(STATIC_LIBS) $(RUST_STATIC_LIB_FOR_SHARED_LIB) $(SHARED_LIBS) $(EXTRA_DSO_LDOPTS) $(MOZ_GLUE_LDFLAGS) $(EXTRA_LIBS) $(OS_LIBS) $(SHLIB_LDENDFILE)
|
||||
endif # DTRACE_LIB_DEPENDENT
|
||||
$(call CHECK_BINARY,$@)
|
||||
|
||||
@ -898,7 +898,7 @@ $(ASOBJS):
|
||||
endif
|
||||
|
||||
ifdef MOZ_RUST
|
||||
ifdef CARGO_FILE
|
||||
ifdef RUST_LIBRARY_FILE
|
||||
|
||||
ifdef MOZ_DEBUG
|
||||
cargo_build_flags =
|
||||
@ -927,30 +927,6 @@ force-cargo-build:
|
||||
|
||||
$(RUST_LIBRARY_FILE): force-cargo-build
|
||||
endif # CARGO_FILE
|
||||
|
||||
ifdef RUST_PRELINK
|
||||
# Make target for building a prelinked rust library. This merges rust .rlibs
|
||||
# together into a single .a file which is used within the FINAL_LIBRARY.
|
||||
#
|
||||
# RUST_PRELINK_FLAGS, RUST_PRELINK_SRC, and RUST_PRELINK_DEPS are set in
|
||||
# recursivemake.py, and together tell rustc how to find the libraries to link
|
||||
# together, but we compute the optimization flags below
|
||||
|
||||
RUST_PRELINK_FLAGS += -g
|
||||
RUST_PRELINK_FLAGS += -C panic=abort
|
||||
|
||||
ifdef MOZ_DEBUG
|
||||
RUST_PRELINK_FLAGS += -C opt-level=1
|
||||
RUST_PRELINK_FLAGS += -C debug-assertions
|
||||
else
|
||||
RUST_PRELINK_FLAGS += -C opt-level=2
|
||||
RUST_PRELINK_FLAGS += -C lto
|
||||
endif
|
||||
|
||||
$(RUST_PRELINK): $(RUST_PRELINK_DEPS) $(RUST_PRELINK_SRC)
|
||||
$(REPORT_BUILD)
|
||||
$(RUSTC) -o $@ --crate-type staticlib --target $(RUST_TARGET) $(RUST_PRELINK_FLAGS) $(RUST_PRELINK_SRC)
|
||||
endif # RUST_PRELINK
|
||||
endif # MOZ_RUST
|
||||
|
||||
$(SOBJS):
|
||||
|
@ -98,15 +98,6 @@ LoadContext::GetNestedFrameId(uint64_t* aId)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
LoadContext::IsAppOfType(uint32_t, bool*)
|
||||
{
|
||||
MOZ_ASSERT(mIsNotNull);
|
||||
|
||||
// don't expect we need this in parent (Thunderbird/SeaMonkey specific?)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
LoadContext::GetIsContent(bool* aIsContent)
|
||||
{
|
||||
|
@ -9738,6 +9738,20 @@ nsDocShell::InternalLoad(nsIURI* aURI,
|
||||
nsIDocShell** aDocShell,
|
||||
nsIRequest** aRequest)
|
||||
{
|
||||
// In most cases both principals (aTriggeringPrincipal and aPrincipalToInherit)
|
||||
// are both null or both non-null. For the exceptional cases let's make sure that:
|
||||
// * if aTriggeringPrincipal is null then either aPrincipalToInherit is null or
|
||||
// it's a NullPrincipal
|
||||
// * if aPrincipalToInherit is null then either aTriggeringPrincipal is null or
|
||||
// it's a NullPrincipal or INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL is set.
|
||||
MOZ_ASSERT(aTriggeringPrincipal ||
|
||||
(!aPrincipalToInherit ||
|
||||
aPrincipalToInherit->GetIsNullPrincipal()));
|
||||
MOZ_ASSERT(aPrincipalToInherit ||
|
||||
(!aTriggeringPrincipal ||
|
||||
aTriggeringPrincipal->GetIsNullPrincipal() ||
|
||||
(aFlags & INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL)));
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
mOriginalUriString.Truncate();
|
||||
|
||||
@ -9929,12 +9943,26 @@ nsDocShell::InternalLoad(nsIURI* aURI,
|
||||
{
|
||||
bool inherits;
|
||||
// One more twist: Don't inherit the principal for external loads.
|
||||
if (aLoadType != LOAD_NORMAL_EXTERNAL && !principalToInherit &&
|
||||
(aFlags & INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL) &&
|
||||
if (!principalToInherit &&
|
||||
NS_SUCCEEDED(nsContentUtils::URIInheritsSecurityContext(aURI,
|
||||
&inherits)) &&
|
||||
inherits) {
|
||||
principalToInherit = GetInheritedPrincipal(true);
|
||||
if (aLoadType != LOAD_NORMAL_EXTERNAL &&
|
||||
(aFlags & INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL)) {
|
||||
principalToInherit = GetInheritedPrincipal(true);
|
||||
}
|
||||
|
||||
// In case we don't have a principalToInherit and the TriggeringPrincipal
|
||||
// either already is a SystemPrincipal or would fall back to become
|
||||
// a SystemPrincipal within the loadInfo then we should explicitly set
|
||||
// the principalToInherit to a freshly created NullPrincipal.
|
||||
if (!principalToInherit &&
|
||||
(nsContentUtils::IsSystemPrincipal(aTriggeringPrincipal) ||
|
||||
(!aTriggeringPrincipal && !aReferrer))) {
|
||||
// We're going to default to inheriting our system triggering principal,
|
||||
// more or less by accident. This doesn't seem like a good idea.
|
||||
principalToInherit = nsNullPrincipal::CreateWithInheritedAttributes(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -12300,7 +12328,7 @@ nsDocShell::AddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel,
|
||||
pAttrs.InheritFromNecko(nAttrs);
|
||||
principalToInherit = nsNullPrincipal::Create(pAttrs);
|
||||
}
|
||||
} else if (loadInfo->GetForceInheritPrincipal()) {
|
||||
} else {
|
||||
principalToInherit = loadInfo->PrincipalToInherit();
|
||||
}
|
||||
}
|
||||
@ -13556,24 +13584,6 @@ nsDocShell::GetNestedFrameId(uint64_t* aId)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::IsAppOfType(uint32_t aAppType, bool* aIsOfType)
|
||||
{
|
||||
RefPtr<nsDocShell> shell = this;
|
||||
while (shell) {
|
||||
uint32_t type;
|
||||
shell->GetAppType(&type);
|
||||
if (type == aAppType) {
|
||||
*aIsOfType = true;
|
||||
return NS_OK;
|
||||
}
|
||||
shell = shell->GetParentDocshell();
|
||||
}
|
||||
|
||||
*aIsOfType = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::IsTrackingProtectionOn(bool* aIsTrackingProtectionOn)
|
||||
{
|
||||
|
@ -224,7 +224,6 @@ public:
|
||||
NS_IMETHOD GetTopWindow(mozIDOMWindowProxy**) override;
|
||||
NS_IMETHOD GetTopFrameElement(nsIDOMElement**) override;
|
||||
NS_IMETHOD GetNestedFrameId(uint64_t*) override;
|
||||
NS_IMETHOD IsAppOfType(uint32_t, bool*) override;
|
||||
NS_IMETHOD GetIsContent(bool*) override;
|
||||
NS_IMETHOD GetUsePrivateBrowsing(bool*) override;
|
||||
NS_IMETHOD SetUsePrivateBrowsing(bool) override;
|
||||
@ -296,9 +295,10 @@ private:
|
||||
friend void mozilla::TimelineConsumers::AddConsumer(nsDocShell*);
|
||||
friend void mozilla::TimelineConsumers::RemoveConsumer(nsDocShell*);
|
||||
friend void mozilla::TimelineConsumers::AddMarkerForDocShell(
|
||||
nsDocShell*, const char*, MarkerTracingType);
|
||||
nsDocShell*, const char*, MarkerTracingType, MarkerStackRequest);
|
||||
friend void mozilla::TimelineConsumers::AddMarkerForDocShell(
|
||||
nsDocShell*, const char*, const TimeStamp&, MarkerTracingType);
|
||||
nsDocShell*, const char*, const TimeStamp&, MarkerTracingType,
|
||||
MarkerStackRequest);
|
||||
friend void mozilla::TimelineConsumers::AddMarkerForDocShell(
|
||||
nsDocShell*, UniquePtr<AbstractTimelineMarker>&&);
|
||||
friend void mozilla::TimelineConsumers::PopMarkers(nsDocShell*,
|
||||
|
@ -132,8 +132,35 @@ interface nsIDocShell : nsIDocShellTreeItem
|
||||
* ignored.
|
||||
* @param aReferrer - Referring URI
|
||||
* @param aReferrerPolicy - Referrer policy
|
||||
* @param aTriggeringPrincipal - Principal that initiated that load
|
||||
* @param aPrincipalToInherit - Principal to be inherited for that load
|
||||
* @param aTriggeringPrincipal - Principal that initiated that load. If passing
|
||||
* null for this argument, then internally a
|
||||
* principal is created from aReferrer. If
|
||||
* aReferrer is also null, then the
|
||||
* triggeringPrincipal defaults to the
|
||||
* SystemPrincipal. Please note that this is the
|
||||
* principal that is used for security checks. If
|
||||
* the argument aURI is provided by the web, then
|
||||
* please pass an explicit triggeringPrincipal to
|
||||
* avoid the fallback to SystemPrincipal and
|
||||
* hence a potential security risk.
|
||||
* If aTriggeringPrincipal is null then either
|
||||
* aPrincipalToInherit is null or it's
|
||||
* a NullPrincipal.
|
||||
* @param aPrincipalToInherit - Principal to be inherited for that load. If
|
||||
* passing null for this argument, then internally
|
||||
* the triggeringPrincipal is also used for the
|
||||
* principalToInherit. There are cases where those
|
||||
* two principals need to be different though.
|
||||
* E.g. the system might initiate a load for
|
||||
* 'about:blank', hence SystemPrincipal is passed
|
||||
* for aTriggeringPrincipal. But the principal to
|
||||
* be inherited for that load should be a
|
||||
* NullPrincipal and not the SystemPrincipal.
|
||||
* In that case, please pass a non null
|
||||
* principalToInherit.
|
||||
* If aPrincipalToInherit is null then either
|
||||
* aTriggeringPrincipal is null or
|
||||
* INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL is set.
|
||||
* @param aFlags - Any of the load flags defined within above.
|
||||
* @param aStopActiveDoc - Flag indicating whether loading the current
|
||||
* document should be stopped.
|
||||
|
@ -60,17 +60,6 @@ interface nsILoadContext : nsISupports
|
||||
*/
|
||||
readonly attribute unsigned long long nestedFrameId;
|
||||
|
||||
/**
|
||||
* Check whether the load is happening in a particular type of application.
|
||||
*
|
||||
* @param an application type. For now, the constants to be passed here are
|
||||
* the nsIDocShell APP_TYPE_* constants.
|
||||
*
|
||||
* @return whether there is some ancestor of the associatedWindow that is of
|
||||
* the given app type.
|
||||
*/
|
||||
boolean isAppOfType(in unsigned long appType);
|
||||
|
||||
/**
|
||||
* True if the load context is content (as opposed to chrome). This is
|
||||
* determined based on the type of window the load is performed in, NOT based
|
||||
|
@ -173,11 +173,12 @@ TimelineConsumers::IsEmpty()
|
||||
void
|
||||
TimelineConsumers::AddMarkerForDocShell(nsDocShell* aDocShell,
|
||||
const char* aName,
|
||||
MarkerTracingType aTracingType)
|
||||
MarkerTracingType aTracingType,
|
||||
MarkerStackRequest aStackRequest)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (HasConsumer(aDocShell)) {
|
||||
aDocShell->mObserved->AddMarker(Move(MakeUnique<TimelineMarker>(aName, aTracingType)));
|
||||
aDocShell->mObserved->AddMarker(Move(MakeUnique<TimelineMarker>(aName, aTracingType, aStackRequest)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -185,11 +186,12 @@ void
|
||||
TimelineConsumers::AddMarkerForDocShell(nsDocShell* aDocShell,
|
||||
const char* aName,
|
||||
const TimeStamp& aTime,
|
||||
MarkerTracingType aTracingType)
|
||||
MarkerTracingType aTracingType,
|
||||
MarkerStackRequest aStackRequest)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (HasConsumer(aDocShell)) {
|
||||
aDocShell->mObserved->AddMarker(Move(MakeUnique<TimelineMarker>(aName, aTime, aTracingType)));
|
||||
aDocShell->mObserved->AddMarker(Move(MakeUnique<TimelineMarker>(aName, aTime, aTracingType, aStackRequest)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -206,20 +208,22 @@ TimelineConsumers::AddMarkerForDocShell(nsDocShell* aDocShell,
|
||||
void
|
||||
TimelineConsumers::AddMarkerForDocShell(nsIDocShell* aDocShell,
|
||||
const char* aName,
|
||||
MarkerTracingType aTracingType)
|
||||
MarkerTracingType aTracingType,
|
||||
MarkerStackRequest aStackRequest)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
AddMarkerForDocShell(static_cast<nsDocShell*>(aDocShell), aName, aTracingType);
|
||||
AddMarkerForDocShell(static_cast<nsDocShell*>(aDocShell), aName, aTracingType, aStackRequest);
|
||||
}
|
||||
|
||||
void
|
||||
TimelineConsumers::AddMarkerForDocShell(nsIDocShell* aDocShell,
|
||||
const char* aName,
|
||||
const TimeStamp& aTime,
|
||||
MarkerTracingType aTracingType)
|
||||
MarkerTracingType aTracingType,
|
||||
MarkerStackRequest aStackRequest)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
AddMarkerForDocShell(static_cast<nsDocShell*>(aDocShell), aName, aTime, aTracingType);
|
||||
AddMarkerForDocShell(static_cast<nsDocShell*>(aDocShell), aName, aTime, aTracingType, aStackRequest);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -71,19 +71,23 @@ public:
|
||||
// Main thread only.
|
||||
void AddMarkerForDocShell(nsDocShell* aDocShell,
|
||||
const char* aName,
|
||||
MarkerTracingType aTracingType);
|
||||
MarkerTracingType aTracingType,
|
||||
MarkerStackRequest aStackRequest = MarkerStackRequest::STACK);
|
||||
void AddMarkerForDocShell(nsIDocShell* aDocShell,
|
||||
const char* aName,
|
||||
MarkerTracingType aTracingType);
|
||||
MarkerTracingType aTracingType,
|
||||
MarkerStackRequest aStackRequest = MarkerStackRequest::STACK);
|
||||
|
||||
void AddMarkerForDocShell(nsDocShell* aDocShell,
|
||||
const char* aName,
|
||||
const TimeStamp& aTime,
|
||||
MarkerTracingType aTracingType);
|
||||
MarkerTracingType aTracingType,
|
||||
MarkerStackRequest aStackRequest = MarkerStackRequest::STACK);
|
||||
void AddMarkerForDocShell(nsIDocShell* aDocShell,
|
||||
const char* aName,
|
||||
const TimeStamp& aTime,
|
||||
MarkerTracingType aTracingType);
|
||||
MarkerTracingType aTracingType,
|
||||
MarkerStackRequest aStackRequest = MarkerStackRequest::STACK);
|
||||
|
||||
// These methods register and receive ownership of an already created marker,
|
||||
// relevant for a specific docshell.
|
||||
|
@ -157,10 +157,6 @@ this.AppsUtils = {
|
||||
usePrivateBrowsing: false,
|
||||
isContent: false,
|
||||
|
||||
isAppOfType: function(appType) {
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsILoadContext,
|
||||
Ci.nsIInterfaceRequestor,
|
||||
Ci.nsISupports]),
|
||||
|
@ -4,9 +4,9 @@
|
||||
* 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/CustomElementsRegistry.h"
|
||||
#include "mozilla/dom/CustomElementRegistry.h"
|
||||
|
||||
#include "mozilla/dom/CustomElementsRegistryBinding.h"
|
||||
#include "mozilla/dom/CustomElementRegistryBinding.h"
|
||||
#include "mozilla/dom/HTMLElementBinding.h"
|
||||
#include "mozilla/dom/WebComponentsBinding.h"
|
||||
#include "nsIParserService.h"
|
||||
@ -99,16 +99,16 @@ CustomElementData::RunCallbackQueue()
|
||||
}
|
||||
|
||||
// Only needed for refcounted objects.
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(CustomElementsRegistry)
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(CustomElementRegistry)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(CustomElementsRegistry)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(CustomElementRegistry)
|
||||
tmp->mCustomDefinitions.Clear();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWhenDefinedPromiseMap)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CustomElementsRegistry)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CustomElementRegistry)
|
||||
for (auto iter = tmp->mCustomDefinitions.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsAutoPtr<LifecycleCallbacks>& callbacks = iter.UserData()->mCallbacks;
|
||||
|
||||
@ -141,7 +141,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CustomElementsRegistry)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(CustomElementsRegistry)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(CustomElementRegistry)
|
||||
for (auto iter = tmp->mCustomDefinitions.Iter(); !iter.Done(); iter.Next()) {
|
||||
aCallbacks.Trace(&iter.UserData()->mConstructor,
|
||||
"mCustomDefinitions constructor",
|
||||
@ -153,16 +153,16 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(CustomElementsRegistry)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(CustomElementsRegistry)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(CustomElementsRegistry)
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(CustomElementRegistry)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(CustomElementRegistry)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CustomElementsRegistry)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CustomElementRegistry)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
/* static */ bool
|
||||
CustomElementsRegistry::IsCustomElementsEnabled(JSContext* aCx, JSObject* aObject)
|
||||
CustomElementRegistry::IsCustomElementEnabled(JSContext* aCx, JSObject* aObject)
|
||||
{
|
||||
JS::Rooted<JSObject*> obj(aCx, aObject);
|
||||
if (Preferences::GetBool("dom.webcomponents.customelements.enabled") ||
|
||||
@ -173,8 +173,8 @@ CustomElementsRegistry::IsCustomElementsEnabled(JSContext* aCx, JSObject* aObjec
|
||||
return false;
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<CustomElementsRegistry>
|
||||
CustomElementsRegistry::Create(nsPIDOMWindowInner* aWindow)
|
||||
/* static */ already_AddRefed<CustomElementRegistry>
|
||||
CustomElementRegistry::Create(nsPIDOMWindowInner* aWindow)
|
||||
{
|
||||
MOZ_ASSERT(aWindow);
|
||||
MOZ_ASSERT(aWindow->IsInnerWindow());
|
||||
@ -188,13 +188,13 @@ CustomElementsRegistry::Create(nsPIDOMWindowInner* aWindow)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<CustomElementsRegistry> customElementsRegistry =
|
||||
new CustomElementsRegistry(aWindow);
|
||||
return customElementsRegistry.forget();
|
||||
RefPtr<CustomElementRegistry> customElementRegistry =
|
||||
new CustomElementRegistry(aWindow);
|
||||
return customElementRegistry.forget();
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
CustomElementsRegistry::ProcessTopElementQueue()
|
||||
CustomElementRegistry::ProcessTopElementQueue()
|
||||
{
|
||||
MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
|
||||
|
||||
@ -222,15 +222,15 @@ CustomElementsRegistry::ProcessTopElementQueue()
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
CustomElementsRegistry::XPCOMShutdown()
|
||||
CustomElementRegistry::XPCOMShutdown()
|
||||
{
|
||||
sProcessingStack.reset();
|
||||
}
|
||||
|
||||
/* static */ Maybe<nsTArray<RefPtr<CustomElementData>>>
|
||||
CustomElementsRegistry::sProcessingStack;
|
||||
CustomElementRegistry::sProcessingStack;
|
||||
|
||||
CustomElementsRegistry::CustomElementsRegistry(nsPIDOMWindowInner* aWindow)
|
||||
CustomElementRegistry::CustomElementRegistry(nsPIDOMWindowInner* aWindow)
|
||||
: mWindow(aWindow)
|
||||
, mIsCustomDefinitionRunning(false)
|
||||
{
|
||||
@ -243,14 +243,14 @@ CustomElementsRegistry::CustomElementsRegistry(nsPIDOMWindowInner* aWindow)
|
||||
}
|
||||
}
|
||||
|
||||
CustomElementsRegistry::~CustomElementsRegistry()
|
||||
CustomElementRegistry::~CustomElementRegistry()
|
||||
{
|
||||
mozilla::DropJSObjects(this);
|
||||
}
|
||||
|
||||
CustomElementDefinition*
|
||||
CustomElementsRegistry::LookupCustomElementDefinition(const nsAString& aLocalName,
|
||||
const nsAString* aIs) const
|
||||
CustomElementRegistry::LookupCustomElementDefinition(const nsAString& aLocalName,
|
||||
const nsAString* aIs) const
|
||||
{
|
||||
nsCOMPtr<nsIAtom> localNameAtom = NS_Atomize(aLocalName);
|
||||
nsCOMPtr<nsIAtom> typeAtom = aIs ? NS_Atomize(*aIs) : localNameAtom;
|
||||
@ -264,7 +264,7 @@ CustomElementsRegistry::LookupCustomElementDefinition(const nsAString& aLocalNam
|
||||
}
|
||||
|
||||
void
|
||||
CustomElementsRegistry::RegisterUnresolvedElement(Element* aElement, nsIAtom* aTypeName)
|
||||
CustomElementRegistry::RegisterUnresolvedElement(Element* aElement, nsIAtom* aTypeName)
|
||||
{
|
||||
mozilla::dom::NodeInfo* info = aElement->NodeInfo();
|
||||
|
||||
@ -289,8 +289,8 @@ CustomElementsRegistry::RegisterUnresolvedElement(Element* aElement, nsIAtom* aT
|
||||
}
|
||||
|
||||
void
|
||||
CustomElementsRegistry::SetupCustomElement(Element* aElement,
|
||||
const nsAString* aTypeExtension)
|
||||
CustomElementRegistry::SetupCustomElement(Element* aElement,
|
||||
const nsAString* aTypeExtension)
|
||||
{
|
||||
nsCOMPtr<nsIAtom> tagAtom = aElement->NodeInfo()->NameAtom();
|
||||
nsCOMPtr<nsIAtom> typeAtom = aTypeExtension ?
|
||||
@ -326,10 +326,10 @@ CustomElementsRegistry::SetupCustomElement(Element* aElement,
|
||||
}
|
||||
|
||||
void
|
||||
CustomElementsRegistry::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType,
|
||||
Element* aCustomElement,
|
||||
LifecycleCallbackArgs* aArgs,
|
||||
CustomElementDefinition* aDefinition)
|
||||
CustomElementRegistry::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType,
|
||||
Element* aCustomElement,
|
||||
LifecycleCallbackArgs* aArgs,
|
||||
CustomElementDefinition* aDefinition)
|
||||
{
|
||||
CustomElementData* elementData = aCustomElement->GetCustomElementData();
|
||||
|
||||
@ -443,15 +443,15 @@ CustomElementsRegistry::EnqueueLifecycleCallback(nsIDocument::ElementCallbackTyp
|
||||
// Create a script runner to process the top of the processing
|
||||
// stack as soon as it is safe to run script.
|
||||
nsCOMPtr<nsIRunnable> runnable =
|
||||
NS_NewRunnableFunction(&CustomElementsRegistry::ProcessTopElementQueue);
|
||||
NS_NewRunnableFunction(&CustomElementRegistry::ProcessTopElementQueue);
|
||||
nsContentUtils::AddScriptRunner(runnable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CustomElementsRegistry::GetCustomPrototype(nsIAtom* aAtom,
|
||||
JS::MutableHandle<JSObject*> aPrototype)
|
||||
CustomElementRegistry::GetCustomPrototype(nsIAtom* aAtom,
|
||||
JS::MutableHandle<JSObject*> aPrototype)
|
||||
{
|
||||
mozilla::dom::CustomElementDefinition* definition = mCustomDefinitions.Get(aAtom);
|
||||
if (definition) {
|
||||
@ -462,9 +462,9 @@ CustomElementsRegistry::GetCustomPrototype(nsIAtom* aAtom,
|
||||
}
|
||||
|
||||
void
|
||||
CustomElementsRegistry::UpgradeCandidates(JSContext* aCx,
|
||||
nsIAtom* aKey,
|
||||
CustomElementDefinition* aDefinition)
|
||||
CustomElementRegistry::UpgradeCandidates(JSContext* aCx,
|
||||
nsIAtom* aKey,
|
||||
CustomElementDefinition* aDefinition)
|
||||
{
|
||||
nsAutoPtr<nsTArray<nsWeakPtr>> candidates;
|
||||
mCandidatesMap.RemoveAndForget(aKey, candidates);
|
||||
@ -509,12 +509,12 @@ CustomElementsRegistry::UpgradeCandidates(JSContext* aCx,
|
||||
}
|
||||
|
||||
JSObject*
|
||||
CustomElementsRegistry::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
CustomElementRegistry::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return CustomElementsRegistryBinding::Wrap(aCx, this, aGivenProto);
|
||||
return CustomElementRegistryBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
nsISupports* CustomElementsRegistry::GetParentObject() const
|
||||
nsISupports* CustomElementRegistry::GetParentObject() const
|
||||
{
|
||||
return mWindow;
|
||||
}
|
||||
@ -558,10 +558,10 @@ CheckLifeCycleCallbacks(JSContext* aCx,
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/scripting.html#element-definition
|
||||
void
|
||||
CustomElementsRegistry::Define(const nsAString& aName,
|
||||
Function& aFunctionConstructor,
|
||||
const ElementDefinitionOptions& aOptions,
|
||||
ErrorResult& aRv)
|
||||
CustomElementRegistry::Define(const nsAString& aName,
|
||||
Function& aFunctionConstructor,
|
||||
const ElementDefinitionOptions& aOptions,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
aRv.MightThrowJSException();
|
||||
|
||||
@ -589,7 +589,7 @@ CustomElementsRegistry::Define(const nsAString& aName,
|
||||
}
|
||||
|
||||
if (!JS::IsConstructor(constructorUnwrapped)) {
|
||||
aRv.ThrowTypeError<MSG_NOT_CONSTRUCTOR>(NS_LITERAL_STRING("Argument 2 of CustomElementsRegistry.define"));
|
||||
aRv.ThrowTypeError<MSG_NOT_CONSTRUCTOR>(NS_LITERAL_STRING("Argument 2 of CustomElementRegistry.define"));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -604,7 +604,7 @@ CustomElementsRegistry::Define(const nsAString& aName,
|
||||
}
|
||||
|
||||
/**
|
||||
* 3. If this CustomElementsRegistry contains an entry with name name, then
|
||||
* 3. If this CustomElementRegistry contains an entry with name name, then
|
||||
* throw a "NotSupportedError" DOMException and abort these steps.
|
||||
*/
|
||||
if (mCustomDefinitions.Get(nameAtom)) {
|
||||
@ -613,7 +613,7 @@ CustomElementsRegistry::Define(const nsAString& aName,
|
||||
}
|
||||
|
||||
/**
|
||||
* 4. If this CustomElementsRegistry contains an entry with constructor constructor,
|
||||
* 4. If this CustomElementRegistry contains an entry with constructor constructor,
|
||||
* then throw a "NotSupportedError" DOMException and abort these steps.
|
||||
*/
|
||||
// TODO: Step 3 of HTMLConstructor also needs a way to look up definition by
|
||||
@ -772,7 +772,7 @@ CustomElementsRegistry::Define(const nsAString& aName,
|
||||
0 /* TODO dependent on HTML imports. Bug 877072 */);
|
||||
|
||||
/**
|
||||
* 12. Add definition to this CustomElementsRegistry.
|
||||
* 12. Add definition to this CustomElementRegistry.
|
||||
*/
|
||||
mCustomDefinitions.Put(nameAtom, definition);
|
||||
|
||||
@ -783,11 +783,11 @@ CustomElementsRegistry::Define(const nsAString& aName,
|
||||
UpgradeCandidates(cx, nameAtom, definition);
|
||||
|
||||
/**
|
||||
* 16. If this CustomElementsRegistry's when-defined promise map contains an
|
||||
* 16. If this CustomElementRegistry's when-defined promise map contains an
|
||||
* entry with key name:
|
||||
* 1. Let promise be the value of that entry.
|
||||
* 2. Resolve promise with undefined.
|
||||
* 3. Delete the entry with key name from this CustomElementsRegistry's
|
||||
* 3. Delete the entry with key name from this CustomElementRegistry's
|
||||
* when-defined promise map.
|
||||
*/
|
||||
RefPtr<Promise> promise;
|
||||
@ -799,8 +799,8 @@ CustomElementsRegistry::Define(const nsAString& aName,
|
||||
}
|
||||
|
||||
void
|
||||
CustomElementsRegistry::Get(JSContext* aCx, const nsAString& aName,
|
||||
JS::MutableHandle<JS::Value> aRetVal)
|
||||
CustomElementRegistry::Get(JSContext* aCx, const nsAString& aName,
|
||||
JS::MutableHandle<JS::Value> aRetVal)
|
||||
{
|
||||
nsCOMPtr<nsIAtom> nameAtom(NS_Atomize(aName));
|
||||
CustomElementDefinition* data = mCustomDefinitions.Get(nameAtom);
|
||||
@ -815,7 +815,7 @@ CustomElementsRegistry::Get(JSContext* aCx, const nsAString& aName,
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
CustomElementsRegistry::WhenDefined(const nsAString& aName, ErrorResult& aRv)
|
||||
CustomElementRegistry::WhenDefined(const nsAString& aName, ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(mWindow);
|
||||
RefPtr<Promise> promise = Promise::Create(global, aRv);
|
@ -4,8 +4,8 @@
|
||||
* 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_CustomElementsRegistry_h
|
||||
#define mozilla_dom_CustomElementsRegistry_h
|
||||
#ifndef mozilla_dom_CustomElementRegistry_h
|
||||
#define mozilla_dom_CustomElementRegistry_h
|
||||
|
||||
#include "js/TypeDecls.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
@ -129,19 +129,19 @@ struct CustomElementDefinition
|
||||
uint32_t mDocOrder;
|
||||
};
|
||||
|
||||
class CustomElementsRegistry final : public nsISupports,
|
||||
public nsWrapperCache
|
||||
class CustomElementRegistry final : public nsISupports,
|
||||
public nsWrapperCache
|
||||
{
|
||||
// Allow nsDocument to access mCustomDefinitions and mCandidatesMap.
|
||||
friend class ::nsDocument;
|
||||
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(CustomElementsRegistry)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(CustomElementRegistry)
|
||||
|
||||
public:
|
||||
static bool IsCustomElementsEnabled(JSContext* aCx, JSObject* aObject);
|
||||
static already_AddRefed<CustomElementsRegistry> Create(nsPIDOMWindowInner* aWindow);
|
||||
static bool IsCustomElementEnabled(JSContext* aCx, JSObject* aObject);
|
||||
static already_AddRefed<CustomElementRegistry> Create(nsPIDOMWindowInner* aWindow);
|
||||
static void ProcessTopElementQueue();
|
||||
|
||||
static void XPCOMShutdown();
|
||||
@ -169,8 +169,8 @@ public:
|
||||
JS::MutableHandle<JSObject*> aPrototype);
|
||||
|
||||
private:
|
||||
explicit CustomElementsRegistry(nsPIDOMWindowInner* aWindow);
|
||||
~CustomElementsRegistry();
|
||||
explicit CustomElementRegistry(nsPIDOMWindowInner* aWindow);
|
||||
~CustomElementRegistry();
|
||||
|
||||
/**
|
||||
* Registers an unresolved custom element that is a candidate for
|
||||
@ -221,7 +221,7 @@ private:
|
||||
private:
|
||||
class MOZ_RAII AutoSetRunningFlag final {
|
||||
public:
|
||||
explicit AutoSetRunningFlag(CustomElementsRegistry* aRegistry)
|
||||
explicit AutoSetRunningFlag(CustomElementRegistry* aRegistry)
|
||||
: mRegistry(aRegistry)
|
||||
{
|
||||
MOZ_ASSERT(!mRegistry->mIsCustomDefinitionRunning,
|
||||
@ -234,7 +234,7 @@ private:
|
||||
}
|
||||
|
||||
private:
|
||||
CustomElementsRegistry* mRegistry;
|
||||
CustomElementRegistry* mRegistry;
|
||||
};
|
||||
|
||||
public:
|
||||
@ -255,4 +255,4 @@ public:
|
||||
} // namespace mozilla
|
||||
|
||||
|
||||
#endif // mozilla_dom_CustomElementsRegistry_h
|
||||
#endif // mozilla_dom_CustomElementRegistry_h
|
@ -2813,9 +2813,9 @@ Element::DescribeAttribute(uint32_t index, nsAString& aOutDescription) const
|
||||
aOutDescription.AppendLiteral("=\"");
|
||||
nsAutoString value;
|
||||
mAttrsAndChildren.AttrAt(index)->ToString(value);
|
||||
for (int i = value.Length(); i >= 0; --i) {
|
||||
if (value[i] == char16_t('"'))
|
||||
value.Insert(char16_t('\\'), uint32_t(i));
|
||||
for (uint32_t i = value.Length(); i > 0; --i) {
|
||||
if (value[i - 1] == char16_t('"'))
|
||||
value.Insert(char16_t('\\'), i - 1);
|
||||
}
|
||||
aOutDescription.Append(value);
|
||||
aOutDescription.Append('"');
|
||||
@ -3723,7 +3723,8 @@ Element::InsertAdjacent(const nsAString& aWhere,
|
||||
}
|
||||
parent->InsertBefore(*aNode, this, aError);
|
||||
} else if (aWhere.LowerCaseEqualsLiteral("afterbegin")) {
|
||||
static_cast<nsINode*>(this)->InsertBefore(*aNode, GetFirstChild(), aError);
|
||||
nsCOMPtr<nsINode> refNode = GetFirstChild();
|
||||
static_cast<nsINode*>(this)->InsertBefore(*aNode, refNode, aError);
|
||||
} else if (aWhere.LowerCaseEqualsLiteral("beforeend")) {
|
||||
static_cast<nsINode*>(this)->AppendChild(*aNode, aError);
|
||||
} else if (aWhere.LowerCaseEqualsLiteral("afterend")) {
|
||||
@ -3731,7 +3732,8 @@ Element::InsertAdjacent(const nsAString& aWhere,
|
||||
if (!parent) {
|
||||
return nullptr;
|
||||
}
|
||||
parent->InsertBefore(*aNode, GetNextSibling(), aError);
|
||||
nsCOMPtr<nsINode> refNode = GetNextSibling();
|
||||
parent->InsertBefore(*aNode, refNode, aError);
|
||||
} else {
|
||||
aError.Throw(NS_ERROR_DOM_SYNTAX_ERR);
|
||||
return nullptr;
|
||||
|
@ -136,7 +136,7 @@ class EventStateManager;
|
||||
namespace dom {
|
||||
|
||||
class Animation;
|
||||
class CustomElementsRegistry;
|
||||
class CustomElementRegistry;
|
||||
class Link;
|
||||
class UndoManager;
|
||||
class DOMRect;
|
||||
@ -427,7 +427,7 @@ private:
|
||||
friend class ::nsFocusManager;
|
||||
|
||||
// Allow CusomtElementRegistry to call AddStates.
|
||||
friend class CustomElementsRegistry;
|
||||
friend class CustomElementRegistry;
|
||||
|
||||
// Also need to allow Link to call UpdateLinkState.
|
||||
friend class Link;
|
||||
@ -748,17 +748,15 @@ public:
|
||||
aError.Throw(NS_ERROR_DOM_INVALID_POINTER_ERR);
|
||||
return;
|
||||
}
|
||||
nsIPresShell::PointerCaptureInfo* pointerCaptureInfo = nullptr;
|
||||
if (nsIPresShell::gPointerCaptureList->Get(aPointerId, &pointerCaptureInfo) &&
|
||||
pointerCaptureInfo && pointerCaptureInfo->mPendingContent == this) {
|
||||
if (HasPointerCapture(aPointerId)) {
|
||||
nsIPresShell::ReleasePointerCapturingContent(aPointerId);
|
||||
}
|
||||
}
|
||||
bool HasPointerCapture(long aPointerId)
|
||||
{
|
||||
nsIPresShell::PointerCaptureInfo* pointerCaptureInfo = nullptr;
|
||||
if (nsIPresShell::gPointerCaptureList->Get(aPointerId, &pointerCaptureInfo) &&
|
||||
pointerCaptureInfo && pointerCaptureInfo->mPendingContent == this) {
|
||||
nsIPresShell::PointerCaptureInfo* pointerCaptureInfo =
|
||||
nsIPresShell::GetPointerCaptureInfo(aPointerId);
|
||||
if (pointerCaptureInfo && pointerCaptureInfo->mPendingContent == this) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -157,7 +157,7 @@ EXPORTS.mozilla.dom += [
|
||||
'ChromeNodeList.h',
|
||||
'ChromeUtils.h',
|
||||
'Comment.h',
|
||||
'CustomElementsRegistry.h',
|
||||
'CustomElementRegistry.h',
|
||||
'DirectionalityUtils.h',
|
||||
'DocumentFragment.h',
|
||||
'DocumentType.h',
|
||||
@ -222,7 +222,7 @@ UNIFIED_SOURCES += [
|
||||
'ChromeUtils.cpp',
|
||||
'Comment.cpp',
|
||||
'Crypto.cpp',
|
||||
'CustomElementsRegistry.cpp',
|
||||
'CustomElementRegistry.cpp',
|
||||
'DirectionalityUtils.cpp',
|
||||
'DocumentFragment.cpp',
|
||||
'DocumentType.cpp',
|
||||
|
@ -38,7 +38,7 @@
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/LoadInfo.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/dom/CustomElementsRegistry.h"
|
||||
#include "mozilla/dom/CustomElementRegistry.h"
|
||||
#include "mozilla/dom/DocumentFragment.h"
|
||||
#include "mozilla/dom/DOMTypes.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
@ -67,6 +67,7 @@
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/dom/Selection.h"
|
||||
#include "mozilla/TextEvents.h"
|
||||
#include "nsArrayUtils.h"
|
||||
#include "nsAString.h"
|
||||
#include "nsAttrName.h"
|
||||
#include "nsAttrValue.h"
|
||||
@ -7693,11 +7694,11 @@ nsContentUtils::TransferableToIPCTransferable(nsITransferable* aTransferable,
|
||||
MOZ_ASSERT((aChild && !aParent) || (!aChild && aParent));
|
||||
|
||||
if (aTransferable) {
|
||||
nsCOMPtr<nsISupportsArray> flavorList;
|
||||
nsCOMPtr<nsIArray> flavorList;
|
||||
aTransferable->FlavorsTransferableCanExport(getter_AddRefs(flavorList));
|
||||
if (flavorList) {
|
||||
uint32_t flavorCount = 0;
|
||||
flavorList->Count(&flavorCount);
|
||||
flavorList->GetLength(&flavorCount);
|
||||
for (uint32_t j = 0; j < flavorCount; ++j) {
|
||||
nsCOMPtr<nsISupportsCString> flavor = do_QueryElementAt(flavorList, j);
|
||||
if (!flavor) {
|
||||
@ -9537,7 +9538,7 @@ nsContentUtils::LookupCustomElementDefinition(nsIDocument* aDoc,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<CustomElementsRegistry> registry(window->CustomElements());
|
||||
RefPtr<CustomElementRegistry> registry(window->CustomElements());
|
||||
if (!registry) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -9570,7 +9571,7 @@ nsContentUtils::SetupCustomElement(Element* aElement,
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<CustomElementsRegistry> registry(window->CustomElements());
|
||||
RefPtr<CustomElementRegistry> registry(window->CustomElements());
|
||||
if (!registry) {
|
||||
return;
|
||||
}
|
||||
@ -9599,7 +9600,7 @@ nsContentUtils::EnqueueLifecycleCallback(nsIDocument* aDoc,
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<CustomElementsRegistry> registry(window->CustomElements());
|
||||
RefPtr<CustomElementRegistry> registry(window->CustomElements());
|
||||
if (!registry) {
|
||||
return;
|
||||
}
|
||||
@ -9628,7 +9629,7 @@ nsContentUtils::GetCustomPrototype(nsIDocument* aDoc,
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<CustomElementsRegistry> registry(window->CustomElements());
|
||||
RefPtr<CustomElementRegistry> registry(window->CustomElements());
|
||||
if (!registry) {
|
||||
return;
|
||||
}
|
||||
|
@ -219,8 +219,8 @@
|
||||
#include "mozilla/dom/TabChild.h"
|
||||
#include "mozilla/dom/UndoManager.h"
|
||||
#include "mozilla/dom/WebComponentsBinding.h"
|
||||
#include "mozilla/dom/CustomElementsRegistryBinding.h"
|
||||
#include "mozilla/dom/CustomElementsRegistry.h"
|
||||
#include "mozilla/dom/CustomElementRegistryBinding.h"
|
||||
#include "mozilla/dom/CustomElementRegistry.h"
|
||||
#include "nsFrame.h"
|
||||
#include "nsDOMCaretPosition.h"
|
||||
#include "nsIDOMHTMLTextAreaElement.h"
|
||||
@ -5374,8 +5374,8 @@ bool IsLowercaseASCII(const nsAString& aValue)
|
||||
return true;
|
||||
}
|
||||
|
||||
already_AddRefed<mozilla::dom::CustomElementsRegistry>
|
||||
nsDocument::GetCustomElementsRegistry()
|
||||
already_AddRefed<mozilla::dom::CustomElementRegistry>
|
||||
nsDocument::GetCustomElementRegistry()
|
||||
{
|
||||
nsAutoString contentType;
|
||||
GetContentType(contentType);
|
||||
@ -5391,7 +5391,7 @@ nsDocument::GetCustomElementsRegistry()
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<CustomElementsRegistry> registry = window->CustomElements();
|
||||
RefPtr<CustomElementRegistry> registry = window->CustomElements();
|
||||
if (!registry) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -5690,7 +5690,7 @@ nsDocument::CustomElementConstructor(JSContext* aCx, unsigned aArgc, JS::Value*
|
||||
return true;
|
||||
}
|
||||
|
||||
RefPtr<mozilla::dom::CustomElementsRegistry> registry = window->CustomElements();
|
||||
RefPtr<mozilla::dom::CustomElementRegistry> registry = window->CustomElements();
|
||||
if (!registry) {
|
||||
return true;
|
||||
}
|
||||
@ -5758,7 +5758,7 @@ nsDocument::RegisterElement(JSContext* aCx, const nsAString& aType,
|
||||
JS::MutableHandle<JSObject*> aRetval,
|
||||
ErrorResult& rv)
|
||||
{
|
||||
RefPtr<CustomElementsRegistry> registry(GetCustomElementsRegistry());
|
||||
RefPtr<CustomElementRegistry> registry(GetCustomElementRegistry());
|
||||
if (!registry) {
|
||||
rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return;
|
||||
@ -8812,7 +8812,10 @@ nsDocument::OnPageHide(bool aPersisted,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
DispatchPageTransition(target, NS_LITERAL_STRING("pagehide"), aPersisted);
|
||||
{
|
||||
PageUnloadingEventTimeStamp timeStamp(this);
|
||||
DispatchPageTransition(target, NS_LITERAL_STRING("pagehide"), aPersisted);
|
||||
}
|
||||
|
||||
mVisible = false;
|
||||
|
||||
|
@ -68,7 +68,7 @@
|
||||
#include "jsfriendapi.h"
|
||||
#include "ImportManager.h"
|
||||
#include "mozilla/LinkedList.h"
|
||||
#include "CustomElementsRegistry.h"
|
||||
#include "CustomElementRegistry.h"
|
||||
|
||||
#define XML_DECLARATION_BITS_DECLARATION_EXISTS (1 << 0)
|
||||
#define XML_DECLARATION_BITS_ENCODING_EXISTS (1 << 1)
|
||||
@ -1364,8 +1364,8 @@ private:
|
||||
ErrorResult& rv);
|
||||
|
||||
public:
|
||||
virtual already_AddRefed<mozilla::dom::CustomElementsRegistry>
|
||||
GetCustomElementsRegistry() override;
|
||||
virtual already_AddRefed<mozilla::dom::CustomElementRegistry>
|
||||
GetCustomElementRegistry() override;
|
||||
|
||||
static bool IsWebComponentsEnabled(JSContext* aCx, JSObject* aObject);
|
||||
|
||||
|
@ -49,9 +49,7 @@
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/ShadowRoot.h"
|
||||
#include "mozilla/dom/EncodingUtils.h"
|
||||
#include "nsContainerFrame.h"
|
||||
#include "nsBlockFrame.h"
|
||||
#include "nsComputedDOMStyle.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
@ -324,85 +322,6 @@ nsDocumentEncoder::IncludeInContext(nsINode *aNode)
|
||||
return false;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
LineHasNonEmptyContentWorker(nsIFrame* aFrame)
|
||||
{
|
||||
// Look for non-empty frames, but ignore inline and br frames.
|
||||
// For inline frames, descend into the children, if any.
|
||||
if (aFrame->GetType() == nsGkAtoms::inlineFrame) {
|
||||
for (nsIFrame* child : aFrame->PrincipalChildList()) {
|
||||
if (LineHasNonEmptyContentWorker(child)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (aFrame->GetType() != nsGkAtoms::brFrame &&
|
||||
!aFrame->IsEmpty()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
LineHasNonEmptyContent(nsLineBox* aLine)
|
||||
{
|
||||
int32_t count = aLine->GetChildCount();
|
||||
for (nsIFrame* frame = aLine->mFirstChild; count > 0;
|
||||
--count, frame = frame->GetNextSibling()) {
|
||||
if (LineHasNonEmptyContentWorker(frame)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
IsInvisibleBreak(nsINode *aNode)
|
||||
{
|
||||
if (!aNode->IsElement() || !aNode->IsEditable()) {
|
||||
return false;
|
||||
}
|
||||
nsIFrame* frame = aNode->AsElement()->GetPrimaryFrame();
|
||||
if (!frame || frame->GetType() != nsGkAtoms::brFrame) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsContainerFrame* f = frame->GetParent();
|
||||
while (f && f->IsFrameOfType(nsBox::eLineParticipant)) {
|
||||
f = f->GetParent();
|
||||
}
|
||||
nsBlockFrame* blockAncestor = do_QueryFrame(f);
|
||||
if (!blockAncestor) {
|
||||
// The container frame doesn't support line breaking.
|
||||
return false;
|
||||
}
|
||||
|
||||
bool valid = false;
|
||||
nsBlockInFlowLineIterator iter(blockAncestor, frame, &valid);
|
||||
if (!valid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool lineNonEmpty = LineHasNonEmptyContent(iter.GetLine());
|
||||
|
||||
while (iter.Next()) {
|
||||
auto currentLine = iter.GetLine();
|
||||
// Completely skip empty lines.
|
||||
if (!currentLine->IsEmpty()) {
|
||||
// If we come across an inline line, the BR has caused a visible line break.
|
||||
if (currentLine->IsInline()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return lineNonEmpty;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDocumentEncoder::SerializeNodeStart(nsINode* aNode,
|
||||
int32_t aStartOffset,
|
||||
@ -437,7 +356,7 @@ nsDocumentEncoder::SerializeNodeStart(nsINode* aNode,
|
||||
if (node->IsElement()) {
|
||||
if ((mFlags & (nsIDocumentEncoder::OutputPreformatted |
|
||||
nsIDocumentEncoder::OutputDropInvisibleBreak)) &&
|
||||
IsInvisibleBreak(node)) {
|
||||
nsLayoutUtils::IsInvisibleBreak(node)) {
|
||||
return NS_OK;
|
||||
}
|
||||
Element* originalElement =
|
||||
|
@ -3799,12 +3799,12 @@ nsGlobalWindow::GetHistory(ErrorResult& aError)
|
||||
return mHistory;
|
||||
}
|
||||
|
||||
CustomElementsRegistry*
|
||||
CustomElementRegistry*
|
||||
nsGlobalWindow::CustomElements()
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(IsInnerWindow());
|
||||
if (!mCustomElements) {
|
||||
mCustomElements = CustomElementsRegistry::Create(AsInner());
|
||||
mCustomElements = CustomElementRegistry::Create(AsInner());
|
||||
}
|
||||
|
||||
return mCustomElements;
|
||||
|
@ -105,7 +105,7 @@ class BarProp;
|
||||
struct ChannelPixelLayout;
|
||||
class Console;
|
||||
class Crypto;
|
||||
class CustomElementsRegistry;
|
||||
class CustomElementRegistry;
|
||||
class External;
|
||||
class Function;
|
||||
class Gamepad;
|
||||
@ -812,7 +812,6 @@ public:
|
||||
|
||||
// Update the VR displays for this window
|
||||
bool UpdateVRDisplays(nsTArray<RefPtr<mozilla::dom::VRDisplay>>& aDisplays);
|
||||
|
||||
// Inner windows only.
|
||||
// Called to inform that the set of active VR displays has changed.
|
||||
void NotifyActiveVRDisplaysChanged();
|
||||
@ -887,7 +886,7 @@ public:
|
||||
mozilla::dom::Location* GetLocation(mozilla::ErrorResult& aError);
|
||||
nsIDOMLocation* GetLocation() override;
|
||||
nsHistory* GetHistory(mozilla::ErrorResult& aError);
|
||||
mozilla::dom::CustomElementsRegistry* CustomElements() override;
|
||||
mozilla::dom::CustomElementRegistry* CustomElements() override;
|
||||
mozilla::dom::BarProp* GetLocationbar(mozilla::ErrorResult& aError);
|
||||
mozilla::dom::BarProp* GetMenubar(mozilla::ErrorResult& aError);
|
||||
mozilla::dom::BarProp* GetPersonalbar(mozilla::ErrorResult& aError);
|
||||
@ -1889,7 +1888,7 @@ protected:
|
||||
uint32_t mTimeoutFiringDepth;
|
||||
RefPtr<mozilla::dom::Location> mLocation;
|
||||
RefPtr<nsHistory> mHistory;
|
||||
RefPtr<mozilla::dom::CustomElementsRegistry> mCustomElements;
|
||||
RefPtr<mozilla::dom::CustomElementRegistry> mCustomElements;
|
||||
|
||||
// These member variables are used on both inner and the outer windows.
|
||||
nsCOMPtr<nsIPrincipal> mDocumentPrincipal;
|
||||
|
@ -33,6 +33,7 @@ using mozilla::dom::BlobImpl;
|
||||
using mozilla::dom::MediaSource;
|
||||
using mozilla::ErrorResult;
|
||||
using mozilla::net::LoadInfo;
|
||||
using mozilla::Move;
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Hash table
|
||||
@ -615,7 +616,7 @@ nsHostObjectProtocolHandler::RemoveDataEntry(const nsACString& aUri,
|
||||
}
|
||||
|
||||
if (!info->mURIs.IsEmpty()) {
|
||||
ReleasingTimerHolder::Create(Move(info->mURIs));
|
||||
mozilla::ReleasingTimerHolder::Create(Move(info->mURIs));
|
||||
}
|
||||
|
||||
gDataTable->Remove(aUri);
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "mozilla/LinkedList.h"
|
||||
#include "mozilla/StyleBackendType.h"
|
||||
#include "mozilla/StyleSheet.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include <bitset> // for member
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
@ -216,6 +217,33 @@ public:
|
||||
nsIDocument();
|
||||
#endif
|
||||
|
||||
// This helper class must be set when we dispatch beforeunload and unload
|
||||
// events in order to avoid unterminate sync XHRs.
|
||||
class MOZ_RAII PageUnloadingEventTimeStamp
|
||||
{
|
||||
nsCOMPtr<nsIDocument> mDocument;
|
||||
bool mSet;
|
||||
|
||||
public:
|
||||
explicit PageUnloadingEventTimeStamp(nsIDocument* aDocument)
|
||||
: mDocument(aDocument)
|
||||
, mSet(false)
|
||||
{
|
||||
MOZ_ASSERT(aDocument);
|
||||
if (mDocument->mPageUnloadingEventTimeStamp.IsNull()) {
|
||||
mDocument->SetPageUnloadingEventTimeStamp();
|
||||
mSet = true;
|
||||
}
|
||||
}
|
||||
|
||||
~PageUnloadingEventTimeStamp()
|
||||
{
|
||||
if (mSet) {
|
||||
mDocument->CleanUnloadEventsTimeStamp();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Let the document know that we're starting to load data into it.
|
||||
* @param aCommand The parser command. Must not be null.
|
||||
@ -936,9 +964,40 @@ public:
|
||||
nsresult GetOrCreateId(nsAString& aId);
|
||||
void SetId(const nsAString& aId);
|
||||
|
||||
mozilla::TimeStamp GetPageUnloadingEventTimeStamp() const
|
||||
{
|
||||
if (!mParentDocument) {
|
||||
return mPageUnloadingEventTimeStamp;
|
||||
}
|
||||
|
||||
mozilla::TimeStamp parentTimeStamp(mParentDocument->GetPageUnloadingEventTimeStamp());
|
||||
if (parentTimeStamp.IsNull()) {
|
||||
return mPageUnloadingEventTimeStamp;
|
||||
}
|
||||
|
||||
if (!mPageUnloadingEventTimeStamp ||
|
||||
parentTimeStamp < mPageUnloadingEventTimeStamp) {
|
||||
return parentTimeStamp;
|
||||
}
|
||||
|
||||
return mPageUnloadingEventTimeStamp;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual Element *GetRootElementInternal() const = 0;
|
||||
|
||||
void SetPageUnloadingEventTimeStamp()
|
||||
{
|
||||
MOZ_ASSERT(!mPageUnloadingEventTimeStamp);
|
||||
mPageUnloadingEventTimeStamp = mozilla::TimeStamp::NowLoRes();
|
||||
}
|
||||
|
||||
void CleanUnloadEventsTimeStamp()
|
||||
{
|
||||
MOZ_ASSERT(mPageUnloadingEventTimeStamp);
|
||||
mPageUnloadingEventTimeStamp = mozilla::TimeStamp();
|
||||
}
|
||||
|
||||
private:
|
||||
class SelectorCacheKey
|
||||
{
|
||||
@ -2515,8 +2574,8 @@ public:
|
||||
const mozilla::dom::ElementRegistrationOptions& aOptions,
|
||||
JS::MutableHandle<JSObject*> aRetval,
|
||||
mozilla::ErrorResult& rv) = 0;
|
||||
virtual already_AddRefed<mozilla::dom::CustomElementsRegistry>
|
||||
GetCustomElementsRegistry() = 0;
|
||||
virtual already_AddRefed<mozilla::dom::CustomElementRegistry>
|
||||
GetCustomElementRegistry() = 0;
|
||||
|
||||
already_AddRefed<nsContentList>
|
||||
GetElementsByTagName(const nsAString& aTagName)
|
||||
@ -3242,6 +3301,8 @@ protected:
|
||||
|
||||
// Whether the user has interacted with the document or not:
|
||||
bool mUserHasInteracted;
|
||||
|
||||
mozilla::TimeStamp mPageUnloadingEventTimeStamp;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocument, NS_IDOCUMENT_IID)
|
||||
|
@ -746,10 +746,17 @@ nsImageLoadingContent::LoadImage(const nsAString& aNewURI,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Pending load/error events need to be canceled in some situations. This
|
||||
// is not documented in the spec, but can cause site compat problems if not
|
||||
// done. See bug 1309461 and https://github.com/whatwg/html/issues/1872.
|
||||
CancelPendingEvent();
|
||||
|
||||
if (aNewURI.IsEmpty()) {
|
||||
// Cancel image requests and then fire only error event per spec.
|
||||
CancelImageRequests(aNotify);
|
||||
FireEvent(NS_LITERAL_STRING("error"));
|
||||
// Mark error event as cancelable only for src="" case, since only this
|
||||
// error causes site compat problem (bug 1308069) for now.
|
||||
FireEvent(NS_LITERAL_STRING("error"), true);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -781,6 +788,11 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
|
||||
nsIDocument* aDocument,
|
||||
nsLoadFlags aLoadFlags)
|
||||
{
|
||||
// Pending load/error events need to be canceled in some situations. This
|
||||
// is not documented in the spec, but can cause site compat problems if not
|
||||
// done. See bug 1309461 and https://github.com/whatwg/html/issues/1872.
|
||||
CancelPendingEvent();
|
||||
|
||||
// Fire loadstart event if required
|
||||
if (aLoadStart) {
|
||||
FireEvent(NS_LITERAL_STRING("loadstart"));
|
||||
@ -1143,7 +1155,7 @@ nsImageLoadingContent::StringToURI(const nsAString& aSpec,
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsImageLoadingContent::FireEvent(const nsAString& aEventType)
|
||||
nsImageLoadingContent::FireEvent(const nsAString& aEventType, bool aIsCancelable)
|
||||
{
|
||||
if (nsContentUtils::DocumentInactiveForImageLoads(GetOurOwnerDoc())) {
|
||||
// Don't bother to fire any events, especially error events.
|
||||
@ -1160,9 +1172,30 @@ nsImageLoadingContent::FireEvent(const nsAString& aEventType)
|
||||
new LoadBlockingAsyncEventDispatcher(thisNode, aEventType, false, false);
|
||||
loadBlockingAsyncDispatcher->PostDOMEvent();
|
||||
|
||||
if (aIsCancelable) {
|
||||
mPendingEvent = loadBlockingAsyncDispatcher;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsImageLoadingContent::AsyncEventRunning(AsyncEventDispatcher* aEvent)
|
||||
{
|
||||
if (mPendingEvent == aEvent) {
|
||||
mPendingEvent = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsImageLoadingContent::CancelPendingEvent()
|
||||
{
|
||||
if (mPendingEvent) {
|
||||
mPendingEvent->Cancel();
|
||||
mPendingEvent = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<imgRequestProxy>&
|
||||
nsImageLoadingContent::PrepareNextRequest(ImageLoadType aImageLoadType)
|
||||
{
|
||||
|
@ -32,6 +32,10 @@ class nsPresContext;
|
||||
class nsIContent;
|
||||
class imgRequestProxy;
|
||||
|
||||
namespace mozilla {
|
||||
class AsyncEventDispatcher;
|
||||
} // namespace mozilla
|
||||
|
||||
#ifdef LoadImage
|
||||
// Undefine LoadImage to prevent naming conflict with Windows.
|
||||
#undef LoadImage
|
||||
@ -213,6 +217,8 @@ protected:
|
||||
// The nsContentPolicyType we would use for this ImageLoadType
|
||||
static nsContentPolicyType PolicyTypeForLoad(ImageLoadType aImageLoadType);
|
||||
|
||||
void AsyncEventRunning(mozilla::AsyncEventDispatcher* aEvent);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Struct used to manage the image observers.
|
||||
@ -260,8 +266,16 @@ private:
|
||||
*
|
||||
* @param aEventType "loadstart", "loadend", "load", or "error" depending on
|
||||
* how things went
|
||||
* @param aIsCancelable true if event is cancelable.
|
||||
*/
|
||||
nsresult FireEvent(const nsAString& aEventType);
|
||||
nsresult FireEvent(const nsAString& aEventType, bool aIsCancelable = false);
|
||||
|
||||
/**
|
||||
* Method to cancel and null-out pending event if they exist.
|
||||
*/
|
||||
void CancelPendingEvent();
|
||||
|
||||
RefPtr<mozilla::AsyncEventDispatcher> mPendingEvent;
|
||||
|
||||
protected:
|
||||
/**
|
||||
|
@ -45,7 +45,7 @@ class AudioContext;
|
||||
class Element;
|
||||
class Performance;
|
||||
class ServiceWorkerRegistration;
|
||||
class CustomElementsRegistry;
|
||||
class CustomElementRegistry;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
@ -95,7 +95,7 @@ public:
|
||||
const nsPIDOMWindowOuter* AsOuter() const;
|
||||
|
||||
virtual nsPIDOMWindowOuter* GetPrivateRoot() = 0;
|
||||
virtual mozilla::dom::CustomElementsRegistry* CustomElements() = 0;
|
||||
virtual mozilla::dom::CustomElementRegistry* CustomElements() = 0;
|
||||
// Outer windows only.
|
||||
virtual void ActivateOrDeactivate(bool aActivate) = 0;
|
||||
|
||||
|
@ -1419,7 +1419,8 @@ nsTreeSanitizer::SanitizeChildren(nsINode* aRoot)
|
||||
nsCOMPtr<nsIContent> child; // Must keep the child alive during move
|
||||
ErrorResult rv;
|
||||
while ((child = node->GetFirstChild())) {
|
||||
parent->InsertBefore(*child, node, rv);
|
||||
nsCOMPtr<nsINode> refNode = node;
|
||||
parent->InsertBefore(*child, refNode, rv);
|
||||
if (rv.Failed()) {
|
||||
break;
|
||||
}
|
||||
|
@ -631,6 +631,7 @@ skip-if = buildapp == 'b2g'
|
||||
[test_bug1281963.html]
|
||||
[test_bug1295852.html]
|
||||
[test_bug1307730.html]
|
||||
[test_bug1308069.html]
|
||||
[test_caretPositionFromPoint.html]
|
||||
[test_change_policy.html]
|
||||
skip-if = buildapp == 'b2g' #no ssl support
|
||||
|
87
dom/base/test/test_bug1308069.html
Normal file
87
dom/base/test/test_bug1308069.html
Normal file
@ -0,0 +1,87 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1308069
|
||||
-->
|
||||
<head>
|
||||
<title>Bug 1308069</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1308069">Mozilla Bug 1308069</a>
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
function testClearPendingErrorEvent() {
|
||||
return new Promise(function(aResolve, aReject) {
|
||||
var hasErrorEvent = false;
|
||||
var imgTarget = new Image();
|
||||
|
||||
var imgForChangingTargetSrc = new Image();
|
||||
// Queue an error event for changing imgTarget's src.
|
||||
imgForChangingTargetSrc.src = '';
|
||||
imgForChangingTargetSrc.onerror = function() {
|
||||
// This clears imgTarget's pending error event.
|
||||
imgTarget.src = 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="96" height="96"><path d="M10,10L32,90L90,32z" fill="lightgreen"/></svg>';
|
||||
|
||||
// Queue an error event for checking and resolving promise.
|
||||
var imgForCheckingAndResolvingPromise = new Image();
|
||||
imgForCheckingAndResolvingPromise.src = '';
|
||||
imgForCheckingAndResolvingPromise.onerror = function() {
|
||||
ok(!hasErrorEvent,
|
||||
'Should not receive an error event since the pending error event ' +
|
||||
'should be cleared before it fired');
|
||||
aResolve();
|
||||
};
|
||||
};
|
||||
|
||||
// Setting src to empty string queues an error event.
|
||||
imgTarget.src = '';
|
||||
imgTarget.onerror = function() {
|
||||
hasErrorEvent = true;
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function testReplacePendingErrorEvent() {
|
||||
return new Promise(function(aResolve) {
|
||||
var numOfErrorEvent = 0;
|
||||
var imgTarget = new Image();
|
||||
|
||||
var imgForChangingTargetSrc = new Image();
|
||||
// Queue an error event for changing imgTarget's src.
|
||||
imgForChangingTargetSrc.src = '';
|
||||
imgForChangingTargetSrc.onerror = function() {
|
||||
// This clears pending error event and fires a new one.
|
||||
imgTarget.src = '';
|
||||
|
||||
// Queue an error event for checking and resolving promise.
|
||||
var imgForCheckingAndResolvingPromise = new Image();
|
||||
imgForCheckingAndResolvingPromise.src = '';
|
||||
imgForCheckingAndResolvingPromise.onerror = function() {
|
||||
is(numOfErrorEvent, 1,
|
||||
'Should only receive one error event since the first pending error ' +
|
||||
'event should be cleared before it fired');
|
||||
aResolve();
|
||||
};
|
||||
};
|
||||
|
||||
// Setting src to empty string queues an error event.
|
||||
imgTarget.src = '';
|
||||
imgTarget.onerror = function() {
|
||||
numOfErrorEvent++;
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
Promise.resolve()
|
||||
.then(() => testClearPendingErrorEvent())
|
||||
.then(() => testReplacePendingErrorEvent())
|
||||
.catch((err) => ok(false, "promise rejected: " + err))
|
||||
.then(() => SimpleTest.finish());
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1281,46 +1281,40 @@ FindEnumStringIndexImpl(const CharT* chars, size_t length, const EnumEntry* valu
|
||||
}
|
||||
|
||||
template<bool InvalidValueFatal>
|
||||
inline int
|
||||
inline bool
|
||||
FindEnumStringIndex(JSContext* cx, JS::Handle<JS::Value> v, const EnumEntry* values,
|
||||
const char* type, const char* sourceDescription, bool* ok)
|
||||
const char* type, const char* sourceDescription, int* index)
|
||||
{
|
||||
// JS_StringEqualsAscii is slow as molasses, so don't use it here.
|
||||
JS::RootedString str(cx, JS::ToString(cx, v));
|
||||
if (!str) {
|
||||
*ok = false;
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
int index;
|
||||
size_t length;
|
||||
JS::AutoCheckCannotGC nogc;
|
||||
if (js::StringHasLatin1Chars(str)) {
|
||||
const JS::Latin1Char* chars = JS_GetLatin1StringCharsAndLength(cx, nogc, str,
|
||||
&length);
|
||||
if (!chars) {
|
||||
*ok = false;
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
index = FindEnumStringIndexImpl(chars, length, values);
|
||||
*index = FindEnumStringIndexImpl(chars, length, values);
|
||||
} else {
|
||||
const char16_t* chars = JS_GetTwoByteStringCharsAndLength(cx, nogc, str,
|
||||
&length);
|
||||
if (!chars) {
|
||||
*ok = false;
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
index = FindEnumStringIndexImpl(chars, length, values);
|
||||
*index = FindEnumStringIndexImpl(chars, length, values);
|
||||
}
|
||||
if (index >= 0) {
|
||||
*ok = true;
|
||||
return index;
|
||||
if (*index >= 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
*ok = EnumValueNotFound<InvalidValueFatal>(cx, str, type, sourceDescription);
|
||||
return -1;
|
||||
return EnumValueNotFound<InvalidValueFatal>(cx, str, type, sourceDescription);
|
||||
}
|
||||
|
||||
inline nsWrapperCache*
|
||||
|
@ -5597,9 +5597,8 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
||||
template = fill(
|
||||
"""
|
||||
{
|
||||
bool ok;
|
||||
int index = FindEnumStringIndex<${invalidEnumValueFatal}>(cx, $${val}, ${values}, "${enumtype}", "${sourceDescription}", &ok);
|
||||
if (!ok) {
|
||||
int index;
|
||||
if (!FindEnumStringIndex<${invalidEnumValueFatal}>(cx, $${val}, ${values}, "${enumtype}", "${sourceDescription}", &index)) {
|
||||
$*{exceptionCode}
|
||||
}
|
||||
$*{handleInvalidEnumValueCode}
|
||||
|
@ -1,9 +1,7 @@
|
||||
[DEFAULT]
|
||||
# Both the "inproc" and "oop" versions of OpenMixedProcess open remote frames,
|
||||
# so we don't run that test on platforms which don't support OOP tests.
|
||||
# OOP tests don't work on native-fennec (bug 774939).
|
||||
# Bug 960345 - Disabled on OSX debug for frequent crashes.
|
||||
skip-if = os == "android" || (toolkit == "cocoa" && debug) || buildapp == 'mulet' || (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || e10s
|
||||
skip-if = os == "android" || e10s
|
||||
support-files =
|
||||
browserElement_OpenMixedProcess.js
|
||||
file_browserElement_ExecuteScript.html
|
||||
|
@ -4745,7 +4745,7 @@ var ctx = canvas.getContext('2d');
|
||||
|
||||
|
||||
ctx.fillStyle = '#0f0';
|
||||
try { ctx.fillStyle = 'hsl(0, 100%, 100%, 1)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
|
||||
try { ctx.fillStyle = 'hsl(0, 100%, 100%,)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
|
||||
ctx.fillRect(0, 0, 100, 50);
|
||||
isPixel(ctx, 50,25, 0,255,0,255, 0);
|
||||
|
||||
@ -4874,7 +4874,7 @@ var ctx = canvas.getContext('2d');
|
||||
|
||||
|
||||
ctx.fillStyle = '#0f0';
|
||||
try { ctx.fillStyle = 'rgb(255.0, 0, 0)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
|
||||
try { ctx.fillStyle = 'rgb(255.0, 0%, 0)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
|
||||
ctx.fillRect(0, 0, 100, 50);
|
||||
isPixel(ctx, 50,25, 0,255,0,255, 0);
|
||||
|
||||
@ -4896,7 +4896,7 @@ var ctx = canvas.getContext('2d');
|
||||
|
||||
|
||||
ctx.fillStyle = '#0f0';
|
||||
try { ctx.fillStyle = 'rgb(255, 0.0, 0)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
|
||||
try { ctx.fillStyle = 'rgb(255%, 0.0, 0)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
|
||||
ctx.fillRect(0, 0, 100, 50);
|
||||
isPixel(ctx, 50,25, 0,255,0,255, 0);
|
||||
|
||||
@ -4962,7 +4962,7 @@ var ctx = canvas.getContext('2d');
|
||||
|
||||
|
||||
ctx.fillStyle = '#0f0';
|
||||
try { ctx.fillStyle = 'rgb(255 0 0)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
|
||||
try { ctx.fillStyle = 'rgb(255, 0 0)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
|
||||
ctx.fillRect(0, 0, 100, 50);
|
||||
isPixel(ctx, 50,25, 0,255,0,255, 0);
|
||||
|
||||
@ -5006,7 +5006,7 @@ var ctx = canvas.getContext('2d');
|
||||
|
||||
|
||||
ctx.fillStyle = '#0f0';
|
||||
try { ctx.fillStyle = 'rgb(255, 0, 0, 1)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
|
||||
try { ctx.fillStyle = 'rgb(255, 0, 0, 1,)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
|
||||
ctx.fillRect(0, 0, 100, 50);
|
||||
isPixel(ctx, 50,25, 0,255,0,255, 0);
|
||||
|
||||
@ -5028,7 +5028,7 @@ var ctx = canvas.getContext('2d');
|
||||
|
||||
|
||||
ctx.fillStyle = '#0f0';
|
||||
try { ctx.fillStyle = 'rgba(255, 0, 0)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
|
||||
try { ctx.fillStyle = 'rgba(255, 0, 0,)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
|
||||
ctx.fillRect(0, 0, 100, 50);
|
||||
isPixel(ctx, 50,25, 0,255,0,255, 0);
|
||||
|
||||
@ -5050,7 +5050,7 @@ var ctx = canvas.getContext('2d');
|
||||
|
||||
|
||||
ctx.fillStyle = '#0f0';
|
||||
try { ctx.fillStyle = 'rgba(255.0, 0, 0, 1)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
|
||||
try { ctx.fillStyle = 'rgba(255.0, 0, 0, 1,)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
|
||||
ctx.fillRect(0, 0, 100, 50);
|
||||
isPixel(ctx, 50,25, 0,255,0,255, 0);
|
||||
|
||||
@ -5094,7 +5094,7 @@ var ctx = canvas.getContext('2d');
|
||||
|
||||
|
||||
ctx.fillStyle = '#0f0';
|
||||
try { ctx.fillStyle = 'rgba(255, 0, 0, 100%)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
|
||||
try { ctx.fillStyle = 'rgba(255, 0, 0, 100.%)'; } catch (e) { } // this shouldn't throw, but it shouldn't matter here if it does
|
||||
ctx.fillRect(0, 0, 100, 50);
|
||||
isPixel(ctx, 50,25, 0,255,0,255, 0);
|
||||
|
||||
|
@ -39,6 +39,7 @@ AsyncEventDispatcher::Run()
|
||||
if (mCanceled) {
|
||||
return NS_OK;
|
||||
}
|
||||
mTarget->AsyncEventRunning(this);
|
||||
RefPtr<Event> event = mEvent ? mEvent->InternalDOMEvent() : nullptr;
|
||||
if (!event) {
|
||||
event = NS_NewDOMEvent(mTarget, nullptr, nullptr);
|
||||
|
@ -16,6 +16,7 @@ class nsIGlobalObject;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class AsyncEventDispatcher;
|
||||
class ErrorResult;
|
||||
class EventListenerManager;
|
||||
|
||||
@ -91,6 +92,9 @@ public:
|
||||
*/
|
||||
virtual EventListenerManager* GetExistingListenerManager() const = 0;
|
||||
|
||||
// Called from AsyncEventDispatcher to notify it is running.
|
||||
virtual void AsyncEventRunning(AsyncEventDispatcher* aEvent) {}
|
||||
|
||||
virtual bool IsApzAware() const;
|
||||
|
||||
protected:
|
||||
|
@ -166,6 +166,12 @@ HTMLImageElement::IsInteractiveHTMLContent(bool aIgnoreTabindex) const
|
||||
nsGenericHTMLElement::IsInteractiveHTMLContent(aIgnoreTabindex);
|
||||
}
|
||||
|
||||
void
|
||||
HTMLImageElement::AsyncEventRunning(AsyncEventDispatcher* aEvent)
|
||||
{
|
||||
nsImageLoadingContent::AsyncEventRunning(aEvent);
|
||||
}
|
||||
|
||||
nsresult
|
||||
HTMLImageElement::GetCurrentSrc(nsAString& aValue)
|
||||
{
|
||||
|
@ -49,6 +49,9 @@ public:
|
||||
// Element
|
||||
virtual bool IsInteractiveHTMLContent(bool aIgnoreTabindex) const override;
|
||||
|
||||
// EventTarget
|
||||
virtual void AsyncEventRunning(AsyncEventDispatcher* aEvent) override;
|
||||
|
||||
// nsIDOMHTMLImageElement
|
||||
NS_DECL_NSIDOMHTMLIMAGEELEMENT
|
||||
|
||||
|
@ -3671,6 +3671,12 @@ HTMLInputElement::IsInteractiveHTMLContent(bool aIgnoreTabindex) const
|
||||
nsGenericHTMLFormElementWithState::IsInteractiveHTMLContent(aIgnoreTabindex);
|
||||
}
|
||||
|
||||
void
|
||||
HTMLInputElement::AsyncEventRunning(AsyncEventDispatcher* aEvent)
|
||||
{
|
||||
nsImageLoadingContent::AsyncEventRunning(aEvent);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLInputElement::Select()
|
||||
{
|
||||
|
@ -142,6 +142,9 @@ public:
|
||||
// Element
|
||||
virtual bool IsInteractiveHTMLContent(bool aIgnoreTabindex) const override;
|
||||
|
||||
// EventTarget
|
||||
virtual void AsyncEventRunning(AsyncEventDispatcher* aEvent) override;
|
||||
|
||||
// nsIDOMHTMLInputElement
|
||||
NS_DECL_NSIDOMHTMLINPUTELEMENT
|
||||
|
||||
|
@ -59,6 +59,12 @@ HTMLObjectElement::IsInteractiveHTMLContent(bool aIgnoreTabindex) const
|
||||
nsGenericHTMLFormElement::IsInteractiveHTMLContent(aIgnoreTabindex);
|
||||
}
|
||||
|
||||
void
|
||||
HTMLObjectElement::AsyncEventRunning(AsyncEventDispatcher* aEvent)
|
||||
{
|
||||
nsImageLoadingContent::AsyncEventRunning(aEvent);
|
||||
}
|
||||
|
||||
bool
|
||||
HTMLObjectElement::IsDoneAddingChildren()
|
||||
{
|
||||
|
@ -48,6 +48,9 @@ public:
|
||||
// Element
|
||||
virtual bool IsInteractiveHTMLContent(bool aIgnoreTabindex) const override;
|
||||
|
||||
// EventTarget
|
||||
virtual void AsyncEventRunning(AsyncEventDispatcher* aEvent) override;
|
||||
|
||||
// nsIDOMHTMLObjectElement
|
||||
NS_DECL_NSIDOMHTMLOBJECTELEMENT
|
||||
|
||||
|
@ -587,7 +587,8 @@ HTMLSelectElement::Add(nsGenericHTMLElement& aElement,
|
||||
|
||||
// If the before parameter is not null, we are equivalent to the
|
||||
// insertBefore method on the parent of before.
|
||||
parent->InsertBefore(aElement, aBefore, aError);
|
||||
nsCOMPtr<nsINode> refNode = aBefore;
|
||||
parent->InsertBefore(aElement, refNode, aError);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -108,6 +108,12 @@ HTMLSharedObjectElement::PostHandleEvent(EventChainPostVisitor& aVisitor)
|
||||
|
||||
#endif // #ifdef XP_MACOSX
|
||||
|
||||
void
|
||||
HTMLSharedObjectElement::AsyncEventRunning(AsyncEventDispatcher* aEvent)
|
||||
{
|
||||
nsImageLoadingContent::AsyncEventRunning(aEvent);
|
||||
}
|
||||
|
||||
nsresult
|
||||
HTMLSharedObjectElement::BindToTree(nsIDocument *aDocument,
|
||||
nsIContent *aParent,
|
||||
|
@ -43,6 +43,9 @@ public:
|
||||
// Can't use macro for nsIDOMHTMLEmbedElement because it has conflicts with
|
||||
// NS_DECL_NSIDOMHTMLAPPLETELEMENT.
|
||||
|
||||
// EventTarget
|
||||
virtual void AsyncEventRunning(AsyncEventDispatcher* aEvent) override;
|
||||
|
||||
// nsIDOMHTMLEmbedElement
|
||||
NS_IMETHOD GetSrc(nsAString &aSrc) override;
|
||||
NS_IMETHOD SetSrc(const nsAString &aSrc) override;
|
||||
|
@ -412,7 +412,8 @@ HTMLTableElement::CreateTHead()
|
||||
}
|
||||
|
||||
ErrorResult rv;
|
||||
nsINode::InsertBefore(*head, nsINode::GetFirstChild(), rv);
|
||||
nsCOMPtr<nsINode> refNode = nsINode::GetFirstChild();
|
||||
nsINode::InsertBefore(*head, refNode, rv);
|
||||
}
|
||||
return head.forget();
|
||||
}
|
||||
@ -503,7 +504,7 @@ HTMLTableElement::CreateTBody()
|
||||
NS_NewHTMLTableSectionElement(nodeInfo.forget());
|
||||
MOZ_ASSERT(newBody);
|
||||
|
||||
nsIContent* referenceNode = nullptr;
|
||||
nsCOMPtr<nsIContent> referenceNode = nullptr;
|
||||
for (nsIContent* child = nsINode::GetLastChild();
|
||||
child;
|
||||
child = child->GetPreviousSibling()) {
|
||||
@ -615,7 +616,8 @@ HTMLTableElement::InsertRow(int32_t aIndex, ErrorResult& aError)
|
||||
HTMLTableSectionElement* section =
|
||||
static_cast<HTMLTableSectionElement*>(rowGroup.get());
|
||||
nsIHTMLCollection* rows = section->Rows();
|
||||
rowGroup->InsertBefore(*newRow, rows->Item(0), aError);
|
||||
nsCOMPtr<nsINode> refNode = rows->Item(0);
|
||||
rowGroup->InsertBefore(*newRow, refNode, aError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,8 @@ public:
|
||||
|
||||
DeleteTHead();
|
||||
if (aTHead) {
|
||||
nsINode::InsertBefore(*aTHead, nsINode::GetFirstChild(), aError);
|
||||
nsCOMPtr<nsINode> refNode = nsINode::GetFirstChild();
|
||||
nsINode::InsertBefore(*aTHead, refNode, aError);
|
||||
}
|
||||
}
|
||||
already_AddRefed<nsGenericHTMLElement> CreateTHead();
|
||||
|
@ -91,7 +91,8 @@ HTMLTableSectionElement::InsertRow(int32_t aIndex, ErrorResult& aError)
|
||||
}
|
||||
|
||||
if (doInsert) {
|
||||
nsINode::InsertBefore(*rowContent, rows->Item(aIndex), aError);
|
||||
nsCOMPtr<nsINode> refNode = rows->Item(aIndex);
|
||||
nsINode::InsertBefore(*rowContent, refNode, aError);
|
||||
} else {
|
||||
nsINode::AppendChild(*rowContent, aError);
|
||||
}
|
||||
|
@ -443,7 +443,8 @@ UndoContentInsert::RedoTransaction()
|
||||
}
|
||||
|
||||
IgnoredErrorResult error;
|
||||
mContent->InsertBefore(*mChild, mNextNode, error);
|
||||
nsCOMPtr<nsIContent> refNode = mNextNode;
|
||||
mContent->InsertBefore(*mChild, refNode, error);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -537,7 +538,8 @@ UndoContentRemove::UndoTransaction()
|
||||
}
|
||||
|
||||
IgnoredErrorResult error;
|
||||
mContent->InsertBefore(*mChild, mNextNode, error);
|
||||
nsCOMPtr<nsIContent> refNode = mNextNode;
|
||||
mContent->InsertBefore(*mChild, refNode, error);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -3098,10 +3098,16 @@ TabChild::DidRequestComposite(const TimeStamp& aCompositeReqStart,
|
||||
RefPtr<TimelineConsumers> timelines = TimelineConsumers::Get();
|
||||
|
||||
if (timelines && timelines->HasConsumer(docShell)) {
|
||||
// Since we're assuming that it's impossible for content JS to directly
|
||||
// trigger a synchronous paint, we can avoid capturing a stack trace here,
|
||||
// which means we won't run into JS engine reentrancy issues like bug
|
||||
// 1310014.
|
||||
timelines->AddMarkerForDocShell(docShell,
|
||||
"CompositeForwardTransaction", aCompositeReqStart, MarkerTracingType::START);
|
||||
"CompositeForwardTransaction", aCompositeReqStart,
|
||||
MarkerTracingType::START, MarkerStackRequest::NO_STACK);
|
||||
timelines->AddMarkerForDocShell(docShell,
|
||||
"CompositeForwardTransaction", aCompositeReqEnd, MarkerTracingType::END);
|
||||
"CompositeForwardTransaction", aCompositeReqEnd,
|
||||
MarkerTracingType::END, MarkerStackRequest::NO_STACK);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3189,7 +3189,6 @@ public:
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHOD GetNestedFrameId(uint64_t*) NO_IMPL
|
||||
NS_IMETHOD IsAppOfType(uint32_t, bool*) NO_IMPL
|
||||
NS_IMETHOD GetIsContent(bool*) NO_IMPL
|
||||
NS_IMETHOD GetUsePrivateBrowsing(bool*) NO_IMPL
|
||||
NS_IMETHOD SetUsePrivateBrowsing(bool) NO_IMPL
|
||||
|
@ -98,6 +98,8 @@ PEColorNotColor=Expected color but found ‘%1$S’.
|
||||
PEColorComponentEOF=color component
|
||||
PEExpectedPercent=Expected a percentage but found ‘%1$S’.
|
||||
PEExpectedInt=Expected an integer but found ‘%1$S’.
|
||||
PEExpectedNumberOrAngle=Expected a number or an angle but found ‘%1$S’.
|
||||
PEExpectedNumberOrPercent=Expected a number or a percentage but found ‘%1$S’.
|
||||
PEColorBadRGBContents=Expected number or percentage in rgb() but found ‘%1$S’.
|
||||
PEColorComponentBadTerm=Expected ‘%2$S’ but found ‘%1$S’.
|
||||
PEColorHueEOF=hue
|
||||
|
@ -30,19 +30,43 @@ var validThemeColors = [
|
||||
'#f00',
|
||||
'#ff0000',
|
||||
'rgb(255,0,0)',
|
||||
'rgb(255,0,0,1)',
|
||||
'rgb(255,0,0,1.0)',
|
||||
'rgb(255,0,0,100%)',
|
||||
'rgb(255 0 0)',
|
||||
'rgb(255 0 0 / 1)',
|
||||
'rgb(255 0 0 / 1.0)',
|
||||
'rgb(255 0 0 / 100%)',
|
||||
'rgb(100%, 0%, 0%)',
|
||||
'rgb(255,0,0)',
|
||||
'rgb(100%, 0%, 0%, 1)',
|
||||
'rgb(100%, 0%, 0%, 1.0)',
|
||||
'rgb(100%, 0%, 0%, 100%)',
|
||||
'rgb(100% 0% 0%)',
|
||||
'rgb(100% 0% 0% / 1)',
|
||||
'rgb(100%, 0%, 0%, 1.0)',
|
||||
'rgb(100%, 0%, 0%, 100%)',
|
||||
'rgb(300,0,0)',
|
||||
'rgb(300 0 0)',
|
||||
'rgb(255,-10,0)',
|
||||
'rgb(110%, 0%, 0%)',
|
||||
'rgb(255,0,0)',
|
||||
'rgba(255,0,0)',
|
||||
'rgba(255,0,0,1)',
|
||||
'rgb(100%,0%,0%)',
|
||||
'rgba(255 0 0 / 1)',
|
||||
'rgba(100%,0%,0%,1)',
|
||||
'rgba(0,0,255,0.5)',
|
||||
'rgba(100%, 50%, 0%, 0.1)',
|
||||
'hsl(120, 100%, 50%)',
|
||||
'hsla(120, 100%, 50%, 1)',
|
||||
'hsl(120 100% 50%)',
|
||||
'hsl(120, 100%, 50%, 1.0)',
|
||||
'hsl(120 100% 50% / 1.0)',
|
||||
'hsla(120, 100%, 50%)',
|
||||
'hsla(120 100% 50%)',
|
||||
'hsla(120, 100%, 50%, 1.0)',
|
||||
'hsla(120 100% 50% / 1.0)',
|
||||
'hsl(120deg, 100%, 50%)',
|
||||
'hsl(133.33333333grad, 100%, 50%)',
|
||||
'hsl(2.0943951024rad, 100%, 50%)',
|
||||
'hsl(0.3333333333turn, 100%, 50%)',
|
||||
];
|
||||
|
||||
validThemeColors.forEach(background_color => {
|
||||
@ -58,15 +82,15 @@ var invalidThemeColors = [
|
||||
'marooon',
|
||||
'f000000',
|
||||
'#ff00000',
|
||||
'rgb(255 0 0)',
|
||||
'rgb(100, 0%, 0%)',
|
||||
'rgb(255,0)',
|
||||
'rgb(300 0 0)',
|
||||
'rbg(255,-10,0)',
|
||||
'rgb(110, 0%, 0%)',
|
||||
'(255,0,0) }',
|
||||
'rgba(255)',
|
||||
' rgb(100%,0%,0%) }',
|
||||
'hsl(120, 100%, 50)',
|
||||
'hsl(120, 100%, 50.0)',
|
||||
'hsl 120, 100%, 50%',
|
||||
'hsla{120, 100%, 50%, 1}',
|
||||
]
|
||||
|
@ -30,19 +30,43 @@ var validThemeColors = [
|
||||
'#f00',
|
||||
'#ff0000',
|
||||
'rgb(255,0,0)',
|
||||
'rgb(255,0,0,1)',
|
||||
'rgb(255,0,0,1.0)',
|
||||
'rgb(255,0,0,100%)',
|
||||
'rgb(255 0 0)',
|
||||
'rgb(255 0 0 / 1)',
|
||||
'rgb(255 0 0 / 1.0)',
|
||||
'rgb(255 0 0 / 100%)',
|
||||
'rgb(100%, 0%, 0%)',
|
||||
'rgb(255,0,0)',
|
||||
'rgb(100%, 0%, 0%, 1)',
|
||||
'rgb(100%, 0%, 0%, 1.0)',
|
||||
'rgb(100%, 0%, 0%, 100%)',
|
||||
'rgb(100% 0% 0%)',
|
||||
'rgb(100% 0% 0% / 1)',
|
||||
'rgb(100%, 0%, 0%, 1.0)',
|
||||
'rgb(100%, 0%, 0%, 100%)',
|
||||
'rgb(300,0,0)',
|
||||
'rgb(300 0 0)',
|
||||
'rgb(255,-10,0)',
|
||||
'rgb(110%, 0%, 0%)',
|
||||
'rgb(255,0,0)',
|
||||
'rgba(255,0,0)',
|
||||
'rgba(255,0,0,1)',
|
||||
'rgb(100%,0%,0%)',
|
||||
'rgba(255 0 0 / 1)',
|
||||
'rgba(100%,0%,0%,1)',
|
||||
'rgba(0,0,255,0.5)',
|
||||
'rgba(100%, 50%, 0%, 0.1)',
|
||||
'hsl(120, 100%, 50%)',
|
||||
'hsla(120, 100%, 50%, 1)',
|
||||
'hsl(120 100% 50%)',
|
||||
'hsl(120, 100%, 50%, 1.0)',
|
||||
'hsl(120 100% 50% / 1.0)',
|
||||
'hsla(120, 100%, 50%)',
|
||||
'hsla(120 100% 50%)',
|
||||
'hsla(120, 100%, 50%, 1.0)',
|
||||
'hsla(120 100% 50% / 1.0)',
|
||||
'hsl(120deg, 100%, 50%)',
|
||||
'hsl(133.33333333grad, 100%, 50%)',
|
||||
'hsl(2.0943951024rad, 100%, 50%)',
|
||||
'hsl(0.3333333333turn, 100%, 50%)',
|
||||
];
|
||||
|
||||
validThemeColors.forEach(theme_color => {
|
||||
@ -58,15 +82,15 @@ var invalidThemeColors = [
|
||||
'marooon',
|
||||
'f000000',
|
||||
'#ff00000',
|
||||
'rgb(255 0 0)',
|
||||
'rgb(100, 0%, 0%)',
|
||||
'rgb(255,0)',
|
||||
'rgb(300 0 0)',
|
||||
'rbg(255,-10,0)',
|
||||
'rgb(110, 0%, 0%)',
|
||||
'(255,0,0) }',
|
||||
'rgba(255)',
|
||||
' rgb(100%,0%,0%) }',
|
||||
'hsl(120, 100%, 50)',
|
||||
'hsl(120, 100%, 50.0)',
|
||||
'hsl 120, 100%, 50%',
|
||||
'hsla{120, 100%, 50%, 1}',
|
||||
]
|
||||
|
@ -585,6 +585,32 @@ AudioCallbackDriver::~AudioCallbackDriver()
|
||||
MOZ_ASSERT(mPromisesForOperation.IsEmpty());
|
||||
}
|
||||
|
||||
bool IsMacbookOrMacbookAir()
|
||||
{
|
||||
#ifdef XP_MACOSX
|
||||
size_t len = 0;
|
||||
sysctlbyname("hw.model", NULL, &len, NULL, 0);
|
||||
if (len) {
|
||||
UniquePtr<char[]> model(new char[len]);
|
||||
// This string can be
|
||||
// MacBook%d,%d for a normal MacBook
|
||||
// MacBookPro%d,%d for a MacBook Pro
|
||||
// MacBookAir%d,%d for a Macbook Air
|
||||
sysctlbyname("hw.model", model.get(), &len, NULL, 0);
|
||||
char* substring = strstr(model.get(), "MacBook");
|
||||
if (substring) {
|
||||
const size_t offset = strlen("MacBook");
|
||||
if (strncmp(model.get() + offset, "Air", len - offset) ||
|
||||
isdigit(model[offset + 1])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
AudioCallbackDriver::Init()
|
||||
{
|
||||
@ -638,6 +664,13 @@ AudioCallbackDriver::Init()
|
||||
}
|
||||
}
|
||||
|
||||
// Macbook and MacBook air don't have enough CPU to run very low latency
|
||||
// MediaStreamGraphs, cap the minimal latency to 512 frames int this case.
|
||||
if (IsMacbookOrMacbookAir()) {
|
||||
latency_frames = std::max((uint32_t) 512, latency_frames);
|
||||
}
|
||||
|
||||
|
||||
input = output;
|
||||
input.channels = mInputChannels; // change to support optional stereo capture
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "mozilla/dom/MediaStreamTrack.h"
|
||||
#include "GetUserMediaRequest.h"
|
||||
#include "MediaStreamListener.h"
|
||||
#include "nsArray.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsHashPropertyBag.h"
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
@ -20,7 +21,6 @@
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIPermissionManager.h"
|
||||
#include "nsIPopupWindowManager.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
@ -2400,14 +2400,10 @@ if (privileged) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISupportsArray> devicesCopy; // before we give up devices below
|
||||
nsCOMPtr<nsIMutableArray> devicesCopy = nsArray::Create(); // before we give up devices below
|
||||
if (!askPermission) {
|
||||
nsresult rv = NS_NewISupportsArray(getter_AddRefs(devicesCopy));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
for (auto& device : **devices) {
|
||||
rv = devicesCopy->AppendElement(device);
|
||||
nsresult rv = devicesCopy->AppendElement(device, /*weak =*/ false);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
@ -3025,15 +3021,15 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
if (aSubject) {
|
||||
// A particular device or devices were chosen by the user.
|
||||
// NOTE: does not allow setting a device to null; assumes nullptr
|
||||
nsCOMPtr<nsISupportsArray> array(do_QueryInterface(aSubject));
|
||||
nsCOMPtr<nsIArray> array(do_QueryInterface(aSubject));
|
||||
MOZ_ASSERT(array);
|
||||
uint32_t len = 0;
|
||||
array->Count(&len);
|
||||
array->GetLength(&len);
|
||||
bool videoFound = false, audioFound = false;
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
nsCOMPtr<nsISupports> supports;
|
||||
array->GetElementAt(i,getter_AddRefs(supports));
|
||||
nsCOMPtr<nsIMediaDevice> device(do_QueryInterface(supports));
|
||||
nsCOMPtr<nsIMediaDevice> device;
|
||||
array->QueryElementAt(i, NS_GET_IID(nsIMediaDevice),
|
||||
getter_AddRefs(device));
|
||||
MOZ_ASSERT(device); // shouldn't be returning anything else...
|
||||
if (device) {
|
||||
nsString type;
|
||||
@ -3127,14 +3123,11 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
}
|
||||
|
||||
nsresult
|
||||
MediaManager::GetActiveMediaCaptureWindows(nsISupportsArray** aArray)
|
||||
MediaManager::GetActiveMediaCaptureWindows(nsIArray** aArray)
|
||||
{
|
||||
MOZ_ASSERT(aArray);
|
||||
nsISupportsArray* array;
|
||||
nsresult rv = NS_NewISupportsArray(&array); // AddRefs
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIMutableArray> array = nsArray::Create();
|
||||
|
||||
for (auto iter = mActiveWindows.Iter(); !iter.Done(); iter.Next()) {
|
||||
const uint64_t& id = iter.Key();
|
||||
@ -3165,11 +3158,11 @@ MediaManager::GetActiveMediaCaptureWindows(nsISupportsArray** aArray)
|
||||
}
|
||||
}
|
||||
if (capturing) {
|
||||
array->AppendElement(window);
|
||||
array->AppendElement(window, /*weak =*/ false);
|
||||
}
|
||||
}
|
||||
|
||||
*aArray = array;
|
||||
array.forget(aArray);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -3328,14 +3321,14 @@ MediaManager::IterateWindowListeners(nsPIDOMWindowInner* aWindow,
|
||||
void
|
||||
MediaManager::StopMediaStreams()
|
||||
{
|
||||
nsCOMPtr<nsISupportsArray> array;
|
||||
nsCOMPtr<nsIArray> array;
|
||||
GetActiveMediaCaptureWindows(getter_AddRefs(array));
|
||||
uint32_t len;
|
||||
array->Count(&len);
|
||||
array->GetLength(&len);
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
nsCOMPtr<nsISupports> window;
|
||||
array->GetElementAt(i, getter_AddRefs(window));
|
||||
nsCOMPtr<nsPIDOMWindowInner> win(do_QueryInterface(window));
|
||||
nsCOMPtr<nsPIDOMWindowInner> win;
|
||||
array->QueryElementAt(i, NS_GET_IID(nsPIDOMWindowInner),
|
||||
getter_AddRefs(win));
|
||||
if (win) {
|
||||
OnNavigation(win->WindowID());
|
||||
}
|
||||
@ -3347,14 +3340,14 @@ MediaManager::IsActivelyCapturingOrHasAPermission(uint64_t aWindowId)
|
||||
{
|
||||
// Does page currently have a gUM stream active?
|
||||
|
||||
nsCOMPtr<nsISupportsArray> array;
|
||||
nsCOMPtr<nsIArray> array;
|
||||
GetActiveMediaCaptureWindows(getter_AddRefs(array));
|
||||
uint32_t len;
|
||||
array->Count(&len);
|
||||
array->GetLength(&len);
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
nsCOMPtr<nsISupports> window;
|
||||
array->GetElementAt(i, getter_AddRefs(window));
|
||||
nsCOMPtr<nsPIDOMWindowInner> win(do_QueryInterface(window));
|
||||
nsCOMPtr<nsPIDOMWindowInner> win;
|
||||
array->QueryElementAt(i, NS_GET_IID(nsPIDOMWindowInner),
|
||||
getter_AddRefs(win));
|
||||
if (win && win->WindowID() == aWindowId) {
|
||||
return true;
|
||||
}
|
||||
|
@ -5,12 +5,12 @@
|
||||
#include "MediaManager.h"
|
||||
#include "MediaPermissionGonk.h"
|
||||
|
||||
#include "nsArray.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIContentPermissionPrompt.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMNavigatorUserMedia.h"
|
||||
#include "nsIStringEnumerator.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsQueryObject.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
@ -67,12 +67,10 @@ static nsresult
|
||||
NotifyPermissionAllow(const nsAString &aCallID, nsTArray<nsCOMPtr<nsIMediaDevice> > &aDevices)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsISupportsArray> array;
|
||||
rv = NS_NewISupportsArray(getter_AddRefs(array));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIMutableArray> array = nsArray::Create();
|
||||
|
||||
for (uint32_t i = 0; i < aDevices.Length(); ++i) {
|
||||
rv = array->AppendElement(aDevices.ElementAt(i));
|
||||
rv = array->AppendElement(aDevices.ElementAt(i), /*weak =*/ false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
|
@ -65,11 +65,6 @@ MediaKeySystemAccessManager::Request(DetailedPromise* aPromise,
|
||||
const nsAString& aKeySystem,
|
||||
const Sequence<MediaKeySystemConfiguration>& aConfigs)
|
||||
{
|
||||
if (aKeySystem.IsEmpty() || aConfigs.IsEmpty()) {
|
||||
aPromise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR,
|
||||
NS_LITERAL_CSTRING("Invalid keysystem type or invalid options sequence"));
|
||||
return;
|
||||
}
|
||||
Request(aPromise, aKeySystem, aConfigs, RequestType::Initial);
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsISupportsArray;
|
||||
interface nsIArray;
|
||||
interface nsIDOMWindow;
|
||||
|
||||
%{C++
|
||||
@ -16,7 +16,7 @@ interface nsIDOMWindow;
|
||||
interface nsIMediaManagerService : nsISupports
|
||||
{
|
||||
/* return a array of inner windows that have active captures */
|
||||
readonly attribute nsISupportsArray activeMediaCaptureWindows;
|
||||
readonly attribute nsIArray activeMediaCaptureWindows;
|
||||
|
||||
/* Get the capture state for the given window and all descendant windows (iframes, etc) */
|
||||
void mediaCaptureWindowState(in nsIDOMWindow aWindow, out boolean aVideo, out boolean aAudio,
|
||||
|
@ -131,7 +131,8 @@ DesktopNotification::PostDesktopNotification()
|
||||
EmptyString(),
|
||||
EmptyString(),
|
||||
principal,
|
||||
inPrivateBrowsing);
|
||||
inPrivateBrowsing,
|
||||
false /* requireInteraction */);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return alerts->ShowAlert(alert, mObserver);
|
||||
}
|
||||
|
@ -928,6 +928,21 @@ NotificationTask::Run()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
Notification::RequireInteractionEnabled(JSContext* aCx, JSObject* aOjb)
|
||||
{
|
||||
if (NS_IsMainThread()) {
|
||||
return Preferences::GetBool("dom.webnotifications.requireinteraction.enabled", false);
|
||||
}
|
||||
|
||||
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
|
||||
if (!workerPrivate) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return workerPrivate->DOMWorkerNotificationRIEnabled();
|
||||
}
|
||||
|
||||
// static
|
||||
bool
|
||||
Notification::PrefEnabled(JSContext* aCx, JSObject* aObj)
|
||||
@ -959,11 +974,13 @@ Notification::Notification(nsIGlobalObject* aGlobal, const nsAString& aID,
|
||||
const nsAString& aTitle, const nsAString& aBody,
|
||||
NotificationDirection aDir, const nsAString& aLang,
|
||||
const nsAString& aTag, const nsAString& aIconUrl,
|
||||
bool aRequireInteraction,
|
||||
const NotificationBehavior& aBehavior)
|
||||
: DOMEventTargetHelper(),
|
||||
mWorkerPrivate(nullptr), mObserver(nullptr),
|
||||
mID(aID), mTitle(aTitle), mBody(aBody), mDir(aDir), mLang(aLang),
|
||||
mTag(aTag), mIconUrl(aIconUrl), mBehavior(aBehavior), mData(JS::NullValue()),
|
||||
mTag(aTag), mIconUrl(aIconUrl), mRequireInteraction(aRequireInteraction),
|
||||
mBehavior(aBehavior), mData(JS::NullValue()),
|
||||
mIsClosed(false), mIsStored(false), mTaskCount(0)
|
||||
{
|
||||
if (NS_IsMainThread()) {
|
||||
@ -1186,6 +1203,7 @@ Notification::CreateInternal(nsIGlobalObject* aGlobal,
|
||||
aOptions.mLang,
|
||||
aOptions.mTag,
|
||||
aOptions.mIcon,
|
||||
aOptions.mRequireInteraction,
|
||||
aOptions.mMozbehavior);
|
||||
rv = notification->Init();
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
@ -1818,6 +1836,11 @@ Notification::ShowInternal()
|
||||
uniqueCookie.AppendInt(sCount++);
|
||||
bool inPrivateBrowsing = IsInPrivateBrowsing();
|
||||
|
||||
bool requireInteraction = mRequireInteraction;
|
||||
if (!Preferences::GetBool("dom.webnotifications.requireinteraction.enabled", false)) {
|
||||
requireInteraction = false;
|
||||
}
|
||||
|
||||
nsAutoString alertName;
|
||||
GetAlertName(alertName);
|
||||
nsCOMPtr<nsIAlertNotification> alert =
|
||||
@ -1831,7 +1854,8 @@ Notification::ShowInternal()
|
||||
mLang,
|
||||
mDataAsBase64,
|
||||
GetPrincipal(),
|
||||
inPrivateBrowsing);
|
||||
inPrivateBrowsing,
|
||||
requireInteraction);
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
|
||||
if (isPersistent) {
|
||||
@ -2361,6 +2385,12 @@ Notification::GetOrigin(nsIPrincipal* aPrincipal, nsString& aOrigin)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
Notification::RequireInteraction() const
|
||||
{
|
||||
return mRequireInteraction;
|
||||
}
|
||||
|
||||
void
|
||||
Notification::GetData(JSContext* aCx,
|
||||
JS::MutableHandle<JS::Value> aRetval)
|
||||
@ -2692,7 +2722,7 @@ Notification::ShowPersistentNotification(JSContext* aCx,
|
||||
// which leads to uglier code.
|
||||
NotificationPermission permission = GetPermission(aGlobal, aRv);
|
||||
|
||||
// "If permission for notification’s origin is not "granted", reject promise with a TypeError exception, and terminate these substeps."
|
||||
// "If permission for notification's origin is not "granted", reject promise with a TypeError exception, and terminate these substeps."
|
||||
if (NS_WARN_IF(aRv.Failed()) || permission == NotificationPermission::Denied) {
|
||||
ErrorResult result;
|
||||
result.ThrowTypeError<MSG_NOTIFICATION_PERMISSION_DENIED>();
|
||||
|
@ -155,6 +155,7 @@ public:
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(Notification, DOMEventTargetHelper)
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
static bool RequireInteractionEnabled(JSContext* aCx, JSObject* aObj);
|
||||
static bool PrefEnabled(JSContext* aCx, JSObject* aObj);
|
||||
// Returns if Notification.get() is allowed for the current global.
|
||||
static bool IsGetEnabled(JSContext* aCx, JSObject* aObj);
|
||||
@ -280,6 +281,8 @@ public:
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
bool RequireInteraction() const;
|
||||
|
||||
void GetData(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval);
|
||||
|
||||
void InitFromJSVal(JSContext* aCx, JS::Handle<JS::Value> aData, ErrorResult& aRv);
|
||||
@ -329,6 +332,7 @@ protected:
|
||||
const nsAString& aTitle, const nsAString& aBody,
|
||||
NotificationDirection aDir, const nsAString& aLang,
|
||||
const nsAString& aTag, const nsAString& aIconUrl,
|
||||
bool aRequireNotification,
|
||||
const NotificationBehavior& aBehavior);
|
||||
|
||||
static already_AddRefed<Notification> CreateInternal(nsIGlobalObject* aGlobal,
|
||||
@ -397,6 +401,7 @@ protected:
|
||||
const nsString mLang;
|
||||
const nsString mTag;
|
||||
const nsString mIconUrl;
|
||||
const bool mRequireInteraction;
|
||||
nsString mDataAsBase64;
|
||||
const NotificationBehavior mBehavior;
|
||||
|
||||
|
@ -43,7 +43,7 @@ private:
|
||||
|
||||
virtual ~PresentationReceiver();
|
||||
|
||||
bool Init();
|
||||
MOZ_IS_CLASS_INIT bool Init();
|
||||
|
||||
void Shutdown();
|
||||
|
||||
|
@ -965,7 +965,8 @@ nsCSPContext::SendReports(nsISupports* aBlockedContentSource,
|
||||
// wire in the string input stream to send the report
|
||||
nsCOMPtr<nsIStringInputStream> sis(do_CreateInstance(NS_STRINGINPUTSTREAM_CONTRACTID));
|
||||
NS_ASSERTION(sis, "nsIStringInputStream is needed but not available to send CSP violation reports");
|
||||
rv = sis->SetData(NS_ConvertUTF16toUTF8(csp_report).get(), csp_report.Length());
|
||||
nsAutoCString utf8CSPReport = NS_ConvertUTF16toUTF8(csp_report);
|
||||
rv = sis->SetData(utf8CSPReport.get(), utf8CSPReport.Length());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(reportChannel));
|
||||
|
@ -121,7 +121,9 @@ function run_test() {
|
||||
});
|
||||
|
||||
// test that eval violations cause a report.
|
||||
makeTest(1, {"blocked-uri": "self"}, false,
|
||||
makeTest(1, {"blocked-uri": "self",
|
||||
// JSON script-sample is UTF8 encoded
|
||||
"script-sample" : "\xc2\xa3\xc2\xa5\xc2\xb5\xe5\x8c\x97\xf0\xa0\x9d\xb9"}, false,
|
||||
function(csp) {
|
||||
let evalOK = true, oReportViolation = {'value': false};
|
||||
evalOK = csp.getAllowsEval(oReportViolation);
|
||||
@ -135,7 +137,10 @@ function run_test() {
|
||||
// force the logging, since the getter doesn't.
|
||||
csp.logViolationDetails(Ci.nsIContentSecurityPolicy.VIOLATION_TYPE_EVAL,
|
||||
selfuri.asciiSpec,
|
||||
"script sample",
|
||||
// sending UTF-16 script sample to make sure
|
||||
// csp report in JSON is not cut-off, please
|
||||
// note that JSON is UTF8 encoded.
|
||||
"\u00a3\u00a5\u00b5\u5317\ud841\udf79",
|
||||
1);
|
||||
}
|
||||
});
|
||||
|
@ -94,6 +94,15 @@ SVGFEImageElement::LoadSVGImage(bool aForce, bool aNotify)
|
||||
return LoadImage(href, aForce, aNotify, eImageLoadType_Normal);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// EventTarget methods:
|
||||
|
||||
void
|
||||
SVGFEImageElement::AsyncEventRunning(AsyncEventDispatcher* aEvent)
|
||||
{
|
||||
nsImageLoadingContent::AsyncEventRunning(aEvent);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// nsIContent methods:
|
||||
|
||||
|
@ -38,6 +38,9 @@ public:
|
||||
// interfaces:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// EventTarget
|
||||
virtual void AsyncEventRunning(AsyncEventDispatcher* aEvent) override;
|
||||
|
||||
virtual FilterPrimitiveDescription
|
||||
GetPrimitiveDescription(nsSVGFilterInstance* aInstance,
|
||||
const IntRect& aFilterSubregion,
|
||||
|
@ -136,6 +136,15 @@ SVGImageElement::LoadSVGImage(bool aForce, bool aNotify)
|
||||
return LoadImage(href, aForce, aNotify, eImageLoadType_Normal);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// EventTarget methods:
|
||||
|
||||
void
|
||||
SVGImageElement::AsyncEventRunning(AsyncEventDispatcher* aEvent)
|
||||
{
|
||||
nsImageLoadingContent::AsyncEventRunning(aEvent);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// nsIContent methods:
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user