@wyw-in-js/transform 1.0.3 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/esm/cache.js +47 -6
  2. package/esm/cache.js.map +1 -1
  3. package/esm/module.js +2 -2
  4. package/esm/module.js.map +1 -1
  5. package/esm/options/buildOptions.js +23 -2
  6. package/esm/options/buildOptions.js.map +1 -1
  7. package/esm/options/buildOptions.test.js +97 -0
  8. package/esm/options/buildOptions.test.js.map +1 -1
  9. package/esm/plugins/shaker.js +87 -9
  10. package/esm/plugins/shaker.js.map +1 -1
  11. package/esm/transform/Entrypoint.helpers.js +8 -1
  12. package/esm/transform/Entrypoint.helpers.js.map +1 -1
  13. package/esm/transform/Entrypoint.js +5 -3
  14. package/esm/transform/Entrypoint.js.map +1 -1
  15. package/esm/transform/EvaluatedEntrypoint.js.map +1 -1
  16. package/esm/transform/actions/BaseAction.js +1 -1
  17. package/esm/transform/actions/BaseAction.js.map +1 -1
  18. package/esm/transform/generators/processImports.js +53 -0
  19. package/esm/transform/generators/processImports.js.map +1 -1
  20. package/esm/transform/generators/resolveImports.js +2 -2
  21. package/esm/transform/generators/resolveImports.js.map +1 -1
  22. package/esm/utils/importOverrides.js +60 -0
  23. package/esm/utils/importOverrides.js.map +1 -1
  24. package/esm/vm/createVmContext.js +48 -16
  25. package/esm/vm/createVmContext.js.map +1 -1
  26. package/lib/cache.js +47 -7
  27. package/lib/cache.js.map +1 -1
  28. package/lib/module.js +2 -2
  29. package/lib/module.js.map +1 -1
  30. package/lib/options/buildOptions.js +23 -3
  31. package/lib/options/buildOptions.js.map +1 -1
  32. package/lib/options/buildOptions.test.js +97 -0
  33. package/lib/options/buildOptions.test.js.map +1 -1
  34. package/lib/plugins/shaker.js +88 -9
  35. package/lib/plugins/shaker.js.map +1 -1
  36. package/lib/transform/Entrypoint.helpers.js +8 -1
  37. package/lib/transform/Entrypoint.helpers.js.map +1 -1
  38. package/lib/transform/Entrypoint.js +5 -3
  39. package/lib/transform/Entrypoint.js.map +1 -1
  40. package/lib/transform/EvaluatedEntrypoint.js.map +1 -1
  41. package/lib/transform/actions/BaseAction.js +1 -1
  42. package/lib/transform/actions/BaseAction.js.map +1 -1
  43. package/lib/transform/generators/processImports.js +53 -0
  44. package/lib/transform/generators/processImports.js.map +1 -1
  45. package/lib/transform/generators/resolveImports.js +1 -1
  46. package/lib/transform/generators/resolveImports.js.map +1 -1
  47. package/lib/utils/importOverrides.js +62 -0
  48. package/lib/utils/importOverrides.js.map +1 -1
  49. package/lib/vm/createVmContext.js +48 -16
  50. package/lib/vm/createVmContext.js.map +1 -1
  51. package/package.json +5 -4
  52. package/types/cache.d.ts +2 -1
  53. package/types/cache.js +48 -6
  54. package/types/module.js +1 -1
  55. package/types/options/buildOptions.js +29 -2
  56. package/types/plugins/shaker.js +104 -9
  57. package/types/transform/Entrypoint.helpers.js +10 -1
  58. package/types/transform/Entrypoint.js +5 -3
  59. package/types/transform/EvaluatedEntrypoint.d.ts +2 -0
  60. package/types/transform/EvaluatedEntrypoint.js +1 -0
  61. package/types/transform/actions/BaseAction.js +1 -1
  62. package/types/transform/generators/processImports.js +70 -0
  63. package/types/transform/generators/resolveImports.js +1 -1
  64. package/types/utils/importOverrides.d.ts +2 -1
  65. package/types/utils/importOverrides.js +63 -0
  66. package/types/vm/createVmContext.js +61 -13
