123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- // @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;
- }
- }
|