@wix/zero-config-implementation 1.68.0 → 1.70.0

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.
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { B as t, D as e, E as o, I as n, N as c, P as l, R as i, a as p, V as E, b as m, c as x, d as f, e as d, f as u, h as C, i as I, j as k, k as y, l as A, m as D, n as P, o as R, p as h, q as B, r as M, s as T, t as b, w } from "./index-BewAGOQY.js";
1
+ import { B as t, D as e, E as o, I as n, N as c, P as l, R as i, a as p, V as E, b as m, c as x, d as f, e as d, f as u, h as C, i as I, j as k, k as y, l as A, m as D, n as P, o as R, p as h, q as B, r as M, s as T, t as b, w } from "./index-DnxDZx90.js";
2
2
  import "react";
3
3
  export {
4
4
  t as BaseError,
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "registry": "https://registry.npmjs.org/",
5
5
  "access": "public"
6
6
  },
7
- "version": "1.68.0",
7
+ "version": "1.70.0",
8
8
  "description": "Core library for extracting component manifests from JS and CSS files",
9
9
  "type": "module",
10
10
  "main": "dist/index.js",
@@ -81,5 +81,5 @@
81
81
  ]
82
82
  }
83
83
  },
84
- "falconPackageHash": "5848ef0051ff536666dd46c6264f765b40f280afa13b5d120028a1a2"
84
+ "falconPackageHash": "f7f9d07ab6659b53c4a239fd98c2c3f0e24345cb528a5f5108c7e6ba"
85
85
  }
@@ -19,7 +19,10 @@
19
19
  *
20
20
  * 2. **`React.createElement` monkey-patch** — Classic JSX transform and explicit
21
21
  * `React.createElement()` calls are intercepted by temporarily replacing the
22
- * function on the React module object.
22
+ * function on the React module object. The ESM loader hook (point 1) also
23
+ * intercepts the `react` bare specifier itself, so Rspack/webpack bundles that
24
+ * use `import * as React from 'react'` and call `React.createElement` are also
25
+ * covered via the data: URL shim's state-aware wrapper.
23
26
  *
24
27
  * 3. **CJS module export patch** — Pre-built CJS bundles that call
25
28
  * `require('react/jsx-runtime')` at runtime. We use `createRequire` to obtain
@@ -67,9 +70,12 @@ import { renderToStaticMarkup } from 'react-dom/server'
67
70
 
68
71
  import type { ExtractorStore } from './information-extractors/react/extractors/core/store'
69
72
  import type { CreateElementEvent } from './information-extractors/react/extractors/core/types'
70
-
71
- // Import the interceptor API - use direct path since vite alias doesn't apply to all packages
72
- import { getOriginals, setJsxInterceptors } from './jsx-runtime-interceptor'
73
+ import {
74
+ getOriginalCreateElement,
75
+ getOriginals,
76
+ setCreateElementInterceptor,
77
+ setJsxInterceptors,
78
+ } from './jsx-runtime-interceptor'
73
79
 
74
80
  export const TRACE_ATTR = 'data-trace-id'
75
81
 
