tutuca 0.9.92 → 0.9.94
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/tutuca-cli.js +310 -60
- package/dist/tutuca-dev.ext.js +1431 -1196
- package/dist/tutuca-dev.js +1431 -1196
- package/dist/tutuca-dev.min.js +3 -2
- package/dist/tutuca-extra.ext.js +186 -52
- package/dist/tutuca-extra.js +187 -53
- package/dist/tutuca-extra.min.js +1 -1
- package/dist/tutuca-storybook.js +69 -11
- package/dist/tutuca.ext.js +186 -52
- package/dist/tutuca.js +187 -53
- package/dist/tutuca.min.js +1 -1
- package/package.json +2 -1
- package/skill/tutuca/core.md +26 -0
- package/skill/tutuca/storybook.md +46 -0
- package/skill/tutuca/testing.md +33 -0
- package/skill/tutuca-source/tutuca.ext.js +186 -52
package/dist/tutuca-cli.js
CHANGED
|
@@ -12963,6 +12963,7 @@ function checkComponent(Comp, lx = new LintContext, { wellKnownExtras = EMPTY_SE
|
|
|
12963
12963
|
checkProvidesAreAddressable(lx, Comp);
|
|
12964
12964
|
checkLookupShapes(lx, Comp);
|
|
12965
12965
|
checkHandlersNotAsync(lx, Comp);
|
|
12966
|
+
checkScopedStyleTopLevel(lx, Comp);
|
|
12966
12967
|
const referencedAlters = new Set;
|
|
12967
12968
|
const referencedInputs = new Set;
|
|
12968
12969
|
const referencedDynamics = new Set;
|
|
@@ -13376,6 +13377,64 @@ function checkHandlersNotAsync(lx, Comp) {
|
|
|
13376
13377
|
}
|
|
13377
13378
|
}
|
|
13378
13379
|
}
|
|
13380
|
+
function blankCssNoise(css) {
|
|
13381
|
+
return css.replace(/\/\*[\s\S]*?\*\//g, blankRun).replace(/"(?:[^"\\\n]|\\.)*"/g, blankRun).replace(/'(?:[^'\\\n]|\\.)*'/g, blankRun);
|
|
13382
|
+
}
|
|
13383
|
+
function offsetToLineCol2(str, index) {
|
|
13384
|
+
let line = 1;
|
|
13385
|
+
let lineStart = 0;
|
|
13386
|
+
for (let i = 0;i < index; i++) {
|
|
13387
|
+
if (str[i] === `
|
|
13388
|
+
`) {
|
|
13389
|
+
line++;
|
|
13390
|
+
lineStart = i + 1;
|
|
13391
|
+
}
|
|
13392
|
+
}
|
|
13393
|
+
return { line, column: index - lineStart + 1 };
|
|
13394
|
+
}
|
|
13395
|
+
function suppressedLines(css) {
|
|
13396
|
+
const lines = new Set;
|
|
13397
|
+
IGNORE_DIRECTIVE.lastIndex = 0;
|
|
13398
|
+
for (let m = IGNORE_DIRECTIVE.exec(css);m !== null; m = IGNORE_DIRECTIVE.exec(css)) {
|
|
13399
|
+
lines.add(offsetToLineCol2(css, m.index).line);
|
|
13400
|
+
}
|
|
13401
|
+
return lines;
|
|
13402
|
+
}
|
|
13403
|
+
function scanScopedCss(lx, css, key) {
|
|
13404
|
+
if (!css)
|
|
13405
|
+
return;
|
|
13406
|
+
const ignore = suppressedLines(css);
|
|
13407
|
+
const clean = blankCssNoise(css);
|
|
13408
|
+
const report = (id, info) => {
|
|
13409
|
+
if (ignore.has(info.location.line))
|
|
13410
|
+
return;
|
|
13411
|
+
lx.error(id, { key, ...info }, { kind: "rephrase", text: STYLE_TO_GLOBAL_HELP });
|
|
13412
|
+
};
|
|
13413
|
+
NON_NESTABLE_AT_RULE.lastIndex = 0;
|
|
13414
|
+
for (let m = NON_NESTABLE_AT_RULE.exec(clean);m !== null; m = NON_NESTABLE_AT_RULE.exec(clean)) {
|
|
13415
|
+
const at = m.index + m[0].indexOf("@");
|
|
13416
|
+
report(TOP_LEVEL_AT_RULE_IN_SCOPED_STYLE, {
|
|
13417
|
+
atRule: m[1].toLowerCase(),
|
|
13418
|
+
location: offsetToLineCol2(clean, at)
|
|
13419
|
+
});
|
|
13420
|
+
}
|
|
13421
|
+
GLOBAL_LEADING_SELECTOR.lastIndex = 0;
|
|
13422
|
+
for (let m = GLOBAL_LEADING_SELECTOR.exec(clean);m !== null; m = GLOBAL_LEADING_SELECTOR.exec(clean)) {
|
|
13423
|
+
const at = m.index + m[0].indexOf(m[1]);
|
|
13424
|
+
report(GLOBAL_SELECTOR_IN_SCOPED_STYLE, {
|
|
13425
|
+
selector: m[1].toLowerCase(),
|
|
13426
|
+
location: offsetToLineCol2(clean, at)
|
|
13427
|
+
});
|
|
13428
|
+
}
|
|
13429
|
+
}
|
|
13430
|
+
function checkScopedStyleTopLevel(lx, Comp) {
|
|
13431
|
+
scanScopedCss(lx, Comp.commonStyle, "commonStyle");
|
|
13432
|
+
for (const name in Comp.views) {
|
|
13433
|
+
const { style } = Comp.views[name];
|
|
13434
|
+
if (style)
|
|
13435
|
+
lx.push({ viewName: name }, () => scanScopedCss(lx, style, "style"));
|
|
13436
|
+
}
|
|
13437
|
+
}
|
|
13379
13438
|
function checkProvidesAreAddressable(lx, Comp) {
|
|
13380
13439
|
for (const name in Comp._rawProvide) {
|
|
13381
13440
|
if (Comp.provide[name] === undefined) {
|
|
@@ -13452,7 +13511,7 @@ class LintContext {
|
|
|
13452
13511
|
this.reports.push({ id, info, level, context: { ...this.frame }, suggestion });
|
|
13453
13512
|
}
|
|
13454
13513
|
}
|
|
13455
|
-
var KNOWN_COMPONENT_SPEC_KEYS, EMPTY_SET2, FRAMEWORK_WELL_KNOWN_EXTRAS, KNOWN_DIRECTIVE_NAMES, ALT_HANDLER_NOT_DEFINED = "ALT_HANDLER_NOT_DEFINED", ALT_HANDLER_NOT_REFERENCED = "ALT_HANDLER_NOT_REFERENCED", DYN_VAL_NOT_DEFINED = "DYN_VAL_NOT_DEFINED", DYN_ALIAS_NOT_REFERENCED = "DYN_ALIAS_NOT_REFERENCED", PROVIDE_NOT_ADDRESSABLE = "PROVIDE_NOT_ADDRESSABLE", LOOKUP_BAD_SHAPE = "LOOKUP_BAD_SHAPE", LOOKUP_TARGET_MALFORMED = "LOOKUP_TARGET_MALFORMED", RENDER_IT_OUTSIDE_OF_LOOP = "RENDER_IT_OUTSIDE_OF_LOOP", UNKNOWN_EVENT_MODIFIER = "UNKNOWN_EVENT_MODIFIER", UNKNOWN_HANDLER_ARG_NAME = "UNKNOWN_HANDLER_ARG_NAME", INPUT_HANDLER_NOT_IMPLEMENTED = "INPUT_HANDLER_NOT_IMPLEMENTED", INPUT_HANDLER_NOT_REFERENCED = "INPUT_HANDLER_NOT_REFERENCED", INPUT_HANDLER_METHOD_NOT_IMPLEMENTED = "INPUT_HANDLER_METHOD_NOT_IMPLEMENTED", INPUT_HANDLER_FOR_INPUT_HANDLER_METHOD = "INPUT_HANDLER_FOR_INPUT_HANDLER_METHOD", INPUT_HANDLER_METHOD_FOR_INPUT_HANDLER = "INPUT_HANDLER_METHOD_FOR_INPUT_HANDLER", FIELD_VAL_NOT_DEFINED = "FIELD_VAL_NOT_DEFINED", FIELD_VAL_IS_METHOD = "FIELD_VAL_IS_METHOD", METHOD_VAL_NOT_DEFINED = "METHOD_VAL_NOT_DEFINED", METHOD_VAL_IS_FIELD = "METHOD_VAL_IS_FIELD", DUPLICATE_ATTR_DEFINITION = "DUPLICATE_ATTR_DEFINITION", IF_NO_BRANCH_SET = "IF_NO_BRANCH_SET", UNKNOWN_REQUEST_NAME = "UNKNOWN_REQUEST_NAME", UNKNOWN_COMPONENT_NAME = "UNKNOWN_COMPONENT_NAME", UNKNOWN_MACRO_ARG = "UNKNOWN_MACRO_ARG", UNKNOWN_DIRECTIVE = "UNKNOWN_DIRECTIVE", UNKNOWN_X_OP = "UNKNOWN_X_OP", UNKNOWN_X_ATTR = "UNKNOWN_X_ATTR", MAYBE_DROP_AT_PREFIX = "MAYBE_DROP_AT_PREFIX", MAYBE_ADD_AT_PREFIX = "MAYBE_ADD_AT_PREFIX", BAD_VALUE = "BAD_VALUE", UNSUPPORTED_EXPR_SYNTAX = "UNSUPPORTED_EXPR_SYNTAX", REDUNDANT_TEMPLATE_STRING = "REDUNDANT_TEMPLATE_STRING", PLACEHOLDERLESS_TEMPLATE_STRING = "PLACEHOLDERLESS_TEMPLATE_STRING", UNKNOWN_COMPONENT_SPEC_KEY = "UNKNOWN_COMPONENT_SPEC_KEY", COMP_FIELD_BAD_SHAPE = "COMP_FIELD_BAD_SHAPE", ASYNC_HANDLER = "ASYNC_HANDLER", X_KNOWN_OP_NAMES, X_KNOWN_ATTR_NAMES, HOST_DIRECTIVE_ONLY_NAMES, LEVEL_WARN2 = "warn", LEVEL_ERROR2 = "error", LEVEL_HINT = "hint", PARSE_ISSUES, UNSUPPORTED_EXPR_GUIDANCE, HTML_LINT_OPTS, NO_WRAPPERS, KNOWN_HANDLER_NAMES, fixTo = (from, to) => ({ kind: "rewrite", from, to }), ATTR_VAL_CHECKERS, NODE_KIND_TO_CTX, HANDLER_CHANNELS, ASYNC_HANDLER_HELP, KNOWN_LOOKUP_KEYS, LintParseContext;
|
|
13514
|
+
var KNOWN_COMPONENT_SPEC_KEYS, EMPTY_SET2, FRAMEWORK_WELL_KNOWN_EXTRAS, KNOWN_DIRECTIVE_NAMES, ALT_HANDLER_NOT_DEFINED = "ALT_HANDLER_NOT_DEFINED", ALT_HANDLER_NOT_REFERENCED = "ALT_HANDLER_NOT_REFERENCED", DYN_VAL_NOT_DEFINED = "DYN_VAL_NOT_DEFINED", DYN_ALIAS_NOT_REFERENCED = "DYN_ALIAS_NOT_REFERENCED", PROVIDE_NOT_ADDRESSABLE = "PROVIDE_NOT_ADDRESSABLE", LOOKUP_BAD_SHAPE = "LOOKUP_BAD_SHAPE", LOOKUP_TARGET_MALFORMED = "LOOKUP_TARGET_MALFORMED", RENDER_IT_OUTSIDE_OF_LOOP = "RENDER_IT_OUTSIDE_OF_LOOP", UNKNOWN_EVENT_MODIFIER = "UNKNOWN_EVENT_MODIFIER", UNKNOWN_HANDLER_ARG_NAME = "UNKNOWN_HANDLER_ARG_NAME", INPUT_HANDLER_NOT_IMPLEMENTED = "INPUT_HANDLER_NOT_IMPLEMENTED", INPUT_HANDLER_NOT_REFERENCED = "INPUT_HANDLER_NOT_REFERENCED", INPUT_HANDLER_METHOD_NOT_IMPLEMENTED = "INPUT_HANDLER_METHOD_NOT_IMPLEMENTED", INPUT_HANDLER_FOR_INPUT_HANDLER_METHOD = "INPUT_HANDLER_FOR_INPUT_HANDLER_METHOD", INPUT_HANDLER_METHOD_FOR_INPUT_HANDLER = "INPUT_HANDLER_METHOD_FOR_INPUT_HANDLER", FIELD_VAL_NOT_DEFINED = "FIELD_VAL_NOT_DEFINED", FIELD_VAL_IS_METHOD = "FIELD_VAL_IS_METHOD", METHOD_VAL_NOT_DEFINED = "METHOD_VAL_NOT_DEFINED", METHOD_VAL_IS_FIELD = "METHOD_VAL_IS_FIELD", DUPLICATE_ATTR_DEFINITION = "DUPLICATE_ATTR_DEFINITION", IF_NO_BRANCH_SET = "IF_NO_BRANCH_SET", UNKNOWN_REQUEST_NAME = "UNKNOWN_REQUEST_NAME", UNKNOWN_COMPONENT_NAME = "UNKNOWN_COMPONENT_NAME", UNKNOWN_MACRO_ARG = "UNKNOWN_MACRO_ARG", UNKNOWN_DIRECTIVE = "UNKNOWN_DIRECTIVE", UNKNOWN_X_OP = "UNKNOWN_X_OP", UNKNOWN_X_ATTR = "UNKNOWN_X_ATTR", MAYBE_DROP_AT_PREFIX = "MAYBE_DROP_AT_PREFIX", MAYBE_ADD_AT_PREFIX = "MAYBE_ADD_AT_PREFIX", BAD_VALUE = "BAD_VALUE", UNSUPPORTED_EXPR_SYNTAX = "UNSUPPORTED_EXPR_SYNTAX", REDUNDANT_TEMPLATE_STRING = "REDUNDANT_TEMPLATE_STRING", PLACEHOLDERLESS_TEMPLATE_STRING = "PLACEHOLDERLESS_TEMPLATE_STRING", UNKNOWN_COMPONENT_SPEC_KEY = "UNKNOWN_COMPONENT_SPEC_KEY", COMP_FIELD_BAD_SHAPE = "COMP_FIELD_BAD_SHAPE", ASYNC_HANDLER = "ASYNC_HANDLER", TOP_LEVEL_AT_RULE_IN_SCOPED_STYLE = "TOP_LEVEL_AT_RULE_IN_SCOPED_STYLE", GLOBAL_SELECTOR_IN_SCOPED_STYLE = "GLOBAL_SELECTOR_IN_SCOPED_STYLE", X_KNOWN_OP_NAMES, X_KNOWN_ATTR_NAMES, HOST_DIRECTIVE_ONLY_NAMES, LEVEL_WARN2 = "warn", LEVEL_ERROR2 = "error", LEVEL_HINT = "hint", PARSE_ISSUES, UNSUPPORTED_EXPR_GUIDANCE, HTML_LINT_OPTS, NO_WRAPPERS, KNOWN_HANDLER_NAMES, fixTo = (from, to) => ({ kind: "rewrite", from, to }), ATTR_VAL_CHECKERS, NODE_KIND_TO_CTX, HANDLER_CHANNELS, ASYNC_HANDLER_HELP, NON_NESTABLE_AT_RULE, GLOBAL_LEADING_SELECTOR, IGNORE_DIRECTIVE, blankRun = (m) => m.replace(/[^\n]/g, " "), STYLE_TO_GLOBAL_HELP, KNOWN_LOOKUP_KEYS, LintParseContext;
|
|
13456
13515
|
var init_lint_check = __esm(() => {
|
|
13457
13516
|
init_anode();
|
|
13458
13517
|
init_htmllinter();
|
|
@@ -13603,6 +13662,10 @@ var init_lint_check = __esm(() => {
|
|
|
13603
13662
|
};
|
|
13604
13663
|
HANDLER_CHANNELS = ["input", "receive", "bubble", "response", "alter"];
|
|
13605
13664
|
ASYNC_HANDLER_HELP = "Move the async work into a request handler and trigger it with " + "ctx.request('name', args), then handle the result in a synchronous response " + "handler. To coordinate other components, keep the handler synchronous and use " + "ctx.send to deliver a message or ctx.bubble to raise an event.";
|
|
13665
|
+
NON_NESTABLE_AT_RULE = /(?:^|[\s;{}])@(?:-[a-z]+-)?(charset|import|namespace|font-face|keyframes|page|property|counter-style|font-feature-values|font-palette-values|view-transition)\b/gi;
|
|
13666
|
+
GLOBAL_LEADING_SELECTOR = /(?:^|[{}])\s*(html|body|:root)\b[^{};]*\{/gi;
|
|
13667
|
+
IGNORE_DIRECTIVE = /\/\*\s*tutuca-lint-ignore\s*\*\//g;
|
|
13668
|
+
STYLE_TO_GLOBAL_HELP = "Move it to the component's 'globalStyle' key, which is injected without the " + "component-scoping wrapper. To suppress a false positive, put a " + "/* tutuca-lint-ignore */ comment on the same line.";
|
|
13606
13669
|
KNOWN_LOOKUP_KEYS = new Set(["for", "default"]);
|
|
13607
13670
|
LintParseContext = class LintParseContext extends ParseContext {
|
|
13608
13671
|
constructor(document2, Text, Comment) {
|
|
@@ -13870,36 +13933,81 @@ class Transactor {
|
|
|
13870
13933
|
this.transactions = [];
|
|
13871
13934
|
this.state = new State2(rootValue);
|
|
13872
13935
|
this.onTransactionPushed = () => {};
|
|
13936
|
+
this._inflight = new Set;
|
|
13873
13937
|
}
|
|
13874
13938
|
pushTransaction(t) {
|
|
13875
13939
|
this.transactions.push(t);
|
|
13876
13940
|
this.onTransactionPushed(t);
|
|
13877
13941
|
}
|
|
13942
|
+
_link(child, parent) {
|
|
13943
|
+
if (parent) {
|
|
13944
|
+
const release = parent.completion.track();
|
|
13945
|
+
child.completion.whenSubtreeSettled().then(release);
|
|
13946
|
+
}
|
|
13947
|
+
return child;
|
|
13948
|
+
}
|
|
13878
13949
|
pushSend(path, name, args = [], opts = {}, parent = null) {
|
|
13879
|
-
|
|
13950
|
+
const t = new SendEvent(path, this, name, args, parent, opts);
|
|
13951
|
+
this.pushTransaction(t);
|
|
13952
|
+
return this._link(t, parent);
|
|
13953
|
+
}
|
|
13954
|
+
pushInput(path, name, args = [], opts = {}, parent = null) {
|
|
13955
|
+
const t = new InputDispatchEvent(path, this, name, args, parent, opts);
|
|
13956
|
+
this.pushTransaction(t);
|
|
13957
|
+
return this._link(t, parent);
|
|
13880
13958
|
}
|
|
13881
13959
|
pushBubble(path, name, args = [], opts = {}, parent = null, targetPath = null) {
|
|
13882
13960
|
const newOpts = opts.skipSelf ? { ...opts, skipSelf: false } : opts;
|
|
13883
|
-
|
|
13884
|
-
|
|
13885
|
-
|
|
13886
|
-
|
|
13887
|
-
|
|
13888
|
-
const
|
|
13889
|
-
const
|
|
13890
|
-
|
|
13891
|
-
|
|
13892
|
-
|
|
13893
|
-
|
|
13894
|
-
|
|
13895
|
-
|
|
13896
|
-
this.
|
|
13961
|
+
const t = new BubbleEvent(path, this, name, args, parent, newOpts, targetPath);
|
|
13962
|
+
this.pushTransaction(t);
|
|
13963
|
+
return this._link(t, parent);
|
|
13964
|
+
}
|
|
13965
|
+
pushRequest(path, name, args = [], opts = {}, parent = null) {
|
|
13966
|
+
const release = parent ? parent.completion.track() : null;
|
|
13967
|
+
const p = this._runRequest(path, name, args, opts, parent, release);
|
|
13968
|
+
this._inflight.add(p);
|
|
13969
|
+
p.finally(() => this._inflight.delete(p));
|
|
13970
|
+
return p;
|
|
13971
|
+
}
|
|
13972
|
+
async settle(maxTurns = 1e4) {
|
|
13973
|
+
while ((this.hasPendingTransactions || this._inflight.size) && maxTurns-- > 0) {
|
|
13974
|
+
while (this.hasPendingTransactions)
|
|
13975
|
+
this.transactNext();
|
|
13976
|
+
if (this._inflight.size)
|
|
13977
|
+
await Promise.allSettled([...this._inflight]);
|
|
13978
|
+
}
|
|
13979
|
+
}
|
|
13980
|
+
async _runRequest(path, name, args = [], opts = {}, parent = null, release = null) {
|
|
13981
|
+
let released = false;
|
|
13982
|
+
const transfer = (t) => {
|
|
13983
|
+
if (release) {
|
|
13984
|
+
released = true;
|
|
13985
|
+
t.completion.whenSubtreeSettled().then(release);
|
|
13986
|
+
}
|
|
13897
13987
|
};
|
|
13898
13988
|
try {
|
|
13899
|
-
const
|
|
13900
|
-
|
|
13901
|
-
|
|
13902
|
-
|
|
13989
|
+
const curRoot = this.state.val;
|
|
13990
|
+
const txnPath = path.toTransactionPath();
|
|
13991
|
+
const curLeaf = txnPath.lookup(curRoot);
|
|
13992
|
+
const handler = this.comps.getRequestFor(curLeaf, name) ?? mkReq404(name);
|
|
13993
|
+
const reqCtx = new RequestContext(path, this, parent, curRoot);
|
|
13994
|
+
const resHandlerName = opts?.onResName ?? name;
|
|
13995
|
+
const resPath = opts?.livePath ? null : txnPath.pinKeys(curRoot);
|
|
13996
|
+
const push = (specificName, baseName, singleArg, result, error) => {
|
|
13997
|
+
const resArgs = specificName ? [singleArg] : [result, error];
|
|
13998
|
+
const t = new ResponseEvent(path, this, specificName ?? baseName, resArgs, parent, resPath);
|
|
13999
|
+
transfer(t);
|
|
14000
|
+
this.pushTransaction(t);
|
|
14001
|
+
};
|
|
14002
|
+
try {
|
|
14003
|
+
const result = await handler.fn.apply(null, [...args, reqCtx]);
|
|
14004
|
+
push(opts?.onOkName, resHandlerName, result, result, null);
|
|
14005
|
+
} catch (error) {
|
|
14006
|
+
push(opts?.onErrorName, resHandlerName, error, null, error);
|
|
14007
|
+
}
|
|
14008
|
+
} finally {
|
|
14009
|
+
if (release && !released)
|
|
14010
|
+
release();
|
|
13903
14011
|
}
|
|
13904
14012
|
}
|
|
13905
14013
|
get hasPendingTransactions() {
|
|
@@ -13910,13 +14018,18 @@ class Transactor {
|
|
|
13910
14018
|
this.transact(this.transactions.shift());
|
|
13911
14019
|
}
|
|
13912
14020
|
transact(transaction) {
|
|
13913
|
-
|
|
13914
|
-
|
|
13915
|
-
|
|
13916
|
-
|
|
13917
|
-
|
|
13918
|
-
|
|
13919
|
-
|
|
14021
|
+
try {
|
|
14022
|
+
const curState = this.state.val;
|
|
14023
|
+
const newState = transaction.run(curState, this.comps);
|
|
14024
|
+
if (newState !== undefined) {
|
|
14025
|
+
this.state.set(newState, { transaction });
|
|
14026
|
+
transaction.afterTransaction();
|
|
14027
|
+
} else
|
|
14028
|
+
console.warn("undefined new state", { curState, transaction });
|
|
14029
|
+
} finally {
|
|
14030
|
+
transaction._completion?.ensureSelfSettled();
|
|
14031
|
+
transaction._completion?.releaseSelf();
|
|
14032
|
+
}
|
|
13920
14033
|
}
|
|
13921
14034
|
transactInputNow(path, event, eventHandler, dragInfo) {
|
|
13922
14035
|
this.transact(new InputEvent(path, event, eventHandler, this, dragInfo));
|
|
@@ -13937,18 +14050,17 @@ class Transaction {
|
|
|
13937
14050
|
this.path = path;
|
|
13938
14051
|
this.transactor = transactor;
|
|
13939
14052
|
this.parentTransaction = parentTransaction;
|
|
13940
|
-
this.
|
|
14053
|
+
this._completion = null;
|
|
13941
14054
|
}
|
|
13942
|
-
get
|
|
13943
|
-
this.
|
|
13944
|
-
return this.
|
|
14055
|
+
get completion() {
|
|
14056
|
+
this._completion ??= new Completion;
|
|
14057
|
+
return this._completion;
|
|
13945
14058
|
}
|
|
13946
|
-
|
|
13947
|
-
return this.
|
|
14059
|
+
whenSettled() {
|
|
14060
|
+
return this.completion.whenSettled();
|
|
13948
14061
|
}
|
|
13949
|
-
|
|
13950
|
-
this.
|
|
13951
|
-
parentTransaction.task.addDep(this.task);
|
|
14062
|
+
whenSubtreeSettled() {
|
|
14063
|
+
return this.completion.whenSubtreeSettled();
|
|
13952
14064
|
}
|
|
13953
14065
|
run(rootValue, comps) {
|
|
13954
14066
|
return this.updateRootValue(rootValue, comps);
|
|
@@ -13974,7 +14086,7 @@ class Transaction {
|
|
|
13974
14086
|
const txnPath = this.getTransactionPath();
|
|
13975
14087
|
const curLeaf = txnPath.lookup(curRoot);
|
|
13976
14088
|
const newLeaf = this.callHandler(curRoot, curLeaf, comps);
|
|
13977
|
-
this.
|
|
14089
|
+
this._completion?.markSelfSettled({ value: newLeaf, old: curLeaf });
|
|
13978
14090
|
return curLeaf !== newLeaf ? txnPath.setValue(curRoot, newLeaf) : curRoot;
|
|
13979
14091
|
}
|
|
13980
14092
|
lookupName(_name) {
|
|
@@ -13985,29 +14097,65 @@ function getValue(e) {
|
|
|
13985
14097
|
return e.target.type === "checkbox" ? e.target.checked : (e instanceof CustomEvent ? e.detail : e.target.value) ?? null;
|
|
13986
14098
|
}
|
|
13987
14099
|
|
|
13988
|
-
class
|
|
14100
|
+
class Completion {
|
|
13989
14101
|
constructor() {
|
|
13990
|
-
this.
|
|
13991
|
-
this.
|
|
13992
|
-
this.
|
|
13993
|
-
|
|
13994
|
-
|
|
14102
|
+
this.val = undefined;
|
|
14103
|
+
this.selfSettled = false;
|
|
14104
|
+
this.subtreeSettled = false;
|
|
14105
|
+
this.pending = 1;
|
|
14106
|
+
this._selfResolve = null;
|
|
14107
|
+
this._selfPromise = null;
|
|
14108
|
+
this._subtreeResolve = null;
|
|
14109
|
+
this._subtreePromise = null;
|
|
14110
|
+
this._selfReleased = false;
|
|
14111
|
+
}
|
|
14112
|
+
whenSettled() {
|
|
14113
|
+
if (this.selfSettled)
|
|
14114
|
+
return Promise.resolve(this.val);
|
|
14115
|
+
this._selfPromise ??= new Promise((res) => {
|
|
14116
|
+
this._selfResolve = res;
|
|
13995
14117
|
});
|
|
13996
|
-
this.
|
|
14118
|
+
return this._selfPromise;
|
|
13997
14119
|
}
|
|
13998
|
-
|
|
13999
|
-
|
|
14000
|
-
|
|
14001
|
-
|
|
14120
|
+
whenSubtreeSettled() {
|
|
14121
|
+
if (this.subtreeSettled)
|
|
14122
|
+
return Promise.resolve(this.val);
|
|
14123
|
+
this._subtreePromise ??= new Promise((res) => {
|
|
14124
|
+
this._subtreeResolve = res;
|
|
14125
|
+
});
|
|
14126
|
+
return this._subtreePromise;
|
|
14002
14127
|
}
|
|
14003
|
-
|
|
14128
|
+
markSelfSettled(val) {
|
|
14129
|
+
if (this.selfSettled)
|
|
14130
|
+
return;
|
|
14131
|
+
this.selfSettled = true;
|
|
14004
14132
|
this.val = val;
|
|
14005
|
-
this.
|
|
14133
|
+
this._selfResolve?.(val);
|
|
14006
14134
|
}
|
|
14007
|
-
|
|
14008
|
-
if (this.
|
|
14009
|
-
this.
|
|
14010
|
-
|
|
14135
|
+
ensureSelfSettled() {
|
|
14136
|
+
if (!this.selfSettled)
|
|
14137
|
+
this.markSelfSettled(this.val);
|
|
14138
|
+
}
|
|
14139
|
+
track() {
|
|
14140
|
+
this.pending++;
|
|
14141
|
+
let done = false;
|
|
14142
|
+
return () => {
|
|
14143
|
+
if (done)
|
|
14144
|
+
return;
|
|
14145
|
+
done = true;
|
|
14146
|
+
this._release();
|
|
14147
|
+
};
|
|
14148
|
+
}
|
|
14149
|
+
releaseSelf() {
|
|
14150
|
+
if (this._selfReleased)
|
|
14151
|
+
return;
|
|
14152
|
+
this._selfReleased = true;
|
|
14153
|
+
this._release();
|
|
14154
|
+
}
|
|
14155
|
+
_release() {
|
|
14156
|
+
if (--this.pending === 0) {
|
|
14157
|
+
this.subtreeSettled = true;
|
|
14158
|
+
this._subtreeResolve?.(this.val);
|
|
14011
14159
|
}
|
|
14012
14160
|
}
|
|
14013
14161
|
}
|
|
@@ -14046,11 +14194,17 @@ class Dispatcher {
|
|
|
14046
14194
|
requestAtPath(path, name, args, opts) {
|
|
14047
14195
|
return this.transactor.pushRequest(path, name, args, opts, this.parent);
|
|
14048
14196
|
}
|
|
14197
|
+
inputAtPath(path, name, args, opts) {
|
|
14198
|
+
return this.transactor.pushInput(path, name, args, opts, this.parent);
|
|
14199
|
+
}
|
|
14049
14200
|
lookupTypeFor(name, inst) {
|
|
14050
14201
|
return this.transactor.comps.getCompFor(inst).scope.lookupComponent(name);
|
|
14051
14202
|
}
|
|
14052
14203
|
}
|
|
14053
|
-
|
|
14204
|
+
function rootDispatcher(transactor) {
|
|
14205
|
+
return new Dispatcher(new Path([]), transactor, null);
|
|
14206
|
+
}
|
|
14207
|
+
var toNullIfNaN = (v) => Number.isNaN(v) ? null : v, InputEvent, NameArgsTransaction, ResponseEvent, SendEvent, BubbleEvent, InputDispatchEvent, EventContext, RequestContext, PathChanges;
|
|
14054
14208
|
var init_transactor = __esm(() => {
|
|
14055
14209
|
init_path();
|
|
14056
14210
|
init_stack();
|
|
@@ -14175,6 +14329,9 @@ var init_transactor = __esm(() => {
|
|
|
14175
14329
|
this.opts.bubbles = false;
|
|
14176
14330
|
}
|
|
14177
14331
|
};
|
|
14332
|
+
InputDispatchEvent = class InputDispatchEvent extends NameArgsTransaction {
|
|
14333
|
+
handlerProp = "input";
|
|
14334
|
+
};
|
|
14178
14335
|
EventContext = class EventContext extends Dispatcher {
|
|
14179
14336
|
get name() {
|
|
14180
14337
|
return this.parent?.name ?? null;
|
|
@@ -14560,6 +14717,49 @@ var init_render2 = __esm(() => {
|
|
|
14560
14717
|
init_render();
|
|
14561
14718
|
});
|
|
14562
14719
|
|
|
14720
|
+
// src/on.js
|
|
14721
|
+
function phaseOps(phase) {
|
|
14722
|
+
const ops = [];
|
|
14723
|
+
for (const type3 of OP_KINDS)
|
|
14724
|
+
for (const a of phase[type3] ?? [])
|
|
14725
|
+
ops.push({ type: type3, ...a });
|
|
14726
|
+
for (const a of phase.do ?? [])
|
|
14727
|
+
ops.push(a);
|
|
14728
|
+
return ops;
|
|
14729
|
+
}
|
|
14730
|
+
function resolveArgs(args, self) {
|
|
14731
|
+
return typeof args === "function" ? args(self) ?? [] : args ?? [];
|
|
14732
|
+
}
|
|
14733
|
+
function dispatchPhase(dispatcher, targetPath, phase, self) {
|
|
14734
|
+
if (!phase)
|
|
14735
|
+
return;
|
|
14736
|
+
for (const op of phaseOps(phase)) {
|
|
14737
|
+
const args = resolveArgs(op.args, self);
|
|
14738
|
+
switch (op.type) {
|
|
14739
|
+
case "send":
|
|
14740
|
+
dispatcher.sendAtPath(targetPath, op.name, args, op.opts);
|
|
14741
|
+
break;
|
|
14742
|
+
case "bubble":
|
|
14743
|
+
dispatcher.sendAtPath(targetPath, op.name, args, {
|
|
14744
|
+
skipSelf: true,
|
|
14745
|
+
bubbles: true,
|
|
14746
|
+
...op.opts
|
|
14747
|
+
});
|
|
14748
|
+
break;
|
|
14749
|
+
case "request":
|
|
14750
|
+
dispatcher.requestAtPath(targetPath, op.name, args, op.opts);
|
|
14751
|
+
break;
|
|
14752
|
+
case "input":
|
|
14753
|
+
dispatcher.inputAtPath(targetPath, op.name, args, op.opts);
|
|
14754
|
+
break;
|
|
14755
|
+
}
|
|
14756
|
+
}
|
|
14757
|
+
}
|
|
14758
|
+
var OP_KINDS;
|
|
14759
|
+
var init_on = __esm(() => {
|
|
14760
|
+
OP_KINDS = ["send", "bubble", "request", "input"];
|
|
14761
|
+
});
|
|
14762
|
+
|
|
14563
14763
|
// tools/core/tests.js
|
|
14564
14764
|
class Describe {
|
|
14565
14765
|
constructor({ title, componentName = null, parent = null }) {
|
|
@@ -14699,7 +14899,9 @@ async function runTests({
|
|
|
14699
14899
|
expect: expect2,
|
|
14700
14900
|
name = null,
|
|
14701
14901
|
grep = null,
|
|
14702
|
-
bail = false
|
|
14902
|
+
bail = false,
|
|
14903
|
+
requestHandlers = null,
|
|
14904
|
+
macros = null
|
|
14703
14905
|
} = {}) {
|
|
14704
14906
|
const counts = { pass: 0, fail: 0, skip: 0, total: 0 };
|
|
14705
14907
|
if (typeof getTests !== "function") {
|
|
@@ -14711,7 +14913,30 @@ async function runTests({
|
|
|
14711
14913
|
throw new Error("runTests: expect must be provided (e.g. chai's expect)");
|
|
14712
14914
|
}
|
|
14713
14915
|
const { describe, test: test2, moduleTests } = makeCollector({ path, components });
|
|
14714
|
-
await getTests({ describe, test: test2, expect: expect2 });
|
|
14916
|
+
await getTests({ describe, test: test2, expect: expect2, drive });
|
|
14917
|
+
let _stack = null;
|
|
14918
|
+
function getStack() {
|
|
14919
|
+
if (_stack)
|
|
14920
|
+
return _stack;
|
|
14921
|
+
_stack = new ComponentStack;
|
|
14922
|
+
_stack.registerComponents(components);
|
|
14923
|
+
if (macros)
|
|
14924
|
+
_stack.registerMacros(macros);
|
|
14925
|
+
if (requestHandlers)
|
|
14926
|
+
_stack.registerRequestHandlers(requestHandlers);
|
|
14927
|
+
return _stack;
|
|
14928
|
+
}
|
|
14929
|
+
async function drive(value, phase, opts = {}) {
|
|
14930
|
+
const transactor = new Transactor(getStack().comps, value);
|
|
14931
|
+
if (opts.onMessage)
|
|
14932
|
+
transactor.state.onChange(({ val, old, info }) => {
|
|
14933
|
+
const t = info?.transaction;
|
|
14934
|
+
opts.onMessage({ kind: t?.handlerProp ?? "input", name: t?.name, args: t?.args, path: t?.path }, old, val);
|
|
14935
|
+
});
|
|
14936
|
+
dispatchPhase(rootDispatcher(transactor), new Path([]), phase, value);
|
|
14937
|
+
await transactor.settle();
|
|
14938
|
+
return transactor.state.val;
|
|
14939
|
+
}
|
|
14715
14940
|
let bailed = false;
|
|
14716
14941
|
async function visit(node) {
|
|
14717
14942
|
if (node instanceof Test) {
|
|
@@ -14779,7 +15004,12 @@ async function runTests({
|
|
|
14779
15004
|
modules: [new ModuleTestReport({ path, suites: suiteResults, counts })]
|
|
14780
15005
|
});
|
|
14781
15006
|
}
|
|
14782
|
-
var init_test = () => {
|
|
15007
|
+
var init_test = __esm(() => {
|
|
15008
|
+
init_components();
|
|
15009
|
+
init_on();
|
|
15010
|
+
init_path();
|
|
15011
|
+
init_transactor();
|
|
15012
|
+
});
|
|
14783
15013
|
|
|
14784
15014
|
// tools/cli/commands/_registry.js
|
|
14785
15015
|
var exports__registry = {};
|
|
@@ -14867,7 +15097,9 @@ var init__registry = __esm(() => {
|
|
|
14867
15097
|
expect,
|
|
14868
15098
|
name: positionals[0] ?? null,
|
|
14869
15099
|
grep: values.grep ?? null,
|
|
14870
|
-
bail: values.bail ?? false
|
|
15100
|
+
bail: values.bail ?? false,
|
|
15101
|
+
requestHandlers: normalized.requestHandlers,
|
|
15102
|
+
macros: normalized.macros
|
|
14871
15103
|
}),
|
|
14872
15104
|
exitOn: (result) => result.hasFailures ? 4 : 0
|
|
14873
15105
|
}
|
|
@@ -15103,6 +15335,18 @@ var init_lint_rules = __esm(() => {
|
|
|
15103
15335
|
group: "Handler effects",
|
|
15104
15336
|
summary: "A handler in `input`/`receive`/`bubble`/`response`/`alter` is an async " + "function — handlers must be synchronous; use a request handler, `ctx.send`, " + "or `ctx.bubble` instead."
|
|
15105
15337
|
},
|
|
15338
|
+
{
|
|
15339
|
+
code: TOP_LEVEL_AT_RULE_IN_SCOPED_STYLE,
|
|
15340
|
+
level: "error",
|
|
15341
|
+
group: "Component styles",
|
|
15342
|
+
summary: "A top-level-only at-rule (`@import`, `@keyframes`, `@font-face`, …) appears " + "in `style`/`commonStyle`, which is wrapped in a component-scoped selector " + "where it is invalid and dropped — move it to `globalStyle`."
|
|
15343
|
+
},
|
|
15344
|
+
{
|
|
15345
|
+
code: GLOBAL_SELECTOR_IN_SCOPED_STYLE,
|
|
15346
|
+
level: "error",
|
|
15347
|
+
group: "Component styles",
|
|
15348
|
+
summary: "A rule whose leading selector is `html`/`body`/`:root` appears in " + "`style`/`commonStyle`; once scoped it becomes a descendant selector that " + "never matches — move it to `globalStyle`."
|
|
15349
|
+
},
|
|
15106
15350
|
{
|
|
15107
15351
|
code: COMP_FIELD_BAD_SHAPE,
|
|
15108
15352
|
level: "error",
|
|
@@ -15298,6 +15542,10 @@ function lintIdToMessage(id, info) {
|
|
|
15298
15542
|
return `MathML attribute '${info.raw}' will be rewritten to '${info.canonical}'${fmtLocationSuffix(info)}`;
|
|
15299
15543
|
case "ASYNC_HANDLER":
|
|
15300
15544
|
return `Handler '${info.name}' in '${info.channel}' is an async function — handlers must be synchronous and return the updated state (an async function returns a Promise the framework won't await)`;
|
|
15545
|
+
case "TOP_LEVEL_AT_RULE_IN_SCOPED_STYLE":
|
|
15546
|
+
return `'@${info.atRule}' is a top-level-only at-rule, but '${info.key}' is wrapped in a component-scoped selector ([data-cid=…]{…}) where it is invalid and silently dropped — move it to 'globalStyle'${fmtLocationSuffix(info)}`;
|
|
15547
|
+
case "GLOBAL_SELECTOR_IN_SCOPED_STYLE":
|
|
15548
|
+
return `Selector '${info.selector}' targets the document root, but '${info.key}' is wrapped in a component-scoped selector, so it becomes a descendant selector that never matches — move it to 'globalStyle'${fmtLocationSuffix(info)}`;
|
|
15301
15549
|
case "LINT_ERROR":
|
|
15302
15550
|
return info.message;
|
|
15303
15551
|
default:
|
|
@@ -15872,7 +16120,9 @@ async function runDevTests(projectDir, devModuleUrls) {
|
|
|
15872
16120
|
getTests: mod.getTests,
|
|
15873
16121
|
components: normalized.components,
|
|
15874
16122
|
path: abs,
|
|
15875
|
-
expect
|
|
16123
|
+
expect,
|
|
16124
|
+
requestHandlers: normalized.requestHandlers,
|
|
16125
|
+
macros: normalized.macros
|
|
15876
16126
|
});
|
|
15877
16127
|
const m = report.modules[0];
|
|
15878
16128
|
totalTests += m.counts.total;
|