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

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.
@@ -1,8 +1,8 @@
1
1
  import { n as __require } from "./chunk-CjcI7cDX.mjs";
2
- import { m as scopeCss, w as HYDRATED_CSS } from "./client-CSm3x5ke.mjs";
2
+ import { m as scopeCss, w as HYDRATED_CSS } from "./client-Dti6fFpE.mjs";
3
3
  import { A as DIST_CUSTOM_ELEMENTS, C as CMP_FLAGS, F as DIST_TYPES, H as GENERATED_DTS, J as STATS, M as DIST_HYDRATE_SCRIPT, N as DIST_LAZY, P as DIST_LAZY_LOADER, R as DOCS_JSON, T as COPY, V as EVENT_FLAGS, X as VALID_CONFIG_OUTPUT_TARGETS, Z as WATCH_FLAGS, _ as sortBy, a as fromEntries, b as toTitleCase, d as isNumber$1, f as isObject, g as pluck, h as noop, i as flatOne, j as DIST_GLOBAL_STYLES, k as DIST_COLLECTION, l as isFunction, m as mergeIntoWith, n as dashToPascalCase, o as isBoolean$1, p as isString$1, u as isIterable, w as COLLECTION_MANIFEST_FILE_NAME, x as unique, y as toDashCase, z as DOCS_README } from "./regular-expression-D5pGVpCu.mjs";
4
4
  import { $ as join$1, A as isOutputTargetCustom, B as isOutputTargetDocsCustomElementsManifest, Ct as stringifyRuntimeData, D as getComponentsFromModules, E as getComponentsDtsTypesFilePath, F as isOutputTargetDistLazy, G as isOutputTargetStats, H as isOutputTargetDocsReadme, I as isOutputTargetDistLazyLoader, J as relativeImport, K as isOutputTargetWww, L as isOutputTargetDistTypes, M as isOutputTargetDistCollection, N as isOutputTargetDistCustomElements, O as isEligiblePrimaryPackageOutputTarget, P as isOutputTargetDistGlobalStyles, Q as loadTypeScriptDiagnostics, R as isOutputTargetDocs, S as ok, T as getComponentsDtsSrcFilePath, U as isOutputTargetDocsVscode, V as isOutputTargetDocsJson, W as isOutputTargetHydrate, X as augmentDiagnosticWithNode, Z as loadTypeScriptDiagnostic, _ as getSourceMappingUrlForEndOfFile, _t as hasWarning, a as getTextDocs, at as resolve$1, b as err, bt as isGlob, d as isTsxFile, f as parsePackageJson, ft as buildError, g as getInlineSourceMappingUrlLinker, gt as hasError, h as isRemoteUrl, ht as catchError, i as generatePreamble, it as relative$1, j as isOutputTargetDist, k as isOutputTargetCopy, lt as normalizeDiagnostics, m as readPackageJson, mt as buildWarn, n as addDocBlock, nt as normalizeFsPathQuery, o as hasDependency, ot as createOnWarnFn, p as readOnlyArrayHasStringMember, pt as buildJsonFileError, q as isValidConfigOutputTarget, r as createJsVarName, rt as normalizePath, s as isDtsFile, st as loadRolldownDiagnostics, t as validateComponentTag, tt as normalizeFsPath, u as isTsFile, ut as splitLineBreaks, w as filterExcludedComponents, wt as byteSize, x as map, xt as formatComponentRuntimeMeta, y as rolldownToStencilSourceMap, yt as isRootPath, z as isOutputTargetDocsCustom } from "./validation-Byxie0Uk.mjs";
5
- import { i as CustomElementsExportBehaviorOptions, o as buildEvents, r as createNodeLogger, t as createNodeSys } from "./node-Bg-mO5dw.mjs";
5
+ import { i as CustomElementsExportBehaviorOptions, o as buildEvents, r as createNodeLogger, t as createNodeSys } from "./node-BF2jSfWg.mjs";
6
6
  import ts, { default as ts$1 } from "typescript";
7
7
  import { readFileSync } from "node:fs";
8
8
  import { basename, dirname, join } from "node:path";
@@ -26,9 +26,9 @@ import { browserslistToTargets, transform } from "lightningcss";
26
26
  import * as process$1 from "process";
27
27
  import { dataToEsm } from "@rollup/pluginutils";
28
28
  //#region src/version.ts
29
- const version = "5.0.0-alpha.3-dev.1775606156.754db56";
30
- const buildId = "1775606156";
31
- const vermoji = "🍹";
29
+ const version = "5.0.0-alpha.4";
30
+ const buildId = "1775838541";
31
+ const vermoji = "";
32
32
  /**
33
33
  * Get the installed version of a tool/dependency.
34
34
  * Handles packages with exports maps that point to subdirectories.
@@ -107,6 +107,7 @@ var CompilerContext = class {
107
107
  rolldownCacheHydrate = null;
108
108
  rolldownCacheLazy = null;
109
109
  rolldownCacheNative = null;
110
+ cssTransformCache = /* @__PURE__ */ new Map();
110
111
  cachedGlobalStyle;
111
112
  styleModeNames = /* @__PURE__ */ new Set();
112
113
  worker = null;
@@ -3219,8 +3220,19 @@ const allCmpStyles = /* @__PURE__ */ new Map();
3219
3220
  * @returns a Rolldown plugin which carries out the necessary work
3220
3221
  */
