xmlui 0.12.4 → 0.12.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/index.cjs +2453 -151
- package/dist/bin/index.js +2405 -106
- package/dist/for-node/vite-xmlui-plugin.cjs +76 -1
- package/dist/for-node/vite-xmlui-plugin.js +76 -1
- package/dist/lib/{extractParam-GS7LIVZM.js → extractParam-JIDhZ5Xc.js} +30 -3
- package/dist/lib/{index-BERG25LO.js → index-CNTDdONe.js} +3945 -3180
- package/dist/lib/index.css +2 -2
- package/dist/lib/{initMock-tbJIWT5s.js → initMock-CU7EJWWZ.js} +2 -2
- package/dist/lib/{parser-C4e5pSIM.js → parser-DhasSn5-.js} +89 -5
- package/dist/lib/testing.d.ts +15 -0
- package/dist/lib/testing.js +3 -3
- package/dist/lib/{xmlui-parser-Dk9Ul7U9.js → xmlui-parser-BJ0vVKbY.js} +1 -1
- package/dist/lib/xmlui-parser.d.ts +14 -1
- package/dist/lib/xmlui-parser.js +2 -2
- package/dist/lib/xmlui.d.ts +27 -3
- package/dist/lib/xmlui.js +5 -3
- package/dist/metadata/TextBox-DAybtr8B.cjs +1 -0
- package/dist/metadata/{TextBox-DNQU3Cnq.js → TextBox-DHL5_vCt.js} +4319 -3539
- package/dist/metadata/behaviors.cjs +1 -1
- package/dist/metadata/behaviors.js +1 -1
- package/dist/metadata/{initMock-CI3hpGyU.js → initMock-BnJbxxe5.js} +1 -1
- package/dist/metadata/{initMock-_V-TJBxb.cjs → initMock-CyKzqt1R.cjs} +1 -1
- package/dist/metadata/metadata-utils.cjs +1 -1
- package/dist/metadata/metadata-utils.js +1 -1
- package/dist/metadata/{transform-8Zh9SKvP.js → transform-D3iR12tV.js} +114 -30
- package/dist/metadata/transform-RxMduR7r.cjs +1 -0
- package/dist/metadata/xmlui-metadata.cjs +1 -1
- package/dist/metadata/xmlui-metadata.js +5 -4
- package/dist/metadata/xmlui.css +2 -2
- package/dist/standalone/xmlui-standalone.es.d.ts +40 -9
- package/dist/standalone/xmlui-standalone.umd.js +42 -43
- package/package.json +1 -3
- package/dist/metadata/TextBox-Ctkog5jq.cjs +0 -1
- package/dist/metadata/transform-C6FwhNer.cjs +0 -1
package/dist/bin/index.cjs
CHANGED
|
@@ -54,12 +54,19 @@ let path = require("path");
|
|
|
54
54
|
path = __toESM(path);
|
|
55
55
|
let __eslint_community_regexpp = require("@eslint-community/regexpp");
|
|
56
56
|
__eslint_community_regexpp = __toESM(__eslint_community_regexpp);
|
|
57
|
+
require("react");
|
|
58
|
+
let lodash_es = require("lodash-es");
|
|
59
|
+
lodash_es = __toESM(lodash_es);
|
|
57
60
|
let node_fs = require("node:fs");
|
|
58
61
|
node_fs = __toESM(node_fs);
|
|
59
62
|
let node_url = require("node:url");
|
|
60
63
|
node_url = __toESM(node_url);
|
|
61
64
|
let node_path = require("node:path");
|
|
62
65
|
node_path = __toESM(node_path);
|
|
66
|
+
let node_fs_promises = require("node:fs/promises");
|
|
67
|
+
node_fs_promises = __toESM(node_fs_promises);
|
|
68
|
+
let node_vm = require("node:vm");
|
|
69
|
+
node_vm = __toESM(node_vm);
|
|
63
70
|
let yargs_yargs = require("yargs/yargs");
|
|
64
71
|
yargs_yargs = __toESM(yargs_yargs);
|
|
65
72
|
let yargs_helpers = require("yargs/helpers");
|
|
@@ -71,7 +78,7 @@ vite_plugin_lib_inject_css = __toESM(vite_plugin_lib_inject_css);
|
|
|
71
78
|
|
|
72
79
|
//#region ../node_modules/picomatch/lib/constants.js
|
|
73
80
|
var require_constants = /* @__PURE__ */ __commonJS({ "../node_modules/picomatch/lib/constants.js": ((exports, module) => {
|
|
74
|
-
const path$
|
|
81
|
+
const path$7 = require("path");
|
|
75
82
|
const WIN_SLASH = "\\\\/";
|
|
76
83
|
const WIN_NO_SLASH = `[^${WIN_SLASH}]`;
|
|
77
84
|
/**
|
|
@@ -196,7 +203,7 @@ var require_constants = /* @__PURE__ */ __commonJS({ "../node_modules/picomatch/
|
|
|
196
203
|
CHAR_UNDERSCORE: 95,
|
|
197
204
|
CHAR_VERTICAL_LINE: 124,
|
|
198
205
|
CHAR_ZERO_WIDTH_NOBREAK_SPACE: 65279,
|
|
199
|
-
SEP: path$
|
|
206
|
+
SEP: path$7.sep,
|
|
200
207
|
extglobChars(chars) {
|
|
201
208
|
return {
|
|
202
209
|
"!": {
|
|
@@ -235,7 +242,7 @@ var require_constants = /* @__PURE__ */ __commonJS({ "../node_modules/picomatch/
|
|
|
235
242
|
//#endregion
|
|
236
243
|
//#region ../node_modules/picomatch/lib/utils.js
|
|
237
244
|
var require_utils = /* @__PURE__ */ __commonJS({ "../node_modules/picomatch/lib/utils.js": ((exports) => {
|
|
238
|
-
const path$
|
|
245
|
+
const path$6 = require("path");
|
|
239
246
|
const win32$1 = process.platform === "win32";
|
|
240
247
|
const { REGEX_BACKSLASH, REGEX_REMOVE_BACKSLASH, REGEX_SPECIAL_CHARS, REGEX_SPECIAL_CHARS_GLOBAL } = require_constants();
|
|
241
248
|
exports.isObject = (val) => val !== null && typeof val === "object" && !Array.isArray(val);
|
|
@@ -255,7 +262,7 @@ var require_utils = /* @__PURE__ */ __commonJS({ "../node_modules/picomatch/lib/
|
|
|
255
262
|
};
|
|
256
263
|
exports.isWindows = (options) => {
|
|
257
264
|
if (options && typeof options.windows === "boolean") return options.windows;
|
|
258
|
-
return win32$1 === true || path$
|
|
265
|
+
return win32$1 === true || path$6.sep === "\\";
|
|
259
266
|
};
|
|
260
267
|
exports.escapeLast = (input, char, lastIdx) => {
|
|
261
268
|
const idx = input.lastIndexOf(char, lastIdx);
|
|
@@ -1431,7 +1438,7 @@ var require_parse = /* @__PURE__ */ __commonJS({ "../node_modules/picomatch/lib/
|
|
|
1431
1438
|
//#endregion
|
|
1432
1439
|
//#region ../node_modules/picomatch/lib/picomatch.js
|
|
1433
1440
|
var require_picomatch$1 = /* @__PURE__ */ __commonJS({ "../node_modules/picomatch/lib/picomatch.js": ((exports, module) => {
|
|
1434
|
-
const path$
|
|
1441
|
+
const path$5 = require("path");
|
|
1435
1442
|
const scan = require_scan();
|
|
1436
1443
|
const parse = require_parse();
|
|
1437
1444
|
const utils = require_utils();
|
|
@@ -1570,7 +1577,7 @@ var require_picomatch$1 = /* @__PURE__ */ __commonJS({ "../node_modules/picomatc
|
|
|
1570
1577
|
* @api public
|
|
1571
1578
|
*/
|
|
1572
1579
|
picomatch.matchBase = (input, glob$2, options, posix$1 = utils.isWindows(options)) => {
|
|
1573
|
-
return (glob$2 instanceof RegExp ? glob$2 : picomatch.makeRe(glob$2, options)).test(path$
|
|
1580
|
+
return (glob$2 instanceof RegExp ? glob$2 : picomatch.makeRe(glob$2, options)).test(path$5.basename(input));
|
|
1574
1581
|
};
|
|
1575
1582
|
/**
|
|
1576
1583
|
* Returns true if **any** of the given glob `patterns` match the specified `string`.
|
|
@@ -5198,10 +5205,66 @@ var Parser = class {
|
|
|
5198
5205
|
endToken = this._lexer.peek();
|
|
5199
5206
|
this.expectToken(TokenType.RParent, "W006");
|
|
5200
5207
|
}
|
|
5201
|
-
|
|
5208
|
+
let newExprResult = this.createExpressionNode(T_NEW_EXPRESSION, {
|
|
5202
5209
|
callee,
|
|
5203
5210
|
arguments: args
|
|
5204
5211
|
}, startToken, endToken);
|
|
5212
|
+
let exitMemberLoop = false;
|
|
5213
|
+
do {
|
|
5214
|
+
const currentStart = this._lexer.peek();
|
|
5215
|
+
switch (currentStart.type) {
|
|
5216
|
+
case TokenType.LParent: {
|
|
5217
|
+
this._lexer.get();
|
|
5218
|
+
let invokeArgs = [];
|
|
5219
|
+
if (this._lexer.peek().type !== TokenType.RParent) {
|
|
5220
|
+
const expr = this.parseExpr();
|
|
5221
|
+
if (!expr) {
|
|
5222
|
+
this.reportError("W001");
|
|
5223
|
+
return null;
|
|
5224
|
+
}
|
|
5225
|
+
invokeArgs = expr.type === T_SEQUENCE_EXPRESSION ? expr.exprs : [expr];
|
|
5226
|
+
}
|
|
5227
|
+
const invokeEndToken = this._lexer.peek();
|
|
5228
|
+
this.expectToken(TokenType.RParent, "W006");
|
|
5229
|
+
newExprResult = this.createExpressionNode(T_FUNCTION_INVOCATION_EXPRESSION, {
|
|
5230
|
+
obj: newExprResult,
|
|
5231
|
+
arguments: invokeArgs
|
|
5232
|
+
}, startToken, invokeEndToken);
|
|
5233
|
+
break;
|
|
5234
|
+
}
|
|
5235
|
+
case TokenType.Dot:
|
|
5236
|
+
case TokenType.OptionalChaining: {
|
|
5237
|
+
this._lexer.get();
|
|
5238
|
+
const member = this._lexer.get();
|
|
5239
|
+
if (!tokenTraits[member.type].keywordLike) {
|
|
5240
|
+
this.reportError("W003");
|
|
5241
|
+
return null;
|
|
5242
|
+
}
|
|
5243
|
+
newExprResult = this.createExpressionNode(T_MEMBER_ACCESS_EXPRESSION, {
|
|
5244
|
+
obj: newExprResult,
|
|
5245
|
+
member: member.text,
|
|
5246
|
+
opt: currentStart.type === TokenType.OptionalChaining
|
|
5247
|
+
}, startToken, member);
|
|
5248
|
+
break;
|
|
5249
|
+
}
|
|
5250
|
+
case TokenType.LSquare: {
|
|
5251
|
+
this._lexer.get();
|
|
5252
|
+
const memberExpr = this.getExpression();
|
|
5253
|
+
if (!memberExpr) return null;
|
|
5254
|
+
const calcEndToken = this._lexer.peek();
|
|
5255
|
+
this.expectToken(TokenType.RSquare, "W005");
|
|
5256
|
+
newExprResult = this.createExpressionNode(T_CALCULATED_MEMBER_ACCESS_EXPRESSION, {
|
|
5257
|
+
obj: newExprResult,
|
|
5258
|
+
member: memberExpr
|
|
5259
|
+
}, startToken, calcEndToken);
|
|
5260
|
+
break;
|
|
5261
|
+
}
|
|
5262
|
+
default:
|
|
5263
|
+
exitMemberLoop = true;
|
|
5264
|
+
break;
|
|
5265
|
+
}
|
|
5266
|
+
} while (!exitMemberLoop);
|
|
5267
|
+
return newExprResult;
|
|
5205
5268
|
}
|
|
5206
5269
|
if (startToken.type === TokenType.Identifier && startToken.text === "await") {
|
|
5207
5270
|
this._lexer.get();
|
|
@@ -6055,70 +6118,70 @@ var ModuleCache = class {
|
|
|
6055
6118
|
* @param path The module path
|
|
6056
6119
|
* @returns The resolved module or undefined if not cached
|
|
6057
6120
|
*/
|
|
6058
|
-
static getResolved(path$
|
|
6059
|
-
return this.resolvedModules.get(path$
|
|
6121
|
+
static getResolved(path$8) {
|
|
6122
|
+
return this.resolvedModules.get(path$8);
|
|
6060
6123
|
}
|
|
6061
6124
|
/**
|
|
6062
6125
|
* Sets a resolved module in cache
|
|
6063
6126
|
* @param path The module path
|
|
6064
6127
|
* @param module The resolved module
|
|
6065
6128
|
*/
|
|
6066
|
-
static setResolved(path$
|
|
6067
|
-
this.resolvedModules.set(path$
|
|
6129
|
+
static setResolved(path$8, module$1) {
|
|
6130
|
+
this.resolvedModules.set(path$8, module$1);
|
|
6068
6131
|
}
|
|
6069
6132
|
/**
|
|
6070
6133
|
* Checks if a resolved module is cached
|
|
6071
6134
|
* @param path The module path
|
|
6072
6135
|
* @returns True if the module is in cache
|
|
6073
6136
|
*/
|
|
6074
|
-
static hasResolved(path$
|
|
6075
|
-
return this.resolvedModules.has(path$
|
|
6137
|
+
static hasResolved(path$8) {
|
|
6138
|
+
return this.resolvedModules.has(path$8);
|
|
6076
6139
|
}
|
|
6077
6140
|
/**
|
|
6078
6141
|
* Gets a parsed module from cache
|
|
6079
6142
|
* @param path The module path
|
|
6080
6143
|
* @returns The parsed module (or promise) or undefined if not cached
|
|
6081
6144
|
*/
|
|
6082
|
-
static getParsed(path$
|
|
6083
|
-
return this.parsedModules.get(path$
|
|
6145
|
+
static getParsed(path$8) {
|
|
6146
|
+
return this.parsedModules.get(path$8);
|
|
6084
6147
|
}
|
|
6085
6148
|
/**
|
|
6086
6149
|
* Sets a parsed module in cache
|
|
6087
6150
|
* @param path The module path
|
|
6088
6151
|
* @param module The parsed module or promise
|
|
6089
6152
|
*/
|
|
6090
|
-
static setParsed(path$
|
|
6091
|
-
this.parsedModules.set(path$
|
|
6153
|
+
static setParsed(path$8, module$1) {
|
|
6154
|
+
this.parsedModules.set(path$8, module$1);
|
|
6092
6155
|
}
|
|
6093
6156
|
/**
|
|
6094
6157
|
* Checks if a parsed module is cached
|
|
6095
6158
|
* @param path The module path
|
|
6096
6159
|
* @returns True if the module is in cache
|
|
6097
6160
|
*/
|
|
6098
|
-
static hasParsed(path$
|
|
6099
|
-
return this.parsedModules.has(path$
|
|
6161
|
+
static hasParsed(path$8) {
|
|
6162
|
+
return this.parsedModules.has(path$8);
|
|
6100
6163
|
}
|
|
6101
6164
|
/**
|
|
6102
6165
|
* Checks if a module is currently being parsed (to detect circular dependencies at parse level)
|
|
6103
6166
|
* @param path The module path
|
|
6104
6167
|
* @returns True if the module is currently being parsed
|
|
6105
6168
|
*/
|
|
6106
|
-
static isCurrentlyParsing(path$
|
|
6107
|
-
return this.currentlyParsing.has(path$
|
|
6169
|
+
static isCurrentlyParsing(path$8) {
|
|
6170
|
+
return this.currentlyParsing.has(path$8);
|
|
6108
6171
|
}
|
|
6109
6172
|
/**
|
|
6110
6173
|
* Mark a module as currently being parsed
|
|
6111
6174
|
* @param path The module path
|
|
6112
6175
|
*/
|
|
6113
|
-
static markCurrentlyParsing(path$
|
|
6114
|
-
this.currentlyParsing.add(path$
|
|
6176
|
+
static markCurrentlyParsing(path$8) {
|
|
6177
|
+
this.currentlyParsing.add(path$8);
|
|
6115
6178
|
}
|
|
6116
6179
|
/**
|
|
6117
6180
|
* Mark a module as no longer being parsed
|
|
6118
6181
|
* @param path The module path
|
|
6119
6182
|
*/
|
|
6120
|
-
static unmarkCurrentlyParsing(path$
|
|
6121
|
-
this.currentlyParsing.delete(path$
|
|
6183
|
+
static unmarkCurrentlyParsing(path$8) {
|
|
6184
|
+
this.currentlyParsing.delete(path$8);
|
|
6122
6185
|
}
|
|
6123
6186
|
/**
|
|
6124
6187
|
* Clears all caches (both resolved and parsed modules) and resets parsing state
|
|
@@ -6187,9 +6250,9 @@ var FilePathResolver = class {
|
|
|
6187
6250
|
* @returns The normalized path
|
|
6188
6251
|
* @throws Error if path tries to go above root
|
|
6189
6252
|
*/
|
|
6190
|
-
normalizePath(path$
|
|
6191
|
-
const isAbsolute$1 = path$
|
|
6192
|
-
const segments = (isAbsolute$1 ? path$
|
|
6253
|
+
normalizePath(path$8) {
|
|
6254
|
+
const isAbsolute$1 = path$8.startsWith("/");
|
|
6255
|
+
const segments = (isAbsolute$1 ? path$8.substring(1) : path$8).split("/").filter((seg) => seg !== "");
|
|
6193
6256
|
const normalized = [];
|
|
6194
6257
|
for (const segment of segments) if (segment === ".") continue;
|
|
6195
6258
|
else if (segment === "..") {
|
|
@@ -6282,16 +6345,16 @@ var PathResolver = class {
|
|
|
6282
6345
|
* @param path The path to check
|
|
6283
6346
|
* @returns True if the path is a URL
|
|
6284
6347
|
*/
|
|
6285
|
-
static isUrl(path$
|
|
6286
|
-
return path$
|
|
6348
|
+
static isUrl(path$8) {
|
|
6349
|
+
return path$8.startsWith("http://") || path$8.startsWith("https://");
|
|
6287
6350
|
}
|
|
6288
6351
|
/**
|
|
6289
6352
|
* Checks if a given string is a file path
|
|
6290
6353
|
* @param path The path to check
|
|
6291
6354
|
* @returns True if the path is a file path
|
|
6292
6355
|
*/
|
|
6293
|
-
static isFilePath(path$
|
|
6294
|
-
return !this.isUrl(path$
|
|
6356
|
+
static isFilePath(path$8) {
|
|
6357
|
+
return !this.isUrl(path$8);
|
|
6295
6358
|
}
|
|
6296
6359
|
/**
|
|
6297
6360
|
* Gets the file name from a path or URL
|
|
@@ -6331,9 +6394,9 @@ var PathResolver = class {
|
|
|
6331
6394
|
* @returns The normalized path
|
|
6332
6395
|
* @throws Error if path tries to go above root
|
|
6333
6396
|
*/
|
|
6334
|
-
static normalizePath(path$
|
|
6335
|
-
if (this.isUrl(path$
|
|
6336
|
-
return new FilePathResolver()["normalizePath"](path$
|
|
6397
|
+
static normalizePath(path$8) {
|
|
6398
|
+
if (this.isUrl(path$8)) return path$8;
|
|
6399
|
+
return new FilePathResolver()["normalizePath"](path$8);
|
|
6337
6400
|
}
|
|
6338
6401
|
};
|
|
6339
6402
|
|
|
@@ -6730,8 +6793,8 @@ async function doParseModule(moduleName, source, moduleFetcher) {
|
|
|
6730
6793
|
const resolvedModule = await ModuleResolver.resolveAndFetchModule(importDecl.source.value, moduleName);
|
|
6731
6794
|
const importedModuleResult = await parseScriptModuleAsync(resolvedModule.path, resolvedModule.content, moduleFetcher);
|
|
6732
6795
|
if (isModuleErrors(importedModuleResult)) {
|
|
6733
|
-
Object.entries(importedModuleResult).forEach(([path$
|
|
6734
|
-
moduleErrors[path$
|
|
6796
|
+
Object.entries(importedModuleResult).forEach(([path$8, errs]) => {
|
|
6797
|
+
moduleErrors[path$8] = errs;
|
|
6735
6798
|
if (errs.some((e) => e.code === ErrorCodes.reactiveVarInImportedModule || e.code === ErrorCodes.constLetInImportedModule)) hasValidationErrors = true;
|
|
6736
6799
|
});
|
|
6737
6800
|
continue;
|
|
@@ -6854,6 +6917,26 @@ const ARROW_EXPR_MARK = "_ARROW_EXPR_";
|
|
|
6854
6917
|
* ```
|
|
6855
6918
|
*/
|
|
6856
6919
|
const PARSED_EVENT_MARK = Symbol.for("__XMLUI_PARSED_EVENT__");
|
|
6920
|
+
/**
|
|
6921
|
+
* Type guard for arrow expression objects.
|
|
6922
|
+
*
|
|
6923
|
+
* Checks if a value is an executable arrow function expression.
|
|
6924
|
+
* These can be called with appropriate context and arguments.
|
|
6925
|
+
*
|
|
6926
|
+
* @param value - The value to check
|
|
6927
|
+
* @returns `true` if the value is an arrow expression object
|
|
6928
|
+
*
|
|
6929
|
+
* @example
|
|
6930
|
+
* ```typescript
|
|
6931
|
+
* const fn = evaluateArrowExpression(node);
|
|
6932
|
+
* if (isArrowExpressionObject(fn)) {
|
|
6933
|
+
* const result = executeFunction(fn, args);
|
|
6934
|
+
* }
|
|
6935
|
+
* ```
|
|
6936
|
+
*/
|
|
6937
|
+
function isArrowExpressionObject(value) {
|
|
6938
|
+
return typeof value === "object" && value !== null && ARROW_EXPR_MARK in value && value[ARROW_EXPR_MARK] === true;
|
|
6939
|
+
}
|
|
6857
6940
|
|
|
6858
6941
|
//#endregion
|
|
6859
6942
|
//#region src/parsers/scripting/types.ts
|
|
@@ -6944,11 +7027,11 @@ var ModuleLoader = class {
|
|
|
6944
7027
|
* }
|
|
6945
7028
|
* ```
|
|
6946
7029
|
*/
|
|
6947
|
-
static async loadModule(path$
|
|
7030
|
+
static async loadModule(path$8, options = {}) {
|
|
6948
7031
|
const { fetcher, allowImports = true, baseUrl, skipCache = false } = options;
|
|
6949
7032
|
try {
|
|
6950
|
-
let resolvedPath = path$
|
|
6951
|
-
if (baseUrl && !PathResolver.isUrl(path$
|
|
7033
|
+
let resolvedPath = path$8;
|
|
7034
|
+
if (baseUrl && !PathResolver.isUrl(path$8) && !PathResolver.isFilePath(path$8)) resolvedPath = PathResolver.resolve(path$8, baseUrl);
|
|
6952
7035
|
if (!skipCache && ModuleCache.hasParsed(resolvedPath)) {
|
|
6953
7036
|
const cached = ModuleCache.getParsed(resolvedPath);
|
|
6954
7037
|
if (cached && !(cached instanceof Promise)) return ok(cached);
|
|
@@ -6959,7 +7042,7 @@ var ModuleLoader = class {
|
|
|
6959
7042
|
return await this.parseWithImports(resolvedPath, content, fetcher);
|
|
6960
7043
|
} catch (error) {
|
|
6961
7044
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
6962
|
-
return err({ [path$
|
|
7045
|
+
return err({ [path$8]: [{
|
|
6963
7046
|
code: "MODULE_LOAD_ERROR",
|
|
6964
7047
|
text: errorMessage,
|
|
6965
7048
|
position: 0,
|
|
@@ -7012,8 +7095,8 @@ var ModuleLoader = class {
|
|
|
7012
7095
|
* @param path The module path to check
|
|
7013
7096
|
* @returns True if the module is cached
|
|
7014
7097
|
*/
|
|
7015
|
-
static isCached(path$
|
|
7016
|
-
return ModuleCache.hasParsed(path$
|
|
7098
|
+
static isCached(path$8) {
|
|
7099
|
+
return ModuleCache.hasParsed(path$8);
|
|
7017
7100
|
}
|
|
7018
7101
|
/**
|
|
7019
7102
|
* Fetches module content from a resolved path
|
|
@@ -7036,8 +7119,8 @@ var ModuleLoader = class {
|
|
|
7036
7119
|
* Parses a module with full import support
|
|
7037
7120
|
*/
|
|
7038
7121
|
static async parseWithImports(moduleName, source, fetcher) {
|
|
7039
|
-
const result = await parseScriptModuleAsync(moduleName, source, fetcher || (async (path$
|
|
7040
|
-
return (await ModuleResolver.resolveModule(path$
|
|
7122
|
+
const result = await parseScriptModuleAsync(moduleName, source, fetcher || (async (path$8) => {
|
|
7123
|
+
return (await ModuleResolver.resolveModule(path$8)).content;
|
|
7041
7124
|
}));
|
|
7042
7125
|
if (this.isModuleErrors(result)) return err(result);
|
|
7043
7126
|
return ok(result);
|
|
@@ -8193,6 +8276,17 @@ function isLineBreak(ch) {
|
|
|
8193
8276
|
return ch === CharacterCodes.lineFeed || ch === CharacterCodes.carriageReturn || ch === CharacterCodes.lineSeparator || ch === CharacterCodes.paragraphSeparator;
|
|
8194
8277
|
}
|
|
8195
8278
|
|
|
8279
|
+
//#endregion
|
|
8280
|
+
//#region src/abstractions/AppContextDefs.ts
|
|
8281
|
+
const MediaBreakpointKeys = [
|
|
8282
|
+
"xs",
|
|
8283
|
+
"sm",
|
|
8284
|
+
"md",
|
|
8285
|
+
"lg",
|
|
8286
|
+
"xl",
|
|
8287
|
+
"xxl"
|
|
8288
|
+
];
|
|
8289
|
+
|
|
8196
8290
|
//#endregion
|
|
8197
8291
|
//#region src/parsers/xmlui-parser/transform.ts
|
|
8198
8292
|
const COMPOUND_COMP_ID = "Component";
|
|
@@ -8443,6 +8537,14 @@ function nodeToComponentDef(node, originalGetText, fileId, preResolvedImports) {
|
|
|
8443
8537
|
comp.uses = splitUsesValue(value);
|
|
8444
8538
|
return;
|
|
8445
8539
|
default:
|
|
8540
|
+
if (name.startsWith("when-")) {
|
|
8541
|
+
const bp = name.slice(5);
|
|
8542
|
+
if (MediaBreakpointKeys.includes(bp)) {
|
|
8543
|
+
comp.responsiveWhen ??= {};
|
|
8544
|
+
comp.responsiveWhen[bp] = value;
|
|
8545
|
+
return;
|
|
8546
|
+
}
|
|
8547
|
+
}
|
|
8446
8548
|
if (startSegment === "var") {
|
|
8447
8549
|
comp.vars ??= {};
|
|
8448
8550
|
comp.vars[name] = value;
|
|
@@ -9136,124 +9238,1894 @@ function splitUsesValue(value) {
|
|
|
9136
9238
|
}
|
|
9137
9239
|
|
|
9138
9240
|
//#endregion
|
|
9139
|
-
//#region src/
|
|
9140
|
-
|
|
9141
|
-
|
|
9142
|
-
|
|
9143
|
-
|
|
9144
|
-
|
|
9145
|
-
|
|
9146
|
-
|
|
9147
|
-
|
|
9148
|
-
|
|
9149
|
-
|
|
9241
|
+
//#region src/components-core/script-runner/ParameterParser.ts
|
|
9242
|
+
/**
|
|
9243
|
+
* This function parses a parameter string and splits them into string literal and binding expression sections
|
|
9244
|
+
* @param source String to parse
|
|
9245
|
+
* @returns Parameter string sections
|
|
9246
|
+
*/
|
|
9247
|
+
function parseParameterString(source) {
|
|
9248
|
+
const result = [];
|
|
9249
|
+
if (source === void 0 || source === null) return result;
|
|
9250
|
+
let phase = ParsePhase.StringLiteral;
|
|
9251
|
+
let section = "";
|
|
9252
|
+
let escape = "";
|
|
9253
|
+
for (let i = 0; i < source.length; i++) {
|
|
9254
|
+
const ch = source[i];
|
|
9255
|
+
switch (phase) {
|
|
9256
|
+
case ParsePhase.StringLiteral:
|
|
9257
|
+
if (ch === "\\") {
|
|
9258
|
+
phase = ParsePhase.Escape;
|
|
9259
|
+
escape = "\\";
|
|
9260
|
+
} else if (ch === "{") {
|
|
9261
|
+
if (section !== "") result.push({
|
|
9262
|
+
type: "literal",
|
|
9263
|
+
value: section
|
|
9264
|
+
});
|
|
9265
|
+
section = "";
|
|
9266
|
+
phase = ParsePhase.ExprStart;
|
|
9267
|
+
} else section += ch;
|
|
9268
|
+
break;
|
|
9269
|
+
case ParsePhase.Escape:
|
|
9270
|
+
if (ch === "\\") {
|
|
9271
|
+
escape += ch;
|
|
9272
|
+
break;
|
|
9273
|
+
}
|
|
9274
|
+
if (ch === "{") section += escape.substring(1) + ch;
|
|
9275
|
+
else section += escape + ch;
|
|
9276
|
+
phase = ParsePhase.StringLiteral;
|
|
9277
|
+
break;
|
|
9278
|
+
case ParsePhase.ExprStart:
|
|
9279
|
+
const exprSource = source.substring(i);
|
|
9280
|
+
const parser = new Parser(source.substring(i));
|
|
9281
|
+
let expr = null;
|
|
9282
|
+
try {
|
|
9283
|
+
expr = parser.parseExpr();
|
|
9284
|
+
} catch (err$1) {
|
|
9285
|
+
throw new Error(`Cannot parse expression: '${exprSource}': ${err$1}`);
|
|
9286
|
+
}
|
|
9287
|
+
const tail = parser.getTail();
|
|
9288
|
+
if (!tail || tail.trim().length < 1 || tail.trim()[0] !== "}") throw new Error(`Unclosed expression: '${source}'\n'${exprSource}'`);
|
|
9289
|
+
else {
|
|
9290
|
+
result.push({
|
|
9291
|
+
type: "expression",
|
|
9292
|
+
value: expr
|
|
9293
|
+
});
|
|
9294
|
+
i = source.length - tail.length;
|
|
9295
|
+
section = "";
|
|
9296
|
+
}
|
|
9297
|
+
phase = ParsePhase.StringLiteral;
|
|
9298
|
+
break;
|
|
9150
9299
|
}
|
|
9151
9300
|
}
|
|
9152
|
-
|
|
9153
|
-
|
|
9301
|
+
switch (phase) {
|
|
9302
|
+
case ParsePhase.StringLiteral:
|
|
9303
|
+
if (section !== "") result.push({
|
|
9304
|
+
type: "literal",
|
|
9305
|
+
value: section
|
|
9306
|
+
});
|
|
9307
|
+
break;
|
|
9308
|
+
case ParsePhase.Escape:
|
|
9309
|
+
result.push({
|
|
9310
|
+
type: "literal",
|
|
9311
|
+
value: section + escape
|
|
9312
|
+
});
|
|
9313
|
+
break;
|
|
9314
|
+
case ParsePhase.ExprStart:
|
|
9315
|
+
result.push({
|
|
9316
|
+
type: "literal",
|
|
9317
|
+
value: section + "{"
|
|
9318
|
+
});
|
|
9319
|
+
break;
|
|
9154
9320
|
}
|
|
9155
|
-
|
|
9156
|
-
|
|
9321
|
+
return result;
|
|
9322
|
+
}
|
|
9323
|
+
var ParsePhase = /* @__PURE__ */ function(ParsePhase$1) {
|
|
9324
|
+
ParsePhase$1[ParsePhase$1["StringLiteral"] = 0] = "StringLiteral";
|
|
9325
|
+
ParsePhase$1[ParsePhase$1["Escape"] = 1] = "Escape";
|
|
9326
|
+
ParsePhase$1[ParsePhase$1["ExprStart"] = 2] = "ExprStart";
|
|
9327
|
+
return ParsePhase$1;
|
|
9328
|
+
}(ParsePhase || {});
|
|
9329
|
+
|
|
9330
|
+
//#endregion
|
|
9331
|
+
//#region src/components-core/script-runner/bannedFunctions.ts
|
|
9332
|
+
/**
|
|
9333
|
+
* Checks if the specified function object is banned from running.
|
|
9334
|
+
* @param func Function to check
|
|
9335
|
+
* @return Information about the banned state, including a helper text
|
|
9336
|
+
*/
|
|
9337
|
+
function isBannedFunction(func) {
|
|
9338
|
+
if (func === void 0) return { banned: false };
|
|
9339
|
+
const bannedInfo = bannedFunctions.find((f) => f.func === func);
|
|
9340
|
+
return bannedInfo ? {
|
|
9341
|
+
banned: true,
|
|
9342
|
+
func: bannedInfo.func,
|
|
9343
|
+
help: bannedInfo.help
|
|
9344
|
+
} : { banned: false };
|
|
9345
|
+
}
|
|
9346
|
+
/**
|
|
9347
|
+
* List of global functions we do not allow to call
|
|
9348
|
+
*/
|
|
9349
|
+
const bannedFunctions = [
|
|
9350
|
+
{ func: globalThis.cancelAnimationFrame },
|
|
9351
|
+
{ func: globalThis.cancelIdleCallback },
|
|
9352
|
+
{ func: globalThis.clearInterval },
|
|
9353
|
+
{ func: globalThis.clearImmediate },
|
|
9354
|
+
{ func: globalThis.clearTimeout },
|
|
9355
|
+
{ func: globalThis.eval },
|
|
9356
|
+
{ func: globalThis.queueMicrotask },
|
|
9357
|
+
{ func: globalThis.requestAnimationFrame },
|
|
9358
|
+
{ func: globalThis.requestIdleCallback },
|
|
9359
|
+
{ func: globalThis.setImmediate },
|
|
9360
|
+
{ func: globalThis.setInterval },
|
|
9361
|
+
{
|
|
9362
|
+
func: globalThis.setTimeout,
|
|
9363
|
+
help: "Use 'delay'"
|
|
9157
9364
|
}
|
|
9158
|
-
|
|
9159
|
-
|
|
9160
|
-
|
|
9161
|
-
|
|
9162
|
-
|
|
9163
|
-
|
|
9164
|
-
|
|
9165
|
-
|
|
9166
|
-
|
|
9167
|
-
|
|
9168
|
-
|
|
9169
|
-
|
|
9170
|
-
|
|
9171
|
-
|
|
9172
|
-
|
|
9173
|
-
|
|
9174
|
-
|
|
9175
|
-
|
|
9176
|
-
|
|
9177
|
-
|
|
9178
|
-
|
|
9179
|
-
|
|
9180
|
-
|
|
9181
|
-
|
|
9365
|
+
];
|
|
9366
|
+
|
|
9367
|
+
//#endregion
|
|
9368
|
+
//#region src/components-core/script-runner/eval-tree-common.ts
|
|
9369
|
+
function getExprValue(expr, thread) {
|
|
9370
|
+
return thread?.valueCache?.get(expr)?.value;
|
|
9371
|
+
}
|
|
9372
|
+
function setExprValue(expr, value, thread) {
|
|
9373
|
+
thread.valueCache ??= /* @__PURE__ */ new Map();
|
|
9374
|
+
thread.valueCache.set(expr, { value });
|
|
9375
|
+
}
|
|
9376
|
+
function isPromise(obj) {
|
|
9377
|
+
return obj && typeof obj.then === "function";
|
|
9378
|
+
}
|
|
9379
|
+
function evalLiteral(thisStack, expr, thread) {
|
|
9380
|
+
setExprValue(expr, { value: expr.value }, thread);
|
|
9381
|
+
thisStack.push(expr.value);
|
|
9382
|
+
return expr.value;
|
|
9383
|
+
}
|
|
9384
|
+
function getIdentifierScope(expr, evalContext, thread) {
|
|
9385
|
+
let type;
|
|
9386
|
+
let scope;
|
|
9387
|
+
if (expr.isGlobal) {
|
|
9388
|
+
scope = globalThis;
|
|
9389
|
+
type = "global";
|
|
9390
|
+
} else {
|
|
9391
|
+
let currentThread = thread ?? evalContext.mainThread;
|
|
9392
|
+
while (currentThread && !scope) {
|
|
9393
|
+
if (currentThread.blocks) for (let idx = currentThread.blocks.length - 1; idx >= 0; idx--) {
|
|
9394
|
+
const blockContext = currentThread.blocks[idx]?.vars;
|
|
9395
|
+
if (blockContext && expr.name in blockContext) {
|
|
9396
|
+
scope = blockContext;
|
|
9397
|
+
type = "block";
|
|
9398
|
+
break;
|
|
9399
|
+
}
|
|
9400
|
+
}
|
|
9401
|
+
if (scope) break;
|
|
9402
|
+
if (currentThread.closures) for (let idx = currentThread.closures.length - 1; idx >= 0; idx--) {
|
|
9403
|
+
const blockContext = currentThread.closures[idx]?.vars;
|
|
9404
|
+
if (blockContext && expr.name in blockContext) {
|
|
9405
|
+
scope = blockContext;
|
|
9406
|
+
type = "block";
|
|
9407
|
+
break;
|
|
9408
|
+
}
|
|
9409
|
+
}
|
|
9410
|
+
if (scope) break;
|
|
9411
|
+
currentThread = currentThread.parent;
|
|
9182
9412
|
}
|
|
9183
|
-
const line = low - 1;
|
|
9184
|
-
return {
|
|
9185
|
-
line,
|
|
9186
|
-
character: offset - lineOffsets[line]
|
|
9187
|
-
};
|
|
9188
9413
|
}
|
|
9189
|
-
|
|
9190
|
-
|
|
9191
|
-
|
|
9192
|
-
|
|
9193
|
-
|
|
9194
|
-
|
|
9195
|
-
|
|
9196
|
-
|
|
9197
|
-
|
|
9198
|
-
if (position.line >= this.newlineOffsets.length) return this.textLength;
|
|
9199
|
-
else if (position.line < 0) return 0;
|
|
9200
|
-
const lineOffset = this.newlineOffsets[position.line];
|
|
9201
|
-
if (position.character <= 0) return lineOffset;
|
|
9202
|
-
const nextLineOffset = position.line + 1 < this.newlineOffsets.length ? this.newlineOffsets[position.line + 1] : this.textLength;
|
|
9203
|
-
return Math.min(lineOffset + position.character, nextLineOffset);
|
|
9414
|
+
if (!scope) if (evalContext.localContext && expr.name in evalContext.localContext) {
|
|
9415
|
+
scope = evalContext.localContext;
|
|
9416
|
+
type = "localContext";
|
|
9417
|
+
} else if (evalContext.appContext?.[expr.name] !== void 0) {
|
|
9418
|
+
scope = evalContext.appContext;
|
|
9419
|
+
type = "app";
|
|
9420
|
+
} else {
|
|
9421
|
+
scope = globalThis;
|
|
9422
|
+
type = "global";
|
|
9204
9423
|
}
|
|
9205
|
-
|
|
9206
|
-
|
|
9207
|
-
|
|
9208
|
-
|
|
9209
|
-
|
|
9424
|
+
return {
|
|
9425
|
+
type,
|
|
9426
|
+
scope
|
|
9427
|
+
};
|
|
9428
|
+
}
|
|
9429
|
+
function evalIdentifier(thisStack, expr, evalContext, thread) {
|
|
9430
|
+
let value;
|
|
9431
|
+
const valueScope = getIdentifierScope(expr, evalContext, thread).scope;
|
|
9432
|
+
let valueIndex = expr.name;
|
|
9433
|
+
value = valueScope[valueIndex];
|
|
9434
|
+
setExprValue(expr, {
|
|
9435
|
+
valueScope,
|
|
9436
|
+
valueIndex,
|
|
9437
|
+
value
|
|
9438
|
+
}, thread);
|
|
9439
|
+
thisStack.push(value);
|
|
9440
|
+
return value;
|
|
9441
|
+
}
|
|
9442
|
+
function getRootIdScope(expr, evalContext, thread) {
|
|
9443
|
+
switch (expr.type) {
|
|
9444
|
+
case T_IDENTIFIER: return {
|
|
9445
|
+
type: getIdentifierScope(expr, evalContext, thread).type,
|
|
9446
|
+
name: expr.name
|
|
9210
9447
|
};
|
|
9448
|
+
case T_MEMBER_ACCESS_EXPRESSION: return getRootIdScope(expr.obj, evalContext, thread);
|
|
9449
|
+
case T_CALCULATED_MEMBER_ACCESS_EXPRESSION: return getRootIdScope(expr.obj, evalContext, thread);
|
|
9211
9450
|
}
|
|
9212
|
-
|
|
9213
|
-
|
|
9214
|
-
|
|
9215
|
-
|
|
9216
|
-
|
|
9217
|
-
|
|
9218
|
-
|
|
9219
|
-
|
|
9220
|
-
|
|
9221
|
-
|
|
9222
|
-
|
|
9223
|
-
|
|
9224
|
-
|
|
9225
|
-
|
|
9226
|
-
|
|
9227
|
-
|
|
9228
|
-
|
|
9229
|
-
|
|
9230
|
-
|
|
9451
|
+
return null;
|
|
9452
|
+
}
|
|
9453
|
+
function evalMemberAccessCore(thisStack, expr, evalContext, thread) {
|
|
9454
|
+
const parentObj = getExprValue(expr.obj, thread)?.value;
|
|
9455
|
+
const value = expr.opt || evalContext.options?.defaultToOptionalMemberAccess ? parentObj?.[expr.member] : parentObj[expr.member];
|
|
9456
|
+
setExprValue(expr, {
|
|
9457
|
+
valueScope: parentObj,
|
|
9458
|
+
valueIndex: expr.member,
|
|
9459
|
+
value
|
|
9460
|
+
}, thread);
|
|
9461
|
+
thisStack.push(value);
|
|
9462
|
+
return value;
|
|
9463
|
+
}
|
|
9464
|
+
function evalCalculatedMemberAccessCore(thisStack, expr, evalContext, thread) {
|
|
9465
|
+
const parentObj = getExprValue(expr.obj, thread)?.value;
|
|
9466
|
+
const memberObj = getExprValue(expr.member, thread)?.value;
|
|
9467
|
+
const value = evalContext.options?.defaultToOptionalMemberAccess ? parentObj?.[memberObj] : parentObj[memberObj];
|
|
9468
|
+
setExprValue(expr, {
|
|
9469
|
+
valueScope: parentObj,
|
|
9470
|
+
valueIndex: memberObj,
|
|
9471
|
+
value
|
|
9472
|
+
}, thread);
|
|
9473
|
+
thisStack.push(value);
|
|
9474
|
+
return value;
|
|
9475
|
+
}
|
|
9476
|
+
function evalUnaryCore(expr, thisStack, evalContext, thread) {
|
|
9477
|
+
let value;
|
|
9478
|
+
const operand = getExprValue(expr.expr, thread);
|
|
9479
|
+
const operValue = operand?.value;
|
|
9480
|
+
switch (expr.op) {
|
|
9481
|
+
case "typeof":
|
|
9482
|
+
value = typeof operValue;
|
|
9483
|
+
break;
|
|
9484
|
+
case "delete":
|
|
9485
|
+
if (operand.valueScope && operand.valueIndex) value = delete operand.valueScope[operand.valueIndex];
|
|
9486
|
+
else value = false;
|
|
9487
|
+
break;
|
|
9488
|
+
case "+":
|
|
9489
|
+
value = operValue;
|
|
9490
|
+
break;
|
|
9491
|
+
case "-":
|
|
9492
|
+
value = -operValue;
|
|
9493
|
+
break;
|
|
9494
|
+
case "!":
|
|
9495
|
+
value = !operValue;
|
|
9496
|
+
break;
|
|
9497
|
+
case "~":
|
|
9498
|
+
value = ~operValue;
|
|
9499
|
+
break;
|
|
9500
|
+
default: throw new Error(`Unknown unary operator: ${expr.op}`);
|
|
9231
9501
|
}
|
|
9232
|
-
|
|
9233
|
-
|
|
9234
|
-
|
|
9235
|
-
|
|
9236
|
-
|
|
9502
|
+
setExprValue(expr, { value }, thread);
|
|
9503
|
+
thisStack.push(value);
|
|
9504
|
+
return value;
|
|
9505
|
+
}
|
|
9506
|
+
function evalBinaryCore(expr, thisStack, evalContext, thread) {
|
|
9507
|
+
let value;
|
|
9508
|
+
const l = getExprValue(expr.left, thread)?.value;
|
|
9509
|
+
const r = getExprValue(expr.right, thread)?.value;
|
|
9510
|
+
switch (expr.op) {
|
|
9511
|
+
case "**":
|
|
9512
|
+
value = l ** r;
|
|
9513
|
+
break;
|
|
9514
|
+
case "*":
|
|
9515
|
+
value = l * r;
|
|
9516
|
+
break;
|
|
9517
|
+
case "/":
|
|
9518
|
+
value = l / r;
|
|
9519
|
+
break;
|
|
9520
|
+
case "%":
|
|
9521
|
+
value = l % r;
|
|
9522
|
+
break;
|
|
9523
|
+
case "+":
|
|
9524
|
+
value = l + r;
|
|
9525
|
+
break;
|
|
9526
|
+
case "-":
|
|
9527
|
+
value = l - r;
|
|
9528
|
+
break;
|
|
9529
|
+
case ">>":
|
|
9530
|
+
value = l >> r;
|
|
9531
|
+
break;
|
|
9532
|
+
case ">>>":
|
|
9533
|
+
value = l >>> r;
|
|
9534
|
+
break;
|
|
9535
|
+
case "<<":
|
|
9536
|
+
value = l << r;
|
|
9537
|
+
break;
|
|
9538
|
+
case "<":
|
|
9539
|
+
value = l < r;
|
|
9540
|
+
break;
|
|
9541
|
+
case "<=":
|
|
9542
|
+
value = l <= r;
|
|
9543
|
+
break;
|
|
9544
|
+
case ">":
|
|
9545
|
+
value = l > r;
|
|
9546
|
+
break;
|
|
9547
|
+
case ">=":
|
|
9548
|
+
value = l >= r;
|
|
9549
|
+
break;
|
|
9550
|
+
case "in":
|
|
9551
|
+
value = l in r;
|
|
9552
|
+
break;
|
|
9553
|
+
case "==":
|
|
9554
|
+
value = l == r;
|
|
9555
|
+
break;
|
|
9556
|
+
case "!=":
|
|
9557
|
+
value = l != r;
|
|
9558
|
+
break;
|
|
9559
|
+
case "===":
|
|
9560
|
+
value = l === r;
|
|
9561
|
+
break;
|
|
9562
|
+
case "!==":
|
|
9563
|
+
value = l !== r;
|
|
9564
|
+
break;
|
|
9565
|
+
case "&":
|
|
9566
|
+
value = l & r;
|
|
9567
|
+
break;
|
|
9568
|
+
case "^":
|
|
9569
|
+
value = l ^ r;
|
|
9570
|
+
break;
|
|
9571
|
+
case "|":
|
|
9572
|
+
value = l | r;
|
|
9573
|
+
break;
|
|
9574
|
+
case "&&":
|
|
9575
|
+
value = l && r;
|
|
9576
|
+
break;
|
|
9577
|
+
case "||":
|
|
9578
|
+
value = l || r;
|
|
9579
|
+
break;
|
|
9580
|
+
case "??":
|
|
9581
|
+
value = l ?? r;
|
|
9582
|
+
break;
|
|
9583
|
+
default: throw new Error(`Unknown binary operator: ${expr.op}`);
|
|
9237
9584
|
}
|
|
9238
|
-
|
|
9239
|
-
|
|
9240
|
-
|
|
9241
|
-
|
|
9242
|
-
|
|
9585
|
+
setExprValue(expr, { value }, thread);
|
|
9586
|
+
thisStack.push(value);
|
|
9587
|
+
return value;
|
|
9588
|
+
}
|
|
9589
|
+
function evalAssignmentCore(thisStack, expr, evalContext, thread) {
|
|
9590
|
+
const leftValue = getExprValue(expr.leftValue, thread);
|
|
9591
|
+
const newValue = getExprValue(expr.expr, thread)?.value;
|
|
9592
|
+
if (!leftValue.valueScope || leftValue.valueIndex === void 0 || leftValue.valueIndex === null) throw new Error(`Evaluation of ${expr.op} requires a left-hand value.`);
|
|
9593
|
+
const leftScope = leftValue.valueScope;
|
|
9594
|
+
const leftIndex = leftValue.valueIndex;
|
|
9595
|
+
if (typeof leftScope !== "object" || leftScope === null) throw new Error(`Unknown left-hand value`);
|
|
9596
|
+
if (expr.leftValue.type === T_IDENTIFIER) {
|
|
9597
|
+
if (isConstVar(expr.leftValue.name, thread)) throw new Error("A const variable cannot be modified");
|
|
9598
|
+
}
|
|
9599
|
+
if (leftScope === globalThis && !(leftIndex in leftScope)) throw new Error(`Left value variable (${leftIndex}) not found in the scope.`);
|
|
9600
|
+
thisStack.pop();
|
|
9601
|
+
switch (expr.op) {
|
|
9602
|
+
case "=":
|
|
9603
|
+
leftScope[leftIndex] = newValue;
|
|
9604
|
+
break;
|
|
9605
|
+
case "+=":
|
|
9606
|
+
leftScope[leftIndex] += newValue;
|
|
9607
|
+
break;
|
|
9608
|
+
case "-=":
|
|
9609
|
+
leftScope[leftIndex] -= newValue;
|
|
9610
|
+
break;
|
|
9611
|
+
case "**=":
|
|
9612
|
+
leftScope[leftIndex] **= newValue;
|
|
9613
|
+
break;
|
|
9614
|
+
case "*=":
|
|
9615
|
+
leftScope[leftIndex] *= newValue;
|
|
9616
|
+
break;
|
|
9617
|
+
case "/=":
|
|
9618
|
+
leftScope[leftIndex] /= newValue;
|
|
9619
|
+
break;
|
|
9620
|
+
case "%=":
|
|
9621
|
+
leftScope[leftIndex] %= newValue;
|
|
9622
|
+
break;
|
|
9623
|
+
case "<<=":
|
|
9624
|
+
leftScope[leftIndex] <<= newValue;
|
|
9625
|
+
break;
|
|
9626
|
+
case ">>=":
|
|
9627
|
+
leftScope[leftIndex] >>= newValue;
|
|
9628
|
+
break;
|
|
9629
|
+
case ">>>=":
|
|
9630
|
+
leftScope[leftIndex] >>>= newValue;
|
|
9631
|
+
break;
|
|
9632
|
+
case "&=":
|
|
9633
|
+
leftScope[leftIndex] &= newValue;
|
|
9634
|
+
break;
|
|
9635
|
+
case "^=":
|
|
9636
|
+
leftScope[leftIndex] ^= newValue;
|
|
9637
|
+
break;
|
|
9638
|
+
case "|=":
|
|
9639
|
+
leftScope[leftIndex] |= newValue;
|
|
9640
|
+
break;
|
|
9641
|
+
case "&&=":
|
|
9642
|
+
leftScope[leftIndex] &&= newValue;
|
|
9643
|
+
break;
|
|
9644
|
+
case "||=":
|
|
9645
|
+
leftScope[leftIndex] ||= newValue;
|
|
9646
|
+
break;
|
|
9647
|
+
case "??=":
|
|
9648
|
+
leftScope[leftIndex] += newValue;
|
|
9649
|
+
break;
|
|
9243
9650
|
}
|
|
9244
|
-
|
|
9245
|
-
|
|
9246
|
-
|
|
9651
|
+
const value = leftScope[leftIndex];
|
|
9652
|
+
setExprValue(expr, { value }, thread);
|
|
9653
|
+
thisStack.push(value);
|
|
9654
|
+
return value;
|
|
9655
|
+
}
|
|
9656
|
+
function evalPreOrPostCore(thisStack, expr, evalContext, thread) {
|
|
9657
|
+
const operand = getExprValue(expr.expr, thread);
|
|
9658
|
+
if (!operand.valueScope || operand.valueIndex === void 0) throw new Error(`Evaluation of ${expr.op} requires a left-hand value.`);
|
|
9659
|
+
if (expr.expr.type === T_IDENTIFIER) {
|
|
9660
|
+
if (isConstVar(expr.expr.name, thread)) throw new Error("A const variable cannot be modified");
|
|
9661
|
+
}
|
|
9662
|
+
const value = expr.op === "++" ? expr.type === T_PREFIX_OP_EXPRESSION ? ++operand.valueScope[operand.valueIndex] : operand.valueScope[operand.valueIndex]++ : expr.type === T_PREFIX_OP_EXPRESSION ? --operand.valueScope[operand.valueIndex] : operand.valueScope[operand.valueIndex]--;
|
|
9663
|
+
setExprValue(expr, { value }, thread);
|
|
9664
|
+
thisStack.push(value);
|
|
9665
|
+
return value;
|
|
9666
|
+
}
|
|
9667
|
+
function evalArrow(thisStack, expr, thread) {
|
|
9668
|
+
if (expr.async) throw new Error("XMLUI does not support async arrow functions.");
|
|
9669
|
+
const lazyArrow = {
|
|
9670
|
+
...expr,
|
|
9671
|
+
_ARROW_EXPR_: true,
|
|
9672
|
+
closureContext: obtainClosures(thread)
|
|
9673
|
+
};
|
|
9674
|
+
setExprValue(expr, { value: lazyArrow }, thread);
|
|
9675
|
+
thisStack.push(lazyArrow);
|
|
9676
|
+
return lazyArrow;
|
|
9677
|
+
}
|
|
9678
|
+
function obtainClosures(thread) {
|
|
9679
|
+
const closures = thread.blocks?.slice(0) ?? [];
|
|
9680
|
+
return thread.parent ? [...obtainClosures(thread.parent), ...closures] : closures;
|
|
9681
|
+
}
|
|
9682
|
+
/**
|
|
9683
|
+
* Gets the context of the variable
|
|
9684
|
+
* @param id Identifier to test
|
|
9685
|
+
* @param thread Thread to use for evaluation
|
|
9686
|
+
*/
|
|
9687
|
+
function isConstVar(id, thread) {
|
|
9688
|
+
if (thread.blocks) for (let idx = thread.blocks.length; idx >= 0; idx--) {
|
|
9689
|
+
const constContext = thread.blocks[idx]?.constVars;
|
|
9690
|
+
if (constContext && constContext.has(id)) return true;
|
|
9691
|
+
}
|
|
9692
|
+
return false;
|
|
9693
|
+
}
|
|
9694
|
+
function evalTemplateLiteralCore(segmentValues) {
|
|
9695
|
+
return segmentValues.map((value) => typeof value === "string" ? value : `${value}`).join("");
|
|
9247
9696
|
}
|
|
9248
9697
|
|
|
9249
9698
|
//#endregion
|
|
9250
|
-
//#region src/
|
|
9251
|
-
|
|
9252
|
-
|
|
9253
|
-
|
|
9254
|
-
|
|
9255
|
-
|
|
9256
|
-
|
|
9699
|
+
//#region src/components-core/script-runner/statement-queue.ts
|
|
9700
|
+
var StatementQueue = class {
|
|
9701
|
+
constructor() {
|
|
9702
|
+
this.items = [];
|
|
9703
|
+
}
|
|
9704
|
+
get length() {
|
|
9705
|
+
return this.items.length;
|
|
9706
|
+
}
|
|
9707
|
+
peek() {
|
|
9708
|
+
return this.items[0];
|
|
9709
|
+
}
|
|
9710
|
+
dequeue() {
|
|
9711
|
+
return this.items.shift();
|
|
9712
|
+
}
|
|
9713
|
+
push(statements) {
|
|
9714
|
+
this.items.push(...statements);
|
|
9715
|
+
}
|
|
9716
|
+
unshift(statements) {
|
|
9717
|
+
this.items.unshift(...statements);
|
|
9718
|
+
}
|
|
9719
|
+
clearToLabel(label) {
|
|
9720
|
+
while (this.items.length > 0 && this.items[0].label !== label) this.items.shift();
|
|
9721
|
+
}
|
|
9722
|
+
};
|
|
9723
|
+
let nextLabelValue = 1;
|
|
9724
|
+
function mapToItem(statement) {
|
|
9725
|
+
return [{
|
|
9726
|
+
label: nextLabelValue++,
|
|
9727
|
+
statement: { ...statement }
|
|
9728
|
+
}];
|
|
9729
|
+
}
|
|
9730
|
+
function mapStatementToQueueItem(stmt) {
|
|
9731
|
+
return {
|
|
9732
|
+
label: nextLabelValue++,
|
|
9733
|
+
statement: stmt.statement,
|
|
9734
|
+
execInfo: { ...stmt.execInfo }
|
|
9735
|
+
};
|
|
9736
|
+
}
|
|
9737
|
+
function mapStatementsToQueueItems(statements) {
|
|
9738
|
+
return statements.map(mapStatementToQueueItem);
|
|
9739
|
+
}
|
|
9740
|
+
|
|
9741
|
+
//#endregion
|
|
9742
|
+
//#region src/components-core/script-runner/process-statement-common.ts
|
|
9743
|
+
function innermostLoopScope(thread) {
|
|
9744
|
+
if (!thread.loops || thread.loops.length === 0) throw new Error("Missing loop scope");
|
|
9745
|
+
return thread.loops[thread.loops.length - 1];
|
|
9746
|
+
}
|
|
9747
|
+
function innermostBlockScope(thread) {
|
|
9748
|
+
if (!thread.blocks || thread.blocks.length === 0) return void 0;
|
|
9749
|
+
return thread.blocks[thread.blocks.length - 1];
|
|
9750
|
+
}
|
|
9751
|
+
function innermostTryScope(thread) {
|
|
9752
|
+
if (!thread.tryBlocks || thread.tryBlocks.length === 0) throw new Error("Missing try scope");
|
|
9753
|
+
return thread.tryBlocks[thread.tryBlocks.length - 1];
|
|
9754
|
+
}
|
|
9755
|
+
function createLoopScope(thread, continueOffset = 0) {
|
|
9756
|
+
thread.loops ??= [];
|
|
9757
|
+
const breakDepth = thread.blocks?.length ?? 0;
|
|
9758
|
+
const tryDepth = thread.tryBlocks?.length ?? 0;
|
|
9759
|
+
const loopScope = {
|
|
9760
|
+
breakLabel: -1,
|
|
9761
|
+
continueLabel: -1,
|
|
9762
|
+
breakBlockDepth: breakDepth,
|
|
9763
|
+
continueBlockDepth: breakDepth + continueOffset,
|
|
9764
|
+
tryBlockDepth: tryDepth
|
|
9765
|
+
};
|
|
9766
|
+
thread.loops.push(loopScope);
|
|
9767
|
+
return loopScope;
|
|
9768
|
+
}
|
|
9769
|
+
function releaseLoopScope(thread, skipContinuation = true) {
|
|
9770
|
+
const loopScope = innermostLoopScope(thread);
|
|
9771
|
+
if (skipContinuation) thread.loops?.pop();
|
|
9772
|
+
if (thread.blocks) thread.blocks.length = skipContinuation ? loopScope.breakBlockDepth : loopScope.continueBlockDepth;
|
|
9773
|
+
}
|
|
9774
|
+
function toStatementItems(statements) {
|
|
9775
|
+
return statements.map((s) => ({ statement: s }));
|
|
9776
|
+
}
|
|
9777
|
+
function guard(statement) {
|
|
9778
|
+
return {
|
|
9779
|
+
statement,
|
|
9780
|
+
execInfo: { guard: true }
|
|
9781
|
+
};
|
|
9782
|
+
}
|
|
9783
|
+
function closing() {
|
|
9784
|
+
return {
|
|
9785
|
+
statement: {
|
|
9786
|
+
type: T_EMPTY_STATEMENT,
|
|
9787
|
+
nodeId: createXmlUiTreeNodeId()
|
|
9788
|
+
},
|
|
9789
|
+
execInfo: { removeBlockScope: true }
|
|
9790
|
+
};
|
|
9791
|
+
}
|
|
9792
|
+
function provideLoopBody(loopScope, loopStatement, breakLabelValue) {
|
|
9793
|
+
const guardStatement = guard(loopStatement);
|
|
9794
|
+
const toUnshift = mapStatementsToQueueItems([{ statement: loopStatement.body }, guardStatement]);
|
|
9795
|
+
loopScope.breakLabel = breakLabelValue ?? -1;
|
|
9796
|
+
loopScope.continueLabel = toUnshift[1].label;
|
|
9797
|
+
return toUnshift;
|
|
9798
|
+
}
|
|
9799
|
+
function createTryScope(thread, tryStatement) {
|
|
9800
|
+
thread.tryBlocks ??= [];
|
|
9801
|
+
const loopScope = {
|
|
9802
|
+
statement: tryStatement,
|
|
9803
|
+
processingPhase: "try",
|
|
9804
|
+
tryLabel: -1
|
|
9805
|
+
};
|
|
9806
|
+
thread.tryBlocks.push(loopScope);
|
|
9807
|
+
return loopScope;
|
|
9808
|
+
}
|
|
9809
|
+
function provideTryBody(thread, tryScope) {
|
|
9810
|
+
const guardStatement = guard(tryScope.statement);
|
|
9811
|
+
thread.blocks.push({ vars: {} });
|
|
9812
|
+
const toUnshift = mapStatementsToQueueItems([
|
|
9813
|
+
...toStatementItems(tryScope.statement.tryB.stmts),
|
|
9814
|
+
closing(),
|
|
9815
|
+
guardStatement
|
|
9816
|
+
]);
|
|
9817
|
+
tryScope.tryLabel = toUnshift[toUnshift.length - 1].label;
|
|
9818
|
+
return toUnshift;
|
|
9819
|
+
}
|
|
9820
|
+
function provideCatchBody(thread, tryScope) {
|
|
9821
|
+
const guardStatement = guard(tryScope.statement);
|
|
9822
|
+
thread.blocks.push({ vars: {} });
|
|
9823
|
+
const toUnshift = mapStatementsToQueueItems([
|
|
9824
|
+
...toStatementItems(tryScope.statement.catchB.stmts),
|
|
9825
|
+
closing(),
|
|
9826
|
+
guardStatement
|
|
9827
|
+
]);
|
|
9828
|
+
tryScope.tryLabel = toUnshift[toUnshift.length - 1].label;
|
|
9829
|
+
return toUnshift;
|
|
9830
|
+
}
|
|
9831
|
+
function provideFinallyBody(thread, tryScope) {
|
|
9832
|
+
const guardStatement = guard(tryScope.statement);
|
|
9833
|
+
thread.blocks.push({ vars: {} });
|
|
9834
|
+
const finallyBlock = tryScope.statement.finallyB;
|
|
9835
|
+
const toUnshift = mapStatementsToQueueItems([
|
|
9836
|
+
...toStatementItems(finallyBlock ? finallyBlock.stmts : []),
|
|
9837
|
+
closing(),
|
|
9838
|
+
guardStatement
|
|
9839
|
+
]);
|
|
9840
|
+
tryScope.tryLabel = toUnshift[toUnshift.length - 1].label;
|
|
9841
|
+
return toUnshift;
|
|
9842
|
+
}
|
|
9843
|
+
function provideFinallyErrorBody(tryScope) {
|
|
9844
|
+
const toUnshift = mapStatementsToQueueItems([guard(tryScope.statement)]);
|
|
9845
|
+
tryScope.tryLabel = toUnshift[0].label;
|
|
9846
|
+
return toUnshift;
|
|
9847
|
+
}
|
|
9848
|
+
function ensureMainThread(evalContext) {
|
|
9849
|
+
if (!evalContext.mainThread) evalContext.mainThread = {
|
|
9850
|
+
childThreads: [],
|
|
9851
|
+
blocks: [{ vars: {} }],
|
|
9852
|
+
loops: [],
|
|
9853
|
+
breakLabelValue: -1
|
|
9854
|
+
};
|
|
9855
|
+
return evalContext.mainThread;
|
|
9856
|
+
}
|
|
9857
|
+
function hoistFunctionDeclarations(thread, statements) {
|
|
9858
|
+
const block = innermostBlockScope(thread);
|
|
9859
|
+
if (!block) throw new Error("Missing block scope");
|
|
9860
|
+
statements.filter((stmt) => stmt.type === T_FUNCTION_DECLARATION).forEach((stmt) => {
|
|
9861
|
+
const funcDecl = stmt;
|
|
9862
|
+
const arrowExpression = {
|
|
9863
|
+
type: T_ARROW_EXPRESSION,
|
|
9864
|
+
args: funcDecl.args,
|
|
9865
|
+
statement: funcDecl.stmt,
|
|
9866
|
+
closureContext: obtainClosures(thread),
|
|
9867
|
+
_ARROW_EXPR_: true
|
|
9868
|
+
};
|
|
9869
|
+
const id = funcDecl.id.name;
|
|
9870
|
+
if (block.vars[id]) throw new Error(`Variable ${id} is already declared in the current scope.`);
|
|
9871
|
+
block.vars[id] = arrowExpression;
|
|
9872
|
+
block.constVars ??= /* @__PURE__ */ new Set();
|
|
9873
|
+
block.constVars.add(id);
|
|
9874
|
+
});
|
|
9875
|
+
}
|
|
9876
|
+
|
|
9877
|
+
//#endregion
|
|
9878
|
+
//#region src/components-core/EngineError.ts
|
|
9879
|
+
/**
|
|
9880
|
+
* The abstract base class of all UI engine errors
|
|
9881
|
+
*/
|
|
9882
|
+
var EngineError = class EngineError extends Error {
|
|
9883
|
+
constructor(message) {
|
|
9884
|
+
super(message);
|
|
9885
|
+
Object.setPrototypeOf(this, EngineError.prototype);
|
|
9886
|
+
}
|
|
9887
|
+
};
|
|
9888
|
+
/**
|
|
9889
|
+
* Custom exception indicating a parser error
|
|
9890
|
+
*/
|
|
9891
|
+
var ScriptParseError = class ScriptParseError extends EngineError {
|
|
9892
|
+
constructor(message, source, position) {
|
|
9893
|
+
message = `Parser Error: ${message}`;
|
|
9894
|
+
super(message);
|
|
9895
|
+
this.source = source;
|
|
9896
|
+
this.position = position;
|
|
9897
|
+
this.errorCategory = "ScriptParserError";
|
|
9898
|
+
Object.setPrototypeOf(this, ScriptParseError.prototype);
|
|
9899
|
+
}
|
|
9900
|
+
};
|
|
9901
|
+
/**
|
|
9902
|
+
* Custom exception signing parsing error
|
|
9903
|
+
*/
|
|
9904
|
+
var StatementExecutionError = class StatementExecutionError extends EngineError {
|
|
9905
|
+
constructor(message, source) {
|
|
9906
|
+
super(message);
|
|
9907
|
+
this.source = source;
|
|
9908
|
+
this.errorCategory = "StatementExecutionError";
|
|
9909
|
+
Object.setPrototypeOf(this, StatementExecutionError.prototype);
|
|
9910
|
+
}
|
|
9911
|
+
};
|
|
9912
|
+
/**
|
|
9913
|
+
* We throw this error when a throw statement is executed
|
|
9914
|
+
*/
|
|
9915
|
+
var ThrowStatementError = class ThrowStatementError extends EngineError {
|
|
9916
|
+
constructor(errorObject) {
|
|
9917
|
+
const message = typeof errorObject === "string" ? errorObject : errorObject?.message || "Error without message";
|
|
9918
|
+
super(message);
|
|
9919
|
+
this.errorObject = errorObject;
|
|
9920
|
+
this.errorCategory = "ThrowStatementError";
|
|
9921
|
+
this.message = message;
|
|
9922
|
+
Object.setPrototypeOf(this, ThrowStatementError.prototype);
|
|
9923
|
+
}
|
|
9924
|
+
};
|
|
9925
|
+
|
|
9926
|
+
//#endregion
|
|
9927
|
+
//#region src/components-core/reportEngineError.ts
|
|
9928
|
+
const appErrors = [];
|
|
9929
|
+
/**
|
|
9930
|
+
* Use this function to report an error
|
|
9931
|
+
* @param error Error or string describing the error to report
|
|
9932
|
+
* @param errorToThrow The error to throw
|
|
9933
|
+
*/
|
|
9934
|
+
function reportEngineError(error, errorToThrow) {
|
|
9935
|
+
if (typeof error === "string") error = new Error(error);
|
|
9936
|
+
let helperMessage = "";
|
|
9937
|
+
let colors = [];
|
|
9938
|
+
if (error instanceof ScriptParseError) {
|
|
9939
|
+
let pos = (error?.position ?? 0) - 1;
|
|
9940
|
+
if (error.source) {
|
|
9941
|
+
while (pos < error.source.length - 1 && error.source[pos] === " ") pos++;
|
|
9942
|
+
helperMessage += `%c${error.message}%c\n\n`;
|
|
9943
|
+
helperMessage += `${error.source.substring(0, pos)}%c${error.source[pos]}%c${error.source.substring(pos + 1) ?? ""}\n\n`;
|
|
9944
|
+
}
|
|
9945
|
+
helperMessage += `%cThe error handler associated with the parsed code did not run.%c`;
|
|
9946
|
+
colors = [
|
|
9947
|
+
"color: red",
|
|
9948
|
+
"color: inherited",
|
|
9949
|
+
"color: red",
|
|
9950
|
+
"color: inherited",
|
|
9951
|
+
"color: orange",
|
|
9952
|
+
"color: inherited"
|
|
9953
|
+
];
|
|
9954
|
+
} else if (error instanceof StatementExecutionError) {
|
|
9955
|
+
helperMessage += `%cError while executing code: ${error.message}%c`;
|
|
9956
|
+
if (error.source) helperMessage += `\n\n${error.source}`;
|
|
9957
|
+
colors = ["color: red", "color: inherited"];
|
|
9958
|
+
} else if (error instanceof ThrowStatementError) {
|
|
9959
|
+
helperMessage += `A 'throw' statement executed:\n\n%c${error.message}%c\n\n${error.errorObject}`;
|
|
9960
|
+
colors = ["color: red", "color: inherited"];
|
|
9961
|
+
}
|
|
9962
|
+
if (helperMessage) console.error(helperMessage, ...colors);
|
|
9963
|
+
appErrors.push({
|
|
9964
|
+
error,
|
|
9965
|
+
helperMessage,
|
|
9966
|
+
colors
|
|
9967
|
+
});
|
|
9968
|
+
throw errorToThrow ?? error;
|
|
9969
|
+
}
|
|
9970
|
+
|
|
9971
|
+
//#endregion
|
|
9972
|
+
//#region src/components-core/script-runner/process-statement-sync.ts
|
|
9973
|
+
const SYNC_EVAL_TIMEOUT = 1e3;
|
|
9974
|
+
function processStatementQueue(statements, evalContext, thread) {
|
|
9975
|
+
if (!thread) thread = ensureMainThread(evalContext);
|
|
9976
|
+
hoistFunctionDeclarations(thread, statements);
|
|
9977
|
+
evalContext.startTick = (/* @__PURE__ */ new Date()).valueOf();
|
|
9978
|
+
const queue = new StatementQueue();
|
|
9979
|
+
queue.push(mapStatementsToQueueItems(toStatementItems(statements)));
|
|
9980
|
+
const diagInfo = {
|
|
9981
|
+
processedStatements: 0,
|
|
9982
|
+
maxQueueLength: queue.length,
|
|
9983
|
+
unshiftedItems: 0,
|
|
9984
|
+
clearToLabels: 0,
|
|
9985
|
+
maxBlocks: 0,
|
|
9986
|
+
maxLoops: 0
|
|
9987
|
+
};
|
|
9988
|
+
while (queue.length > 0) {
|
|
9989
|
+
if (evalContext.startTick !== void 0 && (/* @__PURE__ */ new Date()).valueOf() - evalContext.startTick > SYNC_EVAL_TIMEOUT) throw new Error(`Sync evaluation timeout exceeded ${SYNC_EVAL_TIMEOUT} milliseconds`);
|
|
9990
|
+
const queueItem = queue.dequeue();
|
|
9991
|
+
thread.breakLabelValue = queue.length > 0 ? queue.peek().label : -1;
|
|
9992
|
+
let outcome;
|
|
9993
|
+
try {
|
|
9994
|
+
evalContext?.onStatementStarted?.(evalContext, queueItem.statement);
|
|
9995
|
+
outcome = processStatement(queueItem.statement, queueItem.execInfo ?? {}, evalContext, thread);
|
|
9996
|
+
} catch (err$1) {
|
|
9997
|
+
if (thread.tryBlocks && thread.tryBlocks.length > 0) {
|
|
9998
|
+
const tryScope = thread.tryBlocks[thread.tryBlocks.length - 1];
|
|
9999
|
+
tryScope.errorToThrow = err$1;
|
|
10000
|
+
tryScope.errorSource = tryScope.processingPhase;
|
|
10001
|
+
tryScope.processingPhase = "error";
|
|
10002
|
+
outcome = { clearToLabel: tryScope.tryLabel };
|
|
10003
|
+
} else if (err$1 instanceof ThrowStatementError) reportEngineError(err$1);
|
|
10004
|
+
else reportEngineError(new StatementExecutionError(err$1), err$1);
|
|
10005
|
+
}
|
|
10006
|
+
if (outcome) {
|
|
10007
|
+
if (outcome.toUnshift) {
|
|
10008
|
+
queue.unshift(outcome.toUnshift);
|
|
10009
|
+
diagInfo.unshiftedItems += outcome.toUnshift.length;
|
|
10010
|
+
}
|
|
10011
|
+
if (outcome.clearToLabel !== void 0) {
|
|
10012
|
+
queue.clearToLabel(outcome.clearToLabel);
|
|
10013
|
+
diagInfo.clearToLabels++;
|
|
10014
|
+
}
|
|
10015
|
+
}
|
|
10016
|
+
evalContext?.onStatementCompleted?.(evalContext, queueItem.statement);
|
|
10017
|
+
if (queue.length > diagInfo.maxQueueLength) diagInfo.maxQueueLength = queue.length;
|
|
10018
|
+
if (thread.blocks && thread.blocks.length > diagInfo.maxBlocks) diagInfo.maxBlocks = thread.blocks.length;
|
|
10019
|
+
if (thread.loops && thread.loops.length > diagInfo.maxLoops) diagInfo.maxLoops = thread.loops.length;
|
|
10020
|
+
diagInfo.processedStatements++;
|
|
10021
|
+
}
|
|
10022
|
+
return diagInfo;
|
|
10023
|
+
}
|
|
10024
|
+
/**
|
|
10025
|
+
* Process the specified statement synchronously
|
|
10026
|
+
* @param statement Statement to process
|
|
10027
|
+
* @param evalContext Evaluation context used for processing
|
|
10028
|
+
* @param thread Logical thread to use for statement processing
|
|
10029
|
+
* @returns Items to put back into the queue of statements
|
|
10030
|
+
*/
|
|
10031
|
+
function processStatement(statement, execInfo, evalContext, thread) {
|
|
10032
|
+
let toUnshift = [];
|
|
10033
|
+
let clearToLabel;
|
|
10034
|
+
switch (statement.type) {
|
|
10035
|
+
case T_ASYNC_FUNCTION_DECLARATION: throw new Error("XMLUI does not support async function declarations.");
|
|
10036
|
+
case T_FUNCTION_DECLARATION: break;
|
|
10037
|
+
case T_VAR_STATEMENT:
|
|
10038
|
+
if (thread !== evalContext.mainThread) throw new Error("'var' declarations are not allowed within functions");
|
|
10039
|
+
break;
|
|
10040
|
+
case T_EMPTY_STATEMENT: break;
|
|
10041
|
+
case T_BLOCK_STATEMENT:
|
|
10042
|
+
if (statement.stmts.length === 0) break;
|
|
10043
|
+
thread.blocks ??= [];
|
|
10044
|
+
thread.blocks.push({ vars: {} });
|
|
10045
|
+
hoistFunctionDeclarations(thread, statement.stmts);
|
|
10046
|
+
toUnshift = mapStatementsToQueueItems([...toStatementItems(statement.stmts), closing()]);
|
|
10047
|
+
break;
|
|
10048
|
+
case T_EXPRESSION_STATEMENT:
|
|
10049
|
+
const statementValue = evalBinding(statement.expr, evalContext, thread);
|
|
10050
|
+
if (thread.blocks && thread.blocks.length !== 0) thread.blocks[thread.blocks.length - 1].returnValue = statementValue;
|
|
10051
|
+
break;
|
|
10052
|
+
case T_ARROW_EXPRESSION_STATEMENT:
|
|
10053
|
+
const arrowFuncValue = executeArrowExpressionSync(statement.expr, evalContext, thread, ...evalContext.eventArgs ?? []);
|
|
10054
|
+
if (thread.blocks && thread.blocks.length !== 0) thread.blocks[thread.blocks.length - 1].returnValue = arrowFuncValue;
|
|
10055
|
+
break;
|
|
10056
|
+
case T_LET_STATEMENT: {
|
|
10057
|
+
const block = innermostBlockScope(thread);
|
|
10058
|
+
if (!block) throw new Error("Missing block scope");
|
|
10059
|
+
processDeclarations(block, evalContext, thread, statement.decls);
|
|
10060
|
+
break;
|
|
10061
|
+
}
|
|
10062
|
+
case T_CONST_STATEMENT: {
|
|
10063
|
+
const block = innermostBlockScope(thread);
|
|
10064
|
+
if (!block) throw new Error("Missing block scope");
|
|
10065
|
+
processDeclarations(block, evalContext, thread, statement.decls, true);
|
|
10066
|
+
break;
|
|
10067
|
+
}
|
|
10068
|
+
case T_IF_STATEMENT:
|
|
10069
|
+
if (!!evalBinding(statement.cond, evalContext, thread)) toUnshift = mapToItem(statement.thenB);
|
|
10070
|
+
else if (statement.elseB) toUnshift = mapToItem(statement.elseB);
|
|
10071
|
+
break;
|
|
10072
|
+
case T_RETURN_STATEMENT:
|
|
10073
|
+
if (innermostBlockScope(thread) === void 0) throw new Error("Return requires a block scope");
|
|
10074
|
+
thread.returnValue = statement.expr ? evalBinding(statement.expr, evalContext, thread) : void 0;
|
|
10075
|
+
if ((thread.tryBlocks ?? []).length > 0) {
|
|
10076
|
+
for (let i = 0; i < thread.tryBlocks.length; i++) thread.tryBlocks[i].exitType = "return";
|
|
10077
|
+
const tryScope = innermostTryScope(thread);
|
|
10078
|
+
if (tryScope.processingPhase !== "postFinally") thread.blocks.pop();
|
|
10079
|
+
clearToLabel = tryScope.tryLabel;
|
|
10080
|
+
} else clearToLabel = -1;
|
|
10081
|
+
break;
|
|
10082
|
+
case T_WHILE_STATEMENT: {
|
|
10083
|
+
let loopScope = execInfo.guard ? innermostLoopScope(thread) : createLoopScope(thread);
|
|
10084
|
+
if (!!evalBinding(statement.cond, evalContext, thread)) toUnshift = provideLoopBody(loopScope, statement, thread.breakLabelValue);
|
|
10085
|
+
else releaseLoopScope(thread);
|
|
10086
|
+
break;
|
|
10087
|
+
}
|
|
10088
|
+
case T_DO_WHILE_STATEMENT:
|
|
10089
|
+
if (!execInfo.guard) {
|
|
10090
|
+
toUnshift = provideLoopBody(createLoopScope(thread), statement, thread.breakLabelValue);
|
|
10091
|
+
break;
|
|
10092
|
+
}
|
|
10093
|
+
if (!!evalBinding(statement.cond, evalContext, thread)) toUnshift = provideLoopBody(innermostLoopScope(thread), statement, thread.breakLabelValue);
|
|
10094
|
+
else releaseLoopScope(thread);
|
|
10095
|
+
break;
|
|
10096
|
+
case T_CONTINUE_STATEMENT: {
|
|
10097
|
+
if (!thread.loops || thread.loops.length === 0) throw new Error("Missing loop scope");
|
|
10098
|
+
let loopScope;
|
|
10099
|
+
while (thread.loops.length > 0) {
|
|
10100
|
+
loopScope = innermostLoopScope(thread);
|
|
10101
|
+
if (!loopScope.isSwitch) break;
|
|
10102
|
+
thread.loops.pop();
|
|
10103
|
+
}
|
|
10104
|
+
if (!loopScope) throw new Error("Missing loop scope");
|
|
10105
|
+
if (loopScope.tryBlockDepth >= 0 && loopScope.tryBlockDepth < (thread.tryBlocks ?? []).length) {
|
|
10106
|
+
for (let i = loopScope.tryBlockDepth; i < thread.tryBlocks.length; i++) thread.tryBlocks[loopScope.tryBlockDepth].exitType = "continue";
|
|
10107
|
+
clearToLabel = innermostTryScope(thread).tryLabel;
|
|
10108
|
+
} else {
|
|
10109
|
+
clearToLabel = loopScope.continueLabel;
|
|
10110
|
+
releaseLoopScope(thread, false);
|
|
10111
|
+
}
|
|
10112
|
+
break;
|
|
10113
|
+
}
|
|
10114
|
+
case T_BREAK_STATEMENT: {
|
|
10115
|
+
const loopScope = innermostLoopScope(thread);
|
|
10116
|
+
if (loopScope === void 0) throw new Error("Missing loop scope");
|
|
10117
|
+
if (!!loopScope.isSwitch) {
|
|
10118
|
+
clearToLabel = loopScope.breakLabel;
|
|
10119
|
+
break;
|
|
10120
|
+
}
|
|
10121
|
+
if (loopScope.tryBlockDepth >= 0 && loopScope.tryBlockDepth < (thread.tryBlocks ?? []).length) {
|
|
10122
|
+
for (let i = loopScope.tryBlockDepth; i < thread.tryBlocks.length; i++) thread.tryBlocks[loopScope.tryBlockDepth].exitType = "break";
|
|
10123
|
+
clearToLabel = innermostTryScope(thread).tryLabel;
|
|
10124
|
+
} else {
|
|
10125
|
+
clearToLabel = loopScope.breakLabel;
|
|
10126
|
+
releaseLoopScope(thread);
|
|
10127
|
+
}
|
|
10128
|
+
break;
|
|
10129
|
+
}
|
|
10130
|
+
case T_FOR_STATEMENT:
|
|
10131
|
+
if (!execInfo.guard) {
|
|
10132
|
+
createLoopScope(thread, 1);
|
|
10133
|
+
thread.blocks ??= [];
|
|
10134
|
+
thread.blocks.push({ vars: {} });
|
|
10135
|
+
const guardStatement = guard(statement);
|
|
10136
|
+
if (statement.init) toUnshift = mapStatementsToQueueItems([{ statement: statement.init }, guardStatement]);
|
|
10137
|
+
else toUnshift = mapStatementsToQueueItems([guardStatement]);
|
|
10138
|
+
} else if (!statement.cond || evalBinding(statement.cond, evalContext, thread)) {
|
|
10139
|
+
const loopScope = innermostLoopScope(thread);
|
|
10140
|
+
if (statement.upd) {
|
|
10141
|
+
const updateStmt = { statement: {
|
|
10142
|
+
type: T_EXPRESSION_STATEMENT,
|
|
10143
|
+
nodeId: createXmlUiTreeNodeId(),
|
|
10144
|
+
expr: statement.upd
|
|
10145
|
+
} };
|
|
10146
|
+
toUnshift = mapStatementsToQueueItems([
|
|
10147
|
+
{ statement: statement.body },
|
|
10148
|
+
updateStmt,
|
|
10149
|
+
{
|
|
10150
|
+
statement,
|
|
10151
|
+
execInfo
|
|
10152
|
+
}
|
|
10153
|
+
]);
|
|
10154
|
+
} else toUnshift = mapStatementsToQueueItems([{ statement: statement.body }, {
|
|
10155
|
+
statement,
|
|
10156
|
+
execInfo
|
|
10157
|
+
}]);
|
|
10158
|
+
loopScope.breakLabel = thread.breakLabelValue ?? -1;
|
|
10159
|
+
loopScope.continueLabel = toUnshift[1].label;
|
|
10160
|
+
} else releaseLoopScope(thread);
|
|
10161
|
+
break;
|
|
10162
|
+
case T_FOR_IN_STATEMENT:
|
|
10163
|
+
if (!execInfo.guard) {
|
|
10164
|
+
const keyedObject = evalBinding(statement.expr, evalContext, thread);
|
|
10165
|
+
if (keyedObject == void 0) break;
|
|
10166
|
+
createLoopScope(thread, 1);
|
|
10167
|
+
thread.blocks ??= [];
|
|
10168
|
+
thread.blocks.push({ vars: {} });
|
|
10169
|
+
toUnshift = mapStatementsToQueueItems([{
|
|
10170
|
+
statement,
|
|
10171
|
+
execInfo: {
|
|
10172
|
+
guard: true,
|
|
10173
|
+
keys: Object.keys(keyedObject),
|
|
10174
|
+
keyIndex: 0
|
|
10175
|
+
}
|
|
10176
|
+
}]);
|
|
10177
|
+
} else {
|
|
10178
|
+
if (execInfo.keyIndex === void 0 || execInfo.keys === void 0) throw new Error("Keys information expected in for..in loop");
|
|
10179
|
+
if (execInfo.keyIndex < execInfo.keys.length) {
|
|
10180
|
+
const propValue = execInfo.keys[execInfo.keyIndex++];
|
|
10181
|
+
switch (statement.varB) {
|
|
10182
|
+
case "none":
|
|
10183
|
+
evalBinding({
|
|
10184
|
+
type: T_ASSIGNMENT_EXPRESSION,
|
|
10185
|
+
leftValue: {
|
|
10186
|
+
type: T_IDENTIFIER,
|
|
10187
|
+
name: statement.id.name
|
|
10188
|
+
},
|
|
10189
|
+
op: "=",
|
|
10190
|
+
expr: {
|
|
10191
|
+
type: T_LITERAL,
|
|
10192
|
+
value: propValue
|
|
10193
|
+
}
|
|
10194
|
+
}, evalContext, thread);
|
|
10195
|
+
break;
|
|
10196
|
+
case "const":
|
|
10197
|
+
case "let":
|
|
10198
|
+
{
|
|
10199
|
+
const block = innermostBlockScope(thread);
|
|
10200
|
+
if (!block) throw new Error("Missing block scope");
|
|
10201
|
+
block.vars[statement.id.name] = propValue;
|
|
10202
|
+
if (statement.varB === "const") {
|
|
10203
|
+
block.constVars ??= /* @__PURE__ */ new Set();
|
|
10204
|
+
block.constVars.add(statement.id.name);
|
|
10205
|
+
}
|
|
10206
|
+
}
|
|
10207
|
+
break;
|
|
10208
|
+
}
|
|
10209
|
+
const loopScope = innermostLoopScope(thread);
|
|
10210
|
+
toUnshift = mapStatementsToQueueItems([{ statement: statement.body }, {
|
|
10211
|
+
statement,
|
|
10212
|
+
execInfo
|
|
10213
|
+
}]);
|
|
10214
|
+
loopScope.breakLabel = thread.breakLabelValue ?? -1;
|
|
10215
|
+
loopScope.continueLabel = toUnshift[1].label;
|
|
10216
|
+
} else releaseLoopScope(thread);
|
|
10217
|
+
}
|
|
10218
|
+
break;
|
|
10219
|
+
case T_FOR_OF_STATEMENT:
|
|
10220
|
+
if (!execInfo.guard) {
|
|
10221
|
+
const iteratorObject = evalBinding(statement.expr, evalContext, thread);
|
|
10222
|
+
if (iteratorObject == null || typeof iteratorObject[Symbol.iterator] !== "function") throw new Error("Object in for..of is not iterable");
|
|
10223
|
+
createLoopScope(thread, 1);
|
|
10224
|
+
thread.blocks ??= [];
|
|
10225
|
+
thread.blocks.push({ vars: {} });
|
|
10226
|
+
toUnshift = mapStatementsToQueueItems([{
|
|
10227
|
+
statement,
|
|
10228
|
+
execInfo: {
|
|
10229
|
+
guard: true,
|
|
10230
|
+
iterator: iteratorObject[Symbol.iterator]()
|
|
10231
|
+
}
|
|
10232
|
+
}]);
|
|
10233
|
+
} else {
|
|
10234
|
+
if (execInfo.iterator === void 0) throw new Error("Iterator expected in for..of loop");
|
|
10235
|
+
const nextIteration = execInfo.iterator.next();
|
|
10236
|
+
if (nextIteration.done) {
|
|
10237
|
+
releaseLoopScope(thread);
|
|
10238
|
+
break;
|
|
10239
|
+
}
|
|
10240
|
+
const propValue = nextIteration.value;
|
|
10241
|
+
switch (statement.varB) {
|
|
10242
|
+
case "none":
|
|
10243
|
+
evalBinding({
|
|
10244
|
+
type: T_ASSIGNMENT_EXPRESSION,
|
|
10245
|
+
leftValue: {
|
|
10246
|
+
type: T_IDENTIFIER,
|
|
10247
|
+
name: statement.id.name
|
|
10248
|
+
},
|
|
10249
|
+
op: "=",
|
|
10250
|
+
expr: {
|
|
10251
|
+
type: T_LITERAL,
|
|
10252
|
+
value: propValue
|
|
10253
|
+
}
|
|
10254
|
+
}, evalContext, thread);
|
|
10255
|
+
break;
|
|
10256
|
+
case "const":
|
|
10257
|
+
case "let":
|
|
10258
|
+
{
|
|
10259
|
+
const block = innermostBlockScope(thread);
|
|
10260
|
+
if (!block) throw new Error("Missing block scope");
|
|
10261
|
+
block.vars[statement.id.name] = propValue;
|
|
10262
|
+
if (statement.varB === "const") {
|
|
10263
|
+
block.constVars ??= /* @__PURE__ */ new Set();
|
|
10264
|
+
block.constVars.add(statement.id.name);
|
|
10265
|
+
}
|
|
10266
|
+
}
|
|
10267
|
+
break;
|
|
10268
|
+
}
|
|
10269
|
+
const loopScope = innermostLoopScope(thread);
|
|
10270
|
+
toUnshift = mapStatementsToQueueItems([{ statement: statement.body }, {
|
|
10271
|
+
statement,
|
|
10272
|
+
execInfo
|
|
10273
|
+
}]);
|
|
10274
|
+
loopScope.breakLabel = thread.breakLabelValue ?? -1;
|
|
10275
|
+
loopScope.continueLabel = toUnshift[1].label;
|
|
10276
|
+
}
|
|
10277
|
+
break;
|
|
10278
|
+
case T_THROW_STATEMENT: throw new ThrowStatementError(evalBinding(statement.expr, evalContext, thread));
|
|
10279
|
+
case T_TRY_STATEMENT: {
|
|
10280
|
+
if (!execInfo.guard) {
|
|
10281
|
+
toUnshift = provideTryBody(thread, createTryScope(thread, statement));
|
|
10282
|
+
break;
|
|
10283
|
+
}
|
|
10284
|
+
const tryScope = innermostTryScope(thread);
|
|
10285
|
+
switch (tryScope.processingPhase) {
|
|
10286
|
+
case "error":
|
|
10287
|
+
switch (tryScope.errorSource) {
|
|
10288
|
+
case "try":
|
|
10289
|
+
thread.blocks.pop();
|
|
10290
|
+
if (statement.catchB) {
|
|
10291
|
+
if (tryScope.statement.catchV) {
|
|
10292
|
+
const block = innermostBlockScope(thread);
|
|
10293
|
+
block.vars[tryScope.statement.catchV.name] = tryScope.errorToThrow instanceof ThrowStatementError ? tryScope.errorToThrow.errorObject : tryScope.errorToThrow;
|
|
10294
|
+
}
|
|
10295
|
+
delete tryScope.errorToThrow;
|
|
10296
|
+
tryScope.processingPhase = "catch";
|
|
10297
|
+
toUnshift = provideCatchBody(thread, tryScope);
|
|
10298
|
+
} else if (tryScope.statement.finallyB) {
|
|
10299
|
+
tryScope.processingPhase = "finally";
|
|
10300
|
+
toUnshift = provideFinallyBody(thread, tryScope);
|
|
10301
|
+
}
|
|
10302
|
+
break;
|
|
10303
|
+
case "catch":
|
|
10304
|
+
thread.blocks.pop();
|
|
10305
|
+
tryScope.processingPhase = "finally";
|
|
10306
|
+
toUnshift = provideFinallyBody(thread, tryScope);
|
|
10307
|
+
break;
|
|
10308
|
+
case "finally":
|
|
10309
|
+
thread.blocks.pop();
|
|
10310
|
+
tryScope.processingPhase = "postFinally";
|
|
10311
|
+
toUnshift = provideFinallyErrorBody(tryScope);
|
|
10312
|
+
break;
|
|
10313
|
+
}
|
|
10314
|
+
break;
|
|
10315
|
+
case "try":
|
|
10316
|
+
tryScope.processingPhase = "finally";
|
|
10317
|
+
if (statement.finallyB) toUnshift = provideFinallyBody(thread, tryScope);
|
|
10318
|
+
else toUnshift = provideFinallyErrorBody(tryScope);
|
|
10319
|
+
break;
|
|
10320
|
+
case "catch":
|
|
10321
|
+
tryScope.processingPhase = "finally";
|
|
10322
|
+
if (statement.finallyB) toUnshift = provideFinallyBody(thread, tryScope);
|
|
10323
|
+
else toUnshift = provideFinallyErrorBody(tryScope);
|
|
10324
|
+
break;
|
|
10325
|
+
case "finally":
|
|
10326
|
+
tryScope.processingPhase = "postFinally";
|
|
10327
|
+
toUnshift = provideFinallyErrorBody(tryScope);
|
|
10328
|
+
break;
|
|
10329
|
+
case "postFinally":
|
|
10330
|
+
const innermostTry = thread.tryBlocks.pop();
|
|
10331
|
+
switch (innermostTry.exitType) {
|
|
10332
|
+
case "break": {
|
|
10333
|
+
const loopScope = innermostLoopScope(thread);
|
|
10334
|
+
if (loopScope === void 0) throw new Error("Missing loop scope");
|
|
10335
|
+
releaseLoopScope(thread);
|
|
10336
|
+
clearToLabel = loopScope.breakLabel;
|
|
10337
|
+
break;
|
|
10338
|
+
}
|
|
10339
|
+
case "continue": {
|
|
10340
|
+
const loopScope = innermostLoopScope(thread);
|
|
10341
|
+
if (loopScope === void 0) throw new Error("Missing loop scope");
|
|
10342
|
+
clearToLabel = loopScope.continueLabel;
|
|
10343
|
+
releaseLoopScope(thread, false);
|
|
10344
|
+
break;
|
|
10345
|
+
}
|
|
10346
|
+
case "return":
|
|
10347
|
+
if (thread.tryBlocks && thread.tryBlocks.length > 0) {
|
|
10348
|
+
if (thread.blocks && thread.blocks.length > 1) thread.blocks.pop();
|
|
10349
|
+
clearToLabel = thread.tryBlocks[thread.tryBlocks.length - 1].tryLabel;
|
|
10350
|
+
} else clearToLabel = -1;
|
|
10351
|
+
break;
|
|
10352
|
+
}
|
|
10353
|
+
if (innermostTry.errorToThrow) throw innermostTry.errorToThrow;
|
|
10354
|
+
break;
|
|
10355
|
+
}
|
|
10356
|
+
break;
|
|
10357
|
+
}
|
|
10358
|
+
case T_SWITCH_STATEMENT:
|
|
10359
|
+
if (execInfo.guard) releaseLoopScope(thread);
|
|
10360
|
+
else {
|
|
10361
|
+
let loopScope = createLoopScope(thread);
|
|
10362
|
+
loopScope.isSwitch = true;
|
|
10363
|
+
thread.blocks.push({ vars: {} });
|
|
10364
|
+
const switchValue = evalBinding(statement.expr, evalContext, thread);
|
|
10365
|
+
let matchingIndex = -1;
|
|
10366
|
+
for (let i = 0; i < statement.cases.length; i++) {
|
|
10367
|
+
const currentCase = statement.cases[i];
|
|
10368
|
+
if (currentCase.caseE === void 0) {
|
|
10369
|
+
matchingIndex = i;
|
|
10370
|
+
break;
|
|
10371
|
+
}
|
|
10372
|
+
if (evalBinding(currentCase.caseE, evalContext, thread) === switchValue) {
|
|
10373
|
+
matchingIndex = i;
|
|
10374
|
+
break;
|
|
10375
|
+
}
|
|
10376
|
+
}
|
|
10377
|
+
const statementFlow = [];
|
|
10378
|
+
if (matchingIndex >= 0) for (let i = matchingIndex; i < statement.cases.length; i++) statementFlow.push(...statement.cases[i].stmts);
|
|
10379
|
+
toUnshift = mapStatementsToQueueItems([...toStatementItems(statementFlow), guard(statement)]);
|
|
10380
|
+
loopScope.breakLabel = toUnshift[toUnshift.length - 1].label;
|
|
10381
|
+
}
|
|
10382
|
+
break;
|
|
10383
|
+
}
|
|
10384
|
+
if (execInfo.removeBlockScope) {
|
|
10385
|
+
if (thread.blocks && thread.blocks.length > 0) thread.blocks.pop();
|
|
10386
|
+
}
|
|
10387
|
+
return {
|
|
10388
|
+
toUnshift,
|
|
10389
|
+
clearToLabel
|
|
10390
|
+
};
|
|
10391
|
+
}
|
|
10392
|
+
function processDeclarations(block, evalContext, thread, declarations, addConst = false, useValue = false, baseValue = void 0) {
|
|
10393
|
+
for (let i = 0; i < declarations.length; i++) {
|
|
10394
|
+
let value;
|
|
10395
|
+
const decl = declarations[i];
|
|
10396
|
+
if (useValue) value = baseValue;
|
|
10397
|
+
else if (decl.expr) value = evalBinding(decl.expr, evalContext, thread);
|
|
10398
|
+
visitDeclaration(block, decl, value, addConst);
|
|
10399
|
+
}
|
|
10400
|
+
function visitDeclaration(block$1, decl, baseValue$1, addConst$1) {
|
|
10401
|
+
if (decl.id) visitIdDeclaration(block$1, decl.id, baseValue$1, addConst$1);
|
|
10402
|
+
else if (decl.aDestr) visitArrayDestruct(block$1, decl.aDestr, baseValue$1, addConst$1);
|
|
10403
|
+
else if (decl.oDestr) visitObjectDestruct(block$1, decl.oDestr, baseValue$1, addConst$1);
|
|
10404
|
+
else throw new Error("Unknown declaration specifier");
|
|
10405
|
+
}
|
|
10406
|
+
function visitIdDeclaration(block$1, id, baseValue$1, addConst$1) {
|
|
10407
|
+
if (block$1.vars[id]) throw new Error(`Variable ${id} is already declared in the current scope.`);
|
|
10408
|
+
block$1.vars[id] = baseValue$1;
|
|
10409
|
+
if (addConst$1) {
|
|
10410
|
+
block$1.constVars ??= /* @__PURE__ */ new Set();
|
|
10411
|
+
block$1.constVars.add(id);
|
|
10412
|
+
}
|
|
10413
|
+
}
|
|
10414
|
+
function visitArrayDestruct(block$1, arrayD, baseValue$1, addConst$1) {
|
|
10415
|
+
for (let i = 0; i < arrayD.length; i++) {
|
|
10416
|
+
const arrDecl = arrayD[i];
|
|
10417
|
+
const value = baseValue$1?.[i];
|
|
10418
|
+
if (arrDecl.id) visitIdDeclaration(block$1, arrDecl.id, value, addConst$1);
|
|
10419
|
+
else if (arrDecl.aDestr) visitArrayDestruct(block$1, arrDecl.aDestr, value, addConst$1);
|
|
10420
|
+
else if (arrDecl.oDestr) visitObjectDestruct(block$1, arrDecl.oDestr, value, addConst$1);
|
|
10421
|
+
}
|
|
10422
|
+
}
|
|
10423
|
+
function visitObjectDestruct(block$1, objectD, baseValue$1, addConst$1) {
|
|
10424
|
+
for (let i = 0; i < objectD.length; i++) {
|
|
10425
|
+
const objDecl = objectD[i];
|
|
10426
|
+
const value = baseValue$1?.[objDecl.id];
|
|
10427
|
+
if (objDecl.aDestr) visitArrayDestruct(block$1, objDecl.aDestr, value, addConst$1);
|
|
10428
|
+
else if (objDecl.oDestr) visitObjectDestruct(block$1, objDecl.oDestr, value, addConst$1);
|
|
10429
|
+
else visitIdDeclaration(block$1, objDecl.alias ?? objDecl.id, value, addConst$1);
|
|
10430
|
+
}
|
|
10431
|
+
}
|
|
10432
|
+
}
|
|
10433
|
+
|
|
10434
|
+
//#endregion
|
|
10435
|
+
//#region src/components-core/script-runner/eval-tree-sync.ts
|
|
10436
|
+
/**
|
|
10437
|
+
* Evaluates a binding represented by the specified expression
|
|
10438
|
+
* @param expr Expression to evaluate
|
|
10439
|
+
* @param evalContext Evaluation context to use
|
|
10440
|
+
* @param thread The logical thread to use for evaluation
|
|
10441
|
+
*/
|
|
10442
|
+
function evalBinding(expr, evalContext, thread) {
|
|
10443
|
+
const thisStack = [];
|
|
10444
|
+
ensureMainThread(evalContext);
|
|
10445
|
+
thread ??= evalContext.mainThread;
|
|
10446
|
+
return evalBindingExpressionTree(thisStack, expr, evalContext, thread ?? evalContext.mainThread);
|
|
10447
|
+
}
|
|
10448
|
+
/**
|
|
10449
|
+
* Executes the specified arrow function
|
|
10450
|
+
* @param expr Arrow function expression to run
|
|
10451
|
+
* @param evalContext Evaluation context to use
|
|
10452
|
+
* @param thread The logical thread to use for evaluation
|
|
10453
|
+
* @param args Arguments of the arrow function to execute
|
|
10454
|
+
*/
|
|
10455
|
+
function executeArrowExpressionSync(expr, evalContext, thread, ...args) {
|
|
10456
|
+
if (expr.type !== T_ARROW_EXPRESSION) throw new Error("executeArrowExpression expects an 'ArrowExpression' object.");
|
|
10457
|
+
return createArrowFunction(evalBindingExpressionTree, expr)(expr.args, evalContext, thread ?? evalContext.mainThread, ...args);
|
|
10458
|
+
}
|
|
10459
|
+
/**
|
|
10460
|
+
* Evaluates the specified binding expression tree and retrieves the evaluated value
|
|
10461
|
+
* @param expr Binding tree expression
|
|
10462
|
+
* @param thisStack Stack of "this" object to use with function calls
|
|
10463
|
+
* @param evalContext Evaluation context
|
|
10464
|
+
* @param thread The logical thread to use for evaluation
|
|
10465
|
+
* This code uses the JavaScript semantics and errors when evaluating the code.
|
|
10466
|
+
* We use `thisStack` to keep track of the partial results of the evaluation tree so that we can set
|
|
10467
|
+
* the real `this` context when invoking a function.
|
|
10468
|
+
*/
|
|
10469
|
+
function evalBindingExpressionTree(thisStack, expr, evalContext, thread) {
|
|
10470
|
+
if (!evalContext.options) evalContext.options = { defaultToOptionalMemberAccess: true };
|
|
10471
|
+
const evaluator = evalBindingExpressionTree;
|
|
10472
|
+
switch (expr.type) {
|
|
10473
|
+
case T_TEMPLATE_LITERAL_EXPRESSION: return evalTemplateLiteral(evaluator, thisStack, expr, evalContext, thread);
|
|
10474
|
+
case T_LITERAL: return evalLiteral(thisStack, expr, thread);
|
|
10475
|
+
case T_IDENTIFIER: return evalIdentifier(thisStack, expr, evalContext, thread);
|
|
10476
|
+
case T_MEMBER_ACCESS_EXPRESSION: return evalMemberAccess(evaluator, thisStack, expr, evalContext, thread);
|
|
10477
|
+
case T_CALCULATED_MEMBER_ACCESS_EXPRESSION: return evalCalculatedMemberAccess(evaluator, thisStack, expr, evalContext, thread);
|
|
10478
|
+
case T_SEQUENCE_EXPRESSION: return evalSequence(evaluator, thisStack, expr, evalContext, thread);
|
|
10479
|
+
case T_ARRAY_LITERAL: return evalArrayLiteral(evaluator, thisStack, expr, evalContext, thread);
|
|
10480
|
+
case T_OBJECT_LITERAL: return evalObjectLiteral(evaluator, thisStack, expr, evalContext, thread);
|
|
10481
|
+
case T_UNARY_EXPRESSION: return evalUnary(evaluator, thisStack, expr, evalContext, thread);
|
|
10482
|
+
case T_BINARY_EXPRESSION: return evalBinary(evaluator, thisStack, expr, evalContext, thread);
|
|
10483
|
+
case T_CONDITIONAL_EXPRESSION: return evalConditional(evaluator, thisStack, expr, evalContext, thread);
|
|
10484
|
+
case T_ASSIGNMENT_EXPRESSION: return evalAssignment(evaluator, thisStack, expr, evalContext, thread);
|
|
10485
|
+
case T_PREFIX_OP_EXPRESSION:
|
|
10486
|
+
case T_POSTFIX_OP_EXPRESSION: return evalPreOrPost(evaluator, thisStack, expr, evalContext, thread);
|
|
10487
|
+
case T_FUNCTION_INVOCATION_EXPRESSION:
|
|
10488
|
+
const funcResult = evalFunctionInvocation(evaluator, thisStack, expr, evalContext, thread);
|
|
10489
|
+
if (isPromise(funcResult)) throw new Error("Promises (async function calls) are not allowed in binding expressions.");
|
|
10490
|
+
return funcResult;
|
|
10491
|
+
case T_ARROW_EXPRESSION: return evalArrow(thisStack, expr, thread);
|
|
10492
|
+
case T_SPREAD_EXPRESSION: throw new Error("Cannot use spread expression (...) with the current intermediate value.");
|
|
10493
|
+
case T_AWAIT_EXPRESSION: throw new Error("XMLUI does not support the await operator.");
|
|
10494
|
+
case T_NEW_EXPRESSION: return evalNewExpression(evaluator, thisStack, expr, evalContext, thread);
|
|
10495
|
+
default: throw new Error(`Unknown expression tree node: ${expr.type}`);
|
|
10496
|
+
}
|
|
10497
|
+
}
|
|
10498
|
+
function evalTemplateLiteral(evaluator, thisStack, expr, evalContext, thread) {
|
|
10499
|
+
const value = evalTemplateLiteralCore(expr.segments.map((s) => {
|
|
10500
|
+
const evaledValue = evaluator(thisStack, s, evalContext, thread);
|
|
10501
|
+
thisStack.pop();
|
|
10502
|
+
return evaledValue;
|
|
10503
|
+
}));
|
|
10504
|
+
setExprValue(expr, { value }, thread);
|
|
10505
|
+
thisStack.push(value);
|
|
10506
|
+
return value;
|
|
10507
|
+
}
|
|
10508
|
+
function evalMemberAccess(evaluator, thisStack, expr, evalContext, thread) {
|
|
10509
|
+
evaluator(thisStack, expr.obj, evalContext, thread);
|
|
10510
|
+
return evalMemberAccessCore(thisStack, expr, evalContext, thread);
|
|
10511
|
+
}
|
|
10512
|
+
function evalCalculatedMemberAccess(evaluator, thisStack, expr, evalContext, thread) {
|
|
10513
|
+
evaluator(thisStack, expr.obj, evalContext, thread);
|
|
10514
|
+
evaluator(thisStack, expr.member, evalContext, thread);
|
|
10515
|
+
thisStack.pop();
|
|
10516
|
+
return evalCalculatedMemberAccessCore(thisStack, expr, evalContext, thread);
|
|
10517
|
+
}
|
|
10518
|
+
function evalSequence(evaluator, thisStack, expr, evalContext, thread) {
|
|
10519
|
+
if (!expr.exprs || expr.exprs.length === 0) throw new Error(`Missing expression sequence`);
|
|
10520
|
+
const result = expr.exprs.map((e) => {
|
|
10521
|
+
const value = evaluator(thisStack, e, evalContext, thread);
|
|
10522
|
+
setExprValue(e, { value }, thread);
|
|
10523
|
+
thisStack.pop();
|
|
10524
|
+
return value;
|
|
10525
|
+
});
|
|
10526
|
+
const lastObj = result[result.length - 1];
|
|
10527
|
+
thisStack.push(lastObj);
|
|
10528
|
+
return lastObj;
|
|
10529
|
+
}
|
|
10530
|
+
function evalArrayLiteral(evaluator, thisStack, expr, evalContext, thread) {
|
|
10531
|
+
const value = [];
|
|
10532
|
+
for (const item of expr.items) if (item.type === T_SPREAD_EXPRESSION) {
|
|
10533
|
+
const spreadArray = evaluator(thisStack, item.expr, evalContext, thread);
|
|
10534
|
+
thisStack.pop();
|
|
10535
|
+
if (!Array.isArray(spreadArray)) throw new Error("Spread operator within an array literal expects an array operand.");
|
|
10536
|
+
value.push(...spreadArray);
|
|
10537
|
+
} else {
|
|
10538
|
+
value.push(evaluator(thisStack, item, evalContext, thread));
|
|
10539
|
+
thisStack.pop();
|
|
10540
|
+
thisStack.push(value);
|
|
10541
|
+
}
|
|
10542
|
+
setExprValue(expr, { value }, thread);
|
|
10543
|
+
thisStack.push(value);
|
|
10544
|
+
return value;
|
|
10545
|
+
}
|
|
10546
|
+
function evalObjectLiteral(evaluator, thisStack, expr, evalContext, thread) {
|
|
10547
|
+
const objectHash = {};
|
|
10548
|
+
for (const prop of expr.props) {
|
|
10549
|
+
if (!Array.isArray(prop)) {
|
|
10550
|
+
const spreadItems = evaluator(thisStack, prop.expr, evalContext, thread);
|
|
10551
|
+
thisStack.pop();
|
|
10552
|
+
if (Array.isArray(spreadItems)) for (let i = 0; i < spreadItems.length; i++) objectHash[i] = spreadItems[i];
|
|
10553
|
+
else if (typeof spreadItems === "object") for (const [key$1, value] of Object.entries(spreadItems)) objectHash[key$1] = value;
|
|
10554
|
+
continue;
|
|
10555
|
+
}
|
|
10556
|
+
let key;
|
|
10557
|
+
switch (prop[0].type) {
|
|
10558
|
+
case T_LITERAL:
|
|
10559
|
+
key = prop[0].value;
|
|
10560
|
+
break;
|
|
10561
|
+
case T_IDENTIFIER:
|
|
10562
|
+
key = prop[0].name;
|
|
10563
|
+
break;
|
|
10564
|
+
default:
|
|
10565
|
+
key = evaluator(thisStack, prop[0], evalContext, thread);
|
|
10566
|
+
thisStack.pop();
|
|
10567
|
+
break;
|
|
10568
|
+
}
|
|
10569
|
+
objectHash[key] = evaluator(thisStack, prop[1], evalContext, thread);
|
|
10570
|
+
thisStack.pop();
|
|
10571
|
+
}
|
|
10572
|
+
setExprValue(expr, { value: objectHash }, thread);
|
|
10573
|
+
thisStack.push(objectHash);
|
|
10574
|
+
return objectHash;
|
|
10575
|
+
}
|
|
10576
|
+
function evalUnary(evaluator, thisStack, expr, evalContext, thread) {
|
|
10577
|
+
evaluator(thisStack, expr.expr, evalContext, thread);
|
|
10578
|
+
thisStack.pop();
|
|
10579
|
+
return evalUnaryCore(expr, thisStack, evalContext, thread);
|
|
10580
|
+
}
|
|
10581
|
+
function evalBinary(evaluator, thisStack, expr, evalContext, thread) {
|
|
10582
|
+
evaluator(thisStack, expr.left, evalContext, thread);
|
|
10583
|
+
thisStack.pop();
|
|
10584
|
+
const l = getExprValue(expr.left, thread)?.value;
|
|
10585
|
+
if (expr.op === "&&" && !l) {
|
|
10586
|
+
setExprValue(expr, { value: l }, thread);
|
|
10587
|
+
thisStack.push(l);
|
|
10588
|
+
return l;
|
|
10589
|
+
}
|
|
10590
|
+
if (expr.op === "||" && l) {
|
|
10591
|
+
setExprValue(expr, { value: l }, thread);
|
|
10592
|
+
thisStack.push(l);
|
|
10593
|
+
return l;
|
|
10594
|
+
}
|
|
10595
|
+
if (expr.op === "??" && l !== null && l !== void 0) {
|
|
10596
|
+
setExprValue(expr, { value: l }, thread);
|
|
10597
|
+
thisStack.push(l);
|
|
10598
|
+
return l;
|
|
10599
|
+
}
|
|
10600
|
+
evaluator(thisStack, expr.right, evalContext, thread);
|
|
10601
|
+
thisStack.pop();
|
|
10602
|
+
return evalBinaryCore(expr, thisStack, evalContext, thread);
|
|
10603
|
+
}
|
|
10604
|
+
function evalConditional(evaluator, thisStack, expr, evalContext, thread) {
|
|
10605
|
+
const condition = evaluator(thisStack, expr.cond, evalContext, thread);
|
|
10606
|
+
thisStack.pop();
|
|
10607
|
+
const value = evaluator(thisStack, condition ? expr.thenE : expr.elseE, evalContext, thread);
|
|
10608
|
+
setExprValue(expr, { value }, thread);
|
|
10609
|
+
return value;
|
|
10610
|
+
}
|
|
10611
|
+
function evalAssignment(evaluator, thisStack, expr, evalContext, thread) {
|
|
10612
|
+
const leftValue = expr.leftValue;
|
|
10613
|
+
const rootScope = getRootIdScope(leftValue, evalContext, thread);
|
|
10614
|
+
const updatesState = rootScope && rootScope.type !== "block";
|
|
10615
|
+
if (updatesState && evalContext.onWillUpdate) evalContext.onWillUpdate(rootScope, rootScope.name, "assignment");
|
|
10616
|
+
evaluator(thisStack, leftValue, evalContext, thread);
|
|
10617
|
+
thisStack.pop();
|
|
10618
|
+
evaluator(thisStack, expr.expr, evalContext, thread);
|
|
10619
|
+
thisStack.pop();
|
|
10620
|
+
const value = evalAssignmentCore(thisStack, expr, evalContext, thread);
|
|
10621
|
+
if (updatesState && evalContext.onDidUpdate) evalContext.onDidUpdate(rootScope, rootScope.name, "assignment");
|
|
10622
|
+
return value;
|
|
10623
|
+
}
|
|
10624
|
+
function evalPreOrPost(evaluator, thisStack, expr, evalContext, thread) {
|
|
10625
|
+
const rootScope = getRootIdScope(expr.expr, evalContext, thread);
|
|
10626
|
+
const updatesState = rootScope && rootScope.type !== "block";
|
|
10627
|
+
if (updatesState && evalContext.onWillUpdate) evalContext.onWillUpdate(rootScope, rootScope.name, "pre-post");
|
|
10628
|
+
evaluator(thisStack, expr.expr, evalContext, thread);
|
|
10629
|
+
thisStack.pop();
|
|
10630
|
+
const value = evalPreOrPostCore(thisStack, expr, evalContext, thread);
|
|
10631
|
+
if (updatesState && evalContext.onDidUpdate) evalContext.onDidUpdate(rootScope, rootScope.name, "pre-post");
|
|
10632
|
+
return value;
|
|
10633
|
+
}
|
|
10634
|
+
function evalFunctionInvocation(evaluator, thisStack, expr, evalContext, thread) {
|
|
10635
|
+
let functionObj;
|
|
10636
|
+
let implicitContextObject = null;
|
|
10637
|
+
if (expr.obj.type === T_MEMBER_ACCESS_EXPRESSION) {
|
|
10638
|
+
const hostObject = evaluator(thisStack, expr.obj.obj, evalContext, thread);
|
|
10639
|
+
functionObj = evalMemberAccessCore(thisStack, expr.obj, evalContext, thread);
|
|
10640
|
+
if (expr.obj.obj.type === T_IDENTIFIER && hostObject?._SUPPORT_IMPLICIT_CONTEXT) implicitContextObject = hostObject;
|
|
10641
|
+
} else functionObj = evaluator(thisStack, expr.obj, evalContext, thread);
|
|
10642
|
+
thisStack.pop();
|
|
10643
|
+
const functionArgs = [];
|
|
10644
|
+
if (isArrowExpressionObject(functionObj)) {
|
|
10645
|
+
functionArgs.push(functionObj.args, evalContext, thread, ...expr.arguments.map((a) => ({
|
|
10646
|
+
...a,
|
|
10647
|
+
_EXPRESSION_: true
|
|
10648
|
+
})));
|
|
10649
|
+
functionObj = createArrowFunction(evaluator, functionObj);
|
|
10650
|
+
} else if (expr.obj.type === T_ARROW_EXPRESSION) functionArgs.push(expr.obj.args, evalContext, thread, ...expr.arguments.map((a) => ({
|
|
10651
|
+
...a,
|
|
10652
|
+
_EXPRESSION_: true
|
|
10653
|
+
})));
|
|
10654
|
+
else {
|
|
10655
|
+
for (let i = 0; i < expr.arguments.length; i++) {
|
|
10656
|
+
const arg = expr.arguments[i];
|
|
10657
|
+
if (arg.type === T_SPREAD_EXPRESSION) {
|
|
10658
|
+
const funcArg = evaluator([], arg.expr, evalContext, thread);
|
|
10659
|
+
if (!Array.isArray(funcArg)) throw new Error("Spread operator within a function invocation expects an array operand.");
|
|
10660
|
+
functionArgs.push(...funcArg);
|
|
10661
|
+
} else if (arg.type === T_ARROW_EXPRESSION) {
|
|
10662
|
+
const funcArg = createArrowFunction(evaluator, arg);
|
|
10663
|
+
const wrappedFunc = (...args) => funcArg(arg.args, evalContext, thread, ...args);
|
|
10664
|
+
functionArgs.push(wrappedFunc);
|
|
10665
|
+
} else {
|
|
10666
|
+
const funcArg = evaluator([], arg, evalContext, thread);
|
|
10667
|
+
if (isArrowExpressionObject(funcArg)) {
|
|
10668
|
+
const wrappedFuncArg = createArrowFunction(evaluator, funcArg);
|
|
10669
|
+
const wrappedFunc = (...args) => wrappedFuncArg(funcArg.args, evalContext, thread, ...args);
|
|
10670
|
+
functionArgs.push(wrappedFunc);
|
|
10671
|
+
} else functionArgs.push(funcArg);
|
|
10672
|
+
}
|
|
10673
|
+
}
|
|
10674
|
+
if (implicitContextObject) if (evalContext.implicitContextGetter) {
|
|
10675
|
+
const implicitContext = evalContext.implicitContextGetter(implicitContextObject);
|
|
10676
|
+
functionArgs.unshift(implicitContext);
|
|
10677
|
+
} else throw new Error("Cannot use implicitContextGetter, it is undefined");
|
|
10678
|
+
}
|
|
10679
|
+
const bannedInfo = isBannedFunction(functionObj);
|
|
10680
|
+
if (bannedInfo.banned) throw new Error(`Function ${bannedInfo.func?.name ?? "unknown"} is not allowed to call. ${bannedInfo?.help ?? ""}`);
|
|
10681
|
+
const currentContext = thisStack.length > 0 ? thisStack.pop() : evalContext.localContext;
|
|
10682
|
+
const rootScope = getRootIdScope(expr.obj, evalContext, thread);
|
|
10683
|
+
const updatesState = rootScope && rootScope.type !== "block";
|
|
10684
|
+
if (updatesState && evalContext.onWillUpdate) evalContext.onWillUpdate(rootScope, rootScope.name, "function-call");
|
|
10685
|
+
const value = evalContext.options?.defaultToOptionalMemberAccess ? functionObj?.call(currentContext, ...functionArgs) : functionObj.call(currentContext, ...functionArgs);
|
|
10686
|
+
if (updatesState && evalContext.onDidUpdate) evalContext.onDidUpdate(rootScope, rootScope.name, "function-call");
|
|
10687
|
+
setExprValue(expr, { value }, thread);
|
|
10688
|
+
thisStack.push(value);
|
|
10689
|
+
return value;
|
|
10690
|
+
}
|
|
10691
|
+
function evalNewExpression(evaluator, thisStack, expr, evalContext, thread) {
|
|
10692
|
+
const allowedConstructors = new Map([
|
|
10693
|
+
["String", String],
|
|
10694
|
+
["Date", Date],
|
|
10695
|
+
["Blob", Blob]
|
|
10696
|
+
]);
|
|
10697
|
+
const constructorObj = evaluator(thisStack, expr.callee, evalContext, thread);
|
|
10698
|
+
thisStack.pop();
|
|
10699
|
+
let allowedConstructor = null;
|
|
10700
|
+
for (const [name, ctor] of allowedConstructors) if (constructorObj === ctor) {
|
|
10701
|
+
allowedConstructor = ctor;
|
|
10702
|
+
break;
|
|
10703
|
+
}
|
|
10704
|
+
if (!allowedConstructor) {
|
|
10705
|
+
const constructorName = constructorObj?.name || "unknown";
|
|
10706
|
+
throw new Error(`XMLUI does not support the new operator with constructor '${constructorName}'. Only String, Date, and Blob are allowed.`);
|
|
10707
|
+
}
|
|
10708
|
+
const constructorArgs = [];
|
|
10709
|
+
for (let i = 0; i < expr.arguments.length; i++) {
|
|
10710
|
+
const arg = expr.arguments[i];
|
|
10711
|
+
if (arg.type === T_SPREAD_EXPRESSION) {
|
|
10712
|
+
const funcArg = evaluator([], arg.expr, evalContext, thread);
|
|
10713
|
+
if (!Array.isArray(funcArg)) throw new Error("Spread operator within a new expression expects an array operand.");
|
|
10714
|
+
constructorArgs.push(...funcArg);
|
|
10715
|
+
} else {
|
|
10716
|
+
const funcArg = evaluator([], arg, evalContext, thread);
|
|
10717
|
+
constructorArgs.push(funcArg);
|
|
10718
|
+
}
|
|
10719
|
+
}
|
|
10720
|
+
const value = new allowedConstructor(...constructorArgs);
|
|
10721
|
+
setExprValue(expr, { value }, thread);
|
|
10722
|
+
thisStack.push(value);
|
|
10723
|
+
return value;
|
|
10724
|
+
}
|
|
10725
|
+
function createArrowFunction(evaluator, expr) {
|
|
10726
|
+
return (...args) => {
|
|
10727
|
+
const runTimeEvalContext = args[1];
|
|
10728
|
+
const runtimeThread = args[2];
|
|
10729
|
+
const workingThread = {
|
|
10730
|
+
parent: runtimeThread,
|
|
10731
|
+
childThreads: [],
|
|
10732
|
+
blocks: [{ vars: {} }],
|
|
10733
|
+
loops: [],
|
|
10734
|
+
breakLabelValue: -1,
|
|
10735
|
+
closures: expr.closureContext
|
|
10736
|
+
};
|
|
10737
|
+
runtimeThread.childThreads.push(workingThread);
|
|
10738
|
+
if (expr.name) {
|
|
10739
|
+
const functionBlock = { vars: {} };
|
|
10740
|
+
workingThread.blocks ??= [];
|
|
10741
|
+
workingThread.blocks.push(functionBlock);
|
|
10742
|
+
functionBlock.vars[expr.name] = expr;
|
|
10743
|
+
functionBlock.constVars = new Set([expr.name]);
|
|
10744
|
+
}
|
|
10745
|
+
const arrowBlock = { vars: {} };
|
|
10746
|
+
workingThread.blocks ??= [];
|
|
10747
|
+
workingThread.blocks.push(arrowBlock);
|
|
10748
|
+
const argSpecs = args[0];
|
|
10749
|
+
let restFound = false;
|
|
10750
|
+
for (let i = 0; i < argSpecs.length; i++) {
|
|
10751
|
+
const argSpec = argSpecs[i];
|
|
10752
|
+
let decl;
|
|
10753
|
+
switch (argSpec.type) {
|
|
10754
|
+
case T_IDENTIFIER:
|
|
10755
|
+
decl = {
|
|
10756
|
+
type: T_VAR_DECLARATION,
|
|
10757
|
+
id: argSpec.name
|
|
10758
|
+
};
|
|
10759
|
+
break;
|
|
10760
|
+
case T_DESTRUCTURE:
|
|
10761
|
+
decl = {
|
|
10762
|
+
type: T_VAR_DECLARATION,
|
|
10763
|
+
id: argSpec.id,
|
|
10764
|
+
aDestr: argSpec.aDestr,
|
|
10765
|
+
oDestr: argSpec.oDestr
|
|
10766
|
+
};
|
|
10767
|
+
break;
|
|
10768
|
+
case T_SPREAD_EXPRESSION:
|
|
10769
|
+
restFound = true;
|
|
10770
|
+
decl = {
|
|
10771
|
+
type: T_VAR_DECLARATION,
|
|
10772
|
+
id: argSpec.expr.name
|
|
10773
|
+
};
|
|
10774
|
+
break;
|
|
10775
|
+
default: throw new Error("Unexpected arrow argument specification");
|
|
10776
|
+
}
|
|
10777
|
+
if (decl) if (restFound) {
|
|
10778
|
+
const restArgs = args.slice(i + 3);
|
|
10779
|
+
let argVals = [];
|
|
10780
|
+
for (const arg of restArgs) if (arg?._EXPRESSION_) argVals.push(evaluator([], arg, runTimeEvalContext, runtimeThread));
|
|
10781
|
+
else argVals.push(arg);
|
|
10782
|
+
processDeclarations(arrowBlock, runTimeEvalContext, runtimeThread, [decl], false, true, argVals);
|
|
10783
|
+
} else {
|
|
10784
|
+
let argVal = args[i + 3];
|
|
10785
|
+
if (argVal?._EXPRESSION_) argVal = evaluator([], argVal, runTimeEvalContext, runtimeThread);
|
|
10786
|
+
processDeclarations(arrowBlock, runTimeEvalContext, runtimeThread, [decl], false, true, argVal);
|
|
10787
|
+
}
|
|
10788
|
+
}
|
|
10789
|
+
let returnValue;
|
|
10790
|
+
let statements;
|
|
10791
|
+
switch (expr.statement.type) {
|
|
10792
|
+
case T_EMPTY_STATEMENT:
|
|
10793
|
+
statements = [];
|
|
10794
|
+
break;
|
|
10795
|
+
case T_EXPRESSION_STATEMENT:
|
|
10796
|
+
statements = [{
|
|
10797
|
+
type: T_RETURN_STATEMENT,
|
|
10798
|
+
nodeId: createXmlUiTreeNodeId(),
|
|
10799
|
+
expr: expr.statement.expr
|
|
10800
|
+
}];
|
|
10801
|
+
break;
|
|
10802
|
+
case T_BLOCK_STATEMENT:
|
|
10803
|
+
statements = expr.statement.stmts;
|
|
10804
|
+
break;
|
|
10805
|
+
default: throw new Error(`Arrow expression with a body of '${expr.statement.type}' is not supported yet.`);
|
|
10806
|
+
}
|
|
10807
|
+
processStatementQueue(statements, runTimeEvalContext, workingThread);
|
|
10808
|
+
returnValue = workingThread.returnValue;
|
|
10809
|
+
const workingIndex = runtimeThread.childThreads.indexOf(workingThread);
|
|
10810
|
+
if (workingIndex < 0) throw new Error("Cannot find thread to remove.");
|
|
10811
|
+
runtimeThread.childThreads.splice(workingIndex, 1);
|
|
10812
|
+
workingThread.blocks.pop();
|
|
10813
|
+
return returnValue;
|
|
10814
|
+
};
|
|
10815
|
+
}
|
|
10816
|
+
|
|
10817
|
+
//#endregion
|
|
10818
|
+
//#region src/components-core/utils/LruCache.ts
|
|
10819
|
+
/**
|
|
10820
|
+
* A single node of the LRU cache
|
|
10821
|
+
*/
|
|
10822
|
+
var DoublyLinkedNode = class {
|
|
10823
|
+
constructor(value, key) {
|
|
10824
|
+
this.value = value;
|
|
10825
|
+
this.key = key;
|
|
10826
|
+
this.next = void 0;
|
|
10827
|
+
this.prev = void 0;
|
|
10828
|
+
}
|
|
10829
|
+
};
|
|
10830
|
+
/**
|
|
10831
|
+
* We keep values in the LRU cache in a doubly linked list
|
|
10832
|
+
*/
|
|
10833
|
+
var DoublyLinkedList = class {
|
|
10834
|
+
constructor() {
|
|
10835
|
+
this.size = 0;
|
|
10836
|
+
this.head = void 0;
|
|
10837
|
+
this.tail = void 0;
|
|
10838
|
+
this.size = 0;
|
|
10839
|
+
}
|
|
10840
|
+
/**
|
|
10841
|
+
* Adds a new node to the head of the list
|
|
10842
|
+
* @param node The node to add to head of list
|
|
10843
|
+
*/
|
|
10844
|
+
unshift(node) {
|
|
10845
|
+
if (this.size === 0) {
|
|
10846
|
+
this.head = node;
|
|
10847
|
+
this.tail = node;
|
|
10848
|
+
this.size++;
|
|
10849
|
+
} else {
|
|
10850
|
+
this.head.prev = node;
|
|
10851
|
+
node.next = this.head;
|
|
10852
|
+
node.prev = void 0;
|
|
10853
|
+
this.head = node;
|
|
10854
|
+
this.size++;
|
|
10855
|
+
}
|
|
10856
|
+
}
|
|
10857
|
+
/**
|
|
10858
|
+
* Remove least recently used node from tail
|
|
10859
|
+
*/
|
|
10860
|
+
pop() {
|
|
10861
|
+
const node = this.tail;
|
|
10862
|
+
if (!node) return;
|
|
10863
|
+
else if (this.head === this.tail) {
|
|
10864
|
+
this.head = void 0;
|
|
10865
|
+
this.tail = void 0;
|
|
10866
|
+
} else this.tail.prev.next = void 0;
|
|
10867
|
+
this.tail = node.prev;
|
|
10868
|
+
this.size--;
|
|
10869
|
+
return node;
|
|
10870
|
+
}
|
|
10871
|
+
/**
|
|
10872
|
+
* Moves the specified node to the head
|
|
10873
|
+
*/
|
|
10874
|
+
moveToHead(node) {
|
|
10875
|
+
if (node === this.head) return;
|
|
10876
|
+
if (node === this.head && node === this.tail) return;
|
|
10877
|
+
if (node === this.tail) {
|
|
10878
|
+
this.tail = this.tail.prev;
|
|
10879
|
+
this.tail.next = void 0;
|
|
10880
|
+
node.next = this.head;
|
|
10881
|
+
this.head.prev = node;
|
|
10882
|
+
this.head = node;
|
|
10883
|
+
node.prev = void 0;
|
|
10884
|
+
} else {
|
|
10885
|
+
node.prev.next = node.next;
|
|
10886
|
+
node.next.prev = node.prev;
|
|
10887
|
+
node.next = this.head;
|
|
10888
|
+
this.head.prev = node;
|
|
10889
|
+
this.head = node;
|
|
10890
|
+
node.prev = void 0;
|
|
10891
|
+
}
|
|
10892
|
+
}
|
|
10893
|
+
};
|
|
10894
|
+
/**
|
|
10895
|
+
* This class implements the LRU cache
|
|
10896
|
+
*/
|
|
10897
|
+
var LRUCache = class {
|
|
10898
|
+
constructor(maxSize) {
|
|
10899
|
+
this.maxSize = maxSize;
|
|
10900
|
+
this.store = {};
|
|
10901
|
+
this.list = new DoublyLinkedList();
|
|
10902
|
+
}
|
|
10903
|
+
/**
|
|
10904
|
+
* Gets the number of items stored in the cache
|
|
10905
|
+
*/
|
|
10906
|
+
get length() {
|
|
10907
|
+
return this.list.size;
|
|
10908
|
+
}
|
|
10909
|
+
/**
|
|
10910
|
+
* Gets the value with the specified key
|
|
10911
|
+
* @param key
|
|
10912
|
+
*/
|
|
10913
|
+
get(key) {
|
|
10914
|
+
const existingNode = this.store[key];
|
|
10915
|
+
if (existingNode) this.list.moveToHead(existingNode);
|
|
10916
|
+
return existingNode?.value;
|
|
10917
|
+
}
|
|
10918
|
+
/**
|
|
10919
|
+
* Sets the value for a particular key within the cache
|
|
10920
|
+
* @param key Cache item key
|
|
10921
|
+
* @param value Cache item value
|
|
10922
|
+
*/
|
|
10923
|
+
set(key, value) {
|
|
10924
|
+
const existingNode = this.get(key);
|
|
10925
|
+
if (existingNode) existingNode.value = value;
|
|
10926
|
+
const newNode = new DoublyLinkedNode(value, key);
|
|
10927
|
+
this.store[key] = newNode;
|
|
10928
|
+
this.list.unshift(newNode);
|
|
10929
|
+
if (this.hasReachedMaxSize()) this.evictLeastRecentlyUsed();
|
|
10930
|
+
}
|
|
10931
|
+
hasReachedMaxSize() {
|
|
10932
|
+
return this.list.size === this.maxSize + 1;
|
|
10933
|
+
}
|
|
10934
|
+
evictLeastRecentlyUsed() {
|
|
10935
|
+
const evictedNode = this.list.pop();
|
|
10936
|
+
delete this.store[evictedNode.key];
|
|
10937
|
+
}
|
|
10938
|
+
};
|
|
10939
|
+
|
|
10940
|
+
//#endregion
|
|
10941
|
+
//#region src/components-core/utils/extractParam.ts
|
|
10942
|
+
/**
|
|
10943
|
+
* Extract the value of the specified parameter from the given view container state
|
|
10944
|
+
* @param state The state of the view container
|
|
10945
|
+
* @param param Parameter to extract
|
|
10946
|
+
* @param appContext Application context to use
|
|
10947
|
+
* @param strict Strict evaluation?
|
|
10948
|
+
* @param extractContext
|
|
10949
|
+
* @returns
|
|
10950
|
+
*/
|
|
10951
|
+
function extractParam(state, param, appContext = void 0, strict = false, extractContext = { didResolve: false }) {
|
|
10952
|
+
if (typeof param === "string") {
|
|
10953
|
+
const paramSegments = parseParameterString(param);
|
|
10954
|
+
if (paramSegments.length === 0) return param;
|
|
10955
|
+
if (paramSegments[0].type === "literal" && paramSegments[0].value.trim() === "") paramSegments.shift();
|
|
10956
|
+
if (paramSegments.length === 0) return param;
|
|
10957
|
+
const lastSegment = paramSegments[paramSegments.length - 1];
|
|
10958
|
+
if (lastSegment.type === "literal" && lastSegment.value.trim() === "") paramSegments.pop();
|
|
10959
|
+
if (paramSegments.length === 0) return param;
|
|
10960
|
+
if (paramSegments.length === 1) if (paramSegments[0].type === "literal") return paramSegments[0].value;
|
|
10961
|
+
else {
|
|
10962
|
+
extractContext.didResolve = true;
|
|
10963
|
+
return evalBinding(paramSegments[0].value, {
|
|
10964
|
+
localContext: state,
|
|
10965
|
+
appContext,
|
|
10966
|
+
options: { defaultToOptionalMemberAccess: true }
|
|
10967
|
+
});
|
|
10968
|
+
}
|
|
10969
|
+
let result = "";
|
|
10970
|
+
paramSegments.forEach((ps) => {
|
|
10971
|
+
if (ps.type === "literal") result += ps.value;
|
|
10972
|
+
else {
|
|
10973
|
+
extractContext.didResolve = true;
|
|
10974
|
+
const exprValue = evalBinding(ps.value, {
|
|
10975
|
+
localContext: state,
|
|
10976
|
+
appContext,
|
|
10977
|
+
options: { defaultToOptionalMemberAccess: true }
|
|
10978
|
+
});
|
|
10979
|
+
if (exprValue?.toString) result += exprValue.toString();
|
|
10980
|
+
}
|
|
10981
|
+
});
|
|
10982
|
+
return result;
|
|
10983
|
+
}
|
|
10984
|
+
if (strict) return param;
|
|
10985
|
+
if (Array.isArray(param)) {
|
|
10986
|
+
const arrayExtractContext = { didResolve: false };
|
|
10987
|
+
let resolvedChildren = param.map((childParam) => extractParam(state, childParam, appContext, false, arrayExtractContext));
|
|
10988
|
+
if (arrayExtractContext.didResolve) {
|
|
10989
|
+
extractContext.didResolve = true;
|
|
10990
|
+
return resolvedChildren;
|
|
10991
|
+
}
|
|
10992
|
+
return param;
|
|
10993
|
+
}
|
|
10994
|
+
if ((0, lodash_es.isPlainObject)(param)) {
|
|
10995
|
+
const objectExtractContext = { didResolve: false };
|
|
10996
|
+
const substitutedObject = {};
|
|
10997
|
+
Object.entries(param).forEach(([key, value]) => {
|
|
10998
|
+
substitutedObject[key] = extractParam(state, value, appContext, false, objectExtractContext);
|
|
10999
|
+
});
|
|
11000
|
+
if (objectExtractContext.didResolve) {
|
|
11001
|
+
extractContext.didResolve = true;
|
|
11002
|
+
return substitutedObject;
|
|
11003
|
+
}
|
|
11004
|
+
return param;
|
|
11005
|
+
}
|
|
11006
|
+
return param;
|
|
11007
|
+
}
|
|
11008
|
+
const extractedObjectCache = new LRUCache(1024 * 10);
|
|
11009
|
+
|
|
11010
|
+
//#endregion
|
|
11011
|
+
//#region src/language-server/base/text-document.ts
|
|
11012
|
+
var DocumentCursor = class {
|
|
11013
|
+
constructor(text) {
|
|
11014
|
+
this.text = text;
|
|
11015
|
+
this.newlineOffsets = [0];
|
|
11016
|
+
for (let i = 0; i < text.length; i++) {
|
|
11017
|
+
const ch = text.charCodeAt(i);
|
|
11018
|
+
if (isEOL(ch)) {
|
|
11019
|
+
if (ch === 13 && i + 1 < text.length && text.charCodeAt(i + 1) === 10) i++;
|
|
11020
|
+
this.newlineOffsets.push(i + 1);
|
|
11021
|
+
}
|
|
11022
|
+
}
|
|
11023
|
+
}
|
|
11024
|
+
get textLength() {
|
|
11025
|
+
return this.text.length;
|
|
11026
|
+
}
|
|
11027
|
+
get lineCount() {
|
|
11028
|
+
return this.newlineOffsets.length;
|
|
11029
|
+
}
|
|
11030
|
+
/**
|
|
11031
|
+
* Converts a zero-based offset to a position.
|
|
11032
|
+
*
|
|
11033
|
+
* @param offset A zero-based offset.
|
|
11034
|
+
* @return A valid {@link Position position}.
|
|
11035
|
+
* @example The text document "ab\ncd" produces:
|
|
11036
|
+
* * position { line: 0, character: 0 } for `offset` 0.
|
|
11037
|
+
* * position { line: 0, character: 1 } for `offset` 1.
|
|
11038
|
+
* * position { line: 0, character: 2 } for `offset` 2.
|
|
11039
|
+
* * position { line: 1, character: 0 } for `offset` 3.
|
|
11040
|
+
* * position { line: 1, character: 1 } for `offset` 4.
|
|
11041
|
+
*/
|
|
11042
|
+
positionAt(offset) {
|
|
11043
|
+
offset = Math.max(Math.min(offset, this.textLength), 0);
|
|
11044
|
+
const lineOffsets = this.newlineOffsets;
|
|
11045
|
+
let low = 0, high = lineOffsets.length;
|
|
11046
|
+
if (high === 0) return {
|
|
11047
|
+
line: 0,
|
|
11048
|
+
character: offset
|
|
11049
|
+
};
|
|
11050
|
+
while (low < high) {
|
|
11051
|
+
const mid = Math.floor((low + high) / 2);
|
|
11052
|
+
if (lineOffsets[mid] > offset) high = mid;
|
|
11053
|
+
else low = mid + 1;
|
|
11054
|
+
}
|
|
11055
|
+
const line = low - 1;
|
|
11056
|
+
return {
|
|
11057
|
+
line,
|
|
11058
|
+
character: offset - lineOffsets[line]
|
|
11059
|
+
};
|
|
11060
|
+
}
|
|
11061
|
+
/**
|
|
11062
|
+
* Converts the position to a zero-based offset.
|
|
11063
|
+
* Invalid positions are adjusted as described in {@link Position.line}
|
|
11064
|
+
* and {@link Position.character}.
|
|
11065
|
+
*
|
|
11066
|
+
* @param position A position.
|
|
11067
|
+
* @return A valid zero-based offset.
|
|
11068
|
+
*/
|
|
11069
|
+
offsetAt(position) {
|
|
11070
|
+
if (position.line >= this.newlineOffsets.length) return this.textLength;
|
|
11071
|
+
else if (position.line < 0) return 0;
|
|
11072
|
+
const lineOffset = this.newlineOffsets[position.line];
|
|
11073
|
+
if (position.character <= 0) return lineOffset;
|
|
11074
|
+
const nextLineOffset = position.line + 1 < this.newlineOffsets.length ? this.newlineOffsets[position.line + 1] : this.textLength;
|
|
11075
|
+
return Math.min(lineOffset + position.character, nextLineOffset);
|
|
11076
|
+
}
|
|
11077
|
+
offsetToDisplayPos(offset) {
|
|
11078
|
+
const pos = this.positionAt(offset);
|
|
11079
|
+
return {
|
|
11080
|
+
line: pos.line + 1,
|
|
11081
|
+
character: pos.character + 1
|
|
11082
|
+
};
|
|
11083
|
+
}
|
|
11084
|
+
getSurroundingContext(pos, end, surroundingLines) {
|
|
11085
|
+
const startLine = this.positionAt(pos).line;
|
|
11086
|
+
const endLine = this.positionAt(end).line;
|
|
11087
|
+
const contextStartLine = Math.max(0, startLine - surroundingLines);
|
|
11088
|
+
const contextPos = this.newlineOffsets[contextStartLine];
|
|
11089
|
+
const nextLineAfterContext = Math.min(this.lineCount - 1, endLine + surroundingLines) + 1;
|
|
11090
|
+
let contextEnd;
|
|
11091
|
+
if (nextLineAfterContext < this.lineCount) {
|
|
11092
|
+
const nextLineStart = this.newlineOffsets[nextLineAfterContext];
|
|
11093
|
+
let eolLength = 1;
|
|
11094
|
+
if (nextLineStart > 0 && this.text.charCodeAt(nextLineStart - 1) === 10) {
|
|
11095
|
+
if (nextLineStart > 1 && this.text.charCodeAt(nextLineStart - 2) === 13) eolLength = 2;
|
|
11096
|
+
}
|
|
11097
|
+
contextEnd = nextLineStart - eolLength;
|
|
11098
|
+
} else contextEnd = this.textLength;
|
|
11099
|
+
return {
|
|
11100
|
+
contextPos,
|
|
11101
|
+
contextEnd
|
|
11102
|
+
};
|
|
11103
|
+
}
|
|
11104
|
+
rangeAt(range) {
|
|
11105
|
+
return {
|
|
11106
|
+
start: this.positionAt(range.pos),
|
|
11107
|
+
end: this.positionAt(range.end)
|
|
11108
|
+
};
|
|
11109
|
+
}
|
|
11110
|
+
offsetRangeAt(range) {
|
|
11111
|
+
return {
|
|
11112
|
+
pos: this.offsetAt(range.start),
|
|
11113
|
+
end: this.offsetAt(range.end)
|
|
11114
|
+
};
|
|
11115
|
+
}
|
|
11116
|
+
};
|
|
11117
|
+
function isEOL(char) {
|
|
11118
|
+
return char === 13 || char === 10;
|
|
11119
|
+
}
|
|
11120
|
+
|
|
11121
|
+
//#endregion
|
|
11122
|
+
//#region src/parsers/xmlui-parser/parser.ts
|
|
11123
|
+
const RECOVER_FILE = [
|
|
11124
|
+
SyntaxKind.CData,
|
|
11125
|
+
SyntaxKind.Script,
|
|
11126
|
+
SyntaxKind.OpenNodeStart
|
|
11127
|
+
];
|
|
11128
|
+
const RECOVER_OPEN_TAG = [
|
|
9257
11129
|
SyntaxKind.OpenNodeStart,
|
|
9258
11130
|
SyntaxKind.NodeEnd,
|
|
9259
11131
|
SyntaxKind.NodeClose,
|
|
@@ -10220,9 +12092,9 @@ async function convertResourcesDir(distRoot, flatDist, filePrefix) {
|
|
|
10220
12092
|
}
|
|
10221
12093
|
return ret;
|
|
10222
12094
|
}
|
|
10223
|
-
function removeLeadingSlashForPath(path$
|
|
10224
|
-
if (path$
|
|
10225
|
-
return path$
|
|
12095
|
+
function removeLeadingSlashForPath(path$8) {
|
|
12096
|
+
if (path$8.startsWith("/")) return path$8.substring(1);
|
|
12097
|
+
return path$8;
|
|
10226
12098
|
}
|
|
10227
12099
|
const build = async ({ buildMode = "CONFIG_ONLY", flatDist = false, withMock = false, withHostingMetaFiles = false, withRelativeRoot = false }) => {
|
|
10228
12100
|
const flatDistUiPrefix = "ui_";
|
|
@@ -10411,6 +12283,420 @@ const preview = async ({ proxy }) => {
|
|
|
10411
12283
|
}
|
|
10412
12284
|
};
|
|
10413
12285
|
|
|
12286
|
+
//#endregion
|
|
12287
|
+
//#region bin/ssg/discoverPaths.ts
|
|
12288
|
+
function getPagesComponent(comp) {
|
|
12289
|
+
if (!comp) return null;
|
|
12290
|
+
if (comp.type === "Pages") return comp;
|
|
12291
|
+
if (Array.isArray(comp.children)) for (const child of comp.children) {
|
|
12292
|
+
const result = getPagesComponent(child);
|
|
12293
|
+
if (result) return result;
|
|
12294
|
+
}
|
|
12295
|
+
return null;
|
|
12296
|
+
}
|
|
12297
|
+
function substituteParams(url, params) {
|
|
12298
|
+
let variants = [url];
|
|
12299
|
+
for (const [key, value] of Object.entries(params)) {
|
|
12300
|
+
if (!variants.some((variant) => variant.includes(`:${key}`))) continue;
|
|
12301
|
+
const values = Array.isArray(value) ? value : [value];
|
|
12302
|
+
const next = [];
|
|
12303
|
+
for (const variant of variants) {
|
|
12304
|
+
if (!variant.includes(`:${key}`)) {
|
|
12305
|
+
next.push(variant);
|
|
12306
|
+
continue;
|
|
12307
|
+
}
|
|
12308
|
+
for (const paramValue of values) {
|
|
12309
|
+
if (paramValue === null || paramValue === void 0) continue;
|
|
12310
|
+
next.push(variant.split(`:${key}`).join(String(paramValue)));
|
|
12311
|
+
}
|
|
12312
|
+
}
|
|
12313
|
+
variants = next;
|
|
12314
|
+
}
|
|
12315
|
+
return variants.filter((variant) => !variant.includes(":"));
|
|
12316
|
+
}
|
|
12317
|
+
function normalizeRoute$1(pathname) {
|
|
12318
|
+
let route = pathname.trim();
|
|
12319
|
+
if (route.length === 0) return "/";
|
|
12320
|
+
if (!route.startsWith("/")) route = `/${route}`;
|
|
12321
|
+
if (route !== "/" && route.endsWith("/")) route = route.slice(0, -1);
|
|
12322
|
+
return route;
|
|
12323
|
+
}
|
|
12324
|
+
async function readAllFilesRecursive(dir) {
|
|
12325
|
+
const files = [];
|
|
12326
|
+
let entries;
|
|
12327
|
+
try {
|
|
12328
|
+
entries = await (0, node_fs_promises.readdir)(dir, { withFileTypes: true });
|
|
12329
|
+
} catch {
|
|
12330
|
+
return files;
|
|
12331
|
+
}
|
|
12332
|
+
for (const entry of entries) {
|
|
12333
|
+
const fullPath = node_path.default.join(dir, entry.name);
|
|
12334
|
+
if (entry.isDirectory()) {
|
|
12335
|
+
files.push(...await readAllFilesRecursive(fullPath));
|
|
12336
|
+
continue;
|
|
12337
|
+
}
|
|
12338
|
+
files.push(fullPath);
|
|
12339
|
+
}
|
|
12340
|
+
return files;
|
|
12341
|
+
}
|
|
12342
|
+
async function discoverPaths(cwd) {
|
|
12343
|
+
const mainXmluiPath = node_path.default.resolve(cwd, "src", "Main.xmlui");
|
|
12344
|
+
const discovered = /* @__PURE__ */ new Set();
|
|
12345
|
+
let mainXmluiTextContent;
|
|
12346
|
+
try {
|
|
12347
|
+
mainXmluiTextContent = await (0, node_fs_promises.readFile)(mainXmluiPath, "utf-8");
|
|
12348
|
+
} catch {
|
|
12349
|
+
return ["/"];
|
|
12350
|
+
}
|
|
12351
|
+
const { parse: parse$2, getText } = createXmlUiParser(mainXmluiTextContent);
|
|
12352
|
+
const pagesComp = getPagesComponent(nodeToComponentDef(parse$2().node, getText, 0));
|
|
12353
|
+
if (pagesComp?.children) for (const page of pagesComp.children) {
|
|
12354
|
+
const url = page.props?.url;
|
|
12355
|
+
if (typeof url !== "string" || url.trim().length === 0) continue;
|
|
12356
|
+
if (page.props?.staticPaths) try {
|
|
12357
|
+
const staticPaths = extractParam({}, page.props.staticPaths, void 0, true);
|
|
12358
|
+
if (Array.isArray(staticPaths)) for (const entry of staticPaths) {
|
|
12359
|
+
if (!entry || typeof entry !== "object") continue;
|
|
12360
|
+
const params = entry.params;
|
|
12361
|
+
if (!params || typeof params !== "object") continue;
|
|
12362
|
+
for (const resolved of substituteParams(url, params)) discovered.add(normalizeRoute$1(resolved));
|
|
12363
|
+
}
|
|
12364
|
+
} catch (error) {
|
|
12365
|
+
console.warn(`Failed to evaluate staticPaths for '${url}'`, error);
|
|
12366
|
+
}
|
|
12367
|
+
if (!url.includes(":") && !url.includes("*")) discovered.add(normalizeRoute$1(url));
|
|
12368
|
+
}
|
|
12369
|
+
const contentDir = node_path.default.resolve(cwd, "content");
|
|
12370
|
+
const contentFiles = await readAllFilesRecursive(contentDir);
|
|
12371
|
+
for (const filePath of contentFiles) {
|
|
12372
|
+
if (!filePath.endsWith(".md")) continue;
|
|
12373
|
+
const relative = node_path.default.relative(contentDir, filePath).replace(/\\/g, "/");
|
|
12374
|
+
if (relative.startsWith("pages/") || relative.includes("/pages/")) continue;
|
|
12375
|
+
discovered.add(normalizeRoute$1(`/${relative.replace(/\.md$/, "")}`));
|
|
12376
|
+
}
|
|
12377
|
+
if (discovered.size === 0) return ["/"];
|
|
12378
|
+
return [...discovered];
|
|
12379
|
+
}
|
|
12380
|
+
async function pathExists(targetPath) {
|
|
12381
|
+
try {
|
|
12382
|
+
await (0, node_fs_promises.stat)(targetPath);
|
|
12383
|
+
return true;
|
|
12384
|
+
} catch {
|
|
12385
|
+
return false;
|
|
12386
|
+
}
|
|
12387
|
+
}
|
|
12388
|
+
|
|
12389
|
+
//#endregion
|
|
12390
|
+
//#region bin/ssg.ts
|
|
12391
|
+
const TEMP_ENTRY_FILE_NAME = ".xmlui-ssg-entry.tsx";
|
|
12392
|
+
const EXTENSION_FILE_CANDIDATES = [
|
|
12393
|
+
"extensions.ts",
|
|
12394
|
+
"extensions.tsx",
|
|
12395
|
+
"extensions.mts",
|
|
12396
|
+
"extensions.mjs",
|
|
12397
|
+
"extensions.cjs",
|
|
12398
|
+
"extensions.js"
|
|
12399
|
+
];
|
|
12400
|
+
function log(message) {
|
|
12401
|
+
console.log(`[xmlui ssg] ${message}`);
|
|
12402
|
+
}
|
|
12403
|
+
function normalizeRoute(pathname) {
|
|
12404
|
+
let normalized = new URL(pathname, "http://localhost").pathname;
|
|
12405
|
+
if (!normalized.startsWith("/")) normalized = `/${normalized}`;
|
|
12406
|
+
if (normalized !== "/" && normalized.endsWith("/")) normalized = normalized.slice(0, -1);
|
|
12407
|
+
return normalized || "/";
|
|
12408
|
+
}
|
|
12409
|
+
function getOutputHtmlPath(outDir, routePath) {
|
|
12410
|
+
if (routePath === "/") return node_path.default.join(outDir, "index.html");
|
|
12411
|
+
return node_path.default.join(outDir, routePath.slice(1), "index.html");
|
|
12412
|
+
}
|
|
12413
|
+
function executeInlineScripts(html) {
|
|
12414
|
+
const scriptRegex = /<script\b([^>]*)>([\s\S]*?)<\/script>/gi;
|
|
12415
|
+
let match;
|
|
12416
|
+
while ((match = scriptRegex.exec(html)) !== null) {
|
|
12417
|
+
const attrs = match[1] || "";
|
|
12418
|
+
const content = (match[2] || "").trim();
|
|
12419
|
+
if (/\bsrc\s*=/.test(attrs) || !content) continue;
|
|
12420
|
+
try {
|
|
12421
|
+
node_vm.default.runInThisContext(content);
|
|
12422
|
+
} catch (error) {
|
|
12423
|
+
log(`inline script execution warning: ${content.slice(0, 500)}`);
|
|
12424
|
+
console.error(error);
|
|
12425
|
+
}
|
|
12426
|
+
}
|
|
12427
|
+
}
|
|
12428
|
+
function mergeHtmlClasses(shellHtml, htmlClasses) {
|
|
12429
|
+
if (!htmlClasses.trim()) return shellHtml;
|
|
12430
|
+
return shellHtml.replace(/<html([^>]*?)>/i, (full, attributes) => {
|
|
12431
|
+
const classMatch = /class=["']([^"']*)["']/.exec(attributes);
|
|
12432
|
+
if (!classMatch) return `<html${attributes} class="${htmlClasses}">`;
|
|
12433
|
+
const merged = `${classMatch[1].trim()} ${htmlClasses}`.trim();
|
|
12434
|
+
return `<html${attributes.replace(classMatch[0], `class="${merged}"`)}>`;
|
|
12435
|
+
});
|
|
12436
|
+
}
|
|
12437
|
+
function injectStylesIntoHead(shellHtml, ssrStyles, ssrHashes) {
|
|
12438
|
+
if (!ssrStyles.trim()) return shellHtml;
|
|
12439
|
+
const styleTag = `<style data-style-registry="true" data-ssr-hashes="${ssrHashes}">${ssrStyles}</style>`;
|
|
12440
|
+
if (shellHtml.includes("</head>")) return shellHtml.replace("</head>", `${styleTag}</head>`);
|
|
12441
|
+
return `${styleTag}${shellHtml}`;
|
|
12442
|
+
}
|
|
12443
|
+
function injectMarkup(shellHtml, markup) {
|
|
12444
|
+
const rootRegex = /<div([^>]*\bid=["']root["'][^>]*)>[\s\S]*?<\/div>/i;
|
|
12445
|
+
if (rootRegex.test(shellHtml)) return shellHtml.replace(rootRegex, `<div$1>${markup}</div>`);
|
|
12446
|
+
if (shellHtml.includes("</body>")) return shellHtml.replace("</body>", `${markup}</body>`);
|
|
12447
|
+
return `${shellHtml}${markup}`;
|
|
12448
|
+
}
|
|
12449
|
+
function applyRenderToShell(shellHtml, renderResult) {
|
|
12450
|
+
let html = shellHtml;
|
|
12451
|
+
html = mergeHtmlClasses(html, renderResult.htmlClasses);
|
|
12452
|
+
html = injectStylesIntoHead(html, renderResult.ssrStyles, renderResult.ssrHashes);
|
|
12453
|
+
html = injectMarkup(html, renderResult.markup);
|
|
12454
|
+
if (!html.toLowerCase().startsWith("<!doctype")) return `<!DOCTYPE html>${html}`;
|
|
12455
|
+
return html;
|
|
12456
|
+
}
|
|
12457
|
+
function getSsgEntrySource(extensionImportSpecifiers) {
|
|
12458
|
+
return `
|
|
12459
|
+
import React from "react";
|
|
12460
|
+
import { renderToString } from "react-dom/server";
|
|
12461
|
+
import { StaticRouter } from "react-router-dom/server";
|
|
12462
|
+
import {
|
|
12463
|
+
StandaloneApp,
|
|
12464
|
+
StandaloneExtensionManager as ExtMgr,
|
|
12465
|
+
StyleProvider,
|
|
12466
|
+
StyleRegistry,
|
|
12467
|
+
} from "xmlui";
|
|
12468
|
+
|
|
12469
|
+
const runtime = import.meta.glob("./src/**", { eager: true });
|
|
12470
|
+
|
|
12471
|
+
const loadedExtensions: any[] = [];
|
|
12472
|
+
async function loadExtensions() {
|
|
12473
|
+
const extensions: any[] = [];
|
|
12474
|
+
${extensionImportSpecifiers.map((spec, index) => {
|
|
12475
|
+
return ` try {\n const m${index} = await import(${JSON.stringify(spec)});\n extensions.push(m${index}.default ?? m${index});\n } catch (error) {\n console.warn(\"[xmlui ssg] failed to load extension ${spec}\");\n console.error(error);\n }`;
|
|
12476
|
+
}).join("\n")}
|
|
12477
|
+
return extensions;
|
|
12478
|
+
}
|
|
12479
|
+
|
|
12480
|
+
loadedExtensions.push(...(await loadExtensions()));
|
|
12481
|
+
|
|
12482
|
+
function createExtensionManager() {
|
|
12483
|
+
const extensionManager = new ExtMgr();
|
|
12484
|
+
extensionManager.registerExtension(loadedExtensions || []);
|
|
12485
|
+
return extensionManager;
|
|
12486
|
+
}
|
|
12487
|
+
|
|
12488
|
+
export function renderPath(pathname: string) {
|
|
12489
|
+
if (typeof globalThis !== "undefined") {
|
|
12490
|
+
globalThis.location = new URL(pathname, "http://localhost") as unknown as Location;
|
|
12491
|
+
}
|
|
12492
|
+
|
|
12493
|
+
const registry = new StyleRegistry();
|
|
12494
|
+
const app = (
|
|
12495
|
+
<StyleProvider styleRegistry={registry}>
|
|
12496
|
+
<StaticRouter location={pathname}>
|
|
12497
|
+
<StandaloneApp runtime={runtime} extensionManager={createExtensionManager()} />
|
|
12498
|
+
</StaticRouter>
|
|
12499
|
+
</StyleProvider>
|
|
12500
|
+
);
|
|
12501
|
+
|
|
12502
|
+
const markup = renderToString(app);
|
|
12503
|
+
return {
|
|
12504
|
+
markup,
|
|
12505
|
+
ssrStyles: registry.getSsrStyles(),
|
|
12506
|
+
ssrHashes: Array.from(registry.cache.keys()).join(","),
|
|
12507
|
+
htmlClasses: registry.getRootClasses(),
|
|
12508
|
+
};
|
|
12509
|
+
}
|
|
12510
|
+
`;
|
|
12511
|
+
}
|
|
12512
|
+
async function findMonorepoRoot(startDir) {
|
|
12513
|
+
let currentDir = startDir;
|
|
12514
|
+
for (let depth$1 = 0; depth$1 < 12; depth$1++) {
|
|
12515
|
+
const packageJsonPath = node_path.default.join(currentDir, "package.json");
|
|
12516
|
+
if (await pathExists(packageJsonPath)) try {
|
|
12517
|
+
if (JSON.parse(await (0, node_fs_promises.readFile)(packageJsonPath, "utf-8")).workspaces) return currentDir;
|
|
12518
|
+
} catch {}
|
|
12519
|
+
const parent = node_path.default.dirname(currentDir);
|
|
12520
|
+
if (parent === currentDir) break;
|
|
12521
|
+
currentDir = parent;
|
|
12522
|
+
}
|
|
12523
|
+
return null;
|
|
12524
|
+
}
|
|
12525
|
+
async function getWorkspacePatterns(monorepoRoot) {
|
|
12526
|
+
const packageJsonPath = node_path.default.join(monorepoRoot, "package.json");
|
|
12527
|
+
const pkg = JSON.parse(await (0, node_fs_promises.readFile)(packageJsonPath, "utf-8"));
|
|
12528
|
+
if (Array.isArray(pkg.workspaces)) return pkg.workspaces;
|
|
12529
|
+
if (Array.isArray(pkg.workspaces?.packages)) return pkg.workspaces.packages;
|
|
12530
|
+
return [];
|
|
12531
|
+
}
|
|
12532
|
+
async function getExtensionImportSpecifiers(cwd) {
|
|
12533
|
+
for (const fileName of EXTENSION_FILE_CANDIDATES) {
|
|
12534
|
+
const filePath = node_path.default.join(cwd, fileName);
|
|
12535
|
+
if (!await pathExists(filePath)) continue;
|
|
12536
|
+
const matches = (await (0, node_fs_promises.readFile)(filePath, "utf-8")).matchAll(/from\s+["']([^"']+)["']/g);
|
|
12537
|
+
const result = [];
|
|
12538
|
+
for (const match of matches) {
|
|
12539
|
+
const spec = match[1];
|
|
12540
|
+
if (!result.includes(spec)) result.push(spec);
|
|
12541
|
+
}
|
|
12542
|
+
return result;
|
|
12543
|
+
}
|
|
12544
|
+
return [];
|
|
12545
|
+
}
|
|
12546
|
+
async function getWorkspaceExtensionAliases(cwd) {
|
|
12547
|
+
const extensionSpecs = new Set((await getExtensionImportSpecifiers(cwd)).filter((spec) => !spec.startsWith(".") && !spec.startsWith("/")));
|
|
12548
|
+
if (extensionSpecs.size === 0) return {};
|
|
12549
|
+
const monorepoRoot = await findMonorepoRoot(cwd);
|
|
12550
|
+
if (!monorepoRoot) return {};
|
|
12551
|
+
const patterns = await getWorkspacePatterns(monorepoRoot);
|
|
12552
|
+
const aliases = {};
|
|
12553
|
+
for (const pattern of patterns) {
|
|
12554
|
+
if (!pattern.endsWith("/*")) continue;
|
|
12555
|
+
const patternBase = node_path.default.join(monorepoRoot, pattern.slice(0, -2));
|
|
12556
|
+
if (!await pathExists(patternBase)) continue;
|
|
12557
|
+
const entries = await (0, node_fs_promises.readdir)(patternBase, { withFileTypes: true });
|
|
12558
|
+
for (const entry of entries) {
|
|
12559
|
+
if (!entry.isDirectory()) continue;
|
|
12560
|
+
const packageDir = node_path.default.join(patternBase, entry.name);
|
|
12561
|
+
const packageJsonPath = node_path.default.join(packageDir, "package.json");
|
|
12562
|
+
if (!await pathExists(packageJsonPath)) continue;
|
|
12563
|
+
try {
|
|
12564
|
+
const packageName = JSON.parse(await (0, node_fs_promises.readFile)(packageJsonPath, "utf-8")).name;
|
|
12565
|
+
if (!packageName || !extensionSpecs.has(packageName)) continue;
|
|
12566
|
+
const sourceEntryCandidates = [
|
|
12567
|
+
node_path.default.join(packageDir, "src", "index.tsx"),
|
|
12568
|
+
node_path.default.join(packageDir, "src", "index.ts"),
|
|
12569
|
+
node_path.default.join(packageDir, "src", "index.js")
|
|
12570
|
+
];
|
|
12571
|
+
for (const candidate of sourceEntryCandidates) if (await pathExists(candidate)) {
|
|
12572
|
+
aliases[packageName] = candidate;
|
|
12573
|
+
break;
|
|
12574
|
+
}
|
|
12575
|
+
} catch {}
|
|
12576
|
+
}
|
|
12577
|
+
}
|
|
12578
|
+
return aliases;
|
|
12579
|
+
}
|
|
12580
|
+
const ssg = async ({ outDir = "dist-ssg", fallbackFile = "200" } = {}) => {
|
|
12581
|
+
const cwd = process.cwd();
|
|
12582
|
+
const outPath = node_path.default.resolve(cwd, outDir);
|
|
12583
|
+
const distPath = node_path.default.resolve(cwd, "dist");
|
|
12584
|
+
const ssrBuildPath = node_path.default.resolve(cwd, ".xmlui-ssg-ssr");
|
|
12585
|
+
const ssrBundlePath = node_path.default.join(ssrBuildPath, "render.mjs");
|
|
12586
|
+
const builtIndexPath = node_path.default.join(outPath, "index.html");
|
|
12587
|
+
const sourceIndexPath = node_path.default.resolve(cwd, "index.html");
|
|
12588
|
+
const tempEntryPath = node_path.default.resolve(cwd, TEMP_ENTRY_FILE_NAME);
|
|
12589
|
+
log(`starting in ${cwd}`);
|
|
12590
|
+
log(`cleaning output directory ${outPath}`);
|
|
12591
|
+
await (0, node_fs_promises.rm)(outPath, {
|
|
12592
|
+
recursive: true,
|
|
12593
|
+
force: true
|
|
12594
|
+
});
|
|
12595
|
+
await (0, node_fs_promises.mkdir)(outPath, { recursive: true });
|
|
12596
|
+
log("building project assets");
|
|
12597
|
+
await build({
|
|
12598
|
+
buildMode: "INLINE_ALL",
|
|
12599
|
+
withMock: false,
|
|
12600
|
+
withHostingMetaFiles: false,
|
|
12601
|
+
withRelativeRoot: false,
|
|
12602
|
+
flatDist: false
|
|
12603
|
+
});
|
|
12604
|
+
if (!await pathExists(distPath)) throw new Error(`dist folder was not generated: ${distPath}`);
|
|
12605
|
+
log(`copying dist to ${outPath}`);
|
|
12606
|
+
await (0, node_fs_promises.cp)(distPath, outPath, { recursive: true });
|
|
12607
|
+
executeInlineScripts(await (0, node_fs_promises.readFile)(sourceIndexPath, "utf-8"));
|
|
12608
|
+
const shellHtml = await (0, node_fs_promises.readFile)(builtIndexPath, "utf-8");
|
|
12609
|
+
const pathsToRender = (await discoverPaths(cwd)).map(normalizeRoute);
|
|
12610
|
+
const fallbackBaseName = fallbackFile.replace(/\.html$/i, "");
|
|
12611
|
+
const fallbackRoute = normalizeRoute(`/${fallbackBaseName}`);
|
|
12612
|
+
if (pathsToRender.includes(fallbackRoute)) throw new Error(`A discovered page route "${fallbackRoute}" conflicts with the fallback file name "${fallbackBaseName}.html". Use --fallback to specify a different name.`);
|
|
12613
|
+
log(`discovered ${pathsToRender.length} route(s)`);
|
|
12614
|
+
for (const route of pathsToRender) log(`route: ${route}`);
|
|
12615
|
+
const extensionImportSpecifiers = await getExtensionImportSpecifiers(cwd);
|
|
12616
|
+
if (extensionImportSpecifiers.length > 0) log(`detected extensions: ${extensionImportSpecifiers.join(", ")}`);
|
|
12617
|
+
log("creating SSR module");
|
|
12618
|
+
await (0, node_fs_promises.writeFile)(tempEntryPath, getSsgEntrySource(extensionImportSpecifiers), "utf-8");
|
|
12619
|
+
const viteConfig = await getViteConfig({});
|
|
12620
|
+
const extensionAliases = await getWorkspaceExtensionAliases(cwd);
|
|
12621
|
+
if (Object.keys(extensionAliases).length > 0) log(`using workspace extension aliases: ${Object.keys(extensionAliases).join(", ")}`);
|
|
12622
|
+
const existingAlias = viteConfig.resolve?.alias;
|
|
12623
|
+
const mergedAlias = Array.isArray(existingAlias) ? [...existingAlias, ...Object.entries(extensionAliases).map(([find, replacement]) => ({
|
|
12624
|
+
find,
|
|
12625
|
+
replacement
|
|
12626
|
+
}))] : {
|
|
12627
|
+
...existingAlias || {},
|
|
12628
|
+
...extensionAliases
|
|
12629
|
+
};
|
|
12630
|
+
try {
|
|
12631
|
+
log("building SSR module");
|
|
12632
|
+
await (0, node_fs_promises.rm)(ssrBuildPath, {
|
|
12633
|
+
recursive: true,
|
|
12634
|
+
force: true
|
|
12635
|
+
});
|
|
12636
|
+
await (0, vite.build)({
|
|
12637
|
+
...viteConfig,
|
|
12638
|
+
resolve: {
|
|
12639
|
+
...viteConfig.resolve || {},
|
|
12640
|
+
alias: mergedAlias
|
|
12641
|
+
},
|
|
12642
|
+
define: {
|
|
12643
|
+
...viteConfig.define || {},
|
|
12644
|
+
"process.env.VITE_BUILD_MODE": JSON.stringify("INLINE_ALL"),
|
|
12645
|
+
"process.env.VITE_DEV_MODE": false,
|
|
12646
|
+
"process.env.VITE_MOCK_ENABLED": false,
|
|
12647
|
+
"process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV || "production")
|
|
12648
|
+
},
|
|
12649
|
+
build: {
|
|
12650
|
+
...viteConfig.build || {},
|
|
12651
|
+
ssr: tempEntryPath,
|
|
12652
|
+
outDir: ssrBuildPath,
|
|
12653
|
+
emptyOutDir: true,
|
|
12654
|
+
minify: false,
|
|
12655
|
+
rollupOptions: {
|
|
12656
|
+
...viteConfig.build?.rollupOptions || {},
|
|
12657
|
+
input: void 0,
|
|
12658
|
+
output: {
|
|
12659
|
+
...viteConfig.build?.rollupOptions?.output || {},
|
|
12660
|
+
entryFileNames: "render.mjs",
|
|
12661
|
+
inlineDynamicImports: true
|
|
12662
|
+
}
|
|
12663
|
+
}
|
|
12664
|
+
}
|
|
12665
|
+
});
|
|
12666
|
+
if (!await pathExists(ssrBundlePath)) throw new Error(`failed to build SSR bundle: ${ssrBundlePath}`);
|
|
12667
|
+
const renderModule = await import(`${(0, node_url.pathToFileURL)(ssrBundlePath).href}?t=${Date.now()}`);
|
|
12668
|
+
if (!renderModule?.renderPath) throw new Error("failed to load renderPath from temporary SSG entry module");
|
|
12669
|
+
const writePromises = [];
|
|
12670
|
+
for (const route of pathsToRender) {
|
|
12671
|
+
log(`rendering ${route}`);
|
|
12672
|
+
const finalHtml = applyRenderToShell(shellHtml, renderModule.renderPath(route));
|
|
12673
|
+
const outputFile = getOutputHtmlPath(outPath, route);
|
|
12674
|
+
const dir = node_path.default.dirname(outputFile);
|
|
12675
|
+
const writePromise = (async () => {
|
|
12676
|
+
await (0, node_fs_promises.mkdir)(dir, { recursive: true });
|
|
12677
|
+
await (0, node_fs_promises.writeFile)(outputFile, finalHtml, "utf-8");
|
|
12678
|
+
log(`wrote ${outputFile}`);
|
|
12679
|
+
})();
|
|
12680
|
+
writePromises.push(writePromise);
|
|
12681
|
+
}
|
|
12682
|
+
log("waiting for all writes to complete...");
|
|
12683
|
+
await Promise.all(writePromises);
|
|
12684
|
+
const fallbackRendered = renderModule.renderPath(fallbackFile);
|
|
12685
|
+
log(`rendering fallback shell at synthetic route ${fallbackRoute}`);
|
|
12686
|
+
const fallbackHtml = applyRenderToShell(shellHtml, fallbackRendered);
|
|
12687
|
+
const fallbackOutputFile = node_path.default.join(outPath, `${fallbackBaseName}.html`);
|
|
12688
|
+
await (0, node_fs_promises.writeFile)(fallbackOutputFile, fallbackHtml, "utf-8");
|
|
12689
|
+
log(`wrote ${fallbackOutputFile}`);
|
|
12690
|
+
} finally {
|
|
12691
|
+
await (0, node_fs_promises.rm)(tempEntryPath, { force: true });
|
|
12692
|
+
await (0, node_fs_promises.rm)(ssrBuildPath, {
|
|
12693
|
+
recursive: true,
|
|
12694
|
+
force: true
|
|
12695
|
+
});
|
|
12696
|
+
}
|
|
12697
|
+
log(`completed. static files are in ${outPath}`);
|
|
12698
|
+
};
|
|
12699
|
+
|
|
10414
12700
|
//#endregion
|
|
10415
12701
|
//#region bin/build-lib.ts
|
|
10416
12702
|
const buildLib = async ({ watchMode, mode = "production" }) => {
|
|
@@ -10590,6 +12876,22 @@ function getStringArg(arg, defaultValue) {
|
|
|
10590
12876
|
target,
|
|
10591
12877
|
source
|
|
10592
12878
|
});
|
|
12879
|
+
}).command("ssg", "Generate static pages", (yargs$1) => {
|
|
12880
|
+
return yargs$1.option("outDir", {
|
|
12881
|
+
type: "string",
|
|
12882
|
+
default: "dist-ssg",
|
|
12883
|
+
description: "SSG output directory"
|
|
12884
|
+
}).option("fallback", {
|
|
12885
|
+
type: "string",
|
|
12886
|
+
default: "200",
|
|
12887
|
+
description: "Base name for the fallback HTML file served for unknown routes"
|
|
12888
|
+
});
|
|
12889
|
+
}, (argv) => {
|
|
12890
|
+
const { outDir, fallback } = argv;
|
|
12891
|
+
ssg({
|
|
12892
|
+
outDir: getStringArg(outDir, "dist-ssg"),
|
|
12893
|
+
fallbackFile: getStringArg(fallback, "200")
|
|
12894
|
+
});
|
|
10593
12895
|
}).strict().demandCommand(1, "You need to provide a command").help().parse();
|
|
10594
12896
|
|
|
10595
12897
|
//#endregion
|