Skip to content

Commit 628cf3a

Browse files
Fix: don't mutate user-provided configs (fixes #329) (#330)
1 parent d5d1808 commit 628cf3a

File tree

3 files changed

+31
-3
lines changed

3 files changed

+31
-3
lines changed

espree.js

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,26 @@ var lookahead,
7171
extra,
7272
lastToken;
7373

74+
/**
75+
* Object.assign polyfill for Node < 4
76+
* @param {Object} target The target object
77+
* @param {...Object} sources Sources for the object
78+
* @returns {Object} `target` after being mutated
79+
*/
80+
var assign = Object.assign || function assign(target) {
81+
for (var argIndex = 1; argIndex < arguments.length; argIndex++) {
82+
if (arguments[argIndex] !== null && typeof arguments[argIndex] === "object") {
83+
var keys = Object.keys(arguments[argIndex]);
84+
85+
for (var keyIndex = 0; keyIndex < keys.length; keyIndex++) {
86+
target[keys[keyIndex]] = arguments[argIndex][keys[keyIndex]];
87+
}
88+
}
89+
}
90+
91+
return target;
92+
};
93+
7494
/**
7595
* Resets the extra object to its default.
7696
* @returns {void}
@@ -515,7 +535,7 @@ function tokenize(code, options) {
515535
lookahead = null;
516536

517537
// Options matching.
518-
options = options || {};
538+
options = assign({}, options);
519539

520540
var acornOptions = {
521541
ecmaVersion: DEFAULT_ECMA_VERSION,
@@ -551,7 +571,7 @@ function tokenize(code, options) {
551571

552572
// apply parsing flags
553573
if (options.ecmaFeatures && typeof options.ecmaFeatures === "object") {
554-
extra.ecmaFeatures = options.ecmaFeatures;
574+
extra.ecmaFeatures = assign({}, options.ecmaFeatures);
555575
impliedStrict = extra.ecmaFeatures.impliedStrict;
556576
extra.ecmaFeatures.impliedStrict = typeof impliedStrict === "boolean" && impliedStrict;
557577
}
@@ -687,7 +707,7 @@ function parse(code, options) {
687707

688708
// apply parsing flags after sourceType to allow overriding
689709
if (options.ecmaFeatures && typeof options.ecmaFeatures === "object") {
690-
extra.ecmaFeatures = options.ecmaFeatures;
710+
extra.ecmaFeatures = assign({}, options.ecmaFeatures);
691711
impliedStrict = extra.ecmaFeatures.impliedStrict;
692712
extra.ecmaFeatures.impliedStrict = typeof impliedStrict === "boolean" && impliedStrict;
693713
if (options.ecmaFeatures.globalReturn) {

tests/lib/parse.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,5 +77,9 @@ describe("parse()", function() {
7777
assert.deepEqual([ast.loc.end.line, ast.loc.end.column], [1, 5]);
7878
});
7979

80+
it("should not mutate config", function() {
81+
espree.parse("foo", Object.freeze({ ecmaFeatures: Object.freeze({}) }));
82+
});
83+
8084
});
8185
});

tests/lib/tokenize.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,4 +182,8 @@ describe("tokenize()", function() {
182182
);
183183
});
184184

185+
it("should not mutate config", function() {
186+
espree.tokenize("foo", Object.freeze({ ecmaFeatures: Object.freeze({}) }));
187+
});
188+
185189
});

0 commit comments

Comments
 (0)