diff --git a/packages/babel/src/transform/Entrypoint.ts b/packages/babel/src/transform/Entrypoint.ts index fab9ec5f9..17eeede7d 100644 --- a/packages/babel/src/transform/Entrypoint.ts +++ b/packages/babel/src/transform/Entrypoint.ts @@ -356,7 +356,12 @@ export class Entrypoint extends BaseEntrypoint { this.generation + 1 ); - this.log('superseded by %s', newEntrypoint.name); + this.log( + 'superseded by %s (%o -> %o)', + newEntrypoint.name, + this.only, + newEntrypoint.only + ); this.#supersededWith = newEntrypoint; this.onSupersedeHandlers.forEach((handler) => handler(newEntrypoint)); diff --git a/packages/babel/src/transform/generators/processEntrypoint.ts b/packages/babel/src/transform/generators/processEntrypoint.ts index 27e67dcf8..447ec5277 100644 --- a/packages/babel/src/transform/generators/processEntrypoint.ts +++ b/packages/babel/src/transform/generators/processEntrypoint.ts @@ -14,9 +14,21 @@ export function* processEntrypoint( const { only, log } = this.entrypoint; log('start processing (only: %s)', only); + if (this.entrypoint.supersededWith) { + log('entrypoint already superseded, rescheduling processing'); + yield [ + 'processEntrypoint', + this.entrypoint.supersededWith, + undefined, + null, + ]; + return; + } + const abortController = new AbortController(); const onParentAbort = () => { + log('parent aborted, aborting processing'); abortController.abort(); }; @@ -43,7 +55,7 @@ export function* processEntrypoint( ); this.entrypoint.setTransformResult(result); } catch (e) { - if (isAborted(e)) { + if (isAborted(e) && this.entrypoint.supersededWith) { log('aborting processing'); } else { throw e; diff --git a/packages/babel/src/transform/generators/workflow.ts b/packages/babel/src/transform/generators/workflow.ts index 41d7b5003..13e569ab6 100644 --- a/packages/babel/src/transform/generators/workflow.ts +++ b/packages/babel/src/transform/generators/workflow.ts @@ -25,7 +25,7 @@ export function* workflow( try { yield* this.getNext('processEntrypoint', entrypoint, undefined); } catch (e) { - if (isAborted(e)) { + if (isAborted(e) && entrypoint.supersededWith) { entrypoint.log('entrypoint superseded, rescheduling workflow'); yield* this.getNext('workflow', entrypoint.supersededWith!, undefined); } else { diff --git a/packages/testkit/src/__snapshots__/babel.test.ts.snap b/packages/testkit/src/__snapshots__/babel.test.ts.snap index bc5a5b04d..876936e39 100644 --- a/packages/testkit/src/__snapshots__/babel.test.ts.snap +++ b/packages/testkit/src/__snapshots__/babel.test.ts.snap @@ -411,6 +411,90 @@ Dependencies: NA `; +exports[`strategy shaker concurrent multiple parallel chains of reexports 1`] = ` +"import { styled } from '@linaria/react'; +export const H1foo = /*#__PURE__*/styled('h1')({ + name: "H1foo", + class: "H1foo_h1m1lid5", + propsAsIs: false +});" +`; + +exports[`strategy shaker concurrent multiple parallel chains of reexports 2`] = ` + +CSS: + +.H1foo_h1m1lid5 { + color: foo; +} + +Dependencies: ./__fixtures__/re-exports + +`; + +exports[`strategy shaker concurrent multiple parallel chains of reexports 3`] = ` +"import { styled } from '@linaria/react'; +export const H1bar = /*#__PURE__*/styled('h1')({ + name: "H1bar", + class: "H1bar_h1r70tzz", + propsAsIs: false +});" +`; + +exports[`strategy shaker concurrent multiple parallel chains of reexports 4`] = ` + +CSS: + +.H1bar_h1r70tzz { + color: bar; +} + +Dependencies: ./__fixtures__/re-exports + +`; + +exports[`strategy shaker concurrent multiple parallel chains of reexports 5`] = ` +"import { styled } from '@linaria/react'; +export const H1bar1 = /*#__PURE__*/styled('h1')({ + name: "H1bar1", + class: "H1bar1_hsluxkf", + propsAsIs: false +});" +`; + +exports[`strategy shaker concurrent multiple parallel chains of reexports 6`] = ` + +CSS: + +.H1bar1_hsluxkf { + color: bar1; +} + +Dependencies: ./__fixtures__/re-exports + +`; + +exports[`strategy shaker concurrent multiple parallel chains of reexports 7`] = ` +"import { styled } from '@linaria/react'; +export const H1bar2 = /*#__PURE__*/styled('h1')({ + name: "H1bar2", + class: "H1bar2_ht4s9ym", + propsAsIs: false +});" +`; + +exports[`strategy shaker concurrent multiple parallel chains of reexports 8`] = ` + +CSS: + +.H1bar2_ht4s9ym { + color: bar2; +} + +Dependencies: ./__fixtures__/re-exports + +`; + exports[`strategy shaker concurrent two parallel chains of reexports 1`] = ` "import { styled } from '@linaria/react'; export const H1 = /*#__PURE__*/styled('h1')({ diff --git a/packages/testkit/src/babel.test.ts b/packages/testkit/src/babel.test.ts index a2c009982..56a2bf5c4 100644 --- a/packages/testkit/src/babel.test.ts +++ b/packages/testkit/src/babel.test.ts @@ -14,7 +14,7 @@ import { TransformCacheCollection, Entrypoint, } from '@linaria/babel-preset'; -import { linariaLogger } from '@linaria/logger'; +import { enableDebug, linariaLogger } from '@linaria/logger'; import type { Evaluator, StrictOptions, OnEvent } from '@linaria/utils'; import { EventEmitter } from '@linaria/utils'; @@ -3245,5 +3245,39 @@ describe('strategy shaker', () => { 'single' ); }); + + it('multiple parallel chains of reexports', async () => { + enableDebug(); + const cache = new TransformCacheCollection(); + + const onEvent = jest.fn>(); + const emitter = new EventEmitter(onEvent); + + const tokens = ['foo', 'bar', 'bar1', 'bar2']; + + const results = await Promise.all( + tokens.map((token) => + transform( + dedent` + import { styled } from '@linaria/react'; + import { ${token} } from "./__fixtures__/re-exports"; + + export const H1${token} = styled.h1\` + color: ${`\${${token}}`}; + \` + `, + [evaluator], + cache, + emitter, + token + ) + ) + ); + + for (const { code, metadata } of results) { + expect(code).toMatchSnapshot(); + expect(metadata).toMatchSnapshot(); + } + }); }); });