@@ -1 +1 @@
1
- {"version":3,"file":"importOverrides.js","names":["_path","_interopRequireDefault","require","_shared","e","__esModule","default","toCanonicalFileKey","resolved","root","rootDir","path","resolve","process","cwd","normalizedResolved","relative","sep","posix","split","join","startsWith","toImportKey","source","isFileImport","isAbsolute","key","kind","resolveMockSpecifier","importer","mock","stack","specifier","syncResolve","applyImportOverrideToOnly","only","override","noShake"],"sources":["../../src/utils/importOverrides.ts"],"sourcesContent":["import path from 'path';\n\nimport { syncResolve, type ImportOverride } from '@wyw-in-js/shared';\n\nexport type ImportKeyKind = 'file' | 'package';\n\nexport type ImportKey = {\n key: string;\n kind: ImportKeyKind;\n};\n\nexport function toCanonicalFileKey(\n resolved: string,\n root: string | undefined\n): string {\n const rootDir = root ? path.resolve(root) : process.cwd();\n const normalizedResolved = path.resolve(resolved);\n let relative = path.relative(rootDir, normalizedResolved);\n\n if (path.sep !== path.posix.sep) {\n relative = relative.split(path.sep).join(path.posix.sep);\n }\n\n if (!relative.startsWith('.')) {\n relative = `./${relative}`;\n }\n\n return relative;\n}\n\nexport function toImportKey({\n source,\n resolved,\n root,\n}: {\n resolved: string | null;\n root: string | undefined;\n source: string;\n}): ImportKey {\n const isFileImport = source.startsWith('.') || path.isAbsolute(source);\n\n if (isFileImport && resolved) {\n return { key: toCanonicalFileKey(resolved, root), kind: 'file' };\n }\n\n return { key: source, kind: 'package' };\n}\n\nexport function resolveMockSpecifier({\n importer,\n mock,\n root,\n stack,\n}: {\n importer: string;\n mock: string;\n root: string | undefined;\n stack: string[];\n}): string {\n const specifier =\n mock.startsWith('.') && root ? path.resolve(root, mock) : mock;\n\n return syncResolve(specifier, importer, stack);\n}\n\nexport function applyImportOverrideToOnly(\n only: string[],\n override: ImportOverride | undefined\n): string[] {\n if (override?.noShake) {\n return ['*'];\n }\n\n return only;\n}\n"],"mappings":";;;;;;;;;AAAA,IAAAA,KAAA,GAAAC,sBAAA,CAAAC,OAAA;AAEA,IAAAC,OAAA,GAAAD,OAAA;AAAqE,SAAAD,uBAAAG,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAS9D,SAASG,kBAAkBA,CAChCC,QAAgB,EAChBC,IAAwB,EAChB;EACR,MAAMC,OAAO,GAAGD,IAAI,GAAGE,aAAI,CAACC,OAAO,CAACH,IAAI,CAAC,GAAGI,OAAO,CAACC,GAAG,CAAC,CAAC;EACzD,MAAMC,kBAAkB,GAAGJ,aAAI,CAACC,OAAO,CAACJ,QAAQ,CAAC;EACjD,IAAIQ,QAAQ,GAAGL,aAAI,CAACK,QAAQ,CAACN,OAAO,EAAEK,kBAAkB,CAAC;EAEzD,IAAIJ,aAAI,CAACM,GAAG,KAAKN,aAAI,CAACO,KAAK,CAACD,GAAG,EAAE;IAC/BD,QAAQ,GAAGA,QAAQ,CAACG,KAAK,CAACR,aAAI,CAACM,GAAG,CAAC,CAACG,IAAI,CAACT,aAAI,CAACO,KAAK,CAACD,GAAG,CAAC;EAC1D;EAEA,IAAI,CAACD,QAAQ,CAACK,UAAU,CAAC,GAAG,CAAC,EAAE;IAC7BL,QAAQ,GAAG,KAAKA,QAAQ,EAAE;EAC5B;EAEA,OAAOA,QAAQ;AACjB;AAEO,SAASM,WAAWA,CAAC;EAC1BC,MAAM;EACNf,QAAQ;EACRC;AAKF,CAAC,EAAa;EACZ,MAAMe,YAAY,GAAGD,MAAM,CAACF,UAAU,CAAC,GAAG,CAAC,IAAIV,aAAI,CAACc,UAAU,CAACF,MAAM,CAAC;EAEtE,IAAIC,YAAY,IAAIhB,QAAQ,EAAE;IAC5B,OAAO;MAAEkB,GAAG,EAAEnB,kBAAkB,CAACC,QAAQ,EAAEC,IAAI,CAAC;MAAEkB,IAAI,EAAE;IAAO,CAAC;EAClE;EAEA,OAAO;IAAED,GAAG,EAAEH,MAAM;IAAEI,IAAI,EAAE;EAAU,CAAC;AACzC;AAEO,SAASC,oBAAoBA,CAAC;EACnCC,QAAQ;EACRC,IAAI;EACJrB,IAAI;EACJsB;AAMF,CAAC,EAAU;EACT,MAAMC,SAAS,GACbF,IAAI,CAACT,UAAU,CAAC,GAAG,CAAC,IAAIZ,IAAI,GAAGE,aAAI,CAACC,OAAO,CAACH,IAAI,EAAEqB,IAAI,CAAC,GAAGA,IAAI;EAEhE,OAAO,IAAAG,mBAAW,EAACD,SAAS,EAAEH,QAAQ,EAAEE,KAAK,CAAC;AAChD;AAEO,SAASG,yBAAyBA,CACvCC,IAAc,EACdC,QAAoC,EAC1B;EACV,IAAIA,QAAQ,aAARA,QAAQ,eAARA,QAAQ,CAAEC,OAAO,EAAE;IACrB,OAAO,CAAC,GAAG,CAAC;EACd;EAEA,OAAOF,IAAI;AACb","ignoreList":[]}
1
+ {"version":3,"file":"importOverrides.js","names":["_path","_interopRequireDefault","require","_shared","_minimatch","e","__esModule","default","toCanonicalFileKey","resolved","root","rootDir","path","resolve","process","cwd","normalizedResolved","relative","sep","posix","split","join","startsWith","toImportKey","source","isFileImport","isAbsolute","key","kind","resolveMockSpecifier","importer","mock","stack","specifier","syncResolve","applyImportOverrideToOnly","only","override","noShake","compiledImportOverridesCache","WeakMap","minimatchOptions","dot","nocomment","nonegate","getPatternSpecificity","pattern","wildcardCount","escaped","char","length","compileImportOverrides","importOverrides","matchers","Object","entries","map","matcher","Minimatch","specificity","sort","a","b","bySpecificity","byLength","localeCompare","getCompiledImportOverrides","cached","get","compiled","set","getImportOverride","_matchers$find","undefined","direct","find","match"],"sources":["../../src/utils/importOverrides.ts"],"sourcesContent":["import path from 'path';\n\nimport {\n syncResolve,\n type ImportOverride,\n type ImportOverrides,\n} from '@wyw-in-js/shared';\nimport { Minimatch } from 'minimatch';\n\nexport type ImportKeyKind = 'file' | 'package';\n\nexport type ImportKey = {\n key: string;\n kind: ImportKeyKind;\n};\n\nexport function toCanonicalFileKey(\n resolved: string,\n root: string | undefined\n): string {\n const rootDir = root ? path.resolve(root) : process.cwd();\n const normalizedResolved = path.resolve(resolved);\n let relative = path.relative(rootDir, normalizedResolved);\n\n if (path.sep !== path.posix.sep) {\n relative = relative.split(path.sep).join(path.posix.sep);\n }\n\n if (!relative.startsWith('.')) {\n relative = `./${relative}`;\n }\n\n return relative;\n}\n\nexport function toImportKey({\n source,\n resolved,\n root,\n}: {\n resolved: string | null;\n root: string | undefined;\n source: string;\n}): ImportKey {\n const isFileImport = source.startsWith('.') || path.isAbsolute(source);\n\n if (isFileImport && resolved) {\n return { key: toCanonicalFileKey(resolved, root), kind: 'file' };\n }\n\n return { key: source, kind: 'package' };\n}\n\nexport function resolveMockSpecifier({\n importer,\n mock,\n root,\n stack,\n}: {\n importer: string;\n mock: string;\n root: string | undefined;\n stack: string[];\n}): string {\n const specifier =\n mock.startsWith('.') && root ? path.resolve(root, mock) : mock;\n\n return syncResolve(specifier, importer, stack);\n}\n\nexport function applyImportOverrideToOnly(\n only: string[],\n override: ImportOverride | undefined\n): string[] {\n if (override?.noShake) {\n return ['*'];\n }\n\n return only;\n}\n\ntype CompiledImportOverrides = {\n matchers: Array<{\n matcher: Minimatch;\n override: ImportOverride;\n pattern: string;\n specificity: number;\n }>;\n};\n\nconst compiledImportOverridesCache = new WeakMap<\n ImportOverrides,\n CompiledImportOverrides\n>();\n\nconst minimatchOptions = {\n dot: true,\n nocomment: true,\n nonegate: true,\n} as const;\n\nfunction getPatternSpecificity(pattern: string): number {\n let wildcardCount = 0;\n let escaped = false;\n for (const char of pattern) {\n if (escaped) {\n escaped = false;\n } else if (char === '\\\\') {\n escaped = true;\n } else if (char === '*' || char === '?') {\n wildcardCount += 1;\n }\n }\n\n return pattern.length - wildcardCount * 10;\n}\n\nfunction compileImportOverrides(\n importOverrides: ImportOverrides\n): CompiledImportOverrides {\n const matchers = Object.entries(importOverrides)\n .map(([pattern, override]) => {\n return {\n matcher: new Minimatch(pattern, minimatchOptions),\n override,\n pattern,\n specificity: getPatternSpecificity(pattern),\n };\n })\n .sort((a, b) => {\n const bySpecificity = b.specificity - a.specificity;\n if (bySpecificity !== 0) return bySpecificity;\n\n const byLength = b.pattern.length - a.pattern.length;\n if (byLength !== 0) return byLength;\n\n return a.pattern.localeCompare(b.pattern);\n });\n\n return { matchers };\n}\n\nfunction getCompiledImportOverrides(\n importOverrides: ImportOverrides\n): CompiledImportOverrides {\n const cached = compiledImportOverridesCache.get(importOverrides);\n if (cached) return cached;\n\n const compiled = compileImportOverrides(importOverrides);\n compiledImportOverridesCache.set(importOverrides, compiled);\n return compiled;\n}\n\nexport function getImportOverride(\n importOverrides: ImportOverrides | undefined,\n key: string\n): ImportOverride | undefined {\n if (!importOverrides) {\n return undefined;\n }\n\n const direct = importOverrides[key];\n if (direct) return direct;\n\n const { matchers } = getCompiledImportOverrides(importOverrides);\n return matchers.find(({ matcher }) => matcher.match(key))?.override;\n}\n"],"mappings":"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","ignoreList":[]}
@@ -10,7 +10,13 @@ var process = _interopRequireWildcard(require("./process"));
10
10
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
11
11
  const NOOP = () => {};
