@stencil/core 5.0.0-alpha.3 → 5.0.0-alpha.31

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 (56) hide show
  1. package/README.md +94 -0
  2. package/dist/app-data/index.d.ts +2 -0
  3. package/dist/{runtime/app-data → app-data}/index.js +17 -11
  4. package/dist/{client-CSm3x5ke.mjs → client-D1MsT-Rp.mjs} +2717 -2424
  5. package/dist/compiler/index.d.mts +170 -6
  6. package/dist/compiler/index.mjs +4 -3
  7. package/dist/compiler/utils/index.d.mts +272 -2
  8. package/dist/compiler/utils/index.mjs +4 -3
  9. package/dist/{compiler-D6iP7Bzb.mjs → compiler-Cddp97Pg.mjs} +14953 -12327
  10. package/dist/declarations/stencil-ext-modules.d.ts +5 -5
  11. package/dist/declarations/stencil-public-compiler.d.ts +728 -287
  12. package/dist/declarations/stencil-public-compiler.js +2 -3
  13. package/dist/declarations/stencil-public-docs.d.ts +19 -0
  14. package/dist/declarations/stencil-public-runtime.d.ts +131 -17
  15. package/dist/fragment-Di1hWOC8.mjs +4 -0
  16. package/dist/{index-tUR6pD3J.d.mts → index-BHj3EBl2.d.mts} +1052 -668
  17. package/dist/{index-CyrGY82h.d.ts → index-D2PAsXxx.d.ts} +215 -40
  18. package/dist/index-VK8okIiF.d.mts +108 -0
  19. package/dist/index.d.mts +4 -1
  20. package/dist/index.mjs +91 -2
  21. package/dist/jsx-runtime.d.mts +18 -0
  22. package/dist/jsx-runtime.mjs +3 -0
  23. package/dist/{node-Bg-mO5dw.mjs → node-BQR4L-TG.mjs} +76 -73
  24. package/dist/reactive-controller-BdCpSAQP.d.mts +13 -0
  25. package/dist/{regular-expression-D5pGVpCu.mjs → regular-expression-XqU5zmPp.mjs} +141 -31
  26. package/dist/{chunk-CjcI7cDX.mjs → rolldown-runtime-BhDjJH2R.mjs} +1 -1
  27. package/dist/{runtime-BBCnuprF.js → runtime/client/lazy.js} +2987 -2443
  28. package/dist/runtime/client/{index.d.ts → runtime.d.ts} +228 -83
  29. package/dist/runtime/client/{index.js → runtime.js} +2852 -2432
  30. package/dist/runtime/index.d.ts +48 -29
  31. package/dist/runtime/index.js +5069 -2
  32. package/dist/runtime/server/index.d.mts +182 -75
  33. package/dist/runtime/server/index.mjs +2769 -2283
  34. package/dist/runtime/server/runner.d.mts +47 -32
  35. package/dist/runtime/server/runner.mjs +563 -687
  36. package/dist/signals/index.d.ts +49 -0
  37. package/dist/signals/index.js +199 -0
  38. package/dist/sys/node/index.d.mts +1 -2
  39. package/dist/sys/node/index.mjs +1 -1
  40. package/dist/sys/node/worker.d.mts +1 -1
  41. package/dist/sys/node/worker.mjs +6 -3
  42. package/dist/testing/index.d.mts +98 -9
  43. package/dist/testing/index.mjs +395 -70
  44. package/dist/util-BIa-iHnt.mjs +724 -0
  45. package/dist/validation-Dd3g77T5.mjs +778 -0
  46. package/package.json +49 -36
  47. package/dist/index-CXHCTQNt.d.mts +0 -190
  48. package/dist/index-hS-KBdAP.d.ts +0 -30
  49. package/dist/jsx-runtime-DlDkTqps.d.ts +0 -28
  50. package/dist/jsx-runtime.d.ts +0 -2
  51. package/dist/jsx-runtime.js +0 -2
  52. package/dist/runtime/app-data/index.d.ts +0 -2
  53. package/dist/validation-Byxie0Uk.mjs +0 -1445
  54. /package/{LICENSE.md → LICENSE} +0 -0
  55. /package/dist/{runtime/app-globals → app-globals}/index.d.ts +0 -0
  56. /package/dist/{runtime/app-globals → app-globals}/index.js +0 -0