3221
3222
  const extTransformsPlugin = (config, compilerCtx, buildCtx) => {
3223
+ let transformCount = 0;
3224
+ let cacheHits = 0;
3225
+ let firstTransformStart = null;
3226
+ let lastTransformEnd = 0;
3222
3227
  return {
3223
3228
  name: "extTransformsPlugin",
3229
+ buildEnd() {
3230
+ if (config.logLevel === "debug" && firstTransformStart !== null) {
3231
+ const totalElapsed = lastTransformEnd - firstTransformStart;
3232
+ const computed = transformCount - cacheHits;
3233
+ buildCtx.debug(`extTransformsPlugin: ${transformCount} stylesheets in ${totalElapsed.toFixed(1)}ms wall-clock` + (cacheHits > 0 ? ` (${computed} computed, ${cacheHits} from cache)` : ""));
3234
+ }
3235
+ },
3224
3236
  async transform(_, id) {
3225
3237
  if (/\0/.test(id)) return null;
3226
3238
  /**
@@ -3230,24 +3242,53 @@ const extTransformsPlugin = (config, compilerCtx, buildCtx) => {
3230
3242
  if (!compilerCtx.worker) return null;
3231
3243
  const { data } = parseImportPath(id);
3232
3244
  if (data != null) {
3233
- let cmpStyles = void 0;
3234
- let cmp = void 0;
3235
3245
  const filePath = normalizeFsPath(id);
3236
- const code = await compilerCtx.fs.readFile(filePath);
3237
- if (typeof code !== "string") return null;
3246
+ const wasCached = compilerCtx.cssTransformCache.has(id);
3247
+ if (!wasCached) {
3248
+ const code = await compilerCtx.fs.readFile(filePath);
3249
+ if (typeof code !== "string") compilerCtx.cssTransformCache.set(id, null);
3250
+ else {
3251
+ const pluginTransforms = await runPluginTransformsEsmImports(config, compilerCtx, buildCtx, code, filePath);
3252
+ const cssTransformResults = await compilerCtx.worker.transformCssToEsm({
3253
+ file: pluginTransforms.id,
3254
+ input: pluginTransforms.code,
3255
+ tag: data.tag,
3256
+ tags: buildCtx.components.map((c) => c.tagName),
3257
+ addTagTransformers: !!buildCtx.config.extras.additionalTagTransformers,
3258
+ encapsulation: data.encapsulation,
3259
+ mode: data.mode,
3260
+ sourceMap: config.sourceMap,
3261
+ minify: config.minifyCss,
3262
+ autoprefixer: config.autoprefixCss,
3263
+ docs: config.buildDocs
3264
+ });
3265
+ compilerCtx.cssTransformCache.set(id, {
3266
+ pluginTransformId: pluginTransforms.id,
3267
+ pluginTransformCode: pluginTransforms.code,
3268
+ pluginTransformDependencies: pluginTransforms.dependencies,
3269
+ pluginTransformDiagnostics: pluginTransforms.diagnostics,
3270
+ cssTransformOutput: cssTransformResults
3271
+ });
3272
+ }
3273
+ }
3274
+ const cacheEntry = compilerCtx.cssTransformCache.get(id);
3275
+ if (wasCached) cacheHits++;
3276
+ if (cacheEntry == null) return null;
3238
3277
  /**
3239
3278
  * add file to watch list if it is outside of the `srcDir` config path
3240
3279
  */
3241
3280
  if (config.watch && (id.startsWith("/") || id.startsWith(".")) && !id.startsWith(config.srcDir)) compilerCtx.addWatchFile(id.split("?")[0]);
3242
- const pluginTransforms = await runPluginTransformsEsmImports(config, compilerCtx, buildCtx, code, filePath);
3281
+ if (firstTransformStart === null) firstTransformStart = performance.now();
3282
+ let cmpStyles = void 0;
3283
+ let cmp = void 0;
3243
3284
  if (data.tag) {
3244
3285
  cmp = buildCtx.components.find((c) => c.tagName === data.tag);
3245
3286
  if (cmp && !cmp.isCollectionDependency && compilerCtx.moduleMap.get(cmp.sourceFilePath)) {
3246
3287
  const collectionDirs = config.outputTargets.filter(isOutputTargetDistCollection);
3247
- const relPath = relative$1(config.srcDir, pluginTransforms.id);
3288
+ const relPath = relative$1(config.srcDir, cacheEntry.pluginTransformId);
3248
3289
  await Promise.all(collectionDirs.map(async (outputTarget) => {
3249
3290
  const collectionPath = join$1(outputTarget.collectionDir, relPath);
3250
- await compilerCtx.fs.writeFile(collectionPath, pluginTransforms.code);
3291
+ await compilerCtx.fs.writeFile(collectionPath, cacheEntry.pluginTransformCode);
3251
3292
  }));
3252
3293
  }
3253
3294
  /**
@@ -3257,46 +3298,35 @@ const extTransformsPlugin = (config, compilerCtx, buildCtx) => {
3257
3298
  if (!allCmpStyles.has(scopeId)) allCmpStyles.set(scopeId, /* @__PURE__ */ new Map());
3258
3299
  cmpStyles = allCmpStyles.get(scopeId);
3259
3300
  }
3260
- const cssTransformResults = await compilerCtx.worker.transformCssToEsm({
3261
- file: pluginTransforms.id,
3262
- input: pluginTransforms.code,
3263
- tag: data.tag,
3264
- tags: buildCtx.components.map((c) => c.tagName),
3265
- addTagTransformers: !!buildCtx.config.extras.additionalTagTransformers,
3266
- encapsulation: data.encapsulation,
3267
- mode: data.mode,
3268
- sourceMap: config.sourceMap,
3269
- minify: config.minifyCss,
3270
- autoprefixer: config.autoprefixCss,
3271
- docs: config.buildDocs
3272
- });
3301
+ transformCount++;
3302
+ lastTransformEnd = performance.now();
3273
3303
  /**
3274
3304
  * persist component styles for transformed stylesheet
3275
3305
  */
3276
- if (cmpStyles) cmpStyles.set(filePath, cssTransformResults.styleText);
3306
+ if (cmpStyles) cmpStyles.set(filePath, cacheEntry.cssTransformOutput.styleText);
3277
3307
  if (cmp) {
3278
3308
  cmp.styleDocs ||= [];
3279
- mergeIntoWith(cmp.styleDocs, cssTransformResults.styleDocs, (docs) => `${docs.name},${docs.mode}`);
3309
+ mergeIntoWith(cmp.styleDocs, cacheEntry.cssTransformOutput.styleDocs, (docs) => `${docs.name},${docs.mode}`);
3280
3310
  }
3281
- for (const dep of pluginTransforms.dependencies) {
3311
+ for (const dep of cacheEntry.pluginTransformDependencies) {
3282
3312
  this.addWatchFile(dep);
3283
3313
  compilerCtx.addWatchFile(dep);
3284
3314
  }
3285
- buildCtx.diagnostics.push(...pluginTransforms.diagnostics);
3286
- buildCtx.diagnostics.push(...cssTransformResults.diagnostics);
3287
- if (hasError(cssTransformResults.diagnostics) || hasError(pluginTransforms.diagnostics)) this.error("Plugin CSS transform error");
3315
+ buildCtx.diagnostics.push(...cacheEntry.pluginTransformDiagnostics);
3316
+ buildCtx.diagnostics.push(...cacheEntry.cssTransformOutput.diagnostics);
3317
+ if (hasError(cacheEntry.cssTransformOutput.diagnostics) || hasError(cacheEntry.pluginTransformDiagnostics)) this.error("Plugin CSS transform error");
3288
3318
  /**
3289
3319
  * if the style has updated, compose all styles for the component
3290
3320
  */
3291
3321
  if (!buildCtx.stylesUpdated.some((s) => {
3292
- return s.styleTag === data.tag && s.styleMode === data.mode && s.styleText === cssTransformResults.styleText;
3322
+ return s.styleTag === data.tag && s.styleMode === data.mode && s.styleText === cacheEntry.cssTransformOutput.styleText;
3293
3323
  }) && data.tag && data.mode) {
3294
3324
  const externalStyles = cmp?.styles?.[0]?.externalStyles;
3295
3325
  /**
3296
3326
  * if component has external styles, use a list to keep the order to which
3297
3327
  * styles are applied.
3298
3328
  */
3299
- const styleText = cmpStyles ? externalStyles ? externalStyles.map((es) => cmpStyles.get(es.originalComponentPath) || cmpStyles.get(es.absolutePath)).join("\n") : [...cmpStyles.values()].join("\n") : cssTransformResults.styleText;
3329
+ const styleText = cmpStyles ? externalStyles ? externalStyles.map((es) => cmpStyles.get(es.originalComponentPath) || cmpStyles.get(es.absolutePath)).join("\n") : [...cmpStyles.values()].join("\n") : cacheEntry.cssTransformOutput.styleText;
3300
3330
  buildCtx.stylesUpdated.push({
3301
3331
  styleTag: data.tag,
3302
3332
  styleMode: data.mode,
@@ -3304,8 +3334,8 @@ const extTransformsPlugin = (config, compilerCtx, buildCtx) => {
3304
3334
  });
3305
3335
  }
3306
3336
  return {
3307
- code: cssTransformResults.output,
3308
- map: cssTransformResults.map,
3337
+ code: cacheEntry.cssTransformOutput.output,
3338
+ map: cacheEntry.cssTransformOutput.map,
3309
3339
  moduleSideEffects: false
3310
3340
  };
3311
3341
  }
@@ -3538,8 +3568,25 @@ const createModule = (staticSourceFile, staticSourceFileText, emitFilepath) => (
3538
3568
  * @returns the rolldown plugin for handling TypeScript files.
3539
3569
  */
3540
3570
  const typescriptPlugin = (compilerCtx, bundleOpts, config) => {
3571
+ /**
3572
+ * Cache the result of `ts.transpileModule` for a given file, keyed by the
3573
+ * normalized file path. Rolldown re-runs the `transform` hook for every
3574
+ * `.generate()` call on the same build object (once per output format:
3575
+ * esm-browser, esm, cjs), so without this cache a 220-component project
3576
+ * would call `ts.transpileModule` 660 times; with it, only 220.
3577
+ *
3578
+ * The cache is intentionally scoped to this plugin instance (one per
3579
+ * `bundleOutput` call) so it is automatically discarded when the Rolldown
3580
+ * build object is garbage-collected — no manual invalidation required.
3581
+ */
3582
+ const transformCache = /* @__PURE__ */ new Map();
3583
+ let cacheHits = 0;
3584
+ let cacheMisses = 0;
3541
3585
  return {
3542
3586
  name: `${bundleOpts.id}TypescriptPlugin`,
3587
+ buildEnd() {
3588
+ if (config.logLevel === "debug" && cacheMisses > 0) config.logger.debug(`${bundleOpts.id}TypescriptPlugin: ${cacheMisses} transforms computed` + (cacheHits > 0 ? `, ${cacheHits} from cache` : ""));
3589
+ },
3543
3590
  load(id) {
3544
3591
  if (isAbsolute(id)) {
3545
3592
  const module = getModule(compilerCtx, normalizeFsPath(id));
@@ -3560,13 +3607,28 @@ const typescriptPlugin = (compilerCtx, bundleOpts, config) => {
3560
3607
  },
3561
3608
  transform(_code, id) {
3562
3609
  if (isAbsolute(id)) {
3563
- const mod = getModule(compilerCtx, normalizeFsPath(id));
3610
+ const fsFilePath = normalizeFsPath(id);
3611
+ const mod = getModule(compilerCtx, fsFilePath);
3564
3612
  if (mod?.cmps) {
3613
+ const cached = transformCache.get(fsFilePath);
3614
+ if (cached) {
3615
+ cacheHits++;
3616
+ const sourceMap = cached.sourceMapText ? JSON.parse(cached.sourceMapText) : null;
3617
+ return {
3618
+ code: cached.outputText,
3619
+ map: sourceMap
3620
+ };
3621
+ }
3622
+ cacheMisses++;
3565
3623
  const tsResult = ts.transpileModule(mod.staticSourceFileText, {
3566
3624
  compilerOptions: config.tsCompilerOptions,
3567
3625
  fileName: mod.sourceFilePath,
3568
3626
  transformers: { before: bundleOpts.customBeforeTransformers ?? [] }
3569
3627
  });
3628
+ transformCache.set(fsFilePath, {
3629
+ outputText: tsResult.outputText,
3630
+ sourceMapText: tsResult.sourceMapText ?? null
3631
+ });
3570
3632
  const sourceMap = tsResult.sourceMapText ? JSON.parse(tsResult.sourceMapText) : null;
3571
3633
  return {
3572
3634
  code: tsResult.outputText,
@@ -4308,7 +4370,7 @@ const getRolldownOptions = (config, compilerCtx, buildCtx, bundleOpts) => {
4308
4370
  transform: { define: { "process.env.NODE_ENV": config.devMode ? "\"development\"" : "\"production\"" } },
4309
4371
  checks: {
4310
4372
  preferBuiltinFeature: false,
4311
- pluginTimings: config.devMode
4373
+ pluginTimings: config.logLevel === "debug"
4312
4374
  },
4313
4375
  moduleTypes: {
4314
4376
  ".css": "js",
@@ -6666,7 +6728,7 @@ const generateHydrateApp = async (config, compilerCtx, buildCtx, outputTargets)
6666
6728
  }],
6667
6729
  treeshake: false,
6668
6730
  onwarn: createOnWarnFn(buildCtx.diagnostics),
6669
- checks: { pluginTimings: config.devMode }
6731
+ checks: { pluginTimings: config.logLevel === "debug" }
6670
6732
  });
6671
6733
  const buildPromises = [buildHydrateAppFor("esm", rolldownAppBuild, config, compilerCtx, buildCtx, outputTargets)];
6672
6734
  if (outputTargets.some((o) => o.cjs)) buildPromises.push(buildHydrateAppFor("cjs", rolldownAppBuild, config, compilerCtx, buildCtx, outputTargets));
@@ -7511,10 +7573,12 @@ const outputLazy = async (config, compilerCtx, buildCtx) => {
7511
7573
  [LAZY_BROWSER_ENTRY_ID]: getLazyEntry(true)
7512
7574
  }
7513
7575
  };
7576
+ const entryGenStart = performance.now();
7514
7577
  generateEntryModules(config, buildCtx);
7515
7578
  buildCtx.entryModules.forEach((entryModule) => {
7516
7579
  bundleOpts.inputs[entryModule.entryKey] = entryModule.entryKey;
7517
7580
  });
7581
+ buildCtx.debug(`lazy: generateEntryModules: ${(performance.now() - entryGenStart).toFixed(1)}ms`);
7518
7582
  const rolldownBuild = await bundleOutput(config, compilerCtx, buildCtx, bundleOpts);
7519
7583
  if (rolldownBuild != null) {
7520
7584
  (await Promise.all([
@@ -14264,6 +14328,7 @@ const tsResolveModuleName = (config, compilerCtx, moduleName, containingFile) =>
14264
14328
  const host = patchTsSystemFileSystem(config, config.sys, compilerCtx.fs, ts.sys);
14265
14329
  const compilerOptions = { ...config.tsCompilerOptions };
14266
14330
  compilerOptions.resolveJsonModule = true;
14331
+ compilerOptions.noResolve = false;
14267
14332
  return resolveModuleName(moduleName, containingFile, compilerOptions, host);
14268
14333
  }
14269
14334
  return null;
@@ -14429,6 +14494,41 @@ const deDupeMembers = (dedupeMembers, staticMembers) => {
14429
14494
  }));
14430
14495
  };
14431
14496
  /**
14497
+ * When a parent-class source file is fetched directly from disk (via
14498
+ * {@link tsGetSourceFile}) rather than from the compiler's moduleMap cache, it
14499
+ * arrives with its original decorator syntax intact. The static-meta parsers
14500
+ * (`parseStaticProps`, `parseStaticStates`, etc.) only understand the static-
14501
+ * getter form produced by {@link convertDecoratorsToStatic}.
14502
+ *
14503
+ * This helper creates a self-contained mini TypeScript program for the single
14504
+ * file and runs the decorator→static transformer on it, returning the
14505
+ * transformed source file. Prop types may be under-resolved (external imports
14506
+ * are not available in the mini program) and will fall back to `any`, which is
14507
+ * acceptable for the purpose of walking the inheritance chain.
14508
+ *
14509
+ * @param sourceFile the raw (decorator-syntax) source file from disk
14510
+ * @param config the current Stencil validated config
14511
+ * @param target the script target to use when converting decorators to static (if needed)
14512
+ * @returns the source file with decorators converted to static getters
14513
+ */
14514
+ function convertDiskSourceFileDecorators(sourceFile, config, target = ts.ScriptTarget.ESNext) {
14515
+ const compilerOptions = {
14516
+ ...config.tsCompilerOptions,
14517
+ experimentalDecorators: true,
14518
+ noLib: true,
14519
+ noResolve: true,
14520
+ isolatedModules: false,
14521
+ target
14522
+ };
14523
+ const host = ts.createCompilerHost(compilerOptions);
14524
+ const program = ts.createProgram([sourceFile.fileName], compilerOptions, host);
14525
+ const typeChecker = program.getTypeChecker();
14526
+ const ownSourceFile = program.getSourceFile(sourceFile.fileName) ?? sourceFile;
14527
+ const result = ts.transform(ownSourceFile, [convertDecoratorsToStatic(config, [], typeChecker, program)]);
14528
+ const printed = ts.createPrinter({ removeComments: false }).printFile(result.transformed[0]);
14529
+ return ts.createSourceFile(sourceFile.fileName, printed, target, true);
14530
+ }
14531
+ /**
14432
14532
  * Helper function to resolve and process an extended class from a module.
14433
14533
  * This handles:
14434
14534
  * 1. Resolving the module path
@@ -14443,12 +14543,13 @@ const deDupeMembers = (dedupeMembers, staticMembers) => {
14443
14543
  * @param moduleSpecifier - the module path to resolve
14444
14544
  * @param className - the name of the class to find in the resolved module
14445
14545
  * @param dependentClasses - the array to add found classes to
14446
- * @param keepLooking - whether to continue recursively looking for more extended classes
14447
14546
  * @param typeChecker - the TypeScript type checker
14448
14547
  * @param ogModule - the original module file of the class declaration
14548
+ * @param targetScriptTarget - the script target to use when converting decorators to static (if needed)
14449
14549
  * @returns the found class declaration or undefined
14450
14550
  */
14451
- function resolveAndProcessExtendedClass(compilerCtx, buildCtx, classDeclaration, currentSource, moduleSpecifier, className, dependentClasses, keepLooking, typeChecker, ogModule) {
14551
+ function resolveAndProcessExtendedClass(compilerCtx, buildCtx, classDeclaration, currentSource, moduleSpecifier, className, dependentClasses, typeChecker, ogModule, targetScriptTarget = ts.ScriptTarget.ESNext) {
14552
+ let keepLooking = true;
14452
14553
  const foundFile = tsResolveModuleName(buildCtx.config, compilerCtx, moduleSpecifier, currentSource.fileName);
14453
14554
  if (!foundFile?.resolvedModule || !className) return;
14454
14555
  let foundSource = compilerCtx.moduleMap.get(foundFile.resolvedModule.resolvedFileName)?.staticSourceFile;
@@ -14461,6 +14562,7 @@ function resolveAndProcessExtendedClass(compilerCtx, buildCtx, classDeclaration,
14461
14562
  if (!buildCtx.config._isTesting) augmentDiagnosticWithNode(err, classDeclaration);
14462
14563
  return;
14463
14564
  }
14565
+ foundSource = convertDiskSourceFileDecorators(foundSource, buildCtx.config, targetScriptTarget);
14464
14566
  }
14465
14567
  const matchedStatement = foundSource.statements.find(matchesNamedDeclaration(className));
14466
14568
  if (!matchedStatement) {
@@ -14556,6 +14658,7 @@ function buildExtendsTree(compilerCtx, classDeclaration, dependentClasses, typeC
14556
14658
  if (!hasHeritageClauses?.length) return dependentClasses;
14557
14659
  const extendsClause = hasHeritageClauses.find((clause) => clause.token === ts.SyntaxKind.ExtendsKeyword);
14558
14660
  if (!extendsClause) return dependentClasses;
14661
+ const targetScriptTarget = (ogModule?.staticSourceFile)?.languageVersion ?? ts.ScriptTarget.ESNext;
14559
14662
  let classIdentifiers = [];
14560
14663
  let foundClassDeclaration;
14561
14664
  let keepLooking = true;
@@ -14641,13 +14744,13 @@ function buildExtendsTree(compilerCtx, classDeclaration, dependentClasses, typeC
14641
14744
  if (statement.importClause?.namedBindings && ts.isNamedImports(statement.importClause?.namedBindings)) statement.importClause?.namedBindings.elements.forEach((element) => {
14642
14745
  if (element.name.getText() === extendee.getText()) {
14643
14746
  const className = element.propertyName?.getText() || element.name.getText();
14644
- resolveAndProcessExtendedClass(compilerCtx, buildCtx, classDeclaration, currentSource, statement.moduleSpecifier.getText().replaceAll(/['"]/g, ""), className, dependentClasses, keepLooking, typeChecker, ogModule);
14747
+ resolveAndProcessExtendedClass(compilerCtx, buildCtx, classDeclaration, currentSource, statement.moduleSpecifier.getText().replaceAll(/['"]/g, ""), className, dependentClasses, typeChecker, ogModule, targetScriptTarget);
14645
14748
  }
14646
14749
  });
14647
14750
  });
14648
14751
  if (!importStatements.length) currentSource.statements.filter(ts.isVariableStatement).forEach((statement) => {
14649
14752
  statement.declarationList.declarations.forEach((declaration) => {
14650
- if (declaration.initializer && ts.isCallExpression(declaration.initializer) && ts.isIdentifier(declaration.initializer.expression) && declaration.initializer.expression.escapedText === "require" && declaration.initializer.arguments.length === 1 && ts.isStringLiteral(declaration.initializer.arguments[0])) resolveAndProcessExtendedClass(compilerCtx, buildCtx, classDeclaration, currentSource, declaration.initializer.arguments[0].text.replaceAll(/['"]/g, ""), extendee.getText(), dependentClasses, keepLooking, typeChecker, ogModule);
14753
+ if (declaration.initializer && ts.isCallExpression(declaration.initializer) && ts.isIdentifier(declaration.initializer.expression) && declaration.initializer.expression.escapedText === "require" && declaration.initializer.arguments.length === 1 && ts.isStringLiteral(declaration.initializer.arguments[0])) resolveAndProcessExtendedClass(compilerCtx, buildCtx, classDeclaration, currentSource, declaration.initializer.arguments[0].text.replaceAll(/['"]/g, ""), extendee.getText(), dependentClasses, typeChecker, ogModule, targetScriptTarget);
14651
14754
  });
14652
14755
  });
14653
14756
  }
@@ -14688,9 +14791,10 @@ function mergeExtendedClassMeta(compilerCtx, typeChecker, buildCtx, cmpNode, sta
14688
14791
  const mixinEvents = parseStaticEvents(extendedStaticMembers) ?? [];
14689
14792
  const isMixin = mixinProps.length > 0 || mixinStates.length > 0 || mixinMethods.length > 0 || mixinEvents.length > 0;
14690
14793
  const module = compilerCtx.moduleMap.get(extendedClass.fileName);
14691
- if (!module) return;
14692
- module.isMixin = isMixin;
14693
- module.isExtended = true;
14794
+ if (module) {
14795
+ module.isMixin = isMixin;
14796
+ module.isExtended = true;
14797
+ }
14694
14798
  doesExtend = true;
14695
14799
  if ((mixinProps.length > 0 || mixinStates.length > 0) && !detectModernPropDeclarations(extendedClass.classNode, extendedClass.sourceFile)) {
14696
14800
  const err = buildWarn(buildCtx.diagnostics);
@@ -17893,25 +17997,29 @@ const createInMemoryFs = (sys) => {
17893
17997
  * modify the in-memory filesystem cache. Otherwise it will create directories
17894
17998
  * in the real FS.
17895
17999
  *
18000
+ * All directories are created concurrently using `{ recursive: true }`, which
18001
+ * lets the OS handle parent-before-child ordering without requiring the sorted
18002
+ * sequential loop that was previously needed.
18003
+ *
17896
18004
  * @param dirsToEnsure directories we want to ensure exist
17897
18005
  * @param inMemoryOnly whether directory creation should be confined to the
17898
18006
  * in-memory cache
17899
18007
  * @returns a Promise wrapping a list of directories created
17900
18008
  */
17901
18009
  const commitEnsureDirs = async (dirsToEnsure, inMemoryOnly) => {
17902
- const dirsAdded = [];
17903
- for (const dirPath of dirsToEnsure) {
18010
+ return (await Promise.all(dirsToEnsure.map(async (dirPath) => {
17904
18011
  const item = getItem(dirPath);
17905
- if (item.exists === true && item.isDirectory === true) continue;
18012
+ if (item.exists === true && item.isDirectory === true) return null;
17906
18013
  try {
17907
18014
  item.exists = true;
17908
18015
  item.isDirectory = true;
17909
18016
  item.isFile = false;
17910
- if (!inMemoryOnly) await sys.createDir(dirPath);
17911
- dirsAdded.push(dirPath);
17912
- } catch {}
17913
- }
17914
- return dirsAdded;
18017
+ if (!inMemoryOnly) await sys.createDir(dirPath, { recursive: true });
18018
+ return dirPath;
18019
+ } catch {
18020
+ return null;
18021
+ }
18022
+ }))).filter((d) => d !== null);
17915
18023
  };
17916
18024
  /**
17917
18025
  * Commit copy file operations to disk
@@ -18250,6 +18358,26 @@ const createWorkerMainContext = (workerCtrl) => ({
18250
18358
  //#endregion
18251
18359
  //#region src/compiler/optimize/autoprefixer.ts
18252
18360
  /**
18361
+ * Cache for resolved browserslist targets to avoid re-parsing for every stylesheet.
18362
+ * The key is a JSON-stringified version of the browser targets array.
18363
+ */
18364
+ let cachedTargets = null;
18365
+ let cachedTargetKey = null;
18366
+ /**
18367
+ * Get Lightning CSS targets from browser targets, using a cache to avoid
18368
+ * repeatedly parsing the same browserslist query for every stylesheet.
18369
+ *
18370
+ * @param browserTargets array of browserslist query strings
18371
+ * @returns Lightning CSS targets object
18372
+ */
18373
+ const getTargets = (browserTargets) => {
18374
+ const key = JSON.stringify(browserTargets);
18375
+ if (cachedTargetKey === key && cachedTargets !== null) return cachedTargets;
18376
+ cachedTargets = browserslistToTargets(browserslist(browserTargets));
18377
+ cachedTargetKey = key;
18378
+ return cachedTargets;
18379
+ };
18380
+ /**
18253
18381
  * Autoprefix a CSS string, adding vendor prefixes to ensure that what is
18254
18382
  * written in the CSS will render correctly across our range of supported
18255
18383
  * browsers. Uses Lightning CSS to add vendor prefixes based on a browserslist
@@ -18258,24 +18386,26 @@ const createWorkerMainContext = (workerCtrl) => ({
18258
18386
  * @param cssText the CSS text to be prefixed
18259
18387
  * @param opts options controlling which browsers to target, or `null` to use
18260
18388
  * the default browser targets
18389
+ * @param filePath optional file path for error reporting
18390
+ * @param minify whether to also minify the CSS (default: false)
18261
18391
  * @returns a Promise wrapping the prefixed CSS and any diagnostics
18262
18392
  */
18263
- const autoprefixCss = async (cssText, opts) => {
18393
+ const autoprefixCss = async (cssText, opts, filePath, minify = false) => {
18264
18394
  const output = {
18265
18395
  output: cssText,
18266
18396
  diagnostics: []
18267
18397
  };
18268
18398
  try {
18269
- const targets = browserslistToTargets(browserslist(opts != null && typeof opts === "object" && Array.isArray(opts.targets) ? opts.targets : DEFAULT_BROWSER_TARGETS));
18399
+ const targets = getTargets(opts != null && typeof opts === "object" && Array.isArray(opts.targets) ? opts.targets : DEFAULT_BROWSER_TARGETS);
18270
18400
  output.output = transform({
18271
- filename: "style.css",
18401
+ filename: filePath ?? "style.css",
18272
18402
  code: Buffer.from(cssText),
18273
18403
  targets,
18274
- minify: false
18404
+ minify
18275
18405
  }).code.toString();
18276
18406
  } catch (e) {
18277
18407
  const diagnostic = {
18278
- header: `Autoprefix CSS`,
18408
+ header: `CSS Error`,
18279
18409
  messageText: `CSS Error: ${e}`,
18280
18410
  level: `error`,
18281
18411
  type: `css`,
@@ -18283,6 +18413,30 @@ const autoprefixCss = async (cssText, opts) => {
18283
18413
  };
18284
18414
  if (typeof e.name === "string") diagnostic.header = e.name;
18285
18415
  if (typeof e.message === "string") diagnostic.messageText = e.message;
18416
+ if (filePath) diagnostic.absFilePath = filePath;
18417
+ else if (typeof e.fileName === "string" && e.fileName !== "style.css") diagnostic.absFilePath = e.fileName;
18418
+ if (e.loc && typeof e.loc.line === "number") {
18419
+ diagnostic.lineNumber = e.loc.line;
18420
+ diagnostic.columnNumber = e.loc.column ?? 1;
18421
+ const lines = (typeof e.source === "string" ? e.source : cssText).split("\n");
18422
+ const errorLine = e.loc.line;
18423
+ const errorColumn = e.loc.column ?? 1;
18424
+ const startLine = Math.max(1, errorLine - 2);
18425
+ const endLine = Math.min(lines.length, errorLine + 2);
18426
+ const printLines = [];
18427
+ for (let lineNum = startLine; lineNum <= endLine; lineNum++) {
18428
+ const lineIndex = lineNum - 1;
18429
+ const lineText = lines[lineIndex] ?? "";
18430
+ printLines.push({
18431
+ lineIndex,
18432
+ lineNumber: lineNum,
18433
+ text: lineText,
18434
+ errorCharStart: lineNum === errorLine ? errorColumn - 1 : -1,
18435
+ errorLength: lineNum === errorLine ? Math.max(1, lineText.length - (errorColumn - 1)) : 0
18436
+ });
18437
+ }
18438
+ diagnostic.lines = printLines;
18439
+ }
18286
18440
  output.diagnostics.push(diagnostic);
18287
18441
  }
18288
18442
  return output;
@@ -19036,7 +19190,7 @@ const optimizeCss = async (inputOpts) => {
19036
19190
  diagnostics: []
19037
19191
  };
19038
19192
  if (inputOpts.autoprefixer !== false && inputOpts.autoprefixer !== null) {
19039
- result = await autoprefixCss(inputOpts.input, inputOpts.autoprefixer ?? null);
19193
+ result = await autoprefixCss(inputOpts.input, inputOpts.autoprefixer ?? null, inputOpts.filePath);
19040
19194
  if (hasError(result.diagnostics)) return result;
19041
19195
  }
19042
19196
  if (inputOpts.minify !== false) result.output = await minifyCss({
@@ -21242,7 +21396,8 @@ const getTranspileConfig = (input) => {
21242
21396
  file: compileOpts.file,
21243
21397
  style: compileOpts.style,
21244
21398
  styleImportData: compileOpts.styleImportData,
21245
- target: compileOpts.target
21399
+ target: compileOpts.target,
21400
+ extraFiles: input.extraFiles
21246
21401
  };
21247
21402
  return {
21248
21403
  compileOpts,
@@ -21370,9 +21525,20 @@ const transpileModule = (config, input, transformOpts) => {
21370
21525
  if (tsCompilerOptions.jsx != null && !isAutomaticRuntime && !isString$1(tsCompilerOptions.jsxFragmentFactory)) tsCompilerOptions.jsxFragmentFactory = "Fragment";
21371
21526
  if (tsCompilerOptions.paths && !isString$1(tsCompilerOptions.baseUrl)) tsCompilerOptions.baseUrl = ".";
21372
21527
  const sourceFile = ts.createSourceFile(sourceFilePath, input, tsCompilerOptions.target);
21373
- const program = ts.createProgram([sourceFilePath], tsCompilerOptions, {
21528
+ const extraSourceFiles = /* @__PURE__ */ new Map();
21529
+ if (transformOpts.extraFiles) {
21530
+ const currentDir = normalizePath(transformOpts.currentDirectory || process.cwd());
21531
+ for (const [filePath, text] of Object.entries(transformOpts.extraFiles)) {
21532
+ const resolvedPath = normalizePath(filePath.startsWith("/") ? filePath : join$1(currentDir, filePath));
21533
+ extraSourceFiles.set(resolvedPath, ts.createSourceFile(resolvedPath, text, tsCompilerOptions.target));
21534
+ }
21535
+ tsCompilerOptions.noResolve = false;
21536
+ }
21537
+ const compilerHost = {
21374
21538
  getSourceFile: (fileName) => {
21375
- return normalizePath(fileName) === normalizePath(sourceFilePath) ? sourceFile : void 0;
21539
+ const normalized = normalizePath(fileName);
21540
+ if (normalized === normalizePath(sourceFilePath)) return sourceFile;
21541
+ return extraSourceFiles.get(normalized);
21376
21542
  },
21377
21543
  writeFile: (name, text) => {
21378
21544
  if (name.endsWith(".js.map") || name.endsWith(".mjs.map")) results.map = text;
@@ -21383,12 +21549,45 @@ const transpileModule = (config, input, transformOpts) => {
21383
21549
  getCanonicalFileName: (fileName) => fileName,
21384
21550
  getCurrentDirectory: () => transformOpts.currentDirectory || process.cwd(),
21385
21551
  getNewLine: () => ts.sys.newLine || "\n",
21386
- fileExists: (fileName) => normalizePath(fileName) === normalizePath(sourceFilePath),
21552
+ fileExists: (fileName) => {
21553
+ const normalized = normalizePath(fileName);
21554
+ return normalized === normalizePath(sourceFilePath) || extraSourceFiles.has(normalized);
21555
+ },
21387
21556
  readFile: () => "",
21388
21557
  directoryExists: () => true,
21389
21558
  getDirectories: () => []
21390
- });
21559
+ };
21560
+ const program = ts.createProgram([sourceFilePath, ...extraSourceFiles.keys()], tsCompilerOptions, compilerHost);
21391
21561
  const typeChecker = program.getTypeChecker();
21562
+ if (extraSourceFiles.size > 0) {
21563
+ const miniCompilerHost = {
21564
+ getSourceFile: (fileName) => extraSourceFiles.get(normalizePath(fileName)),
21565
+ writeFile: () => {},
21566
+ getDefaultLibFileName: () => "lib.d.ts",
21567
+ useCaseSensitiveFileNames: () => false,
21568
+ getCanonicalFileName: (f) => f,
21569
+ getCurrentDirectory: () => transformOpts.currentDirectory || process.cwd(),
21570
+ getNewLine: () => ts.sys.newLine || "\n",
21571
+ fileExists: (f) => extraSourceFiles.has(normalizePath(f)),
21572
+ readFile: () => "",
21573
+ directoryExists: () => true,
21574
+ getDirectories: () => []
21575
+ };
21576
+ const miniProgram = ts.createProgram([...extraSourceFiles.keys()], {
21577
+ ...tsCompilerOptions,
21578
+ noResolve: true
21579
+ }, miniCompilerHost);
21580
+ const miniTypeChecker = miniProgram.getTypeChecker();
21581
+ const decoratorConverter = convertDecoratorsToStatic(config, buildCtx.diagnostics, miniTypeChecker, miniProgram);
21582
+ for (const [resolvedPath, rawSource] of extraSourceFiles) {
21583
+ const transformResult = ts.transform(rawSource, [decoratorConverter], tsCompilerOptions);
21584
+ const processedSource = transformResult.transformed[0];
21585
+ transformResult.dispose();
21586
+ const moduleFile = getModuleLegacy(compilerCtx, resolvedPath);
21587
+ moduleFile.staticSourceFile = processedSource;
21588
+ moduleFile.staticSourceFileText = processedSource.getFullText?.() ?? rawSource.text;
21589
+ }
21590
+ }
21392
21591
  const transformers = {
21393
21592
  before: [
21394
21593
  convertDecoratorsToStatic(config, buildCtx.diagnostics, typeChecker, program),
@@ -21404,7 +21603,8 @@ const transpileModule = (config, input, transformOpts) => {
21404
21603
  }
21405
21604
  if (transformOpts.componentExport === "customelement" || transformOpts.componentExport === "module") transformers.after.push(nativeComponentTransform(compilerCtx, transformOpts, buildCtx));
21406
21605
  else transformers.after.push(lazyComponentTransform(compilerCtx, transformOpts, buildCtx));
21407
- program.emit(void 0, void 0, void 0, false, transformers);
21606
+ const emitTarget = extraSourceFiles.size > 0 ? program.getSourceFile(sourceFilePath) : void 0;
21607
+ program.emit(emitTarget, void 0, void 0, false, transformers);
21408
21608
  const tsDiagnostics = [...program.getSyntacticDiagnostics()];
21409
21609
  if (config.validateTypes) tsDiagnostics.push(...program.getOptionsDiagnostics());
21410
21610
  buildCtx.diagnostics.push(...loadTypeScriptDiagnostics(tsDiagnostics));