12
12
  const IMPORT_META_ENV = '__wyw_import_meta_env';
13
+ const HAPPY_DOM_REQUIRE_HOOK = '__wyw_requireHappyDom';
13
14
  let importMetaEnvWarned = false;
15
+ let happyDomRequireEsmWarned = false;
16
+ let happyDomUnavailable = false;
17
+ function isErrRequireEsm(error) {
18
+ return typeof error === 'object' && error !== null && 'code' in error && error.code === 'ERR_REQUIRE_ESM';
19
+ }
14
20
  function createImportMetaEnvProxy() {
15
21
  const target = Object.create(null);
16
22
  const warnOnce = () => {
@@ -49,18 +55,43 @@ function createImportMetaEnvProxy() {
49
55
  }
50
56
  });
51
57
  }
58
+ function requireHappyDom() {
59
+ const hook = globalThis[HAPPY_DOM_REQUIRE_HOOK];
60
+ if (typeof hook === 'function') {
61
+ return hook();
62
+ }
63
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
64
+ return require('happy-dom');
65
+ }
52
66
  function createWindow() {
53
- const {
54
- Window,
55
- GlobalWindow
56
- } = require('happy-dom');
57
- const HappyWindow = GlobalWindow || Window;
58
- const win = new HappyWindow();
67
+ if (happyDomUnavailable) return undefined;
68
+ try {
69
+ const {
70
+ Window,
71
+ GlobalWindow
72
+ } = requireHappyDom();
73
+ const HappyWindow = GlobalWindow || Window;
74
+ const win = new HappyWindow();
59
75
 
60
- // TODO: browser doesn't expose Buffer, but a lot of dependencies use it
61
- win.Buffer = Buffer;
62
- win.Uint8Array = Uint8Array;
63
- return win;
76
+ // TODO: browser doesn't expose Buffer, but a lot of dependencies use it
77
+ win.Buffer = Buffer;
78
+ win.Uint8Array = Uint8Array;
79
+ return win;
80
+ } catch (error) {
81
+ if (!isErrRequireEsm(error)) {
82
+ throw error;
83
+ }
84
+ const hasCustomRequireHook = typeof globalThis[HAPPY_DOM_REQUIRE_HOOK] === 'function';
85
+ if (!hasCustomRequireHook) {
86
+ happyDomUnavailable = true;
87
+ }
88
+ if (happyDomRequireEsmWarned) return undefined;
89
+ happyDomRequireEsmWarned = true;
90
+
91
+ // eslint-disable-next-line no-console
92
+ console.warn([`[wyw-in-js] DOM emulation is enabled (features.happyDOM), but "happy-dom" could not be loaded in this build-time runtime.`, `This usually happens because "happy-dom" is ESM-only and cannot be loaded via require() in a CJS build.`, ``, `WyW will continue without DOM emulation (as if features.happyDOM:false).`, ``, `To silence this warning: set features: { happyDOM: false }.`, `To get real DOM emulation in Node 20+, WyW needs an ESM-only eval architecture (planned for v2.0.0),`, `or a runtime that supports require(ESM) (Node 24+).`].join('\n'));
93
+ return undefined;
94
+ }
64
95
  }
65
96
 