@@ -1,10 +1,13 @@
1
- import { B as BUILD, E as reWireGetterSetter, V as Env, _ as getElement, a as Mixin, b as setAssetPath, c as forceUpdate, d as createEvent, f as getMode, g as h, h as Host, l as getRenderingRef, o as Fragment, s as bootstrapLazy, t as insertVdomAnnotations, u as renderVdom, y as getAssetPath } from "../client-CSm3x5ke.mjs";
2
- import { C as CMP_FLAGS, V as EVENT_FLAGS, h as noop } from "../regular-expression-D5pGVpCu.mjs";
3
- import { _ as getBuildFeatures, c as createWorkerContext, h as BuildContext, i as createSystem, m as Cache, p as createInMemoryFs } from "../compiler-D6iP7Bzb.mjs";
4
- import { St as formatLazyBundleRuntimeMeta } from "../validation-Byxie0Uk.mjs";
5
- import { o as buildEvents } from "../node-Bg-mO5dw.mjs";
6
- import path from "node:path";
7
- import path$1 from "path";
1
+ import { A as HYDRATE_ID, C as setAssetPath, D as DEFAULT_DOC_DATA, F as reWireGetterSetter, L as BUILD, M as STENCIL_DOC_DATA, P as getHostRef$1, R as Env, S as getAssetPath, _ as insertBefore, b as getElement, c as Mixin, g as getRenderingRef, h as forceUpdate, j as NODE_TYPE, k as HYDRATE_CHILD_ID, l as bootstrapLazy, m as h, p as Host, s as ReactiveControllerHost, u as getMode, v as renderVdom, y as createEvent } from "../client-D1MsT-Rp.mjs";
2
+ import { R as EVENT_FLAGS, h as noop, w as CMP_FLAGS } from "../regular-expression-XqU5zmPp.mjs";
3
+ import { t as Fragment } from "../fragment-Di1hWOC8.mjs";
4
+ import { b as getBuildFeatures, c as createWorkerContext, h as Cache, i as createSystem, o as loadConfig, p as createInMemoryFs, s as createCompiler, v as BuildContext } from "../compiler-Cddp97Pg.mjs";
5
+ import { C as formatLazyBundleRuntimeMeta } from "../validation-Dd3g77T5.mjs";
6
+ import { o as buildEvents } from "../node-BQR4L-TG.mjs";
7
+ import fs from "node:fs";
8
+ import nodePath from "node:path";
9
+ import { fileURLToPath } from "node:url";
10
+ import path from "path";
8
11
  import { MockWindow, setupGlobal } from "@stencil/mock-doc";
9
12
  import { createHash } from "crypto";
10
13
  import { afterAll, vi } from "vitest";
