diff --git a/src/Astx.ts b/src/Astx.ts index e373512..b4957bd 100644 --- a/src/Astx.ts +++ b/src/Astx.ts @@ -602,7 +602,10 @@ export default class Astx extends ExtendableProxy implements Iterable { const { parsePatternToNodes } = backend try { if (typeof arg0 === 'function') { - for (const astx of this) { + // Always replace in reverse so that if there are matches inside of + // matches, the inner matches get replaced first (since they come + // later in the code) + for (const astx of [...this].reverse()) { const replacement = arg0(astx, parsePatternToNodes) replace( astx.match, @@ -614,12 +617,12 @@ export default class Astx extends ExtendableProxy implements Iterable { } } else if (typeof arg0 === 'string') { const replacement = parsePatternToNodes(arg0) - for (const match of this._matches) { - replace(match, replacement, this.context) + for (let i = this._matches.length - 1; i >= 0; i--) { + replace(this._matches[i], replacement, this.context) } } else if (isNode(arg0) || isNodeArray(arg0)) { - for (const match of this._matches) { - replace(match, arg0, this.context) + for (let i = this._matches.length - 1; i >= 0; i--) { + replace(this._matches[i], arg0, this.context) } } else { const finalPaths = parsePatternToNodes(arg0, ...quasis) diff --git a/test/astx/bugs_nesting.ts b/test/astx/bugs_nesting.ts new file mode 100644 index 0000000..a72fb92 --- /dev/null +++ b/test/astx/bugs_nesting.ts @@ -0,0 +1,21 @@ +import { TransformOptions } from '../../src' +import { astxTestcase } from '../astxTestcase' +import dedent from 'dedent-js' + +astxTestcase({ + file: __filename, + input: dedent` + const validator = t.ref(() => t.object({ + a: t.ref(() => Foo) + })) + `, + parsers: ['babel', 'babel/tsx'], + astx: ({ astx }: TransformOptions): void => { + astx.find`t.ref(() => $x)`().replace`z.lazy(() => $x)`() + }, + expected: dedent` + const validator = z.lazy(() => t.object({ + a: z.lazy(() => Foo) + })); + `, +})