@@ -165,7 +171,7 @@ export function renderWithExtractors(
165
171
  const getNextId = () => `t${++nextId}`
166
172
 
167
173
  // Store originals
168
- const originalCreateElement = React.createElement
174
+ const originalCreateElement = getOriginalCreateElement() as ElementCreator
169
175
  const { jsx: originalJsx, jsxs: originalJsxs, jsxDEV: originalJsxDEV } = getOriginals()
170
176
 
171
177
  // Obtain real CJS module objects so we can patch them for pre-built CJS consumers
@@ -240,8 +246,11 @@ export function renderWithExtractors(
240
246
  const interceptedJsxDEV = createInterceptor(originalJsxDEV as ElementCreator, listeners, getNextId, store)
241
247
 
242
248
  try {
243
- // @ts-expect-error Monkey-patch createElement
249
+ // @ts-expect-error Monkey-patch createElement for default-import callers
244
250
  React.createElement = interceptedCreateElement
251
+ // The data: URL react shim (registered by registerJsxLoaderHook) reads this state on every
252
+ // createElement call, covering Rspack/webpack bundles that use `import * as React from 'react'`.
253
+ setCreateElementInterceptor(interceptedCreateElement)
245
254
  // Use the interceptor API for jsx-runtime (includes jsxDEV for dev mode)
246
255
  setJsxInterceptors(
247
256
  interceptedJsx as typeof originalJsx,
@@ -270,7 +279,9 @@ export function renderWithExtractors(
270
279
  return (userRenderToStaticMarkup ?? renderToStaticMarkup)(element)
271
280
  } finally {
272
281
  // Restore originals
282
+ // @ts-expect-error Restore monkey-patched createElement
273
283
  React.createElement = originalCreateElement
284
+ setCreateElementInterceptor(null)
274
285
  setJsxInterceptors() // Restores to originals
275
286
  // Restore CJS module exports
276
287
  cjsRuntime.jsx = origCjsJsx
@@ -19,6 +19,14 @@ const originalDevRuntime = require('react/jsx-dev-runtime') as typeof import('re
19
19
  // Type for jsxDEV function
20
20
  type JsxDevFn = typeof originalDevRuntime.jsxDEV
21
21
 
22
+ // biome-ignore lint/suspicious/noExplicitAny: broad function type matching React.createElement's signature
23
+ type CreateElementFn = (...args: any[]) => unknown
24
+
25
+ // Captured at module-init time for getOriginalCreateElement(); also reused in
26
+ // registerJsxLoaderHook() to stash the full exports for the react data: URL shim.
27
+ const cjsReact = require('react') as { createElement: CreateElementFn }
28
+ const originalCreateElement: CreateElementFn = cjsReact.createElement
29
+
22
30
  // ─────────────────────────────────────────────────────────────────────────────
23
31
  // Shared state via globalThis
24
32
  //
@@ -33,6 +41,8 @@ interface JsxInterceptorState {
33
41
  currentJsxs: typeof originalRuntime.jsxs
34
42
  currentJsxDEV: JsxDevFn
35
43
  isInsideOriginal: boolean
44
+ /** Interceptor for React.createElement set during render; null when not intercepting. */
45
+ currentCreateElement: CreateElementFn | null
36
46
  }
37
47
 
38
48
  function getState(): JsxInterceptorState {
@@ -43,6 +53,7 @@ function getState(): JsxInterceptorState {
43
53
  currentJsxs: originalRuntime.jsxs,
44
54
  currentJsxDEV: originalDevRuntime.jsxDEV,
45
55
  isInsideOriginal: false,
56
+ currentCreateElement: null,
46
57
  }
47
58
  }
48
59
  return g[STATE_KEY]!
@@ -74,6 +85,27 @@ export function getOriginals() {
74
85
  }
75
86
  }
76
87
 
88
+ /**
89
+ * Sets (or clears) the React.createElement interceptor used by the wrapper
90
+ * installed on the CJS react module by registerJsxLoaderHook.
91
+ *
92
+ * This handles ESM namespace imports (`import * as React from 'react'`) which
93
+ * snapshot the createElement reference at module-load time. Those snapshots
94
+ * point to the wrapper, which reads from this state on every call.
95
+ *
96
+ * Pass null to restore pass-through behaviour (wrapper delegates to original).
97
+ */
98
+ export function setCreateElementInterceptor(fn: CreateElementFn | null): void {
99
+ getState().currentCreateElement = fn
100
+ }
101
+
102
+ /**
103
+ * Returns the pre-wrapper React.createElement captured at module-init time.
104
+ */
105
+ export function getOriginalCreateElement(): CreateElementFn {
106
+ return originalCreateElement
107
+ }
108
+
77
109
  // ─────────────────────────────────────────────────────────────────────────────
78
110
  // Hook Registration
79
111
  // ─────────────────────────────────────────────────────────────────────────────
@@ -88,10 +120,22 @@ interface JsxOriginals {
88
120
  jsxDEV: JsxDevFn
89
121
  }
90
122
 
123
+ const REACT_ORIGINALS_KEY = Symbol.for('zero-config:react-originals')
124
+
91
125
  /**
92
- * Registers a Node.js ESM loader hook that redirects `react/jsx-runtime` and
93
- * `react/jsx-dev-runtime` imports to an in-memory interceptor built from
94
- * `data:` URLs — no separate files required, safe for bundled consumers.
126
+ * Registers a Node.js ESM loader hook that redirects `react/jsx-runtime`,
127
+ * `react/jsx-dev-runtime`, and `react` imports to in-memory `data:` URL
128
+ * interceptors — no separate files required, safe for bundled consumers.
129
+ *
130
+ * Intercepting `react` itself is necessary for bundled components (e.g. from
131
+ * @wix/site-ui) that use `import * as React from 'react'` (Rspack/webpack style)
132
+ * and call `React.createElement` through the namespace object. Node.js snapshots
133
+ * named CJS exports into the namespace at first-load time; since Vitest loads
134
+ * react before our module runs, the snapshot always contains the unwrapped
135
+ * original. The loader hook fires for NEWLY-loaded modules (i.e., the user bundle
136
+ * and its dependencies), redirecting `react` to a data: shim that wraps
137
+ * `createElement` with our state-based interceptor while delegating everything
138
+ * else to the real react instance.
95
139
  *
96
140
  * Must be called before any dynamic `import()` of user components.
97
141
  * Safe to call multiple times; subsequent calls are no-ops.
@@ -105,8 +149,8 @@ export function registerJsxLoaderHook(): void {
105
149
  const realRuntime = cjsRequire('react/jsx-runtime') as typeof originalRuntime
106
150
  const realDevRuntime = cjsRequire('react/jsx-dev-runtime') as typeof originalDevRuntime
107
151
 
108
- // Stash originals so the data: interceptor module can read them without needing
109
- // createRequire (data: modules have no filesystem context for CJS resolution)
152
+ // Stash jsx-runtime originals so the data: interceptor module can read them
153
+ // without needing createRequire (data: modules have no filesystem context)
110
154
  globalRecord[ORIGINALS_KEY] = {
111
155
  Fragment: realRuntime.Fragment,
112
156
  jsx: realRuntime.jsx,
@@ -114,6 +158,36 @@ export function registerJsxLoaderHook(): void {
114
158
  jsxDEV: realDevRuntime.jsxDEV,
115
159
  } satisfies JsxOriginals
116
160
 
161
+ // Stash the full react module so the react data: shim can re-export everything
162
+ const cjsReactExports = cjsRequire('react') as Record<string, unknown>
163
+ globalRecord[REACT_ORIGINALS_KEY] = cjsReactExports
164
+
165
+ // Generate named re-export lines for every enumerable property of react.
166
+ // `createElement` gets a state-aware wrapper; everything else is a direct
167
+ // delegation to the real react so hooks and other internals work correctly.
168
+ const reactExportLines = Object.keys(cjsReactExports)
169
+ .map((key) => {
170
+ if (key === 'createElement') {
171
+ return `export function createElement() {
172
+ var state = globalThis[STATE_KEY];
173
+ if (state && state.currentCreateElement) return state.currentCreateElement.apply(null, arguments);
174
+ return r.createElement.apply(null, arguments);
175
+ }`
176
+ }
177
+ return `export var ${key} = r.${key};`
178
+ })
179
+ .join('\n')
180
+
181
+ const reactShimSource = `
182
+ var REACT_KEY = Symbol.for('zero-config:react-originals');
183
+ var STATE_KEY = Symbol.for('zero-config:jsx-interceptor');
184
+ var r = globalThis[REACT_KEY];
185
+ export default r;
186
+ ${reactExportLines}
187
+ `
188
+
189
+ const reactShimUrl = `data:text/javascript,${encodeURIComponent(reactShimSource)}`
190
+
117
191
  const interceptorSource = `
118
192
  const ORIGINALS_KEY = Symbol.for('zero-config:jsx-originals');
119
193
  const STATE_KEY = Symbol.for('zero-config:jsx-interceptor');
@@ -155,10 +229,14 @@ export function jsxDEV(type, props, key, isStaticChildren, source, self) {
155
229
 
156
230
  const loaderSource = `
157
231
  const INTERCEPTOR_URL = ${JSON.stringify(interceptorDataUrl)};
232
+ const REACT_SHIM_URL = ${JSON.stringify(reactShimUrl)};
158
233
  export async function resolve(specifier, context, nextResolve) {
159
234
  if (specifier === 'react/jsx-runtime' || specifier === 'react/jsx-dev-runtime') {
160
235
  return { shortCircuit: true, url: INTERCEPTOR_URL };
161
236
  }
237
+ if (specifier === 'react') {
238
+ return { shortCircuit: true, url: REACT_SHIM_URL };
239
+ }
162
240
  return nextResolve(specifier, context);
163
241
  }
164
242
  `