Comparing version 2.1.1 to 3.0.0
@@ -0,1 +1,51 @@ | ||
## [3.0.0](https://github.com/estools/espurify/releases/tag/v3.0.0) (2022-07-17) | ||
#### Features | ||
* [Provide ecmaVersion option to make cloned AST conform to each annual estree spec](https://github.com/estools/espurify/pull/26) | ||
* set default ecmaVersion to 2022 | ||
* [Introduce `espurify.purifyAst` as an alias of default function](https://github.com/estools/espurify/pull/28/files) | ||
* [Rename all WhiteList to AllowList in favor of more inclusive language](https://github.com/estools/espurify/pull/27) | ||
* [Support ES2022 grammar](https://github.com/estools/espurify/commit/f80cfb6f2cc0a44ea4d971312bb52ce449b4c070) | ||
* support PropertyDefinition | ||
* support PrivateIdentifier | ||
* support StaticBlock | ||
* [Support ES2020 grammar](https://github.com/estools/espurify/pull/21) | ||
* support ChainExpression | ||
* support ImportExpression | ||
* support exported property of ExportAllDeclaration | ||
* support BigInt literals | ||
#### Breaking Changes | ||
This release will not affect most users immediately. There are three notable changes. | ||
1. `espurify` function is still exported as default but deprecated in favor of named exports aiming ESM era, and will be removed in future major releases. Please use `espurify.purifyAst` instead. | ||
2. `espurify.cloneWithWhitelist` is still exported but deprecated in favor of more inclusive language and will be removed in future major releases. Please use `espurify.cloneWithAllowlist` instead. | ||
3. Some new properties will appear in purified AST and may affect deep-equality of the tree, since default ecmaVersion is changed from 2018 to 2022 which add some properties to existing Nodes. | ||
```diff | ||
- CallExpression: ['type', 'callee', 'arguments'], | ||
+ CallExpression: ['type', 'callee', 'arguments', 'optional'], | ||
- ExportAllDeclaration: ['type', 'source'], | ||
+ ExportAllDeclaration: ['type', 'source', 'exported'], | ||
- Literal: ['type', 'value', 'regex'], | ||
+ Literal: ['type', 'value', 'regex', 'bigint'], | ||
``` | ||
To make espurify's behavior same as v2, please use `espurify.customize` function with `ecmaVersion: 2018` option. | ||
``` | ||
const purify = espurify.customize({ ecmaVersion: 2018 }); | ||
const clonedAst = purify(originalAst); | ||
``` | ||
### [2.1.1](https://github.com/estools/espurify/releases/tag/v2.1.1) (2021-03-29) | ||
@@ -2,0 +52,0 @@ |
20
index.js
@@ -6,3 +6,3 @@ /** | ||
* | ||
* Copyright (c) 2014-2019 Takuto Wada | ||
* Copyright (c) 2014-2022 Takuto Wada | ||
* Licensed under the MIT license. | ||
@@ -13,12 +13,20 @@ * https://github.com/estools/espurify/blob/master/MIT-LICENSE.txt | ||
var createWhitelist = require('./lib/create-whitelist'); | ||
var cloneWithWhitelist = require('./lib/clone-ast'); | ||
const createAllowlist = require('./lib/create-allowlist'); | ||
const cloneWithAllowlist = require('./lib/clone-ast'); | ||
function createCloneFunction (options) { | ||
return cloneWithWhitelist(createWhitelist(options)); | ||
return cloneWithAllowlist(createAllowlist(options)); | ||
} | ||
var espurify = createCloneFunction(); | ||
/** | ||
* @deprecated since version 3.0.0. Use `espurify.purifyAst` instead. | ||
*/ | ||
const espurify = createCloneFunction(); | ||
espurify.purifyAst = createCloneFunction(); | ||
espurify.customize = createCloneFunction; | ||
espurify.cloneWithWhitelist = cloneWithWhitelist; | ||
espurify.cloneWithAllowlist = cloneWithAllowlist; | ||
/** | ||
* @deprecated since version 3.0.0. Use `espurify.cloneWithAllowlist` instead. | ||
*/ | ||
espurify.cloneWithWhitelist = cloneWithAllowlist; | ||
module.exports = espurify; |
'use strict'; | ||
module.exports = function cloneWithWhitelist (astWhiteList) { | ||
var whitelist = Object.keys(astWhiteList).reduce(function (props, key) { | ||
var propNames = astWhiteList[key]; | ||
var prepend = (propNames.indexOf('type') === -1) ? ['type'] : []; | ||
module.exports = function cloneWithAllowlist (astAllowList) { | ||
const allowlist = Object.keys(astAllowList).reduce(function (props, key) { | ||
const propNames = astAllowList[key]; | ||
const prepend = (propNames.indexOf('type') === -1) ? ['type'] : []; | ||
props[key] = prepend.concat(propNames || []); | ||
@@ -12,3 +12,3 @@ return props; | ||
function cloneNodeOrObject (clone, obj, seen) { | ||
var props = obj.type ? whitelist[obj.type] : null; | ||
const props = obj.type ? allowlist[obj.type] : null; | ||
if (props) { | ||
@@ -22,3 +22,3 @@ return cloneNode(clone, obj, props, seen); | ||
function cloneArray (clone, ary, seen) { | ||
var i = ary.length; | ||
let i = ary.length; | ||
while (i--) { | ||
@@ -35,6 +35,6 @@ if (seen.has(ary[i])) { | ||
function cloneNode (clone, node, props, seen) { | ||
var i, len, key; | ||
let i, len, key; | ||
for (i = 0, len = props.length; i < len; i += 1) { | ||
key = props[i]; | ||
if (node.hasOwnProperty(key)) { | ||
if (Object.prototype.hasOwnProperty.call(node, key)) { | ||
if (seen.has(node[key])) { | ||
@@ -51,4 +51,4 @@ clone[key] = seen.get(node[key]); | ||
function cloneObject (clone, obj, seen) { | ||
var props = Object.keys(obj); | ||
var i, len, key, value; | ||
const props = Object.keys(obj); | ||
let i, len, key, value; | ||
for (i = 0, len = props.length; i < len; i += 1) { | ||
@@ -71,7 +71,7 @@ key = props[i]; | ||
} else if (Array.isArray(val)) { | ||
var clone = []; | ||
const clone = []; | ||
seen.set(val, clone); | ||
return cloneArray(clone, val, seen); | ||
} else { | ||
var clone = {}; | ||
const clone = {}; | ||
seen.set(val, clone); | ||
@@ -86,4 +86,4 @@ return cloneNodeOrObject(clone, val, seen); | ||
function cloneRoot (obj) { | ||
var seen = new Map(); | ||
var clone = {}; | ||
const seen = new Map(); | ||
const clone = {}; | ||
seen.set(obj, clone); | ||
@@ -90,0 +90,0 @@ return cloneNodeOrObject(clone, obj, seen); |
@@ -1,2 +0,2 @@ | ||
Copyright (c) 2014-2019 Takuto Wada, https://github.com/estools/espurify | ||
Copyright (c) 2014-2022 Takuto Wada, https://github.com/estools/espurify | ||
@@ -3,0 +3,0 @@ Permission is hereby granted, free of charge, to any person obtaining |
{ | ||
"name": "espurify", | ||
"description": "Clone AST without extra properties", | ||
"version": "2.1.1", | ||
"version": "3.0.0", | ||
"author": { | ||
@@ -27,5 +27,5 @@ "name": "Takuto Wada", | ||
"estraverse": "^5.0.0", | ||
"mocha": "^8.0.0", | ||
"semistandard": "^14.0.0", | ||
"snazzy": "^8.0.0" | ||
"mocha": "^9.0.0", | ||
"semistandard": "^16.0.0", | ||
"snazzy": "^9.0.0" | ||
}, | ||
@@ -32,0 +32,0 @@ "files": [ |
222
README.md
@@ -15,3 +15,3 @@ espurify | ||
### var purifiedAstClone = espurify(originalAst) | ||
### const purifiedAstClone = espurify.purifyAst(originalAst) | ||
@@ -22,2 +22,4 @@ Returns new clone of `originalAst` but without extra properties. | ||
(note: using `espurify` as a default exported function is deprecated in favor of named exports aiming ESM era, and will be removed in future major releases) | ||
#### Supported ECMAScript versions | ||
@@ -31,10 +33,14 @@ | ||
- [ES2019](https://github.com/estree/estree/blob/master/es2019.md) | ||
- [ES2020](https://github.com/estree/estree/blob/master/es2020.md) | ||
- [ES2021](https://github.com/estree/estree/blob/master/es2021.md) | ||
- [ES2022](https://github.com/estree/estree/blob/master/es2022.md) | ||
### var customizedCloneFunctionWithWhiteList = espurify.cloneWithWhitelist(whiteList) | ||
### const customizedCloneFunctionWithAllowList = espurify.cloneWithAllowlist(allowList) | ||
Returns customized function for cloning AST, with user-provided `whiteList`. | ||
Returns customized function for cloning AST, with user-provided `allowList`. | ||
(note: `espurify.cloneWithWhitelist` is still exported but deprecated in favor of more inclusive language and will be removed in future major releases) | ||
### var purifiedAstClone = customizedCloneFunctionWithWhiteList(originalAst) | ||
### const purifiedAstClone = customizedCloneFunctionWithAllowList(originalAst) | ||
@@ -44,3 +50,3 @@ Returns new clone of `originalAst` by customized function. | ||
#### whiteList | ||
#### allowList | ||
@@ -51,3 +57,3 @@ | type | default value | | ||
`whiteList` is an object containing NodeType as keys and properties as values. | ||
`allowList` is an object containing NodeType as keys and properties as values. | ||
@@ -64,3 +70,3 @@ ```js | ||
### var customizedCloneFunction = espurify.customize(options) | ||
### const customizedCloneFunction = espurify.customize(options) | ||
@@ -70,3 +76,3 @@ Returns customized function for cloning AST, configured by custom `options`. | ||
### var purifiedAstClone = customizedCloneFunction(originalAst) | ||
### const purifiedAstClone = customizedCloneFunction(originalAst) | ||
@@ -86,2 +92,11 @@ Returns new clone of `originalAst` by customized function. | ||
#### options.ecmaVersion | ||
| type | default value | | ||
|:---------------------|:--------------| | ||
| `string` or `number` | `2022` | | ||
Indicates the ECMAScript version to clone. Must be either 5, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022. | ||
#### options.extra | ||
@@ -100,24 +115,24 @@ | ||
```javascript | ||
var espurify = require('espurify'), | ||
estraverse = require('estraverse'), | ||
esprima = require('esprima'), | ||
syntax = estraverse.Syntax, | ||
assert = require('assert'); | ||
const espurify = require('espurify'); | ||
const estraverse = require('estraverse'); | ||
const acorn = require('acorn'); | ||
const syntax = estraverse.Syntax; | ||
const assert = require('assert'); | ||
var jsCode = 'assert("foo")'; | ||
const jsCode = 'assert("foo")'; | ||
// Adding extra informations to AST | ||
var originalAst = esprima.parse(jsCode, {tolerant: true, loc: true, raw: true}); | ||
const originalAst = acorn.parse(jsCode, { locations: true, ranges: true, ecmaVersion: 2022 }); | ||
estraverse.replace(originalAst, { | ||
leave: function (currentNode, parentNode) { | ||
if (currentNode.type === syntax.Literal && typeof currentNode.raw !== 'undefined') { | ||
currentNode['x-verbatim-bar'] = { | ||
content : currentNode.raw, | ||
precedence : 18 // escodegen.Precedence.Primary | ||
}; | ||
return currentNode; | ||
} else { | ||
return undefined; | ||
} | ||
leave: function (currentNode, parentNode) { | ||
if (currentNode.type === syntax.Literal && typeof currentNode.raw !== 'undefined') { | ||
currentNode['x-verbatim-bar'] = { | ||
content : currentNode.raw, | ||
precedence : 18 // escodegen.Precedence.Primary | ||
}; | ||
return currentNode; | ||
} else { | ||
return undefined; | ||
} | ||
} | ||
}); | ||
@@ -127,16 +142,91 @@ | ||
// purify AST | ||
var purifiedClone = espurify(originalAst); | ||
const purifiedClone = espurify.purifyAst(originalAst); | ||
// Extra properties are eliminated from cloned AST | ||
assert.deepEqual(purifiedClone, { | ||
type: 'Program', | ||
body: [ | ||
{ | ||
type: 'ExpressionStatement', | ||
expression: { | ||
type: 'CallExpression', | ||
callee: { | ||
type: 'Identifier', | ||
name: 'assert' | ||
}, | ||
arguments: [ | ||
{ | ||
type: 'Literal', | ||
value: 'foo' | ||
} | ||
], | ||
optional: false | ||
} | ||
} | ||
], | ||
sourceType: 'script' | ||
}); | ||
// original AST is not modified | ||
assert.deepEqual(originalAst, { | ||
assert.deepEqual(originalAst,{ | ||
type: 'Program', | ||
start: 0, | ||
end: 13, | ||
loc: { | ||
start: { | ||
line: 1, | ||
column: 0 | ||
}, | ||
end: { | ||
line: 1, | ||
column: 13 | ||
} | ||
}, | ||
range: [ | ||
0, | ||
13 | ||
], | ||
body: [ | ||
{ | ||
type: 'ExpressionStatement', | ||
start: 0, | ||
end: 13, | ||
loc: { | ||
start: { | ||
line: 1, | ||
column: 0 | ||
}, | ||
end: { | ||
line: 1, | ||
column: 13 | ||
} | ||
}, | ||
range: [ | ||
0, | ||
13 | ||
], | ||
expression: { | ||
type: 'CallExpression', | ||
start: 0, | ||
end: 13, | ||
loc: { | ||
start: { | ||
line: 1, | ||
column: 0 | ||
}, | ||
end: { | ||
line: 1, | ||
column: 13 | ||
} | ||
}, | ||
range: [ | ||
0, | ||
13 | ||
], | ||
callee: { | ||
type: 'Identifier', | ||
name: 'assert', | ||
start: 0, | ||
end: 6, | ||
loc: { | ||
@@ -151,3 +241,8 @@ start: { | ||
} | ||
} | ||
}, | ||
range: [ | ||
0, | ||
6 | ||
], | ||
name: 'assert' | ||
}, | ||
@@ -157,4 +252,4 @@ arguments: [ | ||
type: 'Literal', | ||
value: 'foo', | ||
raw: '"foo"', | ||
start: 7, | ||
end: 12, | ||
loc: { | ||
@@ -170,2 +265,8 @@ start: { | ||
}, | ||
range: [ | ||
7, | ||
12 | ||
], | ||
value: 'foo', | ||
raw: '"foo"', | ||
"x-verbatim-bar": { | ||
@@ -177,61 +278,8 @@ content: '"foo"', | ||
], | ||
loc: { | ||
start: { | ||
line: 1, | ||
column: 0 | ||
}, | ||
end: { | ||
line: 1, | ||
column: 13 | ||
} | ||
} | ||
}, | ||
loc: { | ||
start: { | ||
line: 1, | ||
column: 0 | ||
}, | ||
end: { | ||
line: 1, | ||
column: 13 | ||
} | ||
optional: false | ||
} | ||
} | ||
], | ||
loc: { | ||
start: { | ||
line: 1, | ||
column: 0 | ||
}, | ||
end: { | ||
line: 1, | ||
column: 13 | ||
} | ||
}, | ||
errors: [] | ||
sourceType: 'script' | ||
}); | ||
// Extra properties are eliminated from cloned AST | ||
assert.deepEqual(purifiedClone, { | ||
type: 'Program', | ||
body: [ | ||
{ | ||
type: 'ExpressionStatement', | ||
expression: { | ||
type: 'CallExpression', | ||
callee: { | ||
type: 'Identifier', | ||
name: 'assert' | ||
}, | ||
arguments: [ | ||
{ | ||
type: 'Literal', | ||
value: 'foo' | ||
} | ||
] | ||
} | ||
} | ||
] | ||
}); | ||
``` | ||
@@ -252,3 +300,3 @@ | ||
```javascript | ||
var espurify = require('espurify'); | ||
const espurify = require('espurify'); | ||
``` | ||
@@ -255,0 +303,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
41229
14
530
317
1