@stencil/core 2.15.1 → 2.16.1-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/cli/index.cjs +115 -27
  2. package/cli/index.js +115 -27
  3. package/cli/package.json +1 -1
  4. package/compiler/package.json +1 -1
  5. package/compiler/stencil.js +821 -291
  6. package/compiler/stencil.min.js +2 -2
  7. package/dependencies.json +1 -1
  8. package/dev-server/client/index.js +1 -1
  9. package/dev-server/client/package.json +1 -1
  10. package/dev-server/client/test/hmr-util.spec.d.ts +1 -0
  11. package/dev-server/client/test/status.spec.d.ts +1 -0
  12. package/dev-server/connector.html +3 -3
  13. package/dev-server/index.js +1 -1
  14. package/dev-server/package.json +1 -1
  15. package/dev-server/server-process.js +5 -3
  16. package/internal/app-data/package.json +1 -1
  17. package/internal/client/css-shim.js +1 -1
  18. package/internal/client/dom.js +1 -1
  19. package/internal/client/index.js +11 -9
  20. package/internal/client/package.json +1 -1
  21. package/internal/client/patch-browser.js +1 -1
  22. package/internal/client/patch-esm.js +1 -1
  23. package/internal/client/shadow-css.js +2 -3
  24. package/internal/hydrate/index.js +37 -32
  25. package/internal/hydrate/package.json +1 -1
  26. package/internal/hydrate/shadow-css.js +9 -9
  27. package/internal/package.json +1 -1
  28. package/internal/stencil-private.d.ts +39 -3
  29. package/internal/stencil-public-compiler.d.ts +70 -3
  30. package/internal/stencil-public-docs.d.ts +3 -0
  31. package/internal/testing/index.js +35 -30
  32. package/internal/testing/package.json +1 -1
  33. package/internal/testing/shadow-css.js +9 -9
  34. package/mock-doc/index.cjs +8 -2
  35. package/mock-doc/index.d.ts +9 -2
  36. package/mock-doc/index.js +8 -2
  37. package/mock-doc/package.json +1 -1
  38. package/package.json +22 -16
  39. package/screenshot/index.js +2 -0
  40. package/screenshot/package.json +1 -1
  41. package/sys/node/autoprefixer.js +1 -1
  42. package/sys/node/index.js +2038 -1330
  43. package/sys/node/package.json +1 -1
  44. package/sys/node/worker.js +1 -1
  45. package/testing/index.js +335 -331
  46. package/testing/jest/test/jest-config.spec.d.ts +1 -0
  47. package/testing/jest/test/jest-preprocessor.spec.d.ts +1 -0
  48. package/testing/jest/test/jest-runner.spec.d.ts +1 -0
  49. package/testing/jest/test/jest-serializer.spec.d.ts +1 -0
  50. package/testing/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  /*!
2
- Stencil Compiler v2.15.1 | MIT Licensed | https://stenciljs.com
2
+ Stencil Compiler v2.16.1-0 | MIT Licensed | https://stenciljs.com
3
3
  */