66
97
  /**
@@ -96,8 +127,15 @@ function createBaseContext(win, additionalContext) {
96
127
  }
97
128
  return baseContext;
98
129
  }
130
+ function createNothing() {
131
+ return {
132
+ teardown: () => {},
133
+ window: undefined
134
+ };
135
+ }
99
136
  function createHappyDOMWindow() {
100
137
  const win = createWindow();
138
+ if (!win) return createNothing();
101
139
  return {
102
140
  teardown: () => {
103
141
  win.happyDOM.abort();
@@ -105,12 +143,6 @@ function createHappyDOMWindow() {
105
143
  window: win
106
144
  };
107
145
  }
108
- function createNothing() {
109
- return {
110
- teardown: () => {},
111
- window: undefined
112
- };
113
- }
114
146
  function createVmContext(filename, features, additionalContext, overrideContext = i => i) {
115
147
  const isHappyDOMEnabled = (0, _shared.isFeatureEnabled)(features, 'happyDOM', filename);
116
148
  const {
@@ -1 +1 @@
1
- {"version":3,"file":"createVmContext.js","names":["vm","_interopRequireWildcard","require","_shared","process","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","NOOP","IMPORT_META_ENV","importMetaEnvWarned","createImportMetaEnvProxy","target","create","warnOnce","console","warn","join","Proxy","obj","key","Reflect","ownKeys","value","createWindow","Window","GlobalWindow","HappyWindow","win","Buffer","Uint8Array","setReferencePropertyIfNotPresent","context","createBaseContext","additionalContext","baseContext","document","clearImmediate","clearInterval","clearTimeout","setImmediate","requestAnimationFrame","setInterval","setTimeout","createHappyDOMWindow","teardown","happyDOM","abort","window","createNothing","undefined","createVmContext","filename","features","overrideContext","isHappyDOMEnabled","isFeatureEnabled","envContext","__filename","createContext"],"sources":["../../src/vm/createVmContext.ts"],"sourcesContent":["import * as vm from 'vm';\n\nimport type { Window } from 'happy-dom';\n\nimport type { FeatureFlags, StrictOptions } from '@wyw-in-js/shared';\nimport { isFeatureEnabled } from '@wyw-in-js/shared';\n\nimport * as process from './process';\n\nconst NOOP = () => {};\nconst IMPORT_META_ENV = '__wyw_import_meta_env';\n\nlet importMetaEnvWarned = false;\n\nfunction createImportMetaEnvProxy(): Record<string, unknown> {\n const target = Object.create(null) as Record<string, unknown>;\n\n const warnOnce = () => {\n if (importMetaEnvWarned) return;\n importMetaEnvWarned = true;\n // eslint-disable-next-line no-console\n console.warn(\n [\n `[wyw-in-js] import.meta.env was accessed during build-time evaluation, but no env values were provided.`,\n ``,\n `If you're using Vite, make sure @wyw-in-js/vite plugin is enabled (it injects Vite env for evaluation).`,\n `Otherwise provide \"__wyw_import_meta_env\" via pluginOptions.overrideContext.`,\n ].join('\\n')\n );\n };\n\n return new Proxy(target, {\n get(obj, key) {\n if (typeof key === 'symbol') {\n return Reflect.get(obj, key);\n }\n\n warnOnce();\n return obj[key];\n },\n has(obj, key) {\n if (typeof key === 'symbol') {\n return Reflect.has(obj, key);\n }\n\n warnOnce();\n return Reflect.has(obj, key);\n },\n getOwnPropertyDescriptor(obj, key) {\n return Reflect.getOwnPropertyDescriptor(obj, key);\n },\n ownKeys(obj) {\n return Reflect.ownKeys(obj);\n },\n set(obj, key, value) {\n if (typeof key === 'symbol') {\n return Reflect.set(obj, key, value);\n }\n\n warnOnce();\n return Reflect.set(obj, key, value);\n },\n });\n}\n\nfunction createWindow(): Window {\n const { Window, GlobalWindow } = require('happy-dom');\n const HappyWindow = GlobalWindow || Window;\n const win = new HappyWindow();\n\n // TODO: browser doesn't expose Buffer, but a lot of dependencies use it\n win.Buffer = Buffer;\n win.Uint8Array = Uint8Array;\n\n return win;\n}\n\n/**\n * `happy-dom` already has required references, so we don't need to set them.\n */\nfunction setReferencePropertyIfNotPresent(\n context: vm.Context,\n key: string\n): void {\n if (context[key] === context) {\n return;\n }\n\n context[key] = context;\n}\n\nfunction createBaseContext(\n win: Window | undefined,\n additionalContext: Partial<vm.Context>\n): Partial<vm.Context> {\n const baseContext: vm.Context = win ?? {};\n\n setReferencePropertyIfNotPresent(baseContext, 'window');\n setReferencePropertyIfNotPresent(baseContext, 'self');\n setReferencePropertyIfNotPresent(baseContext, 'top');\n setReferencePropertyIfNotPresent(baseContext, 'parent');\n setReferencePropertyIfNotPresent(baseContext, 'global');\n setReferencePropertyIfNotPresent(baseContext, 'process');\n\n baseContext.document = win?.document;\n baseContext.process = process;\n\n baseContext.clearImmediate = NOOP;\n baseContext.clearInterval = NOOP;\n baseContext.clearTimeout = NOOP;\n baseContext.setImmediate = NOOP;\n baseContext.requestAnimationFrame = NOOP;\n baseContext.setInterval = NOOP;\n baseContext.setTimeout = NOOP;\n\n // eslint-disable-next-line guard-for-in,no-restricted-syntax\n for (const key in additionalContext) {\n baseContext[key] = additionalContext[key];\n }\n\n return baseContext;\n}\n\nfunction createHappyDOMWindow() {\n const win = createWindow();\n\n return {\n teardown: () => {\n win.happyDOM.abort();\n },\n window: win,\n };\n}\n\nfunction createNothing() {\n return {\n teardown: () => {},\n window: undefined,\n };\n}\n\nexport function createVmContext(\n filename: string,\n features: FeatureFlags<'happyDOM'>,\n additionalContext: Partial<vm.Context>,\n overrideContext: StrictOptions['overrideContext'] = (i) => i\n) {\n const isHappyDOMEnabled = isFeatureEnabled(features, 'happyDOM', filename);\n\n const { teardown, window } = isHappyDOMEnabled\n ? createHappyDOMWindow()\n : createNothing();\n const envContext: Partial<vm.Context> = {\n [IMPORT_META_ENV]: createImportMetaEnvProxy(),\n };\n const baseContext = createBaseContext(\n window,\n overrideContext(\n {\n __filename: filename,\n ...envContext,\n ...additionalContext,\n },\n filename\n )\n );\n\n const context = vm.createContext(baseContext);\n\n return {\n context,\n teardown,\n };\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"createVmContext.js","names":["vm","_interopRequireWildcard","require","_shared","process","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","NOOP","IMPORT_META_ENV","HAPPY_DOM_REQUIRE_HOOK","importMetaEnvWarned","happyDomRequireEsmWarned","happyDomUnavailable","isErrRequireEsm","error","code","createImportMetaEnvProxy","target","create","warnOnce","console","warn","join","Proxy","obj","key","Reflect","ownKeys","value","requireHappyDom","hook","globalThis","createWindow","undefined","Window","GlobalWindow","HappyWindow","win","Buffer","Uint8Array","hasCustomRequireHook","setReferencePropertyIfNotPresent","context","createBaseContext","additionalContext","baseContext","document","clearImmediate","clearInterval","clearTimeout","setImmediate","requestAnimationFrame","setInterval","setTimeout","createNothing","teardown","window","createHappyDOMWindow","happyDOM","abort","createVmContext","filename","features","overrideContext","isHappyDOMEnabled","isFeatureEnabled","envContext","__filename","createContext"],"sources":["../../src/vm/createVmContext.ts"],"sourcesContent":["import * as vm from 'vm';\n\nimport type { Window } from 'happy-dom';\n\nimport type { FeatureFlags, StrictOptions } from '@wyw-in-js/shared';\nimport { isFeatureEnabled } from '@wyw-in-js/shared';\n\nimport * as process from './process';\n\nconst NOOP = () => {};\nconst IMPORT_META_ENV = '__wyw_import_meta_env';\nconst HAPPY_DOM_REQUIRE_HOOK = '__wyw_requireHappyDom';\n\nlet importMetaEnvWarned = false;\nlet happyDomRequireEsmWarned = false;\nlet happyDomUnavailable = false;\n\nfunction isErrRequireEsm(error: unknown): boolean {\n return (\n typeof error === 'object' &&\n error !== null &&\n 'code' in error &&\n (error as { code?: unknown }).code === 'ERR_REQUIRE_ESM'\n );\n}\n\nfunction createImportMetaEnvProxy(): Record<string, unknown> {\n const target = Object.create(null) as Record<string, unknown>;\n\n const warnOnce = () => {\n if (importMetaEnvWarned) return;\n importMetaEnvWarned = true;\n // eslint-disable-next-line no-console\n console.warn(\n [\n `[wyw-in-js] import.meta.env was accessed during build-time evaluation, but no env values were provided.`,\n ``,\n `If you're using Vite, make sure @wyw-in-js/vite plugin is enabled (it injects Vite env for evaluation).`,\n `Otherwise provide \"__wyw_import_meta_env\" via pluginOptions.overrideContext.`,\n ].join('\\n')\n );\n };\n\n return new Proxy(target, {\n get(obj, key) {\n if (typeof key === 'symbol') {\n return Reflect.get(obj, key);\n }\n\n warnOnce();\n return obj[key];\n },\n has(obj, key) {\n if (typeof key === 'symbol') {\n return Reflect.has(obj, key);\n }\n\n warnOnce();\n return Reflect.has(obj, key);\n },\n getOwnPropertyDescriptor(obj, key) {\n return Reflect.getOwnPropertyDescriptor(obj, key);\n },\n ownKeys(obj) {\n return Reflect.ownKeys(obj);\n },\n set(obj, key, value) {\n if (typeof key === 'symbol') {\n return Reflect.set(obj, key, value);\n }\n\n warnOnce();\n return Reflect.set(obj, key, value);\n },\n });\n}\n\ntype HappyDomExports = {\n GlobalWindow?: new () => Window;\n Window: new () => Window;\n};\n\nfunction requireHappyDom(): HappyDomExports {\n const hook = (globalThis as Record<string, unknown>)[HAPPY_DOM_REQUIRE_HOOK];\n if (typeof hook === 'function') {\n return (hook as () => HappyDomExports)();\n }\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n return require('happy-dom') as HappyDomExports;\n}\n\nfunction createWindow(): Window | undefined {\n if (happyDomUnavailable) return undefined;\n\n try {\n const { Window, GlobalWindow } = requireHappyDom();\n const HappyWindow = GlobalWindow || Window;\n const win = new HappyWindow();\n\n // TODO: browser doesn't expose Buffer, but a lot of dependencies use it\n win.Buffer = Buffer;\n win.Uint8Array = Uint8Array;\n\n return win;\n } catch (error) {\n if (!isErrRequireEsm(error)) {\n throw error;\n }\n\n const hasCustomRequireHook =\n typeof (globalThis as Record<string, unknown>)[HAPPY_DOM_REQUIRE_HOOK] ===\n 'function';\n if (!hasCustomRequireHook) {\n happyDomUnavailable = true;\n }\n\n if (happyDomRequireEsmWarned) return undefined;\n happyDomRequireEsmWarned = true;\n\n // eslint-disable-next-line no-console\n console.warn(\n [\n `[wyw-in-js] DOM emulation is enabled (features.happyDOM), but \"happy-dom\" could not be loaded in this build-time runtime.`,\n `This usually happens because \"happy-dom\" is ESM-only and cannot be loaded via require() in a CJS build.`,\n ``,\n `WyW will continue without DOM emulation (as if features.happyDOM:false).`,\n ``,\n `To silence this warning: set features: { happyDOM: false }.`,\n `To get real DOM emulation in Node 20+, WyW needs an ESM-only eval architecture (planned for v2.0.0),`,\n `or a runtime that supports require(ESM) (Node 24+).`,\n ].join('\\n')\n );\n\n return undefined;\n }\n}\n\n/**\n * `happy-dom` already has required references, so we don't need to set them.\n */\nfunction setReferencePropertyIfNotPresent(\n context: vm.Context,\n key: string\n): void {\n if (context[key] === context) {\n return;\n }\n\n context[key] = context;\n}\n\nfunction createBaseContext(\n win: Window | undefined,\n additionalContext: Partial<vm.Context>\n): Partial<vm.Context> {\n const baseContext: vm.Context = win ?? {};\n\n setReferencePropertyIfNotPresent(baseContext, 'window');\n setReferencePropertyIfNotPresent(baseContext, 'self');\n setReferencePropertyIfNotPresent(baseContext, 'top');\n setReferencePropertyIfNotPresent(baseContext, 'parent');\n setReferencePropertyIfNotPresent(baseContext, 'global');\n setReferencePropertyIfNotPresent(baseContext, 'process');\n\n baseContext.document = win?.document;\n baseContext.process = process;\n\n baseContext.clearImmediate = NOOP;\n baseContext.clearInterval = NOOP;\n baseContext.clearTimeout = NOOP;\n baseContext.setImmediate = NOOP;\n baseContext.requestAnimationFrame = NOOP;\n baseContext.setInterval = NOOP;\n baseContext.setTimeout = NOOP;\n\n // eslint-disable-next-line guard-for-in,no-restricted-syntax\n for (const key in additionalContext) {\n baseContext[key] = additionalContext[key];\n }\n\n return baseContext;\n}\n\nfunction createNothing() {\n return {\n teardown: () => {},\n window: undefined,\n };\n}\n\nfunction createHappyDOMWindow() {\n const win = createWindow();\n if (!win) return createNothing();\n\n return {\n teardown: () => {\n win.happyDOM.abort();\n },\n window: win,\n };\n}\n\nexport function createVmContext(\n filename: string,\n features: FeatureFlags<'happyDOM'>,\n additionalContext: Partial<vm.Context>,\n overrideContext: StrictOptions['overrideContext'] = (i) => i\n) {\n const isHappyDOMEnabled = isFeatureEnabled(features, 'happyDOM', filename);\n\n const { teardown, window } = isHappyDOMEnabled\n ? createHappyDOMWindow()\n : createNothing();\n const envContext: Partial<vm.Context> = {\n [IMPORT_META_ENV]: createImportMetaEnvProxy(),\n };\n const baseContext = createBaseContext(\n window,\n overrideContext(\n {\n __filename: filename,\n ...envContext,\n ...additionalContext,\n },\n filename\n )\n );\n\n const context = vm.createContext(baseContext);\n\n return {\n context,\n teardown,\n };\n}\n"],"mappings":"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","ignoreList":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wyw-in-js/transform",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "dependencies": {
5
5
  "@babel/core": "^7.23.5",
6
6
  "@babel/generator": "^7.23.5",
@@ -9,10 +9,11 @@
9
9
  "@babel/template": "^7.22.15",
10
10
  "@babel/traverse": "^7.23.5",
11
11
  "@babel/types": "^7.23.5",
12
- "@wyw-in-js/processor-utils": "1.0.2",
13
- "@wyw-in-js/shared": "1.0.2",
12
+ "@wyw-in-js/processor-utils": "1.0.4",
13
+ "@wyw-in-js/shared": "1.0.4",
14
14
  "cosmiconfig": "^8.0.0",
15
15
  "happy-dom": "^20.1.0",
16
+ "minimatch": "^9.0.5",
16
17
  "source-map": "^0.7.4",
17
18
  "stylis": "^4.3.0",
18
19
  "ts-invariant": "^0.10.3"
@@ -41,7 +42,7 @@
41
42
  "typescript": "^5.2.2"
42
43
  },
