@octanejs/rspack-plugin 0.1.43 → 0.1.45

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@octanejs/rspack-plugin",
3
- "version": "0.1.43",
3
+ "version": "0.1.45",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "engines": {
@@ -45,7 +45,7 @@
45
45
  },
46
46
  "peerDependencies": {
47
47
  "@rspack/core": "^2.0.0",
48
- "octane": "0.1.48"
48
+ "octane": "0.1.50"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@rspack/core": "^2.1.4",
@@ -54,7 +54,7 @@
54
54
  "css-loader": "6.11.0",
55
55
  "jsdom": "^30.0.1",
56
56
  "vitest": "^4.1.10",
57
- "octane": "0.1.48"
57
+ "octane": "0.1.50"
58
58
  },
59
59
  "scripts": {
60
60
  "test": "vitest run --config vitest.config.js"
@@ -94,6 +94,39 @@ function targetForRequest(compilation, importer, request) {
94
94
  return targets.size === 1 ? targets.values().next().value : null;
95
95
  }
96
96
 
97
+ /** Resolve several exact requests with one fresh walk of the current graph. */
98
+ function targetsForRequests(compilation, importer, requests) {
99
+ const states = new Map();
100
+ for (const request of requests) {
101
+ states.set(request, { id: null, target: null, invalid: false });
102
+ }
103
+ let invalid = 0;
104
+ for (const connection of compilation.moduleGraph.getOutgoingConnections(importer)) {
105
+ const dependency = connection.dependency;
106
+ if (dependency?.category !== 'esm') continue;
107
+ const state = states.get(dependency.request);
108
+ if (state === undefined || state.invalid) continue;
109
+ const target = connection.module;
110
+ const id =
111
+ dependency.attributes != null && Object.keys(dependency.attributes).length > 0
112
+ ? null
113
+ : identifier(target);
114
+ if (id === null || (state.id !== null && state.id !== id)) {
115
+ state.invalid = true;
116
+ state.target = null;
117
+ invalid++;
118
+ if (invalid === states.size) break;
119
+ continue;
120
+ }
121
+ state.id = id;
122
+ state.target = target;
123
+ }
124
+ for (const [request, state] of states) {
125
+ states.set(request, state.invalid ? null : state.target);
126
+ }
127
+ return states;
128
+ }
129
+
97
130
  function sortedStrings(values) {
98
131
  return [...new Set([...iterable(values)].filter((value) => typeof value === 'string'))].sort();
99
132
  }
@@ -175,8 +208,7 @@ function sameStrings(left, right) {
175
208
  return a.length === b.length && a.every((value, index) => value === b[index]);
176
209
  }
177
210
 
178
- function verifyTarget(compilation, importer, entry) {
179
- const target = targetForRequest(compilation, importer, entry.request);
211
+ function verifyResolvedTarget(importer, entry, target) {
180
212
  if (identifier(target) !== entry.id)
181
213
  changed(identifier(importer), entry.request, 'the effective module identity differs');
182
214
  if (!JAVASCRIPT_TYPES.has(target.type))
@@ -187,23 +219,32 @@ function verifyTarget(compilation, importer, entry) {
187
219
  }
188
220
  }
189
221
 
222
+ function verifyTarget(compilation, importer, entry) {
223
+ verifyResolvedTarget(importer, entry, targetForRequest(compilation, importer, entry.request));
224
+ }
225
+
190
226
  function verifyGraph(compilation, state) {
191
227
  if (state.receipts.size === 0) return;
192
228
  const modules = currentModules(compilation.modules);
193
229
  for (const [id, receipt] of state.receipts) {
194
230
  const importer = modules.get(id);
195
231
  const info = candidateInfo(importer);
232
+ const requests = receipt.imports.map((entry) => entry.request);
196
233
  if (
197
234
  info === null ||
198
235
  info.sourceHash !== receipt.sourceHash ||
199
- !sameStrings(
200
- info.consumed,
201
- receipt.imports.map((entry) => entry.request),
202
- )
236
+ !sameStrings(info.consumed, requests)
203
237
  ) {
204
238
  changed(id, undefined, 'the authored importer or committed-use receipt differs');
205
239
  }
206
- for (const entry of receipt.imports) verifyTarget(compilation, importer, entry);
240
+ if (receipt.imports.length === 1) {
241
+ verifyTarget(compilation, importer, receipt.imports[0]);
242
+ } else {
243
+ const targets = targetsForRequests(compilation, importer, requests);
244
+ for (const entry of receipt.imports) {
245
+ verifyResolvedTarget(importer, entry, targets.get(entry.request));
246
+ }
247
+ }
207
248
  }
208
249
  }
209
250
 
@@ -251,8 +292,14 @@ async function collectAndRebuild(compilation, state, option, environment) {
251
292
  const importer = modules.get(id);
252
293
  const info = candidateInfo(importer);
253
294
  const imports = [];
254
- for (const request of [...new Set(info.requests)].sort()) {
255
- const target = targetForRequest(compilation, importer, request);
295
+ const requests = [...new Set(info.requests)].sort();
296
+ const targets =
297
+ requests.length === 1 ? null : targetsForRequests(compilation, importer, requests);
298
+ for (const request of requests) {
299
+ const target =
300
+ targets === null
301
+ ? targetForRequest(compilation, importer, request)
302
+ : targets.get(request);
256
303
  if (target === null) continue;
257
304
  const proof = readTargetProof(target, option, environment, cache);
258
305
  if (proof !== null) imports.push({ request, ...proof });
package/src/loader.js CHANGED
@@ -118,6 +118,7 @@ export default function octaneLoader(source, inputSourceMap) {
118
118
  root,
119
119
  profile,
120
120
  ...(options.strong === undefined ? null : { strong: options.strong }),
121
+ ...(options.nativeReads === undefined ? null : { nativeReads: options.nativeReads }),
121
122
  ...(options.exclude === undefined ? null : { exclude: options.exclude }),
122
123
  ...(compilerOptions.renderers === undefined
123
124
  ? null
package/src/plugin.js CHANGED
@@ -177,6 +177,7 @@ function createDiscoveryCompiler(options, root, profile, specialization) {
177
177
  root,
178
178
  profile,
179
179
  ...(options.strong === undefined ? null : { strong: options.strong }),
180
+ ...(options.nativeReads === undefined ? null : { nativeReads: options.nativeReads }),
180
181
  ...(options.exclude === undefined ? null : { exclude: options.exclude }),
181
182
  ...(renderers === undefined ? null : { renderers }),
182
183
  ...(universalRuntime === undefined ? null : { universalRuntime }),
@@ -367,6 +368,7 @@ export class OctaneRspackPlugin {
367
368
  dev,
368
369
  profile,
369
370
  strong: this.options.strong === true,
371
+ nativeReads: this.options.nativeReads === true,
370
372
  exclude: this.options.exclude ?? [],
371
373
  renderers: this.options.renderers?.signature,
372
374
  runtime: this.options.runtime,
@@ -407,6 +409,9 @@ export class OctaneRspackPlugin {
407
409
  environment,
408
410
  profile,
409
411
  ...(this.options.strong === undefined ? null : { strong: this.options.strong }),
412
+ ...(this.options.nativeReads === undefined
413
+ ? null
414
+ : { nativeReads: this.options.nativeReads }),
410
415
  ...(this.options.hmr === undefined ? null : { hmr: this.options.hmr }),
411
416
  ...(this.options.dev === undefined ? null : { dev: this.options.dev }),
412
417
  ...(this.options.exclude === undefined ? null : { exclude: this.options.exclude }),
package/src/shared.js CHANGED
@@ -41,6 +41,7 @@ const LOADER_OPTION_KEYS = new Set([
41
41
  'dev',
42
42
  'profile',
43
43
  'strong',
44
+ 'nativeReads',
44
45
  'exclude',
45
46
  'renderers',
46
47
  'requireDirective',
@@ -208,6 +209,7 @@ function normalizeOptions(value, plugin) {
208
209
  assertBooleanOption(options, 'dev');
209
210
  assertBooleanOption(options, 'profile');
210
211
  assertBooleanOption(options, 'strong');
212
+ assertBooleanOption(options, 'nativeReads');
211
213
  assertBooleanOption(options, 'requireDirective');
212
214
  if (
213
215
  options.exclude !== undefined &&
@@ -239,6 +241,7 @@ function normalizeOptions(value, plugin) {
239
241
  ...(options.dev === undefined ? null : { dev: options.dev }),
240
242
  ...(options.profile === undefined ? null : { profile: options.profile }),
241
243
  ...(options.strong === undefined ? null : { strong: options.strong }),
244
+ ...(options.nativeReads === undefined ? null : { nativeReads: options.nativeReads }),
242
245
  ...(options.exclude === undefined ? null : { exclude: [...options.exclude] }),
243
246
  ...(renderers === undefined ? null : { renderers }),
244
247
  ...(universalRuntime === undefined ? null : { universalRuntime }),
package/types/index.d.ts CHANGED
@@ -144,6 +144,8 @@ export interface OctaneRspackLoaderOptions {
144
144
  * @default false
145
145
  */
146
146
  strong?: boolean;
147
+ /** Experimental native signal reads in DOM client/server render scopes. */
148
+ nativeReads?: boolean;
147
149
  /**
148
150
  * Path fragments excluded from the plain `.ts`/`.js` hook-slot pass. With
149
151
  * `requireDirective`, excluded paths are exempt from Octane ownership