4
4
  (function(exports) {
5
5
  'use strict';
@@ -717,7 +717,7 @@ const computeListenerFlags = (listener) => {
717
717
  };
718
718
  const trimFalsy = (data) => {
719
719
  const arr = data;
720
- for (var i = arr.length - 1; i >= 0; i--) {
720
+ for (let i = arr.length - 1; i >= 0; i--) {
721
721
  if (arr[i]) {
722
722
  break;
723
723
  }
@@ -826,136 +826,15 @@ const isGlob = (str) => {
826
826
  };
827
827
 
828
828
  /**
829
- * Checks if the path is the OS root path, such as "/" or "C:\"
829
+ * Checks if the path is the Operating System (OS) root path, such as "/" or "C:\". This function does not take the OS
830
+ * the code is running on into account when performing this evaluation.
831
+ * @param p the path to check
832
+ * @returns `true` if the path is an OS root path, `false` otherwise
830
833
  */
831
834
  const isRootPath = (p) => p === '/' || windowsPathRegex.test(p);
832
835
  // https://github.com/nodejs/node/blob/5883a59b21a97e8b7339f435c977155a2c29ba8d/lib/path.js#L43
833
836
  const windowsPathRegex = /^(?:[a-zA-Z]:|[\\/]{2}[^\\/]+[\\/]+[^\\/]+)?[\\/]$/;
834
837
 
835
- /**
836
- * Iterate through a series of diagnostics to provide minor fix-ups for various edge cases, deduplicate messages, etc.
837
- * @param compilerCtx the current compiler context
838
- * @param diagnostics the diagnostics to normalize
839
- * @returns the normalize documents
840
- */
841
- const normalizeDiagnostics = (compilerCtx, diagnostics) => {
842
- const normalizedErrors = [];
843
- const normalizedOthers = [];
844
- const dups = new Set();
845
- for (let i = 0; i < diagnostics.length; i++) {
846
- const d = normalizeDiagnostic(compilerCtx, diagnostics[i]);
847
- const key = d.absFilePath + d.code + d.messageText + d.type;
848
- if (dups.has(key)) {
849
- continue;
850
- }
851
- dups.add(key);
852
- const total = normalizedErrors.length + normalizedOthers.length;
853
- if (d.level === 'error') {
854
- normalizedErrors.push(d);
855
- }
856
- else if (total < MAX_ERRORS) {
857
- normalizedOthers.push(d);
858
- }
859
- }
860
- return [...normalizedErrors, ...normalizedOthers];
861
- };
862
- /**
863
- * Perform post-processing on a `Diagnostic` to handle a few message edge cases, massaging error message text and
864
- * updating build failure contexts
865
- * @param compilerCtx the current compiler
866
- * @param diagnostic the diagnostic to normalize
867
- * @returns the altered diagnostic
868
- */
869
- const normalizeDiagnostic = (compilerCtx, diagnostic) => {
870
- if (diagnostic.messageText) {
871
- if (typeof diagnostic.messageText.message === 'string') {
872
- diagnostic.messageText = diagnostic.messageText.message;
873
- }
874
- else if (typeof diagnostic.messageText === 'string' && diagnostic.messageText.indexOf('Error: ') === 0) {
875
- diagnostic.messageText = diagnostic.messageText.slice(7);
876
- }
877
- }
878
- if (diagnostic.messageText) {
879
- if (diagnostic.messageText.includes(`Cannot find name 'h'`)) {
880
- diagnostic.header = `Missing "h" import for JSX types`;
881
- diagnostic.messageText = `In order to load accurate JSX types for components, the "h" function must be imported from "@stencil/core" by each component using JSX. For example: import { Component, h } from '@stencil/core';`;
882
- try {
883
- const sourceText = compilerCtx.fs.readFileSync(diagnostic.absFilePath);
884
- const srcLines = splitLineBreaks(sourceText);
885
- for (let i = 0; i < srcLines.length; i++) {
886
- const srcLine = srcLines[i];
887
- if (srcLine.includes('@stencil/core')) {
888
- const msgLines = [];
889
- const beforeLineIndex = i - 1;
890
- if (beforeLineIndex > -1) {
891
- const beforeLine = {
892
- lineIndex: beforeLineIndex,
893
- lineNumber: beforeLineIndex + 1,
894
- text: srcLines[beforeLineIndex],
895
- errorCharStart: -1,
896
- errorLength: -1,
897
- };
898
- msgLines.push(beforeLine);
899
- }
900
- const errorLine = {
901
- lineIndex: i,
902
- lineNumber: i + 1,
903
- text: srcLine,
904
- errorCharStart: 0,
905
- errorLength: -1,
906
- };
907
- msgLines.push(errorLine);
908
- diagnostic.lineNumber = errorLine.lineNumber;
909
- diagnostic.columnNumber = srcLine.indexOf('}');
910
- const afterLineIndex = i + 1;
911
- if (afterLineIndex < srcLines.length) {
912
- const afterLine = {
913
- lineIndex: afterLineIndex,
914
- lineNumber: afterLineIndex + 1,
915
- text: srcLines[afterLineIndex],
916
- errorCharStart: -1,
917
- errorLength: -1,
918
- };
919
- msgLines.push(afterLine);
920
- }
921
- diagnostic.lines = msgLines;
922
- break;
923
- }
924
- }
925
- }
926
- catch (e) { }
927
- }
928
- }
929
- return diagnostic;
930
- };
931
- /**
932
- * Split a corpus by newlines. Carriage returns are treated a newlines.
933
- * @param sourceText the corpus to split
934
- * @returns the split text
935
- */
936
- const splitLineBreaks = (sourceText) => {
937
- if (typeof sourceText !== 'string')
938
- return [];
939
- sourceText = sourceText.replace(/\\r/g, '\n');
940
- return sourceText.split('\n');
941
- };
942
- const escapeHtml = (unsafe) => {
943
- if (unsafe === undefined)
944
- return 'undefined';
945
- if (unsafe === null)
946
- return 'null';
947
- if (typeof unsafe !== 'string') {
948
- unsafe = unsafe.toString();
949
- }
950
- return unsafe
951
- .replace(/&/g, '&amp;')
952
- .replace(/</g, '&lt;')
953
- .replace(/>/g, '&gt;')
954
- .replace(/"/g, '&quot;')
955
- .replace(/'/g, '&#039;');
956
- };
957
- const MAX_ERRORS = 25;
958
-
959
838
  /**
960
839
  * Builds a template `Diagnostic` entity for a build error. The created `Diagnostic` is returned, and have little
961
840
  * detail attached to it regarding the specifics of the error - it is the responsibility of the caller of this method
@@ -1120,6 +999,130 @@ const shouldIgnoreError = (msg) => {
1120
999
  };
1121
1000
  const TASK_CANCELED_MSG = `task canceled`;
1122
1001
 
1002
+ /**
1003
+ * Iterate through a series of diagnostics to provide minor fix-ups for various edge cases, deduplicate messages, etc.
1004
+ * @param compilerCtx the current compiler context
1005
+ * @param diagnostics the diagnostics to normalize
1006
+ * @returns the normalize documents
1007
+ */
1008
+ const normalizeDiagnostics = (compilerCtx, diagnostics) => {
1009
+ const maxErrorsToNormalize = 25;
1010
+ const normalizedErrors = [];
1011
+ const normalizedOthers = [];
1012
+ const dups = new Set();
1013
+ for (let i = 0; i < diagnostics.length; i++) {
1014
+ const d = normalizeDiagnostic(compilerCtx, diagnostics[i]);
1015
+ const key = d.absFilePath + d.code + d.messageText + d.type;
1016
+ if (dups.has(key)) {
1017
+ continue;
1018
+ }
1019
+ dups.add(key);
1020
+ const total = normalizedErrors.length + normalizedOthers.length;
1021
+ if (d.level === 'error') {
1022
+ normalizedErrors.push(d);
1023
+ }
1024
+ else if (total < maxErrorsToNormalize) {
1025
+ normalizedOthers.push(d);
1026
+ }
1027
+ }
1028
+ return [...normalizedErrors, ...normalizedOthers];
1029
+ };
1030
+ /**
1031
+ * Perform post-processing on a `Diagnostic` to handle a few message edge cases, massaging error message text and
1032
+ * updating build failure contexts
1033
+ * @param compilerCtx the current compiler
1034
+ * @param diagnostic the diagnostic to normalize
1035
+ * @returns the altered diagnostic
1036
+ */
1037
+ const normalizeDiagnostic = (compilerCtx, diagnostic) => {
1038
+ if (diagnostic.messageText) {
1039
+ if (typeof diagnostic.messageText.message === 'string') {
1040
+ diagnostic.messageText = diagnostic.messageText.message;
1041
+ }
1042
+ else if (typeof diagnostic.messageText === 'string' && diagnostic.messageText.indexOf('Error: ') === 0) {
1043
+ diagnostic.messageText = diagnostic.messageText.slice(7);
1044
+ }
1045
+ }
1046
+ if (diagnostic.messageText) {
1047
+ if (diagnostic.messageText.includes(`Cannot find name 'h'`)) {
1048
+ diagnostic.header = `Missing "h" import for JSX types`;
1049
+ diagnostic.messageText = `In order to load accurate JSX types for components, the "h" function must be imported from "@stencil/core" by each component using JSX. For example: import { Component, h } from '@stencil/core';`;
1050
+ try {
1051
+ const sourceText = compilerCtx.fs.readFileSync(diagnostic.absFilePath);
1052
+ const srcLines = splitLineBreaks(sourceText);
1053
+ for (let i = 0; i < srcLines.length; i++) {
1054
+ const srcLine = srcLines[i];
1055
+ if (srcLine.includes('@stencil/core')) {
1056
+ const msgLines = [];
1057
+ const beforeLineIndex = i - 1;
1058
+ if (beforeLineIndex > -1) {
1059
+ const beforeLine = {
1060
+ lineIndex: beforeLineIndex,
1061
+ lineNumber: beforeLineIndex + 1,
1062
+ text: srcLines[beforeLineIndex],
1063
+ errorCharStart: -1,
1064
+ errorLength: -1,
1065
+ };
1066
+ msgLines.push(beforeLine);
1067
+ }
1068
+ const errorLine = {
1069
+ lineIndex: i,
1070
+ lineNumber: i + 1,
1071
+ text: srcLine,
1072
+ errorCharStart: 0,
1073
+ errorLength: -1,
1074
+ };
1075
+ msgLines.push(errorLine);
1076
+ diagnostic.lineNumber = errorLine.lineNumber;
1077
+ diagnostic.columnNumber = srcLine.indexOf('}');
1078
+ const afterLineIndex = i + 1;
1079
+ if (afterLineIndex < srcLines.length) {
1080
+ const afterLine = {
1081
+ lineIndex: afterLineIndex,
1082
+ lineNumber: afterLineIndex + 1,
1083
+ text: srcLines[afterLineIndex],
1084
+ errorCharStart: -1,
1085
+ errorLength: -1,
1086
+ };
1087
+ msgLines.push(afterLine);
1088
+ }
1089
+ diagnostic.lines = msgLines;
1090
+ break;
1091
+ }
1092
+ }
1093
+ }
1094
+ catch (e) { }
1095
+ }
1096
+ }
1097
+ return diagnostic;
1098
+ };
1099
+ /**
1100
+ * Split a corpus by newlines. Carriage returns are treated a newlines.
1101
+ * @param sourceText the corpus to split
1102
+ * @returns the split text
1103
+ */
1104
+ const splitLineBreaks = (sourceText) => {
1105
+ if (typeof sourceText !== 'string')
1106
+ return [];
1107
+ sourceText = sourceText.replace(/\\r/g, '\n');
1108
+ return sourceText.split('\n');
1109
+ };
1110
+ const escapeHtml = (unsafe) => {
1111
+ if (unsafe === undefined)
1112
+ return 'undefined';
1113
+ if (unsafe === null)
1114
+ return 'null';
1115
+ if (typeof unsafe !== 'string') {
1116
+ unsafe = unsafe.toString();
1117
+ }
1118
+ return unsafe
1119
+ .replace(/&/g, '&amp;')
1120
+ .replace(/</g, '&lt;')
1121
+ .replace(/>/g, '&gt;')
1122
+ .replace(/"/g, '&quot;')
1123
+ .replace(/'/g, '&#039;');
1124
+ };
1125
+
1123
1126
  const loadRollupDiagnostics = (config, compilerCtx, buildCtx, rollupError) => {
1124
1127
  const formattedCode = formatErrorCode(rollupError.code);
1125
1128
  const diagnostic = {
@@ -1258,6 +1261,8 @@ const formatErrorCode = (errorCode) => {
1258
1261
  * Forward-slash paths can be used in Windows as long as they're not
1259
1262
  * extended-length paths and don't contain any non-ascii characters.
1260
1263
  * This was created since the path methods in Node.js outputs \\ paths on Windows.
1264
+ * @param path the Windows-based path to convert
1265
+ * @returns the converted path
1261
1266
  */
1262
1267
  const normalizePath$1 = (path) => {
1263
1268
  if (typeof path !== 'string') {
@@ -1393,8 +1398,10 @@ const pathComponents = (path, rootLength) => {
1393
1398
  return [root, ...rest];
1394
1399
  };
1395
1400
  /**
1396
- * Same as normalizePath(), expect it'll also strip any querystrings
1401
+ * Same as normalizePath(), expect it'll also strip any query strings
1397
1402
  * from the path name. So /dir/file.css?tag=cmp-a becomes /dir/file.css
1403
+ * @param p the path to normalize
1404
+ * @returns the normalized path, sans any query strings
1398
1405
  */
1399
1406
  const normalizeFsPath = (p) => normalizePath$1(p.split('?')[0].replace(/\0/g, ''));
1400
1407
  const normalizeFsPathQuery = (importPath) => {
@@ -1570,6 +1577,15 @@ const flattenDiagnosticMessageText = (tsDiagnostic, diag) => {
1570
1577
  return result.trim();
1571
1578
  };
1572
1579
 
1580
+ /**
1581
+ * Determines whether a string should be considered a remote url or not.
1582
+ *
1583
+ * This helper only checks the provided string to evaluate is one of a few pre-defined schemes, and should not be
1584
+ * considered all-encompassing
1585
+ *
1586
+ * @param p the string to evaluate
1587
+ * @returns `true` if the provided string is a remote url, `false` otherwise
1588
+ */
1573
1589
  const isRemoteUrl = (p) => {
1574
1590
  if (isString$1(p)) {
1575
1591
  p = p.toLowerCase();
@@ -1639,12 +1655,23 @@ ${docs.tags
1639
1655
  .map((tag) => `@${tag.name} ${(tag.text || '').replace(lineBreakRegex, ' ')}`)
1640
1656
  .join('\n')}`.trim();
1641
1657
  }
1658
+ /**
1659
+ * Retrieve a project's dependencies from the current build context
1660
+ * @param buildCtx the current build context to query for a specific package
1661
+ * @returns a list of package names the project is dependent on
1662
+ */
1642
1663
  const getDependencies = (buildCtx) => {
1643
1664
  if (buildCtx.packageJson != null && buildCtx.packageJson.dependencies != null) {
1644
1665
  return Object.keys(buildCtx.packageJson.dependencies).filter((pkgName) => !SKIP_DEPS.includes(pkgName));
1645
1666
  }
1646
1667
  return [];
1647
1668
  };
1669
+ /**
1670
+ * Utility to determine whether a project has a dependency on a package
1671
+ * @param buildCtx the current build context to query for a specific package
1672
+ * @param depName the name of the dependency/package
1673
+ * @returns `true` if the project has a dependency a packaged with the provided name, `false` otherwise
1674
+ */
1648
1675
  const hasDependency = (buildCtx, depName) => {
1649
1676
  return getDependencies(buildCtx).includes(depName);
1650
1677
  };
@@ -2236,10 +2263,36 @@ const createWebWorkerMainController = (sys, maxConcurrentWorkers) => {
2236
2263
 
2237
2264
  const COMMON_DIR_MODULE_EXTS = ['.tsx', '.ts', '.mjs', '.js', '.jsx', '.json', '.md'];
2238
2265
  const COMMON_DIR_FILENAMES = ['package.json', 'index.js', 'index.mjs'];
2266
+ /**
2267
+ * Determine if a stringified file path is a TypeScript declaration file based on the extension at the end of the path.
2268
+ * @param p the path to evaluate
2269
+ * @returns `true` if the path ends in `.d.ts` (case-sensitive), `false` otherwise.
2270
+ */
2239
2271
  const isDtsFile = (p) => p.endsWith('.d.ts');
2272
+ /**
2273
+ * Determine if a stringified file path is a TypeScript file based on the extension at the end of the path. This
2274
+ * function does _not_ consider type declaration files (`.d.ts` files) to be TypeScript files.
2275
+ * @param p the path to evaluate
2276
+ * @returns `true` if the path ends in `.ts` (case-sensitive) but does _not_ end in `.d.ts`, `false` otherwise.
2277
+ */
2240
2278
  const isTsFile = (p) => !isDtsFile(p) && p.endsWith('.ts');
2279
+ /**
2280
+ * Determine if a stringified file path is a TSX file based on the extension at the end of the path
2281
+ * @param p the path to evaluate
2282
+ * @returns `true` if the path ends in `.tsx` (case-sensitive), `false` otherwise.
2283
+ */
2241
2284
  const isTsxFile = (p) => p.endsWith('.tsx');
2285
+ /**
2286
+ * Determine if a stringified file path is a JSX file based on the extension at the end of the path
2287
+ * @param p the path to evaluate
2288
+ * @returns `true` if the path ends in `.jsx` (case-sensitive), `false` otherwise.
2289
+ */
2242
2290
  const isJsxFile = (p) => p.endsWith('.jsx');
2291
+ /**
2292
+ * Determine if a stringified file path is a JavaScript file based on the extension at the end of the path
2293
+ * @param p the path to evaluate
2294
+ * @returns `true` if the path ends in `.js` (case-sensitive), `false` otherwise.
2295
+ */
2243
2296
  const isJsFile = (p) => p.endsWith('.js');
2244
2297
  const isJsonFile = (p) => p.endsWith('.json');
2245
2298
  const getCommonDirName = (dirPath, fileName) => dirPath + '/' + fileName;
@@ -3974,16 +4027,16 @@ const createCustomResolverAsync = (sys, inMemoryFs, exts) => {
3974
4027
  };
3975
4028
  };
3976
4029
 
3977
- const buildId = '20220418164701';
4030
+ const buildId = '20220603032000';
3978
4031
  const minfyJsId = 'terser5.6.1_7';
3979
- const optimizeCssId = 'autoprefixer10.2.5_postcss8.2.8_7';
4032
+ const optimizeCssId = 'autoprefixer10.2.5_postcss8.2.13_7';
3980
4033
  const parse5Version = '6.0.1';
3981
4034
  const rollupVersion = '2.42.3';
3982
4035
  const sizzleVersion = '2.42.3';
3983
4036
  const terserVersion = '5.6.1';
3984
4037
  const typescriptVersion = '4.5.4';
3985
- const vermoji = '🐼';
3986
- const version$3 = '2.15.1';
4038
+ const vermoji = '🌸';
4039
+ const version$3 = '2.16.1-0';
3987
4040
  const versions = {
3988
4041
  stencil: version$3,
3989
4042
  parse5: parse5Version,
@@ -11000,7 +11053,6 @@ const CSS_PROP_ANNOTATION = `@prop`;
11000
11053
  const safeSelector = (selector) => {
11001
11054
  const placeholders = [];
11002
11055
  let index = 0;
11003
- let content;
11004
11056
  // Replaces attribute selectors with placeholders.
11005
11057
  // The WS in [attr="va lue"] would otherwise be interpreted as a selector separator.
11006
11058
  selector = selector.replace(/(\[[^\]]*\])/g, (_, keep) => {
@@ -11011,7 +11063,7 @@ const safeSelector = (selector) => {
11011
11063
  });
11012
11064
  // Replaces the expression in `:nth-child(2n + 1)` with a placeholder.
11013
11065
  // WS and "+" would otherwise be interpreted as selector separators.
11014
- content = selector.replace(/(:nth-[-\w]+)(\([^)]+\))/g, (_, pseudo, exp) => {
11066
+ const content = selector.replace(/(:nth-[-\w]+)(\([^)]+\))/g, (_, pseudo, exp) => {
11015
11067
  const replaceBy = `__ph-${index}__`;
11016
11068
  placeholders.push(exp);
11017
11069
  index++;
@@ -11645,7 +11697,7 @@ const createWorkerMessageHandler = (sys) => {
11645
11697
  const fnArgs = msgToWorker.args.slice(1);
11646
11698
  const fn = workerCtx[fnName];
11647
11699
  if (typeof fn === 'function') {
11648
- return fn.apply(null, fnArgs);
11700
+ return fn(...fnArgs);
11649
11701
  }
11650
11702
  };
11651
11703
  };
@@ -12032,25 +12084,33 @@ const isOutputTargetWww = (o) => o.type === WWW;
12032
12084
  const isOutputTargetStats = (o) => o.type === STATS;
12033
12085
  const isOutputTargetDistTypes = (o) => o.type === DIST_TYPES;
12034
12086
  const getComponentsFromModules = (moduleFiles) => sortBy(flatOne(moduleFiles.map((m) => m.cmps)), (c) => c.tagName);
12035
- const ANGULAR = `angular`;
12087
+ const ANGULAR = 'angular';
12036
12088
  const COPY = 'copy';
12037
- const CUSTOM = `custom`;
12038
- const DIST = `dist`;
12039
- const DIST_COLLECTION = `dist-collection`;
12040
- const DIST_CUSTOM_ELEMENTS = `dist-custom-elements`;
12041
- const DIST_CUSTOM_ELEMENTS_BUNDLE = `dist-custom-elements-bundle`;
12042
- const DIST_TYPES = `dist-types`;
12043
- const DIST_HYDRATE_SCRIPT = `dist-hydrate-script`;
12044
- const DIST_LAZY = `dist-lazy`;
12045
- const DIST_LAZY_LOADER = `dist-lazy-loader`;
12089
+ const CUSTOM = 'custom';
12090
+ const DIST = 'dist';
12091
+ const DIST_COLLECTION = 'dist-collection';
12092
+ const DIST_CUSTOM_ELEMENTS = 'dist-custom-elements';
12093
+ const DIST_CUSTOM_ELEMENTS_BUNDLE = 'dist-custom-elements-bundle';
12094
+ const DIST_TYPES = 'dist-types';
12095
+ const DIST_HYDRATE_SCRIPT = 'dist-hydrate-script';
12096
+ const DIST_LAZY = 'dist-lazy';
12097
+ const DIST_LAZY_LOADER = 'dist-lazy-loader';
12046
12098
  const DIST_GLOBAL_STYLES = 'dist-global-styles';
12047
12099
  const DOCS_CUSTOM = 'docs-custom';
12048
- const DOCS_JSON = `docs-json`;
12049
- const DOCS_README = `docs-readme`;
12050
- const DOCS_VSCODE = `docs-vscode`;
12051
- const STATS = `stats`;
12052
- const WWW = `www`;
12053
- const VALID_TYPES = [
12100
+ const DOCS_JSON = 'docs-json';
12101
+ const DOCS_README = 'docs-readme';
12102
+ const DOCS_VSCODE = 'docs-vscode';
12103
+ const STATS = 'stats';
12104
+ const WWW = 'www';
12105
+ /**
12106
+ * Valid output targets to specify in a Stencil config.
12107
+ *
12108
+ * Note that there are some output targets (e.g. `DIST_TYPES`) which are
12109
+ * programmatically set as output targets by the compiler when other output
12110
+ * targets (in that case `DIST`) are set, but which are _not_ supported in a
12111
+ * Stencil config. This is enforced in the output target validation code.
12112
+ */
12113
+ const VALID_CONFIG_OUTPUT_TARGETS = [
12054
12114
  // DIST
12055
12115
  WWW,
12056
12116
  DIST,
@@ -12070,6 +12130,20 @@ const VALID_TYPES = [
12070
12130
  CUSTOM,
12071
12131
  STATS,
12072
12132
  ];
12133
+ /**
12134
+ * Check whether a given output target is a valid one to be set in a Stencil config
12135
+ *
12136
+ * @param targetType the type which we want to check
12137
+ * @returns whether or not the targetType is a valid, configurable output target.
12138
+ */
12139
+ function isValidConfigOutputTarget(targetType) {
12140
+ // unfortunately `includes` is typed on `ReadonlyArray<T>` as `(el: T):
12141
+ // boolean` so a `string` cannot be passed to `includes` on a
12142
+ // `ReadonlyArray` 😢 thus we `as any`
12143
+ //
12144
+ // see microsoft/TypeScript#31018 for some discussion of this
12145
+ return VALID_CONFIG_OUTPUT_TARGETS.includes(targetType);
12146
+ }
12073
12147
  const GENERATED_DTS$1 = 'components.d.ts';
12074
12148
 
12075
12149
  var concatMap$1 = function (xs, fn) {
@@ -13675,6 +13749,7 @@ const generateBuildResults = (config, compilerCtx, buildCtx) => {
13675
13749
  * @returns CompilerBuildStats or an Object including diagnostics.
13676
13750
  */
13677
13751
  function generateBuildStats(config, buildCtx) {
13752
+ // TODO(STENCIL-461): Investigate making this return only a single type
13678
13753
  const buildResults = buildCtx.buildResults;
13679
13754
  let jsonData;
13680
13755
  try {
@@ -13737,8 +13812,8 @@ function generateBuildStats(config, buildCtx) {
13737
13812
  /**
13738
13813
  * Writes the files from the stats config to the file system
13739
13814
  * @param config the project build configuration
13740
- * @param buildCtx An instance of the build which holds the details about the build
13741
- * @returns
13815
+ * @param data the information to write out to disk (as specified by each stats output target specified in the provided
13816
+ * config)
13742
13817
  */
13743
13818
  async function writeBuildStats(config, data) {
13744
13819
  const statsTargets = config.outputTargets.filter(isOutputTargetStats);
@@ -13767,7 +13842,7 @@ function sanitizeBundlesForStats(bundleArray) {
13767
13842
  });
13768
13843
  }
13769
13844
  function getSourceGraph(config, buildCtx) {
13770
- let sourceGraph = {};
13845
+ const sourceGraph = {};
13771
13846
  sortBy(buildCtx.moduleFiles, (m) => m.sourceFilePath).forEach((moduleFile) => {
13772
13847
  const key = relativePath$1(config, moduleFile.sourceFilePath);
13773
13848
  sourceGraph[key] = moduleFile.localImports.map((localImport) => relativePath$1(config, localImport)).sort();
@@ -15515,7 +15590,11 @@ class MockNode {
15515
15590
  if (otherNode === this) {
15516
15591
  return true;
15517
15592
  }
15518
- return this.childNodes.includes(otherNode);
15593
+ const childNodes = Array.from(this.childNodes);
15594
+ if (childNodes.includes(otherNode)) {
15595
+ return true;
15596
+ }
15597
+ return childNodes.some((node) => this.contains.bind(node)(otherNode));
15519
15598
  }
15520
15599
  removeChild(childNode) {
15521
15600
  const index = this.childNodes.indexOf(childNode);
@@ -40773,7 +40852,7 @@ const parseDevModuleUrl = (config, u) => {
40773
40852
  const url = new URL(u, 'https://stenciljs.com');
40774
40853
  let reqPath = basename(url.pathname);
40775
40854
  reqPath = reqPath.substring(0, reqPath.length - 3);
40776
- let splt = reqPath.split('@');
40855
+ const splt = reqPath.split('@');
40777
40856
  if (splt.length === 2) {
40778
40857
  parsedUrl.nodeModuleId = decodeURIComponent(splt[0]);
40779
40858
  parsedUrl.nodeModuleVersion = decodeURIComponent(splt[1]);
@@ -42658,7 +42737,14 @@ const parse$1 = (input, options) => {
42658
42737
  }
42659
42738
 
42660
42739
  if (token.inner.includes('*') && (rest = remaining()) && /^\.[^\\/.]+$/.test(rest)) {
42661
- output = token.close = `)${rest})${extglobStar})`;
42740
+ // Any non-magical string (`.ts`) or even nested expression (`.{ts,tsx}`) can follow after the closing parenthesis.
42741
+ // In this case, we need to parse the string and use it in the output of the original pattern.
42742
+ // Suitable patterns: `/!(*.d).ts`, `/!(*.d).{ts,tsx}`, `**/!(*-dbg).@(js)`.
42743
+ //
42744
+ // Disabling the `fastpaths` option due to a problem with parsing strings as `.ts` in the pattern like `**/!(*.d).ts`.
42745
+ const expression = parse$1(rest, { ...options, fastpaths: false }).output;
42746
+
42747
+ output = token.close = `)${expression})${extglobStar})`;
42662
42748
  }
42663
42749
 
42664
42750
  if (token.prev.type === 'bos') {
@@ -55377,6 +55463,7 @@ const addDefineCustomElementFunction = (tagNames, newStatements, caseStatements)
55377
55463
  * ```typescript
55378
55464
  * defineCustomElement(MyPrincipalComponent);
55379
55465
  * ```
55466
+ * @param componentName the component's class name to use as the first argument to `defineCustomElement`
55380
55467
  * @returns the expression statement described above
55381
55468
  */
55382
55469
  function createAutoDefinitionExpression(componentName) {
@@ -55414,9 +55501,9 @@ const proxyCustomElement = (compilerCtx, transformOpts) => {
55414
55501
  return tsSourceFile;
55415
55502
  }
55416
55503
  const principalComponent = moduleFile.cmps[0];
55417
- for (let [stmtIndex, stmt] of tsSourceFile.statements.entries()) {
55504
+ for (const [stmtIndex, stmt] of tsSourceFile.statements.entries()) {
55418
55505
  if (t.isVariableStatement(stmt)) {
55419
- for (let [declarationIndex, declaration] of stmt.declarationList.declarations.entries()) {
55506
+ for (const [declarationIndex, declaration] of stmt.declarationList.declarations.entries()) {
55420
55507
  if (declaration.name.getText() !== principalComponent.componentClassName) {
55421
55508
  continue;
55422
55509
  }
@@ -56581,6 +56668,20 @@ const strickCheckDocs = (config, docsData) => {
56581
56668
  });
56582
56669
  };
56583
56670
 
56671
+ /**
56672
+ * Generate [custom data](https://github.com/microsoft/vscode-custom-data) to augment existing HTML types in VS Code.
56673
+ * This function writes the custom data as a JSON file to disk, which can be used in VS Code to inform the IDE about
56674
+ * custom elements generated by Stencil.
56675
+ *
56676
+ * The JSON generated by this function must conform to the
56677
+ * [HTML custom data schema](https://github.com/microsoft/vscode-html-languageservice/blob/e7ae8a7170df5e721a13cee1b86e293b24eb3b20/docs/customData.schema.json).
56678
+ *
56679
+ * This function generates custom data for HTML only at this time (it does not generate custom data for CSS).
56680
+ *
56681
+ * @param compilerCtx the current compiler context
56682
+ * @param docsData an intermediate representation documentation derived from compiled Stencil components
56683
+ * @param outputTargets the output target(s) the associated with the current build
56684
+ */
56584
56685
  const generateVscodeDocs = async (compilerCtx, docsData, outputTargets) => {
56585
56686
  const vsCodeOutputTargets = outputTargets.filter(isOutputTargetDocsVscode);
56586
56687
  if (vsCodeOutputTargets.length === 0) {
@@ -56588,6 +56689,13 @@ const generateVscodeDocs = async (compilerCtx, docsData, outputTargets) => {
56588
56689
  }
56589
56690
  await Promise.all(vsCodeOutputTargets.map(async (outputTarget) => {
56590
56691
  const json = {
56692
+ /**
56693
+ * the 'version' top-level field is required by the schema. changes to the JSON generated by Stencil must:
56694
+ * - comply with v1.X of the schema _OR_
56695
+ * - increment this field as a part of updating the JSON generation. This should be considered a breaking change
56696
+ *
56697
+ * {@link https://github.com/microsoft/vscode-html-languageservice/blob/e7ae8a7170df5e721a13cee1b86e293b24eb3b20/src/htmlLanguageTypes.ts#L184}
56698
+ */
56591
56699
  version: 1.1,
56592
56700
  tags: docsData.components.map((cmp) => ({
56593
56701
  name: cmp.tag,
@@ -56595,20 +56703,31 @@ const generateVscodeDocs = async (compilerCtx, docsData, outputTargets) => {
56595
56703
  kind: 'markdown',
56596
56704
  value: cmp.docs,
56597
56705
  },
56598
- attributes: cmp.props.filter((p) => p.attr).map(serializeAttribute),
56706
+ attributes: cmp.props
56707
+ .filter((p) => p.attr !== undefined && p.attr.length > 0)
56708
+ .map(serializeAttribute),
56599
56709
  references: getReferences(cmp, outputTarget.sourceCodeBaseUrl),
56600
56710
  })),
56601
56711
  };
56712
+ // fields in the custom data may have a value of `undefined`. calling `stringify` will remove such fields.
56602
56713
  const jsonContent = JSON.stringify(json, null, 2);
56603
56714
  await compilerCtx.fs.writeFile(outputTarget.file, jsonContent);
56604
56715
  }));
56605
56716
  };
56717
+ /**
56718
+ * Generate a 'references' section for a component's documentation.
56719
+ * @param cmp the Stencil component to generate a references section for
56720
+ * @param repoBaseUrl an optional URL, that when provided, will add a reference to the source code for the component
56721
+ * @returns the generated references section, or undefined if no references could be generated
56722
+ */
56606
56723
  const getReferences = (cmp, repoBaseUrl) => {
56724
+ var _a;
56725
+ // collect any `@reference` JSDoc tags on the component
56607
56726
  const references = getNameText('reference', cmp.docsTags).map(([name, url]) => ({ name, url }));
56608
56727
  if (repoBaseUrl) {
56609
56728
  references.push({
56610
56729
  name: 'Source code',
56611
- url: join(repoBaseUrl, cmp.filePath),
56730
+ url: join(repoBaseUrl, (_a = cmp.filePath) !== null && _a !== void 0 ? _a : ''),
56612
56731
  });
56613
56732
  }
56614
56733
  if (references.length > 0) {
@@ -56616,14 +56735,19 @@ const getReferences = (cmp, repoBaseUrl) => {
56616
56735
  }
56617
56736
  return undefined;
56618
56737
  };
56738
+ /**
56739
+ * Serialize a component's class member decorated with `@Prop` to be written to disk
56740
+ * @param prop the intermediate representation of the documentation to serialize
56741
+ * @returns the serialized data
56742
+ */
56619
56743
  const serializeAttribute = (prop) => {
56620
56744
  const attribute = {
56621
56745
  name: prop.attr,
56622
56746
  description: prop.docs,
56623
56747
  };
56624
56748
  const values = prop.values
56625
- .filter(({ type, value }) => type === 'string' && value !== undefined)
56626
- .map(({ value }) => ({ name: value }));
56749
+ .filter((jsonDocValue) => jsonDocValue.type === 'string' && jsonDocValue.value !== undefined)
56750
+ .map((jsonDocValue) => ({ name: jsonDocValue.value }));
56627
56751
  if (values.length > 0) {
56628
56752
  attribute.values = values;
56629
56753
  }
@@ -56715,9 +56839,15 @@ const addLazyElementGetter = (classMembers, moduleFile, cmp) => {
56715
56839
 
56716
56840
  /**
56717
56841
  * Adds static "style" getter within the class
56842
+ * ```typescript
56718
56843
  * const MyComponent = class {
56719
56844
  * static get style() { return "styles"; }
56720
56845
  * }
56846
+ * ```
56847
+ * @param classMembers a class to existing members of a class. **this parameter will be mutated** rather than returning
56848
+ * a cloned version
56849
+ * @param cmp the metadata associated with the component being evaluated
56850
+ * @param commentOriginalSelector if `true`, add a comment with the original CSS selector to the style.
56721
56851
  */
56722
56852
  const addStaticStyleGetterWithinClass = (classMembers, cmp, commentOriginalSelector) => {
56723
56853
  const styleLiteral = getStyleLiteral(cmp, commentOriginalSelector);
@@ -56727,11 +56857,15 @@ const addStaticStyleGetterWithinClass = (classMembers, cmp, commentOriginalSelec
56727
56857
  };
56728
56858
  /**
56729
56859
  * Adds static "style" property to the class variable.
56860
+ * ```typescript
56730
56861
  * const MyComponent = class {}
56731
56862
  * MyComponent.style = "styles";
56863
+ * ```
56864
+ * @param styleStatements a list of statements containing style assignments to a class
56865
+ * @param cmp the metadata associated with the component being evaluated
56732
56866
  */
56733
- const addStaticStylePropertyToClass = (styleStatements, cmp, commentOriginalSelector) => {
56734
- const styleLiteral = getStyleLiteral(cmp, commentOriginalSelector);
56867
+ const addStaticStylePropertyToClass = (styleStatements, cmp) => {
56868
+ const styleLiteral = getStyleLiteral(cmp, false);
56735
56869
  if (styleLiteral) {
56736
56870
  const statement = t.createStatement(t.createAssignment(t.createPropertyAccess(t.createIdentifier(cmp.componentClassName), 'style'), styleLiteral));
56737
56871
  styleStatements.push(statement);
@@ -57333,7 +57467,7 @@ const updateLazyComponentMembers = (transformOpts, styleStatements, classNode, m
57333
57467
  addWatchers(classMembers, cmp);
57334
57468
  transformHostData(classMembers, moduleFile);
57335
57469
  if (transformOpts.style === 'static') {
57336
- addStaticStylePropertyToClass(styleStatements, cmp, false);
57470
+ addStaticStylePropertyToClass(styleStatements, cmp);
57337
57471
  }
57338
57472
  return classMembers;
57339
57473
  };
@@ -57434,6 +57568,7 @@ const getBundleId = async (config, entryKey, shouldHash, code, sufix) => {
57434
57568
  };
57435
57569
 
57436
57570
  const generateLazyModules = async (config, compilerCtx, buildCtx, outputTargetType, destinations, results, sourceTarget, isBrowserBuild, sufix) => {
57571
+ var _a;
57437
57572
  if (!Array.isArray(destinations) || destinations.length === 0) {
57438
57573
  return [];
57439
57574
  }
@@ -57441,14 +57576,15 @@ const generateLazyModules = async (config, compilerCtx, buildCtx, outputTargetTy
57441
57576
  const rollupResults = results.filter((r) => r.type === 'chunk');
57442
57577
  const entryComponentsResults = rollupResults.filter((rollupResult) => rollupResult.isComponent);
57443
57578
  const chunkResults = rollupResults.filter((rollupResult) => !rollupResult.isComponent && !rollupResult.isEntry);
57444
- const [bundleModules] = await Promise.all([
57445
- Promise.all(entryComponentsResults.map((rollupResult) => {
57446
- return generateLazyEntryModule(config, compilerCtx, buildCtx, rollupResult, outputTargetType, destinations, sourceTarget, shouldMinify, isBrowserBuild, sufix);
57447
- })),
57448
- Promise.all(chunkResults.map((rollupResult) => {
57449
- return writeLazyChunk(config, compilerCtx, buildCtx, rollupResult, outputTargetType, destinations, sourceTarget, shouldMinify, isBrowserBuild);
57450
- })),
57451
- ]);
57579
+ const bundleModules = await Promise.all(entryComponentsResults.map((rollupResult) => {
57580
+ return generateLazyEntryModule(config, compilerCtx, buildCtx, rollupResult, outputTargetType, destinations, sourceTarget, shouldMinify, isBrowserBuild, sufix);
57581
+ }));
57582
+ if (!!((_a = config.extras) === null || _a === void 0 ? void 0 : _a.experimentalImportInjection) && !isBrowserBuild) {
57583
+ addStaticImports(rollupResults, bundleModules);
57584
+ }
57585
+ await Promise.all(chunkResults.map((rollupResult) => {
57586
+ return writeLazyChunk(config, compilerCtx, buildCtx, rollupResult, outputTargetType, destinations, sourceTarget, shouldMinify, isBrowserBuild);
57587
+ }));
57452
57588
  const lazyRuntimeData = formatLazyBundlesRuntimeMeta(bundleModules);
57453
57589
  const entryResults = rollupResults.filter((rollupResult) => !rollupResult.isComponent && rollupResult.isEntry);
57454
57590
  await Promise.all(entryResults.map((rollupResult) => {
@@ -57463,6 +57599,74 @@ const generateLazyModules = async (config, compilerCtx, buildCtx, outputTargetTy
57463
57599
  }));
57464
57600
  return bundleModules;
57465
57601
  };
57602
+ /**
57603
+ * Add imports for each bundle to Stencil's lazy loader. Some bundlers that are built atop of Rollup strictly impose
57604
+ * the limitations that are laid out in https://github.com/rollup/plugins/tree/master/packages/dynamic-import-vars#limitations.
57605
+ * This function injects an explicit import statement for each bundle that can be lazily loaded.
57606
+ * @param rollupChunkResults the results of running Rollup across a Stencil project
57607
+ * @param bundleModules lazy-loadable modules that can be resolved at runtime
57608
+ */
57609
+ const addStaticImports = (rollupChunkResults, bundleModules) => {
57610
+ rollupChunkResults.filter(isStencilCoreResult).forEach((index) => {
57611
+ const generateCjs = isCjsFormat(index) ? generateCaseClauseCjs : generateCaseClause;
57612
+ index.code = index.code.replace('/*!__STENCIL_STATIC_IMPORT_SWITCH__*/', `
57613
+ if (!hmrVersionId || !BUILD.hotModuleReplacement) {
57614
+ const processMod = importedModule => {
57615
+ cmpModules.set(bundleId, importedModule);
57616
+ return importedModule[exportName];
57617
+ }
57618
+ switch(bundleId) {
57619
+ ${bundleModules.map((mod) => generateCjs(mod.output.bundleId)).join('')}
57620
+ }
57621
+ }`);
57622
+ });
57623
+ };
57624
+ /**
57625
+ * Determine if a Rollup output chunk contains Stencil runtime code
57626
+ * @param rollupChunkResult the rollup chunk output to test
57627
+ * @returns true if the output chunk contains Stencil runtime code, false otherwise
57628
+ */
57629
+ const isStencilCoreResult = (rollupChunkResult) => {
57630
+ return (rollupChunkResult.isCore &&
57631
+ rollupChunkResult.entryKey === 'index' &&
57632
+ (rollupChunkResult.moduleFormat === 'es' ||
57633
+ rollupChunkResult.moduleFormat === 'esm' ||
57634
+ isCjsFormat(rollupChunkResult)));
57635
+ };
57636
+ /**
57637
+ * Helper function to determine if a Rollup chunk has a commonjs module format
57638
+ * @param rollupChunkResult the Rollup result to test
57639
+ * @returns true if the Rollup chunk has a commonjs module format, false otherwise
57640
+ */
57641
+ const isCjsFormat = (rollupChunkResult) => {
57642
+ return rollupChunkResult.moduleFormat === 'cjs' || rollupChunkResult.moduleFormat === 'commonjs';
57643
+ };
57644
+ /**
57645
+ * Generate a 'case' clause to be used within a `switch` statement. The case clause generated will key-off the provided
57646
+ * bundle ID for a component, and load a file (tied to that ID) at runtime.
57647
+ * @param bundleId the name of the bundle to load
57648
+ * @returns the case clause that will load the component's file at runtime
57649
+ */
57650
+ const generateCaseClause = (bundleId) => {
57651
+ return `
57652
+ case '${bundleId}':
57653
+ return import(
57654
+ /* webpackMode: "lazy" */
57655
+ './${bundleId}.entry.js').then(processMod, consoleError);`;
57656
+ };
57657
+ /**
57658
+ * Generate a 'case' clause to be used within a `switch` statement. The case clause generated will key-off the provided
57659
+ * bundle ID for a component, and load a CommonJS file (tied to that ID) at runtime.
57660
+ * @param bundleId the name of the bundle to load
57661
+ * @returns the case clause that will load the component's file at runtime
57662
+ */
57663
+ const generateCaseClauseCjs = (bundleId) => {
57664
+ return `
57665
+ case '${bundleId}':
57666
+ return Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require(
57667
+ /* webpackMode: "lazy" */
57668
+ './${bundleId}.entry.js')); }).then(processMod, consoleError);`;
57669
+ };
57466
57670
  const generateLazyEntryModule = async (config, compilerCtx, buildCtx, rollupResult, outputTargetType, destinations, sourceTarget, shouldMinify, isBrowserBuild, sufix) => {
57467
57671
  const entryModule = buildCtx.entryModules.find((entryModule) => entryModule.entryKey === rollupResult.entryKey);
57468
57672
  const shouldHash = config.hashFileNames && isBrowserBuild;
@@ -57491,7 +57695,7 @@ const writeLazyEntry = async (config, compilerCtx, buildCtx, rollupResult, outpu
57491
57695
  if (isBrowserBuild && ['loader'].includes(rollupResult.entryKey)) {
57492
57696
  return;
57493
57697
  }
57494
- let inputCode = rollupResult.code.replace(`[/*!__STENCIL_LAZY_DATA__*/]`, `${lazyRuntimeData}`);
57698
+ const inputCode = rollupResult.code.replace(`[/*!__STENCIL_LAZY_DATA__*/]`, `${lazyRuntimeData}`);
57495
57699
  const { code, sourceMap } = await convertChunk(config, compilerCtx, buildCtx, sourceTarget, shouldMinify, false, isBrowserBuild, inputCode, rollupResult.map);
57496
57700
  await Promise.all(destinations.map((dst) => {
57497
57701
  const filePath = join(dst, rollupResult.fileName);
@@ -57509,7 +57713,7 @@ const formatLazyBundlesRuntimeMeta = (bundleModules) => {
57509
57713
  return stringifyRuntimeData(lazyBundles);
57510
57714
  };
57511
57715
  const formatLazyRuntimeBundle = (bundleModule) => {
57512
- let bundleId = bundleModule.output.bundleId;
57716
+ const bundleId = bundleModule.output.bundleId;
57513
57717
  const bundleCmps = bundleModule.cmps.slice().sort(sortBundleComponents);
57514
57718
  return [bundleId, bundleCmps.map((cmp) => formatComponentRuntimeMeta(cmp, true))];
57515
57719
  };
@@ -58929,6 +59133,68 @@ const updateStencilTypesImports = (typesDir, dtsFilePath, dtsContent) => {
58929
59133
  }
58930
59134
  return dtsContent;
58931
59135
  };
59136
+ /**
59137
+ * Utility for ensuring that naming collisions do not appear in type declaration files for a component's class members
59138
+ * decorated with @Prop, @Event, and @Method
59139
+ * @param typeReferences all type names used by a component class member
59140
+ * @param typeImportData locally/imported/globally used type names, which may be used to prevent naming collisions
59141
+ * @param sourceFilePath the path to the source file of a component using the type being inspected
59142
+ * @param initialType the name of the type that may be updated
59143
+ * @returns the updated type name, which may be the same as the initial type name provided as an argument to this
59144
+ * function
59145
+ */
59146
+ const updateTypeIdentifierNames = (typeReferences, typeImportData, sourceFilePath, initialType) => {
59147
+ let currentTypeName = initialType;
59148
+ // iterate over each of the type references, as there may be >1 reference to inspect
59149
+ for (const typeReference of Object.values(typeReferences)) {
59150
+ const importResolvedFile = getTypeImportPath(typeReference.path, sourceFilePath);
59151
+ if (!typeImportData.hasOwnProperty(importResolvedFile)) {
59152
+ continue;
59153
+ }
59154
+ for (const typesImportDatumElement of typeImportData[importResolvedFile]) {
59155
+ currentTypeName = updateTypeName(currentTypeName, typesImportDatumElement);
59156
+ }
59157
+ }
59158
+ return currentTypeName;
59159
+ };
59160
+ /**
59161
+ * Determine the path of a given type reference, relative to the path of a source file
59162
+ * @param importResolvedFile the path to the file containing the resolve type. may be absolute or relative
59163
+ * @param sourceFilePath the component source file path to resolve against
59164
+ * @returns the path of the type import
59165
+ */
59166
+ const getTypeImportPath = (importResolvedFile, sourceFilePath) => {
59167
+ const isPathRelative = importResolvedFile && importResolvedFile.startsWith('.');
59168
+ if (isPathRelative) {
59169
+ importResolvedFile = resolve$1(dirname(sourceFilePath), importResolvedFile);
59170
+ }
59171
+ return importResolvedFile;
59172
+ };
59173
+ /**
59174
+ * Determine whether the string representation of a type should be replaced with an alias
59175
+ * @param currentTypeName the current string representation of a type
59176
+ * @param typeAlias a type member and a potential different name associated with the type member
59177
+ * @returns the updated string representation of a type. If the type is not updated, the original type name is returned
59178
+ */
59179
+ const updateTypeName = (currentTypeName, typeAlias) => {
59180
+ if (!typeAlias.importName) {
59181
+ return currentTypeName;
59182
+ }
59183
+ // TODO(STENCIL-419): Update this functionality to no longer use a regex
59184
+ // negative lookahead specifying that quotes that designate a string in JavaScript cannot follow some expression
59185
+ const endingStrChar = '(?!("|\'|`))';
59186
+ /**
59187
+ * A regular expression that looks at type names along a [word boundary](https://www.regular-expressions.info/wordboundaries.html).
59188
+ * This is used as the best approximation for replacing type collisions, as this stage of compilation has only
59189
+ * 'flattened' type information in the form of a String.
59190
+ *
59191
+ * This regex should be expected to capture types that are found in generics, unions, intersections, etc., but not
59192
+ * those in string literals. We do not check for a starting quote (" | ' | `) here as some browsers do not support
59193
+ * negative lookbehind. This works "well enough" until STENCIL-419 is completed.
59194
+ */
59195
+ const typeNameRegex = new RegExp(`${typeAlias.localName}\\b${endingStrChar}`, 'g');
59196
+ return currentTypeName.replace(typeNameRegex, typeAlias.importName);
59197
+ };
58932
59198
  /**
58933
59199
  * Writes Stencil core typings file to disk for a dist-* output target
58934
59200
  * @param config the Stencil configuration associated with the project being compiled
@@ -58970,15 +59236,16 @@ const sortImportNames = (a, b) => {
58970
59236
  /**
58971
59237
  * Generates the individual event types for all @Event() decorated events in a component
58972
59238
  * @param cmpMeta component runtime metadata for a single component
59239
+ * @param typeImportData locally/imported/globally used type names, which may be used to prevent naming collisions
59240
+ * @param cmpClassName The pascal cased name of the component class
58973
59241
  * @returns the generated type metadata
58974
59242
  */
58975
- const generateEventTypes = (cmpMeta) => {
59243
+ const generateEventTypes = (cmpMeta, typeImportData, cmpClassName) => {
58976
59244
  return cmpMeta.events.map((cmpEvent) => {
58977
59245
  const name = `on${toTitleCase(cmpEvent.name)}`;
58978
- const type = cmpEvent.complexType.original
58979
- ? `(event: CustomEvent<${cmpEvent.complexType.original}>) => void`
58980
- : `CustomEvent`;
58981
- return {
59246
+ const cmpEventDetailInterface = `${cmpClassName}CustomEvent`;
59247
+ const type = getEventType$1(cmpEvent, cmpEventDetailInterface, typeImportData, cmpMeta.sourceFilePath);
59248
+ const typeInfo = {
58982
59249
  name,
58983
59250
  type,
58984
59251
  optional: false,
@@ -58986,35 +59253,63 @@ const generateEventTypes = (cmpMeta) => {
58986
59253
  internal: cmpEvent.internal,
58987
59254
  jsdoc: getTextDocs(cmpEvent.docs),
58988
59255
  };
59256
+ return typeInfo;
58989
59257
  });
58990
59258
  };
59259
+ /**
59260
+ * Determine the correct type name for all type(s) used by a class member annotated with `@Event()`
59261
+ * @param cmpEvent the compiler metadata for a single `@Event()`
59262
+ * @param cmpEventDetailInterface the name of the custom event type to use in the generated type
59263
+ * @param typeImportData locally/imported/globally used type names, which may be used to prevent naming collisions
59264
+ * @param componentSourcePath the path to the component on disk
59265
+ * @returns the type associated with a `@Event()`
59266
+ */
59267
+ const getEventType$1 = (cmpEvent, cmpEventDetailInterface, typeImportData, componentSourcePath) => {
59268
+ if (!cmpEvent.complexType.original) {
59269
+ return 'CustomEvent';
59270
+ }
59271
+ const updatedTypeName = updateTypeIdentifierNames(cmpEvent.complexType.references, typeImportData, componentSourcePath, cmpEvent.complexType.original);
59272
+ return `(event: ${cmpEventDetailInterface}<${updatedTypeName}>) => void`;
59273
+ };
58991
59274
 
58992
59275
  /**
58993
59276
  * Generates the individual event types for all @Method() decorated events in a component
58994
59277
  * @param cmpMeta component runtime metadata for a single component
59278
+ * @param typeImportData locally/imported/globally used type names, which may be used to prevent naming collisions
58995
59279
  * @returns the generated type metadata
58996
59280
  */
58997
- const generateMethodTypes = (cmpMeta) => {
59281
+ const generateMethodTypes = (cmpMeta, typeImportData) => {
58998
59282
  return cmpMeta.methods.map((cmpMethod) => ({
58999
59283
  name: cmpMethod.name,
59000
- type: cmpMethod.complexType.signature,
59284
+ type: getType$1(cmpMethod, typeImportData, cmpMeta.sourceFilePath),
59001
59285
  optional: false,
59002
59286
  required: false,
59003
59287
  internal: cmpMethod.internal,
59004
59288
  jsdoc: getTextDocs(cmpMethod.docs),
59005
59289
  }));
59006
59290
  };
59291
+ /**
59292
+ * Determine the correct type name for all type(s) used by a class member annotated with `@Method()`
59293
+ * @param cmpMethod the compiler metadata for a single `@Method()`
59294
+ * @param typeImportData locally/imported/globally used type names, which may be used to prevent naming collisions
59295
+ * @param componentSourcePath the path to the component on disk
59296
+ * @returns the type associated with a `@Method()`
59297
+ */
59298
+ function getType$1(cmpMethod, typeImportData, componentSourcePath) {
59299
+ return updateTypeIdentifierNames(cmpMethod.complexType.references, typeImportData, componentSourcePath, cmpMethod.complexType.signature);
59300
+ }
59007
59301
 
59008
59302
  /**
59009
59303
  * Generates the individual event types for all @Prop() decorated events in a component
59010
59304
  * @param cmpMeta component runtime metadata for a single component
59305
+ * @param typeImportData locally/imported/globally used type names, which may be used to prevent naming collisions
59011
59306
  * @returns the generated type metadata
59012
59307
  */
59013
- const generatePropTypes = (cmpMeta) => {
59308
+ const generatePropTypes = (cmpMeta, typeImportData) => {
59014
59309
  return [
59015
59310
  ...cmpMeta.properties.map((cmpProp) => ({
59016
59311
  name: cmpProp.name,
59017
- type: cmpProp.complexType.original,
59312
+ type: getType(cmpProp, typeImportData, cmpMeta.sourceFilePath),
59018
59313
  optional: cmpProp.optional,
59019
59314
  required: cmpProp.required,
59020
59315
  internal: cmpProp.internal,
@@ -59030,20 +59325,31 @@ const generatePropTypes = (cmpMeta) => {
59030
59325
  })),
59031
59326
  ];
59032
59327
  };
59328
+ /**
59329
+ * Determine the correct type name for all type(s) used by a class member annotated with `@Prop()`
59330
+ * @param cmpProp the compiler metadata for a single `@Prop()`
59331
+ * @param typeImportData locally/imported/globally used type names, which may be used to prevent naming collisions
59332
+ * @param componentSourcePath the path to the component on disk
59333
+ * @returns the type associated with a `@Prop()`
59334
+ */
59335
+ function getType(cmpProp, typeImportData, componentSourcePath) {
59336
+ return updateTypeIdentifierNames(cmpProp.complexType.references, typeImportData, componentSourcePath, cmpProp.complexType.original);
59337
+ }
59033
59338
 
59034
59339
  /**
59035
59340
  * Generate a string based on the types that are defined within a component
59036
59341
  * @param cmp the metadata for the component that a type definition string is generated for
59342
+ * @param typeImportData locally/imported/globally used type names, which may be used to prevent naming collisions
59037
59343
  * @param areTypesInternal `true` if types being generated are for a project's internal purposes, `false` otherwise
59038
59344
  * @returns the generated types string alongside additional metadata
59039
59345
  */
59040
- const generateComponentTypes = (cmp, areTypesInternal) => {
59346
+ const generateComponentTypes = (cmp, typeImportData, areTypesInternal) => {
59041
59347
  const tagName = cmp.tagName.toLowerCase();
59042
59348
  const tagNameAsPascal = dashToPascalCase$1(tagName);
59043
59349
  const htmlElementName = `HTML${tagNameAsPascal}Element`;
59044
- const propAttributes = generatePropTypes(cmp);
59045
- const methodAttributes = generateMethodTypes(cmp);
59046
- const eventAttributes = generateEventTypes(cmp);
59350
+ const propAttributes = generatePropTypes(cmp, typeImportData);
59351
+ const methodAttributes = generateMethodTypes(cmp, typeImportData);
59352
+ const eventAttributes = generateEventTypes(cmp, typeImportData, tagNameAsPascal);
59047
59353
  const componentAttributes = attributesToMultiLineString([...propAttributes, ...methodAttributes], false, areTypesInternal);
59048
59354
  const isDep = cmp.isCollectionDependency;
59049
59355
  const jsxAttributes = attributesToMultiLineString([...propAttributes, ...eventAttributes], true, areTypesInternal);
@@ -59087,66 +59393,111 @@ const attributesToMultiLineString = (attributes, jsxAttributes, internal) => {
59087
59393
  return attributesStr !== '' ? `${attributesStr}\n` : '';
59088
59394
  };
59089
59395
 
59396
+ /**
59397
+ * Generates the custom event interface for each component that combines the `CustomEvent` interface with
59398
+ * the HTMLElement target. This is used to allow implementers to use strict typings on event handlers.
59399
+ *
59400
+ * The generated interface accepts a generic for the event detail type. This allows implementers to use
59401
+ * custom typings for individual events without Stencil needing to generate an interface for each event.
59402
+ *
59403
+ * @param cmp The component compiler metadata
59404
+ * @returns The generated interface type definition.
59405
+ */
59406
+ const generateEventDetailTypes = (cmp) => {
59407
+ const tagName = cmp.tagName.toLowerCase();
59408
+ const tagNameAsPascal = dashToPascalCase$1(tagName);
59409
+ const htmlElementName = `HTML${tagNameAsPascal}Element`;
59410
+ const isDep = cmp.isCollectionDependency;
59411
+ const cmpEventInterface = `${tagNameAsPascal}CustomEvent`;
59412
+ const cmpInterface = [
59413
+ `export interface ${cmpEventInterface}<T> extends CustomEvent<T> {`,
59414
+ ` detail: T;`,
59415
+ ` target: ${htmlElementName};`,
59416
+ `}`,
59417
+ ];
59418
+ return {
59419
+ isDep,
59420
+ tagName,
59421
+ tagNameAsPascal,
59422
+ htmlElementName,
59423
+ component: cmpInterface.join('\n'),
59424
+ jsx: cmpInterface.join('\n'),
59425
+ element: cmpInterface.join('\n'),
59426
+ };
59427
+ };
59428
+
59090
59429
  /**
59091
59430
  * Find all referenced types by a component and add them to the `importDataObj` parameter
59092
- * @param importDataObj key/value of type import file, each value is an array of imported types
59093
- * @param allTypes an output parameter containing a map of seen types and the number of times the type has been seen
59431
+ * @param importDataObj an output parameter that contains the imported types seen thus far by the compiler
59432
+ * @param typeCounts a map of seen types and the number of times the type has been seen
59094
59433
  * @param cmp the metadata associated with the component whose types are being inspected
59095
59434
  * @param filePath the path of the component file
59096
59435
  * @returns the updated import data
59097
59436
  */
59098
- const updateReferenceTypeImports = (importDataObj, allTypes, cmp, filePath) => {
59099
- const updateImportReferences = updateImportReferenceFactory(allTypes, filePath);
59437
+ const updateReferenceTypeImports = (importDataObj, typeCounts, cmp, filePath) => {
59438
+ const updateImportReferences = updateImportReferenceFactory(typeCounts, filePath);
59100
59439
  return [...cmp.properties, ...cmp.events, ...cmp.methods]
59101
59440
  .filter((cmpProp) => cmpProp.complexType && cmpProp.complexType.references)
59102
- .reduce((obj, cmpProp) => {
59103
- return updateImportReferences(obj, cmpProp.complexType.references);
59441
+ .reduce((typesImportData, cmpProp) => {
59442
+ return updateImportReferences(typesImportData, cmpProp.complexType.references);
59104
59443
  }, importDataObj);
59105
59444
  };
59106
- const updateImportReferenceFactory = (allTypes, filePath) => {
59445
+ /**
59446
+ * Factory function to create an `ImportReferenceUpdater` instance
59447
+ * @param typeCounts a key-value store of seen type names and the number of times the type name has been seen
59448
+ * @param filePath the path of the file containing the component whose imports are being inspected
59449
+ * @returns an `ImportReferenceUpdater` instance for updating import references in the provided `filePath`
59450
+ */
59451
+ const updateImportReferenceFactory = (typeCounts, filePath) => {
59452
+ /**
59453
+ * Determines the number of times that a type identifier (name) has been used. If an identifier has been used before,
59454
+ * append the number of times the identifier has been seen to its name to avoid future naming collisions
59455
+ * @param name the identifier name to check for previous usages
59456
+ * @returns the identifier name, potentially with an integer appended to its name if it has been seen before.
59457
+ */
59107
59458
  function getIncrementTypeName(name) {
59108
- const counter = allTypes.get(name);
59459
+ const counter = typeCounts.get(name);
59109
59460
  if (counter === undefined) {
59110
- allTypes.set(name, 1);
59461
+ typeCounts.set(name, 1);
59111
59462
  return name;
59112
59463
  }
59113
- allTypes.set(name, counter + 1);
59464
+ typeCounts.set(name, counter + 1);
59114
59465
  return `${name}${counter}`;
59115
59466
  }
59116
- return (obj, typeReferences) => {
59467
+ return (existingTypeImportData, typeReferences) => {
59117
59468
  Object.keys(typeReferences)
59118
59469
  .map((typeName) => {
59119
59470
  return [typeName, typeReferences[typeName]];
59120
59471
  })
59121
- .forEach(([typeName, type]) => {
59122
- let importFileLocation;
59472
+ .forEach(([typeName, typeReference]) => {
59473
+ let importResolvedFile;
59123
59474
  // If global then there is no import statement needed
59124
- if (type.location === 'global') {
59475
+ if (typeReference.location === 'global') {
59125
59476
  return;
59126
59477
  // If local then import location is the current file
59127
59478
  }
59128
- else if (type.location === 'local') {
59129
- importFileLocation = filePath;
59479
+ else if (typeReference.location === 'local') {
59480
+ importResolvedFile = filePath;
59130
59481
  }
59131
- else if (type.location === 'import') {
59132
- importFileLocation = type.path;
59482
+ else if (typeReference.location === 'import') {
59483
+ importResolvedFile = typeReference.path;
59133
59484
  }
59134
59485
  // If this is a relative path make it absolute
59135
- if (importFileLocation.startsWith('.')) {
59136
- importFileLocation = resolve$1(dirname(filePath), importFileLocation);
59486
+ if (importResolvedFile.startsWith('.')) {
59487
+ importResolvedFile = resolve$1(dirname(filePath), importResolvedFile);
59137
59488
  }
59138
- obj[importFileLocation] = obj[importFileLocation] || [];
59489
+ existingTypeImportData[importResolvedFile] = existingTypeImportData[importResolvedFile] || [];
59139
59490
  // If this file already has a reference to this type move on
59140
- if (obj[importFileLocation].find((df) => df.localName === typeName)) {
59491
+ if (existingTypeImportData[importResolvedFile].find((df) => df.localName === typeName)) {
59141
59492
  return;
59142
59493
  }
59143
59494
  const newTypeName = getIncrementTypeName(typeName);
59144
- obj[importFileLocation].push({
59495
+ existingTypeImportData[importResolvedFile].push({
59145
59496
  localName: typeName,
59146
59497
  importName: newTypeName,
59147
59498
  });
59148
59499
  });
59149
- return obj;
59500
+ return existingTypeImportData;
59150
59501
  };
59151
59502
  };
59152
59503
 
@@ -59184,7 +59535,7 @@ const generateAppTypes = async (config, compilerCtx, buildCtx, destination) => {
59184
59535
  return hasComponentsDtsChanged;
59185
59536
  };
59186
59537
  /**
59187
- * Generates a `component.d.ts` file's contents, which contains the typings for all components in a Stencil project
59538
+ * Generates a `components.d.ts` file's contents, which contains the typings for all components in a Stencil project
59188
59539
  * @param config the Stencil configuration associated with the project being compiled
59189
59540
  * @param buildCtx the context associated with the current build
59190
59541
  * @param areTypesInternal determines if non-exported type definitions are being generated or not
@@ -59195,12 +59546,26 @@ const generateComponentTypesFile = (config, buildCtx, areTypesInternal) => {
59195
59546
  const c = [];
59196
59547
  const allTypes = new Map();
59197
59548
  const components = buildCtx.components.filter((m) => !m.isCollectionDependency);
59549
+ const componentEventDetailTypes = [];
59198
59550
  const modules = components.map((cmp) => {
59551
+ /**
59552
+ * Generate a key-value store that uses the path to the file where an import is defined as the key, and an object
59553
+ * containing the import's original name and any 'new' name we give it to avoid collisions. We're generating this
59554
+ * data structure for each Stencil component in series, therefore the memory footprint of this entity will likely
59555
+ * grow as more components (with additional types) are processed.
59556
+ */
59199
59557
  typeImportData = updateReferenceTypeImports(typeImportData, allTypes, cmp, cmp.sourceFilePath);
59200
- return generateComponentTypes(cmp, areTypesInternal);
59558
+ if (cmp.events.length > 0) {
59559
+ /**
59560
+ * Only generate event detail types for components that have events.
59561
+ */
59562
+ componentEventDetailTypes.push(generateEventDetailTypes(cmp));
59563
+ }
59564
+ return generateComponentTypes(cmp, typeImportData, areTypesInternal);
59201
59565
  });
59202
59566
  c.push(COMPONENTS_DTS_HEADER);
59203
59567
  c.push(`import { HTMLStencilElement, JSXBase } from "@stencil/core/internal";`);
59568
+ // write the import statements for our type declaration file
59204
59569
  c.push(...Object.keys(typeImportData).map((filePath) => {
59205
59570
  const typeData = typeImportData[filePath];
59206
59571
  let importFilePath;
@@ -59222,7 +59587,10 @@ const generateComponentTypesFile = (config, buildCtx, areTypesInternal) => {
59222
59587
  })
59223
59588
  .join(`, `)} } from "${importFilePath}";`;
59224
59589
  }));
59225
- c.push(`export namespace Components {\n${modules.map((m) => `${m.component}`).join('\n')}\n}`);
59590
+ c.push(`export namespace Components {`);
59591
+ c.push(...modules.map((m) => `${m.component}`));
59592
+ c.push(`}`);
59593
+ c.push(...componentEventDetailTypes.map((m) => `${m.component}`));
59226
59594
  c.push(`declare global {`);
59227
59595
  c.push(...modules.map((m) => m.element));
59228
59596
  c.push(` interface HTMLElementTagNameMap {`);
@@ -61950,7 +62318,7 @@ const getRelativeDts = (config, srcPath, emitDtsPath) => {
61950
62318
  emitDtsPath = join(emitDtsPath, '..');
61951
62319
  srcPath = normalizePath$1(join(srcPath, '..'));
61952
62320
  }
61953
- return join.apply(null, parts.reverse());
62321
+ return join(...parts.reverse());
61954
62322
  };
61955
62323
 
61956
62324
  const outputServiceWorkers = async (config, buildCtx) => {
@@ -62253,52 +62621,114 @@ const getTsOptionsToExtend = (config) => {
62253
62621
  return tsOptions;
62254
62622
  };
62255
62623
 
62624
+ /**
62625
+ * Create a TypeScript Program ({@link ts.Program}) to perform builds of a Stencil project using the provided
62626
+ * `buildCallback` entity
62627
+ * @param config a Stencil configuration to apply to a full build of a Stencil project
62628
+ * @param buildCallback a callback that invokes the actual transpilation of a Stencil project
62629
+ * @returns a Program that marries the TypeScript and Stencil compilers together.
62630
+ */
62256
62631
  const createTsBuildProgram = async (config, buildCallback) => {
62257
- let isRunning = false;
62258
- let timeoutId;
62632
+ let isBuildRunning = false;
62633
+ let currentBuildTimeoutId;
62259
62634
  const optionsToExtend = getTsOptionsToExtend(config);
62635
+ /**
62636
+ * Create a {@link ts.System}. The System is responsible for handling all interactions between the TypeScript compiler
62637
+ * and the host operating system.
62638
+ */
62260
62639
  const tsWatchSys = {
62261
62640
  ...t.sys,
62262
- watchFile(path, callback) {
62263
- if (path.endsWith(`/${GENERATED_DTS$1}`)) {
62264
- return t.sys.watchFile(path, callback);
62265
- }
62641
+ /**
62642
+ * Watch changes in source files, missing files needed to update the program or config file
62643
+ * @returns a no-op file watcher
62644
+ */
62645
+ watchFile() {
62266
62646
  return {
62267
62647
  close() { },
62268
62648
  };
62269
62649
  },
62650
+ /**
62651
+ * Watch a resolved module's failed lookup locations, config file specs, type roots where auto type reference
62652
+ * directives are added
62653
+ * @returns a no-op file watcher
62654
+ */
62270
62655
  watchDirectory() {
62271
62656
  return {
62272
62657
  close() { },
62273
62658
  };
62274
62659
  },
62275
- setTimeout(callback, time) {
62276
- timeoutId = setInterval(() => {
62277
- if (!isRunning) {
62660
+ /**
62661
+ * Set delayed compilation, so that multiple changes in short span are compiled together
62662
+ * @param callback a callback to invoke upon the completion of compilation. this function is provided to Stencil by
62663
+ * the TypeScript compiler.
62664
+ * @param timeoutMs the minimum time to wait (in milliseconds) before checking if compilation is complete or not
62665
+ * @returns the identifier for the interval that's created
62666
+ */
62667
+ setTimeout(callback, timeoutMs) {
62668
+ currentBuildTimeoutId = setInterval(() => {
62669
+ if (!isBuildRunning) {
62278
62670
  callback();
62279
- clearInterval(timeoutId);
62671
+ clearInterval(currentBuildTimeoutId);
62280
62672
  }
62281
- }, config.sys.watchTimeout || time);
62282
- return timeoutId;
62673
+ }, config.sys.watchTimeout || timeoutMs);
62674
+ return currentBuildTimeoutId;
62283
62675
  },
62284
- clearTimeout(id) {
62285
- return clearInterval(id);
62676
+ /**
62677
+ * Reset existing delayed compilation
62678
+ * @param timeoutId the current build timeout identifier to clear
62679
+ */
62680
+ clearTimeout(timeoutId) {
62681
+ clearInterval(timeoutId);
62286
62682
  },
62287
62683
  };
62288
- config.sys.addDestory(() => tsWatchSys.clearTimeout(timeoutId));
62684
+ config.sys.addDestory(() => tsWatchSys.clearTimeout(currentBuildTimeoutId));
62685
+ /**
62686
+ * Create a {@link ts.WatchCompilerHost}. A CompilerHost allows a {@link ts.Program} to interact with the
62687
+ * {@link ts.System}, by acting as an intermediary:
62688
+ * ```
62689
+ * ┌────────────┐ ┌──────────────────────┐ ┌───────────┐ ┌──────────────────┐
62690
+ * │ ts.Program │<->│ ts.WatchCompilerHost │<->│ ts.System │<->│ Operating System │
62691
+ * └────────────┘ └──────────────────────┘ └───────────┘ └──────────────────┘
62692
+ * ```
62693
+ *
62694
+ * Strictly speaking, the created entity is a subclass of a WatchCompilerHost. The
62695
+ * {@link ts.WatchCompilerHostOfConfigFile} class has the following features that makes it useful to Stencil (even
62696
+ * when Stencil is performing a single, full build):
62697
+ * - it provides the opportunity to extend/alter an existing tsconfig file, allowing users to override specific
62698
+ * configuration options via {@link ts.WatchCompilerHostOfConfigFile#optionsToExtend}, which is a provided as an
62699
+ * argument in the constructor
62700
+ * - it includes the {@link ts.WatchCompilerHost#afterProgramCreate} function in its interface, which Stencil
62701
+ * overrides to invoke a build callback (not as a part of this object's creation)
62702
+ */
62289
62703
  const tsWatchHost = t.createWatchCompilerHost(config.tsconfig, optionsToExtend, tsWatchSys, t.createEmitAndSemanticDiagnosticsBuilderProgram, (reportDiagnostic) => {
62290
62704
  config.logger.debug('watch reportDiagnostic:' + reportDiagnostic.messageText);
62291
62705
  }, (reportWatchStatus) => {
62292
62706
  config.logger.debug(reportWatchStatus.messageText);
62293
62707
  });
62708
+ /**
62709
+ * Override {@link ts.WatchCompilerHost#afterProgramCreate} to invoke the build callback that was provided as an
62710
+ * argument to this function.
62711
+ * @param tsBuilder a {@link ts.BuilderProgram} to manage the {@link ts.Program} in the provided build context
62712
+ */
62294
62713
  tsWatchHost.afterProgramCreate = async (tsBuilder) => {
62295
- isRunning = true;
62714
+ isBuildRunning = true;
62296
62715
  await buildCallback(tsBuilder);
62297
- isRunning = false;
62716
+ isBuildRunning = false;
62298
62717
  };
62718
+ /**
62719
+ * Create the initial {@link ts.Program} using Stencil's custom {@link ts.WatchCompilerHostOfConfigFile}. The Program
62720
+ * represents the _TypeScript_ compiler context, that will work in tandem with Stencil's compiler context and build
62721
+ * context
62722
+ */
62299
62723
  return t.createWatchProgram(tsWatchHost);
62300
62724
  };
62301
62725
 
62726
+ /**
62727
+ * Build a callable function to perform a full build of a Stencil project
62728
+ * @param config a Stencil configuration to apply to a full build of a Stencil project
62729
+ * @param compilerCtx the current Stencil compiler context
62730
+ * @returns the results of a full build of Stencil
62731
+ */
62302
62732
  const createFullBuild = async (config, compilerCtx) => {
62303
62733
  return new Promise((resolve) => {
62304
62734
  let tsWatchProgram = null;
@@ -62306,6 +62736,10 @@ const createFullBuild = async (config, compilerCtx) => {
62306
62736
  config.logger.debug(`fileUpdate: ${p}`);
62307
62737
  compilerCtx.fs.clearFileCache(p);
62308
62738
  });
62739
+ /**
62740
+ * A function that kicks off the transpilation process for both the TypeScript and Stencil compilers
62741
+ * @param tsBuilder the manager of the {@link ts.Program} state
62742
+ */
62309
62743
  const onBuild = async (tsBuilder) => {
62310
62744
  const buildCtx = new BuildContext(config, compilerCtx);
62311
62745
  buildCtx.isRebuild = false;
@@ -62362,9 +62796,16 @@ const createInMemoryFs = (sys) => {
62362
62796
  return data.exists;
62363
62797
  };
62364
62798
  /**
62365
- * Synchronous!!! Do not use!!!
62799
+ * **Synchronous!!! Do not use!!!**
62366
62800
  * (Only typescript transpiling is allowed to use)
62367
- * @param filePath
62801
+ *
62802
+ * Synchronously get information about a file from a provided path. This function will attempt to use an in-memory
62803
+ * cache before performing a blocking read.
62804
+ *
62805
+ * In the event of a cache hit, the content from the cache will be returned and skip the read.
62806
+ *
62807
+ * @param filePath the path to the file to read
62808
+ * @returns `true` if the file exists, `false` otherwise
62368
62809
  */
62369
62810
  const accessSync = (filePath) => {
62370
62811
  const item = getItem(filePath);
@@ -62536,9 +62977,19 @@ const createInMemoryFs = (sys) => {
62536
62977
  return fileText;
62537
62978
  };
62538
62979
  /**
62539
- * Synchronous!!! Do not use!!!
62980
+ * **Synchronous!!! Do not use!!!**
62540
62981
  * (Only typescript transpiling is allowed to use)
62541
- * @param filePath
62982
+ *
62983
+ * Synchronously read a file from a provided path. This function will attempt to use an in-memory cache before
62984
+ * performing a blocking read in the following circumstances:
62985
+ * - no `opts` are provided
62986
+ * - the `useCache` member on `opts` is set to `true`, or is not set
62987
+ *
62988
+ * In the event of a cache hit, the content from the cache will be returned and skip the read.
62989
+ *
62990
+ * @param filePath the path to the file to read
62991
+ * @param opts a configuration to use when reading a file
62992
+ * @returns the contents of the file (read from either disk or the cache).
62542
62993
  */
62543
62994
  const readFileSync = (filePath, opts) => {
62544
62995
  if (opts == null || opts.useCache === true || opts.useCache === undefined) {
@@ -62631,10 +63082,13 @@ const createInMemoryFs = (sys) => {
62631
63082
  };
62632
63083
  };
62633
63084
  /**
62634
- * Synchronous!!! Do not use!!!
62635
- * Always returns an object, does not throw errors.
63085
+ * **Synchronous!!! Do not use!!!**
62636
63086
  * (Only typescript transpiling is allowed to use)
62637
- * @param itemPath
63087
+ *
63088
+ * Searches an in-memory cache for an item at the provided path. Always returns an object, **does not throw errors**.
63089
+ *
63090
+ * @param itemPath the path to the file to read
63091
+ * @returns an object describing the item found at the provided `itemPath`
62638
63092
  */
62639
63093
  const statSync = (itemPath) => {
62640
63094
  const item = getItem(itemPath);
@@ -63460,6 +63914,11 @@ const patchFs = (userSys) => {
63460
63914
  Object.assign(fsObj.__sys, userSys);
63461
63915
  };
63462
63916
 
63917
+ /**
63918
+ * Generate a Stencil compiler instance
63919
+ * @param config a Stencil configuration to apply to the compiler instance
63920
+ * @returns a new instance of a Stencil compiler
63921
+ */
63463
63922
  const createCompiler = async (config) => {
63464
63923
  // actual compiler code
63465
63924
  // could be in a web worker on the browser
@@ -64140,7 +64599,7 @@ const getComponentPathContent = (componentGraph, outputTarget) => {
64140
64599
  const dependencies = [
64141
64600
  {
64142
64601
  name: "@stencil/core",
64143
- version: "2.15.1",
64602
+ version: "2.16.1-0",
64144
64603
  main: "compiler/stencil.js",
64145
64604
  resources: [
64146
64605
  "package.json",
@@ -64254,29 +64713,55 @@ const getAbsolutePath = (config, dir) => {
64254
64713
  }
64255
64714
  return dir;
64256
64715
  };
64716
+ /**
64717
+ * This function does two things:
64718
+ *
64719
+ * 1. If you pass a `flagName`, it will hoist that `flagName` out of the
64720
+ * `ConfigFlags` object and onto the 'root' level (if you will) of the
64721
+ * `config` under the `configName` (`keyof d.Config`) that you pass.
64722
+ * 2. If you _don't_ pass a `flagName` it will just set the value you supply
64723
+ * on the config.
64724
+ *
64725
+ * @param config the config that we want to update
64726
+ * @param configName the key we're setting on the config
64727
+ * @param flagName either the name of a ConfigFlag prop we want to hoist up or null
64728
+ * @param defaultValue the default value we should set!
64729
+ */
64257
64730
  const setBooleanConfig = (config, configName, flagName, defaultValue) => {
64731
+ var _a;
64258
64732
  if (flagName) {
64259
- if (typeof config.flags[flagName] === 'boolean') {
64260
- config[configName] = config.flags[flagName];
64733
+ const flagValue = (_a = config.flags) === null || _a === void 0 ? void 0 : _a[flagName];
64734
+ if (isBoolean$1(flagValue)) {
64735
+ config[configName] = flagValue;
64261
64736
  }
64262
64737
  }
64263
64738
  const userConfigName = getUserConfigName(config, configName);
64264
64739
  if (typeof config[userConfigName] === 'function') {
64265
64740
  config[userConfigName] = !!config[userConfigName]();
64266
64741
  }
64267
- if (typeof config[userConfigName] === 'boolean') {
64742
+ if (isBoolean$1(config[userConfigName])) {
64268
64743
  config[configName] = config[userConfigName];
64269
64744
  }
64270
64745
  else {
64271
64746
  config[configName] = defaultValue;
64272
64747
  }
64273
64748
  };
64749
+ /**
64750
+ * Find any possibly mis-capitalized configuration names on the config, logging
64751
+ * and warning if one is found.
64752
+ *
64753
+ * @param config the user-supplied config that we're dealing with
64754
+ * @param correctConfigName the configuration name that we're checking for right now
64755
+ * @returns a string container a mis-capitalized config name found on the
64756
+ * config object, if any.
64757
+ */
64274
64758
  const getUserConfigName = (config, correctConfigName) => {
64759
+ var _a;
64275
64760
  const userConfigNames = Object.keys(config);
64276
64761
  for (const userConfigName of userConfigNames) {
64277
64762
  if (userConfigName.toLowerCase() === correctConfigName.toLowerCase()) {
64278
64763
  if (userConfigName !== correctConfigName) {
64279
- config.logger.warn(`config "${userConfigName}" should be "${correctConfigName}"`);
64764
+ (_a = config.logger) === null || _a === void 0 ? void 0 : _a.warn(`config "${userConfigName}" should be "${correctConfigName}"`);
64280
64765
  return userConfigName;
64281
64766
  }
64282
64767
  break;
@@ -64286,19 +64771,20 @@ const getUserConfigName = (config, correctConfigName) => {
64286
64771
  };
64287
64772
 
64288
64773
  const validateDevServer = (config, diagnostics) => {
64289
- var _a;
64774
+ var _a, _b, _c, _d, _e, _f, _g;
64290
64775
  if ((config.devServer === null || config.devServer) === false) {
64291
- return null;
64776
+ return undefined;
64292
64777
  }
64293
- const flags = config.flags;
64778
+ const flags = (_a = config.flags) !== null && _a !== void 0 ? _a : {};
64294
64779
  const devServer = { ...config.devServer };
64295
- if (isString$1(flags.address)) {
64780
+ if (flags.address && isString$1(flags.address)) {
64296
64781
  devServer.address = flags.address;
64297
64782
  }
64298
64783
  else if (!isString$1(devServer.address)) {
64299
64784
  devServer.address = '0.0.0.0';
64300
64785
  }
64301
- let addressProtocol;
64786
+ // default to http for localdev
64787
+ let addressProtocol = 'http';
64302
64788
  if (devServer.address.toLowerCase().startsWith('http://')) {
64303
64789
  devServer.address = devServer.address.substring(7);
64304
64790
  addressProtocol = 'http';
@@ -64308,8 +64794,13 @@ const validateDevServer = (config, diagnostics) => {
64308
64794
  addressProtocol = 'https';
64309
64795
  }
64310
64796
  devServer.address = devServer.address.split('/')[0];
64311
- let addressPort;
64797
+ // split on `:` to get the domain and the (possibly present) port
64798
+ // separately. we've already sliced off the protocol (if present) above
64799
+ // so we can safely split on `:` here.
64312
64800
  const addressSplit = devServer.address.split(':');
64801
+ const isLocalhost = addressSplit[0] === 'localhost' || !isNaN(addressSplit[0].split('.')[0]);
64802
+ // if localhost we use 3333 as a default port
64803
+ let addressPort = isLocalhost ? 3333 : undefined;
64313
64804
  if (addressSplit.length > 1) {
64314
64805
  if (!isNaN(addressSplit[1])) {
64315
64806
  devServer.address = addressSplit[0];
@@ -64323,12 +64814,6 @@ const validateDevServer = (config, diagnostics) => {
64323
64814
  if (isNumber$1(addressPort)) {
64324
64815
  devServer.port = addressPort;
64325
64816
  }
64326
- else if (devServer.address === 'localhost' || !isNaN(devServer.address.split('.')[0])) {
64327
- devServer.port = 3333;
64328
- }
64329
- else {
64330
- devServer.port = null;
64331
- }
64332
64817
  }
64333
64818
  if (devServer.reloadStrategy === undefined) {
64334
64819
  devServer.reloadStrategy = 'hmr';
@@ -64348,14 +64833,14 @@ const validateDevServer = (config, diagnostics) => {
64348
64833
  if (!isBoolean$1(devServer.websocket)) {
64349
64834
  devServer.websocket = true;
64350
64835
  }
64351
- if ((_a = config === null || config === void 0 ? void 0 : config.flags) === null || _a === void 0 ? void 0 : _a.ssr) {
64836
+ if ((_b = config === null || config === void 0 ? void 0 : config.flags) === null || _b === void 0 ? void 0 : _b.ssr) {
64352
64837
  devServer.ssr = true;
64353
64838
  }
64354
64839
  else {
64355
64840
  devServer.ssr = !!devServer.ssr;
64356
64841
  }
64357
64842
  if (devServer.ssr) {
64358
- const wwwOutput = config.outputTargets.find(isOutputTargetWww);
64843
+ const wwwOutput = ((_c = config.outputTargets) !== null && _c !== void 0 ? _c : []).find(isOutputTargetWww);
64359
64844
  devServer.prerenderConfig = wwwOutput === null || wwwOutput === void 0 ? void 0 : wwwOutput.prerenderConfig;
64360
64845
  }
64361
64846
  if (isString$1(config.srcIndexHtml)) {
@@ -64379,16 +64864,17 @@ const validateDevServer = (config, diagnostics) => {
64379
64864
  else if (flags.prerender && !config.watch) {
64380
64865
  devServer.openBrowser = false;
64381
64866
  }
64382
- let serveDir = null;
64383
- let basePath = null;
64384
- const wwwOutputTarget = config.outputTargets.find(isOutputTargetWww);
64867
+ let serveDir;
64868
+ let basePath;
64869
+ const wwwOutputTarget = ((_d = config.outputTargets) !== null && _d !== void 0 ? _d : []).find(isOutputTargetWww);
64385
64870
  if (wwwOutputTarget) {
64386
- const baseUrl = new URL(wwwOutputTarget.baseUrl, 'http://config.stenciljs.com');
64871
+ const baseUrl = new URL((_e = wwwOutputTarget.baseUrl) !== null && _e !== void 0 ? _e : '', 'http://config.stenciljs.com');
64387
64872
  basePath = baseUrl.pathname;
64388
- serveDir = wwwOutputTarget.appDir;
64873
+ serveDir = (_f = wwwOutputTarget.appDir) !== null && _f !== void 0 ? _f : '';
64389
64874
  }
64390
64875
  else {
64391
- serveDir = config.rootDir;
64876
+ basePath = '';
64877
+ serveDir = (_g = config.rootDir) !== null && _g !== void 0 ? _g : '';
64392
64878
  }
64393
64879
  if (!isString$1(basePath) || basePath.trim() === '') {
64394
64880
  basePath = `/`;
@@ -64470,7 +64956,8 @@ const validateNamespace = (c, diagnostics) => {
64470
64956
  }
64471
64957
  };
64472
64958
  const validateDistNamespace = (config, diagnostics) => {
64473
- const hasDist = config.outputTargets.some(isOutputTargetDist);
64959
+ var _a;
64960
+ const hasDist = ((_a = config.outputTargets) !== null && _a !== void 0 ? _a : []).some(isOutputTargetDist);
64474
64961
  if (hasDist) {
64475
64962
  if (!isString$1(config.namespace) || config.namespace.toLowerCase() === 'app') {
64476
64963
  const err = buildError(diagnostics);
@@ -64480,10 +64967,25 @@ const validateDistNamespace = (config, diagnostics) => {
64480
64967
  };
64481
64968
  const DEFAULT_NAMESPACE = 'App';
64482
64969
 
64970
+ /**
64971
+ * Check the provided `.hydratedFlag` prop and return a properly-validated value.
64972
+ *
64973
+ * @param config the configuration we're examining
64974
+ * @returns a suitable value for the hydratedFlag property
64975
+ */
64483
64976
  const validateHydrated = (config) => {
64977
+ /**
64978
+ * If `config.hydratedFlag` is set to `null` that is an explicit signal that we
64979
+ * should _not_ create a default configuration when validating and should instead
64980
+ * just return `undefined`.
64981
+ *
64982
+ * See {@link HydratedFlag} for more details.
64983
+ */
64484
64984
  if (config.hydratedFlag === null || config.hydratedFlag === false) {
64485
- return null;
64985
+ return undefined;
64486
64986
  }
64987
+ // Here we start building up a default config since `.hydratedFlag` wasn't set to
64988
+ // `null` on the provided config.
64487
64989
  const hydratedFlag = { ...config.hydratedFlag };
64488
64990
  if (!isString$1(hydratedFlag.name) || hydratedFlag.property === '') {
64489
64991
  hydratedFlag.name = `hydrated`;
@@ -64597,9 +65099,19 @@ const validateCustomOutput = (config, diagnostics, userOutputs) => {
64597
65099
  });
64598
65100
  };
64599
65101
 
65102
+ /**
65103
+ * Validate that the "dist" output targets are valid and ready to go.
65104
+ *
65105
+ * This function will also add in additional output targets to its output, based on the input supplied.
65106
+ *
65107
+ * @param config the compiler config, what else?
65108
+ * @param userOutputs a user-supplied list of output targets.
65109
+ * @returns a list of OutputTargets which have been validated for us.
65110
+ */
64600
65111
  const validateDist = (config, userOutputs) => {
64601
65112
  const distOutputTargets = userOutputs.filter(isOutputTargetDist);
64602
65113
  return distOutputTargets.reduce((outputs, o) => {
65114
+ var _a;
64603
65115
  const distOutputTarget = validateOutputTargetDist(config, o);
64604
65116
  outputs.push(distOutputTarget);
64605
65117
  const namespace = config.fsNamespace || 'app';
@@ -64619,7 +65131,7 @@ const validateDist = (config, userOutputs) => {
64619
65131
  type: COPY,
64620
65132
  dir: lazyDir,
64621
65133
  copyAssets: 'dist',
64622
- copy: [...distOutputTarget.copy],
65134
+ copy: ((_a = distOutputTarget.copy) !== null && _a !== void 0 ? _a : []).concat(),
64623
65135
  });
64624
65136
  outputs.push({
64625
65137
  type: DIST_GLOBAL_STYLES,
@@ -64629,7 +65141,6 @@ const validateDist = (config, userOutputs) => {
64629
65141
  type: DIST_TYPES,
64630
65142
  dir: distOutputTarget.dir,
64631
65143
  typesDir: distOutputTarget.typesDir,
64632
- empty: distOutputTarget.empty,
64633
65144
  });
64634
65145
  if (config.buildDist) {
64635
65146
  if (distOutputTarget.collectionDir) {
@@ -64674,39 +65185,44 @@ const validateDist = (config, userOutputs) => {
64674
65185
  return outputs;
64675
65186
  }, []);
64676
65187
  };
65188
+ /**
65189
+ * Validate that an OutputTargetDist object has what it needs to do it's job.
65190
+ * To enforce this, we have this function return
65191
+ * `Required<d.OutputTargetDist>`, giving us a compile-time check that all
65192
+ * properties are defined (with either user-supplied or default values).
65193
+ *
65194
+ * @param config the current config
65195
+ * @param o the OutputTargetDist object we want to validate
65196
+ * @returns `Required<d.OutputTargetDist>`, i.e. `d.OutputTargetDist` with all
65197
+ * optional properties rendered un-optional.
65198
+ */
64677
65199
  const validateOutputTargetDist = (config, o) => {
65200
+ var _a;
65201
+ // we need to create an object with a bunch of default values here so that
65202
+ // the typescript compiler can infer their types correctly
64678
65203
  const outputTarget = {
64679
65204
  ...o,
64680
65205
  dir: getAbsolutePath(config, o.dir || DEFAULT_DIR),
65206
+ buildDir: isString$1(o.buildDir) ? o.buildDir : DEFAULT_BUILD_DIR,
65207
+ collectionDir: o.collectionDir !== undefined ? o.collectionDir : DEFAULT_COLLECTION_DIR,
65208
+ typesDir: o.typesDir || DEFAULT_TYPES_DIR,
65209
+ esmLoaderPath: o.esmLoaderPath || DEFAULT_ESM_LOADER_DIR,
65210
+ copy: validateCopy((_a = o.copy) !== null && _a !== void 0 ? _a : [], []),
65211
+ polyfills: isBoolean$1(o.polyfills) ? o.polyfills : undefined,
65212
+ empty: isBoolean$1(o.empty) ? o.empty : true,
64681
65213
  };
64682
- if (!isString$1(outputTarget.buildDir)) {
64683
- outputTarget.buildDir = DEFAULT_BUILD_DIR;
64684
- }
64685
65214
  if (!isAbsolute$1(outputTarget.buildDir)) {
64686
65215
  outputTarget.buildDir = join(outputTarget.dir, outputTarget.buildDir);
64687
65216
  }
64688
- if (outputTarget.collectionDir === undefined) {
64689
- outputTarget.collectionDir = DEFAULT_COLLECTION_DIR;
64690
- }
64691
65217
  if (outputTarget.collectionDir && !isAbsolute$1(outputTarget.collectionDir)) {
64692
65218
  outputTarget.collectionDir = join(outputTarget.dir, outputTarget.collectionDir);
64693
65219
  }
64694
- if (!outputTarget.esmLoaderPath) {
64695
- outputTarget.esmLoaderPath = DEFAULT_ESM_LOADER_DIR;
64696
- }
64697
65220
  if (!isAbsolute$1(outputTarget.esmLoaderPath)) {
64698
65221
  outputTarget.esmLoaderPath = resolve$1(outputTarget.dir, outputTarget.esmLoaderPath);
64699
65222
  }
64700
- if (!outputTarget.typesDir) {
64701
- outputTarget.typesDir = DEFAULT_TYPES_DIR;
64702
- }
64703
65223
  if (!isAbsolute$1(outputTarget.typesDir)) {
64704
65224
  outputTarget.typesDir = join(outputTarget.dir, outputTarget.typesDir);
64705
65225
  }
64706
- if (!isBoolean$1(outputTarget.empty)) {
64707
- outputTarget.empty = true;
64708
- }
64709
- outputTarget.copy = validateCopy(outputTarget.copy, []);
64710
65226
  return outputTarget;
64711
65227
  };
64712
65228
  const DEFAULT_DIR = 'dist';
@@ -65106,9 +65622,9 @@ const validateCustomElementBundle = (config, userOutputs) => {
65106
65622
  const validateOutputTargets = (config, diagnostics) => {
65107
65623
  const userOutputs = (config.outputTargets || []).slice();
65108
65624
  userOutputs.forEach((outputTarget) => {
65109
- if (!VALID_TYPES.includes(outputTarget.type)) {
65625
+ if (!isValidConfigOutputTarget(outputTarget.type)) {
65110
65626
  const err = buildError(diagnostics);
65111
- err.messageText = `Invalid outputTarget type "${outputTarget.type}". Valid outputTarget types include: ${VALID_TYPES.map((t) => `"${t}"`).join(', ')}`;
65627
+ err.messageText = `Invalid outputTarget type "${outputTarget.type}". Valid outputTarget types include: ${VALID_CONFIG_OUTPUT_TARGETS.map((t) => `"${t}"`).join(', ')}`;
65112
65628
  }
65113
65629
  else if (outputTarget.type === DIST_CUSTOM_ELEMENTS_BUNDLE) {
65114
65630
  // TODO(STENCIL-260): Remove this check when the 'dist-custom-elements-bundle' is removed
@@ -65244,6 +65760,7 @@ const DEFAULT_ROLLUP_CONFIG = {
65244
65760
  };
65245
65761
 
65246
65762
  const validateTesting = (config, diagnostics) => {
65763
+ var _a;
65247
65764
  const testing = (config.testing = Object.assign({}, config.testing || {}));
65248
65765
  if (!config.flags || (!config.flags.e2e && !config.flags.spec)) {
65249
65766
  return;
@@ -65298,10 +65815,11 @@ const validateTesting = (config, diagnostics) => {
65298
65815
  testing.testPathIgnorePatterns = DEFAULT_IGNORE_PATTERNS.map((ignorePattern) => {
65299
65816
  return join(testing.rootDir, ignorePattern);
65300
65817
  });
65301
- config.outputTargets
65818
+ ((_a = config.outputTargets) !== null && _a !== void 0 ? _a : [])
65302
65819
  .filter((o) => (isOutputTargetDist(o) || isOutputTargetWww(o)) && o.dir)
65303
65820
  .forEach((outputTarget) => {
65304
- testing.testPathIgnorePatterns.push(outputTarget.dir);
65821
+ var _a;
65822
+ (_a = testing.testPathIgnorePatterns) === null || _a === void 0 ? void 0 : _a.push(outputTarget.dir);
65305
65823
  });
65306
65824
  }
65307
65825
  if (typeof testing.preset !== 'string') {
@@ -65418,7 +65936,15 @@ const validateWorkers = (config) => {
65418
65936
  }
65419
65937
  };
65420
65938
 
65421
- const validateConfig = (userConfig) => {
65939
+ /**
65940
+ * Validate a Config object, ensuring that all its field are present and
65941
+ * consistent with our expectations. This function transforms an
65942
+ * `UnvalidatedConfig` to a `Config`.
65943
+ *
65944
+ * @param userConfig an unvalidated config that we've gotten from a user
65945
+ * @returns an object with config and diagnostics props
65946
+ */
65947
+ const validateConfig = (userConfig = {}) => {
65422
65948
  const config = Object.assign({}, userConfig || {}); // not positive it's json safe
65423
65949
  const diagnostics = [];
65424
65950
  // copy flags (we know it'll be json safe)
@@ -65986,6 +66512,10 @@ const convertStaticToMeta = (config, compilerCtx, buildCtx, typeChecker, collect
65986
66512
 
65987
66513
  /**
65988
66514
  * Stand-alone compiling of a single string
66515
+ * @param config the Stencil configuration to use in the compilation process
66516
+ * @param input the string to compile
66517
+ * @param transformOpts a configuration object for how the string is compiled
66518
+ * @returns the results of compiling the provided input string
65989
66519
  */
65990
66520
  const transpileModule = (config, input, transformOpts) => {
65991
66521
  if (!config.logger) {