|
|
// @ts-check
import { WalkerBase } from './walker.js';
/** @typedef { import('estree').BaseNode} BaseNode *//** @typedef { import('./walker.js').WalkerContext} WalkerContext */
/** @typedef {( * this: WalkerContext, * node: BaseNode, * parent: BaseNode, * key: string, * index: number * ) => void} SyncHandler */
export class SyncWalker extends WalkerBase { /** * * @param {SyncHandler} enter * @param {SyncHandler} leave */ constructor(enter, leave) { super();
/** @type {SyncHandler} */ this.enter = enter;
/** @type {SyncHandler} */ this.leave = leave; }
/** * * @param {BaseNode} node * @param {BaseNode} parent * @param {string} [prop] * @param {number} [index] * @returns {BaseNode} */ 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; }
for (const key in node) { const value = node[key];
if (typeof value !== "object") { continue; } else if (Array.isArray(value)) { for (let i = 0; i < value.length; i += 1) { if (value[i] !== null && typeof value[i].type === 'string') { if (!this.visit(value[i], node, key, i)) { // removed
i--; } } } } else if (value !== null && typeof value.type === "string") { 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; }}
|