43
44
  "engines": {
44
- "node": ">=16.0.0"
45
+ "node": ">=20.0.0"
45
46
  },
46
47
  "files": [
47
48
  "esm/",
package/types/cache.d.ts CHANGED
@@ -25,6 +25,7 @@ export declare class TransformCacheCollection<TEntrypoint extends IBaseCachedEnt
25
25
  has(cacheName: CacheNames, key: string): boolean;
26
26
  invalidate(cacheName: CacheNames, key: string): void;
27
27
  invalidateForFile(filename: string): void;
28
- invalidateIfChanged(filename: string, content: string, previousVisitedFiles?: Set<string>): boolean;
28
+ invalidateIfChanged(filename: string, content: string, previousVisitedFiles?: Set<string>, source?: 'fs' | 'loaded'): boolean;
29
+ private setContentHash;
29
30
  }
30
31
  export {};
package/types/cache.js CHANGED
@@ -44,7 +44,28 @@ class TransformCacheCollection {
44
44
  }
45
45
  cache.set(key, value);
46
46
  if ('initialCode' in value) {
47
- this.contentHashes.set(key, hashContent(value.initialCode ?? ''));
47
+ const maybeOriginalCode = value
48
+ .originalCode;
49
+ const isLoaded = typeof value.initialCode === 'string';
50
+ const source = isLoaded ? 'loaded' : 'fs';
51
+ let resolvedCode;
52
+ if (isLoaded) {
53
+ resolvedCode = value.initialCode;
54
+ }
55
+ else if (typeof maybeOriginalCode === 'string') {
56
+ resolvedCode = maybeOriginalCode;
57
+ }
58
+ if (resolvedCode !== undefined) {
59
+ this.setContentHash(key, source, hashContent(resolvedCode));
60
+ return;
61
+ }
62
+ try {
63
+ const fileContent = node_fs_1.default.readFileSync((0, parseRequest_1.stripQueryAndHash)(key), 'utf8');
64
+ this.setContentHash(key, source, hashContent(fileContent));
65
+ }
66
+ catch {
67
+ this.setContentHash(key, source, hashContent(''));
68
+ }
48
69
  }
