@schukai/monster 4.152.0 → 4.153.1
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/README.md +24 -1
- package/package.json +1 -1
- package/source/components/content/viewer/message.mjs +1 -0
- package/source/components/form/select.mjs +2 -0
- package/source/components/form/util/fetch.mjs +6 -7
- package/source/components/state/log.mjs +7 -0
- package/source/components/state/thread.mjs +11 -0
- package/source/components/time/month-calendar.mjs +80 -30
- package/source/data/buildmap.mjs +3 -2
- package/source/data/buildtree.mjs +0 -8
- package/source/data/pathfinder.mjs +48 -19
- package/source/data/transformer.mjs +2 -2
- package/source/dom/customcontrol.mjs +35 -9
- package/source/dom/customelement.mjs +21 -2
- package/source/dom/resource.mjs +19 -5
- package/source/dom/sanitize-html.mjs +34 -29
- package/source/dom/slotted.mjs +46 -31
- package/source/dom/template.mjs +4 -1
- package/source/dom/updater.mjs +51 -15
- package/source/types/node.mjs +1 -3
- package/source/types/proxyobserver.mjs +32 -10
- package/test/cases/components/datatable/drag-scroll.mjs +28 -1
- package/test/cases/components/form/button-bar.mjs +9 -6
- package/test/cases/components/form/confirm-button.mjs +4 -4
- package/test/cases/components/form/control-bar.mjs +73 -72
- package/test/cases/components/form/input-group.mjs +3 -1
- package/test/cases/components/form/password.mjs +2 -2
- package/test/cases/components/form/popper-button.mjs +2 -2
- package/test/cases/components/form/select-sort-callback.mjs +57 -0
- package/test/cases/components/form/select.mjs +2 -2
- package/test/cases/components/form/sheet.mjs +13 -1
- package/test/cases/components/layout/popper.mjs +3 -1
- package/test/cases/components/layout/tabs.mjs +4 -1
- package/test/cases/components/navigation/site-navigation.mjs +12 -26
- package/test/cases/components/navigation/table-of-content.mjs +3 -0
- package/test/cases/components/state/ticker-lifecycle.mjs +47 -0
- package/test/cases/components/time/month-calendar.mjs +100 -0
- package/test/cases/data/buildmap.mjs +14 -0
- package/test/cases/data/buildtree.mjs +49 -0
- package/test/cases/data/pathfinder.mjs +34 -0
- package/test/cases/data/transformer.mjs +33 -0
- package/test/cases/dom/customcontrol.mjs +87 -6
- package/test/cases/dom/customelement.mjs +54 -0
- package/test/cases/dom/ready.mjs +3 -3
- package/test/cases/dom/resource-availability.mjs +46 -0
- package/test/cases/dom/resourcemanager.mjs +12 -6
- package/test/cases/dom/sanitize-html.mjs +71 -0
- package/test/cases/dom/slotted-nodes.mjs +48 -1
- package/test/cases/dom/template.mjs +11 -0
- package/test/cases/dom/updater.mjs +119 -1
- package/test/cases/types/proxyobserver.mjs +75 -0
- package/test/cases/util/processing.mjs +3 -3
|
@@ -1,14 +1,61 @@
|
|
|
1
1
|
import {expect} from 'chai';
|
|
2
2
|
import {getSlottedNodes} from "../../../source/dom/slotted.mjs";
|
|
3
|
+
import {getSlottedElements} from "../../../source/dom/slotted.mjs";
|
|
4
|
+
import {initJSDOM} from "../../util/jsdom.mjs";
|
|
3
5
|
|
|
4
6
|
|
|
5
7
|
describe('getSlottedNodes', () => {
|
|
6
8
|
|
|
9
|
+
before(async () => {
|
|
10
|
+
await initJSDOM();
|
|
11
|
+
});
|
|
12
|
+
|
|
7
13
|
|
|
8
14
|
it('should return an empty Set if there is no ShadowRoot', () => {
|
|
9
15
|
expect(getSlottedNodes).is.a('function');
|
|
10
16
|
});
|
|
11
17
|
|
|
18
|
+
it('should ignore text nodes when applying an element query issue #567', () => {
|
|
19
|
+
const host = document.createElement('div');
|
|
20
|
+
host.append(' whitespace ');
|
|
21
|
+
const child = document.createElement('span');
|
|
22
|
+
child.className = 'match';
|
|
23
|
+
host.appendChild(child);
|
|
24
|
+
host.attachShadow({mode: 'open'}).innerHTML = '<slot></slot>';
|
|
25
|
+
document.body.appendChild(host);
|
|
26
|
+
|
|
27
|
+
expect([...getSlottedNodes.call(host, '.match')]).to.deep.equal([child]);
|
|
28
|
+
host.remove();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('should match empty and spaced slot names without selector interpolation issue #567', () => {
|
|
32
|
+
const host = document.createElement('div');
|
|
33
|
+
const defaultChild = document.createElement('span');
|
|
34
|
+
const namedChild = document.createElement('span');
|
|
35
|
+
namedChild.slot = 'some slot';
|
|
36
|
+
host.append(defaultChild, namedChild);
|
|
37
|
+
host.attachShadow({mode: 'open'}).innerHTML =
|
|
38
|
+
'<slot name=""></slot><slot name="some slot"></slot>';
|
|
39
|
+
document.body.appendChild(host);
|
|
40
|
+
|
|
41
|
+
expect([...getSlottedElements.call(host, undefined, null)]).to.deep.equal([defaultChild]);
|
|
42
|
+
expect([...getSlottedElements.call(host, undefined, 'some slot')]).to.deep.equal([namedChild]);
|
|
43
|
+
host.remove();
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('should accept the internally managed closed shadow root issue #567', () => {
|
|
47
|
+
const host = document.createElement('div');
|
|
48
|
+
const child = document.createElement('span');
|
|
49
|
+
host.appendChild(child);
|
|
50
|
+
const root = host.attachShadow({mode: 'closed'});
|
|
51
|
+
root.innerHTML = '<slot></slot>';
|
|
52
|
+
document.body.appendChild(host);
|
|
53
|
+
|
|
54
|
+
expect(host.shadowRoot).to.equal(null);
|
|
55
|
+
expect([...getSlottedElements.call(host, undefined, undefined, root)])
|
|
56
|
+
.to.deep.equal([child]);
|
|
57
|
+
host.remove();
|
|
58
|
+
});
|
|
12
59
|
|
|
13
|
-
});
|
|
14
60
|
|
|
61
|
+
});
|
|
@@ -81,6 +81,17 @@ describe('Template', function () {
|
|
|
81
81
|
expect(t).is.instanceof(Template);
|
|
82
82
|
|
|
83
83
|
})
|
|
84
|
+
|
|
85
|
+
it('should resolve from a text node context issue #567', function () {
|
|
86
|
+
const container = document.createElement('div');
|
|
87
|
+
const text = document.createTextNode('context');
|
|
88
|
+
container.appendChild(text);
|
|
89
|
+
document.body.appendChild(container);
|
|
90
|
+
|
|
91
|
+
const template = findDocumentTemplate('mytemplate', text);
|
|
92
|
+
expect(template).to.be.instanceof(Template);
|
|
93
|
+
container.remove();
|
|
94
|
+
});
|
|
84
95
|
});
|
|
85
96
|
|
|
86
97
|
describe('Thmened Template', function () {
|
|
@@ -780,7 +780,7 @@ describe("DOM", function () {
|
|
|
780
780
|
|
|
781
781
|
[false, true].forEach((batchUpdates) => {
|
|
782
782
|
it(`should bulk insert and reuse indexed entries with batchUpdates=${batchUpdates} issue #548`, async function () {
|
|
783
|
-
this.timeout(
|
|
783
|
+
this.timeout(20000);
|
|
784
784
|
const mocks = document.getElementById("mocks");
|
|
785
785
|
mocks.innerHTML = `
|
|
786
786
|
<template id="bulk-row">
|
|
@@ -1665,6 +1665,78 @@ describe("DOM", function () {
|
|
|
1665
1665
|
.catch((e) => done(new Error(e)));
|
|
1666
1666
|
});
|
|
1667
1667
|
|
|
1668
|
+
it("should not move unchanged keyed nodes issue #564", async function () {
|
|
1669
|
+
const element = document.getElementById("test-patch");
|
|
1670
|
+
const a = document.createElement("span");
|
|
1671
|
+
const b = document.createElement("span");
|
|
1672
|
+
a.dataset.key = "a";
|
|
1673
|
+
b.dataset.key = "b";
|
|
1674
|
+
|
|
1675
|
+
const updater = new Updater(element, {
|
|
1676
|
+
text: "",
|
|
1677
|
+
contentNode: document.createElement("div"),
|
|
1678
|
+
fragmentNode: document.createDocumentFragment(),
|
|
1679
|
+
itemsArray: [],
|
|
1680
|
+
keyedItems: [a, b],
|
|
1681
|
+
keyedDataItems: [],
|
|
1682
|
+
items: [],
|
|
1683
|
+
});
|
|
1684
|
+
updater.setCallback("getPatchKey", (value) => value?.dataset?.key);
|
|
1685
|
+
await updater.run();
|
|
1686
|
+
|
|
1687
|
+
const target = document.getElementById("patch-keyed");
|
|
1688
|
+
let moves = 0;
|
|
1689
|
+
const appendChild = target.appendChild;
|
|
1690
|
+
const insertBefore = target.insertBefore;
|
|
1691
|
+
target.appendChild = function (...args) {
|
|
1692
|
+
moves++;
|
|
1693
|
+
return appendChild.apply(this, args);
|
|
1694
|
+
};
|
|
1695
|
+
target.insertBefore = function (...args) {
|
|
1696
|
+
moves++;
|
|
1697
|
+
return insertBefore.apply(this, args);
|
|
1698
|
+
};
|
|
1699
|
+
|
|
1700
|
+
updater.getSubject().keyedItems = [a, b];
|
|
1701
|
+
await new Promise((resolve) => setTimeout(resolve, 30));
|
|
1702
|
+
|
|
1703
|
+
expect(moves).to.equal(0);
|
|
1704
|
+
expect(Array.from(target.children)).to.deep.equal([a, b]);
|
|
1705
|
+
});
|
|
1706
|
+
|
|
1707
|
+
it("should dispose a keyed node replaced under the same key issue #564", async function () {
|
|
1708
|
+
const element = document.getElementById("test-patch");
|
|
1709
|
+
const first = document.createElement("span");
|
|
1710
|
+
const replacement = document.createElement("span");
|
|
1711
|
+
first.dataset.key = "same";
|
|
1712
|
+
replacement.dataset.key = "same";
|
|
1713
|
+
let disposeCount = 0;
|
|
1714
|
+
addToObjectLink(
|
|
1715
|
+
first,
|
|
1716
|
+
customElementUpdaterLinkSymbol,
|
|
1717
|
+
new Set([{dispose() { disposeCount++; }}]),
|
|
1718
|
+
);
|
|
1719
|
+
|
|
1720
|
+
const updater = new Updater(element, {
|
|
1721
|
+
text: "",
|
|
1722
|
+
contentNode: document.createElement("div"),
|
|
1723
|
+
fragmentNode: document.createDocumentFragment(),
|
|
1724
|
+
itemsArray: [],
|
|
1725
|
+
keyedItems: [first],
|
|
1726
|
+
keyedDataItems: [],
|
|
1727
|
+
items: [],
|
|
1728
|
+
});
|
|
1729
|
+
updater.setCallback("getPatchKey", (value) => value?.dataset?.key);
|
|
1730
|
+
await updater.run();
|
|
1731
|
+
|
|
1732
|
+
updater.getSubject().keyedItems = [replacement];
|
|
1733
|
+
await new Promise((resolve) => setTimeout(resolve, 30));
|
|
1734
|
+
|
|
1735
|
+
expect(disposeCount).to.equal(1);
|
|
1736
|
+
expect(first.isConnected).to.equal(false);
|
|
1737
|
+
expect(document.getElementById("patch-keyed").firstChild).to.equal(replacement);
|
|
1738
|
+
});
|
|
1739
|
+
|
|
1668
1740
|
it("should remove stale keyed nodes and keep surviving node identity", function (done) {
|
|
1669
1741
|
let element = document.getElementById("test-patch");
|
|
1670
1742
|
const a = document.createElement("span");
|
|
@@ -2620,6 +2692,52 @@ describe("DOM", function () {
|
|
|
2620
2692
|
});
|
|
2621
2693
|
});
|
|
2622
2694
|
|
|
2695
|
+
describe("Updater binding correctness issue #563", function () {
|
|
2696
|
+
it("should ignore unchecked radios during retrieve", function () {
|
|
2697
|
+
const mocks = document.getElementById("mocks");
|
|
2698
|
+
mocks.innerHTML = `
|
|
2699
|
+
<input type="radio" value="selected" checked data-monster-bind="path:choice">
|
|
2700
|
+
<input type="radio" value="unchecked" data-monster-bind="path:choice">
|
|
2701
|
+
`;
|
|
2702
|
+
|
|
2703
|
+
const updater = new Updater(mocks, {choice: "initial"});
|
|
2704
|
+
updater.retrieve();
|
|
2705
|
+
|
|
2706
|
+
expect(updater.getSubject().choice).to.equal("selected");
|
|
2707
|
+
});
|
|
2708
|
+
|
|
2709
|
+
it("should not change select state for non-value attributes", async function () {
|
|
2710
|
+
const mocks = document.getElementById("mocks");
|
|
2711
|
+
mocks.innerHTML = `
|
|
2712
|
+
<select id="binding-select" data-monster-attributes="title path:title">
|
|
2713
|
+
<option value="a">a</option>
|
|
2714
|
+
<option value="b" selected>b</option>
|
|
2715
|
+
</select>
|
|
2716
|
+
`;
|
|
2717
|
+
|
|
2718
|
+
const updater = new Updater(mocks, {title: "label"});
|
|
2719
|
+
await updater.run();
|
|
2720
|
+
|
|
2721
|
+
const select = document.getElementById("binding-select");
|
|
2722
|
+
expect(select.title).to.equal("label");
|
|
2723
|
+
expect(select.value).to.equal("b");
|
|
2724
|
+
});
|
|
2725
|
+
|
|
2726
|
+
it("should evaluate static attribute and property commands", async function () {
|
|
2727
|
+
const mocks = document.getElementById("mocks");
|
|
2728
|
+
mocks.innerHTML = `
|
|
2729
|
+
<div id="static-attribute" data-monster-attributes="title static:hello"></div>
|
|
2730
|
+
<input id="static-property" data-monster-properties="value static:world">
|
|
2731
|
+
`;
|
|
2732
|
+
|
|
2733
|
+
const updater = new Updater(mocks, {trigger: true});
|
|
2734
|
+
await updater.run();
|
|
2735
|
+
|
|
2736
|
+
expect(document.getElementById("static-attribute").title).to.equal("hello");
|
|
2737
|
+
expect(document.getElementById("static-property").value).to.equal("world");
|
|
2738
|
+
});
|
|
2739
|
+
});
|
|
2740
|
+
|
|
2623
2741
|
describe("Updater pipe failure recovery issue #498", function () {
|
|
2624
2742
|
const waitForUpdate = () => new Promise((resolve) => setTimeout(resolve, 20));
|
|
2625
2743
|
|
|
@@ -241,6 +241,40 @@ describe('ProxyObserver', function () {
|
|
|
241
241
|
proxy.attachObserver(observer);
|
|
242
242
|
delete proxy.getSubject().a;
|
|
243
243
|
});
|
|
244
|
+
|
|
245
|
+
it('should ignore missing and inherited deletes without notifying issue #570', async function () {
|
|
246
|
+
const prototype = {inherited: true};
|
|
247
|
+
const value = Object.create(prototype);
|
|
248
|
+
const proxy = new ProxyObserver(value);
|
|
249
|
+
let notifications = 0;
|
|
250
|
+
proxy.attachObserver(new Observer(function () {
|
|
251
|
+
notifications++;
|
|
252
|
+
}));
|
|
253
|
+
|
|
254
|
+
expect(() => delete proxy.getSubject().missing).to.not.throw();
|
|
255
|
+
expect(() => delete proxy.getSubject().inherited).to.not.throw();
|
|
256
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
257
|
+
|
|
258
|
+
expect(proxy.getSubject().inherited).to.equal(true);
|
|
259
|
+
expect(notifications).to.equal(0);
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
it('should report failed non-configurable deletes without notifying issue #570', async function () {
|
|
263
|
+
const value = {};
|
|
264
|
+
Object.defineProperty(value, 'fixed', {
|
|
265
|
+
configurable: false,
|
|
266
|
+
value: true,
|
|
267
|
+
});
|
|
268
|
+
const proxy = new ProxyObserver(value);
|
|
269
|
+
let notifications = 0;
|
|
270
|
+
proxy.attachObserver(new Observer(function () {
|
|
271
|
+
notifications++;
|
|
272
|
+
}));
|
|
273
|
+
|
|
274
|
+
expect(Reflect.deleteProperty(proxy.getSubject(), 'fixed')).to.equal(false);
|
|
275
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
276
|
+
expect(notifications).to.equal(0);
|
|
277
|
+
});
|
|
244
278
|
});
|
|
245
279
|
|
|
246
280
|
describe('symbol properties', function () {
|
|
@@ -342,6 +376,47 @@ describe('ProxyObserver', function () {
|
|
|
342
376
|
expect(proxy.getSubject().map).to.equal(replacement);
|
|
343
377
|
expect(notifications).to.equal(1);
|
|
344
378
|
});
|
|
379
|
+
|
|
380
|
+
it('should obey frozen-property proxy invariants issue #570', function () {
|
|
381
|
+
const nested = {value: true};
|
|
382
|
+
const frozen = Object.freeze({nested});
|
|
383
|
+
const subject = new ProxyObserver({frozen}).getSubject();
|
|
384
|
+
|
|
385
|
+
expect(() => subject.frozen.nested).to.not.throw();
|
|
386
|
+
expect(subject.frozen.nested).to.equal(nested);
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
it('should preserve confirmed internal-slot native objects issue #570', async function () {
|
|
390
|
+
const weakKey = {};
|
|
391
|
+
const regexp = /monster/g;
|
|
392
|
+
const buffer = new ArrayBuffer(8);
|
|
393
|
+
const view = new DataView(buffer);
|
|
394
|
+
const typed = new Uint8Array(buffer);
|
|
395
|
+
const weakMap = new WeakMap([[weakKey, 'value']]);
|
|
396
|
+
const weakSet = new WeakSet([weakKey]);
|
|
397
|
+
const promise = Promise.resolve('resolved');
|
|
398
|
+
const subject = new ProxyObserver({
|
|
399
|
+
regexp,
|
|
400
|
+
buffer,
|
|
401
|
+
view,
|
|
402
|
+
typed,
|
|
403
|
+
weakMap,
|
|
404
|
+
weakSet,
|
|
405
|
+
promise,
|
|
406
|
+
}).getSubject();
|
|
407
|
+
|
|
408
|
+
expect(subject.regexp).to.equal(regexp);
|
|
409
|
+
expect(subject.regexp.test('monster')).to.equal(true);
|
|
410
|
+
expect(subject.buffer).to.equal(buffer);
|
|
411
|
+
expect(subject.buffer.byteLength).to.equal(8);
|
|
412
|
+
expect(subject.view).to.equal(view);
|
|
413
|
+
expect(subject.view.byteLength).to.equal(8);
|
|
414
|
+
expect(subject.typed).to.equal(typed);
|
|
415
|
+
expect(subject.typed.length).to.equal(8);
|
|
416
|
+
expect(subject.weakMap.get(weakKey)).to.equal('value');
|
|
417
|
+
expect(subject.weakSet.has(weakKey)).to.equal(true);
|
|
418
|
+
expect(await subject.promise).to.equal('resolved');
|
|
419
|
+
});
|
|
345
420
|
});
|
|
346
421
|
|
|
347
422
|
})
|
|
@@ -12,7 +12,7 @@ describe('Processing', function () {
|
|
|
12
12
|
let t = +new Date();
|
|
13
13
|
|
|
14
14
|
const desiredDelay = 200;
|
|
15
|
-
this.timeout(
|
|
15
|
+
this.timeout(2000);
|
|
16
16
|
|
|
17
17
|
// delay 12
|
|
18
18
|
new Processing((v) => {
|
|
@@ -33,7 +33,7 @@ describe('Processing', function () {
|
|
|
33
33
|
expect(counter).to.be.equal(4);
|
|
34
34
|
expect(v === 'test').to.be.true;
|
|
35
35
|
// check delay
|
|
36
|
-
expect(+new Date()
|
|
36
|
+
expect(+new Date() >= t + desiredDelay).to.be.true;
|
|
37
37
|
} catch (e) {
|
|
38
38
|
return done(e);
|
|
39
39
|
}
|
|
@@ -107,4 +107,4 @@ describe('Processing', function () {
|
|
|
107
107
|
|
|
108
108
|
});
|
|
109
109
|
|
|
110
|
-
});
|
|
110
|
+
});
|