Merge branch 'master' into harmony-v2.8.15

This commit is contained in:
alexlamsl
2017-03-23 15:11:16 +08:00
14 changed files with 248 additions and 130 deletions

View File

@@ -5,7 +5,6 @@ node_js:
- "0.12" - "0.12"
- "4" - "4"
- "6" - "6"
- "7"
env: env:
- UGLIFYJS_TEST_ALL=1 - UGLIFYJS_TEST_ALL=1
matrix: matrix:

View File

@@ -10,8 +10,10 @@ There's also an
[in-browser online demo](http://lisperator.net/uglifyjs/#demo) (for Firefox, [in-browser online demo](http://lisperator.net/uglifyjs/#demo) (for Firefox,
Chrome and probably Safari). Chrome and probably Safari).
Note: release versions of `uglify-js` only support ECMAScript 5 (ES5). If you wish to minify #### Note:
- release versions of `uglify-js` only support ECMAScript 5 (ES5). If you wish to minify
ES2015+ (ES6+) code then please use the [harmony](#harmony) development branch. ES2015+ (ES6+) code then please use the [harmony](#harmony) development branch.
- Node 7 has a known performance regression and runs `uglify-js` twice as slow.
Install Install
------- -------

View File

@@ -132,6 +132,11 @@ merge(Compressor.prototype, {
} }
return node; return node;
}, },
info: function() {
if (this.options.warnings == "verbose") {
AST_Node.warn.apply(AST_Node, arguments);
}
},
warn: function(text, props) { warn: function(text, props) {
if (this.options.warnings) { if (this.options.warnings) {
// only emit unique warnings // only emit unique warnings
@@ -629,12 +634,24 @@ merge(Compressor.prototype, {
|| node instanceof AST_IterationStatement || node instanceof AST_IterationStatement
|| (parent instanceof AST_If && node !== parent.condition) || (parent instanceof AST_If && node !== parent.condition)
|| (parent instanceof AST_Conditional && node !== parent.condition) || (parent instanceof AST_Conditional && node !== parent.condition)
|| (node instanceof AST_SymbolRef
&& !are_references_in_scope(node.definition(), self))
|| (parent instanceof AST_Binary || (parent instanceof AST_Binary
&& (parent.operator == "&&" || parent.operator == "||") && (parent.operator == "&&" || parent.operator == "||")
&& node === parent.right) && node === parent.right)
|| (parent instanceof AST_Switch && node !== parent.expression)) { || (parent instanceof AST_Switch && node !== parent.expression)) {
return side_effects_encountered = unwind = true, node; return side_effects_encountered = unwind = true, node;
} }
function are_references_in_scope(def, scope) {
if (def.orig.length === 1
&& def.orig[0] instanceof AST_SymbolDefun) return true;
if (def.scope.get_defun_scope() !== scope) return false;
var refs = def.references;
for (var i = 0, len = refs.length; i < len; i++) {
if (refs[i].scope.get_defun_scope() !== scope) return false;
}
return true;
}
}, },
function postorder(node) { function postorder(node) {
if (unwind) return node; if (unwind) return node;
@@ -679,7 +696,7 @@ merge(Compressor.prototype, {
// Further optimize statement after substitution. // Further optimize statement after substitution.
stat.reset_opt_flags(compressor); stat.reset_opt_flags(compressor);
compressor.warn("Collapsing " + (is_constant ? "constant" : "variable") + compressor.info("Collapsing " + (is_constant ? "constant" : "variable") +
" " + var_name + " [{file}:{line},{col}]", node.start); " " + var_name + " [{file}:{line},{col}]", node.start);
CHANGED = true; CHANGED = true;
return value; return value;
@@ -1933,7 +1950,7 @@ merge(Compressor.prototype, {
sym.__unused = true; sym.__unused = true;
if (trim) { if (trim) {
a.pop(); a.pop();
compressor.warn("Dropping unused function argument {name} [{file}:{line},{col}]", { compressor[sym.unreferenced() ? "warn" : "info"]("Dropping unused function argument {name} [{file}:{line},{col}]", {
name : sym.name, name : sym.name,
file : sym.start.file, file : sym.start.file,
line : sym.start.line, line : sym.start.line,
@@ -1949,7 +1966,7 @@ merge(Compressor.prototype, {
if ((node instanceof AST_Defun || node instanceof AST_DefClass) && node !== self) { if ((node instanceof AST_Defun || node instanceof AST_DefClass) && node !== self) {
var keep = (node.name.definition().id in in_use_ids) || !drop_funcs && node.name.definition().global; var keep = (node.name.definition().id in in_use_ids) || !drop_funcs && node.name.definition().global;
if (!keep) { if (!keep) {
compressor.warn("Dropping unused function {name} [{file}:{line},{col}]", { compressor[node.name.unreferenced() ? "warn" : "info"]("Dropping unused function {name} [{file}:{line},{col}]", {
name : node.name.name, name : node.name.name,
file : node.name.start.file, file : node.name.start.file,
line : node.name.start.line, line : node.name.start.line,
@@ -1976,7 +1993,7 @@ merge(Compressor.prototype, {
compressor.warn("Side effects in initialization of unused variable {name} [{file}:{line},{col}]", w); compressor.warn("Side effects in initialization of unused variable {name} [{file}:{line},{col}]", w);
return true; return true;
} }
compressor.warn("Dropping unused variable {name} [{file}:{line},{col}]", w); compressor[def.name.unreferenced() ? "warn" : "info"]("Dropping unused variable {name} [{file}:{line},{col}]", w);
return false; return false;
}); });
// place uninitialized names at the start // place uninitialized names at the start

View File

@@ -2467,12 +2467,52 @@ function parse($TEXT, options) {
}; };
function is_assignable(expr) { function is_assignable(expr) {
if (!options.strict) return true; return expr instanceof AST_PropAccess || expr instanceof AST_SymbolRef;
if (expr instanceof AST_This) return false;
if (expr instanceof AST_Super) return false;
return (expr instanceof AST_PropAccess || expr instanceof AST_Symbol);
}; };
function to_destructuring(node) {
if (node instanceof AST_Object) {
node = new AST_Destructuring({
start: node.start,
names: node.properties.map(to_destructuring),
is_array: false,
end: node.end
});
} else if (node instanceof AST_Array) {
var names = [];
for (var i = 0; i < node.elements.length; i++) {
// Only allow expansion as last element
if (node.elements[i] instanceof AST_Expansion) {
if (i + 1 !== node.elements.length) {
token_error(node.elements[i].start, "Spread must the be last element in destructuring array");
}
node.elements[i].expression = to_destructuring(node.elements[i].expression);
}
names.push(to_destructuring(node.elements[i]));
}
node = new AST_Destructuring({
start: node.start,
names: names,
is_array: true,
end: node.end
});
} else if (node instanceof AST_ObjectProperty) {
node.value = to_destructuring(node.value);
} else if (node instanceof AST_Assign) {
node = new AST_DefaultAssign({
start: node.start,
left: node.left,
operator: "=",
right: node.right,
end: node.end
});
}
return node;
}
// In ES6, AssignmentExpression can also be an ArrowFunction // In ES6, AssignmentExpression can also be an ArrowFunction
var maybe_assign = function(no_in) { var maybe_assign = function(no_in) {
var start = S.token; var start = S.token;
@@ -2506,56 +2546,7 @@ function parse($TEXT, options) {
var val = S.token.value; var val = S.token.value;
if (is("operator") && ASSIGNMENT(val)) { if (is("operator") && ASSIGNMENT(val)) {
if (is_assignable(left)) { if (is_assignable(left) || (left = to_destructuring(left)) instanceof AST_Destructuring) {
var walk = function(node) {
var newNode;
if (node instanceof AST_Object) {
newNode = new AST_Destructuring({
start: node.start,
names: node.properties.map(walk),
is_array: false,
end: node.end
});
node = newNode;
} else if (node instanceof AST_Array) {
var names = [];
for (var i = 0; i < node.elements.length; i++) {
// Only allow expansion as last element
if (node.elements[i] instanceof AST_Expansion) {
if (i + 1 !== node.elements.length) {
token_error(node.elements[i].start, "Spread must the be last element in destructuring array");
}
node.elements[i].expression = walk(node.elements[i].expression);
}
names.push(walk(node.elements[i]));
}
newNode = new AST_Destructuring({
start: node.start,
names: names,
is_array: true,
end: node.end
});
node = newNode;
} else if (node instanceof AST_ObjectProperty) {
node.value = walk(node.value);
} else if (node instanceof AST_Assign) {
node = new AST_DefaultAssign({
start: node.start,
left: node.left,
operator: "=",
right: node.right,
end: node.end
});
}
return node;
}
left = walk(left);
next(); next();
return new AST_Assign({ return new AST_Assign({
start : start, start : start,

View File

@@ -4,7 +4,7 @@
"homepage": "http://lisperator.net/uglifyjs", "homepage": "http://lisperator.net/uglifyjs",
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)", "author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
"license": "BSD-2-Clause", "license": "BSD-2-Clause",
"version": "2.8.14", "version": "2.8.15",
"engines": { "engines": {
"node": ">=0.8.0" "node": ">=0.8.0"
}, },
@@ -30,7 +30,6 @@
], ],
"dependencies": { "dependencies": {
"source-map": "~0.5.1", "source-map": "~0.5.1",
"uglify-to-browserify": "~1.0.0",
"yargs": "~3.10.0" "yargs": "~3.10.0"
}, },
"devDependencies": { "devDependencies": {
@@ -40,13 +39,15 @@
"estraverse": "~1.5.1", "estraverse": "~1.5.1",
"mocha": "~2.3.4" "mocha": "~2.3.4"
}, },
"optionalDependencies": {
"uglify-to-browserify": "~1.0.0"
},
"browserify": { "browserify": {
"transform": [ "transform": [
"uglify-to-browserify" "uglify-to-browserify"
] ]
}, },
"scripts": { "scripts": {
"shrinkwrap": "rm ./npm-shrinkwrap.json; rm -rf ./node_modules; npm i && npm shrinkwrap && npm outdated",
"test": "node test/run-tests.js" "test": "node test/run-tests.js"
}, },
"keywords": ["uglify", "uglify-js", "minify", "minifier"] "keywords": ["uglify", "uglify-js", "minify", "minifier"]

View File

@@ -1514,3 +1514,110 @@ issue_1605_2: {
(new Object).p = 1; (new Object).p = 1;
} }
} }
issue_1631_1: {
options = {
cascade: true,
collapse_vars: true,
hoist_funs: true,
join_vars: true,
sequences: true,
side_effects: true,
}
input: {
var pc = 0;
function f(x) {
pc = 200;
return 100;
}
function x() {
var t = f();
pc += t;
return pc;
}
console.log(x());
}
expect: {
function f(x) {
return pc = 200, 100;
}
function x() {
var t = f();
return pc += t;
}
var pc = 0;
console.log(x());
}
expect_stdout: "300"
}
issue_1631_2: {
options = {
cascade: true,
collapse_vars: true,
hoist_funs: true,
join_vars: true,
sequences: true,
side_effects: true,
}
input: {
var a = 0, b = 1;
function f() {
a = 2;
return 4;
}
function g() {
var t = f();
b = a + t;
return b;
}
console.log(g());
}
expect: {
function f() {
return a = 2, 4;
}
function g() {
var t = f();
return b = a + t;
}
var a = 0, b = 1;
console.log(g());
}
expect_stdout: "6"
}
issue_1631_3: {
options = {
cascade: true,
collapse_vars: true,
hoist_funs: true,
join_vars: true,
sequences: true,
side_effects: true,
}
input: {
function g() {
var a = 0, b = 1;
function f() {
a = 2;
return 4;
}
var t = f();
b = a + t;
return b;
}
console.log(g());
}
expect: {
function g() {
function f() {
return a = 2, 4;
}
var a = 0, b = 1, t = f();
return b = a + t;
}
console.log(g());
}
expect_stdout: "6"
}

View File

@@ -47,22 +47,6 @@ html_comment_in_greater_than_or_equal: {
expect_exact: "function f(a,b){return a-- >=b}"; expect_exact: "function f(a,b){return a-- >=b}";
} }
html_comment_in_right_shift_assign: {
input: {
// Note: illegal javascript
function f(a, b) { return a-- >>= b; }
}
expect_exact: "function f(a,b){return a-- >>=b}";
}
html_comment_in_zero_fill_right_shift_assign: {
input: {
// Note: illegal javascript
function f(a, b) { return a-- >>>= b; }
}
expect_exact: "function f(a,b){return a-- >>>=b}";
}
html_comment_in_string_literal: { html_comment_in_string_literal: {
input: { input: {
function f() { return "<!--HTML-->comment in<!--string literal-->"; } function f() { return "<!--HTML-->comment in<!--string literal-->"; }

View File

@@ -39,7 +39,7 @@ non_hoisted_function_after_return_2a: {
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true, hoist_funs: false, dead_code: true, conditionals: true, comparisons: true,
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true, evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true,
if_return: true, join_vars: true, cascade: true, side_effects: true, if_return: true, join_vars: true, cascade: true, side_effects: true,
collapse_vars: false, passes: 2 collapse_vars: false, passes: 2, warnings: "verbose"
} }
input: { input: {
function foo(x) { function foo(x) {
@@ -75,7 +75,7 @@ non_hoisted_function_after_return_2a: {
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:53,12]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:53,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:56,12]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:56,12]",
"WARN: Dropping unused variable b [test/compress/issue-1034.js:51,20]", "WARN: Dropping unused variable b [test/compress/issue-1034.js:51,20]",
"WARN: Dropping unused variable c [test/compress/issue-1034.js:53,16]" "WARN: Dropping unused variable c [test/compress/issue-1034.js:53,16]",
] ]
} }
@@ -114,8 +114,5 @@ non_hoisted_function_after_return_2b: {
"WARN: Dropping unreachable code [test/compress/issue-1034.js:97,12]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:97,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:97,12]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:97,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:101,12]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:101,12]",
"WARN: Dropping unused variable b [test/compress/issue-1034.js:95,20]",
"WARN: Dropping unused variable c [test/compress/issue-1034.js:97,16]"
] ]
} }

View File

@@ -0,0 +1 @@
console.log(x);

View File

@@ -1,10 +1,11 @@
var Uglify = require('../../'); var Uglify = require('../../');
var assert = require("assert"); var assert = require("assert");
var path = require("path");
describe("minify() with input file globs", function() { describe("minify() with input file globs", function() {
it("minify() with one input file glob string.", function() { it("minify() with one input file glob string.", function() {
var result = Uglify.minify("test/input/issue-1242/foo.*"); var result = Uglify.minify("test/input/issue-1242/foo.*");
assert.strictEqual(result.code, 'function foo(o){print("Foo:",2*o)}var print=console.log.bind(console);'); assert.strictEqual(result.code, 'function foo(o){var n=2*o;print("Foo:",n)}var print=console.log.bind(console);');
}); });
it("minify() with an array of one input file glob.", function() { it("minify() with an array of one input file glob.", function() {
var result = Uglify.minify([ var result = Uglify.minify([
@@ -19,6 +20,39 @@ describe("minify() with input file globs", function() {
], { ], {
compress: { toplevel: true } compress: { toplevel: true }
}); });
assert.strictEqual(result.code, 'var print=console.log.bind(console);print("qux",function(n){return 3*n}(3),function(n){return n/2}(12)),function(n){print("Foo:",2*n)}(11);'); assert.strictEqual(result.code, 'var print=console.log.bind(console),a=function(n){return 3*n}(3),b=function(n){return n/2}(12);print("qux",a,b),function(n){var o=2*n;print("Foo:",o)}(11);');
});
it("should throw with non-matching glob string", function() {
var glob = "test/input/issue-1242/blah.*";
assert.strictEqual(Uglify.simple_glob(glob).length, 1);
assert.strictEqual(Uglify.simple_glob(glob)[0], glob);
assert.throws(function() {
Uglify.minify(glob);
}, "should throw file not found");
});
it('"?" in glob string should not match "/"', function() {
var glob = "test/input?issue-1242/foo.*";
assert.strictEqual(Uglify.simple_glob(glob).length, 1);
assert.strictEqual(Uglify.simple_glob(glob)[0], glob);
assert.throws(function() {
Uglify.minify(glob);
}, "should throw file not found");
});
it("should handle special characters in glob string", function() {
var result = Uglify.minify("test/input/issue-1632/^{*}[???](*)+$.??");
assert.strictEqual(result.code, "console.log(x);");
});
it("should handle array of glob strings - matching and otherwise", function() {
var dir = "test/input/issue-1242";
var matches = Uglify.simple_glob([
path.join(dir, "b*.es5"),
path.join(dir, "z*.es5"),
path.join(dir, "*.js"),
]);
assert.strictEqual(matches.length, 4);
assert.strictEqual(matches[0], path.join(dir, "bar.es5"));
assert.strictEqual(matches[1], path.join(dir, "baz.es5"));
assert.strictEqual(matches[2], path.join(dir, "z*.es5"));
assert.strictEqual(matches[3], path.join(dir, "qux.js"));
}); });
}); });

View File

@@ -5,7 +5,7 @@ var UglifyJS = require(".."),
escodegen = require("escodegen"), escodegen = require("escodegen"),
esfuzz = require("esfuzz"), esfuzz = require("esfuzz"),
estraverse = require("estraverse"), estraverse = require("estraverse"),
prefix = Array(20).join("\b") + " "; prefix = "\r ";
// Normalizes input AST for UglifyJS in order to get correct comparison. // Normalizes input AST for UglifyJS in order to get correct comparison.
@@ -62,7 +62,7 @@ module.exports = function(options) {
var ast1 = normalizeInput(esfuzz.generate({ var ast1 = normalizeInput(esfuzz.generate({
maxDepth: options.maxDepth maxDepth: options.maxDepth
})); }));
var ast2 = var ast2 =
UglifyJS UglifyJS
.AST_Node .AST_Node

View File

@@ -114,7 +114,7 @@ function run_compress_tests() {
U.AST_Node.warn_function = function(text) { U.AST_Node.warn_function = function(text) {
warnings_emitted.push("WARN: " + text); warnings_emitted.push("WARN: " + text);
}; };
options.warnings = true; if (!options.warnings) options.warnings = true;
} }
var cmp = new U.Compressor(options, true); var cmp = new U.Compressor(options, true);
var output_options = test.beautify || {}; var output_options = test.beautify || {};

View File

@@ -18,6 +18,6 @@ exports["tokenizer"] = tokenizer;
exports["is_identifier"] = is_identifier; exports["is_identifier"] = is_identifier;
exports["SymbolDef"] = SymbolDef; exports["SymbolDef"] = SymbolDef;
if (typeof DEBUG !== "undefined" && DEBUG) { if (global.UGLIFY_DEBUG) {
exports["EXPECT_DIRECTIVE"] = EXPECT_DIRECTIVE; exports["EXPECT_DIRECTIVE"] = EXPECT_DIRECTIVE;
} }

View File

@@ -7,7 +7,8 @@
var path = require("path"); var path = require("path");
var fs = require("fs"); var fs = require("fs");
var FILES = exports.FILES = [ var UglifyJS = exports;
var FILES = UglifyJS.FILES = [
"../lib/utils.js", "../lib/utils.js",
"../lib/ast.js", "../lib/ast.js",
"../lib/parse.js", "../lib/parse.js",
@@ -20,17 +21,14 @@ var FILES = exports.FILES = [
"../lib/propmangle.js", "../lib/propmangle.js",
"./exports.js", "./exports.js",
].map(function(file){ ].map(function(file){
return fs.realpathSync(path.join(path.dirname(__filename), file)); return require.resolve(file);
}); });
var UglifyJS = exports; new Function("MOZ_SourceMap", "exports", FILES.map(function(file){
new Function("MOZ_SourceMap", "exports", "DEBUG", FILES.map(function(file){
return fs.readFileSync(file, "utf8"); return fs.readFileSync(file, "utf8");
}).join("\n\n"))( }).join("\n\n"))(
require("source-map"), require("source-map"),
UglifyJS, UglifyJS
!!global.UGLIFY_DEBUG
); );
UglifyJS.AST_Node.warn_function = function(txt) { UglifyJS.AST_Node.warn_function = function(txt) {
@@ -46,7 +44,7 @@ function read_source_map(code) {
return JSON.parse(new Buffer(match[2], "base64")); return JSON.parse(new Buffer(match[2], "base64"));
} }
exports.minify = function(files, options) { UglifyJS.minify = function(files, options) {
options = UglifyJS.defaults(options, { options = UglifyJS.defaults(options, {
spidermonkey : false, spidermonkey : false,
outSourceMap : null, outSourceMap : null,
@@ -181,7 +179,7 @@ exports.minify = function(files, options) {
}; };
}; };
// exports.describe_ast = function() { // UglifyJS.describe_ast = function() {
// function doitem(ctor) { // function doitem(ctor) {
// var sub = {}; // var sub = {};
// ctor.SUBCLASSES.forEach(function(ctor){ // ctor.SUBCLASSES.forEach(function(ctor){
@@ -195,7 +193,7 @@ exports.minify = function(files, options) {
// return doitem(UglifyJS.AST_Node).sub; // return doitem(UglifyJS.AST_Node).sub;
// } // }
exports.describe_ast = function() { UglifyJS.describe_ast = function() {
var out = UglifyJS.OutputStream({ beautify: true }); var out = UglifyJS.OutputStream({ beautify: true });
function doitem(ctor) { function doitem(ctor) {
out.print("AST_" + ctor.TYPE); out.print("AST_" + ctor.TYPE);
@@ -249,13 +247,13 @@ function readReservedFile(filename, reserved) {
return reserved; return reserved;
} }
exports.readReservedFile = readReservedFile; UglifyJS.readReservedFile = readReservedFile;
exports.readDefaultReservedFile = function(reserved) { UglifyJS.readDefaultReservedFile = function(reserved) {
return readReservedFile(path.join(__dirname, "domprops.json"), reserved); return readReservedFile(require.resolve("./domprops.json"), reserved);
}; };
exports.readNameCache = function(filename, key) { UglifyJS.readNameCache = function(filename, key) {
var cache = null; var cache = null;
if (filename) { if (filename) {
try { try {
@@ -273,7 +271,7 @@ exports.readNameCache = function(filename, key) {
return cache; return cache;
}; };
exports.writeNameCache = function(filename, key, cache) { UglifyJS.writeNameCache = function(filename, key, cache) {
if (filename) { if (filename) {
var data; var data;
try { try {
@@ -294,13 +292,9 @@ exports.writeNameCache = function(filename, key, cache) {
// Example: "foo/bar/*baz??.*.js" // Example: "foo/bar/*baz??.*.js"
// Argument `glob` may be a string or an array of strings. // Argument `glob` may be a string or an array of strings.
// Returns an array of strings. Garbage in, garbage out. // Returns an array of strings. Garbage in, garbage out.
exports.simple_glob = function simple_glob(glob) { UglifyJS.simple_glob = function simple_glob(glob) {
var results = [];
if (Array.isArray(glob)) { if (Array.isArray(glob)) {
glob.forEach(function(elem) { return [].concat.apply([], glob.map(simple_glob));
results = results.concat(simple_glob(elem));
});
return results;
} }
if (glob.match(/\*|\?/)) { if (glob.match(/\*|\?/)) {
var dir = path.dirname(glob); var dir = path.dirname(glob);
@@ -308,28 +302,19 @@ exports.simple_glob = function simple_glob(glob) {
var entries = fs.readdirSync(dir); var entries = fs.readdirSync(dir);
} catch (ex) {} } catch (ex) {}
if (entries) { if (entries) {
var pattern = "^" + (path.basename(glob) var pattern = "^" + path.basename(glob)
.replace(/\(/g, "\\(") .replace(/[.+^$[\]\\(){}]/g, "\\$&")
.replace(/\)/g, "\\)")
.replace(/\{/g, "\\{")
.replace(/\}/g, "\\}")
.replace(/\[/g, "\\[")
.replace(/\]/g, "\\]")
.replace(/\+/g, "\\+")
.replace(/\^/g, "\\^")
.replace(/\$/g, "\\$")
.replace(/\*/g, "[^/\\\\]*") .replace(/\*/g, "[^/\\\\]*")
.replace(/\./g, "\\.") .replace(/\?/g, "[^/\\\\]") + "$";
.replace(/\?/g, ".")) + "$";
var mod = process.platform === "win32" ? "i" : ""; var mod = process.platform === "win32" ? "i" : "";
var rx = new RegExp(pattern, mod); var rx = new RegExp(pattern, mod);
for (var i in entries) { var results = entries.filter(function(name) {
if (rx.test(entries[i])) return rx.test(name);
results.push(dir + "/" + entries[i]); }).map(function(name) {
} return path.join(dir, name);
});
if (results.length) return results;
} }
} }
if (results.length === 0) return [ glob ];
results = [ glob ];
return results;
}; };