Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

hermes-parser

Package Overview
Dependencies
Maintainers
3
Versions
43
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

hermes-parser - npm Package Compare versions

Comparing version 0.7.0 to 0.8.0

dist/getModuleDocblock.js

64

dist/generated/visitor-keys.js

@@ -80,2 +80,5 @@ /**

},
ChainExpression: {
expression: 'Node'
},
ClassBody: {

@@ -106,14 +109,2 @@ body: 'NodeList'

},
ClassPrivateProperty: {
key: 'Node',
value: 'Node',
variance: 'Node',
typeAnnotation: 'Node'
},
ClassProperty: {
key: 'Node',
value: 'Node',
variance: 'Node',
typeAnnotation: 'Node'
},
ConditionalExpression: {

@@ -217,2 +208,3 @@ test: 'Node',

ExportAllDeclaration: {
exported: 'Node',
source: 'Node'

@@ -228,5 +220,2 @@ },

},
ExportNamespaceSpecifier: {
exported: 'Node'
},
ExportSpecifier: {

@@ -456,7 +445,2 @@ exported: 'Node',

},
OptionalCallExpression: {
callee: 'Node',
typeArguments: 'Node',
arguments: 'NodeList'
},
OptionalIndexedAccessType: {

@@ -466,9 +450,3 @@ objectType: 'Node',

},
OptionalMemberExpression: {
object: 'Node',
property: 'Node'
},
PrivateName: {
id: 'Node'
},
PrivateIdentifier: {},
Program: {

@@ -481,2 +459,8 @@ body: 'NodeList'

},
PropertyDefinition: {
key: 'Node',
value: 'Node',
variance: 'Node',
typeAnnotation: 'Node'
},
QualifiedTypeIdentifier: {

@@ -610,4 +594,28 @@ qualification: 'Node',

},
Import: {}
Import: {},
ClassProperty: {
key: 'Node',
value: 'Node',
variance: 'Node',
typeAnnotation: 'Node'
},
ClassPrivateProperty: {
key: 'Node',
value: 'Node',
variance: 'Node',
typeAnnotation: 'Node'
},
PrivateName: {
id: 'Node'
},
OptionalCallExpression: {
callee: 'Node',
typeArguments: 'Node',
arguments: 'NodeList'
},
OptionalMemberExpression: {
object: 'Node',
property: 'Node'
}
};
exports.HERMES_AST_VISITOR_KEYS = HERMES_AST_VISITOR_KEYS;

@@ -176,6 +176,2 @@ "use strict";

mapPrivateProperty(node) {
throw new SyntaxError(this.formatError(node, 'Private properties are not supported'));
}
formatError(node, message) {

@@ -182,0 +178,0 @@ return `${message} (${node.loc.start.line}:${node.loc.start.column})`;

@@ -92,2 +92,5 @@ "use strict";

case 'ExportNamespaceSpecifier':
return this.mapExportNamespaceSpecifier(node);
case 'ExportAllDeclaration':

@@ -106,2 +109,4 @@ return this.mapExportAllDeclaration(node);

case 'PrivateName':
return this.mapPrivateName(node);
case 'ClassPrivateProperty':

@@ -118,2 +123,5 @@ return this.mapPrivateProperty(node);

case 'BigIntLiteral':
return this.mapBigIntLiteral(node);
default:

@@ -284,3 +292,3 @@ return this.mapNodeDefault(node);

} = value;
return {
const newNode = {
type: 'ObjectMethod',

@@ -292,2 +300,3 @@ loc: node.loc,

kind: node.kind === 'init' ? 'method' : node.kind,
method: node.kind === 'init' ? true : false,
computed: node.computed,

@@ -304,2 +313,9 @@ key,

};
if (node.kind !== 'init') {
// babel emits an empty variance property on accessors for some reason
newNode.variance = null;
}
return newNode;
} else {

@@ -355,3 +371,11 @@ // Non-method property nodes should be renamed to ObjectProperty

restElement.typeAnnotation = annotation;
restElement.argument.typeAnnotation = null;
restElement.argument.typeAnnotation = null; // Unfortunately there's no way for us to recover the end location of
// the argument for the general case
if (restElement.argument.type === 'Identifier') {
restElement.argument.end = restElement.argument.start + restElement.argument.name.length;
restElement.argument.loc.end = { ...restElement.argument.loc.start,
column: restElement.argument.loc.start.column + restElement.argument.name.length
};
}
}

@@ -372,5 +396,9 @@

type: 'Import',
loc: node.loc,
loc: { ...node.loc,
end: { ...node.loc.start,
column: node.loc.start.column + 'import'.length
}
},
start: node.start,
end: node.end
end: node.start + 'import'.length
},

@@ -418,4 +446,55 @@ arguments: [this.mapNode(node.source)]

mapBigIntLiteral(node) {
const bigint = node.bigint.replace(/n$/, '').replace(/_/, '');
node.value = typeof BigInt === 'function' ? BigInt(bigint) : null;
return node;
}
mapPrivateProperty(nodeUnprocessed) {
const node = this.mapNodeDefault(nodeUnprocessed);
node.key = {
type: 'PrivateName',
id: { ...node.key,
// babel doesn't include the hash in the identifier
start: node.key.start + 1,
loc: { ...node.key.loc,
start: { ...node.key.loc.start,
column: node.key.loc.start.column + 1
}
}
},
start: node.key.start,
end: node.key.end,
loc: node.key.loc
};
return node;
}
mapPrivateName(node) {
// babel doesn't include the hash in the identifier
node.id.start += 1;
node.id.loc.start.column += 1;
return node;
}
mapExportNamespaceSpecifier(nodeUnprocessed) {
const node = this.mapNodeDefault(nodeUnprocessed); // the hermes AST emits the location as the location of the entire export
// but babel emits the location as *just* the "* as id" bit
// the end will always align with the end of the identifier (ezpz)
// but the start will align with the "*" token - which we can't recover from just the AST
// so we just fudge the start location a bit to get it "good enough"
// it will be wrong if the AST is anything like "export * as x from 'y'"... but oh well
node.start = node.start + 'export '.length;
node.loc.start.column = node.loc.start.column + 'export '.length;
node.end = node.exported.end;
node.loc.end = {
column: node.exported.loc.end.column,
line: node.exported.loc.end.line
};
return node;
}
}
exports.default = HermesToBabelAdapter;

@@ -10,2 +10,4 @@ "use strict";

var _getModuleDocblock = require("./getModuleDocblock");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

@@ -53,2 +55,4 @@

node.range = [loc.rangeStart, loc.rangeEnd];
delete node.start;
delete node.end;
}

@@ -105,8 +109,22 @@

case 'Property':
return this.mapProperty(node);
case 'FunctionDeclaration':
case 'FunctionExpression':
case 'ArrowFunctionExpression':
return this.mapFunction(node);
case 'PrivateName':
return this.mapPrivateName(node);
case 'ClassProperty':
case 'ClassPrivateProperty':
return this.mapPrivateProperty(node);
return this.mapClassProperty(node);
case 'Property':
return this.mapProperty(node);
case 'MemberExpression':
case 'OptionalMemberExpression':
case 'CallExpression':
case 'OptionalCallExpression':
return this.mapChainExpression(node);

@@ -121,2 +139,3 @@ default:

node.sourceType = this.getSourceType();
node.docblock = (0, _getModuleDocblock.getModuleDocblock)(node);
return node;

@@ -253,4 +272,187 @@ }

mapFunction(nodeUnprocessed) {
const node = this.mapNodeDefault(nodeUnprocessed);
switch (node.type) {
case 'FunctionDeclaration':
case 'FunctionExpression':
node.expression = false;
return node;
case 'ArrowFunctionExpression':
node.expression = node.body.type !== 'BlockStatement';
return node;
}
return node;
}
mapChainExpression(nodeUnprocessed) {
/*
NOTE - In the below comments `MemberExpression` and `CallExpression`
are completely interchangable. For terseness we just reference
one each time.
*/
/*
Hermes uses the old babel-style AST:
```
(one?.two).three?.four;
^^^^^^^^^^^^^^^^^^^^^^ OptionalMemberExpression
^^^^^^^^^^^^^^^^ MemberExpression
^^^^^^^^ OptionalMemberExpression
```
We need to convert it to the ESTree representation:
```
(one?.two).three?.four;
^^^^^^^^^^^^^^^^^^^^^^ ChainExpression
^^^^^^^^^^^^^^^^^^^^^^ MemberExpression[optional = true]
^^^^^^^^^^^^^^^^ MemberExpression[optional = false]
^^^^^^^^ ChainExpression
^^^^^^^^ MemberExpression[optional = true]
```
We do this by converting the AST and its children (depth first), and then unwrapping
the resulting AST as appropriate.
Put another way:
1) traverse to the leaf
2) if the current node is an `OptionalMemberExpression`:
a) if the `.object` is a `ChainExpression`:
i) unwrap the child (`node.object = child.expression`)
b) convert this node to a `MemberExpression[optional = true]`
c) wrap this node (`node = ChainExpression[expression = node]`)
3) if the current node is a `MembedExpression`:
a) convert this node to a `MemberExpression[optional = true]`
*/
const node = this.mapNodeDefault(nodeUnprocessed);
const {
child,
childKey,
isOptional
} = (() => {
const isOptional = node.optional === true;
if (node.type.endsWith('MemberExpression')) {
return {
child: node.object,
childKey: 'object',
isOptional
};
} else if (node.type.endsWith('CallExpression')) {
return {
child: node.callee,
childKey: 'callee',
isOptional
};
} else {
return {
child: node.expression,
childKey: 'expression',
isOptional: false
};
}
})();
const isChildUnwrappable = child.type === 'ChainExpression' && // (x?.y).z is semantically different to `x?.y.z`.
// In the un-parenthesised case `.z` is only executed if and only if `x?.y` returns a non-nullish value.
// In the parenthesised case, `.z` is **always** executed, regardless of the return of `x?.y`.
// As such the AST is different between the two cases.
//
// In the hermes AST - any member part of a non-short-circuited optional chain is represented with `OptionalMemberExpression`
// so if we see a `MemberExpression`, then we know we've hit a parenthesis boundary.
node.type !== 'MemberExpression' && node.type !== 'CallExpression';
if (node.type.startsWith('Optional')) {
node.type = node.type.replace('Optional', '');
node.optional = isOptional;
} else {
node.optional = false;
}
if (!isChildUnwrappable && !isOptional) {
return node;
}
if (isChildUnwrappable) {
const newChild = child.expression;
node[childKey] = newChild;
}
return {
type: 'ChainExpression',
expression: node,
loc: node.loc,
range: node.range
};
}
mapClassProperty(nodeUnprocessed) {
const node = this.mapNodeDefault(nodeUnprocessed);
const key = (() => {
if (node.type === 'ClassPrivateProperty') {
const key = this.mapNodeDefault(node.key);
return {
type: 'PrivateIdentifier',
name: key.name,
range: key.range,
loc: key.loc
};
}
return node.key;
})();
return { ...node,
computed: node.type === 'ClassPrivateProperty' ? false : node.computed,
key,
type: 'PropertyDefinition'
};
}
mapPrivateName(node) {
return {
type: 'PrivateIdentifier',
name: node.id.name,
// estree the location refers to the entire string including the hash token
range: node.range,
loc: node.loc
};
}
mapExportNamedDeclaration(nodeUnprocessed) {
const node = super.mapExportNamedDeclaration(nodeUnprocessed);
const namespaceSpecifier = node.specifiers.find(spec => spec.type === 'ExportNamespaceSpecifier');
if (namespaceSpecifier != null) {
var _node$exportKind;
if (node.specifiers.length !== 1) {
// this should already a hermes parser error - but let's be absolutely sure we're aligned with the spec
throw new Error('Cannot use an export all with any other specifiers');
}
return {
type: 'ExportAllDeclaration',
source: node.source,
exportKind: (_node$exportKind = node.exportKind) != null ? _node$exportKind : 'value',
exported: namespaceSpecifier.exported,
range: node.range,
loc: node.loc
};
}
return node;
}
mapExportAllDeclaration(nodeUnprocessed) {
var _node$exported;
const node = super.mapExportAllDeclaration(nodeUnprocessed);
node.exported = (_node$exported = node.exported) != null ? _node$exported : null;
return node;
}
}
exports.default = HermesToESTreeAdapter;
{
"name": "hermes-parser",
"version": "0.7.0",
"version": "0.8.0",
"description": "A JavaScript parser built from the Hermes engine",

@@ -12,6 +12,8 @@ "main": "dist/index.js",

"dependencies": {
"hermes-estree": "0.7.0"
"hermes-estree": "0.8.0"
},
"devDependencies": {
"hermes-transform": "0.7.0"
"@babel/parser": "7.7.4",
"espree": "9.3.2",
"hermes-transform": "0.8.0"
},

@@ -18,0 +20,0 @@ "files": [

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

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