@@ -86,7 +89,7 @@ const createTestingSystem = () => {
86
89
  let diskReads = 0;
87
90
  let diskWrites = 0;
88
91
  const sys = createSystem();
89
- sys.platformPath = path$1;
92
+ sys.platformPath = path;
90
93
  sys.generateContentHash = (content, length) => {
91
94
  let hash = createHash("sha1").update(content).digest("hex").toLowerCase();
92
95
  if (typeof length === "number") hash = hash.slice(0, length);
@@ -223,9 +226,11 @@ const mockComponentMeta = (overrides = {}) => ({
223
226
  hasVdomStyle: false,
224
227
  hasVdomText: false,
225
228
  hasVdomXlink: false,
229
+ hasSignalsImport: false,
226
230
  hasWatchCallback: false,
227
231
  htmlAttrNames: [],
228
232
  htmlParts: [],
233
+ htmlSlots: [],
229
234
  htmlTagNames: [],
230
235
  internal: false,
231
236
  isCollectionDependency: false,
@@ -246,6 +251,7 @@ const mockComponentMeta = (overrides = {}) => ({
246
251
  states: [],
247
252
  styleDocs: [],
248
253
  styles: [],
254
+ globalStyles: [],
249
255
  tagName: "stub-cmp",
250
256
  virtualProperties: [],
251
257
  watchers: [],
@@ -260,16 +266,17 @@ const mockComponentMeta = (overrides = {}) => ({
260
266
  */
261
267
  function mockValidatedConfig(overrides = {}) {
262
268
  const baseConfig = mockConfig(overrides);
263
- const rootDir = path.resolve("/");
269
+ const rootDir = nodePath.resolve("/");
264
270
  return {
265
271
  ...baseConfig,
266
272
  cacheDir: ".stencil",
267
273
  devMode: true,
268
274
  devServer: {},
269
- extras: {},
275
+ compat: {
276
+ suppressPublicNameWarnings: false,
277
+ suppressEventNameWarnings: false
278
+ },
270
279
  fsNamespace: "testing",
271
- hashFileNames: false,
272
- hashedFileNameLength: 8,
273
280
  hydratedFlag: null,
274
281
  logLevel: "info",
275
282
  logger: mockLogger(),
@@ -277,19 +284,14 @@ function mockValidatedConfig(overrides = {}) {
277
284
  minifyJs: false,
278
285
  namespace: "Testing",
279
286
  outputTargets: baseConfig.outputTargets ?? [],
280
- packageJsonFilePath: path.join(rootDir, "package.json"),
287
+ packageJsonFilePath: nodePath.join(rootDir, "package.json"),
281
288
  rootDir,
282
289
  sourceMap: true,
283
290
  srcDir: "/src",
284
291
  srcIndexHtml: "src/index.html",
285
- suppressReservedPublicNameWarnings: false,
286
292
  sys: createTestingSystem(),
287
293
  transformAliasedImportPaths: true,
288
- rolldownConfig: {
289
- inputOptions: {},
290
- outputOptions: {}
291
- },
292
- validatePrimaryPackageOutputTarget: false,
294
+ rolldownConfig: {},
293
295
  ...overrides
294
296
  };
295
297
  }
@@ -301,20 +303,21 @@ function mockValidatedConfig(overrides = {}) {
301
303
  * @returns the mock Stencil configuration
302
304
  */
303
305
  function mockConfig(overrides = {}) {
304
- const rootDir = path.resolve("/");
306
+ const rootDir = nodePath.resolve("/");
305
307
  let { sys } = overrides;
306
308
  if (!sys) sys = createTestingSystem();
307
309
  sys.getCurrentDirectory = () => rootDir;
308
310
  return {
309
311
  _isTesting: true,
310
312
  buildAppCore: false,
311
- buildDist: true,
312
313
  bundles: null,
313
314
  devMode: true,
314
315
  enableCache: false,
315
- extras: {},
316
+ compat: {
317
+ suppressPublicNameWarnings: false,
318
+ suppressEventNameWarnings: false
319
+ },
316
320
  globalScript: null,
317
- hashFileNames: false,
318
321
  logger: new TestingLogger(),
319
322
  maxConcurrentWorkers: 0,
320
323
  minifyCss: false,
@@ -328,7 +331,6 @@ function mockConfig(overrides = {}) {
328
331
  },
329
332
  rootDir,
330
333
  sourceMap: true,
331
- suppressReservedPublicNameWarnings: false,
332
334
  sys,
333
335
  validateTypes: false,
334
336
  ...overrides
@@ -348,7 +350,6 @@ const mockLoadConfigInit = (overrides) => {
348
350
  return {
349
351
  config: {},
350
352
  configPath: void 0,
351
- initTsConfig: true,
352
353
  logger: void 0,
353
354
  sys: void 0,
354
355
  ...overrides
@@ -366,7 +367,7 @@ function mockCompilerCtx(config) {
366
367
  activeFilesUpdated: [],
367
368
  addWatchDir: noop,
368
369
  addWatchFile: noop,
369
- cachedGlobalStyle: null,
370
+ globalStyleCache: /* @__PURE__ */ new Map(),
370
371
  changedFiles: /* @__PURE__ */ new Set(),
371
372
  changedModules: /* @__PURE__ */ new Set(),
372
373
  collections: [],
@@ -383,11 +384,14 @@ function mockCompilerCtx(config) {
383
384
  reset: noop,
384
385
  resolvedCollections: /* @__PURE__ */ new Set(),
385
386
  rolldownCache: /* @__PURE__ */ new Map(),
386
- rolldownCacheHydrate: null,
387
+ rolldownCacheSsr: null,
387
388
  rolldownCacheLazy: null,
388
389
  rolldownCacheNative: null,
390
+ transpileCache: /* @__PURE__ */ new Map(),
391
+ prevStylesMap: /* @__PURE__ */ new Map(),
389
392
  styleModeNames: /* @__PURE__ */ new Set(),
390
- worker: createWorkerContext(innerConfig.sys)
393
+ worker: createWorkerContext(innerConfig.sys),
394
+ cssTransformCache: /* @__PURE__ */ new Map()
391
395
  };
392
396
  Object.defineProperty(compilerCtx, "fs", { get() {
393
397
  if (this._fs == null) this._fs = createInMemoryFs(innerConfig.sys);
@@ -401,7 +405,8 @@ function mockCompilerCtx(config) {
401
405
  }
402
406
  function mockBuildCtx(config, compilerCtx) {
403
407
  const validatedConfig = config || mockValidatedConfig();
404
- return new BuildContext(validatedConfig, compilerCtx || mockCompilerCtx(validatedConfig));
408
+ const validatedCompilerCtx = compilerCtx || mockCompilerCtx(validatedConfig);
409
+ return new BuildContext(validatedConfig, validatedCompilerCtx);
405
410
  }
406
411
  function mockCache(config, compilerCtx) {
407
412
  config.enableCache = true;
@@ -453,6 +458,7 @@ const mockModule = (mod = {}) => ({
453
458
  htmlAttrNames: [],
454
459
  htmlTagNames: [],
455
460
  htmlParts: [],
461
+ htmlSlots: [],
456
462
  isCollectionDependency: false,
457
463
  isLegacy: false,
458
464
  jsFilePath: "",
@@ -477,9 +483,173 @@ const mockModule = (mod = {}) => ({
477
483
  hasVdomStyle: false,
478
484
  hasVdomText: false,
479
485
  hasVdomXlink: false,
486
+ hasSignalsImport: false,
480
487
  ...mod
481
488
  });
482
489
  //#endregion
490
+ //#region src/testing/create-test-compiler.ts
491
+ const __dirname = nodePath.dirname(fileURLToPath(import.meta.url));
492
+ const TESTING_TSCONFIG = nodePath.resolve(__dirname, "fixtures/tsconfig.testing.json");
493
+ /**
494
+ * Builds a patched sys that falls through to real disk for TypeScript lib files.
495
+ *
496
+ * @returns A compiler system instance with patched readFileSync, readFile, accessSync, and statSync methods
497
+ */
498
+ const createPatchedSys = () => {
499
+ const sys = mockCompilerSystem();
500
+ const originalReadFileSync = sys.readFileSync.bind(sys);
501
+ sys.readFileSync = (p) => {
502
+ const mem = originalReadFileSync(p);
503
+ if (mem !== void 0) return mem;
504
+ try {
505
+ return fs.readFileSync(p, "utf-8");
506
+ } catch {
507
+ return;
508
+ }
509
+ };
510
+ const originalReadFile = sys.readFile.bind(sys);
511
+ sys.readFile = async (p) => {
512
+ const mem = await originalReadFile(p);
513
+ if (mem !== void 0) return mem;
514
+ try {
515
+ return fs.readFileSync(p, "utf-8");
516
+ } catch {
517
+ return;
518
+ }
519
+ };
520
+ const originalAccessSync = sys.accessSync.bind(sys);
521
+ sys.accessSync = (p) => {
522
+ if (originalAccessSync(p)) return true;
523
+ try {
524
+ fs.accessSync(p);
525
+ return true;
526
+ } catch {
527
+ return false;
528
+ }
529
+ };
530
+ const originalStatSync = sys.statSync.bind(sys);
531
+ sys.statSync = (p) => {
532
+ const mem = originalStatSync(p);
533
+ if (!mem.error) return mem;
534
+ try {
535
+ const s = fs.statSync(p);
536
+ return {
537
+ isDirectory: s.isDirectory(),
538
+ isFile: s.isFile(),
539
+ isSymbolicLink: s.isSymbolicLink(),
540
+ size: s.size,
541
+ error: null
542
+ };
543
+ } catch {
544
+ return mem;
545
+ }
546
+ };
547
+ sys.getCompilerExecutingPath = () => nodePath.resolve(__dirname, "../../dist/compiler/index.mjs");
548
+ return sys;
549
+ };
550
+ /**
551
+ * Runs the expensive one-time setup for a test compiler suite: patching the
552
+ * sys, reading and validating the tsconfig. Use this in a `beforeAll` block
553
+ * when a describe block contains multiple tests that each need a fresh
554
+ * compiler, to avoid repeating `loadConfig` on every test.
555
+ *
556
+ * @param options - Configuration options for preparing the test compiler
557
+ * @returns A {@link PreparedTestCompiler} that can be passed to {@link createTestCompiler}
558
+ *
559
+ * @example
560
+ * ```ts
561
+ * let setup: PreparedTestCompiler;
562
+ * beforeAll(async () => { setup = await prepareTestCompiler(); });
563
+ * beforeEach(async () => {
564
+ * const { compiler } = await createTestCompiler({ setup });
565
+ * });
566
+ * ```
567
+ */
568
+ const prepareTestCompiler = async (options = {}) => {
569
+ const sys = createPatchedSys();
570
+ const tsconfigPath = options.tsconfig ?? TESTING_TSCONFIG;
571
+ const userConfig = {
572
+ devMode: true,
573
+ sourceMap: false,
574
+ enableCache: false,
575
+ minifyJs: false,
576
+ minifyCss: false,
577
+ namespace: "Testing",
578
+ tsconfig: tsconfigPath,
579
+ ...options.config
580
+ };
581
+ const { config: validatedConfig } = await loadConfig({
582
+ sys,
583
+ config: userConfig
584
+ });
585
+ return {
586
+ _validatedConfig: validatedConfig,
587
+ _tsconfigPath: tsconfigPath
588
+ };
589
+ };
590
+ /**
591
+ * Creates a test compiler instance with a hybrid filesystem (reads from disk, writes to memory).
592
+ * This utility handles the common setup pattern for compiler tests.
593
+ *
594
+ * When multiple tests in the same suite need independent compiler instances,
595
+ * pass a {@link PreparedTestCompiler} from {@link prepareTestCompiler} as
596
+ * `options.setup` to skip the expensive `loadConfig` step on each test.
597
+ *
598
+ * @param options - Configuration options for the test compiler
599
+ * @returns An object with the compiler, validated config, and system instance
600
+ *
601
+ * @example
602
+ * ```ts
603
+ * const { compiler, config } = await createTestCompiler({
604
+ * config: { minifyCss: true }
605
+ * });
606
+ * await compiler.fs.writeFile('/src/index.html', '<cmp-a></cmp-a>');
607
+ * const result = await compiler.build();
608
+ * ```
609
+ */
610
+ const createTestCompiler = async (options = {}) => {
611
+ let validatedConfig;
612
+ let tsconfigPath;
613
+ if (options.setup) {
614
+ const freshSys = createPatchedSys();
615
+ validatedConfig = {
616
+ ...options.setup._validatedConfig,
617
+ sys: freshSys
618
+ };
619
+ tsconfigPath = options.setup._tsconfigPath;
620
+ } else {
621
+ const sys = createPatchedSys();
622
+ tsconfigPath = options.tsconfig ?? TESTING_TSCONFIG;
623
+ const userConfig = {
624
+ devMode: true,
625
+ sourceMap: false,
626
+ enableCache: false,
627
+ minifyJs: false,
628
+ minifyCss: false,
629
+ namespace: "Testing",
630
+ tsconfig: tsconfigPath,
631
+ ...options.config
632
+ };
633
+ const { config } = await loadConfig({
634
+ sys,
635
+ config: userConfig
636
+ });
637
+ validatedConfig = config;
638
+ }
639
+ const compiler = await createCompiler(validatedConfig);
640
+ const tsconfigObj = JSON.parse(fs.readFileSync(tsconfigPath, "utf-8"));
641
+ await compiler.fs.writeFile(tsconfigPath, JSON.stringify({
642
+ ...tsconfigObj,
643
+ include: [validatedConfig.srcDir]
644
+ }));
645
+ await compiler.fs.writeFile(nodePath.join(validatedConfig.srcDir, "components.d.ts"), "");
646
+ return {
647
+ compiler,
648
+ config: validatedConfig,
649
+ sys: validatedConfig.sys
650
+ };
651
+ };
652
+ //#endregion
483
653
  //#region src/testing/platform/testing-constants.ts
484
654
  const styles = /* @__PURE__ */ new Map();
485
655
  const modeResolutionChain = [];
@@ -515,7 +685,7 @@ const Build = {
515
685
  * @returns the corresponding Stencil reference data structure, or undefined if one cannot be found
516
686
  */
517
687
  const getHostRef = (elm) => {
518
- if (elm.__stencil__getHostRef) return elm.__stencil__getHostRef();
688
+ if (elm.__s_ghr) return elm.__s_ghr();
519
689
  };
520
690
  /**
521
691
  * Add the provided `hostRef` instance to the global {@link hostRefs} map, using the provided `lazyInstance` as a key.
@@ -536,7 +706,7 @@ const registerInstance = (lazyInstance, hostRef) => {
536
706
  });
537
707
  hostRef = getHostRef(elm);
538
708
  }
539
- lazyInstance.__stencil__getHostRef = () => hostRef;
709
+ lazyInstance.__s_ghr = () => hostRef;
540
710
  hostRef.$lazyInstance$ = lazyInstance;
541
711
  if (hostRef.$cmpMeta$?.$flags$ & CMP_FLAGS.hasModernPropertyDecls && (BUILD.state || BUILD.prop)) reWireGetterSetter(lazyInstance, hostRef);
542
712
  const Cstr = lazyInstance.constructor;
@@ -587,7 +757,7 @@ const registerHost = (elm, cmpMeta) => {
587
757
  hostRef.$onReadyPromise$ = new Promise((r) => hostRef.$onReadyResolve$ = r);
588
758
  elm["s-p"] = [];
589
759
  elm["s-rc"] = [];
590
- elm.__stencil__getHostRef = () => hostRef;
760
+ elm.__s_ghr = () => hostRef;
591
761
  };
592
762
  const setErrorHandler = (handler) => handler;
593
763
  //#endregion
@@ -727,6 +897,8 @@ function flushLoadModule(bundleId) {
727
897
  const isVitestEnvironment = typeof process !== "undefined" && process.env?.VITEST;
728
898
  const existingWindow = typeof globalThis !== "undefined" && globalThis.window;
729
899
  const win = isVitestEnvironment && existingWindow ? existingWindow : setupGlobal(global);
900
+ //#endregion
901
+ //#region src/testing/platform/testing-platform.ts
730
902
  const plt = {
731
903
  $flags$: 0,
732
904
  $resourcesUrl$: "",
@@ -737,14 +909,6 @@ const plt = {
737
909
  ce: (eventName, opts) => new win.CustomEvent(eventName, opts)
738
910
  };
739
911
  /**
740
- * Helper function to programmatically set shadow DOM support in testing scenarios.
741
- *
742
- * This function modifies the global {@link supportsShadow} variable.
743
- *
744
- * @param supports `true` if shadow DOM is supported, `false` otherwise
745
- */
746
- const setSupportsShadowDom = (supports) => {};
747
- /**
748
912
  * Resets global testing variables and collections, so that a new set of tests can be started with a "clean slate".
749
913
  *
750
914
  * It is expected that this function be called between spec tests, and should be automatically configured by Stencil to
@@ -808,6 +972,162 @@ function registerModule(bundleId, Cstr) {
808
972
  moduleLoaded.set(bundleId, Cstr);
809
973
  }
810
974
  //#endregion
975
+ //#region src/runtime/vdom/vdom-annotations.ts
976
+ /**
977
+ * Updates the DOM generated on the server with annotations such as node attributes and
978
+ * comment nodes to facilitate future client-side hydration. These annotations are used for things
979
+ * like moving elements back to their original hosts if using Shadow DOM on the client, and for quickly
980
+ * reconstructing the vNode representations of the DOM.
981
+ *
982
+ * @param doc The DOM generated by the server.
983
+ * @param staticComponents Any components that should be considered static and do not need client-side hydration.
984
+ */
985
+ const insertVdomAnnotations = (doc, staticComponents) => {
986
+ if (doc != null) {
987
+ /**
988
+ * Initiated `docData` object from the document if it exists to ensure we
989
+ * maintain the same `docData` object across multiple hydration hydration runs.
990
+ */
991
+ const docData = "_stencilDocData" in doc ? doc[STENCIL_DOC_DATA] : { ...DEFAULT_DOC_DATA };
992
+ docData.staticComponents = new Set(staticComponents);
993
+ const orgLocationNodes = [];
994
+ parseVNodeAnnotations(doc, doc.body, docData, orgLocationNodes);
995
+ orgLocationNodes.forEach((orgLocationNode) => {
996
+ if (orgLocationNode != null && orgLocationNode["s-nr"]) {
997
+ const nodeRef = orgLocationNode["s-nr"];
998
+ let hostId = nodeRef["s-host-id"];
999
+ let nodeId = nodeRef["s-node-id"];
1000
+ let childId = `${hostId}.${nodeId}`;
1001
+ if (hostId == null) {
1002
+ hostId = 0;
1003
+ docData.rootLevelIds++;
1004
+ nodeId = docData.rootLevelIds;
1005
+ childId = `${hostId}.${nodeId}`;
1006
+ if (nodeRef.nodeType === NODE_TYPE.ElementNode) {
1007
+ nodeRef.setAttribute(HYDRATE_CHILD_ID, childId);
1008
+ if (typeof nodeRef["s-sn"] === "string" && !nodeRef.getAttribute("slot")) nodeRef.setAttribute("s-sn", nodeRef["s-sn"]);
1009
+ } else if (nodeRef.nodeType === NODE_TYPE.TextNode) {
1010
+ if (hostId === 0) {
1011
+ if (nodeRef.nodeValue?.trim() === "") {
1012
+ orgLocationNode.remove();
1013
+ return;
1014
+ }
1015
+ }
1016
+ const commentBeforeTextNode = doc.createComment(childId);
1017
+ commentBeforeTextNode.nodeValue = `t.${childId}`;
1018
+ insertBefore(nodeRef.parentNode, commentBeforeTextNode, nodeRef);
1019
+ } else if (nodeRef.nodeType === NODE_TYPE.CommentNode) {
1020
+ const commentBeforeTextNode = doc.createComment(childId);
1021
+ commentBeforeTextNode.nodeValue = `c.${childId}`;
1022
+ nodeRef.parentNode.insertBefore(commentBeforeTextNode, nodeRef);
1023
+ }
1024
+ }
1025
+ let orgLocationNodeId = `o.${childId}`;
1026
+ const orgLocationParentNode = orgLocationNode.parentElement;
1027
+ if (orgLocationParentNode) {
1028
+ if (orgLocationParentNode["s-en"] === "") orgLocationNodeId += `.`;
1029
+ else if (orgLocationParentNode["s-en"] === "c") orgLocationNodeId += `.c`;
1030
+ }
1031
+ orgLocationNode.nodeValue = orgLocationNodeId;
1032
+ }
1033
+ });
1034
+ }
1035
+ };
1036
+ /**
1037
+ * Recursively parses a node generated by the server and its children to set host and child id
1038
+ * attributes read during client-side hydration. This function also tracks whether each node is
1039
+ * an original location reference node meaning that a node has been moved via slot relocation.
1040
+ *
1041
+ * @param doc The DOM generated by the server.
1042
+ * @param node The node to parse.
1043
+ * @param docData An object containing metadata about the document.
1044
+ * @param orgLocationNodes An array of nodes that have been moved via slot relocation.
1045
+ */
1046
+ const parseVNodeAnnotations = (doc, node, docData, orgLocationNodes) => {
1047
+ if (node == null) return;
1048
+ if (node["s-nr"] != null) orgLocationNodes.push(node);
1049
+ if (node.nodeType === NODE_TYPE.ElementNode) [...Array.from(node.childNodes), ...Array.from(node.shadowRoot?.childNodes || [])].forEach((childNode) => {
1050
+ const hostRef = getHostRef$1(childNode);
1051
+ if (hostRef != null && !docData.staticComponents.has(childNode.nodeName.toLowerCase())) insertVNodeAnnotations(doc, childNode, hostRef.$vnode$, docData, { nodeIds: 0 });
1052
+ parseVNodeAnnotations(doc, childNode, docData, orgLocationNodes);
1053
+ });
1054
+ };
1055
+ /**
1056
+ * Insert attribute annotations on an element for its host ID and, potentially, its child ID.
1057
+ * Also makes calls to insert annotations on the element's children, keeping track of the depth of
1058
+ * the component tree.
1059
+ *
1060
+ * @param doc The DOM generated by the server.
1061
+ * @param hostElm The element to insert annotations for.
1062
+ * @param vnode The vNode representation of the element.
1063
+ * @param docData An object containing metadata about the document.
1064
+ * @param cmpData An object containing metadata about the component.
1065
+ */
1066
+ const insertVNodeAnnotations = (doc, hostElm, vnode, docData, cmpData) => {
1067
+ if (vnode != null) {
1068
+ const hostId = ++docData.hostIds;
1069
+ hostElm.setAttribute(HYDRATE_ID, hostId);
1070
+ if (hostElm["s-cr"] != null) hostElm["s-cr"].nodeValue = `r.${hostId}`;
1071
+ if (vnode.$children$ != null) {
1072
+ const depth = 0;
1073
+ vnode.$children$.forEach((vnodeChild, index) => {
1074
+ insertChildVNodeAnnotations(doc, vnodeChild, cmpData, hostId, depth, index);
1075
+ });
1076
+ }
1077
+ if (hostElm && vnode && vnode.$elm$ && !hostElm.hasAttribute("c-id")) {
1078
+ const parent = hostElm.parentElement;
1079
+ if (parent && parent.childNodes) {
1080
+ const parentChildNodes = Array.from(parent.childNodes);
1081
+ const comment = parentChildNodes.find((node) => node.nodeType === NODE_TYPE.CommentNode && node["s-sr"]);
1082
+ if (comment) {
1083
+ const index = parentChildNodes.indexOf(hostElm) - 1;
1084
+ vnode.$elm$.setAttribute(HYDRATE_CHILD_ID, `${comment["s-host-id"]}.${comment["s-node-id"]}.0.${index}`);
1085
+ }
1086
+ }
1087
+ }
1088
+ }
1089
+ };
1090
+ /**
1091
+ * Recursively analyzes the type of a child vNode and inserts annotations on the vNodes's element based on its type.
1092
+ * Element nodes receive a child ID attribute, text nodes have a comment with the child ID inserted before them,
1093
+ * and comment nodes representing a slot have their node value set to a slot node ID containing the child ID.
1094
+ *
1095
+ * @param doc The DOM generated by the server.
1096
+ * @param vnodeChild The vNode to insert annotations for.
1097
+ * @param cmpData An object containing metadata about the component.
1098
+ * @param hostId The host ID of this element's parent.
1099
+ * @param depth How deep this element sits in the component tree relative to its parent.
1100
+ * @param index The index of this element in its parent's children array.
1101
+ */
1102
+ const insertChildVNodeAnnotations = (doc, vnodeChild, cmpData, hostId, depth, index) => {
1103
+ const childElm = vnodeChild.$elm$;
1104
+ if (childElm == null) return;
1105
+ const nodeId = cmpData.nodeIds++;
1106
+ const childId = `${hostId}.${nodeId}.${depth}.${index}`;
1107
+ childElm["s-host-id"] = hostId;
1108
+ childElm["s-node-id"] = nodeId;
1109
+ if (childElm.nodeType === NODE_TYPE.ElementNode) {
1110
+ childElm.setAttribute(HYDRATE_CHILD_ID, childId);
1111
+ if (typeof childElm["s-sn"] === "string" && !childElm.getAttribute("slot")) childElm.setAttribute("s-sn", childElm["s-sn"]);
1112
+ } else if (childElm.nodeType === NODE_TYPE.TextNode) {
1113
+ const parentNode = childElm.parentNode;
1114
+ const nodeName = parentNode?.nodeName;
1115
+ if (nodeName !== "STYLE" && nodeName !== "SCRIPT") {
1116
+ const textNodeId = `t.${childId}`;
1117
+ const commentBeforeTextNode = doc.createComment(textNodeId);
1118
+ insertBefore(parentNode, commentBeforeTextNode, childElm);
1119
+ }
1120
+ } else if (childElm.nodeType === NODE_TYPE.CommentNode) {
1121
+ if (childElm["s-sr"]) childElm.nodeValue = `s.${childId}.${childElm["s-sn"] || ""}`;
1122
+ }
1123
+ if (vnodeChild.$children$ != null) {
1124
+ const childDepth = depth + 1;
1125
+ vnodeChild.$children$.forEach((vnode, childIndex) => {
1126
+ insertChildVNodeAnnotations(doc, vnode, cmpData, hostId, childDepth, childIndex);
1127
+ });
1128
+ }
1129
+ };
1130
+ //#endregion
811
1131
  //#region src/testing/platform/index.ts
812
1132
  const setMode = (handler) => {
813
1133
  modeResolutionChain.length = 0;
@@ -860,13 +1180,13 @@ function resetBuildConditionals(b) {
860
1180
  b.hydratedAttribute = false;
861
1181
  b.hydratedClass = true;
862
1182
  b.invisiblePrehydration = true;
863
- b.appendChildSlotFix = false;
864
- b.cloneNodeFix = false;
1183
+ b.staticHydrationStyles = false;
1184
+ b.lightDomPatches = false;
1185
+ b.slotChildNodes = false;
1186
+ b.slotCloneNode = false;
1187
+ b.slotDomMutations = false;
1188
+ b.slotTextContent = false;
865
1189
  b.hotModuleReplacement = false;
866
- b.scopedSlotTextContentFix = false;
867
- b.slotChildNodesFix = false;
868
- b.experimentalSlotFixes = false;
869
- b.experimentalScopedSlotChanges = false;
870
1190
  }
871
1191
  //#endregion
872
1192
  //#region src/testing/spec-page.ts
@@ -886,14 +1206,8 @@ async function newSpecPage(opts) {
886
1206
  resetBuildConditionals(BUILD);
887
1207
  if (Array.isArray(opts.components)) registerComponents(opts.components);
888
1208
  if (opts.hydrateClientSide) opts.includeAnnotations = true;
889
- if (opts.hydrateServerSide) {
890
- opts.includeAnnotations = true;
891
- setSupportsShadowDom(false);
892
- } else {
893
- opts.includeAnnotations = !!opts.includeAnnotations;
894
- if (opts.supportsShadowDom === false) setSupportsShadowDom(false);
895
- else setSupportsShadowDom(true);
896
- }
1209
+ if (opts.hydrateServerSide) opts.includeAnnotations = true;
1210
+ else opts.includeAnnotations = !!opts.includeAnnotations;
897
1211
  BUILD.cssAnnotations = opts.includeAnnotations;
898
1212
  const cmpTags = /* @__PURE__ */ new Set();
899
1213
  win["__stencil_spec_options"] = opts;
@@ -916,7 +1230,13 @@ async function newSpecPage(opts) {
916
1230
  /**
917
1231
  * just pass through functional components that don't have styles nor any other metadata
918
1232
  */
919
- if (Cstr.COMPILER_META == null) return formatLazyBundleRuntimeMeta(`fc.${generateRandBundleId()}`, []);
1233
+ if (Cstr.COMPILER_META == null) {
1234
+ /**
1235
+ * the bundleId can be arbitrary, but must be unique
1236
+ */
1237
+ const arbitraryBundleId = `fc.${generateRandBundleId()}`;
1238
+ return formatLazyBundleRuntimeMeta(arbitraryBundleId, []);
1239
+ }
920
1240
  cmpTags.add(Cstr.COMPILER_META.tagName);
921
1241
  Cstr.isProxied = false;
922
1242
  proxyComponentLifeCycles(Cstr);
@@ -934,7 +1254,8 @@ async function newSpecPage(opts) {
934
1254
  registerModule(bundleId, Cstr);
935
1255
  return formatLazyBundleRuntimeMeta(bundleId, [Cstr.COMPILER_META]);
936
1256
  });
937
- const cmpBuild = getBuildFeatures(opts.components.filter((Cstr) => Cstr.COMPILER_META != null).map((Cstr) => Cstr.COMPILER_META));
1257
+ const cmpCompilerMeta = opts.components.filter((Cstr) => Cstr.COMPILER_META != null).map((Cstr) => Cstr.COMPILER_META);
1258
+ const cmpBuild = getBuildFeatures(cmpCompilerMeta);
938
1259
  if (opts.strictBuild) Object.assign(BUILD, cmpBuild);
939
1260
  else Object.keys(cmpBuild).forEach((key) => {
940
1261
  if (cmpBuild[key] === true) BUILD[key] = true;
@@ -947,9 +1268,8 @@ async function newSpecPage(opts) {
947
1268
  BUILD.hydrateServerSide = true;
948
1269
  BUILD.hydrateClientSide = false;
949
1270
  }
950
- BUILD.cloneNodeFix = false;
951
- BUILD.shadowDomShim = false;
952
- BUILD.attachStyles = !!opts.attachStyles;
1271
+ BUILD.slotCloneNode = false;
1272
+ if (opts.buildFlags) Object.assign(BUILD, opts.buildFlags);
953
1273
  if (typeof opts.url === "string") page.win.location.href = opts.url;
954
1274
  if (typeof opts.direction === "string") page.doc.documentElement.setAttribute("dir", opts.direction);
955
1275
  if (typeof opts.language === "string") page.doc.documentElement.setAttribute("lang", opts.language);
@@ -962,18 +1282,23 @@ async function newSpecPage(opts) {
962
1282
  if (typeof opts.userAgent === "string") try {
963
1283
  page.win.navigator.userAgent = opts.userAgent;
964
1284
  } catch {}
1285
+ if (opts.hydrateServerSide && opts.serializeShadowRoot === "scoped") {
1286
+ for (const [, cmps] of lazyBundles) for (const cmp of cmps) if (cmp[0] & CMP_FLAGS.shadowDomEncapsulation) cmp[0] |= CMP_FLAGS.shadowNeedsScopedCss;
1287
+ }
965
1288
  bootstrapLazy(lazyBundles);
966
- if (typeof opts.template === "function") renderVdom({
967
- $ancestorComponent$: void 0,
968
- $flags$: 0,
969
- $modeName$: void 0,
970
- $cmpMeta$: {
1289
+ if (typeof opts.template === "function") {
1290
+ const ref = {
1291
+ $ancestorComponent$: void 0,
971
1292
  $flags$: 0,
972
- $tagName$: "body"
973
- },
974
- $hostElement$: page.body
975
- }, opts.template());
976
- else if (typeof opts.html === "string") page.body.innerHTML = opts.html;
1293
+ $modeName$: void 0,
1294
+ $cmpMeta$: {
1295
+ $flags$: 0,
1296
+ $tagName$: "body"
1297
+ },
1298
+ $hostElement$: page.body
1299
+ };
1300
+ renderVdom(ref, opts.template());
1301
+ } else if (typeof opts.html === "string") page.body.innerHTML = opts.html;
977
1302
  if (opts.flushQueue !== false) await page.waitForChanges();
978
1303
  let rootComponent = null;
979
1304
  Object.defineProperty(page, "root", { get() {
@@ -1167,4 +1492,4 @@ function setupConsoleMocker() {
1167
1492
  };
1168
1493
  }
1169
1494
  //#endregion
1170
- export { Build, Env, Fragment, Host, Mixin, createEvent, createTestingSystem, forceUpdate, getAssetPath, getElement, getHostRef, getMode, getRenderingRef, h, mockBuildCtx, mockCompilerCtx, mockCompilerSystem, mockComponentMeta, mockConfig, mockDocument, mockLoadConfigInit, mockLogger, mockModule, mockValidatedConfig, mockWindow, newSpecPage, readTask, registerHost, registerInstance, setAssetPath, setErrorHandler, setMode, setupConsoleMocker, shuffleArray, writeTask };
1495
+ export { Build, Env, Fragment, Host, Mixin, ReactiveControllerHost, createEvent, createTestCompiler, createTestingSystem, forceUpdate, getAssetPath, getElement, getHostRef, getMode, getRenderingRef, h, mockBuildCtx, mockCompilerCtx, mockCompilerSystem, mockComponentMeta, mockConfig, mockDocument, mockLoadConfigInit, mockLogger, mockModule, mockValidatedConfig, mockWindow, newSpecPage, prepareTestCompiler, readTask, registerHost, registerInstance, setAssetPath, setErrorHandler, setMode, setupConsoleMocker, shuffleArray, writeTask };