49
70
  }
50
71
  clear(cacheName) {
@@ -86,7 +107,7 @@ class TransformCacheCollection {
86
107
  this.invalidate(cacheName, filename);
87
108
  });
88
109
  }
89
- invalidateIfChanged(filename, content, previousVisitedFiles) {
110
+ invalidateIfChanged(filename, content, previousVisitedFiles, source = 'loaded') {
90
111
  const visitedFiles = new Set(previousVisitedFiles);
91
112
  const fileEntrypoint = this.get('entrypoints', filename);
92
113
  // We need to check all dependencies of the file
@@ -97,19 +118,40 @@ class TransformCacheCollection {
97
118
  const dependencyFilename = dependency.resolved;
98
119
  if (dependencyFilename) {
99
120
  const dependencyContent = node_fs_1.default.readFileSync((0, parseRequest_1.stripQueryAndHash)(dependencyFilename), 'utf8');
100
- this.invalidateIfChanged(dependencyFilename, dependencyContent, visitedFiles);
121
+ this.invalidateIfChanged(dependencyFilename, dependencyContent, visitedFiles, 'fs');
101
122
  }
102
123
  }
103
124
  }
104
- const hash = this.contentHashes.get(filename);
125
+ const existing = this.contentHashes.get(filename);
126
+ const previousHash = existing?.[source];
105
127
  const newHash = hashContent(content);
106
- if (hash !== newHash) {
128
+ if (previousHash === undefined) {
129
+ const otherSource = source === 'fs' ? 'loaded' : 'fs';
130
+ const otherHash = existing?.[otherSource];
131
+ if (otherHash !== undefined && otherHash !== newHash) {
132
+ cacheLogger('content has changed, invalidate all for %s', filename);
133
+ this.setContentHash(filename, source, newHash);
134
+ this.invalidateForFile(filename);
135
+ return true;
136
+ }
137
+ this.setContentHash(filename, source, newHash);
138
+ return false;
139
+ }
140
+ if (previousHash !== newHash) {
107
141
  cacheLogger('content has changed, invalidate all for %s', filename);
108
- this.contentHashes.set(filename, newHash);
142
+ this.setContentHash(filename, source, newHash);
109
143
  this.invalidateForFile(filename);
110
144
  return true;
111
145
  }
112
146
  return false;
113
147
  }
148
+ setContentHash(filename, source, hash) {
149
+ const current = this.contentHashes.get(filename);
150
+ if (current) {
151
+ current[source] = hash;
152
+ return;
153
+ }
154
+ this.contentHashes.set(filename, { [source]: hash });
155
+ }
114
156
  }
115
157
  exports.TransformCacheCollection = TransformCacheCollection;
package/types/module.js CHANGED
@@ -401,7 +401,7 @@ class Module {
401
401
  resolved,
402
402
  root,
403
403
  });
404
- const override = this.services.options.pluginOptions.importOverrides?.[keyInfo.key];
404
+ const override = (0, importOverrides_1.getImportOverride)(this.services.options.pluginOptions.importOverrides, keyInfo.key);
405
405
  const policy = override?.unknown ?? (override?.mock ? 'allow' : 'warn');
406
406
  const shouldWarn = !this.ignored && policy === 'warn';
407
407
  let finalResolved = resolved;
