@stencil/core 5.0.0-beta.34 → 5.0.0-beta.36
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/{client-UbH-XkYu.mjs → client-CqQpuOUk.mjs} +11 -2
- package/dist/compiler/browser.js +128 -14
- package/dist/compiler/index.d.mts +1 -1
- package/dist/compiler/index.mjs +2 -2
- package/dist/compiler/utils/index.d.mts +1 -1
- package/dist/{compiler-CVL510L-.mjs → compiler-DHNkXDvK.mjs} +318 -33
- package/dist/declarations/stencil-public-compiler.d.ts +16 -0
- package/dist/declarations/stencil-public-runtime.d.ts +10 -0
- package/dist/{index-Da-rNa6f.d.mts → index-CIjtinKD.d.mts} +1 -1
- package/dist/{index-B0NfYeIA.d.mts → index-DG4wtfhx.d.mts} +16 -0
- package/dist/index.mjs +1 -1
- package/dist/jsx-runtime.mjs +1 -1
- package/dist/{node-eg7pofz5.mjs → node-DwwBX_GL.mjs} +1 -1
- package/dist/runtime/client/lazy.js +11 -4
- package/dist/runtime/client/runtime.d.ts +18 -1
- package/dist/runtime/client/runtime.js +11 -4
- package/dist/runtime/index.d.ts +2 -1
- package/dist/runtime/index.js +11 -4
- package/dist/runtime/server/index.d.mts +16 -0
- package/dist/runtime/server/index.mjs +76 -8
- package/dist/runtime/server/runner.d.mts +39 -1
- package/dist/runtime/server/runner.mjs +230 -15
- package/dist/sys/node/index.d.mts +1 -1
- package/dist/sys/node/index.mjs +1 -1
- package/dist/sys/node/worker.mjs +2 -2
- package/dist/testing/index.mjs +23 -5
- package/package.json +4 -4
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { n as __require } from "./rolldown-runtime-BhDjJH2R.mjs";
|
|
2
|
-
import { E as SERVER_BUILD_FLAGS, T as HYDRATED_CSS, w as CLIENT_BUILD_FLAGS } from "./client-
|
|
2
|
+
import { A as SSR_PROP_REF_PREFIX, D as HYDRATE_ID, E as HYDRATE_CHILD_ID, O as SERVER_BUILD_FLAGS, T as HYDRATED_CSS, k as SSR_PROPS_REGISTRY_KEY, w as CLIENT_BUILD_FLAGS } from "./client-CqQpuOUk.mjs";
|
|
3
3
|
import { $ as VALID_CONFIG_OUTPUT_TARGETS, A as DIST_LAZY, D as COPY, E as COLLECTION_MANIFEST_FILE_NAME, J as STANDALONE, L as EVENT_FLAGS, P as DOCS_JSON, Q as TYPES, R as GENERATED_DTS, S as ASSETS, T as COLLECTION_APP_DATA_FILE_NAME, U as LOADER_BUNDLE, X as STYLE_EXT, Y as STATS, a as isBoolean$1, b as unique, c as isFunction, d as isObject, et as WATCH_FLAGS, f as isString$1, g as sortBy, i as fromEntries, l as isIterable, m as noop, p as mergeIntoWith, r as flatOne, t as dashToPascalCase, u as isNumber$1, v as toDashCase, w as COLLECTION, y as toTitleCase, z as GLOBAL_STYLE } from "./helpers-Cpp3qc3u.mjs";
|
|
4
4
|
import { E as escapeRegExpSpecialCharacters, S as formatComponentRuntimeMeta, T as byteSize, _ as loadRolldownDiagnostics, a as getSourceMappingUrlForEndOfFile, b as splitLineBreaks, c as err, f as augmentDiagnosticWithNode, g as isRolldownError, h as createOnWarnFn, i as getInlineSourceMappingUrlLinker, l as map, m as loadTypeScriptDiagnostics, n as validateComponentTag, p as loadTypeScriptDiagnostic, r as isRemoteUrl, s as rolldownToStencilSourceMap, t as validateComponentModes, u as ok, w as stringifyRuntimeData, x as isRootPath, y as normalizeDiagnostics } from "./validation-BlVm1Vu0.mjs";
|
|
5
5
|
import { $ as buildWarn, A as isOutputTargetDocsVscode, B as isValidConfigOutputTarget, C as isOutputTargetDistLazy, D as isOutputTargetDocsCustomElementsManifest, E as isOutputTargetDocsCustom, F as isOutputTargetSsrWasm, G as normalizeFsPath, H as shouldExcludeComponent, I as isOutputTargetStandalone, J as relative$1, K as normalizeFsPathQuery, L as isOutputTargetStats, M as isOutputTargetLoaderBundle, N as isOutputTargetServerRenderer, O as isOutputTargetDocsJson, P as isOutputTargetSsr, Q as buildJsonFileError, R as isOutputTargetTypes, S as isOutputTargetCustom, T as isOutputTargetDocsAgentSkill, U as join$2, V as relativeImport, Y as resolve$2, Z as buildError, a as hasDependency, b as isOutputTargetCollection, d as parsePackageJson, et as catchError, f as readOnlyArrayHasStringMember, g as getComponentsDtsSrcFilePath, h as filterExcludedComponents, i as getTextDocs, it as isGlob, j as isOutputTargetGlobalStyle, k as isOutputTargetDocsReadme, l as isTsFile, m as filterActiveTargets, n as createJsVarName, nt as hasWarning, o as isDtsFile, p as readPackageJson, q as normalizePath, r as generatePreamble, t as addDocBlock, tt as hasError, u as isTsxFile, v as getComponentsFromModules, w as isOutputTargetDocs, x as isOutputTargetCopy, y as isOutputTargetAssets, z as isOutputTargetWww } from "./util-C-H1H84W.mjs";
|
|
6
|
-
import { i as CustomElementsExportBehaviorOptions, o as buildEvents, r as createNodeLogger, t as createNodeSys } from "./node-
|
|
6
|
+
import { i as CustomElementsExportBehaviorOptions, o as buildEvents, r as createNodeLogger, t as createNodeSys } from "./node-DwwBX_GL.mjs";
|
|
7
7
|
import ts, { default as ts$1 } from "typescript";
|
|
8
8
|
import { readFileSync } from "node:fs";
|
|
9
9
|
import { basename, dirname, isAbsolute, join, resolve } from "node:path";
|
|
@@ -461,9 +461,9 @@ const scopeCss = (cssText, scopeId, commentOriginalSelector) => {
|
|
|
461
461
|
};
|
|
462
462
|
//#endregion
|
|
463
463
|
//#region src/version.ts
|
|
464
|
-
const version = "5.0.0-beta.
|
|
465
|
-
const buildId = "
|
|
466
|
-
const vermoji = "
|
|
464
|
+
const version = "5.0.0-beta.36";
|
|
465
|
+
const buildId = "1794253443";
|
|
466
|
+
const vermoji = "🌎";
|
|
467
467
|
/**
|
|
468
468
|
* Get the installed version of a tool/dependency.
|
|
469
469
|
* Handles packages with exports maps that point to subdirectories.
|
|
@@ -3049,6 +3049,9 @@ const objectLiteralToObjectMap = (objectLiteral, typeChecker, diagnostics, error
|
|
|
3049
3049
|
case ts.SyntaxKind.FalseKeyword:
|
|
3050
3050
|
val = false;
|
|
3051
3051
|
break;
|
|
3052
|
+
case ts.SyntaxKind.NullKeyword:
|
|
3053
|
+
val = null;
|
|
3054
|
+
break;
|
|
3052
3055
|
case ts.SyntaxKind.Identifier:
|
|
3053
3056
|
const escapedText = propAssignment.initializer.escapedText;
|
|
3054
3057
|
if (escapedText === "String") val = String;
|
|
@@ -3235,7 +3238,7 @@ const getAllTypeReferences = (checker, node) => {
|
|
|
3235
3238
|
*/
|
|
3236
3239
|
const getTypeReferenceLocation = (typeName, type, sourceFile, checker, program) => {
|
|
3237
3240
|
const importTypeDeclaration = sourceFile.statements.find((st) => {
|
|
3238
|
-
if (!(ts.isImportDeclaration(st) && st.importClause && ts.isImportClause(st.importClause) && st.importClause.namedBindings && ts.isNamedImports(st.importClause.namedBindings) && Array.isArray(st.importClause.namedBindings.elements) && st.importClause.namedBindings.elements.find((nbe) => nbe.name.
|
|
3241
|
+
if (!(ts.isImportDeclaration(st) && st.importClause && ts.isImportClause(st.importClause) && st.importClause.namedBindings && ts.isNamedImports(st.importClause.namedBindings) && Array.isArray(st.importClause.namedBindings.elements) && st.importClause.namedBindings.elements.find((nbe) => nbe.name.text === typeName))) return false;
|
|
3239
3242
|
return true;
|
|
3240
3243
|
});
|
|
3241
3244
|
const namedImportBindings = importTypeDeclaration?.importClause?.namedBindings;
|
|
@@ -3244,7 +3247,7 @@ const getTypeReferenceLocation = (typeName, type, sourceFile, checker, program)
|
|
|
3244
3247
|
const options = program.getCompilerOptions();
|
|
3245
3248
|
const importHomeModule = getHomeModule(sourceFile, localImportPath, options, ts.createCompilerHost(options), program);
|
|
3246
3249
|
if (importHomeModule) {
|
|
3247
|
-
const importElement = namedImportBindings.elements.find((nbe) => nbe.name.
|
|
3250
|
+
const importElement = namedImportBindings.elements.find((nbe) => nbe.name.text === typeName);
|
|
3248
3251
|
const importName = importElement.name;
|
|
3249
3252
|
const originalTypeName = getOriginalTypeName(importName, checker);
|
|
3250
3253
|
const importedAs = importElement.propertyName ? importElement.propertyName.getText() : typeName;
|
|
@@ -7705,9 +7708,9 @@ const updateStencilCoreImports = (updatedCoreImportPath) => {
|
|
|
7705
7708
|
}
|
|
7706
7709
|
if (moduleSpecifierText === "@stencil/core") {
|
|
7707
7710
|
if (s.importClause && s.importClause.namedBindings && s.importClause.namedBindings.kind === ts.SyntaxKind.NamedImports) {
|
|
7708
|
-
const keepImports = s.importClause.namedBindings.elements.
|
|
7711
|
+
const keepImports = s.importClause.namedBindings.elements.filter((e) => KEEP_IMPORTS.has((e.propertyName ?? e.name).text));
|
|
7709
7712
|
if (keepImports.length > 0) {
|
|
7710
|
-
const newImport = ts.factory.updateImportDeclaration(s, void 0, ts.factory.createImportClause(false, void 0, ts.factory.createNamedImports(keepImports.map((
|
|
7713
|
+
const newImport = ts.factory.updateImportDeclaration(s, void 0, ts.factory.createImportClause(false, void 0, ts.factory.createNamedImports(keepImports.map((e) => ts.factory.createImportSpecifier(false, e.propertyName ? ts.factory.createIdentifier(e.propertyName.text) : void 0, ts.factory.createIdentifier(e.name.text))))), ts.factory.createStringLiteral(updatedCoreImportPath), void 0);
|
|
7711
7714
|
newStatements.push(newImport);
|
|
7712
7715
|
}
|
|
7713
7716
|
}
|
|
@@ -12524,10 +12527,44 @@ const SSR_FACTORY_INTRO = `
|
|
|
12524
12527
|
// Used for the hydrate timeout timer to avoid being affected by constrainTimeouts.
|
|
12525
12528
|
var $nativeSetTimeout = (typeof globalThis !== 'undefined' ? globalThis : global).setTimeout;
|
|
12526
12529
|
var $nativeClearTimeout = (typeof globalThis !== 'undefined' ? globalThis : global).clearTimeout;
|
|
12530
|
+
// Holds the \`ssrProp()\` registry, which template code writes to outside the factory.
|
|
12531
|
+
var $stencilNativeGlobal = typeof globalThis !== 'undefined' ? globalThis : global;
|
|
12527
12532
|
// Used to abort in-flight fetch() calls and to call any user defined AbortControllers when ssr times out.
|
|
12528
12533
|
var $stencilNativeAbortController = AbortController;
|
|
12529
12534
|
|
|
12535
|
+
// Evaluated SSR platforms, per window and per serializeShadowRoot mode. Evaluating the platform
|
|
12536
|
+
// (runtime, vdom and every component class) is the main fixed cost of a render, so a window that's
|
|
12537
|
+
// rendered into again (see the \`reuseWindow\` option) reuses it. A new window gets a new platform.
|
|
12538
|
+
var $stencilSsrApps = new WeakMap();
|
|
12539
|
+
|
|
12530
12540
|
export function ssrFactory($stencilWindow, $stencilHydrateOpts, $stencilHydrateResults, $stencilAfterHydrate, $stencilHydrateResolve) {
|
|
12541
|
+
// Rendering shadow components as scoped permanently changes their metadata inside the platform,
|
|
12542
|
+
// so a platform is only shared by renders whose serializeShadowRoot marks the same components as
|
|
12543
|
+
// scoped: keyed by the canonical key the renderer computes for it.
|
|
12544
|
+
var $stencilShadowModeKey = $stencilHydrateOpts.serializeShadowRootKey;
|
|
12545
|
+
var $stencilApp;
|
|
12546
|
+
if (typeof $stencilShadowModeKey !== 'string') {
|
|
12547
|
+
$stencilApp = $stencilCreateSsrApp($stencilWindow);
|
|
12548
|
+
} else {
|
|
12549
|
+
var $stencilWindowApps = $stencilSsrApps.get($stencilWindow);
|
|
12550
|
+
if (!$stencilWindowApps) {
|
|
12551
|
+
$stencilWindowApps = new Map();
|
|
12552
|
+
$stencilSsrApps.set($stencilWindow, $stencilWindowApps);
|
|
12553
|
+
}
|
|
12554
|
+
$stencilApp = $stencilWindowApps.get($stencilShadowModeKey);
|
|
12555
|
+
if (!$stencilApp) {
|
|
12556
|
+
$stencilApp = $stencilCreateSsrApp($stencilWindow);
|
|
12557
|
+
$stencilWindowApps.set($stencilShadowModeKey, $stencilApp);
|
|
12558
|
+
}
|
|
12559
|
+
}
|
|
12560
|
+
$stencilApp($stencilHydrateOpts, $stencilHydrateResults, $stencilAfterHydrate, $stencilHydrateResolve);
|
|
12561
|
+
}
|
|
12562
|
+
|
|
12563
|
+
/**
|
|
12564
|
+
* Evaluates the SSR platform for a window, and returns a function that renders with it.
|
|
12565
|
+
* Renders using the same platform must run one at a time.
|
|
12566
|
+
*/
|
|
12567
|
+
function $stencilCreateSsrApp($stencilWindow) {
|
|
12531
12568
|
var globalThis = $stencilWindow;
|
|
12532
12569
|
var self = $stencilWindow;
|
|
12533
12570
|
var top = $stencilWindow;
|
|
@@ -12616,7 +12653,9 @@ export function ssrFactory($stencilWindow, $stencilHydrateOpts, $stencilHydrateR
|
|
|
12616
12653
|
// Aborted when the render times out or errors, so in-flight fetch() calls
|
|
12617
12654
|
// made by component code stop holding the render's window/results alive
|
|
12618
12655
|
// instead of running to completion against a torn-down window. See #6864.
|
|
12619
|
-
|
|
12656
|
+
// A new one is created for every render (see the function returned below),
|
|
12657
|
+
// so one render's timeout never cancels the next render's work.
|
|
12658
|
+
var $stencilAbortController;
|
|
12620
12659
|
|
|
12621
12660
|
// Any AbortController a component creates itself is transparently wired to
|
|
12622
12661
|
// cascade-abort when the render times out too, so component code using the
|
|
@@ -12688,10 +12727,19 @@ export function ssrFactory($stencilWindow, $stencilHydrateOpts, $stencilHydrateR
|
|
|
12688
12727
|
`;
|
|
12689
12728
|
const SSR_FACTORY_OUTRO = `
|
|
12690
12729
|
/*hydrateAppClosure end*/
|
|
12691
|
-
|
|
12730
|
+
return function ($stencilHydrateOpts, $stencilHydrateResults, $stencilAfterHydrate, $stencilHydrateResolve) {
|
|
12731
|
+
$stencilAbortController = new $stencilNativeAbortController();
|
|
12732
|
+
// a reused window is reset between renders, which removes these; put them back
|
|
12733
|
+
$stencilWindow.fetch = fetch;
|
|
12734
|
+
$stencilWindow.FetchError = FetchError;
|
|
12735
|
+
$stencilWindow.Headers = Headers;
|
|
12736
|
+
$stencilWindow.Request = Request;
|
|
12737
|
+
$stencilWindow.Response = Response;
|
|
12738
|
+
ssrApp(window, $stencilHydrateOpts, $stencilHydrateResults, $stencilAfterHydrate, $stencilHydrateResolve, $stencilAbortController);
|
|
12739
|
+
};
|
|
12692
12740
|
}
|
|
12693
12741
|
|
|
12694
|
-
hydrateAppClosure($stencilWindow);
|
|
12742
|
+
return hydrateAppClosure($stencilWindow);
|
|
12695
12743
|
}
|
|
12696
12744
|
`;
|
|
12697
12745
|
//#endregion
|
|
@@ -12805,6 +12853,7 @@ const writeSsrOutput = async (config, compilerCtx, buildCtx, outputTarget, rolld
|
|
|
12805
12853
|
const hydrateAppDirPath = outputTarget.dir;
|
|
12806
12854
|
if (!hydrateAppDirPath) throw new Error(`outputTarget config missing the "dir" property`);
|
|
12807
12855
|
await copySsrRunnerDts(config, compilerCtx, hydrateAppDirPath);
|
|
12856
|
+
await writeSsrPropModule(compilerCtx, hydrateAppDirPath, outputTarget.cjs === true);
|
|
12808
12857
|
buildCtx.ssrAppFilePath = join$2(hydrateAppDirPath, "index.js");
|
|
12809
12858
|
const minify = outputTarget.minify === true;
|
|
12810
12859
|
await Promise.all(rolldownOutput.output.map(async (output) => {
|
|
@@ -12828,7 +12877,86 @@ const copySsrRunnerDts = async (config, compilerCtx, hydrateAppDirPath) => {
|
|
|
12828
12877
|
const packageDir = join$2(config.sys.getCompilerExecutingPath(), "..", "..");
|
|
12829
12878
|
const srcSsrDir = join$2(packageDir, "runtime", "server", "runner.d.mts");
|
|
12830
12879
|
const runnerDtsDestPath = join$2(hydrateAppDirPath, "index.d.ts");
|
|
12831
|
-
await
|
|
12880
|
+
const dts = await config.sys.readFile(srcSsrDir);
|
|
12881
|
+
if (dts == null) return;
|
|
12882
|
+
await compilerCtx.fs.writeFile(runnerDtsDestPath, stripSideEffectImports(dts), { immediateWrite: true });
|
|
12883
|
+
};
|
|
12884
|
+
/**
|
|
12885
|
+
* The bundled runner types keep bare imports (`import "rolldown";`) of modules whose types were
|
|
12886
|
+
* tree-shaken away. They declare nothing, but a library's consumers won't have those packages
|
|
12887
|
+
* (often not even `@stencil/core`), which breaks under `noUncheckedSideEffectImports`.
|
|
12888
|
+
* @param dts the runner's `.d.mts` contents
|
|
12889
|
+
* @returns the contents without bare imports
|
|
12890
|
+
*/
|
|
12891
|
+
const stripSideEffectImports = (dts) => dts.replace(/^import\s*["'][^"']+["'];?[ \t]*\r?\n/gm, "");
|
|
12892
|
+
const SSR_PROP_JS = `const PREFIX = ${JSON.stringify(SSR_PROP_REF_PREFIX)};
|
|
12893
|
+
const REGISTRY = Symbol.for(${JSON.stringify(SSR_PROPS_REGISTRY_KEY)});
|
|
12894
|
+
// a value nothing picked up (the page never reached renderToString()) is dropped after this long
|
|
12895
|
+
const TTL = 60000;
|
|
12896
|
+
let nextSweep = 0;
|
|
12897
|
+
|
|
12898
|
+
/**
|
|
12899
|
+
* Pass a value to a component's property from a framework template, so it reaches the component
|
|
12900
|
+
* when it's rendered on the server too. In the browser, returns the value. On the server, keeps
|
|
12901
|
+
* the value and returns a reference to it, which the template renders as an attribute and the
|
|
12902
|
+
* SSR module (in the same process) turns back into the value. Getting it on to the browser is the
|
|
12903
|
+
* prop's job: @Prop({ serialize: 'json' }), or a @PropSerialize() / @AttrDeserialize() pair.
|
|
12904
|
+
*/
|
|
12905
|
+
export function ssrProp(value) {
|
|
12906
|
+
if (typeof window !== 'undefined') return value;
|
|
12907
|
+
const registry = globalThis[REGISTRY] || (globalThis[REGISTRY] = new Map());
|
|
12908
|
+
const now = Date.now();
|
|
12909
|
+
if (now > nextSweep) {
|
|
12910
|
+
nextSweep = now + TTL;
|
|
12911
|
+
for (const [id, entry] of registry) if (entry.expires < now) registry.delete(id);
|
|
12912
|
+
}
|
|
12913
|
+
const id = globalThis.crypto && globalThis.crypto.randomUUID
|
|
12914
|
+
? globalThis.crypto.randomUUID()
|
|
12915
|
+
: Math.random().toString(36).slice(2) + now.toString(36);
|
|
12916
|
+
registry.set(id, { value, expires: now + TTL });
|
|
12917
|
+
return PREFIX + id;
|
|
12918
|
+
}
|
|
12919
|
+
`;
|
|
12920
|
+
const SSR_PROP_DTS = `/**
|
|
12921
|
+
* Pass a value to a component's property from a framework template, so it reaches the component
|
|
12922
|
+
* when it's rendered on the server too.
|
|
12923
|
+
*
|
|
12924
|
+
* \`\`\`vue
|
|
12925
|
+
* <my-chart :data="ssrProp(data)" />
|
|
12926
|
+
* \`\`\`
|
|
12927
|
+
*
|
|
12928
|
+
* In the browser, returns the value. On the server, keeps the value and returns a reference to it
|
|
12929
|
+
* (a string the template renders as an attribute), which the SSR module turns back into the
|
|
12930
|
+
* value. Nothing is serialized, so any value works: a \`Map\`, a \`Date\`, a class instance.
|
|
12931
|
+
*
|
|
12932
|
+
* The SSR module must render the page in the same process, soon after the template runs: the
|
|
12933
|
+
* whole-document \`renderToString()\` hook every framework integration uses.
|
|
12934
|
+
*
|
|
12935
|
+
* This gets the value into the server render only. For the component to have it when it first
|
|
12936
|
+
* renders in the browser too, before the framework sets the property, the prop needs to carry it
|
|
12937
|
+
* in its attribute: \`@Prop({ serialize: 'json' })\`, or a \`@PropSerialize()\` /
|
|
12938
|
+
* \`@AttrDeserialize()\` pair for other formats. Without either, \`renderToString()\` adds a
|
|
12939
|
+
* warning to its \`diagnostics\`.
|
|
12940
|
+
* @param value the property value
|
|
12941
|
+
* @returns \`value\` in the browser, a reference to it (a string) typed as \`T\` on the server
|
|
12942
|
+
*/
|
|
12943
|
+
export declare function ssrProp<T>(value: T): T;
|
|
12944
|
+
`;
|
|
12945
|
+
/**
|
|
12946
|
+
* Write `ssr-prop.js` (`./ssr-prop` in export maps): `ssrProp()`, for framework templates. It runs
|
|
12947
|
+
* on both server and client, so it's separate from the server-only SSR module.
|
|
12948
|
+
* @param compilerCtx the compiler context
|
|
12949
|
+
* @param dir the ssr output directory
|
|
12950
|
+
* @param cjs whether to also write a CommonJS copy
|
|
12951
|
+
*/
|
|
12952
|
+
const writeSsrPropModule = async (compilerCtx, dir, cjs) => {
|
|
12953
|
+
const opts = { immediateWrite: true };
|
|
12954
|
+
await compilerCtx.fs.writeFile(join$2(dir, "ssr-prop.js"), SSR_PROP_JS, opts);
|
|
12955
|
+
await compilerCtx.fs.writeFile(join$2(dir, "ssr-prop.d.ts"), SSR_PROP_DTS, opts);
|
|
12956
|
+
if (cjs) {
|
|
12957
|
+
const cjsCode = SSR_PROP_JS.replace("export function ssrProp", "function ssrProp") + "exports.ssrProp = ssrProp;\n";
|
|
12958
|
+
await compilerCtx.fs.writeFile(join$2(dir, "ssr-prop.cjs"), cjsCode, opts);
|
|
12959
|
+
}
|
|
12832
12960
|
};
|
|
12833
12961
|
//#endregion
|
|
12834
12962
|
//#region src/compiler/output-targets/ssr/generate-ssr-app.ts
|
|
@@ -12941,10 +13069,42 @@ const generateSsrFactoryEntry = async (buildCtx) => {
|
|
|
12941
13069
|
return s.toString();
|
|
12942
13070
|
};
|
|
12943
13071
|
//#endregion
|
|
13072
|
+
//#region src/compiler/output-targets/ssr/validate-reserved-attributes.ts
|
|
13073
|
+
/** Attributes server rendering writes on component hosts and the nodes they render. */
|
|
13074
|
+
const SSR_ATTRIBUTES = /* @__PURE__ */ new Set([
|
|
13075
|
+
HYDRATE_ID,
|
|
13076
|
+
HYDRATE_CHILD_ID,
|
|
13077
|
+
"s-sn",
|
|
13078
|
+
"s-mode"
|
|
13079
|
+
]);
|
|
13080
|
+
/**
|
|
13081
|
+
* Report props whose attribute would collide with one server rendering writes (`@Prop() sId` is
|
|
13082
|
+
* `s-id`): the server would overwrite or remove the value and the client would misread it. Only
|
|
13083
|
+
* relevant to builds that render on a server, so it's run by the `ssr` and `ssr-wasm` outputs.
|
|
13084
|
+
*
|
|
13085
|
+
* Complex props have no attribute of their own, but templates bind `ssrProp()` values under the
|
|
13086
|
+
* dash-cased prop name, so that's checked too.
|
|
13087
|
+
*
|
|
13088
|
+
* @param config the validated config
|
|
13089
|
+
* @param buildCtx the current build context
|
|
13090
|
+
*/
|
|
13091
|
+
const validateSsrReservedAttributes = (config, buildCtx) => {
|
|
13092
|
+
for (const cmp of buildCtx.components) for (const prop of cmp.properties) {
|
|
13093
|
+
const attribute = prop.attribute ?? toDashCase(prop.name);
|
|
13094
|
+
if (!SSR_ATTRIBUTES.has(attribute)) continue;
|
|
13095
|
+
const err = buildError(buildCtx.diagnostics);
|
|
13096
|
+
err.header = "Reserved Attribute Name";
|
|
13097
|
+
err.messageText = `The "${prop.name}" prop of <${cmp.tagName}> uses the attribute "${attribute}", which Stencil writes when it renders on the server. Rename the prop, or give it another attribute name: @Prop({ attribute: '...' }).`;
|
|
13098
|
+
err.absFilePath = cmp.sourceFilePath;
|
|
13099
|
+
err.relFilePath = relative$1(config.rootDir, cmp.sourceFilePath);
|
|
13100
|
+
}
|
|
13101
|
+
};
|
|
13102
|
+
//#endregion
|
|
12944
13103
|
//#region src/compiler/output-targets/ssr/index.ts
|
|
12945
13104
|
const outputSsr = async (config, compilerCtx, buildCtx) => {
|
|
12946
13105
|
const ssrOutputTargets = filterActiveTargets(config.outputTargets.filter(isOutputTargetSsr), config.devMode);
|
|
12947
13106
|
if (ssrOutputTargets.length > 0) {
|
|
13107
|
+
validateSsrReservedAttributes(config, buildCtx);
|
|
12948
13108
|
const timespan = buildCtx.createTimeSpan(`generate SSR app started`);
|
|
12949
13109
|
await generateSsrApp(config, compilerCtx, buildCtx, ssrOutputTargets);
|
|
12950
13110
|
timespan.finish(`generate SSR app finished`);
|
|
@@ -13081,9 +13241,17 @@ const SSR_WASM_INTERFACE = `declare module "main" {
|
|
|
13081
13241
|
export function resetSsrDocData(): void;
|
|
13082
13242
|
}\n`;
|
|
13083
13243
|
const SSR_WASM_OUTRO = `
|
|
13244
|
+
// Whether a renderToString call is in progress. Still true at the start of a call means the last
|
|
13245
|
+
// call ended with its render waiting on work that never resolved (see below).
|
|
13246
|
+
var $stencilWasmRenderInProgress = false;
|
|
13247
|
+
|
|
13084
13248
|
module.exports = {
|
|
13085
13249
|
renderToString: async function() {
|
|
13086
13250
|
try {
|
|
13251
|
+
if ($stencilWasmRenderInProgress && typeof resetReusableWindows === 'function') {
|
|
13252
|
+
// That render will never finish, so it would hold its reusable window and queue forever.
|
|
13253
|
+
resetReusableWindows();
|
|
13254
|
+
}
|
|
13087
13255
|
if (typeof renderToString !== 'function') {
|
|
13088
13256
|
Host.outputString(JSON.stringify({ __error: 'renderToString is ' + typeof renderToString }));
|
|
13089
13257
|
return;
|
|
@@ -13095,15 +13263,20 @@ module.exports = {
|
|
|
13095
13263
|
// silence, then overwrite it once renderToString() actually resolves.
|
|
13096
13264
|
Host.outputString(JSON.stringify({ __error: 'renderToString did not complete - a component may be waiting on work that never resolves' }));
|
|
13097
13265
|
var opts = inp.options || {};
|
|
13266
|
+
// A plugin instance runs one call at a time, so its renders can always share one window
|
|
13267
|
+
// (see the reuseWindow option). Skips re-evaluating the whole platform on every call.
|
|
13268
|
+
if (typeof opts.reuseWindow !== 'boolean') opts.reuseWindow = true;
|
|
13098
13269
|
var budget = typeof opts.timeout === 'number' ? opts.timeout : 15000;
|
|
13099
13270
|
var timers = globalThis.__stencilSsrWasmTimers;
|
|
13100
13271
|
var render = timers && timers.start(budget, function() {
|
|
13101
13272
|
Host.outputString(JSON.stringify({ __error: 'renderToString did not complete within the ' + budget + 'ms timeout - a component may be waiting on work that never resolves, on a timer due after the timeout, or on timers it schedules forever' }));
|
|
13102
13273
|
});
|
|
13103
13274
|
var result;
|
|
13275
|
+
$stencilWasmRenderInProgress = true;
|
|
13104
13276
|
try {
|
|
13105
|
-
result = await renderToString(inp.html,
|
|
13277
|
+
result = await renderToString(inp.html, opts);
|
|
13106
13278
|
} finally {
|
|
13279
|
+
$stencilWasmRenderInProgress = false;
|
|
13107
13280
|
if (render) timers.stop(render);
|
|
13108
13281
|
}
|
|
13109
13282
|
// renderToString reports some failures (e.g. input that isn't an HTML string) as an
|
|
@@ -13129,6 +13302,9 @@ module.exports = {
|
|
|
13129
13302
|
var m = mappings.find(function(x) { return x.from === tag; });
|
|
13130
13303
|
return m ? m.to : tag;
|
|
13131
13304
|
});
|
|
13305
|
+
// Platforms register components under their transformed tags when they're set up, so the
|
|
13306
|
+
// reused windows' platforms have to be set up again.
|
|
13307
|
+
if (typeof resetReusableWindows === 'function') resetReusableWindows();
|
|
13132
13308
|
},
|
|
13133
13309
|
resetSsrDocData: function() {
|
|
13134
13310
|
resetSsrDocData();
|
|
@@ -13225,6 +13401,7 @@ const compileToWasm = async (buildCtx, jsPath, interfacePath, wasmPath) => {
|
|
|
13225
13401
|
const outputSsrWasm = async (config, compilerCtx, buildCtx) => {
|
|
13226
13402
|
const ssrWasmTargets = filterActiveTargets(config.outputTargets.filter(isOutputTargetSsrWasm), config.devMode);
|
|
13227
13403
|
if (ssrWasmTargets.length > 0) {
|
|
13404
|
+
if (filterActiveTargets(config.outputTargets.filter(isOutputTargetSsr), config.devMode).length === 0) validateSsrReservedAttributes(config, buildCtx);
|
|
13228
13405
|
const timespan = buildCtx.createTimeSpan(`generate SSR WASM started`);
|
|
13229
13406
|
await generateSsrWasmApp(config, compilerCtx, buildCtx, ssrWasmTargets);
|
|
13230
13407
|
timespan.finish(`generate SSR WASM finished`);
|
|
@@ -13305,17 +13482,9 @@ const createDefineCase = (tagName, actionExpression) => {
|
|
|
13305
13482
|
return ts.factory.createCaseClause(ts.factory.createStringLiteral(tagName), [ts.factory.createIfStatement(getCheck, ts.factory.createBlock([ts.factory.createExpressionStatement(actionExpression)])), ts.factory.createBreakStatement()]);
|
|
13306
13483
|
};
|
|
13307
13484
|
/**
|
|
13308
|
-
* Adds the exported `defineCustomElement` function declaration.
|
|
13485
|
+
* Adds the exported `defineCustomElement` function declaration. `__stencil_getRegistry()` returns
|
|
13486
|
+
* `undefined` where there's no `customElements` (e.g. on a server), so the call is a no-op there.
|
|
13309
13487
|
*
|
|
13310
|
-
* Global path:
|
|
13311
|
-
* ```js
|
|
13312
|
-
* export function defineCustomElement() {
|
|
13313
|
-
* if (typeof customElements === 'undefined') return;
|
|
13314
|
-
* ['my-comp', ...].forEach(tagName => { switch (tagName) { ... } });
|
|
13315
|
-
* }
|
|
13316
|
-
* ```
|
|
13317
|
-
*
|
|
13318
|
-
* Scoped path:
|
|
13319
13488
|
* ```js
|
|
13320
13489
|
* export function defineCustomElement(opts) {
|
|
13321
13490
|
* const _storeReg = __stencil_getRegistry();
|
|
@@ -15838,8 +16007,8 @@ var ImportAliasMap = class extends Map {
|
|
|
15838
16007
|
for (const importDeclaration of importDeclarations) if (importDeclaration.moduleSpecifier.getText().includes("@stencil/core")) {
|
|
15839
16008
|
const namedBindings = importDeclaration.importClause?.namedBindings;
|
|
15840
16009
|
if (namedBindings && ts.isNamedImports(namedBindings)) for (const element of namedBindings.elements) {
|
|
15841
|
-
const importName = element.name.
|
|
15842
|
-
const originalImportName = element.propertyName?.
|
|
16010
|
+
const importName = element.name.text;
|
|
16011
|
+
const originalImportName = element.propertyName?.text ?? importName;
|
|
15843
16012
|
if (STENCIL_DECORATORS.includes(originalImportName)) this.set(originalImportName, importName);
|
|
15844
16013
|
}
|
|
15845
16014
|
}
|
|
@@ -15849,6 +16018,102 @@ var ImportAliasMap = class extends Map {
|
|
|
15849
16018
|
}
|
|
15850
16019
|
};
|
|
15851
16020
|
//#endregion
|
|
16021
|
+
//#region src/compiler/transformers/decorators-to-static/json-serialize-prop.ts
|
|
16022
|
+
/**
|
|
16023
|
+
* `@Prop({ serialize: 'json' })` is shorthand for a `@PropSerialize()` / `@AttrDeserialize()` pair
|
|
16024
|
+
* that writes the value to the prop's attribute as JSON on the server, and reads it back in the
|
|
16025
|
+
* browser. These are the generated methods' names (no leading `_`: the runtime metadata drops
|
|
16026
|
+
* those keys), and the alias of the `Build` import they use.
|
|
16027
|
+
*/
|
|
16028
|
+
const JSON_SERIALIZE_METHOD = "stencilSerializeJson";
|
|
16029
|
+
const JSON_DESERIALIZE_METHOD = "stencilDeserializeJson";
|
|
16030
|
+
const BUILD_ALIAS = "__stencil_Build";
|
|
16031
|
+
/**
|
|
16032
|
+
* Find the props declared `@Prop({ serialize: 'json' })`, reporting invalid combinations.
|
|
16033
|
+
* @param diagnostics for surfacing errors
|
|
16034
|
+
* @param typeChecker a TypeScript typechecker instance
|
|
16035
|
+
* @param decoratedMembers the class's decorated members
|
|
16036
|
+
* @param propDecoratorName the name `@Prop` is imported as
|
|
16037
|
+
* @param handWritten serializers and deserializers written with the decorators
|
|
16038
|
+
* @returns the names of the props to serialize as JSON
|
|
16039
|
+
*/
|
|
16040
|
+
const getJsonSerializedProps = (diagnostics, typeChecker, decoratedMembers, propDecoratorName, handWritten) => decoratedMembers.flatMap((member) => {
|
|
16041
|
+
if (!ts.isPropertyDeclaration(member) && !ts.isGetAccessor(member)) return [];
|
|
16042
|
+
const decorator = retrieveTsDecorators(member)?.find(isDecoratorNamed(propDecoratorName));
|
|
16043
|
+
if (!decorator) return [];
|
|
16044
|
+
const [options] = getDecoratorParameters(decorator, typeChecker);
|
|
16045
|
+
if (options?.serialize == null) return [];
|
|
16046
|
+
const { staticName: propName } = tsPropDeclName(member, typeChecker);
|
|
16047
|
+
const error = (messageText) => {
|
|
16048
|
+
const err = buildError(diagnostics);
|
|
16049
|
+
err.messageText = messageText;
|
|
16050
|
+
augmentDiagnosticWithNode(err, decorator);
|
|
16051
|
+
};
|
|
16052
|
+
if (options.serialize !== "json") {
|
|
16053
|
+
error(`@Prop({ serialize }) on "${propName}" must be 'json'. For other formats, use @PropSerialize() and @AttrDeserialize().`);
|
|
16054
|
+
return [];
|
|
16055
|
+
}
|
|
16056
|
+
if (options.attribute === null) {
|
|
16057
|
+
error(`@Prop({ serialize: 'json' }) on "${propName}" needs an attribute to write to, but it has "attribute: null".`);
|
|
16058
|
+
return [];
|
|
16059
|
+
}
|
|
16060
|
+
if (handWritten.some((h) => h.propName === propName)) {
|
|
16061
|
+
error(`"${propName}" has both @Prop({ serialize: 'json' }) and its own @PropSerialize() / @AttrDeserialize(). Use one or the other.`);
|
|
16062
|
+
return [];
|
|
16063
|
+
}
|
|
16064
|
+
return [propName];
|
|
16065
|
+
});
|
|
16066
|
+
/**
|
|
16067
|
+
* The methods `@Prop({ serialize: 'json' })` uses, shared by every such prop in a class:
|
|
16068
|
+
*
|
|
16069
|
+
* ```ts
|
|
16070
|
+
* stencilSerializeJson(value) {
|
|
16071
|
+
* return __stencil_Build.isServer ? JSON.stringify(value) : null;
|
|
16072
|
+
* }
|
|
16073
|
+
* stencilDeserializeJson(value, propName) {
|
|
16074
|
+
* try {
|
|
16075
|
+
* return JSON.parse(value);
|
|
16076
|
+
* } catch {
|
|
16077
|
+
* if (__stencil_Build.isDev) console.warn(...);
|
|
16078
|
+
* // leave the prop as it is
|
|
16079
|
+
* return __stencil_Build.isServer ? undefined : this[propName];
|
|
16080
|
+
* }
|
|
16081
|
+
* }
|
|
16082
|
+
* ```
|
|
16083
|
+
*
|
|
16084
|
+
* The serializer only writes on the server, like a hand-written one should: in the browser the
|
|
16085
|
+
* attribute's job is done, and rewriting it on every change would be wasted work.
|
|
16086
|
+
* @returns the two method declarations
|
|
16087
|
+
*/
|
|
16088
|
+
const createJsonSerializerMethods = () => {
|
|
16089
|
+
const f = ts.factory;
|
|
16090
|
+
const build = (flag) => f.createPropertyAccessExpression(f.createIdentifier(BUILD_ALIAS), flag);
|
|
16091
|
+
const jsonCall = (method, arg) => f.createCallExpression(f.createPropertyAccessExpression(f.createIdentifier("JSON"), method), void 0, [arg]);
|
|
16092
|
+
const param = (name) => f.createParameterDeclaration(void 0, void 0, name);
|
|
16093
|
+
const method = (name, params, body) => f.createMethodDeclaration(void 0, void 0, name, void 0, void 0, params.map(param), void 0, f.createBlock(body, true));
|
|
16094
|
+
const serialize = method(JSON_SERIALIZE_METHOD, ["value"], [f.createReturnStatement(f.createConditionalExpression(build("isServer"), void 0, jsonCall("stringify", f.createIdentifier("value")), void 0, f.createNull()))]);
|
|
16095
|
+
const warn = f.createIfStatement(build("isDev"), f.createExpressionStatement(f.createCallExpression(f.createPropertyAccessExpression(f.createIdentifier("console"), "warn"), void 0, [f.createTemplateExpression(f.createTemplateHead("The \""), [f.createTemplateSpan(f.createIdentifier("propName"), f.createTemplateMiddle(`" attribute isn't valid JSON, so the prop was left as it is: `)), f.createTemplateSpan(f.createIdentifier("value"), f.createTemplateTail(""))])])));
|
|
16096
|
+
return [serialize, method(JSON_DESERIALIZE_METHOD, ["value", "propName"], [f.createTryStatement(f.createBlock([f.createReturnStatement(jsonCall("parse", f.createIdentifier("value")))], true), f.createCatchClause(void 0, f.createBlock([warn, f.createReturnStatement(f.createConditionalExpression(build("isServer"), void 0, f.createIdentifier("undefined"), void 0, f.createElementAccessExpression(f.createThis(), f.createIdentifier("propName"))))], true)), void 0)])];
|
|
16097
|
+
};
|
|
16098
|
+
/**
|
|
16099
|
+
* Import `Build` (as {@link BUILD_ALIAS}) from `@stencil/core`, for the generated methods. Added
|
|
16100
|
+
* to an existing `@stencil/core` import, which a component's source always has.
|
|
16101
|
+
* @param sourceFile the source file
|
|
16102
|
+
* @returns the source file with the import
|
|
16103
|
+
*/
|
|
16104
|
+
const addBuildImport = (sourceFile) => {
|
|
16105
|
+
const f = ts.factory;
|
|
16106
|
+
const specifier = f.createImportSpecifier(false, f.createIdentifier("Build"), f.createIdentifier(BUILD_ALIAS));
|
|
16107
|
+
let added = false;
|
|
16108
|
+
const statements = sourceFile.statements.map((s) => {
|
|
16109
|
+
if (added || !ts.isImportDeclaration(s) || !ts.isStringLiteral(s.moduleSpecifier) || s.moduleSpecifier.text !== "@stencil/core" || !s.importClause?.namedBindings || !ts.isNamedImports(s.importClause.namedBindings) || s.importClause.isTypeOnly) return s;
|
|
16110
|
+
added = true;
|
|
16111
|
+
return f.updateImportDeclaration(s, s.modifiers, f.updateImportClause(s.importClause, false, s.importClause.name, f.updateNamedImports(s.importClause.namedBindings, [...s.importClause.namedBindings.elements, specifier])), s.moduleSpecifier, s.attributes);
|
|
16112
|
+
});
|
|
16113
|
+
if (!added) statements.unshift(f.createImportDeclaration(void 0, f.createImportClause(false, void 0, f.createNamedImports([specifier])), f.createStringLiteral(STENCIL_CORE_ID)));
|
|
16114
|
+
return f.updateSourceFile(sourceFile, statements);
|
|
16115
|
+
};
|
|
16116
|
+
//#endregion
|
|
15852
16117
|
//#region src/compiler/transformers/decorators-to-static/listen-decorator.ts
|
|
15853
16118
|
const listenDecoratorsToStatic = (diagnostics, typeChecker, decoratedMembers, newMembers, decoratorName) => {
|
|
15854
16119
|
const listeners = decoratedMembers.filter(ts.isMethodDeclaration).map((method) => parseListenDecorators(diagnostics, typeChecker, method, decoratorName));
|
|
@@ -16262,7 +16527,7 @@ const isTypePromise = (typeStr) => {
|
|
|
16262
16527
|
};
|
|
16263
16528
|
const validateMethods = (diagnostics, members) => {
|
|
16264
16529
|
members.filter(ts.isMethodDeclaration).map((method) => {
|
|
16265
|
-
if (method.name
|
|
16530
|
+
if (ts.isIdentifier(method.name) && method.name.text === "componentDidUnload") {
|
|
16266
16531
|
const err = buildError(diagnostics);
|
|
16267
16532
|
err.header = `Replace "componentDidUnload()" with "disconnectedCallback()"`;
|
|
16268
16533
|
err.messageText = `The "componentDidUnload()" method was removed in Stencil 2. Please use the "disconnectedCallback()" method instead.`;
|
|
@@ -16627,7 +16892,7 @@ const getPropertyNameText = (name) => {
|
|
|
16627
16892
|
};
|
|
16628
16893
|
//#endregion
|
|
16629
16894
|
//#region src/compiler/transformers/decorators-to-static/serialize-decorators.ts
|
|
16630
|
-
const serializeDecoratorsToStatic = (typeChecker, decoratedProps, newMembers, decoratorName, translateType, propDecoratorName) => {
|
|
16895
|
+
const serializeDecoratorsToStatic = (typeChecker, decoratedProps, newMembers, decoratorName, translateType, propDecoratorName, generated = []) => {
|
|
16631
16896
|
const props = decoratedProps.filter((prop) => ts.isPropertyDeclaration(prop) || ts.isGetAccessor(prop)).flatMap((prop) => {
|
|
16632
16897
|
if (retrieveTsDecorators(prop)?.find(isDecoratorNamed(propDecoratorName))) {
|
|
16633
16898
|
const { staticName } = tsPropDeclName(prop, typeChecker);
|
|
@@ -16635,7 +16900,7 @@ const serializeDecoratorsToStatic = (typeChecker, decoratedProps, newMembers, de
|
|
|
16635
16900
|
}
|
|
16636
16901
|
return [];
|
|
16637
16902
|
});
|
|
16638
|
-
const serializers = decoratedProps.filter(ts.isMethodDeclaration).flatMap((method) => parseSerializeDecorator(typeChecker, method, decoratorName, props));
|
|
16903
|
+
const serializers = [...decoratedProps.filter(ts.isMethodDeclaration).flatMap((method) => parseSerializeDecorator(typeChecker, method, decoratorName, props)), ...generated];
|
|
16639
16904
|
if (serializers.length > 0) {
|
|
16640
16905
|
if (translateType === "PropSerialize") newMembers.push(createStaticGetter("serializers", convertValueToLiteral(serializers)));
|
|
16641
16906
|
else newMembers.push(createStaticGetter("deserializers", convertValueToLiteral(serializers)));
|
|
@@ -16735,6 +17000,8 @@ const parseWatchDecorator = (typeChecker, method, decoratorName) => {
|
|
|
16735
17000
|
* @returns a TypeScript transformer factory which can be passed to
|
|
16736
17001
|
* TypeScript to transform source code during the compilation process
|
|
16737
17002
|
*/
|
|
17003
|
+
/** Source files with a `@Prop({ serialize: 'json' })`, which need a `Build` import. */
|
|
17004
|
+
const filesWithJsonProps = /* @__PURE__ */ new WeakSet();
|
|
16738
17005
|
const convertDecoratorsToStatic = (config, diagnostics, typeChecker, program, includeClassExpressions = false) => {
|
|
16739
17006
|
return (transformCtx) => {
|
|
16740
17007
|
let sourceFile;
|
|
@@ -16744,7 +17011,8 @@ const convertDecoratorsToStatic = (config, diagnostics, typeChecker, program, in
|
|
|
16744
17011
|
};
|
|
16745
17012
|
return (tsSourceFile) => {
|
|
16746
17013
|
sourceFile = tsSourceFile;
|
|
16747
|
-
|
|
17014
|
+
const updated = ts.visitEachChild(tsSourceFile, visit, transformCtx);
|
|
17015
|
+
return filesWithJsonProps.has(tsSourceFile) ? addBuildImport(updated) : updated;
|
|
16748
17016
|
};
|
|
16749
17017
|
};
|
|
16750
17018
|
};
|
|
@@ -16782,8 +17050,20 @@ const visitClassDeclaration = (config, diagnostics, typeChecker, program, classN
|
|
|
16782
17050
|
const filteredMethodsAndFields = removeStencilMethodDecorators(Array.from(classMembers), diagnostics, importAliasMap);
|
|
16783
17051
|
if (componentDecorator && ts.isClassDeclaration(classNode)) componentDecoratorToStatic(config, typeChecker, diagnostics, classNode, filteredMethodsAndFields, componentDecorator);
|
|
16784
17052
|
if (decoratedMembers.length > 0) {
|
|
16785
|
-
const
|
|
16786
|
-
const
|
|
17053
|
+
const handWritten = serializeDecoratorsToStatic(typeChecker, decoratedMembers, [], importAliasMap.get("PropSerialize"), "PropSerialize", importAliasMap.get("Prop")).concat(serializeDecoratorsToStatic(typeChecker, decoratedMembers, [], importAliasMap.get("AttrDeserialize"), "AttrDeserialize", importAliasMap.get("Prop")));
|
|
17054
|
+
const jsonProps = getJsonSerializedProps(diagnostics, typeChecker, decoratedMembers, importAliasMap.get("Prop"), handWritten);
|
|
17055
|
+
if (jsonProps.length > 0) {
|
|
17056
|
+
filteredMethodsAndFields.push(...createJsonSerializerMethods());
|
|
17057
|
+
filesWithJsonProps.add(sourceFile);
|
|
17058
|
+
}
|
|
17059
|
+
const serializers = serializeDecoratorsToStatic(typeChecker, decoratedMembers, filteredMethodsAndFields, importAliasMap.get("PropSerialize"), "PropSerialize", importAliasMap.get("Prop"), jsonProps.map((propName) => ({
|
|
17060
|
+
propName,
|
|
17061
|
+
methodName: JSON_SERIALIZE_METHOD
|
|
17062
|
+
})));
|
|
17063
|
+
const deserializers = serializeDecoratorsToStatic(typeChecker, decoratedMembers, filteredMethodsAndFields, importAliasMap.get("AttrDeserialize"), "AttrDeserialize", importAliasMap.get("Prop"), jsonProps.map((propName) => ({
|
|
17064
|
+
propName,
|
|
17065
|
+
methodName: JSON_DESERIALIZE_METHOD
|
|
17066
|
+
})));
|
|
16787
17067
|
propDecoratorsToStatic(config, diagnostics, decoratedMembers, typeChecker, program, filteredMethodsAndFields, importAliasMap.get("Prop"), serializers, deserializers);
|
|
16788
17068
|
stateDecoratorsToStatic(decoratedMembers, filteredMethodsAndFields, typeChecker, importAliasMap.get("State"));
|
|
16789
17069
|
eventDecoratorsToStatic(config, diagnostics, decoratedMembers, typeChecker, program, filteredMethodsAndFields, importAliasMap.get("Event"));
|
|
@@ -19030,7 +19310,7 @@ const performAutomaticKeyInsertion = (transformCtx) => {
|
|
|
19030
19310
|
* @returns the result of handling the node
|
|
19031
19311
|
*/
|
|
19032
19312
|
function findRenderMethodVisitor(node) {
|
|
19033
|
-
if (ts.isMethodDeclaration(node) && node.name
|
|
19313
|
+
if (ts.isMethodDeclaration(node) && ts.isIdentifier(node.name) && node.name.text === "render" && numReturnStatements(node) === 1) {
|
|
19034
19314
|
resetKeyCounter();
|
|
19035
19315
|
return ts.visitEachChild(node, jsxElementVisitor, transformCtx);
|
|
19036
19316
|
} else return ts.visitEachChild(node, findRenderMethodVisitor, transformCtx);
|
|
@@ -20392,6 +20672,11 @@ const getGeneratedExports = (config, buildCtx, loaderBundle, standalone, ssr, ty
|
|
|
20392
20672
|
import: `${outDir}/index.js`,
|
|
20393
20673
|
require: ssr.cjs ? `${outDir}/index.cjs` : void 0
|
|
20394
20674
|
};
|
|
20675
|
+
generated["./ssr-prop"] = {
|
|
20676
|
+
types: `${outDir}/ssr-prop.d.ts`,
|
|
20677
|
+
import: `${outDir}/ssr-prop.js`,
|
|
20678
|
+
require: ssr.cjs ? `${outDir}/ssr-prop.cjs` : void 0
|
|
20679
|
+
};
|
|
20395
20680
|
}
|
|
20396
20681
|
if (loaderBundle || standalone) {
|
|
20397
20682
|
const globalStyles = config.outputTargets.filter(isOutputTargetGlobalStyle);
|
|
@@ -2536,6 +2536,16 @@ interface SsrDocumentOptions {
|
|
|
2536
2536
|
* Sets `document.referrer`
|
|
2537
2537
|
*/
|
|
2538
2538
|
referrer?: string;
|
|
2539
|
+
/**
|
|
2540
|
+
* Render into one long-lived mock window, reset between renders, instead of creating a new one
|
|
2541
|
+
* for every call. Skips evaluating the whole SSR platform (runtime and every component)
|
|
2542
|
+
* on each render: most of the cost of rendering a small fragment, and a good part of a whole page.
|
|
2543
|
+
*
|
|
2544
|
+
* Applies to HTML string input (not a `Document`). One window per distinct `serializeShadowRoot` value,
|
|
2545
|
+
* and renders sharing a window run one at a time.
|
|
2546
|
+
* Defaults to `false`, except in the `ssr-wasm` output target, where it defaults to `true`.
|
|
2547
|
+
*/
|
|
2548
|
+
reuseWindow?: boolean;
|
|
2539
2549
|
/**
|
|
2540
2550
|
* Removes every `<script>` element found in the `document`. Defaults to `false`.
|
|
2541
2551
|
*/
|
|
@@ -2672,6 +2682,12 @@ interface SsrFactoryOptions extends SerializeDocumentOptions {
|
|
|
2672
2682
|
serializeToHtml: boolean;
|
|
2673
2683
|
destroyWindow: boolean;
|
|
2674
2684
|
destroyDocument: boolean;
|
|
2685
|
+
/**
|
|
2686
|
+
* A canonical key for `serializeShadowRoot`, set by the renderer. Renders with the same key
|
|
2687
|
+
* render every component the same way, so they can share an SSR platform.
|
|
2688
|
+
* @internal
|
|
2689
|
+
*/
|
|
2690
|
+
serializeShadowRootKey?: string;
|
|
2675
2691
|
}
|
|
2676
2692
|
/**
|
|
2677
2693
|
* Backwards compat for v4
|
|
@@ -191,6 +191,16 @@ interface PropOptions {
|
|
|
191
191
|
* In this case you can set the `reflect` option to `true`, since it defaults to `false`:
|
|
192
192
|
*/
|
|
193
193
|
reflect?: boolean;
|
|
194
|
+
/**
|
|
195
|
+
* Carry the prop's value from a server render to the browser in its attribute, as JSON:
|
|
196
|
+
* shorthand for a `@PropSerialize()` that writes `JSON.stringify(value)` on the server and an
|
|
197
|
+
* `@AttrDeserialize()` that reads it back with `JSON.parse()`. Attribute values that aren't
|
|
198
|
+
* valid JSON leave the prop as it is (with a warning in dev builds).
|
|
199
|
+
*
|
|
200
|
+
* For other formats (a `Map`, a `Date`...), write the `@PropSerialize()` /
|
|
201
|
+
* `@AttrDeserialize()` pair yourself.
|
|
202
|
+
*/
|
|
203
|
+
serialize?: 'json';
|
|
194
204
|
}
|
|
195
205
|
interface MethodDecorator {
|
|
196
206
|
(opts?: MethodOptions): CustomMethodDecorator<any>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ar as RafCallback, cr as TagTransformer, lr as UserBuildConditionals, n as ChildType, nr as ErrorHandler, p as HostElement, rr as FunctionalComponent, sr as ResolutionHandler, ur as VNode, v as PropsType, y as RuntimeRef } from "./index-
|
|
1
|
+
import { ar as RafCallback, cr as TagTransformer, lr as UserBuildConditionals, n as ChildType, nr as ErrorHandler, p as HostElement, rr as FunctionalComponent, sr as ResolutionHandler, ur as VNode, v as PropsType, y as RuntimeRef } from "./index-DG4wtfhx.mjs";
|
|
2
2
|
//#region src/client/client-build.d.ts
|
|
3
3
|
/**
|
|
4
4
|
* `isDev` / `isTesting` are getters, not copies: the transpile path (e.g. `@stencil/unplugin`)
|
|
@@ -2583,6 +2583,16 @@ interface SsrDocumentOptions {
|
|
|
2583
2583
|
* Sets `document.referrer`
|
|
2584
2584
|
*/
|
|
2585
2585
|
referrer?: string;
|
|
2586
|
+
/**
|
|
2587
|
+
* Render into one long-lived mock window, reset between renders, instead of creating a new one
|
|
2588
|
+
* for every call. Skips evaluating the whole SSR platform (runtime and every component)
|
|
2589
|
+
* on each render: most of the cost of rendering a small fragment, and a good part of a whole page.
|
|
2590
|
+
*
|
|
2591
|
+
* Applies to HTML string input (not a `Document`). One window per distinct `serializeShadowRoot` value,
|
|
2592
|
+
* and renders sharing a window run one at a time.
|
|
2593
|
+
* Defaults to `false`, except in the `ssr-wasm` output target, where it defaults to `true`.
|
|
2594
|
+
*/
|
|
2595
|
+
reuseWindow?: boolean;
|
|
2586
2596
|
/**
|
|
2587
2597
|
* Removes every `<script>` element found in the `document`. Defaults to `false`.
|
|
2588
2598
|
*/
|
|
@@ -2719,6 +2729,12 @@ interface SsrFactoryOptions extends SerializeDocumentOptions {
|
|
|
2719
2729
|
serializeToHtml: boolean;
|
|
2720
2730
|
destroyWindow: boolean;
|
|
2721
2731
|
destroyDocument: boolean;
|
|
2732
|
+
/**
|
|
2733
|
+
* A canonical key for `serializeShadowRoot`, set by the renderer. Renders with the same key
|
|
2734
|
+
* render every component the same way, so they can share an SSR platform.
|
|
2735
|
+
* @internal
|
|
2736
|
+
*/
|
|
2737
|
+
serializeShadowRootKey?: string;
|
|
2722
2738
|
}
|
|
2723
2739
|
/**
|
|
2724
2740
|
* Backwards compat for v4
|