Socket
Socket
Sign inDemoInstall

acorn-class-fields

Package Overview
Dependencies
Maintainers
1
Versions
14
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

acorn-class-fields - npm Package Compare versions

Comparing version 0.1.2 to 0.2.0

3

.eslintrc.json

@@ -78,3 +78,4 @@ {

"error",
"declaration"
"declaration",
{ "allowArrowFunctions": true }
],

@@ -81,0 +82,0 @@ "function-paren-newline": "off",

@@ -0,1 +1,6 @@

## 0.2.0 (2018-09-14)
* Update to new acorn 6 interface
* Change license to MIT
## 0.1.2 (2018-01-26)

@@ -2,0 +7,0 @@

"use strict"
module.exports = require("./inject")(require("acorn"))
const skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g
const acorn = require("acorn")
const tt = acorn.tokTypes
const TokenType = acorn.TokenType
function maybeParseFieldValue(field) {
if (this.eat(tt.eq)) {
const oldInFieldValue = this._inFieldValue
this._inFieldValue = true
field.value = this.parseExpression()
this._inFieldValue = oldInFieldValue
} else field.value = null
}
function parsePrivateName() {
const node = this.startNode()
node.name = this.value
this.next()
this.finishNode(node, "PrivateName")
if (this.options.allowReserved == "never") this.checkUnreserved(node)
return node
}
const privateNameToken = new TokenType("privateName")
module.exports = function(Parser) {
return class extends Parser {
// Parse # token
getTokenFromCode(code) {
if (code === 35) {
++this.pos
const word = this.readWord1()
return this.finishToken(privateNameToken, word)
}
return super.getTokenFromCode(code)
}
// Manage stacks and check for undeclared private names
parseClass(node, isStatement) {
this._privateBoundNamesStack = this._privateBoundNamesStack || []
const privateBoundNames = Object.create(this._privateBoundNamesStack[this._privateBoundNamesStack.length - 1] || null)
this._privateBoundNamesStack.push(privateBoundNames)
this._unresolvedPrivateNamesStack = this._unresolvedPrivateNamesStack || []
const unresolvedPrivateNames = Object.create(null)
this._unresolvedPrivateNamesStack.push(unresolvedPrivateNames)
const _return = super.parseClass(node, isStatement)
this._privateBoundNamesStack.pop()
this._unresolvedPrivateNamesStack.pop()
if (!this._unresolvedPrivateNamesStack.length) {
const names = Object.keys(unresolvedPrivateNames)
if (names.length) {
names.sort((n1, n2) => unresolvedPrivateNames[n1] - unresolvedPrivateNames[n2])
this.raise(unresolvedPrivateNames[names[0]], "Usage of undeclared private name")
}
} else Object.assign(this._unresolvedPrivateNamesStack[this._unresolvedPrivateNamesStack.length - 1], unresolvedPrivateNames)
return _return
}
// Parse private fields
parseClassElement() {
if (this.eat(tt.semi)) return null
const node = this.startNode()
if (!(this.options.ecmaVersion >= 8) || this.type != privateNameToken) {
// Special-case for `async`, since `parseClassMember` currently looks
// for `(` to determine whether `async` is a method name
if (this.isContextual("async")) {
skipWhiteSpace.lastIndex = this.pos
let skip = skipWhiteSpace.exec(this.input)
let next = this.input.charAt(this.pos + skip[0].length)
if (next === ";" || next === "=") {
node.key = this.parseIdent(true)
node.computed = false
maybeParseFieldValue.call(this, node)
this.finishNode(node, "FieldDefinition")
this.semicolon()
return node
}
}
return super.parseClassElement()
}
node.key = parsePrivateName.call(this)
node.computed = false
if (node.key.name == "constructor") this.raise(node.start, "Classes may not have a field named constructor")
if (Object.prototype.hasOwnProperty.call(this._privateBoundNamesStack[this._privateBoundNamesStack.length - 1], node.key.name)) this.raise(node.start, "Duplicate private element")
this._privateBoundNamesStack[this._privateBoundNamesStack.length - 1][node.key.name] = true
delete this._unresolvedPrivateNamesStack[this._unresolvedPrivateNamesStack.length - 1][node.key.name]
maybeParseFieldValue.call(this, node)
this.finishNode(node, "FieldDefinition")
this.semicolon()
return node
}
// Parse public fields
parseClassMethod(method, isGenerator, isAsync) {
if (isGenerator || isAsync || method.kind != "method" || method.static || this.options.ecmaVersion < 8 || this.type == tt.parenL) {
return super.parseClassMethod(method, isGenerator, isAsync)
}
maybeParseFieldValue.call(this, method)
delete method.kind
delete method.static
method = this.finishNode(method, "FieldDefinition")
this.semicolon()
return method
}
// Parse private element access
parseSubscripts(base, startPos, startLoc, noCalls) {
for (let computed; ;) {
if ((computed = this.eat(tt.bracketL)) || this.eat(tt.dot)) {
let node = this.startNodeAt(startPos, startLoc)
node.object = base
if (computed) {
node.property = this.parseExpression()
} else if (this.type == privateNameToken) {
node.property = parsePrivateName.call(this)
if (!this._privateBoundNamesStack.length || !this._privateBoundNamesStack[this._privateBoundNamesStack.length - 1][node.property.name]) {
this._unresolvedPrivateNamesStack[this._unresolvedPrivateNamesStack.length - 1][node.property.name] = node.property.start
}
} else {
node.property = this.parseIdent(true)
}
node.computed = Boolean(computed)
if (computed) this.expect(tt.bracketR)
base = this.finishNode(node, "MemberExpression")
} else {
return super.parseSubscripts(base, startPos, startLoc, noCalls)
}
}
}
// Prohibit delete of private class elements
parseMaybeUnary(refDestructuringErrors, sawUnary) {
const _return = super.parseMaybeUnary(refDestructuringErrors, sawUnary)
if (_return.operator == "delete") {
if (_return.argument.type == "MemberExpression" && _return.argument.property.type == "PrivateName") {
this.raise(_return.start, "Private elements may not be deleted")
}
}
return _return
}
// Prohibit arguments in class field initializers
parseIdent(liberal, isBinding) {
const ident = super.parseIdent(liberal, isBinding)
if (this._inFieldValue && ident.name == "arguments") this.raise(ident.start, "A class field initializer may not contain arguments")
return ident
}
// Prohibit super in class field initializers
parseExprAtom(refDestructuringErrors) {
const atom = super.parseExprAtom(refDestructuringErrors)
if (this._inFieldValue && atom.type == "Super") this.raise(atom.start, "A class field initializer may not contain super")
return atom
}
}
}