@@ -45,8 +45,35 @@ const getItemOptions = (item) => {
45
45
  const toItemWithOptions = (key, options) => Object.keys(options).length ? [key, options] : key;
46
46
  const normalizeKey = (key) => key.replace(/\\/g, '/');
47
47
  const extractPackageNameFromPath = (key) => {
48
- const match = normalizeKey(key).match(/\/node_modules\/(@[^/]+\/[^/]+|[^/]+)\//);
49
- return match?.[1] ?? null;
48
+ const normalized = normalizeKey(key);
49
+ const token = '/node_modules/';
50
+ let nodeModulesIndex = normalized.lastIndexOf(token);
51
+ while (nodeModulesIndex !== -1) {
52
+ const start = nodeModulesIndex + token.length;
53
+ const firstChar = normalized[start];
54
+ if (!firstChar)
55
+ return null;
56
+ let packageName = null;
57
+ if (firstChar === '@') {
58
+ const scopeEnd = normalized.indexOf('/', start);
59
+ if (scopeEnd === -1)
60
+ return null;
61
+ const nameEnd = normalized.indexOf('/', scopeEnd + 1);
62
+ if (nameEnd === -1)
63
+ return null;
64
+ packageName = normalized.slice(start, nameEnd);
65
+ }
66
+ else {
67
+ const nameEnd = normalized.indexOf('/', start);
68
+ if (nameEnd === -1)
69
+ return null;
70
+ packageName = normalized.slice(start, nameEnd);
71
+ }
72
+ if (!packageName.startsWith('.'))
73
+ return packageName;
74
+ nodeModulesIndex = normalized.lastIndexOf(token, nodeModulesIndex - 1);
75
+ }
76
+ return null;
50
77
  };
51
78
  const addBabelVariants = (kind, variants, key) => {
52
79
  const prefix = kind === 'preset'
@@ -13,6 +13,7 @@ const scopeHelpers_1 = require("../utils/scopeHelpers");
13
13
  const traversalCache_1 = require("../utils/traversalCache");
14
14
  const parseRequest_1 = require("../utils/parseRequest");
15
15
  const importOverrides_1 = require("../utils/importOverrides");
16
+ const warnedDynamicImportFiles = new Set();
16
17
  function getNonParamBinding(exportPath, name) {
17
18
  const binding = exportPath.scope.getBinding(name);
18
19
  if (binding && binding.kind !== 'param') {
@@ -162,9 +163,9 @@ function shakerPlugin(babel, { keepSideEffects = false, ifUnknownExport = 'skip-
162
163
  return cached;
163
164
  }
164
165
  const strippedSource = (0, parseRequest_1.stripQueryAndHash)(source);
165
- const direct = importOverrides[source] ??
166
+ const direct = (0, importOverrides_1.getImportOverride)(importOverrides, source) ??
166
167
  (strippedSource !== source
167
- ? importOverrides[strippedSource]
168
+ ? (0, importOverrides_1.getImportOverride)(importOverrides, strippedSource)
168
169
  : null);
169
170
  if (direct) {
170
171
  const result = shouldKeepOverride(direct);
@@ -184,7 +185,7 @@ function shakerPlugin(babel, { keepSideEffects = false, ifUnknownExport = 'skip-
184
185
  resolved,
185
186
  root,
186
187
  });
187
- const override = importOverrides[key];
188
+ const override = (0, importOverrides_1.getImportOverride)(importOverrides, key);
188
189
  const result = shouldKeepOverride(override);
189
190
  cache.set(source, result);
190
191
  return result;
@@ -196,9 +197,10 @@ function shakerPlugin(babel, { keepSideEffects = false, ifUnknownExport = 'skip-
196
197
  };
197
198
  })();
198
199
  const collected = (0, collectExportsAndImports_1.collectExportsAndImports)(file.path);
199
- const sideEffectImports = collected.imports.filter(collectExportsAndImports_1.sideEffectImport);
200
+ const { imports } = collected;
201
+ const sideEffectImports = imports.filter(collectExportsAndImports_1.sideEffectImport);
200
202
  log('import-and-exports', [
201
- `imports: ${collected.imports.length} (side-effects: ${sideEffectImports.length})`,
203
+ `imports: ${imports.length} (side-effects: ${sideEffectImports.length})`,
202
204
  `exports: ${Object.values(collected.exports).length}`,
203
205
  `reexports: ${collected.reexports.length}`,
204
206
  ].join(', '));
@@ -241,7 +243,7 @@ function shakerPlugin(babel, { keepSideEffects = false, ifUnknownExport = 'skip-
241
243
  if (onlyExportsSet.has('default') &&
242
244
  hasDefault &&
243
245
  !collected.isEsModule) {
244
- this.imports = collected.imports;
246
+ this.imports = imports;
245
247
  this.exports = exports;
246
248
  this.reexports = collected.reexports;
247
249
  this.deadExports = [];
@@ -251,7 +253,7 @@ function shakerPlugin(babel, { keepSideEffects = false, ifUnknownExport = 'skip-
251
253
  // __esModule should be kept alive
252
254
  onlyExportsSet.add('__esModule');
253
255
  const aliveExports = new Set();
254
- const importNames = collected.imports.map(({ imported }) => imported);
256
+ const importNames = imports.map(({ imported }) => imported);
255
257
  Object.entries(exports).forEach(([exported, local]) => {
256
258
  if (onlyExportsSet.has(exported)) {
257
259
  aliveExports.add(local);
@@ -305,7 +307,7 @@ function shakerPlugin(babel, { keepSideEffects = false, ifUnknownExport = 'skip-
305
307
  });
306
308
  }
307
309
  if (ifUnknownExport === 'skip-shaking') {
308
- this.imports = collected.imports;
310
+ this.imports = imports;
309
311
  this.exports = exports;
310
312
  this.reexports = collected.reexports;
311
313
  this.deadExports = [];
@@ -441,7 +443,7 @@ function shakerPlugin(babel, { keepSideEffects = false, ifUnknownExport = 'skip-
441
443
  }
442
444
  }
443
445
  }
444
- this.imports = withoutRemoved(collected.imports);
446
+ this.imports = withoutRemoved(imports);
445
447
  this.exports = {};
446
448
  this.deadExports = [];
447
449
  Object.entries(exports).forEach(([exported, local]) => {
@@ -457,6 +459,99 @@ function shakerPlugin(babel, { keepSideEffects = false, ifUnknownExport = 'skip-
457
459
  visitor: {},
458
460
  post(file) {
459
461
  const log = shakerLogger.extend((0, getFileIdx_1.getFileIdx)(file.opts.filename));
462
+ const dynamicImportWarningsEnabled = Boolean(process.env.WYW_WARN_DYNAMIC_IMPORTS) &&
463
+ process.env.WYW_WARN_DYNAMIC_IMPORTS !== '0' &&
464
+ process.env.WYW_WARN_DYNAMIC_IMPORTS !== 'false';
465
+ const filename = file.opts.filename;
466
+ if (dynamicImportWarningsEnabled &&
467
+ !warnedDynamicImportFiles.has(filename)) {
468
+ const dynamicImports = this.imports.filter((imp) => !(0, collectExportsAndImports_1.sideEffectImport)(imp) && imp.type === 'dynamic');
469
+ if (dynamicImports.length > 0) {
470
+ const sources = Array.from(new Set(dynamicImports.map((imp) => imp.source))).sort();
471
+ const sourcesToWarn = (() => {
472
+ if (!importOverrides || Object.keys(importOverrides).length === 0) {
473
+ return sources;
474
+ }
475
+ const shouldWarn = (source) => {
476
+ const strippedSource = (0, parseRequest_1.stripQueryAndHash)(source);
477
+ const direct = (0, importOverrides_1.getImportOverride)(importOverrides, source) ??
478
+ (strippedSource !== source
479
+ ? (0, importOverrides_1.getImportOverride)(importOverrides, strippedSource)
480
+ : undefined);
481
+ if (direct !== undefined) {
482
+ return false;
483
+ }
484
+ const isFileImport = strippedSource.startsWith('.') ||
485
+ path_1.default.isAbsolute(strippedSource);
486
+ if (!isFileImport) {
487
+ return true;
488
+ }
489
+ try {
490
+ const resolved = (0, shared_1.syncResolve)(strippedSource, filename, []);
491
+ const importKey = (0, importOverrides_1.toImportKey)({
492
+ source: strippedSource,
493
+ resolved,
494
+ root,
495
+ }).key;
496
+ return ((0, importOverrides_1.getImportOverride)(importOverrides, importKey) === undefined);
497
+ }
498
+ catch {
499
+ return true;
500
+ }
501
+ };
502
+ return sources.filter(shouldWarn);
503
+ })();
504
+ if (sourcesToWarn.length > 0) {
505
+ warnedDynamicImportFiles.add(filename);
506
+ const overrideKeys = sourcesToWarn
507
+ .map((source) => {
508
+ const strippedSource = (0, parseRequest_1.stripQueryAndHash)(source);
509
+ const isFileImport = strippedSource.startsWith('.') ||
510
+ path_1.default.isAbsolute(strippedSource);
511
+ if (!isFileImport) {
512
+ return { source, key: source };
513
+ }
514
+ try {
515
+ const resolved = (0, shared_1.syncResolve)(strippedSource, filename, []);
516
+ return {
517
+ source,
518
+ key: (0, importOverrides_1.toImportKey)({
519
+ source: strippedSource,
520
+ resolved,
521
+ root,
522
+ }).key,
523
+ };
524
+ }
525
+ catch {
526
+ return { source, key: strippedSource };
527
+ }
528
+ })
529
+ .filter((item, index, array) => {
530
+ const firstIndexForKey = array.findIndex((i) => i.key === item.key);
531
+ return firstIndexForKey === index;
532
+ });
533
+ const warning = [
534
+ `[wyw-in-js] Dynamic imports reached prepare stage`,
535
+ ``,
536
+ `file: ${filename}`,
537
+ `count: ${sourcesToWarn.length}`,
538
+ `sources:`,
539
+ ...sourcesToWarn.map((source) => ` - ${source}`),
540
+ ``,
541
+ `note: these imports will be resolved/processed even if they are lazy (e.g. React.lazy(() => import(...)))`,
542
+ ``,
543
+ `tip: if the imported module is runtime-only or heavy, mock it during evaluation via importOverrides:`,
544
+ ` importOverrides: {`,
545
+ ...overrideKeys.map(({ key, source }) => ` '${key}': { mock: './path/to/mock' }, // from ${source}`),
546
+ ` }`,
547
+ ``,
548
+ `note: importOverrides affects only build-time evaluation (it does not change your bundler runtime behavior)`,
549
+ ].join('\n');
550
+ // eslint-disable-next-line no-console
551
+ console.warn(warning);
552
+ }
553
+ }
554
+ }
460
555
  const processedImports = new Set();
461
556
  const imports = new Map();
462
557
  const addImport = ({ imported, source, }) => {
@@ -204,7 +204,16 @@ function loadAndParse(services, name, loadedCode, log) {
204
204
  reason: 'extension',
205
205
  };
206
206
  }
207
- const code = loadedCode ?? (0, fs_1.readFileSync)(filename, 'utf-8');
207
+ let code = loadedCode;
208
+ if (code === undefined) {
209
+ const cachedEntrypoint = services.cache.get('entrypoints', name);
210
+ if (cachedEntrypoint &&
211
+ 'initialCode' in cachedEntrypoint &&
212
+ typeof cachedEntrypoint.initialCode === 'string') {
213
+ code = cachedEntrypoint.initialCode;
214
+ }
215
+ }
216
+ code ??= (0, fs_1.readFileSync)(filename, 'utf-8');
208
217
  const { action, babelOptions } = getMatchedRule(pluginOptions.rules, filename, code);
209
218
  let ast;
210
219
  const { evalConfig, parseConfig } = buildConfigs(services, filename, pluginOptions, babelOptions);
@@ -42,7 +42,7 @@ class Entrypoint extends BaseEntrypoint_1.BaseEntrypoint {
42
42
  loadedAndParsed ??
43
43
  services.loadAndParseFn(services, name, initialCode, parents[0]?.log ?? services.log);
44
44
  if (this.loadedAndParsed.code !== undefined) {
45
- services.cache.invalidateIfChanged(name, this.loadedAndParsed.code);
45
+ services.cache.invalidateIfChanged(name, this.loadedAndParsed.code, undefined, this.initialCode === undefined ? 'fs' : 'loaded');
46
46
  }
47
47
  const code = this.loadedAndParsed.evaluator === 'ignored'
48
48
  ? '[IGNORED]'
@@ -100,7 +100,7 @@ class Entrypoint extends BaseEntrypoint_1.BaseEntrypoint {
100
100
  const { cache } = services;
101
101
  const cached = cache.get('entrypoints', name);
102
102
  const changed = loadedCode !== undefined
103
- ? cache.invalidateIfChanged(name, loadedCode)
103
+ ? cache.invalidateIfChanged(name, loadedCode, undefined, 'loaded')
104
104
  : false;
105
105
  if (!cached?.evaluated && cached?.ignored) {
106
106
  return ['cached', cached];
@@ -187,7 +187,9 @@ class Entrypoint extends BaseEntrypoint_1.BaseEntrypoint {
187
187
  createEvaluated() {
188
188
  const evaluatedOnly = (0, Entrypoint_helpers_1.mergeOnly)(this.evaluatedOnly, this.only);
189
189
  this.log('create EvaluatedEntrypoint for %o', evaluatedOnly);
190
- return new EvaluatedEntrypoint_1.EvaluatedEntrypoint(this.services, evaluatedOnly, this.exportsProxy, this.generation + 1, this.name, this.only, this.parents, this.dependencies);
190
+ const evaluated = new EvaluatedEntrypoint_1.EvaluatedEntrypoint(this.services, evaluatedOnly, this.exportsProxy, this.generation + 1, this.name, this.only, this.parents, this.dependencies);
191
+ evaluated.initialCode = this.initialCode;
192
+ return evaluated;
191
193
  }
192
194
  getDependency(name) {
193
195
  return this.dependencies.get(name);
@@ -8,10 +8,12 @@ export interface IEvaluatedEntrypoint {
8
8
  exports: Record<string | symbol, unknown>;
9
9
  generation: number;
10
10
  ignored: false;
11
+ initialCode?: string;
11
12
  log: Debugger;
12
13
  only: string[];
13
14
  }
14
15
  export declare class EvaluatedEntrypoint extends BaseEntrypoint implements IEvaluatedEntrypoint {
15
16
  readonly evaluated = true;
16
17
  readonly ignored = false;
18
+ initialCode?: string;
17
19
  }
@@ -5,5 +5,6 @@ const BaseEntrypoint_1 = require("./BaseEntrypoint");
5
5
  class EvaluatedEntrypoint extends BaseEntrypoint_1.BaseEntrypoint {
6
6
  evaluated = true;
7
7
  ignored = false;
8
+ initialCode;
8
9
  }
9
10
  exports.EvaluatedEntrypoint = EvaluatedEntrypoint;
@@ -65,7 +65,7 @@ class BaseAction {
65
65
  }
66
66
  run(handler) {
67
67
  if (this.handler && this.handler !== handler) {
68
- throw new Error(`action handler is already set`);
68
+ throw new Error(`action handler is already set for ${this.ref} (${this.entrypoint.name})`);
69
69
  }
70
70
  this.handler = handler;
71
71
  if (!this.activeScenario) {