tutuca 0.9.93 → 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 +230 -59
- package/dist/tutuca-dev.ext.js +1362 -1199
- package/dist/tutuca-dev.js +1362 -1199
- package/dist/tutuca-dev.min.js +2 -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 +10 -1
- 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-dev.ext.js
CHANGED
|
@@ -5800,1386 +5800,1546 @@ class LintParseContext extends ParseContext {
|
|
|
5800
5800
|
}
|
|
5801
5801
|
}
|
|
5802
5802
|
|
|
5803
|
-
//
|
|
5804
|
-
class
|
|
5805
|
-
constructor(
|
|
5806
|
-
this.
|
|
5807
|
-
this.
|
|
5808
|
-
this.counts = counts;
|
|
5809
|
-
this.warnings = warnings;
|
|
5810
|
-
}
|
|
5811
|
-
}
|
|
5812
|
-
|
|
5813
|
-
class ComponentSummary {
|
|
5814
|
-
constructor({ name, views, fields }) {
|
|
5815
|
-
this.name = name;
|
|
5816
|
-
this.views = views;
|
|
5817
|
-
this.fields = fields;
|
|
5818
|
-
}
|
|
5819
|
-
}
|
|
5820
|
-
|
|
5821
|
-
class ComponentList {
|
|
5822
|
-
constructor({ items, total = null, truncated = false }) {
|
|
5823
|
-
this.items = items;
|
|
5824
|
-
this.total = total ?? items.length;
|
|
5825
|
-
this.truncated = truncated;
|
|
5803
|
+
// src/components.js
|
|
5804
|
+
class Components {
|
|
5805
|
+
constructor() {
|
|
5806
|
+
this.getComponentSymbol = Symbol("getComponent");
|
|
5807
|
+
this.byId = new Map;
|
|
5826
5808
|
}
|
|
5827
|
-
|
|
5828
|
-
|
|
5829
|
-
|
|
5830
|
-
constructor({ sections, total = null, truncated = false }) {
|
|
5831
|
-
this.sections = sections;
|
|
5832
|
-
this.total = total ?? sections.reduce((n, s) => n + (s.items?.length ?? 0), 0);
|
|
5833
|
-
this.truncated = truncated;
|
|
5809
|
+
registerComponent(comp) {
|
|
5810
|
+
comp.Class.prototype[this.getComponentSymbol] = () => comp;
|
|
5811
|
+
this.byId.set(comp.id, comp);
|
|
5834
5812
|
}
|
|
5835
|
-
|
|
5836
|
-
|
|
5837
|
-
class ComponentDocs {
|
|
5838
|
-
constructor({ items }) {
|
|
5839
|
-
this.items = items;
|
|
5813
|
+
getComponentForId(id) {
|
|
5814
|
+
return this.byId.get(id) ?? null;
|
|
5840
5815
|
}
|
|
5841
|
-
|
|
5842
|
-
|
|
5843
|
-
class LintFinding {
|
|
5844
|
-
constructor({ id, level, info, context = {}, suggestion = null }) {
|
|
5845
|
-
this.id = id;
|
|
5846
|
-
this.level = level;
|
|
5847
|
-
this.info = info;
|
|
5848
|
-
this.context = context;
|
|
5849
|
-
this.suggestion = suggestion;
|
|
5816
|
+
getCompFor(v) {
|
|
5817
|
+
return v?.[this.getComponentSymbol]?.() ?? null;
|
|
5850
5818
|
}
|
|
5851
|
-
|
|
5852
|
-
|
|
5853
|
-
class LintComponentResult {
|
|
5854
|
-
constructor({ componentName, findings }) {
|
|
5855
|
-
this.componentName = componentName;
|
|
5856
|
-
this.findings = findings;
|
|
5819
|
+
getHandlerFor(v, name, key) {
|
|
5820
|
+
return this.getCompFor(v)?.[key][name] ?? null;
|
|
5857
5821
|
}
|
|
5858
|
-
|
|
5859
|
-
return this.
|
|
5822
|
+
getRequestFor(v, name) {
|
|
5823
|
+
return this.getCompFor(v)?.scope.lookupRequest(name) ?? null;
|
|
5860
5824
|
}
|
|
5861
|
-
|
|
5862
|
-
|
|
5825
|
+
compileStyles() {
|
|
5826
|
+
const styles = [];
|
|
5827
|
+
for (const comp of this.byId.values())
|
|
5828
|
+
styles.push(comp.compileStyle());
|
|
5829
|
+
return styles.join(`
|
|
5830
|
+
`);
|
|
5863
5831
|
}
|
|
5864
5832
|
}
|
|
5865
5833
|
|
|
5866
|
-
class
|
|
5867
|
-
constructor(
|
|
5868
|
-
this.
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
|
|
5834
|
+
class ComponentStack {
|
|
5835
|
+
constructor(comps = new Components, parent = null) {
|
|
5836
|
+
this.comps = comps;
|
|
5837
|
+
this.parent = parent;
|
|
5838
|
+
this.byName = {};
|
|
5839
|
+
this.reqsByName = {};
|
|
5840
|
+
this.macros = {};
|
|
5872
5841
|
}
|
|
5873
|
-
|
|
5874
|
-
return this.
|
|
5842
|
+
enter() {
|
|
5843
|
+
return new ComponentStack(this.comps, this);
|
|
5875
5844
|
}
|
|
5876
|
-
|
|
5877
|
-
|
|
5845
|
+
registerComponents(comps, opts) {
|
|
5846
|
+
const { aliases = {} } = opts ?? {};
|
|
5847
|
+
for (let i = 0;i < comps.length; i++) {
|
|
5848
|
+
const comp = comps[i];
|
|
5849
|
+
comp.scope = this.enter();
|
|
5850
|
+
comp.Class.scope = comp.scope;
|
|
5851
|
+
this.comps.registerComponent(comp);
|
|
5852
|
+
this.byName[comp.name] = comp;
|
|
5853
|
+
}
|
|
5854
|
+
for (const alias in aliases) {
|
|
5855
|
+
const comp = this.byName[aliases[alias]];
|
|
5856
|
+
console.assert(this.byName[alias] === undefined, "alias overrides component", alias);
|
|
5857
|
+
if (comp !== undefined)
|
|
5858
|
+
this.byName[alias] = comp;
|
|
5859
|
+
else
|
|
5860
|
+
console.warn("alias", alias, "to inexistent component", aliases[alias]);
|
|
5861
|
+
}
|
|
5878
5862
|
}
|
|
5879
|
-
|
|
5880
|
-
|
|
5881
|
-
|
|
5882
|
-
|
|
5883
|
-
|
|
5884
|
-
|
|
5885
|
-
this.componentName = componentName;
|
|
5886
|
-
this.view = view;
|
|
5887
|
-
this.html = html;
|
|
5888
|
-
this.error = error;
|
|
5863
|
+
registerMacros(macros) {
|
|
5864
|
+
for (const key in macros) {
|
|
5865
|
+
const lower = key.toLowerCase();
|
|
5866
|
+
console.assert(this.macros[lower] === undefined, "macro key collision", lower);
|
|
5867
|
+
this.macros[lower] = macros[key];
|
|
5868
|
+
}
|
|
5889
5869
|
}
|
|
5890
|
-
|
|
5891
|
-
|
|
5892
|
-
class RenderedSection {
|
|
5893
|
-
constructor({ title, description = null, items }) {
|
|
5894
|
-
this.title = title;
|
|
5895
|
-
this.description = description;
|
|
5896
|
-
this.items = items;
|
|
5870
|
+
getCompFor(v) {
|
|
5871
|
+
return this.comps.getCompFor(v);
|
|
5897
5872
|
}
|
|
5898
|
-
|
|
5899
|
-
|
|
5900
|
-
|
|
5901
|
-
constructor({ sections }) {
|
|
5902
|
-
this.sections = sections;
|
|
5873
|
+
registerRequestHandlers(handlers) {
|
|
5874
|
+
for (const name in handlers)
|
|
5875
|
+
this.reqsByName[name] = new RequestHandler(name, handlers[name]);
|
|
5903
5876
|
}
|
|
5904
|
-
|
|
5905
|
-
return this.
|
|
5877
|
+
lookupRequest(name) {
|
|
5878
|
+
return this.reqsByName[name] ?? this.parent?.lookupRequest(name) ?? null;
|
|
5906
5879
|
}
|
|
5907
|
-
|
|
5908
|
-
|
|
5909
|
-
class TestResult {
|
|
5910
|
-
constructor({ title, fullPath, componentName = null, status, durationMs = 0, error = null }) {
|
|
5911
|
-
this.title = title;
|
|
5912
|
-
this.fullPath = fullPath;
|
|
5913
|
-
this.componentName = componentName;
|
|
5914
|
-
this.status = status;
|
|
5915
|
-
this.durationMs = durationMs;
|
|
5916
|
-
this.error = error;
|
|
5880
|
+
lookupComponent(name) {
|
|
5881
|
+
return this.byName[name] ?? this.parent?.lookupComponent(name) ?? null;
|
|
5917
5882
|
}
|
|
5918
|
-
|
|
5919
|
-
|
|
5920
|
-
class DescribeResult {
|
|
5921
|
-
constructor({ title, componentName = null, children = [] }) {
|
|
5922
|
-
this.title = title;
|
|
5923
|
-
this.componentName = componentName;
|
|
5924
|
-
this.children = children;
|
|
5883
|
+
lookupMacro(name) {
|
|
5884
|
+
return this.macros[name] ?? this.parent?.lookupMacro(name) ?? null;
|
|
5925
5885
|
}
|
|
5926
5886
|
}
|
|
5927
5887
|
|
|
5928
|
-
class
|
|
5929
|
-
constructor(
|
|
5930
|
-
this.
|
|
5931
|
-
this.
|
|
5932
|
-
this.
|
|
5888
|
+
class ProvideInfo {
|
|
5889
|
+
constructor(name, val, symbol) {
|
|
5890
|
+
this.name = name;
|
|
5891
|
+
this.val = val;
|
|
5892
|
+
this.symbol = symbol;
|
|
5933
5893
|
}
|
|
5934
5894
|
}
|
|
5935
5895
|
|
|
5936
|
-
class
|
|
5937
|
-
constructor(
|
|
5938
|
-
this.
|
|
5939
|
-
|
|
5940
|
-
|
|
5941
|
-
|
|
5942
|
-
|
|
5943
|
-
fail: acc.fail + m.counts.fail,
|
|
5944
|
-
skip: acc.skip + m.counts.skip,
|
|
5945
|
-
total: acc.total + m.counts.total
|
|
5946
|
-
}), { pass: 0, fail: 0, skip: 0, total: 0 });
|
|
5896
|
+
class LookupInfo {
|
|
5897
|
+
constructor(name, compName, provideName, val) {
|
|
5898
|
+
this.name = name;
|
|
5899
|
+
this.compName = compName;
|
|
5900
|
+
this.provideName = provideName;
|
|
5901
|
+
this.val = val;
|
|
5902
|
+
this._sym = undefined;
|
|
5947
5903
|
}
|
|
5948
|
-
|
|
5949
|
-
|
|
5904
|
+
getProducerSymbol(stack) {
|
|
5905
|
+
if (this._sym === undefined)
|
|
5906
|
+
this._sym = stack.lookupType(this.compName)?.provide?.[this.provideName]?.symbol ?? null;
|
|
5907
|
+
return this._sym;
|
|
5950
5908
|
}
|
|
5951
5909
|
}
|
|
5910
|
+
var isString = (v) => typeof v === "string";
|
|
5911
|
+
var _rawSpecKeys = "name view style commonStyle globalStyle input receive bubble response alter views provide lookup fields methods statics";
|
|
5912
|
+
var KNOWN_SPEC_KEYS = new Set(_rawSpecKeys.split(" "));
|
|
5913
|
+
var _compId = 0;
|
|
5952
5914
|
|
|
5953
|
-
|
|
5954
|
-
|
|
5955
|
-
|
|
5956
|
-
this.
|
|
5957
|
-
this.
|
|
5958
|
-
this.
|
|
5959
|
-
this.
|
|
5915
|
+
class Component {
|
|
5916
|
+
constructor(Class, o) {
|
|
5917
|
+
this.id = _compId++;
|
|
5918
|
+
this.name = o.name ?? "UnkComp";
|
|
5919
|
+
this.Class = Class;
|
|
5920
|
+
this.views = { main: new View("main", o.view, o.style) };
|
|
5921
|
+
this.commonStyle = o.commonStyle ?? "";
|
|
5922
|
+
this.globalStyle = o.globalStyle ?? "";
|
|
5923
|
+
this.input = o.input ?? {};
|
|
5924
|
+
this.receive = o.receive ?? {};
|
|
5925
|
+
this.bubble = o.bubble ?? {};
|
|
5926
|
+
this.response = o.response ?? {};
|
|
5927
|
+
this.alter = o.alter ?? {};
|
|
5928
|
+
for (const name in o.views ?? {}) {
|
|
5929
|
+
const v = o.views[name];
|
|
5930
|
+
const { view, style } = isString(v) ? { view: v } : v;
|
|
5931
|
+
this.views[name] = new View(name, view, style);
|
|
5932
|
+
}
|
|
5933
|
+
this._rawProvide = o.provide ?? {};
|
|
5934
|
+
this._rawLookup = o.lookup ?? {};
|
|
5935
|
+
this.provide = {};
|
|
5936
|
+
this.lookup = {};
|
|
5937
|
+
this.scope = null;
|
|
5938
|
+
this.spec = o;
|
|
5939
|
+
this.extra = {};
|
|
5940
|
+
for (const key of Object.keys(o))
|
|
5941
|
+
if (!KNOWN_SPEC_KEYS.has(key))
|
|
5942
|
+
this.extra[key] = o[key];
|
|
5960
5943
|
}
|
|
5961
|
-
|
|
5962
|
-
|
|
5963
|
-
class Test {
|
|
5964
|
-
constructor({ title, fn, componentName = null, parent = null }) {
|
|
5965
|
-
this.title = title;
|
|
5966
|
-
this.fn = fn;
|
|
5967
|
-
this.componentName = componentName;
|
|
5968
|
-
this.parent = parent;
|
|
5944
|
+
clone() {
|
|
5945
|
+
return Component.fromSpec(this.spec);
|
|
5969
5946
|
}
|
|
5970
|
-
|
|
5971
|
-
|
|
5972
|
-
|
|
5973
|
-
|
|
5974
|
-
this.
|
|
5975
|
-
|
|
5947
|
+
compile(ParseContext2) {
|
|
5948
|
+
for (const name in this.views)
|
|
5949
|
+
this.views[name].compile(new ParseContext2, this.scope, this.id);
|
|
5950
|
+
const ctx = this.views.main.ctx;
|
|
5951
|
+
for (const key in this._rawProvide) {
|
|
5952
|
+
const val = vp.parseProvide(this._rawProvide[key], ctx);
|
|
5953
|
+
if (val)
|
|
5954
|
+
this.provide[key] = new ProvideInfo(key, val, Symbol(key));
|
|
5955
|
+
}
|
|
5956
|
+
for (const key in this._rawLookup) {
|
|
5957
|
+
const linfo = this._rawLookup[key];
|
|
5958
|
+
const forStr = isString(linfo) ? linfo : isString(linfo?.for) ? linfo.for : null;
|
|
5959
|
+
const [compName, provideName] = forStr === null ? [] : forStr.split(".");
|
|
5960
|
+
if (!isString(compName) || !isString(provideName))
|
|
5961
|
+
continue;
|
|
5962
|
+
const defStr = isString(linfo?.default) ? linfo.default : null;
|
|
5963
|
+
const val = defStr === null ? null : vp.parseField(defStr, ctx);
|
|
5964
|
+
this.lookup[key] = new LookupInfo(key, compName, provideName, val);
|
|
5965
|
+
}
|
|
5966
|
+
for (const key in this.lookup)
|
|
5967
|
+
if (this.provide[key] !== undefined)
|
|
5968
|
+
console.warn("name declared in both provide and lookup", this.name, key);
|
|
5969
|
+
}
|
|
5970
|
+
make(args, opts) {
|
|
5971
|
+
return this.Class.make(args, opts ?? { scope: this.scope });
|
|
5972
|
+
}
|
|
5973
|
+
getView(name) {
|
|
5974
|
+
return this.views[name] ?? this.views.main;
|
|
5975
|
+
}
|
|
5976
|
+
getEventForId(id, name = "main") {
|
|
5977
|
+
return this.getView(name).ctx.getEventForId(id);
|
|
5978
|
+
}
|
|
5979
|
+
getNodeForId(id, name = "main") {
|
|
5980
|
+
return this.getView(name).ctx.getNodeForId(id);
|
|
5981
|
+
}
|
|
5982
|
+
compileStyle() {
|
|
5983
|
+
const { id, commonStyle, globalStyle, views } = this;
|
|
5984
|
+
const styles = commonStyle ? [`[data-cid="${id}"]{${commonStyle}}`] : [];
|
|
5985
|
+
if (globalStyle !== "")
|
|
5986
|
+
styles.push(globalStyle);
|
|
5987
|
+
for (const name in views) {
|
|
5988
|
+
const { style } = views[name];
|
|
5989
|
+
if (style !== "")
|
|
5990
|
+
styles.push(`[data-cid="${id}"][data-vid="${name}"]{${style}}`);
|
|
5991
|
+
}
|
|
5992
|
+
return styles.join(`
|
|
5993
|
+
`);
|
|
5976
5994
|
}
|
|
5977
5995
|
}
|
|
5978
5996
|
|
|
5979
|
-
|
|
5980
|
-
|
|
5981
|
-
|
|
5982
|
-
|
|
5997
|
+
// src/on.js
|
|
5998
|
+
var OP_KINDS = ["send", "bubble", "request", "input"];
|
|
5999
|
+
function phaseOps(phase) {
|
|
6000
|
+
const ops = [];
|
|
6001
|
+
for (const type of OP_KINDS)
|
|
6002
|
+
for (const a of phase[type] ?? [])
|
|
6003
|
+
ops.push({ type, ...a });
|
|
6004
|
+
for (const a of phase.do ?? [])
|
|
6005
|
+
ops.push(a);
|
|
6006
|
+
return ops;
|
|
5983
6007
|
}
|
|
5984
|
-
function
|
|
5985
|
-
return
|
|
6008
|
+
function resolveArgs(args, self) {
|
|
6009
|
+
return typeof args === "function" ? args(self) ?? [] : args ?? [];
|
|
5986
6010
|
}
|
|
5987
|
-
function
|
|
5988
|
-
if (
|
|
5989
|
-
return
|
|
5990
|
-
|
|
5991
|
-
|
|
5992
|
-
|
|
5993
|
-
|
|
6011
|
+
function dispatchPhase(dispatcher, targetPath, phase, self) {
|
|
6012
|
+
if (!phase)
|
|
6013
|
+
return;
|
|
6014
|
+
for (const op of phaseOps(phase)) {
|
|
6015
|
+
const args = resolveArgs(op.args, self);
|
|
6016
|
+
switch (op.type) {
|
|
6017
|
+
case "send":
|
|
6018
|
+
dispatcher.sendAtPath(targetPath, op.name, args, op.opts);
|
|
6019
|
+
break;
|
|
6020
|
+
case "bubble":
|
|
6021
|
+
dispatcher.sendAtPath(targetPath, op.name, args, {
|
|
6022
|
+
skipSelf: true,
|
|
6023
|
+
bubbles: true,
|
|
6024
|
+
...op.opts
|
|
6025
|
+
});
|
|
6026
|
+
break;
|
|
6027
|
+
case "request":
|
|
6028
|
+
dispatcher.requestAtPath(targetPath, op.name, args, op.opts);
|
|
6029
|
+
break;
|
|
6030
|
+
case "input":
|
|
6031
|
+
dispatcher.inputAtPath(targetPath, op.name, args, op.opts);
|
|
6032
|
+
break;
|
|
6033
|
+
}
|
|
5994
6034
|
}
|
|
5995
|
-
return null;
|
|
5996
6035
|
}
|
|
5997
|
-
|
|
5998
|
-
|
|
5999
|
-
|
|
6000
|
-
|
|
6001
|
-
|
|
6002
|
-
|
|
6003
|
-
|
|
6004
|
-
|
|
6036
|
+
|
|
6037
|
+
// src/stack.js
|
|
6038
|
+
var STOP = Symbol("STOP");
|
|
6039
|
+
var NEXT = Symbol("NEXT");
|
|
6040
|
+
function lookup(chain, name, dv = null) {
|
|
6041
|
+
let n = chain;
|
|
6042
|
+
while (n !== null) {
|
|
6043
|
+
const r = n[0].lookup(name);
|
|
6044
|
+
if (r === STOP)
|
|
6045
|
+
return dv;
|
|
6046
|
+
if (r !== NEXT)
|
|
6047
|
+
return r;
|
|
6048
|
+
n = n[1];
|
|
6049
|
+
}
|
|
6050
|
+
return dv;
|
|
6005
6051
|
}
|
|
6006
|
-
|
|
6007
|
-
|
|
6008
|
-
|
|
6009
|
-
|
|
6010
|
-
|
|
6011
|
-
|
|
6012
|
-
let fn;
|
|
6013
|
-
if (args.length === 2) {
|
|
6014
|
-
[head, fn] = args;
|
|
6015
|
-
} else if (args.length === 3) {
|
|
6016
|
-
[head, options, fn] = args;
|
|
6017
|
-
} else {
|
|
6018
|
-
throw new Error(`describe() expects 2 or 3 arguments, got ${args.length}`);
|
|
6019
|
-
}
|
|
6020
|
-
if (typeof fn !== "function") {
|
|
6021
|
-
throw new Error(`describe(${JSON.stringify(titleFromArg(head))}): final argument must be a function`);
|
|
6022
|
-
}
|
|
6023
|
-
let componentName = null;
|
|
6024
|
-
if (typeof head !== "string") {
|
|
6025
|
-
componentName = resolveComponentName(head, components);
|
|
6026
|
-
}
|
|
6027
|
-
if (componentName === null && options && options.component != null) {
|
|
6028
|
-
componentName = resolveComponentName(options.component, components);
|
|
6029
|
-
}
|
|
6030
|
-
if (componentName === null) {
|
|
6031
|
-
const parent2 = stack.length ? stack[stack.length - 1] : null;
|
|
6032
|
-
if (parent2)
|
|
6033
|
-
componentName = parent2.componentName;
|
|
6034
|
-
}
|
|
6035
|
-
const parent = stack.length ? stack[stack.length - 1] : null;
|
|
6036
|
-
const node = new Describe({
|
|
6037
|
-
title: titleFromArg(head),
|
|
6038
|
-
componentName,
|
|
6039
|
-
parent
|
|
6040
|
-
});
|
|
6041
|
-
if (parent)
|
|
6042
|
-
parent.children.push(node);
|
|
6043
|
-
else
|
|
6044
|
-
moduleTests.suites.push(node);
|
|
6045
|
-
stack.push(node);
|
|
6046
|
-
try {
|
|
6047
|
-
fn();
|
|
6048
|
-
} finally {
|
|
6049
|
-
stack.pop();
|
|
6050
|
-
}
|
|
6052
|
+
|
|
6053
|
+
class BindFrame {
|
|
6054
|
+
constructor(it, binds, isFrame) {
|
|
6055
|
+
this.it = it;
|
|
6056
|
+
this.binds = binds;
|
|
6057
|
+
this.isFrame = isFrame;
|
|
6051
6058
|
}
|
|
6052
|
-
|
|
6053
|
-
|
|
6054
|
-
|
|
6055
|
-
}
|
|
6056
|
-
if (typeof fn !== "function") {
|
|
6057
|
-
throw new Error(`test(${JSON.stringify(title)}): fn must be a function`);
|
|
6058
|
-
}
|
|
6059
|
-
const parent = stack.length ? stack[stack.length - 1] : null;
|
|
6060
|
-
if (!parent) {
|
|
6061
|
-
throw new Error(`test(${JSON.stringify(title)}) must be called inside a describe()`);
|
|
6062
|
-
}
|
|
6063
|
-
parent.children.push(new Test({
|
|
6064
|
-
title,
|
|
6065
|
-
fn,
|
|
6066
|
-
componentName: parent.componentName,
|
|
6067
|
-
parent
|
|
6068
|
-
}));
|
|
6059
|
+
lookup(name) {
|
|
6060
|
+
const v = this.binds[name];
|
|
6061
|
+
return v === undefined ? this.isFrame ? STOP : NEXT : v;
|
|
6069
6062
|
}
|
|
6070
|
-
return { describe, test, moduleTests };
|
|
6071
6063
|
}
|
|
6072
6064
|
|
|
6073
|
-
|
|
6074
|
-
|
|
6075
|
-
|
|
6076
|
-
|
|
6077
|
-
|
|
6078
|
-
|
|
6079
|
-
|
|
6065
|
+
class ObjectFrame {
|
|
6066
|
+
constructor(binds) {
|
|
6067
|
+
this.binds = binds;
|
|
6068
|
+
}
|
|
6069
|
+
lookup(key) {
|
|
6070
|
+
const v = this.binds[key];
|
|
6071
|
+
return v === undefined ? NEXT : v;
|
|
6080
6072
|
}
|
|
6081
|
-
return parts.join(" > ");
|
|
6082
6073
|
}
|
|
6083
|
-
function
|
|
6084
|
-
|
|
6085
|
-
|
|
6086
|
-
|
|
6087
|
-
|
|
6088
|
-
|
|
6089
|
-
|
|
6074
|
+
function computeViewsId(views) {
|
|
6075
|
+
let s = "";
|
|
6076
|
+
let n = views;
|
|
6077
|
+
while (n !== null) {
|
|
6078
|
+
s += n[0];
|
|
6079
|
+
n = n[1];
|
|
6080
|
+
}
|
|
6081
|
+
return s === "main" ? "" : s;
|
|
6090
6082
|
}
|
|
6091
|
-
|
|
6092
|
-
|
|
6093
|
-
|
|
6094
|
-
|
|
6095
|
-
|
|
6096
|
-
|
|
6097
|
-
|
|
6098
|
-
|
|
6099
|
-
|
|
6100
|
-
|
|
6101
|
-
if (typeof getTests !== "function") {
|
|
6102
|
-
return new TestReport({
|
|
6103
|
-
modules: [new ModuleTestReport({ path, suites: [], counts })]
|
|
6104
|
-
});
|
|
6083
|
+
|
|
6084
|
+
class Stack {
|
|
6085
|
+
constructor(comps, it, binds, dynBinds, views, viewsId, ctx = null) {
|
|
6086
|
+
this.comps = comps;
|
|
6087
|
+
this.it = it;
|
|
6088
|
+
this.binds = binds;
|
|
6089
|
+
this.dynBinds = dynBinds;
|
|
6090
|
+
this.views = views;
|
|
6091
|
+
this.viewsId = viewsId;
|
|
6092
|
+
this.ctx = ctx;
|
|
6105
6093
|
}
|
|
6106
|
-
|
|
6107
|
-
|
|
6094
|
+
_pushProvides() {
|
|
6095
|
+
const provide = this.comps.getCompFor(this.it)?.provide;
|
|
6096
|
+
if (provide == null)
|
|
6097
|
+
return this;
|
|
6098
|
+
const dynObj = {};
|
|
6099
|
+
let has = false;
|
|
6100
|
+
for (const k in provide) {
|
|
6101
|
+
dynObj[provide[k].symbol] = provide[k].val.eval(this);
|
|
6102
|
+
has = true;
|
|
6103
|
+
}
|
|
6104
|
+
if (!has)
|
|
6105
|
+
return this;
|
|
6106
|
+
const newDynBinds = [new ObjectFrame(dynObj), this.dynBinds];
|
|
6107
|
+
const { comps, it, binds, views, viewsId, ctx } = this;
|
|
6108
|
+
return new Stack(comps, it, binds, newDynBinds, views, viewsId, ctx);
|
|
6108
6109
|
}
|
|
6109
|
-
|
|
6110
|
-
|
|
6111
|
-
|
|
6112
|
-
|
|
6113
|
-
|
|
6114
|
-
|
|
6115
|
-
|
|
6116
|
-
|
|
6117
|
-
|
|
6118
|
-
|
|
6119
|
-
|
|
6120
|
-
|
|
6121
|
-
|
|
6122
|
-
|
|
6123
|
-
|
|
6124
|
-
|
|
6125
|
-
|
|
6126
|
-
|
|
6127
|
-
|
|
6128
|
-
|
|
6129
|
-
|
|
6130
|
-
|
|
6131
|
-
|
|
6132
|
-
|
|
6133
|
-
|
|
6134
|
-
|
|
6135
|
-
|
|
6136
|
-
|
|
6137
|
-
|
|
6138
|
-
|
|
6139
|
-
|
|
6140
|
-
|
|
6141
|
-
|
|
6142
|
-
if (bail)
|
|
6143
|
-
bailed = true;
|
|
6144
|
-
return new TestResult({
|
|
6145
|
-
title: node.title,
|
|
6146
|
-
fullPath,
|
|
6147
|
-
componentName: node.componentName,
|
|
6148
|
-
status: "fail",
|
|
6149
|
-
durationMs: performance.now() - start,
|
|
6150
|
-
error: captureError(e)
|
|
6151
|
-
});
|
|
6152
|
-
}
|
|
6153
|
-
}
|
|
6154
|
-
const childResults = [];
|
|
6155
|
-
for (const child of node.children) {
|
|
6156
|
-
const r = await visit(child);
|
|
6157
|
-
if (r !== null)
|
|
6158
|
-
childResults.push(r);
|
|
6159
|
-
}
|
|
6160
|
-
if (childResults.length === 0)
|
|
6110
|
+
static root(comps, it, ctx) {
|
|
6111
|
+
const binds = [new BindFrame(it, { it }, true), null];
|
|
6112
|
+
const dynBinds = [new ObjectFrame({}), null];
|
|
6113
|
+
const views = ["main", null];
|
|
6114
|
+
return new Stack(comps, it, binds, dynBinds, views, "", ctx)._pushProvides();
|
|
6115
|
+
}
|
|
6116
|
+
enter(it, bindings = {}, isFrame = true) {
|
|
6117
|
+
const { comps, binds, dynBinds, views, viewsId, ctx } = this;
|
|
6118
|
+
const newBinds = [new BindFrame(it, bindings, isFrame), binds];
|
|
6119
|
+
const stack = new Stack(comps, it, newBinds, dynBinds, views, viewsId, ctx);
|
|
6120
|
+
return isFrame ? stack._pushProvides() : stack;
|
|
6121
|
+
}
|
|
6122
|
+
pushViewName(name) {
|
|
6123
|
+
const { comps, it, binds, dynBinds, views, ctx } = this;
|
|
6124
|
+
const newViews = [name, views];
|
|
6125
|
+
return new Stack(comps, it, binds, dynBinds, newViews, computeViewsId(newViews), ctx);
|
|
6126
|
+
}
|
|
6127
|
+
_pushDynBindValuesToArray(arr, comp) {
|
|
6128
|
+
for (const k in comp.provide)
|
|
6129
|
+
arr.push(this._lookupProvide(comp.provide[k]));
|
|
6130
|
+
for (const k in comp.lookup)
|
|
6131
|
+
arr.push(this._lookupAlias(comp.lookup[k]));
|
|
6132
|
+
}
|
|
6133
|
+
_lookupProvide(p) {
|
|
6134
|
+
return lookup(this.dynBinds, p.symbol) ?? p.val.eval(this) ?? null;
|
|
6135
|
+
}
|
|
6136
|
+
_lookupAlias(lk) {
|
|
6137
|
+
const sym = lk.getProducerSymbol(this);
|
|
6138
|
+
return (sym != null ? lookup(this.dynBinds, sym) : null) ?? lk.val?.eval(this) ?? null;
|
|
6139
|
+
}
|
|
6140
|
+
lookupDynamic(name) {
|
|
6141
|
+
const comp = this.comps.getCompFor(this.it);
|
|
6142
|
+
if (comp == null)
|
|
6161
6143
|
return null;
|
|
6162
|
-
|
|
6163
|
-
|
|
6164
|
-
|
|
6165
|
-
|
|
6166
|
-
|
|
6144
|
+
const lk = comp.lookup[name];
|
|
6145
|
+
if (lk !== undefined)
|
|
6146
|
+
return this._lookupAlias(lk);
|
|
6147
|
+
const p = comp.provide[name];
|
|
6148
|
+
return p !== undefined ? this._lookupProvide(p) : null;
|
|
6167
6149
|
}
|
|
6168
|
-
|
|
6169
|
-
|
|
6170
|
-
const r = await visit(suite);
|
|
6171
|
-
if (r !== null)
|
|
6172
|
-
suiteResults.push(r);
|
|
6150
|
+
lookupBind(name) {
|
|
6151
|
+
return lookup(this.binds, name);
|
|
6173
6152
|
}
|
|
6174
|
-
|
|
6175
|
-
|
|
6176
|
-
});
|
|
6177
|
-
}
|
|
6178
|
-
|
|
6179
|
-
// tools/core/test-console.js
|
|
6180
|
-
var PASS = "color: #0a0; font-weight: bold";
|
|
6181
|
-
var FAIL = "color: #c00; font-weight: bold";
|
|
6182
|
-
var SKIP = "color: #888";
|
|
6183
|
-
var DIM = "color: #888";
|
|
6184
|
-
var RESET = "color: inherit; font-weight: normal";
|
|
6185
|
-
function reportTestNode(node) {
|
|
6186
|
-
if (node.children) {
|
|
6187
|
-
const label = node.componentName ? `${node.title} [${node.componentName}]` : node.title;
|
|
6188
|
-
console.group(label);
|
|
6189
|
-
for (const child of node.children)
|
|
6190
|
-
reportTestNode(child);
|
|
6191
|
-
console.groupEnd();
|
|
6192
|
-
return;
|
|
6153
|
+
lookupType(name) {
|
|
6154
|
+
return this.comps.getCompFor(this.it).scope.lookupComponent(name);
|
|
6193
6155
|
}
|
|
6194
|
-
|
|
6195
|
-
|
|
6196
|
-
console.log(`%c✓%c ${node.title}%c${dur}`, PASS, RESET, DIM);
|
|
6197
|
-
} else if (node.status === "skip") {
|
|
6198
|
-
console.log(`%c○ ${node.title}%c (skipped)`, SKIP, RESET);
|
|
6199
|
-
} else {
|
|
6200
|
-
console.group(`%c✗%c ${node.title}%c${dur}`, FAIL, RESET, DIM);
|
|
6201
|
-
console.error(node.error?.message ?? "(no error message)");
|
|
6202
|
-
if (node.error && (("expected" in node.error) || ("actual" in node.error))) {
|
|
6203
|
-
console.log("expected:", node.error.expected);
|
|
6204
|
-
console.log("actual: ", node.error.actual);
|
|
6205
|
-
}
|
|
6206
|
-
if (node.error?.stack)
|
|
6207
|
-
console.log(node.error.stack);
|
|
6208
|
-
console.groupEnd();
|
|
6156
|
+
lookupFieldRaw(name) {
|
|
6157
|
+
return this.it[name] ?? null;
|
|
6209
6158
|
}
|
|
6210
|
-
|
|
6211
|
-
|
|
6212
|
-
|
|
6213
|
-
|
|
6214
|
-
|
|
6215
|
-
|
|
6216
|
-
|
|
6217
|
-
|
|
6218
|
-
|
|
6219
|
-
|
|
6159
|
+
lookupMethod(name) {
|
|
6160
|
+
const fn = this.it[name];
|
|
6161
|
+
return fn instanceof Function ? fn.call(this.it) : null;
|
|
6162
|
+
}
|
|
6163
|
+
lookupName(name) {
|
|
6164
|
+
return this.ctx.lookupName(name);
|
|
6165
|
+
}
|
|
6166
|
+
getHandlerFor(name, key) {
|
|
6167
|
+
return this.comps.getHandlerFor(this.it, name, key);
|
|
6168
|
+
}
|
|
6169
|
+
lookupRequest(name) {
|
|
6170
|
+
return this.comps.getRequestFor(this.it, name);
|
|
6171
|
+
}
|
|
6172
|
+
lookupBestView(views, defaultViewName) {
|
|
6173
|
+
let n = this.views;
|
|
6174
|
+
while (n !== null) {
|
|
6175
|
+
const view = views[n[0]];
|
|
6176
|
+
if (view !== undefined)
|
|
6177
|
+
return view;
|
|
6178
|
+
n = n[1];
|
|
6220
6179
|
}
|
|
6221
|
-
|
|
6222
|
-
const summary = `${c.pass} passed, ${c.fail} failed, ${c.skip} skipped (${c.total} total)`;
|
|
6223
|
-
if (c.fail > 0)
|
|
6224
|
-
console.error(`%c${summary}`, FAIL);
|
|
6225
|
-
else if (c.total === 0)
|
|
6226
|
-
console.log(`%c${summary}`, DIM);
|
|
6227
|
-
else
|
|
6228
|
-
console.log(`%c${summary}`, PASS);
|
|
6229
|
-
console.groupEnd();
|
|
6180
|
+
return views[defaultViewName];
|
|
6230
6181
|
}
|
|
6231
|
-
return report;
|
|
6232
6182
|
}
|
|
6233
6183
|
|
|
6234
|
-
//
|
|
6235
|
-
|
|
6236
|
-
|
|
6237
|
-
|
|
6238
|
-
|
|
6239
|
-
"call-with-args": "method call with arguments"
|
|
6240
|
-
};
|
|
6241
|
-
function unsupportedExprMessage(info) {
|
|
6242
|
-
const v = JSON.stringify(info.value);
|
|
6243
|
-
const label = UNSUPPORTED_EXPR_LABEL[info.detected] ?? "expression";
|
|
6244
|
-
switch (info.role) {
|
|
6245
|
-
case "attr":
|
|
6246
|
-
return `Unsupported ${label} ${v} in dynamic attribute ':${info.attr}'`;
|
|
6247
|
-
case "directive":
|
|
6248
|
-
return `Unsupported ${label} ${v} in directive '@${info.directive}'`;
|
|
6249
|
-
case "if":
|
|
6250
|
-
return `Unsupported ${label} ${v} in '@if.${info.attr}' condition`;
|
|
6251
|
-
case "x-op":
|
|
6252
|
-
return `Unsupported ${label} ${v} in <x ${info.op}>`;
|
|
6253
|
-
default:
|
|
6254
|
-
return `Unsupported ${label} ${v}`;
|
|
6184
|
+
// src/transactor.js
|
|
6185
|
+
class State2 {
|
|
6186
|
+
constructor(val) {
|
|
6187
|
+
this.val = val;
|
|
6188
|
+
this.changeSubs = [];
|
|
6255
6189
|
}
|
|
6256
|
-
|
|
6257
|
-
|
|
6258
|
-
const v = JSON.stringify(info.value);
|
|
6259
|
-
switch (info.role) {
|
|
6260
|
-
case "attr":
|
|
6261
|
-
return `Cannot parse value ${v} for attribute ':${info.attr}'`;
|
|
6262
|
-
case "directive":
|
|
6263
|
-
return `Cannot parse value ${v} for directive '@${info.directive}'`;
|
|
6264
|
-
case "if":
|
|
6265
|
-
return `Cannot parse condition ${v} for '@if.${info.attr}'`;
|
|
6266
|
-
case "x-op":
|
|
6267
|
-
return `Cannot parse value ${v} for <x ${info.op}>`;
|
|
6268
|
-
case "handler-name":
|
|
6269
|
-
return `Cannot parse handler name ${v}`;
|
|
6270
|
-
case "handler-arg":
|
|
6271
|
-
return `Cannot parse handler argument ${v}`;
|
|
6272
|
-
case "macro-var":
|
|
6273
|
-
return `Macro variable '^${info.name}' is not defined`;
|
|
6274
|
-
default:
|
|
6275
|
-
return `Cannot parse value ${v}`;
|
|
6190
|
+
onChange(cb) {
|
|
6191
|
+
this.changeSubs.push(cb);
|
|
6276
6192
|
}
|
|
6277
|
-
|
|
6278
|
-
|
|
6279
|
-
|
|
6280
|
-
|
|
6281
|
-
|
|
6282
|
-
const t = tagDisplay(info?.tag);
|
|
6283
|
-
return t && t !== "x" ? ` on <${t}>` : "";
|
|
6284
|
-
}
|
|
6285
|
-
function fmtOriginSuffix(info) {
|
|
6286
|
-
if (!info)
|
|
6287
|
-
return "";
|
|
6288
|
-
const parts = [];
|
|
6289
|
-
if (info.originAttr) {
|
|
6290
|
-
const branch = info.branch ? `[${info.branch}]` : "";
|
|
6291
|
-
parts.push(`in ${info.originAttr}${branch}`);
|
|
6193
|
+
set(val, info) {
|
|
6194
|
+
const old = this.val;
|
|
6195
|
+
this.val = val;
|
|
6196
|
+
for (const sub of this.changeSubs)
|
|
6197
|
+
sub({ val, old, info, timestamp: Date.now() });
|
|
6292
6198
|
}
|
|
6293
|
-
|
|
6294
|
-
|
|
6199
|
+
update(fn, info) {
|
|
6200
|
+
return this.set(fn(this.val), info);
|
|
6295
6201
|
}
|
|
6296
|
-
const t = tagDisplay(info.tag);
|
|
6297
|
-
if (t && t !== "x")
|
|
6298
|
-
parts.push(`on <${t}>`);
|
|
6299
|
-
return parts.length ? ` (${parts.join(", ")})` : "";
|
|
6300
|
-
}
|
|
6301
|
-
function fmtEventSuffix(info) {
|
|
6302
|
-
if (info?.originAttr)
|
|
6303
|
-
return ` in ${info.originAttr}`;
|
|
6304
|
-
if (info?.eventName)
|
|
6305
|
-
return ` in @on.${info.eventName}`;
|
|
6306
|
-
return "";
|
|
6307
6202
|
}
|
|
6308
|
-
|
|
6309
|
-
|
|
6310
|
-
|
|
6311
|
-
|
|
6312
|
-
|
|
6313
|
-
|
|
6314
|
-
|
|
6315
|
-
|
|
6316
|
-
|
|
6317
|
-
|
|
6318
|
-
|
|
6319
|
-
|
|
6320
|
-
|
|
6321
|
-
|
|
6322
|
-
|
|
6323
|
-
|
|
6324
|
-
|
|
6325
|
-
case "INPUT_HANDLER_FOR_INPUT_HANDLER_METHOD":
|
|
6326
|
-
return `'$${info.name}' is a method reference, but '${info.name}' is defined as an input handler${fmtEventSuffix(info)}`;
|
|
6327
|
-
case "INPUT_HANDLER_METHOD_FOR_INPUT_HANDLER":
|
|
6328
|
-
return `'${info.name}' is an input handler reference, but '${info.name}' is defined as a method${fmtEventSuffix(info)}`;
|
|
6329
|
-
case "FIELD_VAL_NOT_DEFINED":
|
|
6330
|
-
return `Field '.${info.name}' is not defined${fmtOriginSuffix(info)}`;
|
|
6331
|
-
case "FIELD_VAL_IS_METHOD":
|
|
6332
|
-
return `'.${info.name}' reads a field, but '${info.name}' is defined as a method — use '$${info.name}'${fmtOriginSuffix(info)}`;
|
|
6333
|
-
case "METHOD_VAL_NOT_DEFINED":
|
|
6334
|
-
return `Method '$${info.name}' is not defined${fmtOriginSuffix(info)}`;
|
|
6335
|
-
case "METHOD_VAL_IS_FIELD":
|
|
6336
|
-
return `'$${info.name}' calls a method, but '${info.name}' is defined as a field — use '.${info.name}'${fmtOriginSuffix(info)}`;
|
|
6337
|
-
case "DUPLICATE_ATTR_DEFINITION": {
|
|
6338
|
-
const sources = info.sources?.length ? ` (${info.sources.join(", ")})` : "";
|
|
6339
|
-
const tag = info.tag ? ` on <${String(info.tag).toLowerCase()}>` : "";
|
|
6340
|
-
return `Attribute '${info.name}' is set ${info.sources?.length ?? "multiple"} times${sources}${tag}`;
|
|
6203
|
+
|
|
6204
|
+
class Transactor {
|
|
6205
|
+
constructor(comps, rootValue) {
|
|
6206
|
+
this.comps = comps;
|
|
6207
|
+
this.transactions = [];
|
|
6208
|
+
this.state = new State2(rootValue);
|
|
6209
|
+
this.onTransactionPushed = () => {};
|
|
6210
|
+
this._inflight = new Set;
|
|
6211
|
+
}
|
|
6212
|
+
pushTransaction(t) {
|
|
6213
|
+
this.transactions.push(t);
|
|
6214
|
+
this.onTransactionPushed(t);
|
|
6215
|
+
}
|
|
6216
|
+
_link(child, parent) {
|
|
6217
|
+
if (parent) {
|
|
6218
|
+
const release = parent.completion.track();
|
|
6219
|
+
child.completion.whenSubtreeSettled().then(release);
|
|
6341
6220
|
}
|
|
6342
|
-
|
|
6343
|
-
|
|
6344
|
-
|
|
6345
|
-
|
|
6346
|
-
|
|
6347
|
-
|
|
6348
|
-
|
|
6349
|
-
|
|
6350
|
-
|
|
6351
|
-
|
|
6352
|
-
|
|
6353
|
-
|
|
6354
|
-
|
|
6355
|
-
|
|
6356
|
-
|
|
6357
|
-
|
|
6358
|
-
|
|
6359
|
-
|
|
6360
|
-
|
|
6361
|
-
|
|
6362
|
-
|
|
6363
|
-
|
|
6364
|
-
|
|
6365
|
-
|
|
6366
|
-
|
|
6367
|
-
|
|
6368
|
-
|
|
6369
|
-
|
|
6370
|
-
|
|
6371
|
-
|
|
6372
|
-
|
|
6221
|
+
return child;
|
|
6222
|
+
}
|
|
6223
|
+
pushSend(path, name, args = [], opts = {}, parent = null) {
|
|
6224
|
+
const t = new SendEvent(path, this, name, args, parent, opts);
|
|
6225
|
+
this.pushTransaction(t);
|
|
6226
|
+
return this._link(t, parent);
|
|
6227
|
+
}
|
|
6228
|
+
pushInput(path, name, args = [], opts = {}, parent = null) {
|
|
6229
|
+
const t = new InputDispatchEvent(path, this, name, args, parent, opts);
|
|
6230
|
+
this.pushTransaction(t);
|
|
6231
|
+
return this._link(t, parent);
|
|
6232
|
+
}
|
|
6233
|
+
pushBubble(path, name, args = [], opts = {}, parent = null, targetPath = null) {
|
|
6234
|
+
const newOpts = opts.skipSelf ? { ...opts, skipSelf: false } : opts;
|
|
6235
|
+
const t = new BubbleEvent(path, this, name, args, parent, newOpts, targetPath);
|
|
6236
|
+
this.pushTransaction(t);
|
|
6237
|
+
return this._link(t, parent);
|
|
6238
|
+
}
|
|
6239
|
+
pushRequest(path, name, args = [], opts = {}, parent = null) {
|
|
6240
|
+
const release = parent ? parent.completion.track() : null;
|
|
6241
|
+
const p = this._runRequest(path, name, args, opts, parent, release);
|
|
6242
|
+
this._inflight.add(p);
|
|
6243
|
+
p.finally(() => this._inflight.delete(p));
|
|
6244
|
+
return p;
|
|
6245
|
+
}
|
|
6246
|
+
async settle(maxTurns = 1e4) {
|
|
6247
|
+
while ((this.hasPendingTransactions || this._inflight.size) && maxTurns-- > 0) {
|
|
6248
|
+
while (this.hasPendingTransactions)
|
|
6249
|
+
this.transactNext();
|
|
6250
|
+
if (this._inflight.size)
|
|
6251
|
+
await Promise.allSettled([...this._inflight]);
|
|
6252
|
+
}
|
|
6253
|
+
}
|
|
6254
|
+
async _runRequest(path, name, args = [], opts = {}, parent = null, release = null) {
|
|
6255
|
+
let released = false;
|
|
6256
|
+
const transfer = (t) => {
|
|
6257
|
+
if (release) {
|
|
6258
|
+
released = true;
|
|
6259
|
+
t.completion.whenSubtreeSettled().then(release);
|
|
6260
|
+
}
|
|
6261
|
+
};
|
|
6262
|
+
try {
|
|
6263
|
+
const curRoot = this.state.val;
|
|
6264
|
+
const txnPath = path.toTransactionPath();
|
|
6265
|
+
const curLeaf = txnPath.lookup(curRoot);
|
|
6266
|
+
const handler = this.comps.getRequestFor(curLeaf, name) ?? mkReq404(name);
|
|
6267
|
+
const reqCtx = new RequestContext(path, this, parent, curRoot);
|
|
6268
|
+
const resHandlerName = opts?.onResName ?? name;
|
|
6269
|
+
const resPath = opts?.livePath ? null : txnPath.pinKeys(curRoot);
|
|
6270
|
+
const push = (specificName, baseName, singleArg, result, error) => {
|
|
6271
|
+
const resArgs = specificName ? [singleArg] : [result, error];
|
|
6272
|
+
const t = new ResponseEvent(path, this, specificName ?? baseName, resArgs, parent, resPath);
|
|
6273
|
+
transfer(t);
|
|
6274
|
+
this.pushTransaction(t);
|
|
6275
|
+
};
|
|
6276
|
+
try {
|
|
6277
|
+
const result = await handler.fn.apply(null, [...args, reqCtx]);
|
|
6278
|
+
push(opts?.onOkName, resHandlerName, result, result, null);
|
|
6279
|
+
} catch (error) {
|
|
6280
|
+
push(opts?.onErrorName, resHandlerName, error, null, error);
|
|
6281
|
+
}
|
|
6282
|
+
} finally {
|
|
6283
|
+
if (release && !released)
|
|
6284
|
+
release();
|
|
6373
6285
|
}
|
|
6374
|
-
case "MAYBE_ADD_AT_PREFIX":
|
|
6375
|
-
return `'${info.name}' on <${(info.tag ?? "").toLowerCase()}> is a plain attribute, but '@${info.name}' is a directive — add the leading '@'`;
|
|
6376
|
-
case "BAD_VALUE":
|
|
6377
|
-
return `${badValueMessage(info)}${fmtTagSuffix(info)}`;
|
|
6378
|
-
case "UNSUPPORTED_EXPR_SYNTAX":
|
|
6379
|
-
return `${unsupportedExprMessage(info)}${fmtTagSuffix(info)}`;
|
|
6380
|
-
case "REDUNDANT_TEMPLATE_STRING":
|
|
6381
|
-
return `Redundant template string — '{${info.simpler}}' should be just '${info.simpler}'${fmtOriginSuffix(info)}`;
|
|
6382
|
-
case "PLACEHOLDERLESS_TEMPLATE_STRING":
|
|
6383
|
-
return `Template string has no dynamic parts — use the string literal ${info.literal} instead${fmtOriginSuffix(info)}`;
|
|
6384
|
-
case "UNKNOWN_COMPONENT_SPEC_KEY":
|
|
6385
|
-
return `Unknown component spec key '${info.key}' — value will be ignored at runtime`;
|
|
6386
|
-
case "COMP_FIELD_BAD_SHAPE":
|
|
6387
|
-
return info.kind === "args-not-object" ? `Field '${info.fieldName}': in { component, args }, 'args' must be a plain object, got ${info.got}` : `Field '${info.fieldName}': in { component, args }, 'component' must be the component name as a string, got ${info.gotName ? `the ${info.gotName} class` : info.got}`;
|
|
6388
|
-
case "HTML_TAG_NAME_HAS_UPPERCASE":
|
|
6389
|
-
return `Tag <${info.raw}> will be lowercased to <${info.lowercased}>${fmtLocationSuffix(info)}`;
|
|
6390
|
-
case "HTML_SVG_TAG_WILL_LOWERCASE":
|
|
6391
|
-
return `SVG tag <${info.raw}> is not in the WHATWG case-correction list — will be lowercased to <${info.lowercased}>${fmtLocationSuffix(info)}`;
|
|
6392
|
-
case "HTML_TAG_NOT_ALLOWED_IN_PARENT":
|
|
6393
|
-
return `<${info.tag}> not allowed under <${info.parent ?? "?"}> in ${info.mode} — ${htmlActionPhrase(info.action, info.tag, info.parent)}${fmtLocationSuffix(info)}`;
|
|
6394
|
-
case "HTML_TEXT_NOT_ALLOWED_IN_PARENT":
|
|
6395
|
-
return `Non-whitespace text not allowed in ${info.mode}: ${JSON.stringify(info.snippet)}${fmtLocationSuffix(info)}`;
|
|
6396
|
-
case "HTML_VOID_ELEMENT_HAS_CLOSE_TAG":
|
|
6397
|
-
return `Void element <${info.tag}> has an explicit close tag${fmtLocationSuffix(info)}`;
|
|
6398
|
-
case "HTML_DUPLICATE_FORM":
|
|
6399
|
-
return `Nested <form> — the inner form will be dropped by the parser${fmtLocationSuffix(info)}`;
|
|
6400
|
-
case "HTML_NESTED_INTERACTIVE":
|
|
6401
|
-
return `<${info.tag}> nested inside another <${info.tag}> — adoption agency will reorder${fmtLocationSuffix(info)}`;
|
|
6402
|
-
case "HTML_MISNESTED_FORMATTING":
|
|
6403
|
-
return `Misnested formatting tag </${info.tag}> — adoption agency will reorder nodes${fmtLocationSuffix(info)}`;
|
|
6404
|
-
case "HTML_UNEXPECTED_END_TAG":
|
|
6405
|
-
return `Unexpected end tag </${info.tag}>${fmtLocationSuffix(info)}`;
|
|
6406
|
-
case "HTML_UNCLOSED_BEFORE_END":
|
|
6407
|
-
return `<${info.unclosed}> still open when </${info.tag}> was seen — implicitly closed${fmtLocationSuffix(info)}`;
|
|
6408
|
-
case "HTML_DUPLICATE_ATTRIBUTE":
|
|
6409
|
-
return `Duplicate attribute '${info.name}' — second occurrence dropped${fmtLocationSuffix(info)}`;
|
|
6410
|
-
case "HTML_ATTRIBUTES_ON_END_TAG":
|
|
6411
|
-
return `Attributes on end tag </${info.tag}> — dropped by the parser${fmtLocationSuffix(info)}`;
|
|
6412
|
-
case "HTML_SELF_CLOSING_END_TAG":
|
|
6413
|
-
return `Self-closing end tag </${info.tag}/> — trailing '/' is meaningless${fmtLocationSuffix(info)}`;
|
|
6414
|
-
case "HTML_MISSING_ATTRIBUTE_VALUE":
|
|
6415
|
-
return `Attribute '${info.name}' is missing a value${fmtLocationSuffix(info)}`;
|
|
6416
|
-
case "HTML_CDATA_IN_HTML_NAMESPACE":
|
|
6417
|
-
return `CDATA section in HTML namespace — reinterpreted as a bogus comment${fmtLocationSuffix(info)}`;
|
|
6418
|
-
case "HTML_BOGUS_COMMENT":
|
|
6419
|
-
return `Bogus comment — content dropped by the parser${fmtLocationSuffix(info)}`;
|
|
6420
|
-
case "HTML_SVG_ATTR_WILL_LOWERCASE":
|
|
6421
|
-
return `SVG attribute '${info.raw}' will be rewritten to '${info.canonical}'${fmtLocationSuffix(info)}`;
|
|
6422
|
-
case "HTML_MATHML_ATTR_WILL_LOWERCASE":
|
|
6423
|
-
return `MathML attribute '${info.raw}' will be rewritten to '${info.canonical}'${fmtLocationSuffix(info)}`;
|
|
6424
|
-
case "ASYNC_HANDLER":
|
|
6425
|
-
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)`;
|
|
6426
|
-
case "TOP_LEVEL_AT_RULE_IN_SCOPED_STYLE":
|
|
6427
|
-
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)}`;
|
|
6428
|
-
case "GLOBAL_SELECTOR_IN_SCOPED_STYLE":
|
|
6429
|
-
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)}`;
|
|
6430
|
-
case "LINT_ERROR":
|
|
6431
|
-
return info.message;
|
|
6432
|
-
default:
|
|
6433
|
-
return id;
|
|
6434
6286
|
}
|
|
6435
|
-
|
|
6436
|
-
|
|
6437
|
-
|
|
6438
|
-
|
|
6439
|
-
|
|
6440
|
-
|
|
6441
|
-
|
|
6442
|
-
|
|
6443
|
-
|
|
6444
|
-
|
|
6445
|
-
|
|
6446
|
-
|
|
6447
|
-
|
|
6448
|
-
|
|
6449
|
-
|
|
6450
|
-
|
|
6451
|
-
|
|
6452
|
-
|
|
6453
|
-
|
|
6454
|
-
|
|
6455
|
-
|
|
6287
|
+
get hasPendingTransactions() {
|
|
6288
|
+
return this.transactions.length > 0;
|
|
6289
|
+
}
|
|
6290
|
+
transactNext() {
|
|
6291
|
+
if (this.hasPendingTransactions)
|
|
6292
|
+
this.transact(this.transactions.shift());
|
|
6293
|
+
}
|
|
6294
|
+
transact(transaction) {
|
|
6295
|
+
try {
|
|
6296
|
+
const curState = this.state.val;
|
|
6297
|
+
const newState = transaction.run(curState, this.comps);
|
|
6298
|
+
if (newState !== undefined) {
|
|
6299
|
+
this.state.set(newState, { transaction });
|
|
6300
|
+
transaction.afterTransaction();
|
|
6301
|
+
} else
|
|
6302
|
+
console.warn("undefined new state", { curState, transaction });
|
|
6303
|
+
} finally {
|
|
6304
|
+
transaction._completion?.ensureSelfSettled();
|
|
6305
|
+
transaction._completion?.releaseSelf();
|
|
6306
|
+
}
|
|
6307
|
+
}
|
|
6308
|
+
transactInputNow(path, event, eventHandler, dragInfo) {
|
|
6309
|
+
this.transact(new InputEvent(path, event, eventHandler, this, dragInfo));
|
|
6456
6310
|
}
|
|
6457
6311
|
}
|
|
6458
|
-
function
|
|
6459
|
-
const
|
|
6460
|
-
|
|
6461
|
-
|
|
6462
|
-
return
|
|
6312
|
+
function mkReq404(name) {
|
|
6313
|
+
const fn = () => {
|
|
6314
|
+
throw new Error(`Request not found: ${name}`);
|
|
6315
|
+
};
|
|
6316
|
+
return { fn };
|
|
6463
6317
|
}
|
|
6464
|
-
function
|
|
6465
|
-
|
|
6466
|
-
case "ignored":
|
|
6467
|
-
return `the parser will drop this <${tag}>`;
|
|
6468
|
-
case "drop":
|
|
6469
|
-
return `the parser will drop this <${tag}>`;
|
|
6470
|
-
case "auto-close-implicit":
|
|
6471
|
-
return `the parser will close <${parent ?? "?"}> first, then place <${tag}> as a sibling`;
|
|
6472
|
-
case "foster-parent":
|
|
6473
|
-
return `the parser will move <${tag}> outside <${parent ?? "?"}> (foster-parenting)`;
|
|
6474
|
-
case "foreign-breakout":
|
|
6475
|
-
return `the parser will exit foreign content and re-process <${tag}> in HTML mode`;
|
|
6476
|
-
default:
|
|
6477
|
-
return `parser action: ${action}`;
|
|
6478
|
-
}
|
|
6318
|
+
function nullHandler() {
|
|
6319
|
+
return this;
|
|
6479
6320
|
}
|
|
6480
6321
|
|
|
6481
|
-
|
|
6482
|
-
|
|
6483
|
-
|
|
6484
|
-
this.
|
|
6485
|
-
this.
|
|
6322
|
+
class Transaction {
|
|
6323
|
+
constructor(path, transactor, parentTransaction = null) {
|
|
6324
|
+
this.path = path;
|
|
6325
|
+
this.transactor = transactor;
|
|
6326
|
+
this.parentTransaction = parentTransaction;
|
|
6327
|
+
this._completion = null;
|
|
6486
6328
|
}
|
|
6487
|
-
|
|
6488
|
-
|
|
6489
|
-
this.
|
|
6329
|
+
get completion() {
|
|
6330
|
+
this._completion ??= new Completion;
|
|
6331
|
+
return this._completion;
|
|
6490
6332
|
}
|
|
6491
|
-
|
|
6492
|
-
return this.
|
|
6333
|
+
whenSettled() {
|
|
6334
|
+
return this.completion.whenSettled();
|
|
6493
6335
|
}
|
|
6494
|
-
|
|
6495
|
-
return
|
|
6336
|
+
whenSubtreeSettled() {
|
|
6337
|
+
return this.completion.whenSubtreeSettled();
|
|
6496
6338
|
}
|
|
6497
|
-
|
|
6498
|
-
return this.
|
|
6339
|
+
run(rootValue, comps) {
|
|
6340
|
+
return this.updateRootValue(rootValue, comps);
|
|
6499
6341
|
}
|
|
6500
|
-
|
|
6501
|
-
|
|
6342
|
+
afterTransaction() {}
|
|
6343
|
+
buildRootStack(root, comps) {
|
|
6344
|
+
return Stack.root(comps, root);
|
|
6502
6345
|
}
|
|
6503
|
-
|
|
6504
|
-
|
|
6505
|
-
for (const comp of this.byId.values())
|
|
6506
|
-
styles.push(comp.compileStyle());
|
|
6507
|
-
return styles.join(`
|
|
6508
|
-
`);
|
|
6346
|
+
buildStack(root, comps) {
|
|
6347
|
+
return this.path.toTransactionPath().buildStack(this.buildRootStack(root, comps));
|
|
6509
6348
|
}
|
|
6510
|
-
|
|
6511
|
-
|
|
6512
|
-
|
|
6513
|
-
constructor(comps = new Components, parent = null) {
|
|
6514
|
-
this.comps = comps;
|
|
6515
|
-
this.parent = parent;
|
|
6516
|
-
this.byName = {};
|
|
6517
|
-
this.reqsByName = {};
|
|
6518
|
-
this.macros = {};
|
|
6349
|
+
callHandler(root, instance, comps) {
|
|
6350
|
+
const [handler, args] = this.getHandlerAndArgs(root, instance, comps);
|
|
6351
|
+
return handler.apply(instance, args);
|
|
6519
6352
|
}
|
|
6520
|
-
|
|
6521
|
-
return
|
|
6353
|
+
getHandlerAndArgs(_root, _instance, _comps) {
|
|
6354
|
+
return null;
|
|
6522
6355
|
}
|
|
6523
|
-
|
|
6524
|
-
|
|
6525
|
-
for (let i = 0;i < comps.length; i++) {
|
|
6526
|
-
const comp = comps[i];
|
|
6527
|
-
comp.scope = this.enter();
|
|
6528
|
-
comp.Class.scope = comp.scope;
|
|
6529
|
-
this.comps.registerComponent(comp);
|
|
6530
|
-
this.byName[comp.name] = comp;
|
|
6531
|
-
}
|
|
6532
|
-
for (const alias in aliases) {
|
|
6533
|
-
const comp = this.byName[aliases[alias]];
|
|
6534
|
-
console.assert(this.byName[alias] === undefined, "alias overrides component", alias);
|
|
6535
|
-
if (comp !== undefined)
|
|
6536
|
-
this.byName[alias] = comp;
|
|
6537
|
-
else
|
|
6538
|
-
console.warn("alias", alias, "to inexistent component", aliases[alias]);
|
|
6539
|
-
}
|
|
6356
|
+
getTransactionPath() {
|
|
6357
|
+
return this.path.toTransactionPath();
|
|
6540
6358
|
}
|
|
6541
|
-
|
|
6542
|
-
|
|
6543
|
-
|
|
6544
|
-
|
|
6545
|
-
|
|
6546
|
-
|
|
6359
|
+
updateRootValue(curRoot, comps) {
|
|
6360
|
+
const txnPath = this.getTransactionPath();
|
|
6361
|
+
const curLeaf = txnPath.lookup(curRoot);
|
|
6362
|
+
const newLeaf = this.callHandler(curRoot, curLeaf, comps);
|
|
6363
|
+
this._completion?.markSelfSettled({ value: newLeaf, old: curLeaf });
|
|
6364
|
+
return curLeaf !== newLeaf ? txnPath.setValue(curRoot, newLeaf) : curRoot;
|
|
6547
6365
|
}
|
|
6548
|
-
|
|
6549
|
-
return
|
|
6366
|
+
lookupName(_name) {
|
|
6367
|
+
return null;
|
|
6550
6368
|
}
|
|
6551
|
-
|
|
6552
|
-
|
|
6553
|
-
|
|
6369
|
+
}
|
|
6370
|
+
var toNullIfNaN = (v) => Number.isNaN(v) ? null : v;
|
|
6371
|
+
function getValue(e) {
|
|
6372
|
+
return e.target.type === "checkbox" ? e.target.checked : (e instanceof CustomEvent ? e.detail : e.target.value) ?? null;
|
|
6373
|
+
}
|
|
6374
|
+
|
|
6375
|
+
class InputEvent extends Transaction {
|
|
6376
|
+
constructor(path, e, handler, transactor, dragInfo) {
|
|
6377
|
+
super(path, transactor);
|
|
6378
|
+
this.e = e;
|
|
6379
|
+
this.handler = handler;
|
|
6380
|
+
this.dragInfo = dragInfo;
|
|
6381
|
+
this._dispatchPath = null;
|
|
6554
6382
|
}
|
|
6555
|
-
|
|
6556
|
-
|
|
6383
|
+
get dispatchPath() {
|
|
6384
|
+
this._dispatchPath ??= this.path.compact();
|
|
6385
|
+
return this._dispatchPath;
|
|
6557
6386
|
}
|
|
6558
|
-
|
|
6559
|
-
return
|
|
6387
|
+
buildRootStack(root, comps) {
|
|
6388
|
+
return Stack.root(comps, root, this);
|
|
6560
6389
|
}
|
|
6561
|
-
|
|
6562
|
-
|
|
6390
|
+
getHandlerAndArgs(root, _instance, comps) {
|
|
6391
|
+
const stack = this.buildStack(root, comps);
|
|
6392
|
+
const [handler, args] = this.handler.getHandlerAndArgs(stack, this);
|
|
6393
|
+
const path = this.dispatchPath;
|
|
6394
|
+
let dispatcher;
|
|
6395
|
+
for (let i = 0;i < args.length; i++) {
|
|
6396
|
+
if (args[i]?.toHandlerArg) {
|
|
6397
|
+
dispatcher ??= new Dispatcher(path, this.transactor, this);
|
|
6398
|
+
args[i] = args[i].toHandlerArg(dispatcher);
|
|
6399
|
+
}
|
|
6400
|
+
}
|
|
6401
|
+
args.push(new EventContext(path, this.transactor, this));
|
|
6402
|
+
return [handler, args];
|
|
6403
|
+
}
|
|
6404
|
+
lookupName(name) {
|
|
6405
|
+
const { e } = this;
|
|
6406
|
+
switch (name) {
|
|
6407
|
+
case "value":
|
|
6408
|
+
return getValue(e);
|
|
6409
|
+
case "valueAsInt":
|
|
6410
|
+
return toNullIfNaN(parseInt(getValue(e), 10));
|
|
6411
|
+
case "valueAsFloat":
|
|
6412
|
+
return toNullIfNaN(parseFloat(getValue(e)));
|
|
6413
|
+
case "target":
|
|
6414
|
+
return e.target;
|
|
6415
|
+
case "event":
|
|
6416
|
+
return e;
|
|
6417
|
+
case "isAlt":
|
|
6418
|
+
return e.altKey;
|
|
6419
|
+
case "isShift":
|
|
6420
|
+
return e.shiftKey;
|
|
6421
|
+
case "isCtrl":
|
|
6422
|
+
case "isCmd":
|
|
6423
|
+
return isMac && e.metaKey || e.ctrlKey;
|
|
6424
|
+
case "key":
|
|
6425
|
+
return e.key;
|
|
6426
|
+
case "keyCode":
|
|
6427
|
+
return e.keyCode;
|
|
6428
|
+
case "isUpKey":
|
|
6429
|
+
return e.key === "ArrowUp";
|
|
6430
|
+
case "isDownKey":
|
|
6431
|
+
return e.key === "ArrowDown";
|
|
6432
|
+
case "isSend":
|
|
6433
|
+
return e.key === "Enter";
|
|
6434
|
+
case "isCancel":
|
|
6435
|
+
return e.key === "Escape";
|
|
6436
|
+
case "isTabKey":
|
|
6437
|
+
return e.key === "Tab";
|
|
6438
|
+
case "ctx":
|
|
6439
|
+
return new EventContext(this.dispatchPath, this.transactor, this);
|
|
6440
|
+
case "dragInfo":
|
|
6441
|
+
return this.dragInfo;
|
|
6442
|
+
}
|
|
6443
|
+
return null;
|
|
6563
6444
|
}
|
|
6564
6445
|
}
|
|
6565
6446
|
|
|
6566
|
-
class
|
|
6567
|
-
constructor(name,
|
|
6447
|
+
class NameArgsTransaction extends Transaction {
|
|
6448
|
+
constructor(path, transactor, name, args, parentTransaction, opts = {}) {
|
|
6449
|
+
super(path, transactor, parentTransaction);
|
|
6568
6450
|
this.name = name;
|
|
6569
|
-
this.
|
|
6570
|
-
this.
|
|
6451
|
+
this.args = args;
|
|
6452
|
+
this.opts = opts;
|
|
6453
|
+
this.targetPath = path;
|
|
6454
|
+
}
|
|
6455
|
+
handlerProp = null;
|
|
6456
|
+
getHandlerForName(comp) {
|
|
6457
|
+
const handlers = comp?.[this.handlerProp];
|
|
6458
|
+
return handlers?.[this.name] ?? handlers?.$unknown ?? nullHandler;
|
|
6459
|
+
}
|
|
6460
|
+
getHandlerAndArgs(_root, instance, comps) {
|
|
6461
|
+
const handler = this.getHandlerForName(comps.getCompFor(instance));
|
|
6462
|
+
return [handler, [...this.args, new EventContext(this.path, this.transactor, this)]];
|
|
6571
6463
|
}
|
|
6572
6464
|
}
|
|
6573
6465
|
|
|
6574
|
-
class
|
|
6575
|
-
|
|
6576
|
-
|
|
6577
|
-
|
|
6578
|
-
this.
|
|
6579
|
-
this.val = val;
|
|
6580
|
-
this._sym = undefined;
|
|
6466
|
+
class ResponseEvent extends NameArgsTransaction {
|
|
6467
|
+
handlerProp = "response";
|
|
6468
|
+
constructor(path, transactor, name, args, parent, txnPath = null) {
|
|
6469
|
+
super(path, transactor, name, args, parent);
|
|
6470
|
+
this._txnPath = txnPath;
|
|
6581
6471
|
}
|
|
6582
|
-
|
|
6583
|
-
|
|
6584
|
-
this._sym = stack.lookupType(this.compName)?.provide?.[this.provideName]?.symbol ?? null;
|
|
6585
|
-
return this._sym;
|
|
6472
|
+
getTransactionPath() {
|
|
6473
|
+
return this._txnPath ?? super.getTransactionPath();
|
|
6586
6474
|
}
|
|
6587
6475
|
}
|
|
6588
|
-
var isString = (v) => typeof v === "string";
|
|
6589
|
-
var _rawSpecKeys = "name view style commonStyle globalStyle input receive bubble response alter views provide lookup fields methods statics";
|
|
6590
|
-
var KNOWN_SPEC_KEYS = new Set(_rawSpecKeys.split(" "));
|
|
6591
|
-
var _compId = 0;
|
|
6592
6476
|
|
|
6593
|
-
class
|
|
6594
|
-
|
|
6595
|
-
|
|
6596
|
-
this.
|
|
6597
|
-
this.Class = Class;
|
|
6598
|
-
this.views = { main: new View("main", o.view, o.style) };
|
|
6599
|
-
this.commonStyle = o.commonStyle ?? "";
|
|
6600
|
-
this.globalStyle = o.globalStyle ?? "";
|
|
6601
|
-
this.input = o.input ?? {};
|
|
6602
|
-
this.receive = o.receive ?? {};
|
|
6603
|
-
this.bubble = o.bubble ?? {};
|
|
6604
|
-
this.response = o.response ?? {};
|
|
6605
|
-
this.alter = o.alter ?? {};
|
|
6606
|
-
for (const name in o.views ?? {}) {
|
|
6607
|
-
const v = o.views[name];
|
|
6608
|
-
const { view, style } = isString(v) ? { view: v } : v;
|
|
6609
|
-
this.views[name] = new View(name, view, style);
|
|
6610
|
-
}
|
|
6611
|
-
this._rawProvide = o.provide ?? {};
|
|
6612
|
-
this._rawLookup = o.lookup ?? {};
|
|
6613
|
-
this.provide = {};
|
|
6614
|
-
this.lookup = {};
|
|
6615
|
-
this.scope = null;
|
|
6616
|
-
this.spec = o;
|
|
6617
|
-
this.extra = {};
|
|
6618
|
-
for (const key of Object.keys(o))
|
|
6619
|
-
if (!KNOWN_SPEC_KEYS.has(key))
|
|
6620
|
-
this.extra[key] = o[key];
|
|
6477
|
+
class SendEvent extends NameArgsTransaction {
|
|
6478
|
+
handlerProp = "receive";
|
|
6479
|
+
run(rootVal, comps) {
|
|
6480
|
+
return this.opts.skipSelf ? rootVal : this.updateRootValue(rootVal, comps);
|
|
6621
6481
|
}
|
|
6622
|
-
|
|
6623
|
-
|
|
6482
|
+
afterTransaction() {
|
|
6483
|
+
const { path, name, args, opts, targetPath } = this;
|
|
6484
|
+
if (opts.bubbles && path.steps.length > 0)
|
|
6485
|
+
this.transactor.pushBubble(path.popStep(), name, args, opts, this, targetPath);
|
|
6624
6486
|
}
|
|
6625
|
-
|
|
6626
|
-
|
|
6627
|
-
|
|
6628
|
-
|
|
6629
|
-
|
|
6630
|
-
|
|
6631
|
-
|
|
6632
|
-
this.provide[key] = new ProvideInfo(key, val, Symbol(key));
|
|
6633
|
-
}
|
|
6634
|
-
for (const key in this._rawLookup) {
|
|
6635
|
-
const linfo = this._rawLookup[key];
|
|
6636
|
-
const forStr = isString(linfo) ? linfo : isString(linfo?.for) ? linfo.for : null;
|
|
6637
|
-
const [compName, provideName] = forStr === null ? [] : forStr.split(".");
|
|
6638
|
-
if (!isString(compName) || !isString(provideName))
|
|
6639
|
-
continue;
|
|
6640
|
-
const defStr = isString(linfo?.default) ? linfo.default : null;
|
|
6641
|
-
const val = defStr === null ? null : vp.parseField(defStr, ctx);
|
|
6642
|
-
this.lookup[key] = new LookupInfo(key, compName, provideName, val);
|
|
6643
|
-
}
|
|
6644
|
-
for (const key in this.lookup)
|
|
6645
|
-
if (this.provide[key] !== undefined)
|
|
6646
|
-
console.warn("name declared in both provide and lookup", this.name, key);
|
|
6487
|
+
}
|
|
6488
|
+
|
|
6489
|
+
class BubbleEvent extends SendEvent {
|
|
6490
|
+
handlerProp = "bubble";
|
|
6491
|
+
constructor(path, transactor, name, args, parent, opts, targetPath) {
|
|
6492
|
+
super(path, transactor, name, args, parent, opts);
|
|
6493
|
+
this.targetPath = targetPath ?? path;
|
|
6647
6494
|
}
|
|
6648
|
-
|
|
6649
|
-
|
|
6495
|
+
stopPropagation() {
|
|
6496
|
+
this.opts.bubbles = false;
|
|
6650
6497
|
}
|
|
6651
|
-
|
|
6652
|
-
|
|
6498
|
+
}
|
|
6499
|
+
|
|
6500
|
+
class InputDispatchEvent extends NameArgsTransaction {
|
|
6501
|
+
handlerProp = "input";
|
|
6502
|
+
}
|
|
6503
|
+
|
|
6504
|
+
class Completion {
|
|
6505
|
+
constructor() {
|
|
6506
|
+
this.val = undefined;
|
|
6507
|
+
this.selfSettled = false;
|
|
6508
|
+
this.subtreeSettled = false;
|
|
6509
|
+
this.pending = 1;
|
|
6510
|
+
this._selfResolve = null;
|
|
6511
|
+
this._selfPromise = null;
|
|
6512
|
+
this._subtreeResolve = null;
|
|
6513
|
+
this._subtreePromise = null;
|
|
6514
|
+
this._selfReleased = false;
|
|
6515
|
+
}
|
|
6516
|
+
whenSettled() {
|
|
6517
|
+
if (this.selfSettled)
|
|
6518
|
+
return Promise.resolve(this.val);
|
|
6519
|
+
this._selfPromise ??= new Promise((res) => {
|
|
6520
|
+
this._selfResolve = res;
|
|
6521
|
+
});
|
|
6522
|
+
return this._selfPromise;
|
|
6653
6523
|
}
|
|
6654
|
-
|
|
6655
|
-
|
|
6524
|
+
whenSubtreeSettled() {
|
|
6525
|
+
if (this.subtreeSettled)
|
|
6526
|
+
return Promise.resolve(this.val);
|
|
6527
|
+
this._subtreePromise ??= new Promise((res) => {
|
|
6528
|
+
this._subtreeResolve = res;
|
|
6529
|
+
});
|
|
6530
|
+
return this._subtreePromise;
|
|
6656
6531
|
}
|
|
6657
|
-
|
|
6658
|
-
|
|
6532
|
+
markSelfSettled(val) {
|
|
6533
|
+
if (this.selfSettled)
|
|
6534
|
+
return;
|
|
6535
|
+
this.selfSettled = true;
|
|
6536
|
+
this.val = val;
|
|
6537
|
+
this._selfResolve?.(val);
|
|
6659
6538
|
}
|
|
6660
|
-
|
|
6661
|
-
|
|
6662
|
-
|
|
6663
|
-
|
|
6664
|
-
|
|
6665
|
-
|
|
6666
|
-
|
|
6667
|
-
|
|
6668
|
-
|
|
6539
|
+
ensureSelfSettled() {
|
|
6540
|
+
if (!this.selfSettled)
|
|
6541
|
+
this.markSelfSettled(this.val);
|
|
6542
|
+
}
|
|
6543
|
+
track() {
|
|
6544
|
+
this.pending++;
|
|
6545
|
+
let done = false;
|
|
6546
|
+
return () => {
|
|
6547
|
+
if (done)
|
|
6548
|
+
return;
|
|
6549
|
+
done = true;
|
|
6550
|
+
this._release();
|
|
6551
|
+
};
|
|
6552
|
+
}
|
|
6553
|
+
releaseSelf() {
|
|
6554
|
+
if (this._selfReleased)
|
|
6555
|
+
return;
|
|
6556
|
+
this._selfReleased = true;
|
|
6557
|
+
this._release();
|
|
6558
|
+
}
|
|
6559
|
+
_release() {
|
|
6560
|
+
if (--this.pending === 0) {
|
|
6561
|
+
this.subtreeSettled = true;
|
|
6562
|
+
this._subtreeResolve?.(this.val);
|
|
6669
6563
|
}
|
|
6670
|
-
return styles.join(`
|
|
6671
|
-
`);
|
|
6672
6564
|
}
|
|
6673
6565
|
}
|
|
6674
6566
|
|
|
6675
|
-
|
|
6676
|
-
|
|
6677
|
-
|
|
6678
|
-
|
|
6679
|
-
|
|
6680
|
-
|
|
6681
|
-
const r = n[0].lookup(name);
|
|
6682
|
-
if (r === STOP)
|
|
6683
|
-
return dv;
|
|
6684
|
-
if (r !== NEXT)
|
|
6685
|
-
return r;
|
|
6686
|
-
n = n[1];
|
|
6687
|
-
}
|
|
6688
|
-
return dv;
|
|
6689
|
-
}
|
|
6690
|
-
|
|
6691
|
-
class BindFrame {
|
|
6692
|
-
constructor(it, binds, isFrame) {
|
|
6693
|
-
this.it = it;
|
|
6694
|
-
this.binds = binds;
|
|
6695
|
-
this.isFrame = isFrame;
|
|
6567
|
+
class Dispatcher {
|
|
6568
|
+
constructor(path, transactor, parentTransaction, root = transactor.state.val) {
|
|
6569
|
+
this.path = path;
|
|
6570
|
+
this.transactor = transactor;
|
|
6571
|
+
this.parent = parentTransaction;
|
|
6572
|
+
this.root = root;
|
|
6696
6573
|
}
|
|
6697
|
-
|
|
6698
|
-
const
|
|
6699
|
-
|
|
6574
|
+
walkPath(callback) {
|
|
6575
|
+
const comps = this.transactor.comps;
|
|
6576
|
+
const chain = this.path.toTransactionPath().resolveChain(this.root);
|
|
6577
|
+
for (let i = chain.length - 1;i >= 0; i--) {
|
|
6578
|
+
const comp = comps.getCompFor(chain[i]);
|
|
6579
|
+
if (comp && callback(comp, chain[i]) === false)
|
|
6580
|
+
return;
|
|
6581
|
+
}
|
|
6700
6582
|
}
|
|
6701
|
-
|
|
6702
|
-
|
|
6703
|
-
class ObjectFrame {
|
|
6704
|
-
constructor(binds) {
|
|
6705
|
-
this.binds = binds;
|
|
6583
|
+
get at() {
|
|
6584
|
+
return new PathChanges(this);
|
|
6706
6585
|
}
|
|
6707
|
-
|
|
6708
|
-
|
|
6709
|
-
return v === undefined ? NEXT : v;
|
|
6586
|
+
send(name, args, opts) {
|
|
6587
|
+
return this.sendAtPath(this.path, name, args, opts);
|
|
6710
6588
|
}
|
|
6711
|
-
|
|
6712
|
-
|
|
6713
|
-
let s = "";
|
|
6714
|
-
let n = views;
|
|
6715
|
-
while (n !== null) {
|
|
6716
|
-
s += n[0];
|
|
6717
|
-
n = n[1];
|
|
6589
|
+
bubble(name, args, opts) {
|
|
6590
|
+
return this.send(name, args, { skipSelf: true, bubbles: true, ...opts });
|
|
6718
6591
|
}
|
|
6719
|
-
|
|
6720
|
-
|
|
6721
|
-
|
|
6722
|
-
class Stack {
|
|
6723
|
-
constructor(comps, it, binds, dynBinds, views, viewsId, ctx = null) {
|
|
6724
|
-
this.comps = comps;
|
|
6725
|
-
this.it = it;
|
|
6726
|
-
this.binds = binds;
|
|
6727
|
-
this.dynBinds = dynBinds;
|
|
6728
|
-
this.views = views;
|
|
6729
|
-
this.viewsId = viewsId;
|
|
6730
|
-
this.ctx = ctx;
|
|
6592
|
+
sendAtPath(path, name, args, opts) {
|
|
6593
|
+
return this.transactor.pushSend(path, name, args, opts, this.parent);
|
|
6731
6594
|
}
|
|
6732
|
-
|
|
6733
|
-
|
|
6734
|
-
if (provide == null)
|
|
6735
|
-
return this;
|
|
6736
|
-
const dynObj = {};
|
|
6737
|
-
let has = false;
|
|
6738
|
-
for (const k in provide) {
|
|
6739
|
-
dynObj[provide[k].symbol] = provide[k].val.eval(this);
|
|
6740
|
-
has = true;
|
|
6741
|
-
}
|
|
6742
|
-
if (!has)
|
|
6743
|
-
return this;
|
|
6744
|
-
const newDynBinds = [new ObjectFrame(dynObj), this.dynBinds];
|
|
6745
|
-
const { comps, it, binds, views, viewsId, ctx } = this;
|
|
6746
|
-
return new Stack(comps, it, binds, newDynBinds, views, viewsId, ctx);
|
|
6595
|
+
request(name, args, opts) {
|
|
6596
|
+
return this.requestAtPath(this.path, name, args, opts);
|
|
6747
6597
|
}
|
|
6748
|
-
|
|
6749
|
-
|
|
6750
|
-
const dynBinds = [new ObjectFrame({}), null];
|
|
6751
|
-
const views = ["main", null];
|
|
6752
|
-
return new Stack(comps, it, binds, dynBinds, views, "", ctx)._pushProvides();
|
|
6598
|
+
requestAtPath(path, name, args, opts) {
|
|
6599
|
+
return this.transactor.pushRequest(path, name, args, opts, this.parent);
|
|
6753
6600
|
}
|
|
6754
|
-
|
|
6755
|
-
|
|
6756
|
-
const newBinds = [new BindFrame(it, bindings, isFrame), binds];
|
|
6757
|
-
const stack = new Stack(comps, it, newBinds, dynBinds, views, viewsId, ctx);
|
|
6758
|
-
return isFrame ? stack._pushProvides() : stack;
|
|
6601
|
+
inputAtPath(path, name, args, opts) {
|
|
6602
|
+
return this.transactor.pushInput(path, name, args, opts, this.parent);
|
|
6759
6603
|
}
|
|
6760
|
-
|
|
6761
|
-
|
|
6762
|
-
const newViews = [name, views];
|
|
6763
|
-
return new Stack(comps, it, binds, dynBinds, newViews, computeViewsId(newViews), ctx);
|
|
6604
|
+
lookupTypeFor(name, inst) {
|
|
6605
|
+
return this.transactor.comps.getCompFor(inst).scope.lookupComponent(name);
|
|
6764
6606
|
}
|
|
6765
|
-
|
|
6766
|
-
|
|
6767
|
-
|
|
6768
|
-
|
|
6769
|
-
|
|
6607
|
+
}
|
|
6608
|
+
|
|
6609
|
+
class EventContext extends Dispatcher {
|
|
6610
|
+
get name() {
|
|
6611
|
+
return this.parent?.name ?? null;
|
|
6770
6612
|
}
|
|
6771
|
-
|
|
6772
|
-
return
|
|
6613
|
+
get targetPath() {
|
|
6614
|
+
return this.parent.targetPath;
|
|
6773
6615
|
}
|
|
6774
|
-
|
|
6775
|
-
|
|
6776
|
-
return (sym != null ? lookup(this.dynBinds, sym) : null) ?? lk.val?.eval(this) ?? null;
|
|
6616
|
+
stopPropagation() {
|
|
6617
|
+
return this.parent.stopPropagation();
|
|
6777
6618
|
}
|
|
6778
|
-
|
|
6779
|
-
|
|
6780
|
-
|
|
6781
|
-
|
|
6782
|
-
|
|
6783
|
-
|
|
6784
|
-
|
|
6785
|
-
|
|
6786
|
-
|
|
6619
|
+
}
|
|
6620
|
+
|
|
6621
|
+
class RequestContext extends Dispatcher {
|
|
6622
|
+
}
|
|
6623
|
+
|
|
6624
|
+
class PathChanges extends PathBuilder {
|
|
6625
|
+
constructor(dispatcher) {
|
|
6626
|
+
super();
|
|
6627
|
+
this.dispatcher = dispatcher;
|
|
6787
6628
|
}
|
|
6788
|
-
|
|
6789
|
-
return
|
|
6629
|
+
send(name, args, opts) {
|
|
6630
|
+
return this.dispatcher.sendAtPath(this.buildPath(), name, args, opts);
|
|
6790
6631
|
}
|
|
6791
|
-
|
|
6792
|
-
return this.
|
|
6632
|
+
bubble(name, args, opts) {
|
|
6633
|
+
return this.send(name, args, { skipSelf: true, bubbles: true, ...opts });
|
|
6793
6634
|
}
|
|
6794
|
-
|
|
6795
|
-
return this.
|
|
6635
|
+
buildPath() {
|
|
6636
|
+
return this.dispatcher.path.concat(this.pathChanges);
|
|
6796
6637
|
}
|
|
6797
|
-
|
|
6798
|
-
|
|
6799
|
-
|
|
6638
|
+
}
|
|
6639
|
+
function rootDispatcher(transactor) {
|
|
6640
|
+
return new Dispatcher(new Path([]), transactor, null);
|
|
6641
|
+
}
|
|
6642
|
+
|
|
6643
|
+
// tools/core/results.js
|
|
6644
|
+
class ModuleInfo {
|
|
6645
|
+
constructor({ path = null, present = new Set, counts = {}, warnings = [] }) {
|
|
6646
|
+
this.path = path;
|
|
6647
|
+
this.present = present;
|
|
6648
|
+
this.counts = counts;
|
|
6649
|
+
this.warnings = warnings;
|
|
6800
6650
|
}
|
|
6801
|
-
|
|
6802
|
-
|
|
6651
|
+
}
|
|
6652
|
+
|
|
6653
|
+
class ComponentSummary {
|
|
6654
|
+
constructor({ name, views, fields }) {
|
|
6655
|
+
this.name = name;
|
|
6656
|
+
this.views = views;
|
|
6657
|
+
this.fields = fields;
|
|
6803
6658
|
}
|
|
6804
|
-
|
|
6805
|
-
|
|
6659
|
+
}
|
|
6660
|
+
|
|
6661
|
+
class ComponentList {
|
|
6662
|
+
constructor({ items, total = null, truncated = false }) {
|
|
6663
|
+
this.items = items;
|
|
6664
|
+
this.total = total ?? items.length;
|
|
6665
|
+
this.truncated = truncated;
|
|
6806
6666
|
}
|
|
6807
|
-
|
|
6808
|
-
|
|
6667
|
+
}
|
|
6668
|
+
|
|
6669
|
+
class ExampleIndex {
|
|
6670
|
+
constructor({ sections, total = null, truncated = false }) {
|
|
6671
|
+
this.sections = sections;
|
|
6672
|
+
this.total = total ?? sections.reduce((n, s) => n + (s.items?.length ?? 0), 0);
|
|
6673
|
+
this.truncated = truncated;
|
|
6809
6674
|
}
|
|
6810
|
-
|
|
6811
|
-
|
|
6812
|
-
|
|
6813
|
-
|
|
6814
|
-
|
|
6815
|
-
return view;
|
|
6816
|
-
n = n[1];
|
|
6817
|
-
}
|
|
6818
|
-
return views[defaultViewName];
|
|
6675
|
+
}
|
|
6676
|
+
|
|
6677
|
+
class ComponentDocs {
|
|
6678
|
+
constructor({ items }) {
|
|
6679
|
+
this.items = items;
|
|
6819
6680
|
}
|
|
6820
6681
|
}
|
|
6821
6682
|
|
|
6822
|
-
|
|
6823
|
-
|
|
6824
|
-
|
|
6825
|
-
this.
|
|
6826
|
-
this.
|
|
6683
|
+
class LintFinding {
|
|
6684
|
+
constructor({ id, level, info, context = {}, suggestion = null }) {
|
|
6685
|
+
this.id = id;
|
|
6686
|
+
this.level = level;
|
|
6687
|
+
this.info = info;
|
|
6688
|
+
this.context = context;
|
|
6689
|
+
this.suggestion = suggestion;
|
|
6827
6690
|
}
|
|
6828
|
-
|
|
6829
|
-
|
|
6691
|
+
}
|
|
6692
|
+
|
|
6693
|
+
class LintComponentResult {
|
|
6694
|
+
constructor({ componentName, findings }) {
|
|
6695
|
+
this.componentName = componentName;
|
|
6696
|
+
this.findings = findings;
|
|
6830
6697
|
}
|
|
6831
|
-
|
|
6832
|
-
|
|
6833
|
-
this.val = val;
|
|
6834
|
-
for (const sub of this.changeSubs)
|
|
6835
|
-
sub({ val, old, info, timestamp: Date.now() });
|
|
6698
|
+
get errorCount() {
|
|
6699
|
+
return this.findings.filter((f) => f.level === "error").length;
|
|
6836
6700
|
}
|
|
6837
|
-
|
|
6838
|
-
return this.
|
|
6701
|
+
get warnCount() {
|
|
6702
|
+
return this.findings.filter((f) => f.level === "warn").length;
|
|
6839
6703
|
}
|
|
6840
6704
|
}
|
|
6841
6705
|
|
|
6842
|
-
class
|
|
6843
|
-
constructor(
|
|
6844
|
-
this.
|
|
6845
|
-
this.transactions = [];
|
|
6846
|
-
this.state = new State2(rootValue);
|
|
6847
|
-
this.onTransactionPushed = () => {};
|
|
6706
|
+
class LintReport {
|
|
6707
|
+
constructor({ components }) {
|
|
6708
|
+
this.components = components;
|
|
6848
6709
|
}
|
|
6849
|
-
|
|
6850
|
-
this.
|
|
6851
|
-
this.onTransactionPushed(t);
|
|
6710
|
+
get hasErrors() {
|
|
6711
|
+
return this.components.some((c) => c.errorCount > 0);
|
|
6852
6712
|
}
|
|
6853
|
-
|
|
6854
|
-
this.
|
|
6713
|
+
get totalErrors() {
|
|
6714
|
+
return this.components.reduce((n, c) => n + c.errorCount, 0);
|
|
6855
6715
|
}
|
|
6856
|
-
|
|
6857
|
-
|
|
6858
|
-
this.pushTransaction(new BubbleEvent(path, this, name, args, parent, newOpts, targetPath));
|
|
6859
|
-
}
|
|
6860
|
-
async pushRequest(path, name, args = [], opts = {}, parent = null) {
|
|
6861
|
-
const curRoot = this.state.val;
|
|
6862
|
-
const txnPath = path.toTransactionPath();
|
|
6863
|
-
const curLeaf = txnPath.lookup(curRoot);
|
|
6864
|
-
const handler = this.comps.getRequestFor(curLeaf, name) ?? mkReq404(name);
|
|
6865
|
-
const reqCtx = new RequestContext(path, this, parent, curRoot);
|
|
6866
|
-
const resHandlerName = opts?.onResName ?? name;
|
|
6867
|
-
const resPath = opts?.livePath ? null : txnPath.pinKeys(curRoot);
|
|
6868
|
-
const push = (specificName, baseName, singleArg, result, error) => {
|
|
6869
|
-
const resArgs = specificName ? [singleArg] : [result, error];
|
|
6870
|
-
const t = new ResponseEvent(path, this, specificName ?? baseName, resArgs, parent, resPath);
|
|
6871
|
-
this.pushTransaction(t);
|
|
6872
|
-
};
|
|
6873
|
-
try {
|
|
6874
|
-
const result = await handler.fn.apply(null, [...args, reqCtx]);
|
|
6875
|
-
push(opts?.onOkName, resHandlerName, result, result, null);
|
|
6876
|
-
} catch (error) {
|
|
6877
|
-
push(opts?.onErrorName, resHandlerName, error, null, error);
|
|
6878
|
-
}
|
|
6879
|
-
}
|
|
6880
|
-
get hasPendingTransactions() {
|
|
6881
|
-
return this.transactions.length > 0;
|
|
6882
|
-
}
|
|
6883
|
-
transactNext() {
|
|
6884
|
-
if (this.hasPendingTransactions)
|
|
6885
|
-
this.transact(this.transactions.shift());
|
|
6886
|
-
}
|
|
6887
|
-
transact(transaction) {
|
|
6888
|
-
const curState = this.state.val;
|
|
6889
|
-
const newState = transaction.run(curState, this.comps);
|
|
6890
|
-
if (newState !== undefined) {
|
|
6891
|
-
this.state.set(newState, { transaction });
|
|
6892
|
-
transaction.afterTransaction();
|
|
6893
|
-
} else
|
|
6894
|
-
console.warn("undefined new state", { curState, transaction });
|
|
6895
|
-
}
|
|
6896
|
-
transactInputNow(path, event, eventHandler, dragInfo) {
|
|
6897
|
-
this.transact(new InputEvent(path, event, eventHandler, this, dragInfo));
|
|
6716
|
+
get totalWarnings() {
|
|
6717
|
+
return this.components.reduce((n, c) => n + c.warnCount, 0);
|
|
6898
6718
|
}
|
|
6899
6719
|
}
|
|
6900
|
-
function mkReq404(name) {
|
|
6901
|
-
const fn = () => {
|
|
6902
|
-
throw new Error(`Request not found: ${name}`);
|
|
6903
|
-
};
|
|
6904
|
-
return { fn };
|
|
6905
|
-
}
|
|
6906
|
-
function nullHandler() {
|
|
6907
|
-
return this;
|
|
6908
|
-
}
|
|
6909
6720
|
|
|
6910
|
-
class
|
|
6911
|
-
constructor(
|
|
6912
|
-
this.
|
|
6913
|
-
this.
|
|
6914
|
-
this.
|
|
6915
|
-
this.
|
|
6916
|
-
|
|
6917
|
-
|
|
6918
|
-
this._task ??= new Task;
|
|
6919
|
-
return this._task;
|
|
6920
|
-
}
|
|
6921
|
-
getCompletionPromise() {
|
|
6922
|
-
return this.task.promise;
|
|
6923
|
-
}
|
|
6924
|
-
setParent(parentTransaction) {
|
|
6925
|
-
this.parentTransaction = parentTransaction;
|
|
6926
|
-
parentTransaction.task.addDep(this.task);
|
|
6927
|
-
}
|
|
6928
|
-
run(rootValue, comps) {
|
|
6929
|
-
return this.updateRootValue(rootValue, comps);
|
|
6930
|
-
}
|
|
6931
|
-
afterTransaction() {}
|
|
6932
|
-
buildRootStack(root, comps) {
|
|
6933
|
-
return Stack.root(comps, root);
|
|
6934
|
-
}
|
|
6935
|
-
buildStack(root, comps) {
|
|
6936
|
-
return this.path.toTransactionPath().buildStack(this.buildRootStack(root, comps));
|
|
6937
|
-
}
|
|
6938
|
-
callHandler(root, instance, comps) {
|
|
6939
|
-
const [handler, args] = this.getHandlerAndArgs(root, instance, comps);
|
|
6940
|
-
return handler.apply(instance, args);
|
|
6941
|
-
}
|
|
6942
|
-
getHandlerAndArgs(_root, _instance, _comps) {
|
|
6943
|
-
return null;
|
|
6944
|
-
}
|
|
6945
|
-
getTransactionPath() {
|
|
6946
|
-
return this.path.toTransactionPath();
|
|
6947
|
-
}
|
|
6948
|
-
updateRootValue(curRoot, comps) {
|
|
6949
|
-
const txnPath = this.getTransactionPath();
|
|
6950
|
-
const curLeaf = txnPath.lookup(curRoot);
|
|
6951
|
-
const newLeaf = this.callHandler(curRoot, curLeaf, comps);
|
|
6952
|
-
this._task?.complete?.({ value: newLeaf, old: curLeaf });
|
|
6953
|
-
return curLeaf !== newLeaf ? txnPath.setValue(curRoot, newLeaf) : curRoot;
|
|
6954
|
-
}
|
|
6955
|
-
lookupName(_name) {
|
|
6956
|
-
return null;
|
|
6721
|
+
class RenderedExample {
|
|
6722
|
+
constructor({ title, description = null, componentName, view, html, error = null }) {
|
|
6723
|
+
this.title = title;
|
|
6724
|
+
this.description = description;
|
|
6725
|
+
this.componentName = componentName;
|
|
6726
|
+
this.view = view;
|
|
6727
|
+
this.html = html;
|
|
6728
|
+
this.error = error;
|
|
6957
6729
|
}
|
|
6958
6730
|
}
|
|
6959
|
-
var toNullIfNaN = (v) => Number.isNaN(v) ? null : v;
|
|
6960
|
-
function getValue(e) {
|
|
6961
|
-
return e.target.type === "checkbox" ? e.target.checked : (e instanceof CustomEvent ? e.detail : e.target.value) ?? null;
|
|
6962
|
-
}
|
|
6963
6731
|
|
|
6964
|
-
class
|
|
6965
|
-
constructor(
|
|
6966
|
-
|
|
6967
|
-
this.
|
|
6968
|
-
this.
|
|
6969
|
-
this.dragInfo = dragInfo;
|
|
6970
|
-
this._dispatchPath = null;
|
|
6971
|
-
}
|
|
6972
|
-
get dispatchPath() {
|
|
6973
|
-
this._dispatchPath ??= this.path.compact();
|
|
6974
|
-
return this._dispatchPath;
|
|
6975
|
-
}
|
|
6976
|
-
buildRootStack(root, comps) {
|
|
6977
|
-
return Stack.root(comps, root, this);
|
|
6978
|
-
}
|
|
6979
|
-
getHandlerAndArgs(root, _instance, comps) {
|
|
6980
|
-
const stack = this.buildStack(root, comps);
|
|
6981
|
-
const [handler, args] = this.handler.getHandlerAndArgs(stack, this);
|
|
6982
|
-
const path = this.dispatchPath;
|
|
6983
|
-
let dispatcher;
|
|
6984
|
-
for (let i = 0;i < args.length; i++) {
|
|
6985
|
-
if (args[i]?.toHandlerArg) {
|
|
6986
|
-
dispatcher ??= new Dispatcher(path, this.transactor, this);
|
|
6987
|
-
args[i] = args[i].toHandlerArg(dispatcher);
|
|
6988
|
-
}
|
|
6989
|
-
}
|
|
6990
|
-
args.push(new EventContext(path, this.transactor, this));
|
|
6991
|
-
return [handler, args];
|
|
6992
|
-
}
|
|
6993
|
-
lookupName(name) {
|
|
6994
|
-
const { e } = this;
|
|
6995
|
-
switch (name) {
|
|
6996
|
-
case "value":
|
|
6997
|
-
return getValue(e);
|
|
6998
|
-
case "valueAsInt":
|
|
6999
|
-
return toNullIfNaN(parseInt(getValue(e), 10));
|
|
7000
|
-
case "valueAsFloat":
|
|
7001
|
-
return toNullIfNaN(parseFloat(getValue(e)));
|
|
7002
|
-
case "target":
|
|
7003
|
-
return e.target;
|
|
7004
|
-
case "event":
|
|
7005
|
-
return e;
|
|
7006
|
-
case "isAlt":
|
|
7007
|
-
return e.altKey;
|
|
7008
|
-
case "isShift":
|
|
7009
|
-
return e.shiftKey;
|
|
7010
|
-
case "isCtrl":
|
|
7011
|
-
case "isCmd":
|
|
7012
|
-
return isMac && e.metaKey || e.ctrlKey;
|
|
7013
|
-
case "key":
|
|
7014
|
-
return e.key;
|
|
7015
|
-
case "keyCode":
|
|
7016
|
-
return e.keyCode;
|
|
7017
|
-
case "isUpKey":
|
|
7018
|
-
return e.key === "ArrowUp";
|
|
7019
|
-
case "isDownKey":
|
|
7020
|
-
return e.key === "ArrowDown";
|
|
7021
|
-
case "isSend":
|
|
7022
|
-
return e.key === "Enter";
|
|
7023
|
-
case "isCancel":
|
|
7024
|
-
return e.key === "Escape";
|
|
7025
|
-
case "isTabKey":
|
|
7026
|
-
return e.key === "Tab";
|
|
7027
|
-
case "ctx":
|
|
7028
|
-
return new EventContext(this.dispatchPath, this.transactor, this);
|
|
7029
|
-
case "dragInfo":
|
|
7030
|
-
return this.dragInfo;
|
|
7031
|
-
}
|
|
7032
|
-
return null;
|
|
6732
|
+
class RenderedSection {
|
|
6733
|
+
constructor({ title, description = null, items }) {
|
|
6734
|
+
this.title = title;
|
|
6735
|
+
this.description = description;
|
|
6736
|
+
this.items = items;
|
|
7033
6737
|
}
|
|
7034
6738
|
}
|
|
7035
6739
|
|
|
7036
|
-
class
|
|
7037
|
-
constructor(
|
|
7038
|
-
|
|
7039
|
-
this.name = name;
|
|
7040
|
-
this.args = args;
|
|
7041
|
-
this.opts = opts;
|
|
7042
|
-
this.targetPath = path;
|
|
7043
|
-
}
|
|
7044
|
-
handlerProp = null;
|
|
7045
|
-
getHandlerForName(comp) {
|
|
7046
|
-
const handlers = comp?.[this.handlerProp];
|
|
7047
|
-
return handlers?.[this.name] ?? handlers?.$unknown ?? nullHandler;
|
|
6740
|
+
class RenderBatch {
|
|
6741
|
+
constructor({ sections }) {
|
|
6742
|
+
this.sections = sections;
|
|
7048
6743
|
}
|
|
7049
|
-
|
|
7050
|
-
|
|
7051
|
-
return [handler, [...this.args, new EventContext(this.path, this.transactor, this)]];
|
|
6744
|
+
get hasErrors() {
|
|
6745
|
+
return this.sections.some((s) => s.items.some((i) => i.error !== null));
|
|
7052
6746
|
}
|
|
7053
6747
|
}
|
|
7054
6748
|
|
|
7055
|
-
class
|
|
7056
|
-
|
|
7057
|
-
|
|
7058
|
-
|
|
7059
|
-
this.
|
|
7060
|
-
|
|
7061
|
-
|
|
7062
|
-
|
|
6749
|
+
class TestResult {
|
|
6750
|
+
constructor({ title, fullPath, componentName = null, status, durationMs = 0, error = null }) {
|
|
6751
|
+
this.title = title;
|
|
6752
|
+
this.fullPath = fullPath;
|
|
6753
|
+
this.componentName = componentName;
|
|
6754
|
+
this.status = status;
|
|
6755
|
+
this.durationMs = durationMs;
|
|
6756
|
+
this.error = error;
|
|
7063
6757
|
}
|
|
7064
6758
|
}
|
|
7065
6759
|
|
|
7066
|
-
class
|
|
7067
|
-
|
|
7068
|
-
|
|
7069
|
-
|
|
7070
|
-
|
|
7071
|
-
afterTransaction() {
|
|
7072
|
-
const { path, name, args, opts, targetPath } = this;
|
|
7073
|
-
if (opts.bubbles && path.steps.length > 0)
|
|
7074
|
-
this.transactor.pushBubble(path.popStep(), name, args, opts, this, targetPath);
|
|
6760
|
+
class DescribeResult {
|
|
6761
|
+
constructor({ title, componentName = null, children = [] }) {
|
|
6762
|
+
this.title = title;
|
|
6763
|
+
this.componentName = componentName;
|
|
6764
|
+
this.children = children;
|
|
7075
6765
|
}
|
|
7076
6766
|
}
|
|
7077
6767
|
|
|
7078
|
-
class
|
|
7079
|
-
|
|
7080
|
-
|
|
7081
|
-
|
|
7082
|
-
this.
|
|
7083
|
-
}
|
|
7084
|
-
stopPropagation() {
|
|
7085
|
-
this.opts.bubbles = false;
|
|
6768
|
+
class ModuleTestReport {
|
|
6769
|
+
constructor({ path = null, suites = [], counts = { pass: 0, fail: 0, skip: 0, total: 0 } }) {
|
|
6770
|
+
this.path = path;
|
|
6771
|
+
this.suites = suites;
|
|
6772
|
+
this.counts = counts;
|
|
7086
6773
|
}
|
|
7087
6774
|
}
|
|
7088
6775
|
|
|
7089
|
-
class
|
|
7090
|
-
constructor() {
|
|
7091
|
-
this.
|
|
7092
|
-
this.val = this.resolve = this.reject = null;
|
|
7093
|
-
this.promise = new Promise((res, rej) => {
|
|
7094
|
-
this.resolve = res;
|
|
7095
|
-
this.reject = rej;
|
|
7096
|
-
});
|
|
7097
|
-
this.isCompleted = false;
|
|
6776
|
+
class TestReport {
|
|
6777
|
+
constructor({ modules = [] }) {
|
|
6778
|
+
this.modules = modules;
|
|
7098
6779
|
}
|
|
7099
|
-
|
|
7100
|
-
|
|
7101
|
-
|
|
7102
|
-
|
|
6780
|
+
get totals() {
|
|
6781
|
+
return this.modules.reduce((acc, m) => ({
|
|
6782
|
+
pass: acc.pass + m.counts.pass,
|
|
6783
|
+
fail: acc.fail + m.counts.fail,
|
|
6784
|
+
skip: acc.skip + m.counts.skip,
|
|
6785
|
+
total: acc.total + m.counts.total
|
|
6786
|
+
}), { pass: 0, fail: 0, skip: 0, total: 0 });
|
|
7103
6787
|
}
|
|
7104
|
-
|
|
7105
|
-
this.
|
|
7106
|
-
this._check();
|
|
6788
|
+
get hasFailures() {
|
|
6789
|
+
return this.modules.some((m) => m.counts.fail > 0);
|
|
7107
6790
|
}
|
|
7108
|
-
|
|
7109
|
-
|
|
7110
|
-
|
|
7111
|
-
|
|
7112
|
-
|
|
6791
|
+
}
|
|
6792
|
+
|
|
6793
|
+
// tools/core/tests.js
|
|
6794
|
+
class Describe {
|
|
6795
|
+
constructor({ title, componentName = null, parent = null }) {
|
|
6796
|
+
this.title = title;
|
|
6797
|
+
this.componentName = componentName;
|
|
6798
|
+
this.parent = parent;
|
|
6799
|
+
this.children = [];
|
|
7113
6800
|
}
|
|
7114
6801
|
}
|
|
7115
6802
|
|
|
7116
|
-
class
|
|
7117
|
-
constructor(
|
|
7118
|
-
this.
|
|
7119
|
-
this.
|
|
7120
|
-
this.
|
|
7121
|
-
this.
|
|
6803
|
+
class Test {
|
|
6804
|
+
constructor({ title, fn, componentName = null, parent = null }) {
|
|
6805
|
+
this.title = title;
|
|
6806
|
+
this.fn = fn;
|
|
6807
|
+
this.componentName = componentName;
|
|
6808
|
+
this.parent = parent;
|
|
7122
6809
|
}
|
|
7123
|
-
|
|
7124
|
-
|
|
7125
|
-
|
|
7126
|
-
|
|
7127
|
-
|
|
7128
|
-
|
|
7129
|
-
return;
|
|
7130
|
-
}
|
|
6810
|
+
}
|
|
6811
|
+
|
|
6812
|
+
class ModuleTests {
|
|
6813
|
+
constructor({ path = null, suites = [] } = {}) {
|
|
6814
|
+
this.path = path;
|
|
6815
|
+
this.suites = suites;
|
|
7131
6816
|
}
|
|
7132
|
-
|
|
7133
|
-
|
|
6817
|
+
}
|
|
6818
|
+
|
|
6819
|
+
class TestIndex {
|
|
6820
|
+
constructor({ modules = [] } = {}) {
|
|
6821
|
+
this.modules = modules;
|
|
7134
6822
|
}
|
|
7135
|
-
|
|
7136
|
-
|
|
6823
|
+
}
|
|
6824
|
+
function isComponentObject(x) {
|
|
6825
|
+
return x !== null && typeof x === "object" && typeof x.name === "string" && typeof x.Class === "function";
|
|
6826
|
+
}
|
|
6827
|
+
function resolveComponentName(arg, components) {
|
|
6828
|
+
if (isComponentObject(arg))
|
|
6829
|
+
return arg.name;
|
|
6830
|
+
if (typeof arg === "function") {
|
|
6831
|
+
for (const c of components)
|
|
6832
|
+
if (c.Class === arg)
|
|
6833
|
+
return c.name;
|
|
7137
6834
|
}
|
|
7138
|
-
|
|
7139
|
-
|
|
6835
|
+
return null;
|
|
6836
|
+
}
|
|
6837
|
+
function titleFromArg(arg) {
|
|
6838
|
+
if (typeof arg === "string")
|
|
6839
|
+
return arg;
|
|
6840
|
+
if (isComponentObject(arg))
|
|
6841
|
+
return arg.name;
|
|
6842
|
+
if (typeof arg === "function")
|
|
6843
|
+
return arg.name || "(anonymous)";
|
|
6844
|
+
return String(arg);
|
|
6845
|
+
}
|
|
6846
|
+
function makeCollector({ path = null, components = [] } = {}) {
|
|
6847
|
+
const moduleTests = new ModuleTests({ path, suites: [] });
|
|
6848
|
+
const stack = [];
|
|
6849
|
+
function describe(...args) {
|
|
6850
|
+
let head;
|
|
6851
|
+
let options = null;
|
|
6852
|
+
let fn;
|
|
6853
|
+
if (args.length === 2) {
|
|
6854
|
+
[head, fn] = args;
|
|
6855
|
+
} else if (args.length === 3) {
|
|
6856
|
+
[head, options, fn] = args;
|
|
6857
|
+
} else {
|
|
6858
|
+
throw new Error(`describe() expects 2 or 3 arguments, got ${args.length}`);
|
|
6859
|
+
}
|
|
6860
|
+
if (typeof fn !== "function") {
|
|
6861
|
+
throw new Error(`describe(${JSON.stringify(titleFromArg(head))}): final argument must be a function`);
|
|
6862
|
+
}
|
|
6863
|
+
let componentName = null;
|
|
6864
|
+
if (typeof head !== "string") {
|
|
6865
|
+
componentName = resolveComponentName(head, components);
|
|
6866
|
+
}
|
|
6867
|
+
if (componentName === null && options && options.component != null) {
|
|
6868
|
+
componentName = resolveComponentName(options.component, components);
|
|
6869
|
+
}
|
|
6870
|
+
if (componentName === null) {
|
|
6871
|
+
const parent2 = stack.length ? stack[stack.length - 1] : null;
|
|
6872
|
+
if (parent2)
|
|
6873
|
+
componentName = parent2.componentName;
|
|
6874
|
+
}
|
|
6875
|
+
const parent = stack.length ? stack[stack.length - 1] : null;
|
|
6876
|
+
const node = new Describe({
|
|
6877
|
+
title: titleFromArg(head),
|
|
6878
|
+
componentName,
|
|
6879
|
+
parent
|
|
6880
|
+
});
|
|
6881
|
+
if (parent)
|
|
6882
|
+
parent.children.push(node);
|
|
6883
|
+
else
|
|
6884
|
+
moduleTests.suites.push(node);
|
|
6885
|
+
stack.push(node);
|
|
6886
|
+
try {
|
|
6887
|
+
fn();
|
|
6888
|
+
} finally {
|
|
6889
|
+
stack.pop();
|
|
6890
|
+
}
|
|
7140
6891
|
}
|
|
7141
|
-
|
|
7142
|
-
|
|
6892
|
+
function test(title, fn) {
|
|
6893
|
+
if (typeof title !== "string") {
|
|
6894
|
+
throw new Error("test(title, fn): title must be a string");
|
|
6895
|
+
}
|
|
6896
|
+
if (typeof fn !== "function") {
|
|
6897
|
+
throw new Error(`test(${JSON.stringify(title)}): fn must be a function`);
|
|
6898
|
+
}
|
|
6899
|
+
const parent = stack.length ? stack[stack.length - 1] : null;
|
|
6900
|
+
if (!parent) {
|
|
6901
|
+
throw new Error(`test(${JSON.stringify(title)}) must be called inside a describe()`);
|
|
6902
|
+
}
|
|
6903
|
+
parent.children.push(new Test({
|
|
6904
|
+
title,
|
|
6905
|
+
fn,
|
|
6906
|
+
componentName: parent.componentName,
|
|
6907
|
+
parent
|
|
6908
|
+
}));
|
|
7143
6909
|
}
|
|
7144
|
-
|
|
7145
|
-
|
|
6910
|
+
return { describe, test, moduleTests };
|
|
6911
|
+
}
|
|
6912
|
+
|
|
6913
|
+
// tools/core/test.js
|
|
6914
|
+
function buildPath(node) {
|
|
6915
|
+
const parts = [];
|
|
6916
|
+
let cur = node;
|
|
6917
|
+
while (cur) {
|
|
6918
|
+
parts.unshift(cur.title);
|
|
6919
|
+
cur = cur.parent;
|
|
7146
6920
|
}
|
|
7147
|
-
|
|
7148
|
-
|
|
6921
|
+
return parts.join(" > ");
|
|
6922
|
+
}
|
|
6923
|
+
function captureError(e) {
|
|
6924
|
+
const out = { message: e.message, stack: e.stack };
|
|
6925
|
+
if ("expected" in e)
|
|
6926
|
+
out.expected = e.expected;
|
|
6927
|
+
if ("actual" in e)
|
|
6928
|
+
out.actual = e.actual;
|
|
6929
|
+
return out;
|
|
6930
|
+
}
|
|
6931
|
+
async function runTests({
|
|
6932
|
+
getTests,
|
|
6933
|
+
components = [],
|
|
6934
|
+
path = null,
|
|
6935
|
+
expect: expect2,
|
|
6936
|
+
name = null,
|
|
6937
|
+
grep = null,
|
|
6938
|
+
bail = false,
|
|
6939
|
+
requestHandlers = null,
|
|
6940
|
+
macros = null
|
|
6941
|
+
} = {}) {
|
|
6942
|
+
const counts = { pass: 0, fail: 0, skip: 0, total: 0 };
|
|
6943
|
+
if (typeof getTests !== "function") {
|
|
6944
|
+
return new TestReport({
|
|
6945
|
+
modules: [new ModuleTestReport({ path, suites: [], counts })]
|
|
6946
|
+
});
|
|
7149
6947
|
}
|
|
7150
|
-
|
|
7151
|
-
|
|
6948
|
+
if (typeof expect2 !== "function") {
|
|
6949
|
+
throw new Error("runTests: expect must be provided (e.g. chai's expect)");
|
|
7152
6950
|
}
|
|
7153
|
-
}
|
|
7154
|
-
|
|
7155
|
-
|
|
7156
|
-
|
|
7157
|
-
|
|
6951
|
+
const { describe, test, moduleTests } = makeCollector({ path, components });
|
|
6952
|
+
await getTests({ describe, test, expect: expect2, drive });
|
|
6953
|
+
let _stack = null;
|
|
6954
|
+
function getStack() {
|
|
6955
|
+
if (_stack)
|
|
6956
|
+
return _stack;
|
|
6957
|
+
_stack = new ComponentStack;
|
|
6958
|
+
_stack.registerComponents(components);
|
|
6959
|
+
if (macros)
|
|
6960
|
+
_stack.registerMacros(macros);
|
|
6961
|
+
if (requestHandlers)
|
|
6962
|
+
_stack.registerRequestHandlers(requestHandlers);
|
|
6963
|
+
return _stack;
|
|
6964
|
+
}
|
|
6965
|
+
async function drive(value, phase, opts = {}) {
|
|
6966
|
+
const transactor = new Transactor(getStack().comps, value);
|
|
6967
|
+
if (opts.onMessage)
|
|
6968
|
+
transactor.state.onChange(({ val, old, info }) => {
|
|
6969
|
+
const t = info?.transaction;
|
|
6970
|
+
opts.onMessage({ kind: t?.handlerProp ?? "input", name: t?.name, args: t?.args, path: t?.path }, old, val);
|
|
6971
|
+
});
|
|
6972
|
+
dispatchPhase(rootDispatcher(transactor), new Path([]), phase, value);
|
|
6973
|
+
await transactor.settle();
|
|
6974
|
+
return transactor.state.val;
|
|
7158
6975
|
}
|
|
7159
|
-
|
|
7160
|
-
|
|
6976
|
+
let bailed = false;
|
|
6977
|
+
async function visit(node) {
|
|
6978
|
+
if (node instanceof Test) {
|
|
6979
|
+
if (name !== null && node.componentName !== name)
|
|
6980
|
+
return null;
|
|
6981
|
+
const fullPath = buildPath(node);
|
|
6982
|
+
if (grep !== null && !fullPath.includes(grep))
|
|
6983
|
+
return null;
|
|
6984
|
+
counts.total++;
|
|
6985
|
+
if (bailed) {
|
|
6986
|
+
counts.skip++;
|
|
6987
|
+
return new TestResult({
|
|
6988
|
+
title: node.title,
|
|
6989
|
+
fullPath,
|
|
6990
|
+
componentName: node.componentName,
|
|
6991
|
+
status: "skip"
|
|
6992
|
+
});
|
|
6993
|
+
}
|
|
6994
|
+
const start = performance.now();
|
|
6995
|
+
try {
|
|
6996
|
+
await node.fn();
|
|
6997
|
+
counts.pass++;
|
|
6998
|
+
return new TestResult({
|
|
6999
|
+
title: node.title,
|
|
7000
|
+
fullPath,
|
|
7001
|
+
componentName: node.componentName,
|
|
7002
|
+
status: "pass",
|
|
7003
|
+
durationMs: performance.now() - start
|
|
7004
|
+
});
|
|
7005
|
+
} catch (e) {
|
|
7006
|
+
counts.fail++;
|
|
7007
|
+
if (bail)
|
|
7008
|
+
bailed = true;
|
|
7009
|
+
return new TestResult({
|
|
7010
|
+
title: node.title,
|
|
7011
|
+
fullPath,
|
|
7012
|
+
componentName: node.componentName,
|
|
7013
|
+
status: "fail",
|
|
7014
|
+
durationMs: performance.now() - start,
|
|
7015
|
+
error: captureError(e)
|
|
7016
|
+
});
|
|
7017
|
+
}
|
|
7018
|
+
}
|
|
7019
|
+
const childResults = [];
|
|
7020
|
+
for (const child of node.children) {
|
|
7021
|
+
const r = await visit(child);
|
|
7022
|
+
if (r !== null)
|
|
7023
|
+
childResults.push(r);
|
|
7024
|
+
}
|
|
7025
|
+
if (childResults.length === 0)
|
|
7026
|
+
return null;
|
|
7027
|
+
return new DescribeResult({
|
|
7028
|
+
title: node.title,
|
|
7029
|
+
componentName: node.componentName,
|
|
7030
|
+
children: childResults
|
|
7031
|
+
});
|
|
7161
7032
|
}
|
|
7162
|
-
|
|
7163
|
-
|
|
7033
|
+
const suiteResults = [];
|
|
7034
|
+
for (const suite of moduleTests.suites) {
|
|
7035
|
+
const r = await visit(suite);
|
|
7036
|
+
if (r !== null)
|
|
7037
|
+
suiteResults.push(r);
|
|
7164
7038
|
}
|
|
7039
|
+
return new TestReport({
|
|
7040
|
+
modules: [new ModuleTestReport({ path, suites: suiteResults, counts })]
|
|
7041
|
+
});
|
|
7165
7042
|
}
|
|
7166
7043
|
|
|
7167
|
-
|
|
7168
|
-
|
|
7169
|
-
|
|
7170
|
-
|
|
7171
|
-
|
|
7172
|
-
|
|
7173
|
-
|
|
7174
|
-
|
|
7175
|
-
|
|
7176
|
-
|
|
7177
|
-
|
|
7178
|
-
|
|
7179
|
-
|
|
7044
|
+
// tools/core/test-console.js
|
|
7045
|
+
var PASS = "color: #0a0; font-weight: bold";
|
|
7046
|
+
var FAIL = "color: #c00; font-weight: bold";
|
|
7047
|
+
var SKIP = "color: #888";
|
|
7048
|
+
var DIM = "color: #888";
|
|
7049
|
+
var RESET = "color: inherit; font-weight: normal";
|
|
7050
|
+
function reportTestNode(node) {
|
|
7051
|
+
if (node.children) {
|
|
7052
|
+
const label = node.componentName ? `${node.title} [${node.componentName}]` : node.title;
|
|
7053
|
+
console.group(label);
|
|
7054
|
+
for (const child of node.children)
|
|
7055
|
+
reportTestNode(child);
|
|
7056
|
+
console.groupEnd();
|
|
7057
|
+
return;
|
|
7180
7058
|
}
|
|
7181
|
-
|
|
7182
|
-
|
|
7059
|
+
const dur = node.status === "skip" ? "" : ` (${Math.round(node.durationMs)}ms)`;
|
|
7060
|
+
if (node.status === "pass") {
|
|
7061
|
+
console.log(`%c✓%c ${node.title}%c${dur}`, PASS, RESET, DIM);
|
|
7062
|
+
} else if (node.status === "skip") {
|
|
7063
|
+
console.log(`%c○ ${node.title}%c (skipped)`, SKIP, RESET);
|
|
7064
|
+
} else {
|
|
7065
|
+
console.group(`%c✗%c ${node.title}%c${dur}`, FAIL, RESET, DIM);
|
|
7066
|
+
console.error(node.error?.message ?? "(no error message)");
|
|
7067
|
+
if (node.error && (("expected" in node.error) || ("actual" in node.error))) {
|
|
7068
|
+
console.log("expected:", node.error.expected);
|
|
7069
|
+
console.log("actual: ", node.error.actual);
|
|
7070
|
+
}
|
|
7071
|
+
if (node.error?.stack)
|
|
7072
|
+
console.log(node.error.stack);
|
|
7073
|
+
console.groupEnd();
|
|
7074
|
+
}
|
|
7075
|
+
}
|
|
7076
|
+
function reportTestReportToConsole(report) {
|
|
7077
|
+
for (const m of report.modules) {
|
|
7078
|
+
const label = `tutuca tests${m.path ? ` — ${m.path}` : ""}`;
|
|
7079
|
+
console.group(label);
|
|
7080
|
+
if (m.suites.length === 0) {
|
|
7081
|
+
console.log("(no tests)");
|
|
7082
|
+
} else {
|
|
7083
|
+
for (const s of m.suites)
|
|
7084
|
+
reportTestNode(s);
|
|
7085
|
+
}
|
|
7086
|
+
const c = m.counts;
|
|
7087
|
+
const summary = `${c.pass} passed, ${c.fail} failed, ${c.skip} skipped (${c.total} total)`;
|
|
7088
|
+
if (c.fail > 0)
|
|
7089
|
+
console.error(`%c${summary}`, FAIL);
|
|
7090
|
+
else if (c.total === 0)
|
|
7091
|
+
console.log(`%c${summary}`, DIM);
|
|
7092
|
+
else
|
|
7093
|
+
console.log(`%c${summary}`, PASS);
|
|
7094
|
+
console.groupEnd();
|
|
7095
|
+
}
|
|
7096
|
+
return report;
|
|
7097
|
+
}
|
|
7098
|
+
|
|
7099
|
+
// tools/format/lint.js
|
|
7100
|
+
var UNSUPPORTED_EXPR_LABEL = {
|
|
7101
|
+
ternary: "ternary expression",
|
|
7102
|
+
comparison: "comparison",
|
|
7103
|
+
logical: "logical expression",
|
|
7104
|
+
"call-with-args": "method call with arguments"
|
|
7105
|
+
};
|
|
7106
|
+
function unsupportedExprMessage(info) {
|
|
7107
|
+
const v = JSON.stringify(info.value);
|
|
7108
|
+
const label = UNSUPPORTED_EXPR_LABEL[info.detected] ?? "expression";
|
|
7109
|
+
switch (info.role) {
|
|
7110
|
+
case "attr":
|
|
7111
|
+
return `Unsupported ${label} ${v} in dynamic attribute ':${info.attr}'`;
|
|
7112
|
+
case "directive":
|
|
7113
|
+
return `Unsupported ${label} ${v} in directive '@${info.directive}'`;
|
|
7114
|
+
case "if":
|
|
7115
|
+
return `Unsupported ${label} ${v} in '@if.${info.attr}' condition`;
|
|
7116
|
+
case "x-op":
|
|
7117
|
+
return `Unsupported ${label} ${v} in <x ${info.op}>`;
|
|
7118
|
+
default:
|
|
7119
|
+
return `Unsupported ${label} ${v}`;
|
|
7120
|
+
}
|
|
7121
|
+
}
|
|
7122
|
+
function badValueMessage(info) {
|
|
7123
|
+
const v = JSON.stringify(info.value);
|
|
7124
|
+
switch (info.role) {
|
|
7125
|
+
case "attr":
|
|
7126
|
+
return `Cannot parse value ${v} for attribute ':${info.attr}'`;
|
|
7127
|
+
case "directive":
|
|
7128
|
+
return `Cannot parse value ${v} for directive '@${info.directive}'`;
|
|
7129
|
+
case "if":
|
|
7130
|
+
return `Cannot parse condition ${v} for '@if.${info.attr}'`;
|
|
7131
|
+
case "x-op":
|
|
7132
|
+
return `Cannot parse value ${v} for <x ${info.op}>`;
|
|
7133
|
+
case "handler-name":
|
|
7134
|
+
return `Cannot parse handler name ${v}`;
|
|
7135
|
+
case "handler-arg":
|
|
7136
|
+
return `Cannot parse handler argument ${v}`;
|
|
7137
|
+
case "macro-var":
|
|
7138
|
+
return `Macro variable '^${info.name}' is not defined`;
|
|
7139
|
+
default:
|
|
7140
|
+
return `Cannot parse value ${v}`;
|
|
7141
|
+
}
|
|
7142
|
+
}
|
|
7143
|
+
function tagDisplay(tag) {
|
|
7144
|
+
return tag ? String(tag).toLowerCase() : null;
|
|
7145
|
+
}
|
|
7146
|
+
function fmtTagSuffix(info) {
|
|
7147
|
+
const t = tagDisplay(info?.tag);
|
|
7148
|
+
return t && t !== "x" ? ` on <${t}>` : "";
|
|
7149
|
+
}
|
|
7150
|
+
function fmtOriginSuffix(info) {
|
|
7151
|
+
if (!info)
|
|
7152
|
+
return "";
|
|
7153
|
+
const parts = [];
|
|
7154
|
+
if (info.originAttr) {
|
|
7155
|
+
const branch = info.branch ? `[${info.branch}]` : "";
|
|
7156
|
+
parts.push(`in ${info.originAttr}${branch}`);
|
|
7157
|
+
}
|
|
7158
|
+
if (info.handlerName) {
|
|
7159
|
+
parts.push(`handler '${info.handlerName}'${info.argIndex !== undefined ? ` arg ${info.argIndex}` : ""}`);
|
|
7160
|
+
}
|
|
7161
|
+
const t = tagDisplay(info.tag);
|
|
7162
|
+
if (t && t !== "x")
|
|
7163
|
+
parts.push(`on <${t}>`);
|
|
7164
|
+
return parts.length ? ` (${parts.join(", ")})` : "";
|
|
7165
|
+
}
|
|
7166
|
+
function fmtEventSuffix(info) {
|
|
7167
|
+
if (info?.originAttr)
|
|
7168
|
+
return ` in ${info.originAttr}`;
|
|
7169
|
+
if (info?.eventName)
|
|
7170
|
+
return ` in @on.${info.eventName}`;
|
|
7171
|
+
return "";
|
|
7172
|
+
}
|
|
7173
|
+
function lintIdToMessage(id, info) {
|
|
7174
|
+
switch (id) {
|
|
7175
|
+
case "RENDER_IT_OUTSIDE_OF_LOOP":
|
|
7176
|
+
return "<x render-it> used outside of a loop";
|
|
7177
|
+
case "UNKNOWN_EVENT_MODIFIER": {
|
|
7178
|
+
const mods = info.handler?.modifiers ?? [info.modifier];
|
|
7179
|
+
const written = `@on.${info.name}+${mods.join("+")}`;
|
|
7180
|
+
return `Unknown modifier '+${info.modifier}' in '${written}'`;
|
|
7181
|
+
}
|
|
7182
|
+
case "UNKNOWN_HANDLER_ARG_NAME":
|
|
7183
|
+
return `Unknown handler argument '${info.name}'${fmtOriginSuffix(info)}`;
|
|
7184
|
+
case "INPUT_HANDLER_NOT_IMPLEMENTED":
|
|
7185
|
+
return `Input handler '${info.name}' is not implemented${fmtEventSuffix(info)}`;
|
|
7186
|
+
case "INPUT_HANDLER_NOT_REFERENCED":
|
|
7187
|
+
return `Input handler '${info.name}' is defined but never used — remove it or wire it to an @on.* event`;
|
|
7188
|
+
case "INPUT_HANDLER_METHOD_NOT_IMPLEMENTED":
|
|
7189
|
+
return `Method '$${info.name}' is not implemented${fmtEventSuffix(info)}`;
|
|
7190
|
+
case "INPUT_HANDLER_FOR_INPUT_HANDLER_METHOD":
|
|
7191
|
+
return `'$${info.name}' is a method reference, but '${info.name}' is defined as an input handler${fmtEventSuffix(info)}`;
|
|
7192
|
+
case "INPUT_HANDLER_METHOD_FOR_INPUT_HANDLER":
|
|
7193
|
+
return `'${info.name}' is an input handler reference, but '${info.name}' is defined as a method${fmtEventSuffix(info)}`;
|
|
7194
|
+
case "FIELD_VAL_NOT_DEFINED":
|
|
7195
|
+
return `Field '.${info.name}' is not defined${fmtOriginSuffix(info)}`;
|
|
7196
|
+
case "FIELD_VAL_IS_METHOD":
|
|
7197
|
+
return `'.${info.name}' reads a field, but '${info.name}' is defined as a method — use '$${info.name}'${fmtOriginSuffix(info)}`;
|
|
7198
|
+
case "METHOD_VAL_NOT_DEFINED":
|
|
7199
|
+
return `Method '$${info.name}' is not defined${fmtOriginSuffix(info)}`;
|
|
7200
|
+
case "METHOD_VAL_IS_FIELD":
|
|
7201
|
+
return `'$${info.name}' calls a method, but '${info.name}' is defined as a field — use '.${info.name}'${fmtOriginSuffix(info)}`;
|
|
7202
|
+
case "DUPLICATE_ATTR_DEFINITION": {
|
|
7203
|
+
const sources = info.sources?.length ? ` (${info.sources.join(", ")})` : "";
|
|
7204
|
+
const tag = info.tag ? ` on <${String(info.tag).toLowerCase()}>` : "";
|
|
7205
|
+
return `Attribute '${info.name}' is set ${info.sources?.length ?? "multiple"} times${sources}${tag}`;
|
|
7206
|
+
}
|
|
7207
|
+
case "IF_NO_BRANCH_SET":
|
|
7208
|
+
return `'@if.${info.attr}' has no '@then' or '@else' branch — add '@then="…"' or '@else="…"' (or both)${fmtTagSuffix(info)}`;
|
|
7209
|
+
case "UNKNOWN_REQUEST_NAME":
|
|
7210
|
+
return `Unknown request '!${info.name}'${fmtOriginSuffix(info)}`;
|
|
7211
|
+
case "UNKNOWN_COMPONENT_NAME":
|
|
7212
|
+
return `Unknown component '${info.name}'${fmtOriginSuffix(info)}`;
|
|
7213
|
+
case "ALT_HANDLER_NOT_DEFINED":
|
|
7214
|
+
return `Alter handler '${info.name}' is not defined${fmtOriginSuffix(info)}`;
|
|
7215
|
+
case "ALT_HANDLER_NOT_REFERENCED":
|
|
7216
|
+
return `Alter handler '${info.name}' is defined but never used — remove it or reference it from @when, @enrich-with, or @loop-with`;
|
|
7217
|
+
case "DYN_VAL_NOT_DEFINED":
|
|
7218
|
+
return `Dynamic variable '*${info.name}' is not defined${fmtOriginSuffix(info)}`;
|
|
7219
|
+
case "DYN_ALIAS_NOT_REFERENCED":
|
|
7220
|
+
return `Lookup '${info.name}' is defined but never used — remove it or reference it as '*${info.name}' in a view`;
|
|
7221
|
+
case "PROVIDE_NOT_ADDRESSABLE":
|
|
7222
|
+
return `Provide '${info.name}' value '${info.value}' must be a field ('.f') or seq-access ('.s[.k]') — a method/constant can't be a render target`;
|
|
7223
|
+
case "LOOKUP_BAD_SHAPE":
|
|
7224
|
+
return `Lookup '${info.name}' has an invalid shape: ${info.problem}`;
|
|
7225
|
+
case "LOOKUP_TARGET_MALFORMED":
|
|
7226
|
+
return `Lookup '${info.name}' target '${info.target}' must be 'Producer.provideName' (a string, or the 'for' of { for, default })`;
|
|
7227
|
+
case "UNKNOWN_MACRO_ARG":
|
|
7228
|
+
return `Argument '${info.name}' is not declared in macro '${info.macroName}'`;
|
|
7229
|
+
case "UNKNOWN_DIRECTIVE":
|
|
7230
|
+
return `Unknown directive '@${info.name}=${JSON.stringify(info.value)}'${fmtTagSuffix(info)}`;
|
|
7231
|
+
case "UNKNOWN_X_OP":
|
|
7232
|
+
return `Unknown <x> op '${info.name}=${JSON.stringify(info.value)}'${fmtTagSuffix(info)}`;
|
|
7233
|
+
case "UNKNOWN_X_ATTR":
|
|
7234
|
+
return `Unknown attribute '${info.name}=${JSON.stringify(info.value)}' on <x ${info.op}>${fmtTagSuffix(info)}`;
|
|
7235
|
+
case "MAYBE_DROP_AT_PREFIX": {
|
|
7236
|
+
const written = info.value !== undefined ? `${info.name}=${JSON.stringify(info.value)}` : info.name;
|
|
7237
|
+
return `'${written}' on <x> looks like a directive but is actually an x op/attr written with a leading '@'`;
|
|
7238
|
+
}
|
|
7239
|
+
case "MAYBE_ADD_AT_PREFIX":
|
|
7240
|
+
return `'${info.name}' on <${(info.tag ?? "").toLowerCase()}> is a plain attribute, but '@${info.name}' is a directive — add the leading '@'`;
|
|
7241
|
+
case "BAD_VALUE":
|
|
7242
|
+
return `${badValueMessage(info)}${fmtTagSuffix(info)}`;
|
|
7243
|
+
case "UNSUPPORTED_EXPR_SYNTAX":
|
|
7244
|
+
return `${unsupportedExprMessage(info)}${fmtTagSuffix(info)}`;
|
|
7245
|
+
case "REDUNDANT_TEMPLATE_STRING":
|
|
7246
|
+
return `Redundant template string — '{${info.simpler}}' should be just '${info.simpler}'${fmtOriginSuffix(info)}`;
|
|
7247
|
+
case "PLACEHOLDERLESS_TEMPLATE_STRING":
|
|
7248
|
+
return `Template string has no dynamic parts — use the string literal ${info.literal} instead${fmtOriginSuffix(info)}`;
|
|
7249
|
+
case "UNKNOWN_COMPONENT_SPEC_KEY":
|
|
7250
|
+
return `Unknown component spec key '${info.key}' — value will be ignored at runtime`;
|
|
7251
|
+
case "COMP_FIELD_BAD_SHAPE":
|
|
7252
|
+
return info.kind === "args-not-object" ? `Field '${info.fieldName}': in { component, args }, 'args' must be a plain object, got ${info.got}` : `Field '${info.fieldName}': in { component, args }, 'component' must be the component name as a string, got ${info.gotName ? `the ${info.gotName} class` : info.got}`;
|
|
7253
|
+
case "HTML_TAG_NAME_HAS_UPPERCASE":
|
|
7254
|
+
return `Tag <${info.raw}> will be lowercased to <${info.lowercased}>${fmtLocationSuffix(info)}`;
|
|
7255
|
+
case "HTML_SVG_TAG_WILL_LOWERCASE":
|
|
7256
|
+
return `SVG tag <${info.raw}> is not in the WHATWG case-correction list — will be lowercased to <${info.lowercased}>${fmtLocationSuffix(info)}`;
|
|
7257
|
+
case "HTML_TAG_NOT_ALLOWED_IN_PARENT":
|
|
7258
|
+
return `<${info.tag}> not allowed under <${info.parent ?? "?"}> in ${info.mode} — ${htmlActionPhrase(info.action, info.tag, info.parent)}${fmtLocationSuffix(info)}`;
|
|
7259
|
+
case "HTML_TEXT_NOT_ALLOWED_IN_PARENT":
|
|
7260
|
+
return `Non-whitespace text not allowed in ${info.mode}: ${JSON.stringify(info.snippet)}${fmtLocationSuffix(info)}`;
|
|
7261
|
+
case "HTML_VOID_ELEMENT_HAS_CLOSE_TAG":
|
|
7262
|
+
return `Void element <${info.tag}> has an explicit close tag${fmtLocationSuffix(info)}`;
|
|
7263
|
+
case "HTML_DUPLICATE_FORM":
|
|
7264
|
+
return `Nested <form> — the inner form will be dropped by the parser${fmtLocationSuffix(info)}`;
|
|
7265
|
+
case "HTML_NESTED_INTERACTIVE":
|
|
7266
|
+
return `<${info.tag}> nested inside another <${info.tag}> — adoption agency will reorder${fmtLocationSuffix(info)}`;
|
|
7267
|
+
case "HTML_MISNESTED_FORMATTING":
|
|
7268
|
+
return `Misnested formatting tag </${info.tag}> — adoption agency will reorder nodes${fmtLocationSuffix(info)}`;
|
|
7269
|
+
case "HTML_UNEXPECTED_END_TAG":
|
|
7270
|
+
return `Unexpected end tag </${info.tag}>${fmtLocationSuffix(info)}`;
|
|
7271
|
+
case "HTML_UNCLOSED_BEFORE_END":
|
|
7272
|
+
return `<${info.unclosed}> still open when </${info.tag}> was seen — implicitly closed${fmtLocationSuffix(info)}`;
|
|
7273
|
+
case "HTML_DUPLICATE_ATTRIBUTE":
|
|
7274
|
+
return `Duplicate attribute '${info.name}' — second occurrence dropped${fmtLocationSuffix(info)}`;
|
|
7275
|
+
case "HTML_ATTRIBUTES_ON_END_TAG":
|
|
7276
|
+
return `Attributes on end tag </${info.tag}> — dropped by the parser${fmtLocationSuffix(info)}`;
|
|
7277
|
+
case "HTML_SELF_CLOSING_END_TAG":
|
|
7278
|
+
return `Self-closing end tag </${info.tag}/> — trailing '/' is meaningless${fmtLocationSuffix(info)}`;
|
|
7279
|
+
case "HTML_MISSING_ATTRIBUTE_VALUE":
|
|
7280
|
+
return `Attribute '${info.name}' is missing a value${fmtLocationSuffix(info)}`;
|
|
7281
|
+
case "HTML_CDATA_IN_HTML_NAMESPACE":
|
|
7282
|
+
return `CDATA section in HTML namespace — reinterpreted as a bogus comment${fmtLocationSuffix(info)}`;
|
|
7283
|
+
case "HTML_BOGUS_COMMENT":
|
|
7284
|
+
return `Bogus comment — content dropped by the parser${fmtLocationSuffix(info)}`;
|
|
7285
|
+
case "HTML_SVG_ATTR_WILL_LOWERCASE":
|
|
7286
|
+
return `SVG attribute '${info.raw}' will be rewritten to '${info.canonical}'${fmtLocationSuffix(info)}`;
|
|
7287
|
+
case "HTML_MATHML_ATTR_WILL_LOWERCASE":
|
|
7288
|
+
return `MathML attribute '${info.raw}' will be rewritten to '${info.canonical}'${fmtLocationSuffix(info)}`;
|
|
7289
|
+
case "ASYNC_HANDLER":
|
|
7290
|
+
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)`;
|
|
7291
|
+
case "TOP_LEVEL_AT_RULE_IN_SCOPED_STYLE":
|
|
7292
|
+
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)}`;
|
|
7293
|
+
case "GLOBAL_SELECTOR_IN_SCOPED_STYLE":
|
|
7294
|
+
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)}`;
|
|
7295
|
+
case "LINT_ERROR":
|
|
7296
|
+
return info.message;
|
|
7297
|
+
default:
|
|
7298
|
+
return id;
|
|
7299
|
+
}
|
|
7300
|
+
}
|
|
7301
|
+
function suggestionToMessage(suggestion) {
|
|
7302
|
+
if (!suggestion)
|
|
7303
|
+
return null;
|
|
7304
|
+
switch (suggestion.kind) {
|
|
7305
|
+
case "replace-name":
|
|
7306
|
+
return `did you mean '${suggestion.to}'?`;
|
|
7307
|
+
case "drop-prefix":
|
|
7308
|
+
return `did you mean '${suggestion.to}'? (drop the leading '${suggestion.from.slice(0, suggestion.from.length - suggestion.to.length)}')`;
|
|
7309
|
+
case "add-prefix":
|
|
7310
|
+
return `did you mean '${suggestion.to}'? (add the leading '${suggestion.to.slice(0, suggestion.to.length - suggestion.from.length)}')`;
|
|
7311
|
+
case "remove":
|
|
7312
|
+
return `remove ${suggestion.what}`;
|
|
7313
|
+
case "rewrite":
|
|
7314
|
+
return `use '${suggestion.to}' instead of '${suggestion.from}'`;
|
|
7315
|
+
case "wrap":
|
|
7316
|
+
return `wrap it in ${suggestion.to}`;
|
|
7317
|
+
case "rephrase":
|
|
7318
|
+
return suggestion.text ?? null;
|
|
7319
|
+
default:
|
|
7320
|
+
return null;
|
|
7321
|
+
}
|
|
7322
|
+
}
|
|
7323
|
+
function fmtLocationSuffix(info) {
|
|
7324
|
+
const loc = info?.location;
|
|
7325
|
+
if (!loc)
|
|
7326
|
+
return "";
|
|
7327
|
+
return ` at line ${loc.line}, col ${loc.column}`;
|
|
7328
|
+
}
|
|
7329
|
+
function htmlActionPhrase(action, tag, parent) {
|
|
7330
|
+
switch (action) {
|
|
7331
|
+
case "ignored":
|
|
7332
|
+
return `the parser will drop this <${tag}>`;
|
|
7333
|
+
case "drop":
|
|
7334
|
+
return `the parser will drop this <${tag}>`;
|
|
7335
|
+
case "auto-close-implicit":
|
|
7336
|
+
return `the parser will close <${parent ?? "?"}> first, then place <${tag}> as a sibling`;
|
|
7337
|
+
case "foster-parent":
|
|
7338
|
+
return `the parser will move <${tag}> outside <${parent ?? "?"}> (foster-parenting)`;
|
|
7339
|
+
case "foreign-breakout":
|
|
7340
|
+
return `the parser will exit foreign content and re-process <${tag}> in HTML mode`;
|
|
7341
|
+
default:
|
|
7342
|
+
return `parser action: ${action}`;
|
|
7183
7343
|
}
|
|
7184
7344
|
}
|
|
7185
7345
|
|
|
@@ -8208,9 +8368,11 @@ export {
|
|
|
8208
8368
|
setIn,
|
|
8209
8369
|
set,
|
|
8210
8370
|
runTests,
|
|
8371
|
+
resolveArgs,
|
|
8211
8372
|
reportTestReportToConsole,
|
|
8212
8373
|
removeIn,
|
|
8213
8374
|
remove,
|
|
8375
|
+
phaseOps,
|
|
8214
8376
|
mergeWith,
|
|
8215
8377
|
mergeDeepWith,
|
|
8216
8378
|
mergeDeep,
|
|
@@ -8247,6 +8409,7 @@ export {
|
|
|
8247
8409
|
get,
|
|
8248
8410
|
fromJS,
|
|
8249
8411
|
docComponents,
|
|
8412
|
+
dispatchPhase,
|
|
8250
8413
|
css,
|
|
8251
8414
|
component,
|
|
8252
8415
|
compileClassesToStyleText,
|