@@ -15,3 +15,3 @@ {

},
"license": "AGPL-3.0",
"license": "MIT",
"scripts": {

@@ -22,13 +22,14 @@ "test": "mocha",

},
"dependencies": {
"acorn": "^5.3.0"
"peerDependencies": {
"acorn": "^6.0.0"
},
"version": "0.1.2",
"version": "0.2.0",
"devDependencies": {
"eslint": "^4.13.1",
"eslint-plugin-node": "^5.2.1",
"mocha": "^4.0.1",
"test262": "git+https://github.com/tc39/test262.git#66df349af32c3f293936f7a947ac18bfb1ecda5c",
"test262-parser-runner": "^0.2.0"
"acorn": "^6.0.0",
"eslint": "^5.5.0",
"eslint-plugin-node": "^7.0.1",
"mocha": "^5.2.0",
"test262": "git+https://github.com/tc39/test262.git#e286bfa00086226f781a3ed4e0a6295634b8ed11",
"test262-parser-runner": "^0.4.0"
}
}

@@ -11,24 +11,12 @@ # Class fields support for Acorn

You can use this module directly in order to get an Acorn instance with the plugin installed:
This module provides a plugin that can be used to extend the Acorn `Parser` class:
```javascript
var acorn = require('acorn-class-fields');
const {Parser} = require('acorn');
const classFields = require('acorn-class-fields');
Parser.extend(classFields).parse('class X { x = 0 }');
```
Or you can use `inject.js` for injecting the plugin into your own version of Acorn like this:
```javascript
var acorn = require('acorn-class-fields/inject')(require('./custom-acorn'));
```
Then, use the `plugins` option to enable the plugiin:
```javascript
var ast = acorn.parse(code, {
plugins: { classFields: true }
});
```
## License
This plugin is released under the [GNU Affero General Public License](./LICENSE).
This plugin is released under an [MIT License](./LICENSE).

@@ -6,13 +6,10 @@ "use strict"

const run = require("test262-parser-runner")
const parse = require(".").parse
const acorn = require("acorn")
const Parser = acorn.Parser.extend(require("."))
const unsupportedFeatures = [
"async-iteration",
"BigInt",
"object-rest",
"object-spread",
"optional-catch-binding",
"regexp-lookbehind",
"regexp-named-groups",
"regexp-unicode-property-escapes"
"class-static-fields-public",
"class-static-fields-private",
"class-static-methods-private"
]

