aboutsummaryrefslogtreecommitdiffstats
path: root/vanilla/node_modules/estree-walker/src
diff options
context:
space:
mode:
Diffstat (limited to 'vanilla/node_modules/estree-walker/src')
-rw-r--r--vanilla/node_modules/estree-walker/src/async.js152
-rw-r--r--vanilla/node_modules/estree-walker/src/index.js34
-rw-r--r--vanilla/node_modules/estree-walker/src/sync.js152
-rw-r--r--vanilla/node_modules/estree-walker/src/walker.js61
4 files changed, 399 insertions, 0 deletions
diff --git a/vanilla/node_modules/estree-walker/src/async.js b/vanilla/node_modules/estree-walker/src/async.js
new file mode 100644
index 0000000..f068c71
--- /dev/null
+++ b/vanilla/node_modules/estree-walker/src/async.js
@@ -0,0 +1,152 @@
+import { WalkerBase } from './walker.js';
+
+/**
+ * @typedef { import('estree').Node} Node
+ * @typedef { import('./walker.js').WalkerContext} WalkerContext
+ * @typedef {(
+ * this: WalkerContext,
+ * node: Node,
+ * parent: Node | null,
+ * key: string | number | symbol | null | undefined,
+ * index: number | null | undefined
+ * ) => Promise<void>} AsyncHandler
+ */
+
+export class AsyncWalker extends WalkerBase {
+ /**
+ *
+ * @param {AsyncHandler} [enter]
+ * @param {AsyncHandler} [leave]
+ */
+ constructor(enter, leave) {
+ super();
+
+ /** @type {boolean} */
+ this.should_skip = false;
+
+ /** @type {boolean} */
+ this.should_remove = false;
+
+ /** @type {Node | null} */
+ this.replacement = null;
+
+ /** @type {WalkerContext} */
+ this.context = {
+ skip: () => (this.should_skip = true),
+ remove: () => (this.should_remove = true),
+ replace: (node) => (this.replacement = node)
+ };
+
+ /** @type {AsyncHandler | undefined} */
+ this.enter = enter;
+
+ /** @type {AsyncHandler | undefined} */
+ this.leave = leave;
+ }
+
+ /**
+ * @template {Node} Parent
+ * @param {Node} node
+ * @param {Parent | null} parent
+ * @param {keyof Parent} [prop]
+ * @param {number | null} [index]
+ * @returns {Promise<Node | null>}
+ */
+ async visit(node, parent, prop, index) {
+ if (node) {
+ if (this.enter) {
+ const _should_skip = this.should_skip;
+ const _should_remove = this.should_remove;
+ const _replacement = this.replacement;
+ this.should_skip = false;
+ this.should_remove = false;
+ this.replacement = null;
+
+ await this.enter.call(this.context, node, parent, prop, index);
+
+ if (this.replacement) {
+ node = this.replacement;
+ this.replace(parent, prop, index, node);
+ }
+
+ if (this.should_remove) {
+ this.remove(parent, prop, index);
+ }
+
+ const skipped = this.should_skip;
+ const removed = this.should_remove;
+
+ this.should_skip = _should_skip;
+ this.should_remove = _should_remove;
+ this.replacement = _replacement;
+
+ if (skipped) return node;
+ if (removed) return null;
+ }
+
+ /** @type {keyof Node} */
+ let key;
+
+ for (key in node) {
+ /** @type {unknown} */
+ const value = node[key];
+
+ if (value && typeof value === 'object') {
+ if (Array.isArray(value)) {
+ const nodes = /** @type {Array<unknown>} */ (value);
+ for (let i = 0; i < nodes.length; i += 1) {
+ const item = nodes[i];
+ if (isNode(item)) {
+ if (!(await this.visit(item, node, key, i))) {
+ // removed
+ i--;
+ }
+ }
+ }
+ } else if (isNode(value)) {
+ await this.visit(value, node, key, null);
+ }
+ }
+ }
+
+ if (this.leave) {
+ const _replacement = this.replacement;
+ const _should_remove = this.should_remove;
+ this.replacement = null;
+ this.should_remove = false;
+
+ await this.leave.call(this.context, node, parent, prop, index);
+
+ if (this.replacement) {
+ node = this.replacement;
+ this.replace(parent, prop, index, node);
+ }
+
+ if (this.should_remove) {
+ this.remove(parent, prop, index);
+ }
+
+ const removed = this.should_remove;
+
+ this.replacement = _replacement;
+ this.should_remove = _should_remove;
+
+ if (removed) return null;
+ }
+ }
+
+ return node;
+ }
+}
+
+/**
+ * Ducktype a node.
+ *
+ * @param {unknown} value
+ * @returns {value is Node}
+ */
+function isNode(value) {
+ return (
+ value !== null && typeof value === 'object' && 'type' in value && typeof value.type === 'string'
+ );
+}
diff --git a/vanilla/node_modules/estree-walker/src/index.js b/vanilla/node_modules/estree-walker/src/index.js
new file mode 100644
index 0000000..933ea4f
--- /dev/null
+++ b/vanilla/node_modules/estree-walker/src/index.js
@@ -0,0 +1,34 @@
+import { SyncWalker } from './sync.js';
+import { AsyncWalker } from './async.js';
+
+/**
+ * @typedef {import('estree').Node} Node
+ * @typedef {import('./sync.js').SyncHandler} SyncHandler
+ * @typedef {import('./async.js').AsyncHandler} AsyncHandler
+ */
+
+/**
+ * @param {Node} ast
+ * @param {{
+ * enter?: SyncHandler
+ * leave?: SyncHandler
+ * }} walker
+ * @returns {Node | null}
+ */
+export function walk(ast, { enter, leave }) {
+ const instance = new SyncWalker(enter, leave);
+ return instance.visit(ast, null);
+}
+
+/**
+ * @param {Node} ast
+ * @param {{
+ * enter?: AsyncHandler
+ * leave?: AsyncHandler
+ * }} walker
+ * @returns {Promise<Node | null>}
+ */
+export async function asyncWalk(ast, { enter, leave }) {
+ const instance = new AsyncWalker(enter, leave);
+ return await instance.visit(ast, null);
+}
diff --git a/vanilla/node_modules/estree-walker/src/sync.js b/vanilla/node_modules/estree-walker/src/sync.js
new file mode 100644
index 0000000..171fb36
--- /dev/null
+++ b/vanilla/node_modules/estree-walker/src/sync.js
@@ -0,0 +1,152 @@
+import { WalkerBase } from './walker.js';
+
+/**
+ * @typedef { import('estree').Node} Node
+ * @typedef { import('./walker.js').WalkerContext} WalkerContext
+ * @typedef {(
+ * this: WalkerContext,
+ * node: Node,
+ * parent: Node | null,
+ * key: string | number | symbol | null | undefined,
+ * index: number | null | undefined
+ * ) => void} SyncHandler
+ */
+
+export class SyncWalker extends WalkerBase {
+ /**
+ *
+ * @param {SyncHandler} [enter]
+ * @param {SyncHandler} [leave]
+ */
+ constructor(enter, leave) {
+ super();
+
+ /** @type {boolean} */
+ this.should_skip = false;
+
+ /** @type {boolean} */
+ this.should_remove = false;
+
+ /** @type {Node | null} */
+ this.replacement = null;
+
+ /** @type {WalkerContext} */
+ this.context = {
+ skip: () => (this.should_skip = true),
+ remove: () => (this.should_remove = true),
+ replace: (node) => (this.replacement = node)
+ };
+
+ /** @type {SyncHandler | undefined} */
+ this.enter = enter;
+
+ /** @type {SyncHandler | undefined} */
+ this.leave = leave;
+ }
+
+ /**
+ * @template {Node} Parent
+ * @param {Node} node
+ * @param {Parent | null} parent
+ * @param {keyof Parent} [prop]
+ * @param {number | null} [index]
+ * @returns {Node | null}
+ */
+ visit(node, parent, prop, index) {
+ if (node) {
+ if (this.enter) {
+ const _should_skip = this.should_skip;
+ const _should_remove = this.should_remove;
+ const _replacement = this.replacement;
+ this.should_skip = false;
+ this.should_remove = false;
+ this.replacement = null;
+
+ this.enter.call(this.context, node, parent, prop, index);
+
+ if (this.replacement) {
+ node = this.replacement;
+ this.replace(parent, prop, index, node);
+ }
+
+ if (this.should_remove) {
+ this.remove(parent, prop, index);
+ }
+
+ const skipped = this.should_skip;
+ const removed = this.should_remove;
+
+ this.should_skip = _should_skip;
+ this.should_remove = _should_remove;
+ this.replacement = _replacement;
+
+ if (skipped) return node;
+ if (removed) return null;
+ }
+
+ /** @type {keyof Node} */
+ let key;
+
+ for (key in node) {
+ /** @type {unknown} */
+ const value = node[key];
+
+ if (value && typeof value === 'object') {
+ if (Array.isArray(value)) {
+ const nodes = /** @type {Array<unknown>} */ (value);
+ for (let i = 0; i < nodes.length; i += 1) {
+ const item = nodes[i];
+ if (isNode(item)) {
+ if (!this.visit(item, node, key, i)) {
+ // removed
+ i--;
+ }
+ }
+ }
+ } else if (isNode(value)) {
+ this.visit(value, node, key, null);
+ }
+ }
+ }
+
+ if (this.leave) {
+ const _replacement = this.replacement;
+ const _should_remove = this.should_remove;
+ this.replacement = null;
+ this.should_remove = false;
+
+ this.leave.call(this.context, node, parent, prop, index);
+
+ if (this.replacement) {
+ node = this.replacement;
+ this.replace(parent, prop, index, node);
+ }
+
+ if (this.should_remove) {
+ this.remove(parent, prop, index);
+ }
+
+ const removed = this.should_remove;
+
+ this.replacement = _replacement;
+ this.should_remove = _should_remove;
+
+ if (removed) return null;
+ }
+ }
+
+ return node;
+ }
+}
+
+/**
+ * Ducktype a node.
+ *
+ * @param {unknown} value
+ * @returns {value is Node}
+ */
+function isNode(value) {
+ return (
+ value !== null && typeof value === 'object' && 'type' in value && typeof value.type === 'string'
+ );
+}
diff --git a/vanilla/node_modules/estree-walker/src/walker.js b/vanilla/node_modules/estree-walker/src/walker.js
new file mode 100644
index 0000000..6dc6bd7
--- /dev/null
+++ b/vanilla/node_modules/estree-walker/src/walker.js
@@ -0,0 +1,61 @@
+/**
+ * @typedef { import('estree').Node} Node
+ * @typedef {{
+ * skip: () => void;
+ * remove: () => void;
+ * replace: (node: Node) => void;
+ * }} WalkerContext
+ */
+
+export class WalkerBase {
+ constructor() {
+ /** @type {boolean} */
+ this.should_skip = false;
+
+ /** @type {boolean} */
+ this.should_remove = false;
+
+ /** @type {Node | null} */
+ this.replacement = null;
+
+ /** @type {WalkerContext} */
+ this.context = {
+ skip: () => (this.should_skip = true),
+ remove: () => (this.should_remove = true),
+ replace: (node) => (this.replacement = node)
+ };
+ }
+
+ /**
+ * @template {Node} Parent
+ * @param {Parent | null | undefined} parent
+ * @param {keyof Parent | null | undefined} prop
+ * @param {number | null | undefined} index
+ * @param {Node} node
+ */
+ replace(parent, prop, index, node) {
+ if (parent && prop) {
+ if (index != null) {
+ /** @type {Array<Node>} */ (parent[prop])[index] = node;
+ } else {
+ /** @type {Node} */ (parent[prop]) = node;
+ }
+ }
+ }
+
+ /**
+ * @template {Node} Parent
+ * @param {Parent | null | undefined} parent
+ * @param {keyof Parent | null | undefined} prop
+ * @param {number | null | undefined} index
+ */
+ remove(parent, prop, index) {
+ if (parent && prop) {
+ if (index !== null && index !== undefined) {
+ /** @type {Array<Node>} */ (parent[prop]).splice(index, 1);
+ } else {
+ delete parent[prop];
+ }
+ }
+ }
+}