nimma
Version:
Scalable JSONPath engine.
139 lines (122 loc) • 4.28 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
var builders = require('../ast/builders.cjs');
var dump = require('../dump.cjs');
var allocState = require('../templates/alloc-state.cjs');
var internalScope = require('../templates/internal-scope.cjs');
var scope = require('../templates/scope.cjs');
var treeMethod = require('../templates/tree-method.cjs');
var treeMethodCall = require('../templates/tree-method-call.cjs');
var consts = require('./consts.cjs');
var commonjs = require('./modules/commonjs.cjs');
var esm = require('./modules/esm.cjs');
var traversalZones = require('./traversal-zones.cjs');
const DEFAULT_PARAMS = [builders.identifier('input'), builders.identifier('callbacks')];
const NEW_SCOPE_VARIABLE_DECLARATION = builders.variableDeclaration('const', [
builders.variableDeclarator(
scope.default._,
builders.newExpression(builders.identifier('Scope'), DEFAULT_PARAMS),
),
]);
class ESTree {
#tree = builders.objectExpression([]);
#hasShorthands = false;
#runtimeDependencies;
#traverse = [];
#states = -1;
constructor() {
this.body = [];
this.traversalZones = new traversalZones.default();
this.#runtimeDependencies = new Map([['Scope', 'Scope']]);
}
/**
* @param {string} specifier
*/
addRuntimeDependency(specifier) {
this.#runtimeDependencies.set(specifier, specifier);
}
/**
* @param hash
* @returns {*}
*/
getMethodByHash(hash) {
return this.#tree.properties.find(prop => prop.key.value === hash);
}
/**
* @param {Object} id
* @param {'StringLiteral'} id.type
* @param {string} id.value
* @param {Object} block
* @param {number} feedback
*/
addTreeMethod(id, block, feedback) {
let state;
if ((feedback & consts.NEEDS_STATE) > 0) {
state = allocState.default(++this.#states);
this.body.push(state);
} else {
state = null;
}
const needsShorthands = (feedback & consts.NEEDS_SHORTHANDS) > 0;
this.#hasShorthands ||= needsShorthands;
this.#tree.properties.push(treeMethod.default(id, block, feedback));
const call = treeMethodCall.generateTreeMethodCall(id, state, needsShorthands);
((feedback & consts.NEEDS_TRAVERSAL) > 0 ? this.#traverse : this.body).push(call);
}
/**
* Generates JS code based on the underlying ESTree
* @param {'esm'|'commonjs'} format
* @returns {string}
*/
export(format) {
const traversalZones = this.traversalZones.build();
const params = this.#hasShorthands
? [...DEFAULT_PARAMS, internalScope.default.shorthands]
: DEFAULT_PARAMS;
const program = builders.program(
[
traversalZones,
this.#tree.properties.length === 0
? null
: builders.variableDeclaration('const', [
builders.variableDeclarator(internalScope.default.tree, this.#tree),
]),
builders.functionDeclaration(
null,
params,
builders.blockStatement([
NEW_SCOPE_VARIABLE_DECLARATION,
builders.tryStatement(
builders.blockStatement(
[
...this.body,
this.#traverse.length === 0
? null
: builders.expressionStatement(
builders.callExpression(scope.default.traverse, [
builders.arrowFunctionExpression(
[],
builders.blockStatement(Array.from(this.#traverse)),
),
traversalZones === null
? builders.nullLiteral()
: traversalZones.declarations[0].id,
]),
),
].filter(Boolean),
),
null,
builders.blockStatement([
builders.expressionStatement(builders.callExpression(scope.default.destroy, [])),
]),
),
]),
),
].filter(Boolean),
);
const mod = format === 'esm' ? esm.default : commonjs.default;
mod(Array.from(this.#runtimeDependencies), program);
return dump.default(program);
}
}
exports.default = ESTree;