@wix/himalaya-cli 0.1422.0 → 0.1424.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.mjs +216 -34
- package/guides/himi-json-output.md +1 -1
- package/package.json +2 -2
package/dist/cli.mjs
CHANGED
|
@@ -7715,6 +7715,7 @@ function resolveTranslation(value, catalog3, sourceCatalog) {
|
|
|
7715
7715
|
var BINDING_SIGILS, BINDING_SIGIL_RE, TRANSLATION_PREFIX, TRANSLATION_KEY_RE;
|
|
7716
7716
|
var init_bindings = __esm({
|
|
7717
7717
|
"../../core/ts/src/bindings.ts"() {
|
|
7718
|
+
"use strict";
|
|
7718
7719
|
BINDING_SIGILS = ["service", "flag", "item", "t"];
|
|
7719
7720
|
BINDING_SIGIL_RE = new RegExp(
|
|
7720
7721
|
`^\\$(?:${BINDING_SIGILS.filter((s2) => s2 !== "t").join("|")})\\b|^\\$t:`
|
|
@@ -10165,16 +10166,104 @@ var init_rich_content = __esm({
|
|
|
10165
10166
|
}
|
|
10166
10167
|
});
|
|
10167
10168
|
|
|
10169
|
+
// ../../core/dev-server/src/raw-json-depth.ts
|
|
10170
|
+
function rawJsonDepthFinding(value, limit = RAW_JSON_MAX_DEPTH) {
|
|
10171
|
+
const EXIT = Symbol("exit");
|
|
10172
|
+
const stack = [];
|
|
10173
|
+
const trail = [];
|
|
10174
|
+
const onTrail = /* @__PURE__ */ new Set();
|
|
10175
|
+
let max = 0;
|
|
10176
|
+
let path2;
|
|
10177
|
+
if (value && typeof value === "object") stack.push({ v: value, depth: 1, key: "" });
|
|
10178
|
+
while (stack.length) {
|
|
10179
|
+
const step = stack.pop();
|
|
10180
|
+
if (step === EXIT) {
|
|
10181
|
+
onTrail.delete(trail.pop());
|
|
10182
|
+
trail.pop();
|
|
10183
|
+
continue;
|
|
10184
|
+
}
|
|
10185
|
+
const v2 = step.v;
|
|
10186
|
+
if (onTrail.has(v2)) continue;
|
|
10187
|
+
onTrail.add(v2);
|
|
10188
|
+
trail.push(step.key, v2);
|
|
10189
|
+
stack.push(EXIT);
|
|
10190
|
+
if (step.depth > max) max = step.depth;
|
|
10191
|
+
if (step.depth > limit && path2 === void 0) {
|
|
10192
|
+
let p2 = "$";
|
|
10193
|
+
for (let i2 = 2; i2 < trail.length; i2 += 2) {
|
|
10194
|
+
const k2 = trail[i2];
|
|
10195
|
+
p2 += typeof k2 === "number" ? `[${k2}]` : /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(k2) ? `.${k2}` : `[${JSON.stringify(k2)}]`;
|
|
10196
|
+
}
|
|
10197
|
+
path2 = p2;
|
|
10198
|
+
}
|
|
10199
|
+
if (Array.isArray(v2)) {
|
|
10200
|
+
for (let i2 = v2.length - 1; i2 >= 0; i2--) {
|
|
10201
|
+
const c2 = v2[i2];
|
|
10202
|
+
if (c2 && typeof c2 === "object") stack.push({ v: c2, depth: step.depth + 1, key: i2 });
|
|
10203
|
+
}
|
|
10204
|
+
} else {
|
|
10205
|
+
const keys = Object.keys(v2);
|
|
10206
|
+
for (let i2 = keys.length - 1; i2 >= 0; i2--) {
|
|
10207
|
+
const c2 = v2[keys[i2]];
|
|
10208
|
+
if (c2 && typeof c2 === "object") stack.push({ v: c2, depth: step.depth + 1, key: keys[i2] });
|
|
10209
|
+
}
|
|
10210
|
+
}
|
|
10211
|
+
}
|
|
10212
|
+
if (path2 === void 0) return null;
|
|
10213
|
+
return {
|
|
10214
|
+
measure: "json",
|
|
10215
|
+
path: path2,
|
|
10216
|
+
limit,
|
|
10217
|
+
actual: max,
|
|
10218
|
+
message: `JSON nests ${max} levels deep; the limit is ${limit} (it crosses the limit at ${path2}). Native decoders recurse once per level and iOS refuses JSON nested past 512 \u2014 flatten that value (store it as a flat list or a string) or move it out of the descriptor`
|
|
10219
|
+
};
|
|
10220
|
+
}
|
|
10221
|
+
var RAW_JSON_MAX_DEPTH;
|
|
10222
|
+
var init_raw_json_depth = __esm({
|
|
10223
|
+
"../../core/dev-server/src/raw-json-depth.ts"() {
|
|
10224
|
+
RAW_JSON_MAX_DEPTH = 256;
|
|
10225
|
+
}
|
|
10226
|
+
});
|
|
10227
|
+
|
|
10168
10228
|
// ../../core/dev-server/src/realm-parity.ts
|
|
10169
|
-
function
|
|
10170
|
-
|
|
10171
|
-
|
|
10229
|
+
function allowlistSweepSource(keep = []) {
|
|
10230
|
+
const key2 = [...keep].sort().join(",");
|
|
10231
|
+
let source = sweepSources.get(key2);
|
|
10232
|
+
if (source === void 0) {
|
|
10233
|
+
source = buildSweepSource([.../* @__PURE__ */ new Set([...WORKER_ALLOWLIST, ...keep])].sort());
|
|
10234
|
+
if (sweepSources.size >= 32) sweepSources.clear();
|
|
10235
|
+
sweepSources.set(key2, source);
|
|
10236
|
+
}
|
|
10237
|
+
return source;
|
|
10238
|
+
}
|
|
10239
|
+
function buildSweepSource(allow) {
|
|
10240
|
+
return `(function (allow) {
|
|
10241
|
+
var keep = Object.create(null);
|
|
10242
|
+
for (var i = 0; i < allow.length; i++) keep[allow[i]] = true;
|
|
10243
|
+
for (var o = globalThis; o && o !== Object.prototype; o = Object.getPrototypeOf(o)) {
|
|
10244
|
+
var names = Object.getOwnPropertyNames(o);
|
|
10245
|
+
for (var j = 0; j < names.length; j++) {
|
|
10246
|
+
var n = names[j];
|
|
10247
|
+
if (keep[n] || n === "constructor" || n.indexOf("himi.quickjs.") === 0) continue;
|
|
10248
|
+
try { delete o[n]; } catch (e) { /* non-configurable: leave it */ }
|
|
10249
|
+
}
|
|
10250
|
+
}
|
|
10251
|
+
})(${JSON.stringify(allow)});`;
|
|
10252
|
+
}
|
|
10253
|
+
function explainWithheldError(message, deviceParity) {
|
|
10254
|
+
if (!deviceParity || message.includes(FETCH_ADVICE)) return message;
|
|
10255
|
+
return BARE_FETCH_UNDEFINED.test(message) ? `${message} \u2014 ${FETCH_ADVICE}` : message;
|
|
10172
10256
|
}
|
|
10173
10257
|
function realmInstallsIntl(intl, hide) {
|
|
10174
10258
|
return intl === true && !(hide ?? []).includes("Intl");
|
|
10175
10259
|
}
|
|
10260
|
+
var sweepSources, FETCH_ADVICE, BARE_FETCH_UNDEFINED;
|
|
10176
10261
|
var init_realm_parity = __esm({
|
|
10177
10262
|
"../../core/dev-server/src/realm-parity.ts"() {
|
|
10263
|
+
init_allowlist();
|
|
10264
|
+
sweepSources = /* @__PURE__ */ new Map();
|
|
10265
|
+
FETCH_ADVICE = "`fetch` is not available to a Tier-5 worker (no device has it: iOS's JSContext never did and the Android worker strips it, #4499) \u2014 load data through the sanctioned Wix transport (`@himalaya/wix-*` or `globalThis.himalaya.wixApi.call`).";
|
|
10266
|
+
BARE_FETCH_UNDEFINED = /(?:^|[^.\w$'])'?fetch'? is not (?:defined|a function)\b/;
|
|
10178
10267
|
}
|
|
10179
10268
|
});
|
|
10180
10269
|
|
|
@@ -10204,8 +10293,10 @@ __export(validate_descriptor_core_exports, {
|
|
|
10204
10293
|
NATIVE_NESTED_PROPS: () => NATIVE_NESTED_PROPS,
|
|
10205
10294
|
NATIVE_PROP_ENUMS: () => NATIVE_PROP_ENUMS,
|
|
10206
10295
|
NATIVE_REQUIRED_PROPS: () => NATIVE_REQUIRED_PROPS,
|
|
10296
|
+
RAW_JSON_MAX_DEPTH: () => RAW_JSON_MAX_DEPTH,
|
|
10207
10297
|
SERVICE_ONLY_BINDING_PROPS: () => SERVICE_ONLY_BINDING_PROPS,
|
|
10208
10298
|
WHOLE_VALUE_BINDING: () => WHOLE_VALUE_BINDING,
|
|
10299
|
+
allowlistSweepSource: () => allowlistSweepSource,
|
|
10209
10300
|
bareNestedClass: () => bareNestedClass,
|
|
10210
10301
|
bootBundleWorker: () => bootBundleWorker,
|
|
10211
10302
|
collectServiceBindings: () => collectServiceBindings,
|
|
@@ -10215,6 +10306,7 @@ __export(validate_descriptor_core_exports, {
|
|
|
10215
10306
|
deviceParityWithheldFrom: () => deviceParityWithheldFrom,
|
|
10216
10307
|
dryRunBundle: () => dryRunBundle,
|
|
10217
10308
|
enumFieldNames: () => enumFieldNames,
|
|
10309
|
+
explainWithheldError: () => explainWithheldError,
|
|
10218
10310
|
extractBundleContract: () => extractBundleContract,
|
|
10219
10311
|
extractBundleServices: () => extractBundleServices,
|
|
10220
10312
|
findSkipDerive: () => findSkipDerive,
|
|
@@ -10229,17 +10321,18 @@ __export(validate_descriptor_core_exports, {
|
|
|
10229
10321
|
pathCrossesOpaqueAuthorJson: () => pathCrossesOpaqueAuthorJson,
|
|
10230
10322
|
pathValue: () => pathValue,
|
|
10231
10323
|
pinnedIntrinsicsSource: () => pinnedIntrinsicsSource,
|
|
10324
|
+
rawJsonDepthFinding: () => rawJsonDepthFinding,
|
|
10232
10325
|
realmInstallsIntl: () => realmInstallsIntl,
|
|
10233
10326
|
resolveActionEvaluator: () => resolveActionEvaluator,
|
|
10234
10327
|
resolveBootEvaluator: () => resolveBootEvaluator,
|
|
10235
10328
|
resolveEvaluator: () => resolveEvaluator,
|
|
10329
|
+
screenDepthFindings: () => screenDepthFindings,
|
|
10236
10330
|
serviceOnlyBindingValues: () => serviceOnlyBindingValues,
|
|
10237
10331
|
setActionEvaluator: () => setActionEvaluator,
|
|
10238
10332
|
setBootEvaluator: () => setBootEvaluator,
|
|
10239
10333
|
setDefaultEvaluator: () => setDefaultEvaluator,
|
|
10240
10334
|
topBarFindings: () => topBarFindings,
|
|
10241
10335
|
validateScreenDescriptor: () => validateScreenDescriptor,
|
|
10242
|
-
withheldGlobalsSource: () => withheldGlobalsSource,
|
|
10243
10336
|
workerSubtreeAllowed: () => workerSubtreeAllowed
|
|
10244
10337
|
});
|
|
10245
10338
|
function makeInert() {
|
|
@@ -10637,6 +10730,7 @@ async function bootBundleWorker(bundleJs, opts) {
|
|
|
10637
10730
|
timeoutMs: 2e3 + budgetMs,
|
|
10638
10731
|
filename: "himi-bundle.js",
|
|
10639
10732
|
hide,
|
|
10733
|
+
deviceParity: opts.deviceParity === true,
|
|
10640
10734
|
wixCall: wixApi.call,
|
|
10641
10735
|
dispatch: dispatchHost,
|
|
10642
10736
|
skipLoad: opts.skipLoad === true,
|
|
@@ -10647,13 +10741,13 @@ async function bootBundleWorker(bundleJs, opts) {
|
|
|
10647
10741
|
guestActions = ran.actions;
|
|
10648
10742
|
guestSession = ran.session;
|
|
10649
10743
|
if (ran.error) {
|
|
10650
|
-
errors.push({ service: "(boot)", message: ran.error });
|
|
10744
|
+
errors.push({ service: "(boot)", message: explainWithheldError(ran.error, opts.deviceParity === true) });
|
|
10651
10745
|
}
|
|
10652
10746
|
} else {
|
|
10653
|
-
realm.run(bundleJs, sandbox, { timeoutMs: 2e3, filename: "himi-bundle.js", hide, ...pins });
|
|
10747
|
+
realm.run(bundleJs, sandbox, { timeoutMs: 2e3, filename: "himi-bundle.js", hide, deviceParity: opts.deviceParity === true, ...pins });
|
|
10654
10748
|
}
|
|
10655
10749
|
} catch (err) {
|
|
10656
|
-
errors.push({ service: "(boot)", message: err?.message ?? String(err), ...err?.stack ? { stack: err.stack } : {} });
|
|
10750
|
+
errors.push({ service: "(boot)", message: explainWithheldError(err?.message ?? String(err), opts.deviceParity === true), ...err?.stack ? { stack: err.stack } : {} });
|
|
10657
10751
|
}
|
|
10658
10752
|
const clone = (v2) => {
|
|
10659
10753
|
try {
|
|
@@ -10726,6 +10820,17 @@ async function bootBundleWorker(bundleJs, opts) {
|
|
|
10726
10820
|
delete state._error;
|
|
10727
10821
|
return state;
|
|
10728
10822
|
}
|
|
10823
|
+
const explainActionError = (err) => {
|
|
10824
|
+
if (!(err && typeof err === "object" && typeof err.message === "string")) return;
|
|
10825
|
+
const e2 = err;
|
|
10826
|
+
const explained = explainWithheldError(e2.message, opts.deviceParity === true);
|
|
10827
|
+
if (explained !== e2.message) {
|
|
10828
|
+
try {
|
|
10829
|
+
e2.message = explained;
|
|
10830
|
+
} catch {
|
|
10831
|
+
}
|
|
10832
|
+
}
|
|
10833
|
+
};
|
|
10729
10834
|
const commitActionFailure = (def, err) => {
|
|
10730
10835
|
const prev = def.state;
|
|
10731
10836
|
if (!prev || typeof prev !== "object" || Array.isArray(prev)) return;
|
|
@@ -10756,6 +10861,7 @@ async function bootBundleWorker(bundleJs, opts) {
|
|
|
10756
10861
|
const next = await Promise.race([Promise.resolve(fn2(def.state, ...args)), timeout]);
|
|
10757
10862
|
applyResult(def, next);
|
|
10758
10863
|
} catch (err) {
|
|
10864
|
+
explainActionError(err);
|
|
10759
10865
|
commitActionFailure(def, err);
|
|
10760
10866
|
throw err;
|
|
10761
10867
|
} finally {
|
|
@@ -10771,6 +10877,7 @@ async function bootBundleWorker(bundleJs, opts) {
|
|
|
10771
10877
|
def.state = entry.state;
|
|
10772
10878
|
}
|
|
10773
10879
|
if (entry.error !== void 0) {
|
|
10880
|
+
entry.error = explainWithheldError(entry.error, opts.deviceParity === true);
|
|
10774
10881
|
commitActionFailure(def, entry.error);
|
|
10775
10882
|
if (recordErrors && entry.reportError) errors.push({ service: entry.name, message: entry.error });
|
|
10776
10883
|
continue;
|
|
@@ -11721,6 +11828,10 @@ function bottomSheetFindings(descriptor) {
|
|
|
11721
11828
|
visit(descriptor, "", true);
|
|
11722
11829
|
return out2;
|
|
11723
11830
|
}
|
|
11831
|
+
function screenDepthFindings(descriptor) {
|
|
11832
|
+
const raw = rawJsonDepthFinding(descriptor);
|
|
11833
|
+
return raw ? [raw] : depthBudgetFindings(descriptor);
|
|
11834
|
+
}
|
|
11724
11835
|
function depthBudgetIssues(findings) {
|
|
11725
11836
|
return findings.map((f2) => ({
|
|
11726
11837
|
severity: "error",
|
|
@@ -11966,9 +12077,9 @@ function validateScreenDescriptor(screenId, descriptor, opts = {}) {
|
|
|
11966
12077
|
const issues = [];
|
|
11967
12078
|
const strict = opts.strict ?? false;
|
|
11968
12079
|
const hygiene = strict ? "error" : "warning";
|
|
11969
|
-
const depthFindings =
|
|
12080
|
+
const depthFindings = screenDepthFindings(descriptor);
|
|
11970
12081
|
const depthIssues = depthBudgetIssues(depthFindings);
|
|
11971
|
-
if (depthFindings.some((f2) => f2.measure === "depth" && f2.actual > UNSAFE_TO_RECURSE_DEPTH)) {
|
|
12082
|
+
if (depthFindings.some((f2) => f2.measure === "json" || f2.measure === "depth" && f2.actual > UNSAFE_TO_RECURSE_DEPTH)) {
|
|
11972
12083
|
return { screenId, ok: false, strict, issues: depthIssues, services: [] };
|
|
11973
12084
|
}
|
|
11974
12085
|
const fixture = new FixtureValidator({ tokens: opts.tokens, allowedComponents: opts.allowedComponents });
|
|
@@ -12590,6 +12701,8 @@ var init_validate_descriptor_core = __esm({
|
|
|
12590
12701
|
init_frame_limits();
|
|
12591
12702
|
init_rich_content();
|
|
12592
12703
|
init_worker_subtree();
|
|
12704
|
+
init_raw_json_depth();
|
|
12705
|
+
init_realm_parity();
|
|
12593
12706
|
init_realm_parity();
|
|
12594
12707
|
CRAWL_BLOCKING_PASSES = /* @__PURE__ */ new Set([
|
|
12595
12708
|
// A screen whose bindings do not resolve has no state to crawl.
|
|
@@ -14171,8 +14284,10 @@ __export(validate_descriptor_exports, {
|
|
|
14171
14284
|
NATIVE_NESTED_PROPS: () => NATIVE_NESTED_PROPS,
|
|
14172
14285
|
NATIVE_PROP_ENUMS: () => NATIVE_PROP_ENUMS,
|
|
14173
14286
|
NATIVE_REQUIRED_PROPS: () => NATIVE_REQUIRED_PROPS,
|
|
14287
|
+
RAW_JSON_MAX_DEPTH: () => RAW_JSON_MAX_DEPTH,
|
|
14174
14288
|
SERVICE_ONLY_BINDING_PROPS: () => SERVICE_ONLY_BINDING_PROPS,
|
|
14175
14289
|
WHOLE_VALUE_BINDING: () => WHOLE_VALUE_BINDING,
|
|
14290
|
+
allowlistSweepSource: () => allowlistSweepSource,
|
|
14176
14291
|
appWorkerActionsFor: () => appWorkerActionsFor,
|
|
14177
14292
|
bareNestedClass: () => bareNestedClass,
|
|
14178
14293
|
bootBundleWorker: () => bootBundleWorker,
|
|
@@ -14185,6 +14300,7 @@ __export(validate_descriptor_exports, {
|
|
|
14185
14300
|
discoverNativeActions: () => discoverNativeActions,
|
|
14186
14301
|
dryRunBundle: () => dryRunBundle,
|
|
14187
14302
|
enumFieldNames: () => enumFieldNames,
|
|
14303
|
+
explainWithheldError: () => explainWithheldError,
|
|
14188
14304
|
extractBundleContract: () => extractBundleContract,
|
|
14189
14305
|
extractBundleServices: () => extractBundleServices,
|
|
14190
14306
|
findSkipDerive: () => findSkipDerive,
|
|
@@ -14202,6 +14318,7 @@ __export(validate_descriptor_exports, {
|
|
|
14202
14318
|
pathCrossesOpaqueAuthorJson: () => pathCrossesOpaqueAuthorJson,
|
|
14203
14319
|
pathValue: () => pathValue,
|
|
14204
14320
|
pinnedIntrinsicsSource: () => pinnedIntrinsicsSource,
|
|
14321
|
+
rawJsonDepthFinding: () => rawJsonDepthFinding,
|
|
14205
14322
|
readBuiltBundle: () => readBuiltBundle,
|
|
14206
14323
|
readBuiltBundleMap: () => readBuiltBundleMap,
|
|
14207
14324
|
realmInstallsIntl: () => realmInstallsIntl,
|
|
@@ -14209,13 +14326,13 @@ __export(validate_descriptor_exports, {
|
|
|
14209
14326
|
resolveActionEvaluator: () => resolveActionEvaluator,
|
|
14210
14327
|
resolveBootEvaluator: () => resolveBootEvaluator,
|
|
14211
14328
|
resolveEvaluator: () => resolveEvaluator,
|
|
14329
|
+
screenDepthFindings: () => screenDepthFindings,
|
|
14212
14330
|
serviceOnlyBindingValues: () => serviceOnlyBindingValues,
|
|
14213
14331
|
setActionEvaluator: () => setActionEvaluator,
|
|
14214
14332
|
setBootEvaluator: () => setBootEvaluator,
|
|
14215
14333
|
setDefaultEvaluator: () => setDefaultEvaluator,
|
|
14216
14334
|
topBarFindings: () => topBarFindings,
|
|
14217
14335
|
validateScreenDescriptor: () => validateScreenDescriptor,
|
|
14218
|
-
withheldGlobalsSource: () => withheldGlobalsSource,
|
|
14219
14336
|
workerSubtreeAllowed: () => workerSubtreeAllowed
|
|
14220
14337
|
});
|
|
14221
14338
|
import { readFileSync as readFileSync15, existsSync as existsSync13, readdirSync as readdirSync11 } from "node:fs";
|
|
@@ -14317,8 +14434,9 @@ var init_validate_descriptor = __esm({
|
|
|
14317
14434
|
nodeVmEvaluator = {
|
|
14318
14435
|
run(code, sandbox, opts) {
|
|
14319
14436
|
const context = createContext(sandbox);
|
|
14320
|
-
|
|
14321
|
-
|
|
14437
|
+
if (opts.deviceParity) {
|
|
14438
|
+
runInContext(allowlistSweepSource(Object.keys(sandbox)), context, { filename: "himi-sweep.js" });
|
|
14439
|
+
}
|
|
14322
14440
|
const pins = pinnedIntrinsicsSource(opts);
|
|
14323
14441
|
if (pins) {
|
|
14324
14442
|
const pinned = runInContext(`(${pins})(Date, Math)`, context, { timeout: opts.timeoutMs, filename: "himi-pins.js" });
|
|
@@ -16057,6 +16175,10 @@ ${opts.liveTransport ? ` // Every action completion crosses as a RAW, ordered r
|
|
|
16057
16175
|
// minimum local overlay needed for the worker's own subsequent reads; the host replays these
|
|
16058
16176
|
// records through applyResult, which remains the authoritative merge/directive dialect.
|
|
16059
16177
|
var actionBody = "";
|
|
16178
|
+
// The host bridges, captured into this closure: under deviceParity the closing sweep deletes
|
|
16179
|
+
// them from globalThis, so a bundle cannot call a bridge that exists on no device (#4537).
|
|
16180
|
+
var hostWixCall = globalThis.__himiWixCall;
|
|
16181
|
+
var hostDispatch = globalThis.__himiDispatch;
|
|
16060
16182
|
var isArray = Array.isArray;
|
|
16061
16183
|
var promiseResolve = Promise.resolve.bind(Promise);
|
|
16062
16184
|
var promiseReject = Promise.reject.bind(Promise);
|
|
@@ -16305,7 +16427,7 @@ ${opts.liveTransport ? ` var handle = { getState: function () { return def
|
|
|
16305
16427
|
call: function (method, path, body, headers) {
|
|
16306
16428
|
var raw;
|
|
16307
16429
|
try {
|
|
16308
|
-
raw =
|
|
16430
|
+
raw = hostWixCall(
|
|
16309
16431
|
String(method),
|
|
16310
16432
|
String(path),
|
|
16311
16433
|
stringify(body === undefined ? null : body),
|
|
@@ -16327,7 +16449,7 @@ ${opts.liveTransport ? ` var handle = { getState: function () { return def
|
|
|
16327
16449
|
dispatch: function (action, params) {
|
|
16328
16450
|
var raw;
|
|
16329
16451
|
try {
|
|
16330
|
-
raw =
|
|
16452
|
+
raw = hostDispatch(stringValue(action), stringify(params === undefined ? null : params));
|
|
16331
16453
|
} catch (e) {
|
|
16332
16454
|
return promiseReject(e instanceof Error ? e : new Error(stringValue(e)));
|
|
16333
16455
|
}
|
|
@@ -16456,9 +16578,11 @@ ${opts.clock === void 0 ? "" : opts.freezeDate ? ` globalThis.Date = (${pinnedI
|
|
|
16456
16578
|
return sweepPromise;
|
|
16457
16579
|
},
|
|
16458
16580
|
});` : ""}
|
|
16459
|
-
// LAST,
|
|
16460
|
-
// (
|
|
16461
|
-
|
|
16581
|
+
// LAST, under deviceParity: the realm sweeps its OWN globals against the worker allow-list
|
|
16582
|
+
// (#4537), so nothing the prelude installed (the \`fetch\` stub), nothing the engine carries
|
|
16583
|
+
// natively (QuickJS-ng 0.15's \`performance\`, \`queueMicrotask\`) and none of the host bridges
|
|
16584
|
+
// (\`__himiWixCall\`, \`__himiDispatch\` \u2014 captured into this closure above) survives.
|
|
16585
|
+
${opts.deviceParity ? allowlistSweepSource() : ""}
|
|
16462
16586
|
return ${opts.liveTransport ? "{ readback: readback, dispatch: dispatchAction, actions: readActions }" : "readback"};
|
|
16463
16587
|
})();
|
|
16464
16588
|
`;
|
|
@@ -16527,6 +16651,7 @@ async function createQuickJsEvaluator(options = {}) {
|
|
|
16527
16651
|
clock: opts.clock ?? options.clock,
|
|
16528
16652
|
freezeDate: opts.clock !== void 0,
|
|
16529
16653
|
hide: opts.hide,
|
|
16654
|
+
deviceParity: opts.deviceParity === true,
|
|
16530
16655
|
...opts.seed === void 0 ? {} : { seed: opts.seed },
|
|
16531
16656
|
...opts.mirrorRandom ? { mirrorRandom: true } : {}
|
|
16532
16657
|
}),
|
|
@@ -130765,6 +130890,10 @@ function composeStickyTree(payload, header, footer) {
|
|
|
130765
130890
|
}
|
|
130766
130891
|
async function renderDescriptorWeb(descriptor, tokens2, scheme, wantPng, services = null, width, isRTL, idiomContext) {
|
|
130767
130892
|
const desc = descriptor;
|
|
130893
|
+
const tooDeep = rawJsonDepthFinding(descriptor);
|
|
130894
|
+
if (tooDeep) return { renderable: false, reason: `depth_budget_exceeded: ${tooDeep.message}` };
|
|
130895
|
+
const tooDeepState = services ? rawJsonDepthFinding(services) : null;
|
|
130896
|
+
if (tooDeepState) return { renderable: false, reason: `depth_budget_exceeded: worker state \u2014 ${tooDeepState.message}` };
|
|
130768
130897
|
const payload = desc.payload;
|
|
130769
130898
|
if (!payload || typeof payload !== "object" || !payload.body) {
|
|
130770
130899
|
const renderer = desc.renderer ?? "unknown";
|
|
@@ -130932,6 +131061,7 @@ var init_render_descriptor = __esm({
|
|
|
130932
131061
|
init_FakeServiceProvider();
|
|
130933
131062
|
init_env();
|
|
130934
131063
|
init_media_value();
|
|
131064
|
+
init_raw_json_depth();
|
|
130935
131065
|
init_message_format();
|
|
130936
131066
|
init_a11y_contract();
|
|
130937
131067
|
A11Y_MODIFIER_KEYS = [
|
|
@@ -132515,15 +132645,22 @@ async function handleBootRequest(req, res, state) {
|
|
|
132515
132645
|
const tokenDocument = effectiveAppTokens(req, state);
|
|
132516
132646
|
const homeScreenId = config.homeScreenId ?? state.app.meta.homeScreenId ?? null;
|
|
132517
132647
|
let screen = null;
|
|
132648
|
+
let homeScreenRefusal;
|
|
132518
132649
|
if (homeScreenId) {
|
|
132519
132650
|
const evalCtx = evalContextFromReq(req, state.appName);
|
|
132520
132651
|
const caller = await resolveCaller(state.app.module, req);
|
|
132521
|
-
|
|
132522
|
-
|
|
132523
|
-
|
|
132524
|
-
|
|
132525
|
-
|
|
132526
|
-
|
|
132652
|
+
let descriptor = null;
|
|
132653
|
+
try {
|
|
132654
|
+
descriptor = await buildDescriptorForScreenId(
|
|
132655
|
+
reqState,
|
|
132656
|
+
homeScreenId,
|
|
132657
|
+
new URLSearchParams(),
|
|
132658
|
+
{ ctx: evalCtx, caller }
|
|
132659
|
+
);
|
|
132660
|
+
} catch (err) {
|
|
132661
|
+
if (!(err instanceof DescriptorDepthRefusal)) throw err;
|
|
132662
|
+
homeScreenRefusal = { error: "depth_budget_exceeded", screenId: err.screenId, finding: err.finding };
|
|
132663
|
+
}
|
|
132527
132664
|
if (descriptor && typeof descriptor === "object") {
|
|
132528
132665
|
assignStableIds(descriptor);
|
|
132529
132666
|
const acceptLanguage = req.headers["accept-language"];
|
|
@@ -132540,7 +132677,8 @@ async function handleBootRequest(req, res, state) {
|
|
|
132540
132677
|
tokens: tokenDocument?.tokens ?? null,
|
|
132541
132678
|
homeScreenId,
|
|
132542
132679
|
screen,
|
|
132543
|
-
homeBundle: null
|
|
132680
|
+
homeBundle: null,
|
|
132681
|
+
...homeScreenRefusal ? { screenRefusal: homeScreenRefusal } : {}
|
|
132544
132682
|
};
|
|
132545
132683
|
const body = JSON.stringify(payload);
|
|
132546
132684
|
const etag = makeEtag(body);
|
|
@@ -132738,10 +132876,15 @@ function descriptorCacheKey(reqBaseUrl, localeKey, flagKey, caller) {
|
|
|
132738
132876
|
const who = caller.memberId ? `::mid=${caller.memberId}` : "";
|
|
132739
132877
|
return `${reqBaseUrl}::${localeKey}::${flagKey}::ent=${caller.entitled ? 1 : 0}${who}`;
|
|
132740
132878
|
}
|
|
132879
|
+
function refuseTooDeep(screenId, descriptor) {
|
|
132880
|
+
const finding = rawJsonDepthFinding(descriptor);
|
|
132881
|
+
if (finding) throw new DescriptorDepthRefusal(screenId, finding);
|
|
132882
|
+
return descriptor;
|
|
132883
|
+
}
|
|
132741
132884
|
async function buildDescriptorForScreenId(state, screenId, query = new URLSearchParams(), options = {}) {
|
|
132742
132885
|
if (!options.skipOverride) {
|
|
132743
132886
|
const preview = state.localOverrides.get(screenId);
|
|
132744
|
-
if (preview) return { ...preview, screenId };
|
|
132887
|
+
if (preview) return refuseTooDeep(screenId, { ...preview, screenId });
|
|
132745
132888
|
}
|
|
132746
132889
|
if (state.app) {
|
|
132747
132890
|
await state.flagSync.refresh(state.app?.dir, state.flagStore, Date.now());
|
|
@@ -132767,7 +132910,7 @@ async function buildDescriptorForScreenId(state, screenId, query = new URLSearch
|
|
|
132767
132910
|
}
|
|
132768
132911
|
return null;
|
|
132769
132912
|
})();
|
|
132770
|
-
return built ? postprocessDescriptor(built, {
|
|
132913
|
+
return built ? postprocessDescriptor(refuseTooDeep(screenId, built), {
|
|
132771
132914
|
config: uiConfig(state.app.module.config),
|
|
132772
132915
|
flagDefinitions: state.flagStore.list(),
|
|
132773
132916
|
evalContext: evalCtx,
|
|
@@ -135488,6 +135631,9 @@ function createDevServer(opts = {}) {
|
|
|
135488
135631
|
send(res, 404, "not found");
|
|
135489
135632
|
} catch (err) {
|
|
135490
135633
|
console.error("[himalaya-dev] handler error:", err);
|
|
135634
|
+
if (err instanceof DescriptorDepthRefusal) {
|
|
135635
|
+
return sendJson(res, 422, { error: "depth_budget_exceeded", screenId: err.screenId, finding: err.finding });
|
|
135636
|
+
}
|
|
135491
135637
|
if (isContainedCapabilityRefusal(err)) {
|
|
135492
135638
|
return sendJson(res, 422, {
|
|
135493
135639
|
error: "contained_capability_refused",
|
|
@@ -135539,7 +135685,7 @@ ${err.message}`);
|
|
|
135539
135685
|
});
|
|
135540
135686
|
return httpServer;
|
|
135541
135687
|
}
|
|
135542
|
-
var ROOT6, TIER3_ROOT, TIER4_ROOT, tier4Verifier, TIER5_ROOT2, ACTION_HANDLERS_ROOT, SAMPLES_ROOT, TELEMETRY_BUFFER_CAP, overrideHistorySeq, CACHE_CONTROL, TIER5_SRC_ROOT, HMR_TMP_DIR, appReloadSeq, appReloadChain, WEBWIX_CLIENT_ID, WEBWIX_REDIRECT, WEBWIX_COOKIE, webOwnerPreviewInstances, webAccountMemberInstances, MIME, widgetOverrides;
|
|
135688
|
+
var ROOT6, TIER3_ROOT, TIER4_ROOT, tier4Verifier, TIER5_ROOT2, ACTION_HANDLERS_ROOT, SAMPLES_ROOT, TELEMETRY_BUFFER_CAP, overrideHistorySeq, CACHE_CONTROL, DescriptorDepthRefusal, TIER5_SRC_ROOT, HMR_TMP_DIR, appReloadSeq, appReloadChain, WEBWIX_CLIENT_ID, WEBWIX_REDIRECT, WEBWIX_COOKIE, webOwnerPreviewInstances, webAccountMemberInstances, MIME, widgetOverrides;
|
|
135543
135689
|
var init_src6 = __esm({
|
|
135544
135690
|
"../../core/dev-server/src/index.ts"() {
|
|
135545
135691
|
init_inject();
|
|
@@ -135568,6 +135714,7 @@ var init_src6 = __esm({
|
|
|
135568
135714
|
init_player_proxy();
|
|
135569
135715
|
init_app_icon();
|
|
135570
135716
|
init_app_assets();
|
|
135717
|
+
init_raw_json_depth();
|
|
135571
135718
|
init_app_module();
|
|
135572
135719
|
init_provisioning_facts();
|
|
135573
135720
|
init_validate();
|
|
@@ -135594,6 +135741,14 @@ var init_src6 = __esm({
|
|
|
135594
135741
|
TELEMETRY_BUFFER_CAP = 1e3;
|
|
135595
135742
|
overrideHistorySeq = 0;
|
|
135596
135743
|
CACHE_CONTROL = "max-age=600, stale-while-revalidate=86400";
|
|
135744
|
+
DescriptorDepthRefusal = class extends Error {
|
|
135745
|
+
constructor(screenId, finding) {
|
|
135746
|
+
super(finding.message);
|
|
135747
|
+
this.screenId = screenId;
|
|
135748
|
+
this.finding = finding;
|
|
135749
|
+
this.name = "DescriptorDepthRefusal";
|
|
135750
|
+
}
|
|
135751
|
+
};
|
|
135597
135752
|
TIER5_SRC_ROOT = resolve38(ROOT6, "core/dev-server/tier5-bundles-src");
|
|
135598
135753
|
HMR_TMP_DIR = resolve38(ROOT6, "node_modules/.cache/himalaya-hmr");
|
|
135599
135754
|
appReloadSeq = 0;
|
|
@@ -139631,11 +139786,33 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
139631
139786
|
base = BAKE_OFFLINE_BASE;
|
|
139632
139787
|
}
|
|
139633
139788
|
const devFetch = (url, init) => dev.inject(new Request(url, init));
|
|
139789
|
+
const depthRefusalFromText = (status, text9) => {
|
|
139790
|
+
if (status !== 422) return null;
|
|
139791
|
+
try {
|
|
139792
|
+
const body = JSON.parse(text9);
|
|
139793
|
+
return body?.error === "depth_budget_exceeded" && body.finding ? body.finding : null;
|
|
139794
|
+
} catch {
|
|
139795
|
+
return null;
|
|
139796
|
+
}
|
|
139797
|
+
};
|
|
139798
|
+
const depthRefusalOf = async (res) => depthRefusalFromText(res.status, await res.text());
|
|
139799
|
+
const recordUnbuilt = async (screenId, res) => {
|
|
139800
|
+
const text9 = await res.text();
|
|
139801
|
+
const finding = depthRefusalFromText(res.status, text9);
|
|
139802
|
+
if (finding) {
|
|
139803
|
+
failedToBuild.push({ screenId, status: res.status, error: finding.message });
|
|
139804
|
+
if (collect2?.lint && !lint.some((l2) => l2.screenId === screenId)) {
|
|
139805
|
+
lint.push({ screenId, ok: false, issues: depthBudgetIssues([finding]) });
|
|
139806
|
+
}
|
|
139807
|
+
return;
|
|
139808
|
+
}
|
|
139809
|
+
failedToBuild.push({ screenId, status: res.status, error: text9.slice(0, 2e3) });
|
|
139810
|
+
};
|
|
139634
139811
|
try {
|
|
139635
139812
|
for (const screenId of screenIds) {
|
|
139636
139813
|
const res = await devFetch(`${base}/v1/screen/${screenId}`, { headers: { "X-Himalaya-App": app } });
|
|
139637
139814
|
if (!res.ok) {
|
|
139638
|
-
|
|
139815
|
+
await recordUnbuilt(screenId, res);
|
|
139639
139816
|
continue;
|
|
139640
139817
|
}
|
|
139641
139818
|
const descriptor = await res.json();
|
|
@@ -139728,6 +139905,10 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
139728
139905
|
const { services, liveCalls, liveReturned, liveErrors, mockCalls, mockUnserved, mockBootFailed, liveFailed } = await renderServicesFor(bundleName, descriptor, wantedRender);
|
|
139729
139906
|
const rr2 = await renderDescriptorWeb(descriptor, renderTokens, renderScheme, collect2.render.png === true, services, collect2.render.width, collect2.render.rtl === true);
|
|
139730
139907
|
renders.push({ screenId: wantedRender, scheme: renderScheme, ...rr2, ...await renderCompare(descriptor, services), ...collect2.render.dumpState && services ? { serviceState: services } : {}, ...liveCalls ? { liveCalls } : {}, ...liveReturned !== void 0 ? { liveReturned } : {}, ...liveFailed ? { liveFailed } : {}, ...liveErrors ? { liveErrors } : {}, ...mockCalls ? { mockCalls, mockUnserved } : {}, ...mockBootFailed ? { mockBootFailed } : {} });
|
|
139908
|
+
} else if (res.status === 422 && collect2?.lint) {
|
|
139909
|
+
const finding = await depthRefusalOf(res);
|
|
139910
|
+
const recorded = lint.some((l2) => l2.screenId === wantedRender) || failedToBuild.some((f2) => f2.screenId === wantedRender);
|
|
139911
|
+
if (finding && !recorded) lint.push({ screenId: wantedRender, ok: false, issues: depthBudgetIssues([finding]) });
|
|
139731
139912
|
}
|
|
139732
139913
|
}
|
|
139733
139914
|
for (const t2 of preloaded.module.screens.templated ?? []) {
|
|
@@ -139782,7 +139963,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
|
|
|
139782
139963
|
if (screenId.includes("/") || screenId.includes("..")) continue;
|
|
139783
139964
|
const res = await devFetch(`${base}/v1/screen/${encodeURIComponent(screenId)}`, { headers: { "X-Himalaya-App": app } });
|
|
139784
139965
|
if (!res.ok) {
|
|
139785
|
-
|
|
139966
|
+
await recordUnbuilt(screenId, res);
|
|
139786
139967
|
continue;
|
|
139787
139968
|
}
|
|
139788
139969
|
const descriptor = await res.json();
|
|
@@ -180791,7 +180972,7 @@ var NONDETERMINISTIC_FIX = "move those clock or random values out of the service
|
|
|
180791
180972
|
function depthBudgetExceeded(report3) {
|
|
180792
180973
|
return (report3.issues ?? []).some((i2) => i2.severity === "error" && i2.pass === "depth-budget");
|
|
180793
180974
|
}
|
|
180794
|
-
var DEPTH_BUDGET_HINT = "a screen or row template
|
|
180975
|
+
var DEPTH_BUDGET_HINT = "a screen or row template nests too many components, or JSON in its props, modifiers, `input` or action `args` nests past the 256-level ceiling (see the depth-budget issues' path and limit) \u2014 flatten it; `--force` does not override this";
|
|
180795
180976
|
function summarizeLint(app, bres, outcome, strict, extraIssues = []) {
|
|
180796
180977
|
const issues = (outcome.lint ?? []).flatMap((s2) => s2.issues.map((i2) => ({ screen: s2.screenId, ...i2 })));
|
|
180797
180978
|
issues.push(...extraIssues);
|
|
@@ -186198,7 +186379,8 @@ ${[...afterRun.next, ...testReminder ? [testReminder] : []].join("\n")}`);
|
|
|
186198
186379
|
});
|
|
186199
186380
|
const r2 = (outcome.renders ?? [])[0];
|
|
186200
186381
|
if (!r2) {
|
|
186201
|
-
|
|
186382
|
+
const why = (outcome.lint ?? []).find((s2) => s2.screenId === screenId)?.issues ?? [];
|
|
186383
|
+
print({ ok: false, screenId, error: "screen not found or did not build", failedToBuild: outcome.failedToBuild, ...why.length ? { issues: why.map((i2) => ({ screen: screenId, ...i2 })) } : {} });
|
|
186202
186384
|
return 1;
|
|
186203
186385
|
}
|
|
186204
186386
|
const diagnostics = (outcome.lint ?? []).find((s2) => s2.screenId === screenId)?.issues ?? [];
|
|
@@ -188449,8 +188631,8 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
188449
188631
|
io2.error(JSON.stringify({ ok: false, error: "invalid_descriptor", file: file2, screen: id, message: `${file2} is not valid JSON: ${e2.message}` }));
|
|
188450
188632
|
return 1;
|
|
188451
188633
|
}
|
|
188452
|
-
const {
|
|
188453
|
-
const tooDeep = depthBudgetIssues2(
|
|
188634
|
+
const { screenDepthFindings: screenDepthFindings2, depthBudgetIssues: depthBudgetIssues2 } = await Promise.resolve().then(() => (init_validate_descriptor_core(), validate_descriptor_core_exports));
|
|
188635
|
+
const tooDeep = depthBudgetIssues2(screenDepthFindings2(parsed));
|
|
188454
188636
|
if (tooDeep.length > 0) {
|
|
188455
188637
|
io2.error(JSON.stringify({
|
|
188456
188638
|
ok: false,
|
|
@@ -188461,7 +188643,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
188461
188643
|
screen: id,
|
|
188462
188644
|
file: file2,
|
|
188463
188645
|
issues: tooDeep,
|
|
188464
|
-
hint:
|
|
188646
|
+
hint: DEPTH_BUDGET_HINT
|
|
188465
188647
|
}, null, 2));
|
|
188466
188648
|
return 1;
|
|
188467
188649
|
}
|
|
@@ -47,7 +47,7 @@ keeps its existing fields and adds the code:
|
|
|
47
47
|
| `ux_evidence_inherited_screens` | A partial push inherits screens not covered by local UX evidence. |
|
|
48
48
|
| `ux_evidence_unreadable` | The UX evidence artifact cannot be read. |
|
|
49
49
|
| `lint_errors` | Build/lint validation found errors. |
|
|
50
|
-
| `depth_budget_exceeded` | A screen or a bound list/grid row template nests deeper, or has more components, than the depth budget (`depth-budget` validator pass). Each `issues[]` entry with `pass: "depth-budget"` carries the JSON `path` of the deepest node (
|
|
50
|
+
| `depth_budget_exceeded` | A screen or a bound list/grid row template nests deeper, or has more components, than the depth budget (`depth-budget` validator pass), or any of its JSON — props, modifiers, `input`, action `args` — nests past the raw-JSON ceiling of 256 levels. Each `issues[]` entry with `pass: "depth-budget"` carries the JSON `path` of the deepest node (the tree root for a node count, the first value past the ceiling for raw JSON), the `limit` and the `actual` value. Takes precedence over `lint_errors`, and `--force` does not override it: content over the budget overflows the renderer's stack on devices already in the field. Flatten the layout and push again. `himi patch screen` refuses an over-deep raw descriptor with the same code, before any network request, and `himi pack` / `himi template publish` refuse with it even under `--force`. |
|
|
51
51
|
| `control_token_expired` | The selected control token has expired. |
|
|
52
52
|
| `app_source_contains_secrets` | Source archiving detected a possible credential. |
|
|
53
53
|
| `app_source_too_large` | The encoded source archive exceeds its limit. |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/himalaya-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1424.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "himi — the Himalaya authoring CLI. Build a Tier-5 content package on your own machine, push it to the production serve as a draft, preview it on web + Himi Player, and read worker logs back — the remote dev loop. Wraps @himalaya/serve-cli for transport.",
|
|
6
6
|
"keywords": [
|
|
@@ -71,5 +71,5 @@
|
|
|
71
71
|
"artifactId": "himalaya-cli"
|
|
72
72
|
}
|
|
73
73
|
},
|
|
74
|
-
"falconPackageHash": "
|
|
74
|
+
"falconPackageHash": "a0147b33ea7375fa7cf11b0027a0388feef592ede284346c3d5c9919"
|
|
75
75
|
}
|