зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central and fx-team
This commit is contained in:
Коммит
486a0e5021
|
@ -18,6 +18,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "FileUtils", "resource://gre/modules/Fil
|
|||
XPCOMUtils.defineLazyModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "console", "resource://gre/modules/devtools/Console.jsm");
|
||||
|
||||
let SourceMap = {};
|
||||
Cu.import("resource://gre/modules/devtools/SourceMap.jsm", SourceMap);
|
||||
|
||||
let loader = Cu.import("resource://gre/modules/commonjs/toolkit/loader.js", {}).Loader;
|
||||
let promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {}).Promise;
|
||||
|
||||
|
@ -43,7 +46,8 @@ var BuiltinProvider = {
|
|||
load: function() {
|
||||
this.loader = new loader.Loader({
|
||||
modules: {
|
||||
"toolkit/loader": loader
|
||||
"toolkit/loader": loader,
|
||||
"source-map": SourceMap,
|
||||
},
|
||||
paths: {
|
||||
"": "resource://gre/modules/commonjs/",
|
||||
|
@ -54,6 +58,10 @@ var BuiltinProvider = {
|
|||
"devtools/styleinspector/css-logic": "resource://gre/modules/devtools/styleinspector/css-logic",
|
||||
"devtools/client": "resource://gre/modules/devtools/client",
|
||||
|
||||
"escodegen/escodegen": "resource://gre/modules/devtools/escodegen/escodegen",
|
||||
"escodegen/package.json": "resource://gre/modules/devtools/escodegen/package.json",
|
||||
"estraverse": "resource://gre/modules/devtools/escodegen/estraverse",
|
||||
|
||||
// Allow access to xpcshell test items from the loader.
|
||||
"xpcshell-test": "resource://test"
|
||||
},
|
||||
|
@ -92,7 +100,8 @@ var SrcdirProvider = {
|
|||
let mainURI = this.fileURI(OS.Path.join(srcdir, "browser", "devtools", "main.js"));
|
||||
this.loader = new loader.Loader({
|
||||
modules: {
|
||||
"toolkit/loader": loader
|
||||
"toolkit/loader": loader,
|
||||
"source-map": SourceMap,
|
||||
},
|
||||
paths: {
|
||||
"": "resource://gre/modules/commonjs/",
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,32 @@
|
|||
Assuming that escodegen's dependencies have not changed, to upgrade our tree's
|
||||
escodegen to a new version:
|
||||
|
||||
1. Clone the escodegen repository, and check out the version you want to upgrade
|
||||
to:
|
||||
|
||||
$ git clone https://github.com/Constellation/escodegen.git
|
||||
$ cd escodegen
|
||||
$ git checkout <version>
|
||||
|
||||
2. Make sure that all tests pass:
|
||||
|
||||
$ npm install .
|
||||
$ npm test
|
||||
|
||||
If there are any test failures, do not upgrade to that version of escodegen!
|
||||
|
||||
3. Copy escodegen.js to our tree:
|
||||
|
||||
$ cp escodegen.js /path/to/mozilla-central/toolkit/devtools/escodegen/escodegen.js
|
||||
|
||||
4. Copy the package.json to our tree, and append ".js" to make it work with our
|
||||
loader:
|
||||
|
||||
$ cp package.json /path/to/mozilla-central/toolkit/devtools/escodegen/package.json.js
|
||||
|
||||
5. Prepend `module.exports = ` to the package.json file contents, so that the
|
||||
JSON data is exported, and we can load package.json as a module.
|
||||
|
||||
6. Copy the estraverse.js that escodegen depends on into our tree:
|
||||
|
||||
$ cp node_modules/estraverse/estraverse.js /path/to/mozilla-central/devtools/escodegen/estraverse.js
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -0,0 +1,678 @@
|
|||
/*
|
||||
Copyright (C) 2012-2013 Yusuke Suzuki <utatane.tea@gmail.com>
|
||||
Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*jslint vars:false*/
|
||||
/*jshint indent:4*/
|
||||
/*global exports:true, define:true*/
|
||||
(function (root, factory) {
|
||||
'use strict';
|
||||
|
||||
// Universal Module Definition (UMD) to support AMD, CommonJS/Node.js,
|
||||
// and plain browser loading,
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define(['exports'], factory);
|
||||
} else if (typeof exports !== 'undefined') {
|
||||
factory(exports);
|
||||
} else {
|
||||
factory((root.estraverse = {}));
|
||||
}
|
||||
}(this, function (exports) {
|
||||
'use strict';
|
||||
|
||||
var Syntax,
|
||||
isArray,
|
||||
VisitorOption,
|
||||
VisitorKeys,
|
||||
BREAK,
|
||||
SKIP;
|
||||
|
||||
Syntax = {
|
||||
AssignmentExpression: 'AssignmentExpression',
|
||||
ArrayExpression: 'ArrayExpression',
|
||||
BlockStatement: 'BlockStatement',
|
||||
BinaryExpression: 'BinaryExpression',
|
||||
BreakStatement: 'BreakStatement',
|
||||
CallExpression: 'CallExpression',
|
||||
CatchClause: 'CatchClause',
|
||||
ConditionalExpression: 'ConditionalExpression',
|
||||
ContinueStatement: 'ContinueStatement',
|
||||
DebuggerStatement: 'DebuggerStatement',
|
||||
DirectiveStatement: 'DirectiveStatement',
|
||||
DoWhileStatement: 'DoWhileStatement',
|
||||
EmptyStatement: 'EmptyStatement',
|
||||
ExpressionStatement: 'ExpressionStatement',
|
||||
ForStatement: 'ForStatement',
|
||||
ForInStatement: 'ForInStatement',
|
||||
FunctionDeclaration: 'FunctionDeclaration',
|
||||
FunctionExpression: 'FunctionExpression',
|
||||
Identifier: 'Identifier',
|
||||
IfStatement: 'IfStatement',
|
||||
Literal: 'Literal',
|
||||
LabeledStatement: 'LabeledStatement',
|
||||
LogicalExpression: 'LogicalExpression',
|
||||
MemberExpression: 'MemberExpression',
|
||||
NewExpression: 'NewExpression',
|
||||
ObjectExpression: 'ObjectExpression',
|
||||
Program: 'Program',
|
||||
Property: 'Property',
|
||||
ReturnStatement: 'ReturnStatement',
|
||||
SequenceExpression: 'SequenceExpression',
|
||||
SwitchStatement: 'SwitchStatement',
|
||||
SwitchCase: 'SwitchCase',
|
||||
ThisExpression: 'ThisExpression',
|
||||
ThrowStatement: 'ThrowStatement',
|
||||
TryStatement: 'TryStatement',
|
||||
UnaryExpression: 'UnaryExpression',
|
||||
UpdateExpression: 'UpdateExpression',
|
||||
VariableDeclaration: 'VariableDeclaration',
|
||||
VariableDeclarator: 'VariableDeclarator',
|
||||
WhileStatement: 'WhileStatement',
|
||||
WithStatement: 'WithStatement',
|
||||
YieldExpression: 'YieldExpression'
|
||||
};
|
||||
|
||||
function ignoreJSHintError() { }
|
||||
|
||||
isArray = Array.isArray;
|
||||
if (!isArray) {
|
||||
isArray = function isArray(array) {
|
||||
return Object.prototype.toString.call(array) === '[object Array]';
|
||||
};
|
||||
}
|
||||
|
||||
function deepCopy(obj) {
|
||||
var ret = {}, key, val;
|
||||
for (key in obj) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
val = obj[key];
|
||||
if (typeof val === 'object' && val !== null) {
|
||||
ret[key] = deepCopy(val);
|
||||
} else {
|
||||
ret[key] = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
function shallowCopy(obj) {
|
||||
var ret = {}, key;
|
||||
for (key in obj) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
ret[key] = obj[key];
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
ignoreJSHintError(shallowCopy);
|
||||
|
||||
// based on LLVM libc++ upper_bound / lower_bound
|
||||
// MIT License
|
||||
|
||||
function upperBound(array, func) {
|
||||
var diff, len, i, current;
|
||||
|
||||
len = array.length;
|
||||
i = 0;
|
||||
|
||||
while (len) {
|
||||
diff = len >>> 1;
|
||||
current = i + diff;
|
||||
if (func(array[current])) {
|
||||
len = diff;
|
||||
} else {
|
||||
i = current + 1;
|
||||
len -= diff + 1;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
function lowerBound(array, func) {
|
||||
var diff, len, i, current;
|
||||
|
||||
len = array.length;
|
||||
i = 0;
|
||||
|
||||
while (len) {
|
||||
diff = len >>> 1;
|
||||
current = i + diff;
|
||||
if (func(array[current])) {
|
||||
i = current + 1;
|
||||
len -= diff + 1;
|
||||
} else {
|
||||
len = diff;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
ignoreJSHintError(lowerBound);
|
||||
|
||||
VisitorKeys = {
|
||||
AssignmentExpression: ['left', 'right'],
|
||||
ArrayExpression: ['elements'],
|
||||
BlockStatement: ['body'],
|
||||
BinaryExpression: ['left', 'right'],
|
||||
BreakStatement: ['label'],
|
||||
CallExpression: ['callee', 'arguments'],
|
||||
CatchClause: ['param', 'body'],
|
||||
ConditionalExpression: ['test', 'consequent', 'alternate'],
|
||||
ContinueStatement: ['label'],
|
||||
DebuggerStatement: [],
|
||||
DirectiveStatement: [],
|
||||
DoWhileStatement: ['body', 'test'],
|
||||
EmptyStatement: [],
|
||||
ExpressionStatement: ['expression'],
|
||||
ForStatement: ['init', 'test', 'update', 'body'],
|
||||
ForInStatement: ['left', 'right', 'body'],
|
||||
FunctionDeclaration: ['id', 'params', 'body'],
|
||||
FunctionExpression: ['id', 'params', 'body'],
|
||||
Identifier: [],
|
||||
IfStatement: ['test', 'consequent', 'alternate'],
|
||||
Literal: [],
|
||||
LabeledStatement: ['label', 'body'],
|
||||
LogicalExpression: ['left', 'right'],
|
||||
MemberExpression: ['object', 'property'],
|
||||
NewExpression: ['callee', 'arguments'],
|
||||
ObjectExpression: ['properties'],
|
||||
Program: ['body'],
|
||||
Property: ['key', 'value'],
|
||||
ReturnStatement: ['argument'],
|
||||
SequenceExpression: ['expressions'],
|
||||
SwitchStatement: ['discriminant', 'cases'],
|
||||
SwitchCase: ['test', 'consequent'],
|
||||
ThisExpression: [],
|
||||
ThrowStatement: ['argument'],
|
||||
TryStatement: ['block', 'handlers', 'handler', 'guardedHandlers', 'finalizer'],
|
||||
UnaryExpression: ['argument'],
|
||||
UpdateExpression: ['argument'],
|
||||
VariableDeclaration: ['declarations'],
|
||||
VariableDeclarator: ['id', 'init'],
|
||||
WhileStatement: ['test', 'body'],
|
||||
WithStatement: ['object', 'body'],
|
||||
YieldExpression: ['argument']
|
||||
};
|
||||
|
||||
// unique id
|
||||
BREAK = {};
|
||||
SKIP = {};
|
||||
|
||||
VisitorOption = {
|
||||
Break: BREAK,
|
||||
Skip: SKIP
|
||||
};
|
||||
|
||||
function Reference(parent, key) {
|
||||
this.parent = parent;
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
Reference.prototype.replace = function replace(node) {
|
||||
this.parent[this.key] = node;
|
||||
};
|
||||
|
||||
function Element(node, path, wrap, ref) {
|
||||
this.node = node;
|
||||
this.path = path;
|
||||
this.wrap = wrap;
|
||||
this.ref = ref;
|
||||
}
|
||||
|
||||
function Controller() { }
|
||||
|
||||
// API:
|
||||
// return property path array from root to current node
|
||||
Controller.prototype.path = function path() {
|
||||
var i, iz, j, jz, result, element;
|
||||
|
||||
function addToPath(result, path) {
|
||||
if (isArray(path)) {
|
||||
for (j = 0, jz = path.length; j < jz; ++j) {
|
||||
result.push(path[j]);
|
||||
}
|
||||
} else {
|
||||
result.push(path);
|
||||
}
|
||||
}
|
||||
|
||||
// root node
|
||||
if (!this.__current.path) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// first node is sentinel, second node is root element
|
||||
result = [];
|
||||
for (i = 2, iz = this.__leavelist.length; i < iz; ++i) {
|
||||
element = this.__leavelist[i];
|
||||
addToPath(result, element.path);
|
||||
}
|
||||
addToPath(result, this.__current.path);
|
||||
return result;
|
||||
};
|
||||
|
||||
// API:
|
||||
// return array of parent elements
|
||||
Controller.prototype.parents = function parents() {
|
||||
var i, iz, result;
|
||||
|
||||
// first node is sentinel
|
||||
result = [];
|
||||
for (i = 1, iz = this.__leavelist.length; i < iz; ++i) {
|
||||
result.push(this.__leavelist[i].node);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
// API:
|
||||
// return current node
|
||||
Controller.prototype.current = function current() {
|
||||
return this.__current.node;
|
||||
};
|
||||
|
||||
Controller.prototype.__execute = function __execute(callback, element) {
|
||||
var previous, result;
|
||||
|
||||
result = undefined;
|
||||
|
||||
previous = this.__current;
|
||||
this.__current = element;
|
||||
this.__state = null;
|
||||
if (callback) {
|
||||
result = callback.call(this, element.node, this.__leavelist[this.__leavelist.length - 1].node);
|
||||
}
|
||||
this.__current = previous;
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
// API:
|
||||
// notify control skip / break
|
||||
Controller.prototype.notify = function notify(flag) {
|
||||
this.__state = flag;
|
||||
};
|
||||
|
||||
// API:
|
||||
// skip child nodes of current node
|
||||
Controller.prototype.skip = function () {
|
||||
this.notify(SKIP);
|
||||
};
|
||||
|
||||
// API:
|
||||
// break traversals
|
||||
Controller.prototype['break'] = function () {
|
||||
this.notify(BREAK);
|
||||
};
|
||||
|
||||
Controller.prototype.__initialize = function(root, visitor) {
|
||||
this.visitor = visitor;
|
||||
this.root = root;
|
||||
this.__worklist = [];
|
||||
this.__leavelist = [];
|
||||
this.__current = null;
|
||||
this.__state = null;
|
||||
};
|
||||
|
||||
Controller.prototype.traverse = function traverse(root, visitor) {
|
||||
var worklist,
|
||||
leavelist,
|
||||
element,
|
||||
node,
|
||||
nodeType,
|
||||
ret,
|
||||
key,
|
||||
current,
|
||||
current2,
|
||||
candidates,
|
||||
candidate,
|
||||
sentinel;
|
||||
|
||||
this.__initialize(root, visitor);
|
||||
|
||||
sentinel = {};
|
||||
|
||||
// reference
|
||||
worklist = this.__worklist;
|
||||
leavelist = this.__leavelist;
|
||||
|
||||
// initialize
|
||||
worklist.push(new Element(root, null, null, null));
|
||||
leavelist.push(new Element(null, null, null, null));
|
||||
|
||||
while (worklist.length) {
|
||||
element = worklist.pop();
|
||||
|
||||
if (element === sentinel) {
|
||||
element = leavelist.pop();
|
||||
|
||||
ret = this.__execute(visitor.leave, element);
|
||||
|
||||
if (this.__state === BREAK || ret === BREAK) {
|
||||
return;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (element.node) {
|
||||
|
||||
ret = this.__execute(visitor.enter, element);
|
||||
|
||||
if (this.__state === BREAK || ret === BREAK) {
|
||||
return;
|
||||
}
|
||||
|
||||
worklist.push(sentinel);
|
||||
leavelist.push(element);
|
||||
|
||||
if (this.__state === SKIP || ret === SKIP) {
|
||||
continue;
|
||||
}
|
||||
|
||||
node = element.node;
|
||||
nodeType = element.wrap || node.type;
|
||||
candidates = VisitorKeys[nodeType];
|
||||
|
||||
current = candidates.length;
|
||||
while ((current -= 1) >= 0) {
|
||||
key = candidates[current];
|
||||
candidate = node[key];
|
||||
if (!candidate) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isArray(candidate)) {
|
||||
worklist.push(new Element(candidate, key, null, null));
|
||||
continue;
|
||||
}
|
||||
|
||||
current2 = candidate.length;
|
||||
while ((current2 -= 1) >= 0) {
|
||||
if (!candidate[current2]) {
|
||||
continue;
|
||||
}
|
||||
if (nodeType === Syntax.ObjectExpression && 'properties' === candidates[current]) {
|
||||
element = new Element(candidate[current2], [key, current2], 'Property', null);
|
||||
} else {
|
||||
element = new Element(candidate[current2], [key, current2], null, null);
|
||||
}
|
||||
worklist.push(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Controller.prototype.replace = function replace(root, visitor) {
|
||||
var worklist,
|
||||
leavelist,
|
||||
node,
|
||||
nodeType,
|
||||
target,
|
||||
element,
|
||||
current,
|
||||
current2,
|
||||
candidates,
|
||||
candidate,
|
||||
sentinel,
|
||||
outer,
|
||||
key;
|
||||
|
||||
this.__initialize(root, visitor);
|
||||
|
||||
sentinel = {};
|
||||
|
||||
// reference
|
||||
worklist = this.__worklist;
|
||||
leavelist = this.__leavelist;
|
||||
|
||||
// initialize
|
||||
outer = {
|
||||
root: root
|
||||
};
|
||||
element = new Element(root, null, null, new Reference(outer, 'root'));
|
||||
worklist.push(element);
|
||||
leavelist.push(element);
|
||||
|
||||
while (worklist.length) {
|
||||
element = worklist.pop();
|
||||
|
||||
if (element === sentinel) {
|
||||
element = leavelist.pop();
|
||||
|
||||
target = this.__execute(visitor.leave, element);
|
||||
|
||||
// node may be replaced with null,
|
||||
// so distinguish between undefined and null in this place
|
||||
if (target !== undefined && target !== BREAK && target !== SKIP) {
|
||||
// replace
|
||||
element.ref.replace(target);
|
||||
}
|
||||
|
||||
if (this.__state === BREAK || target === BREAK) {
|
||||
return outer.root;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
target = this.__execute(visitor.enter, element);
|
||||
|
||||
// node may be replaced with null,
|
||||
// so distinguish between undefined and null in this place
|
||||
if (target !== undefined && target !== BREAK && target !== SKIP) {
|
||||
// replace
|
||||
element.ref.replace(target);
|
||||
element.node = target;
|
||||
}
|
||||
|
||||
if (this.__state === BREAK || target === BREAK) {
|
||||
return outer.root;
|
||||
}
|
||||
|
||||
// node may be null
|
||||
node = element.node;
|
||||
if (!node) {
|
||||
continue;
|
||||
}
|
||||
|
||||
worklist.push(sentinel);
|
||||
leavelist.push(element);
|
||||
|
||||
if (this.__state === SKIP || target === SKIP) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nodeType = element.wrap || node.type;
|
||||
candidates = VisitorKeys[nodeType];
|
||||
|
||||
current = candidates.length;
|
||||
while ((current -= 1) >= 0) {
|
||||
key = candidates[current];
|
||||
candidate = node[key];
|
||||
if (!candidate) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isArray(candidate)) {
|
||||
worklist.push(new Element(candidate, key, null, new Reference(node, key)));
|
||||
continue;
|
||||
}
|
||||
|
||||
current2 = candidate.length;
|
||||
while ((current2 -= 1) >= 0) {
|
||||
if (!candidate[current2]) {
|
||||
continue;
|
||||
}
|
||||
if (nodeType === Syntax.ObjectExpression && 'properties' === candidates[current]) {
|
||||
element = new Element(candidate[current2], [key, current2], 'Property', new Reference(candidate, current2));
|
||||
} else {
|
||||
element = new Element(candidate[current2], [key, current2], null, new Reference(candidate, current2));
|
||||
}
|
||||
worklist.push(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outer.root;
|
||||
};
|
||||
|
||||
function traverse(root, visitor) {
|
||||
var controller = new Controller();
|
||||
return controller.traverse(root, visitor);
|
||||
}
|
||||
|
||||
function replace(root, visitor) {
|
||||
var controller = new Controller();
|
||||
return controller.replace(root, visitor);
|
||||
}
|
||||
|
||||
function extendCommentRange(comment, tokens) {
|
||||
var target, token;
|
||||
|
||||
target = upperBound(tokens, function search(token) {
|
||||
return token.range[0] > comment.range[0];
|
||||
});
|
||||
|
||||
comment.extendedRange = [comment.range[0], comment.range[1]];
|
||||
|
||||
if (target !== tokens.length) {
|
||||
comment.extendedRange[1] = tokens[target].range[0];
|
||||
}
|
||||
|
||||
target -= 1;
|
||||
if (target >= 0) {
|
||||
if (target < tokens.length) {
|
||||
comment.extendedRange[0] = tokens[target].range[1];
|
||||
} else if (token.length) {
|
||||
comment.extendedRange[1] = tokens[tokens.length - 1].range[0];
|
||||
}
|
||||
}
|
||||
|
||||
return comment;
|
||||
}
|
||||
|
||||
function attachComments(tree, providedComments, tokens) {
|
||||
// At first, we should calculate extended comment ranges.
|
||||
var comments = [], comment, len, i, cursor;
|
||||
|
||||
if (!tree.range) {
|
||||
throw new Error('attachComments needs range information');
|
||||
}
|
||||
|
||||
// tokens array is empty, we attach comments to tree as 'leadingComments'
|
||||
if (!tokens.length) {
|
||||
if (providedComments.length) {
|
||||
for (i = 0, len = providedComments.length; i < len; i += 1) {
|
||||
comment = deepCopy(providedComments[i]);
|
||||
comment.extendedRange = [0, tree.range[0]];
|
||||
comments.push(comment);
|
||||
}
|
||||
tree.leadingComments = comments;
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
|
||||
for (i = 0, len = providedComments.length; i < len; i += 1) {
|
||||
comments.push(extendCommentRange(deepCopy(providedComments[i]), tokens));
|
||||
}
|
||||
|
||||
// This is based on John Freeman's implementation.
|
||||
cursor = 0;
|
||||
traverse(tree, {
|
||||
enter: function (node) {
|
||||
var comment;
|
||||
|
||||
while (cursor < comments.length) {
|
||||
comment = comments[cursor];
|
||||
if (comment.extendedRange[1] > node.range[0]) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (comment.extendedRange[1] === node.range[0]) {
|
||||
if (!node.leadingComments) {
|
||||
node.leadingComments = [];
|
||||
}
|
||||
node.leadingComments.push(comment);
|
||||
comments.splice(cursor, 1);
|
||||
} else {
|
||||
cursor += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// already out of owned node
|
||||
if (cursor === comments.length) {
|
||||
return VisitorOption.Break;
|
||||
}
|
||||
|
||||
if (comments[cursor].extendedRange[0] > node.range[1]) {
|
||||
return VisitorOption.Skip;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
cursor = 0;
|
||||
traverse(tree, {
|
||||
leave: function (node) {
|
||||
var comment;
|
||||
|
||||
while (cursor < comments.length) {
|
||||
comment = comments[cursor];
|
||||
if (node.range[1] < comment.extendedRange[0]) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (node.range[1] === comment.extendedRange[0]) {
|
||||
if (!node.trailingComments) {
|
||||
node.trailingComments = [];
|
||||
}
|
||||
node.trailingComments.push(comment);
|
||||
comments.splice(cursor, 1);
|
||||
} else {
|
||||
cursor += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// already out of owned node
|
||||
if (cursor === comments.length) {
|
||||
return VisitorOption.Break;
|
||||
}
|
||||
|
||||
if (comments[cursor].extendedRange[0] > node.range[1]) {
|
||||
return VisitorOption.Skip;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
exports.version = '1.3.0';
|
||||
exports.Syntax = Syntax;
|
||||
exports.traverse = traverse;
|
||||
exports.replace = replace;
|
||||
exports.attachComments = attachComments;
|
||||
exports.VisitorKeys = VisitorKeys;
|
||||
exports.VisitorOption = VisitorOption;
|
||||
exports.Controller = Controller;
|
||||
}));
|
||||
/* vim: set sw=4 ts=4 et tw=80 : */
|
|
@ -0,0 +1,15 @@
|
|||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
|
||||
|
||||
JS_MODULES_PATH = 'modules/devtools/escodegen'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'escodegen.js',
|
||||
'estraverse.js',
|
||||
'package.json.js',
|
||||
]
|
|
@ -0,0 +1,57 @@
|
|||
module.exports = {
|
||||
"name": "escodegen",
|
||||
"description": "ECMAScript code generator",
|
||||
"homepage": "http://github.com/Constellation/escodegen.html",
|
||||
"main": "escodegen.js",
|
||||
"bin": {
|
||||
"esgenerate": "./bin/esgenerate.js",
|
||||
"escodegen": "./bin/escodegen.js"
|
||||
},
|
||||
"version": "0.0.26",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "Yusuke Suzuki",
|
||||
"email": "utatane.tea@gmail.com",
|
||||
"web": "http://github.com/Constellation"
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "http://github.com/Constellation/escodegen.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"esprima": "~1.0.2",
|
||||
"estraverse": "~1.3.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"source-map": ">= 0.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"esprima-moz": "*",
|
||||
"commonjs-everywhere": "~0.8.0",
|
||||
"q": "*",
|
||||
"bower": "*",
|
||||
"semver": "*",
|
||||
"chai": "~1.7.2",
|
||||
"grunt-contrib-jshint": "~0.5.0",
|
||||
"grunt-cli": "~0.1.9",
|
||||
"grunt": "~0.4.1",
|
||||
"grunt-mocha-test": "~0.6.2"
|
||||
},
|
||||
"licenses": [
|
||||
{
|
||||
"type": "BSD",
|
||||
"url": "http://github.com/Constellation/escodegen/raw/master/LICENSE.BSD"
|
||||
}
|
||||
],
|
||||
"scripts": {
|
||||
"test": "grunt travis",
|
||||
"unit-test": "grunt test",
|
||||
"lint": "grunt lint",
|
||||
"release": "node tools/release.js",
|
||||
"build": "./node_modules/.bin/cjsify -ma path: tools/entry-point.js > escodegen.browser.js"
|
||||
}
|
||||
};
|
|
@ -0,0 +1,40 @@
|
|||
"use strict";
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
const Cr = Components.results;
|
||||
|
||||
const { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
const { require } = devtools;
|
||||
|
||||
// Register a console listener, so console messages don't just disappear
|
||||
// into the ether.
|
||||
let errorCount = 0;
|
||||
let listener = {
|
||||
observe: function (aMessage) {
|
||||
errorCount++;
|
||||
try {
|
||||
// If we've been given an nsIScriptError, then we can print out
|
||||
// something nicely formatted, for tools like Emacs to pick up.
|
||||
var scriptError = aMessage.QueryInterface(Ci.nsIScriptError);
|
||||
dump(aMessage.sourceName + ":" + aMessage.lineNumber + ": " +
|
||||
scriptErrorFlagsToKind(aMessage.flags) + ": " +
|
||||
aMessage.errorMessage + "\n");
|
||||
var string = aMessage.errorMessage;
|
||||
} catch (x) {
|
||||
// Be a little paranoid with message, as the whole goal here is to lose
|
||||
// no information.
|
||||
try {
|
||||
var string = "" + aMessage.message;
|
||||
} catch (x) {
|
||||
var string = "<error converting error message to string>";
|
||||
}
|
||||
}
|
||||
|
||||
do_throw("head_dbg.js got console message: " + string + "\n");
|
||||
}
|
||||
};
|
||||
|
||||
let consoleService = Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService);
|
||||
consoleService.registerListener(listener);
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Test that we can generate source maps via escodegen.
|
||||
*/
|
||||
|
||||
Components.utils.import("resource://gre/modules/reflect.jsm");
|
||||
Components.utils.import("resource://gre/modules/devtools/SourceMap.jsm");
|
||||
const escodegen = require("escodegen/escodegen");
|
||||
|
||||
const testCode = "" + function main() {
|
||||
var a = 5 + 3;
|
||||
var b = 19 * 52;
|
||||
return a / b;
|
||||
};
|
||||
|
||||
function run_test() {
|
||||
const ast = Reflect.parse(testCode);
|
||||
const { code, map } = escodegen.generate(ast, {
|
||||
format: {
|
||||
indent: {
|
||||
// Single space indents so we are mapping different locations.
|
||||
style: " "
|
||||
}
|
||||
},
|
||||
sourceMap: "testCode.js",
|
||||
sourceMapWithCode: true
|
||||
});
|
||||
const smc = new SourceMapConsumer(map.toString());
|
||||
|
||||
let mapping = smc.originalPositionFor({
|
||||
line: 2,
|
||||
column: 1
|
||||
});
|
||||
do_check_eq(mapping.source, "testCode.js");
|
||||
do_check_eq(mapping.line, 2);
|
||||
do_check_eq(mapping.column, 2);
|
||||
|
||||
mapping = smc.originalPositionFor({
|
||||
line: 2,
|
||||
column: 5
|
||||
});
|
||||
do_check_eq(mapping.source, "testCode.js");
|
||||
do_check_eq(mapping.line, 2);
|
||||
do_check_eq(mapping.column, 6);
|
||||
|
||||
mapping = smc.originalPositionFor({
|
||||
line: 3,
|
||||
column: 1
|
||||
});
|
||||
do_check_eq(mapping.source, "testCode.js");
|
||||
do_check_eq(mapping.line, 3);
|
||||
do_check_eq(mapping.column, 2);
|
||||
|
||||
mapping = smc.originalPositionFor({
|
||||
line: 3,
|
||||
column: 5
|
||||
});
|
||||
do_check_eq(mapping.source, "testCode.js");
|
||||
do_check_eq(mapping.line, 3);
|
||||
do_check_eq(mapping.column, 6);
|
||||
|
||||
mapping = smc.originalPositionFor({
|
||||
line: 4,
|
||||
column: 1
|
||||
});
|
||||
do_check_eq(mapping.source, "testCode.js");
|
||||
do_check_eq(mapping.line, 4);
|
||||
do_check_eq(mapping.column, 2);
|
||||
};
|
|
@ -0,0 +1,11 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Test that we can require escodegen.
|
||||
*/
|
||||
|
||||
function run_test() {
|
||||
const escodegen = require("escodegen/escodegen");
|
||||
do_check_eq(typeof escodegen.generate, "function");
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Test that we can go AST -> JS -> AST via escodegen and Reflect.
|
||||
*/
|
||||
|
||||
const escodegen = require("escodegen/escodegen");
|
||||
Components.utils.import("resource://gre/modules/reflect.jsm");
|
||||
|
||||
const testCode = "" + function main () {
|
||||
function makeAcc(n) {
|
||||
return function () {
|
||||
return ++n;
|
||||
};
|
||||
}
|
||||
|
||||
var acc = makeAcc(10);
|
||||
|
||||
for (var i = 0; i < 10; i++) {
|
||||
acc();
|
||||
}
|
||||
|
||||
console.log(acc());
|
||||
};
|
||||
|
||||
function run_test() {
|
||||
const originalAST = Reflect.parse(testCode);
|
||||
const generatedCode = escodegen.generate(originalAST);
|
||||
const generatedAST = Reflect.parse(generatedCode);
|
||||
|
||||
do_print("Original AST:");
|
||||
do_print(JSON.stringify(originalAST, null, 2));
|
||||
do_print("Generated AST:");
|
||||
do_print(JSON.stringify(generatedAST, null, 2));
|
||||
|
||||
checkEquivalentASTs(originalAST, generatedAST);
|
||||
}
|
||||
|
||||
const isObject = (obj) => typeof obj === "object" && obj !== null;
|
||||
const zip = (a, b) => {
|
||||
let pairs = [];
|
||||
for (let i = 0; i < a.length && i < b.length; i++) {
|
||||
pairs.push([a[i], b[i]]);
|
||||
}
|
||||
return pairs;
|
||||
};
|
||||
const isntLoc = k => k !== "loc";
|
||||
|
||||
function checkEquivalentASTs(expected, actual, prop = []) {
|
||||
do_print("Checking: " + prop.join(" "));
|
||||
|
||||
if (!isObject(expected)) {
|
||||
return void do_check_eq(expected, actual);
|
||||
}
|
||||
|
||||
do_check_true(isObject(actual));
|
||||
|
||||
if (Array.isArray(expected)) {
|
||||
do_check_true(Array.isArray(actual));
|
||||
do_check_eq(expected.length, actual.length);
|
||||
let i = 0;
|
||||
for (let [e, a] of zip(expected, actual)) {
|
||||
checkEquivalentASTs(a, e, prop.concat([i++]));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const expectedKeys = Object.keys(expected).filter(isntLoc).sort();
|
||||
const actualKeys = Object.keys(actual).filter(isntLoc).sort();
|
||||
do_check_eq(expectedKeys.length, actualKeys.length);
|
||||
for (let [ek, ak] of zip(expectedKeys, actualKeys)) {
|
||||
do_check_eq(ek, ak);
|
||||
checkEquivalentASTs(expected[ek], actual[ak], prop.concat([ek]));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
[DEFAULT]
|
||||
head = head_escodegen.js
|
||||
tail =
|
||||
|
||||
[test_import_escodegen.js]
|
||||
[test_same_ast.js]
|
||||
[test_generate_source_maps.js]
|
|
@ -13,5 +13,6 @@ PARALLEL_DIRS += [
|
|||
'sourcemap',
|
||||
'webconsole',
|
||||
'apps',
|
||||
'styleinspector'
|
||||
'styleinspector',
|
||||
'escodegen'
|
||||
]
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
head = head_devtools.js
|
||||
tail =
|
||||
|
||||
[test_safeErrorString.js]
|
||||
[test_safeErrorString.js]
|
||||
|
|
Загрузка…
Ссылка в новой задаче