@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.
- package/README.md +94 -0
- package/dist/app-data/index.d.ts +2 -0
- package/dist/{runtime/app-data → app-data}/index.js +17 -11
- package/dist/{client-CSm3x5ke.mjs → client-D1MsT-Rp.mjs} +2717 -2424
- package/dist/compiler/index.d.mts +170 -6
- package/dist/compiler/index.mjs +4 -3
- package/dist/compiler/utils/index.d.mts +272 -2
- package/dist/compiler/utils/index.mjs +4 -3
- package/dist/{compiler-D6iP7Bzb.mjs → compiler-Cddp97Pg.mjs} +14953 -12327
- package/dist/declarations/stencil-ext-modules.d.ts +5 -5
- package/dist/declarations/stencil-public-compiler.d.ts +728 -287
- package/dist/declarations/stencil-public-compiler.js +2 -3
- package/dist/declarations/stencil-public-docs.d.ts +19 -0
- package/dist/declarations/stencil-public-runtime.d.ts +131 -17
- package/dist/fragment-Di1hWOC8.mjs +4 -0
- package/dist/{index-tUR6pD3J.d.mts → index-BHj3EBl2.d.mts} +1052 -668
- package/dist/{index-CyrGY82h.d.ts → index-D2PAsXxx.d.ts} +215 -40
- package/dist/index-VK8okIiF.d.mts +108 -0
- package/dist/index.d.mts +4 -1
- package/dist/index.mjs +91 -2
- package/dist/jsx-runtime.d.mts +18 -0
- package/dist/jsx-runtime.mjs +3 -0
- package/dist/{node-Bg-mO5dw.mjs → node-BQR4L-TG.mjs} +76 -73
- package/dist/reactive-controller-BdCpSAQP.d.mts +13 -0
- package/dist/{regular-expression-D5pGVpCu.mjs → regular-expression-XqU5zmPp.mjs} +141 -31
- package/dist/{chunk-CjcI7cDX.mjs → rolldown-runtime-BhDjJH2R.mjs} +1 -1
- package/dist/{runtime-BBCnuprF.js → runtime/client/lazy.js} +2987 -2443
- package/dist/runtime/client/{index.d.ts → runtime.d.ts} +228 -83
- package/dist/runtime/client/{index.js → runtime.js} +2852 -2432
- package/dist/runtime/index.d.ts +48 -29
- package/dist/runtime/index.js +5069 -2
- package/dist/runtime/server/index.d.mts +182 -75
- package/dist/runtime/server/index.mjs +2769 -2283
- package/dist/runtime/server/runner.d.mts +47 -32
- package/dist/runtime/server/runner.mjs +563 -687
- package/dist/signals/index.d.ts +49 -0
- package/dist/signals/index.js +199 -0
- package/dist/sys/node/index.d.mts +1 -2
- package/dist/sys/node/index.mjs +1 -1
- package/dist/sys/node/worker.d.mts +1 -1
- package/dist/sys/node/worker.mjs +6 -3
- package/dist/testing/index.d.mts +98 -9
- package/dist/testing/index.mjs +395 -70
- package/dist/util-BIa-iHnt.mjs +724 -0
- package/dist/validation-Dd3g77T5.mjs +778 -0
- package/package.json +49 -36
- package/dist/index-CXHCTQNt.d.mts +0 -190
- package/dist/index-hS-KBdAP.d.ts +0 -30
- package/dist/jsx-runtime-DlDkTqps.d.ts +0 -28
- package/dist/jsx-runtime.d.ts +0 -2
- package/dist/jsx-runtime.js +0 -2
- package/dist/runtime/app-data/index.d.ts +0 -2
- package/dist/validation-Byxie0Uk.mjs +0 -1445
- /package/{LICENSE.md → LICENSE} +0 -0
- /package/dist/{runtime/app-globals → app-globals}/index.d.ts +0 -0
- /package/dist/{runtime/app-globals → app-globals}/index.js +0 -0
package/dist/testing/index.mjs
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
7
|
-
import
|
|
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
|
|
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 =
|
|
269
|
+
const rootDir = nodePath.resolve("/");
|
|
264
270
|
return {
|
|
265
271
|
...baseConfig,
|
|
266
272
|
cacheDir: ".stencil",
|
|
267
273
|
devMode: true,
|
|
268
274
|
devServer: {},
|
|
269
|
-
|
|
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:
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
864
|
-
b.
|
|
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
|
-
|
|
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)
|
|
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
|
|
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.
|
|
951
|
-
|
|
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")
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
$modeName$: void 0,
|
|
970
|
-
$cmpMeta$: {
|
|
1289
|
+
if (typeof opts.template === "function") {
|
|
1290
|
+
const ref = {
|
|
1291
|
+
$ancestorComponent$: void 0,
|
|
971
1292
|
$flags$: 0,
|
|
972
|
-
$
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
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 };
|