@@ -23,3 +20,3 @@

run(
(content, options) => parse(content, {sourceType: options.sourceType, ecmaVersion: 9, plugins: { classFields: true }}),
(content, options) => Parser.parse(content, {sourceType: options.sourceType, ecmaVersion: 9}),
{

@@ -26,0 +23,0 @@ testsDirectory: path.dirname(require.resolve("test262/package.json")),

"use strict"
const assert = require("assert")
const acorn = require("..")
const acorn = require("acorn"), classFields = require("..")
const Parser = acorn.Parser.extend(classFields)
function test(text, expectedResult, additionalOptions) {
it(text, function () {
const result = acorn.parse(text, Object.assign({ ecmaVersion: 9, plugins: { classFields: true } }, additionalOptions))
const result = Parser.parse(text, Object.assign({ ecmaVersion: 9 }, additionalOptions))
if (expectedResult) {
assert.deepEqual(result.body[0], expectedResult)
assert.deepStrictEqual(result.body[0], expectedResult)
}

@@ -18,5 +19,5 @@ })

try {
acorn.parse(text, Object.assign({ ecmaVersion: 9, plugins: { classFields: true } }, additionalOptions))
Parser.parse(text, Object.assign({ ecmaVersion: 9 }, additionalOptions))
} catch (e) {
assert.equal(e.message, expectedResult)
assert.strictEqual(e.message, expectedResult)
failed = true

@@ -27,2 +28,3 @@ }

}
const newNode = (start, props) => Object.assign(new acorn.Node({options: {}}, start), props)

@@ -69,95 +71,80 @@ describe("acorn-class-fields", function () {

const body = getBody(10)
return {
return newNode(0, {
type: "ClassDeclaration",
start: 0,
end: body.end + 2,
id: {
id: newNode(6, {
type: "Identifier",
start: 6,
end: 7,
name: "A"
},
}),
superClass: null,
body: {
body: newNode(8, {
type: "ClassBody",
start: 8,
end: body.end + 2,
body: [body]
}
}
})
})
} },
{ text: "class A { %s; }", ast: getBody => {
const body = getBody(10)
return {
return newNode(0, {
type: "ClassDeclaration",
start: 0,
end: body.end + 3,
id: {
id: newNode(6, {
type: "Identifier",
start: 6,
end: 7,
name: "A"
},
}),
superClass: null,
body: {
body: newNode(8, {
type: "ClassBody",
start: 8,
end: body.end + 3,
body: [body]
}
}
})
})
} },
{ text: "class A { %s; #y }", ast: getBody => {
const body = getBody(10)
return {
return newNode(0, {
type: "ClassDeclaration",
start: 0,
end: body.end + 6,
id: {
id: newNode(6, {
type: "Identifier",
start: 6,
end: 7,
name: "A"
},
}),
superClass: null,
body: {
body: newNode(8, {
type: "ClassBody",
start: 8,
end: body.end + 6,
body: [body, {
body: [body, newNode(body.end + 2, {
type: "FieldDefinition",
start: body.end + 2,
end: body.end + 4,
key: {
key: newNode(body.end + 2, {
type: "PrivateName",
start: body.end + 2,
end: body.end + 4,
name: "y"
},
}),
value: null,
computed: false
} ]
}
}
}) ]
})
})
} },
{ text: "class A { %s;a() {} }", ast: getBody => {
const body = getBody(10)
return {
return newNode(0, {
type: "ClassDeclaration",
start: 0,
end: body.end + 9,
id: {
id: newNode(6, {
type: "Identifier",
start: 6,
end: 7,
name: "A"
},
}),
superClass: null,
body: {
body: newNode(8, {
type: "ClassBody",
start: 8,
end: body.end + 9,
body: [ body, {
body: [ body, newNode(body.end + 1, {
type: "MethodDefinition",
start: body.end + 1,
end: body.end + 7,

@@ -167,11 +154,9 @@ kind: "method",

computed: false,
key: {
key: newNode(body.end + 1, {
type: "Identifier",
start: body.end + 1,
end: body.end + 2,
name: "a"
},
value: {
}),
value: newNode(body.end + 2, {
type: "FunctionExpression",
start: body.end + 2,
end: body.end + 7,

@@ -183,35 +168,30 @@ id: null,

params: [],
body: {
body: newNode(body.end + 5, {
type: "BlockStatement",
start: body.end + 5,
end: body.end + 7,
body: []
}
}
} ]
}
}
})
})
}) ]
})
})
} },
{ text: "class A { %s\na() {} }", ast: getBody => {
const body = getBody(10)
return {
return newNode(0, {
type: "ClassDeclaration",
start: 0,
end: body.end + 9,
id: {
id: newNode(6, {
type: "Identifier",
start: 6,
end: 7,
name: "A"
},
}),
superClass: null,
body: {
body: newNode(8, {
type: "ClassBody",
start: 8,
end: body.end + 9,
body: [
body,
{
newNode(body.end + 1, {
type: "MethodDefinition",
start: body.end + 1,
end: body.end + 7,

@@ -221,11 +201,9 @@ kind: "method",

computed: false,
key: {
key: newNode(body.end + 1, {
type: "Identifier",
start: body.end + 1,
end: body.end + 2,
name: "a"
},
value: {
}),
value: newNode(body.end + 2, {
type: "FunctionExpression",
start: body.end + 2,
end: body.end + 7,

@@ -237,13 +215,12 @@ id: null,

params: [],
body: {
body: newNode(body.end + 5, {
type: "BlockStatement",
start: body.end + 5,
end: body.end + 7,
body: []
}
}
}
})
})
})
]
}
}
})
})
} },

@@ -253,109 +230,92 @@ ];

[
{ body: "x", passes: true, ast: start => ({
{ body: "x", passes: true, ast: start => newNode(start, {
type: "FieldDefinition",
start: start,
end: start + 1,
key: {
key: newNode(start, {
type: "Identifier",
start: start,
end: start + 1,
name: "x"
},
}),
value: null,
computed: false
}) },
{ body: "x = 0", passes: true, ast: start => ({
{ body: "x = 0", passes: true, ast: start => newNode(start, {
type: "FieldDefinition",
start: start,
end: start + 5,
key: {
key: newNode(start, {
type: "Identifier",
start: start,
end: start + 1,
name: "x"
},
value: {
}),
value: newNode(start + 4, {
type: "Literal",
start: start + 4,
end: start + 5,
value: 0,
raw: "0"
},
}),
computed: false
}) },
{ body: "[x]", passes: true, ast: start => ({
{ body: "[x]", passes: true, ast: start => newNode(start, {
type: "FieldDefinition",
start: start,
end: start + 3,
computed: true,
key: {
key: newNode(start + 1, {
type: "Identifier",
start: start + 1,
end: start + 2,
name: "x"
},
}),
value: null
}) },
{ body: "[x] = 0", passes: true, ast: start => ({
{ body: "[x] = 0", passes: true, ast: start => newNode(start, {
type: "FieldDefinition",
start: start,
end: start + 7,
computed: true,
key: {
key: newNode(start + 1, {
type: "Identifier",
start: start + 1,
end: start + 2,
name: "x"
},
value: {
}),
value: newNode(start + 6, {
type: "Literal",
start: start + 6,
end: start + 7,
value: 0,
raw: "0"
}
})
}) },
{ body: "#x", passes: true, ast: start => ({
{ body: "#x", passes: true, ast: start => newNode(start, {
type: "FieldDefinition",
start: start,
end: start + 2,
computed: false,
key: {
key: newNode(start, {
type: "PrivateName",
start: start,
end: start + 2,
name: "x"
},
}),
value: null,
}) },
{ body: "#x = 0", passes: true, ast: start => ({
{ body: "#x = 0", passes: true, ast: start => newNode(start, {
type: "FieldDefinition",
start: start,
end: start + 6,
computed: false,
key: {
key: newNode(start, {
type: "PrivateName",
start: start,
end: start + 2,
name: "x"
},
value: {
}),
value: newNode(start + 5, {
type: "Literal",
start: start + 5,
end: start + 6,
value: 0,
raw: "0"
}
})
}) },
{ body: "async", passes: true, ast: start => ({
{ body: "async", passes: true, ast: start => newNode(start, {
type: "FieldDefinition",
start: start,
end: start + 5,
key: {
key: newNode(start, {
type: "Identifier",
start: start,
end: start + 5,
name: "async"
},
}),
value: null,

@@ -365,19 +325,16 @@ computed: false

{ body: "async = 5", passes: true, ast: start => ({
{ body: "async = 5", passes: true, ast: start => newNode(start, {
type: "FieldDefinition",
start: start,
end: start + 9,
key: {
key: newNode(start, {
type: "Identifier",
start: start,
end: start + 5,
name: "async"
},
value: {
}),
value: newNode(start + 8, {
type: "Literal",
start: 18,
end: 19,
end: start + 9,
raw: "5",
value: 5
},
}),
computed: false

@@ -384,0 +341,0 @@ }) },

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc