@ng-org/alien-deepsignals 0.1.2-alpha.5 → 0.1.2-alpha.7
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 +55 -374
- package/dist/core.d.ts +66 -60
- package/dist/core.d.ts.map +1 -1
- package/dist/core.js +70 -82
- package/dist/deepSignal.d.ts +19 -5
- package/dist/deepSignal.d.ts.map +1 -1
- package/dist/deepSignal.js +214 -141
- package/dist/effect.d.ts.map +1 -1
- package/dist/effect.js +8 -1
- package/dist/hooks/react/useDeepSignal.d.ts +1 -1
- package/dist/hooks/react/useDeepSignal.d.ts.map +1 -1
- package/dist/hooks/react/useDeepSignal.js +5 -2
- package/dist/hooks/svelte/index.d.ts +0 -1
- package/dist/hooks/svelte/index.d.ts.map +1 -1
- package/dist/hooks/svelte/useDeepSignal.svelte.d.ts +3 -15
- package/dist/hooks/svelte/useDeepSignal.svelte.d.ts.map +1 -1
- package/dist/hooks/svelte/useDeepSignal.svelte.js +29 -63
- package/dist/hooks/svelte4/index.d.ts +4 -0
- package/dist/hooks/svelte4/index.d.ts.map +1 -0
- package/dist/hooks/svelte4/index.js +8 -0
- package/dist/hooks/svelte4/useDeepSignal.svelte.d.ts +27 -0
- package/dist/hooks/svelte4/useDeepSignal.svelte.d.ts.map +1 -0
- package/dist/hooks/svelte4/useDeepSignal.svelte.js +91 -0
- package/dist/hooks/vue/useDeepSignal.d.ts +2 -2
- package/dist/hooks/vue/useDeepSignal.d.ts.map +1 -1
- package/dist/hooks/vue/useDeepSignal.js +22 -74
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -2
- package/dist/test/frontend/astro-app/src/components/ReactPanel.d.ts.map +1 -1
- package/dist/test/frontend/astro-app/src/components/{ReactPanel.js → ReactPanel.jsx} +56 -45
- package/dist/test/frontend/playwright/crossFrameworkHooks.spec.js +13 -3
- package/dist/test/frontend/utils/mockData.d.ts.map +1 -1
- package/dist/test/frontend/utils/mockData.js +13 -4
- package/dist/test/lib/index.test.js +16 -3
- package/dist/test/lib/misc.test.js +104 -1
- package/dist/test/lib/watch.test.js +2 -11
- package/dist/types.d.ts +94 -19
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +9 -0
- package/dist/watch.d.ts +37 -0
- package/dist/watch.d.ts.map +1 -1
- package/dist/watch.js +35 -0
- package/package.json +8 -5
- package/dist/test/frontend/astro-app/src/components/PerfSuiteClient.d.ts +0 -4
- package/dist/test/frontend/astro-app/src/components/PerfSuiteClient.d.ts.map +0 -1
- package/dist/test/frontend/astro-app/src/components/PerfSuiteClient.js +0 -225
- package/dist/test/frontend/astro-app/src/components/perf/react/ReactPerfDeep.d.ts +0 -4
- package/dist/test/frontend/astro-app/src/components/perf/react/ReactPerfDeep.d.ts.map +0 -1
- package/dist/test/frontend/astro-app/src/components/perf/react/ReactPerfDeep.js +0 -150
- package/dist/test/frontend/astro-app/src/components/perf/react/ReactPerfNative.d.ts +0 -4
- package/dist/test/frontend/astro-app/src/components/perf/react/ReactPerfNative.d.ts.map +0 -1
- package/dist/test/frontend/astro-app/src/components/perf/react/ReactPerfNative.js +0 -184
- package/dist/test/frontend/playwright/perfSuite.spec.d.ts +0 -2
- package/dist/test/frontend/playwright/perfSuite.spec.d.ts.map +0 -1
- package/dist/test/frontend/playwright/perfSuite.spec.js +0 -128
- package/dist/test/frontend/utils/perfScenarios.d.ts +0 -15
- package/dist/test/frontend/utils/perfScenarios.d.ts.map +0 -1
- package/dist/test/frontend/utils/perfScenarios.js +0 -287
- package/dist/test/lib/core.test.d.ts +0 -2
- package/dist/test/lib/core.test.d.ts.map +0 -1
- package/dist/test/lib/core.test.js +0 -53
package/dist/watch.d.ts
CHANGED
|
@@ -14,12 +14,49 @@ export interface WatchOptions {
|
|
|
14
14
|
triggerInstantly?: boolean;
|
|
15
15
|
}
|
|
16
16
|
export interface WatchPatchEvent<T extends object> {
|
|
17
|
+
/** The changes made */
|
|
17
18
|
patches: DeepPatch[];
|
|
18
19
|
/** The version if `triggerInstantly` is not true. */
|
|
19
20
|
version?: number;
|
|
21
|
+
/** The current value of the signal */
|
|
20
22
|
newValue: DeepSignal<T>;
|
|
21
23
|
}
|
|
22
24
|
export type WatchPatchCallback<T extends object> = (event: WatchPatchEvent<T>) => void;
|
|
25
|
+
/**
|
|
26
|
+
* Watch for changes to a deepSignal.
|
|
27
|
+
*
|
|
28
|
+
* Whenever a change is made, `callback` is called with the patches describing the change and the new value.
|
|
29
|
+
* If you set `triggerInstantly`, the callback is called on every property change.
|
|
30
|
+
* If not, all changes are aggregated and `callback` is called in a microtask when
|
|
31
|
+
* the current task finishes, e.g. `await` is called (meaning it supports batching).
|
|
32
|
+
*
|
|
33
|
+
* When objects are added to Sets, their **synthetic ID (usually `@id`) becomes part of the patch path**. This allows patches to uniquely identify which Set entry is being mutated.
|
|
34
|
+
*
|
|
35
|
+
* ```ts
|
|
36
|
+
* const state = deepSignal(
|
|
37
|
+
* { s: new Set() },
|
|
38
|
+
* { ...}
|
|
39
|
+
* );
|
|
40
|
+
*
|
|
41
|
+
* watch(state, ({ patches }) => {
|
|
42
|
+
* console.log(JSON.stringify(patches));
|
|
43
|
+
* });
|
|
44
|
+
*
|
|
45
|
+
* state.s.add({ data: "test" });
|
|
46
|
+
* // Will log:
|
|
47
|
+
* // [
|
|
48
|
+
* // {"path":["s","did:ng:o:123"],"op":"add","type":"object"},
|
|
49
|
+
* // {"path":["s","did:ng:o:123","@id"],"op":"add","value":"did:ng:o:123"},
|
|
50
|
+
* // {"path":["s","did:ng:o:123","data"],"op":"add","value":"test"}
|
|
51
|
+
* // ]
|
|
52
|
+
*
|
|
53
|
+
* state.s.getById("did:ng:o:123")!.data = "new value"
|
|
54
|
+
* // Will log:
|
|
55
|
+
* // [
|
|
56
|
+
* // {"path":["s","did:ng:o:123","data"],"op":"add","value":"new value"}
|
|
57
|
+
* // ]
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
23
60
|
export declare function watch<T extends object>(source: DeepSignalSet<T> | DeepSignalObject<T> | DeepSignal<T>, callback: WatchPatchCallback<T>, options?: WatchOptions): {
|
|
24
61
|
stopListening: () => void;
|
|
25
62
|
registerCleanup: RegisterCleanup;
|
package/dist/watch.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../src/watch.ts"],"names":[],"mappings":"AAgBA,OAAO,EACH,SAAS,EAET,UAAU,EACV,gBAAgB,EAChB,aAAa,EAChB,MAAM,SAAS,CAAC;AAEjB,MAAM,MAAM,eAAe,GAAG,CAAC,SAAS,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;AAE9D,MAAM,WAAW,YAAY;IACzB,8FAA8F;IAC9F,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,uFAAuF;IACvF,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,WAAW,eAAe,CAAC,CAAC,SAAS,MAAM;IAC7C,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,qDAAqD;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;CAC3B;AAED,MAAM,MAAM,kBAAkB,CAAC,CAAC,SAAS,MAAM,IAAI,CAC/C,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC,KACxB,IAAI,CAAC;AAEV,wBAAgB,KAAK,CAAC,CAAC,SAAS,MAAM,EAClC,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,EAC9D,QAAQ,EAAE,kBAAkB,CAAC,CAAC,CAAC,EAC/B,OAAO,GAAE,YAAiB;;;EAiE7B"}
|
|
1
|
+
{"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../src/watch.ts"],"names":[],"mappings":"AAgBA,OAAO,EACH,SAAS,EAET,UAAU,EACV,gBAAgB,EAChB,aAAa,EAChB,MAAM,SAAS,CAAC;AAEjB,MAAM,MAAM,eAAe,GAAG,CAAC,SAAS,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;AAE9D,MAAM,WAAW,YAAY;IACzB,8FAA8F;IAC9F,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,uFAAuF;IACvF,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,WAAW,eAAe,CAAC,CAAC,SAAS,MAAM;IAC7C,uBAAuB;IACvB,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,qDAAqD;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sCAAsC;IACtC,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;CAC3B;AAED,MAAM,MAAM,kBAAkB,CAAC,CAAC,SAAS,MAAM,IAAI,CAC/C,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC,KACxB,IAAI,CAAC;AAEV;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,KAAK,CAAC,CAAC,SAAS,MAAM,EAClC,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,EAC9D,QAAQ,EAAE,kBAAkB,CAAC,CAAC,CAAC,EAC/B,OAAO,GAAE,YAAiB;;;EAiE7B"}
|
package/dist/watch.js
CHANGED
|
@@ -11,6 +11,41 @@
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.watch = watch;
|
|
13
13
|
const deepSignal_1 = require("./deepSignal");
|
|
14
|
+
/**
|
|
15
|
+
* Watch for changes to a deepSignal.
|
|
16
|
+
*
|
|
17
|
+
* Whenever a change is made, `callback` is called with the patches describing the change and the new value.
|
|
18
|
+
* If you set `triggerInstantly`, the callback is called on every property change.
|
|
19
|
+
* If not, all changes are aggregated and `callback` is called in a microtask when
|
|
20
|
+
* the current task finishes, e.g. `await` is called (meaning it supports batching).
|
|
21
|
+
*
|
|
22
|
+
* When objects are added to Sets, their **synthetic ID (usually `@id`) becomes part of the patch path**. This allows patches to uniquely identify which Set entry is being mutated.
|
|
23
|
+
*
|
|
24
|
+
* ```ts
|
|
25
|
+
* const state = deepSignal(
|
|
26
|
+
* { s: new Set() },
|
|
27
|
+
* { ...}
|
|
28
|
+
* );
|
|
29
|
+
*
|
|
30
|
+
* watch(state, ({ patches }) => {
|
|
31
|
+
* console.log(JSON.stringify(patches));
|
|
32
|
+
* });
|
|
33
|
+
*
|
|
34
|
+
* state.s.add({ data: "test" });
|
|
35
|
+
* // Will log:
|
|
36
|
+
* // [
|
|
37
|
+
* // {"path":["s","did:ng:o:123"],"op":"add","type":"object"},
|
|
38
|
+
* // {"path":["s","did:ng:o:123","@id"],"op":"add","value":"did:ng:o:123"},
|
|
39
|
+
* // {"path":["s","did:ng:o:123","data"],"op":"add","value":"test"}
|
|
40
|
+
* // ]
|
|
41
|
+
*
|
|
42
|
+
* state.s.getById("did:ng:o:123")!.data = "new value"
|
|
43
|
+
* // Will log:
|
|
44
|
+
* // [
|
|
45
|
+
* // {"path":["s","did:ng:o:123","data"],"op":"add","value":"new value"}
|
|
46
|
+
* // ]
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
14
49
|
function watch(source, callback, options = {}) {
|
|
15
50
|
if (!(0, deepSignal_1.isDeepSignal)(source)) {
|
|
16
51
|
throw new Error("watch() expects a deepSignal root proxy");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ng-org/alien-deepsignals",
|
|
3
|
-
"version": "0.1.2-alpha.
|
|
3
|
+
"version": "0.1.2-alpha.7",
|
|
4
4
|
"private": false,
|
|
5
5
|
"authors": [
|
|
6
6
|
"Laurin Weger",
|
|
@@ -28,6 +28,10 @@
|
|
|
28
28
|
"types": "./dist/hooks/svelte/index.d.ts",
|
|
29
29
|
"default": "./dist/hooks/svelte/index.js"
|
|
30
30
|
},
|
|
31
|
+
"./svelte4": {
|
|
32
|
+
"types": "./dist/hooks/svelte4/index.d.ts",
|
|
33
|
+
"default": "./dist/hooks/svelte4/index.js"
|
|
34
|
+
},
|
|
31
35
|
"./vue": {
|
|
32
36
|
"types": "./dist/hooks/vue/index.d.ts",
|
|
33
37
|
"default": "./dist/hooks/vue/index.js"
|
|
@@ -38,18 +42,17 @@
|
|
|
38
42
|
},
|
|
39
43
|
"optionalDependencies": {
|
|
40
44
|
"react": "^19.0.0 || ^18.0.0",
|
|
41
|
-
"svelte": "^5.0.0",
|
|
45
|
+
"svelte": "^5.0.0 || ^4.0.0 || ^3.0.0",
|
|
42
46
|
"vue": "^3.0.0"
|
|
43
47
|
},
|
|
44
48
|
"devDependencies": {
|
|
45
49
|
"@astrojs/react": "^4.4.2",
|
|
46
50
|
"@astrojs/svelte": "^7.2.2",
|
|
47
51
|
"@astrojs/vue": "^5.1.3",
|
|
48
|
-
"@sveltejs/vite-plugin-svelte": "^6.2.1",
|
|
49
52
|
"@types/node": "^22.10.9",
|
|
50
53
|
"@types/react": "^19.2.7",
|
|
51
54
|
"@types/react-dom": "^19.2.2",
|
|
52
|
-
"@vitest/coverage-v8": "
|
|
55
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
53
56
|
"astro": "^5.16.1",
|
|
54
57
|
"@playwright/test": "^1.55.0",
|
|
55
58
|
"react-dom": "^19.0.0",
|
|
@@ -57,7 +60,7 @@
|
|
|
57
60
|
"svelte": "^5.1.9",
|
|
58
61
|
"typescript": "^5.4.3",
|
|
59
62
|
"vue": "^3.5.11",
|
|
60
|
-
"vitest": "^
|
|
63
|
+
"vitest": "^4.0.18"
|
|
61
64
|
},
|
|
62
65
|
"repository": {
|
|
63
66
|
"type": "git",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"PerfSuiteClient.d.ts","sourceRoot":"","sources":["../../../../../../src/test/frontend/astro-app/src/components/PerfSuiteClient.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAuC,MAAM,OAAO,CAAC;AA+C5D,QAAA,MAAM,eAAe,EAAE,KAAK,CAAC,EAkL5B,CAAC;AAEF,eAAe,eAAe,CAAC"}
|
|
@@ -1,225 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
const react_1 = __importStar(require("react"));
|
|
37
|
-
const perfScenarios_1 = require("../../../utils/perfScenarios");
|
|
38
|
-
const MAX_RESULTS = 12;
|
|
39
|
-
const sortResults = (results) => [...results].sort((a, b) => (b.completedAt ?? 0) - (a.completedAt ?? 0));
|
|
40
|
-
const resultSignature = (result) => [
|
|
41
|
-
result.framework,
|
|
42
|
-
result.variant,
|
|
43
|
-
result.completedAt ?? result.totalDuration,
|
|
44
|
-
result.runCount,
|
|
45
|
-
].join(":");
|
|
46
|
-
const attachEntryId = (result) => ({
|
|
47
|
-
...result,
|
|
48
|
-
entryId: `${result.framework}-${result.variant}-${result.completedAt ?? Date.now()}-${Math.random()
|
|
49
|
-
.toString(36)
|
|
50
|
-
.slice(2, 8)}`,
|
|
51
|
-
});
|
|
52
|
-
const seedResults = () => {
|
|
53
|
-
if (typeof window === "undefined")
|
|
54
|
-
return [];
|
|
55
|
-
const latest = window.perfSuite?.latestResults;
|
|
56
|
-
if (!latest)
|
|
57
|
-
return [];
|
|
58
|
-
const flattened = Object.values(latest).flatMap((variants) => Object.values(variants));
|
|
59
|
-
return sortResults(flattened.map(attachEntryId));
|
|
60
|
-
};
|
|
61
|
-
const formatDuration = (value) => `${value.toFixed(2)}ms`;
|
|
62
|
-
const formatSubRenderCount = (block, framework) => {
|
|
63
|
-
const entries = block.objectRenderCounts?.[framework];
|
|
64
|
-
if (!entries)
|
|
65
|
-
return 0;
|
|
66
|
-
return Object.values(entries).reduce((sum, count) => sum + count, 0);
|
|
67
|
-
};
|
|
68
|
-
const PerfSuiteClient = () => {
|
|
69
|
-
const [results, setResults] = (0, react_1.useState)(seedResults);
|
|
70
|
-
(0, react_1.useEffect)(() => {
|
|
71
|
-
if ((0, perfScenarios_1.registerPerfRunners)()) {
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
const timer = window.setInterval(() => {
|
|
75
|
-
if ((0, perfScenarios_1.registerPerfRunners)()) {
|
|
76
|
-
window.clearInterval(timer);
|
|
77
|
-
}
|
|
78
|
-
}, 50);
|
|
79
|
-
return () => {
|
|
80
|
-
window.clearInterval(timer);
|
|
81
|
-
};
|
|
82
|
-
}, []);
|
|
83
|
-
(0, react_1.useEffect)(() => {
|
|
84
|
-
if (typeof window === "undefined")
|
|
85
|
-
return;
|
|
86
|
-
const suite = window.perfSuite;
|
|
87
|
-
if (!suite?.subscribe)
|
|
88
|
-
return;
|
|
89
|
-
const unsubscribe = suite.subscribe((result) => {
|
|
90
|
-
setResults((current) => {
|
|
91
|
-
if (current.some((entry) => resultSignature(entry) === resultSignature(result))) {
|
|
92
|
-
return current;
|
|
93
|
-
}
|
|
94
|
-
const augmented = attachEntryId(result);
|
|
95
|
-
const next = sortResults([augmented, ...current]);
|
|
96
|
-
return next.slice(0, MAX_RESULTS);
|
|
97
|
-
});
|
|
98
|
-
});
|
|
99
|
-
return unsubscribe;
|
|
100
|
-
}, []);
|
|
101
|
-
const renderedList = (0, react_1.useMemo)(() => {
|
|
102
|
-
if (!results.length) {
|
|
103
|
-
return (<p className="perf-suite-results__empty">
|
|
104
|
-
Awaiting perf runner output…
|
|
105
|
-
</p>);
|
|
106
|
-
}
|
|
107
|
-
return results.map((result) => (<li key={result.entryId} className="perf-suite-results__item">
|
|
108
|
-
<header>
|
|
109
|
-
<strong>
|
|
110
|
-
{result.framework}/{result.variant}
|
|
111
|
-
</strong>
|
|
112
|
-
<span>{formatDuration(result.totalDuration)}</span>
|
|
113
|
-
</header>
|
|
114
|
-
<div className="perf-suite-results__meta">
|
|
115
|
-
<span>
|
|
116
|
-
runs {result.runCount}
|
|
117
|
-
{result.warmupCount
|
|
118
|
-
? ` (+${result.warmupCount} warmup)`
|
|
119
|
-
: ""}
|
|
120
|
-
</span>
|
|
121
|
-
{result.completedAt ? (<time>
|
|
122
|
-
{new Date(result.completedAt).toLocaleTimeString()}
|
|
123
|
-
</time>) : null}
|
|
124
|
-
</div>
|
|
125
|
-
<dl>
|
|
126
|
-
{Object.entries(result.blocks).map(([name, block]) => (<react_1.default.Fragment key={name}>
|
|
127
|
-
<div className="perf-suite-results__block">
|
|
128
|
-
<dt>{name}</dt>
|
|
129
|
-
<dd>{formatDuration(block.duration)}</dd>
|
|
130
|
-
</div>
|
|
131
|
-
<div className="perf-suite-results__block perf-suite-results__block--subrenders">
|
|
132
|
-
<dt>Subcomponent renders</dt>
|
|
133
|
-
<dd>
|
|
134
|
-
{formatSubRenderCount(block, result.framework)}
|
|
135
|
-
</dd>
|
|
136
|
-
</div>
|
|
137
|
-
</react_1.default.Fragment>))}
|
|
138
|
-
</dl>
|
|
139
|
-
</li>));
|
|
140
|
-
}, [results]);
|
|
141
|
-
return (<div className="perf-suite-results">
|
|
142
|
-
<div className="perf-suite-results__header">
|
|
143
|
-
<h3>Latest Perf Runs</h3>
|
|
144
|
-
<p>Playwright tests stream into this dashboard.</p>
|
|
145
|
-
</div>
|
|
146
|
-
<ul>{renderedList}</ul>
|
|
147
|
-
<style>
|
|
148
|
-
{`
|
|
149
|
-
.perf-suite-results {
|
|
150
|
-
border: 1px solid var(--astro-color-border, rgba(120, 120, 120, 0.4));
|
|
151
|
-
border-radius: 0.75rem;
|
|
152
|
-
padding: 1rem;
|
|
153
|
-
margin-top: 1.5rem;
|
|
154
|
-
max-width: 720px;
|
|
155
|
-
}
|
|
156
|
-
.perf-suite-results__header {
|
|
157
|
-
display: flex;
|
|
158
|
-
flex-direction: column;
|
|
159
|
-
gap: 0.25rem;
|
|
160
|
-
margin-bottom: 0.5rem;
|
|
161
|
-
}
|
|
162
|
-
.perf-suite-results__header h3 {
|
|
163
|
-
margin: 0;
|
|
164
|
-
font-size: 1.1rem;
|
|
165
|
-
}
|
|
166
|
-
.perf-suite-results__header p {
|
|
167
|
-
margin: 0;
|
|
168
|
-
opacity: 0.8;
|
|
169
|
-
font-size: 0.9rem;
|
|
170
|
-
}
|
|
171
|
-
.perf-suite-results ul {
|
|
172
|
-
list-style: none;
|
|
173
|
-
padding: 0;
|
|
174
|
-
margin: 0;
|
|
175
|
-
display: flex;
|
|
176
|
-
flex-direction: column;
|
|
177
|
-
gap: 0.75rem;
|
|
178
|
-
}
|
|
179
|
-
.perf-suite-results__item {
|
|
180
|
-
background: rgba(120, 120, 120, 0.08);
|
|
181
|
-
border: 1px solid rgba(120, 120, 120, 0.3);
|
|
182
|
-
border-radius: 0.5rem;
|
|
183
|
-
padding: 0.75rem;
|
|
184
|
-
display: flex;
|
|
185
|
-
flex-direction: column;
|
|
186
|
-
gap: 0.35rem;
|
|
187
|
-
}
|
|
188
|
-
.perf-suite-results__item header {
|
|
189
|
-
display: flex;
|
|
190
|
-
justify-content: space-between;
|
|
191
|
-
font-size: 0.95rem;
|
|
192
|
-
}
|
|
193
|
-
.perf-suite-results__item header strong {
|
|
194
|
-
text-transform: capitalize;
|
|
195
|
-
}
|
|
196
|
-
.perf-suite-results__meta {
|
|
197
|
-
display: flex;
|
|
198
|
-
justify-content: space-between;
|
|
199
|
-
font-size: 0.8rem;
|
|
200
|
-
opacity: 0.8;
|
|
201
|
-
}
|
|
202
|
-
.perf-suite-results__block {
|
|
203
|
-
display: flex;
|
|
204
|
-
justify-content: space-between;
|
|
205
|
-
font-size: 0.85rem;
|
|
206
|
-
}
|
|
207
|
-
.perf-suite-results__block--subrenders {
|
|
208
|
-
opacity: 0.85;
|
|
209
|
-
}
|
|
210
|
-
.perf-suite-results__block dt {
|
|
211
|
-
margin: 0;
|
|
212
|
-
text-transform: capitalize;
|
|
213
|
-
}
|
|
214
|
-
.perf-suite-results__block dd {
|
|
215
|
-
margin: 0;
|
|
216
|
-
}
|
|
217
|
-
.perf-suite-results__empty {
|
|
218
|
-
font-style: italic;
|
|
219
|
-
opacity: 0.8;
|
|
220
|
-
}
|
|
221
|
-
`}
|
|
222
|
-
</style>
|
|
223
|
-
</div>);
|
|
224
|
-
};
|
|
225
|
-
exports.default = PerfSuiteClient;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ReactPerfDeep.d.ts","sourceRoot":"","sources":["../../../../../../../../src/test/frontend/astro-app/src/components/perf/react/ReactPerfDeep.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AA4D3D,QAAA,MAAM,aAAa,EAAE,KAAK,CAAC,EAwG1B,CAAC;AAEF,eAAe,aAAa,CAAC"}
|
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
const react_1 = __importStar(require("react"));
|
|
40
|
-
const useDeepSignal_1 = __importDefault(require("../../../../../../../hooks/react/useDeepSignal"));
|
|
41
|
-
const state_1 = require("../../../../../utils/state");
|
|
42
|
-
const renderMetrics_1 = require("../../../../../utils/renderMetrics");
|
|
43
|
-
const perfScenarios_1 = require("../../../../../utils/perfScenarios");
|
|
44
|
-
const alien_signals_1 = require("alien-signals");
|
|
45
|
-
const ObjectRow = ({ entry }) => {
|
|
46
|
-
const rowRenderCount = (0, react_1.useRef)(0);
|
|
47
|
-
rowRenderCount.current += 1;
|
|
48
|
-
(0, renderMetrics_1.recordObjectRender)("react", entry["@id"], rowRenderCount.current);
|
|
49
|
-
(0, useDeepSignal_1.default)(entry);
|
|
50
|
-
return (<div className="object-row" data-entry-id={entry["@id"]} data-render-count={rowRenderCount.current}>
|
|
51
|
-
<span className="object-id">{entry["@id"]}</span>
|
|
52
|
-
<input type="text" value={entry.label} data-role="label" onChange={(event) => (entry.label = event.target.value)}/>
|
|
53
|
-
<input type="number" value={entry.count} data-role="count-input" onChange={(event) => (entry.count = Number(event.target.value || 0))}/>
|
|
54
|
-
<span data-role="count">{entry.count}</span>
|
|
55
|
-
<button type="button" data-action="increment" onClick={() => {
|
|
56
|
-
entry.count += 1;
|
|
57
|
-
}}>
|
|
58
|
-
+1
|
|
59
|
-
</button>
|
|
60
|
-
</div>);
|
|
61
|
-
};
|
|
62
|
-
const ReactPerfDeep = () => {
|
|
63
|
-
const state = state_1.sharedState;
|
|
64
|
-
const [revision, bumpRevision] = (0, react_1.useState)(0);
|
|
65
|
-
(0, react_1.useEffect)(() => {
|
|
66
|
-
const stop = (0, alien_signals_1.effect)(() => {
|
|
67
|
-
const objectSet = state_1.sharedState.objectSet;
|
|
68
|
-
if (!objectSet)
|
|
69
|
-
return;
|
|
70
|
-
void objectSet.size;
|
|
71
|
-
bumpRevision((value) => value + 1);
|
|
72
|
-
});
|
|
73
|
-
return stop;
|
|
74
|
-
}, []);
|
|
75
|
-
const renderCount = (0, react_1.useRef)(0);
|
|
76
|
-
const [busy, setBusy] = (0, react_1.useState)(false);
|
|
77
|
-
renderCount.current += 1;
|
|
78
|
-
(0, react_1.useEffect)(() => {
|
|
79
|
-
const dispose = (0, perfScenarios_1.registerSharedStateAdapter)("react");
|
|
80
|
-
return () => dispose();
|
|
81
|
-
}, []);
|
|
82
|
-
(0, react_1.useEffect)(() => {
|
|
83
|
-
if (typeof window !== "undefined") {
|
|
84
|
-
window.__reactSharedIdentity = state === state_1.sharedState;
|
|
85
|
-
window.__reactSharedGlobal =
|
|
86
|
-
state === window.sharedState;
|
|
87
|
-
}
|
|
88
|
-
}, []);
|
|
89
|
-
(0, react_1.useEffect)(() => {
|
|
90
|
-
(0, renderMetrics_1.recordRender)("react", renderCount.current);
|
|
91
|
-
});
|
|
92
|
-
const handleAddEntry = () => {
|
|
93
|
-
const objectSet = state.objectSet;
|
|
94
|
-
if (!objectSet)
|
|
95
|
-
return;
|
|
96
|
-
const id = `react-deep-${Math.random().toString(36).slice(2, 8)}`;
|
|
97
|
-
objectSet.add({
|
|
98
|
-
"@id": id,
|
|
99
|
-
label: `react ${id}`,
|
|
100
|
-
count: 0,
|
|
101
|
-
});
|
|
102
|
-
};
|
|
103
|
-
const handleRemoveEntry = () => {
|
|
104
|
-
const objectSet = state.objectSet;
|
|
105
|
-
if (!objectSet)
|
|
106
|
-
return;
|
|
107
|
-
const last = Array.from(objectSet.values()).pop();
|
|
108
|
-
if (!last)
|
|
109
|
-
return;
|
|
110
|
-
objectSet.delete(last);
|
|
111
|
-
};
|
|
112
|
-
const handleRunScenario = async () => {
|
|
113
|
-
try {
|
|
114
|
-
setBusy(true);
|
|
115
|
-
await (0, perfScenarios_1.runScenarioImmediately)("react", "deep");
|
|
116
|
-
}
|
|
117
|
-
finally {
|
|
118
|
-
setBusy(false);
|
|
119
|
-
}
|
|
120
|
-
};
|
|
121
|
-
const entries = Array.from(state.objectSet?.values?.() ?? []);
|
|
122
|
-
const objectSetSize = state.objectSet?.size ?? entries.length;
|
|
123
|
-
return (<section className="perf-panel react" data-field="objectSet">
|
|
124
|
-
<h2 className="title">react (deepSignal)</h2>
|
|
125
|
-
<div className="render-meta" data-render-count={renderCount.current}>
|
|
126
|
-
Render #{renderCount.current}
|
|
127
|
-
</div>
|
|
128
|
-
<div className="field" data-field="objectSet">
|
|
129
|
-
<legend>objectSet entries</legend>
|
|
130
|
-
<div className="set-controls">
|
|
131
|
-
<span data-role="set-size">Size: {objectSetSize}</span>
|
|
132
|
-
<div>
|
|
133
|
-
<button type="button" onClick={handleAddEntry}>
|
|
134
|
-
Add entry
|
|
135
|
-
</button>
|
|
136
|
-
<button type="button" onClick={handleRemoveEntry}>
|
|
137
|
-
Remove entry
|
|
138
|
-
</button>
|
|
139
|
-
<button type="button" data-action="run-scenario" onClick={handleRunScenario} disabled={busy}>
|
|
140
|
-
{busy ? "Running…" : "Run perf scenario"}
|
|
141
|
-
</button>
|
|
142
|
-
</div>
|
|
143
|
-
</div>
|
|
144
|
-
<div className="object-set">
|
|
145
|
-
{entries.map((entry) => (<ObjectRow key={entry["@id"]} entry={entry}/>))}
|
|
146
|
-
</div>
|
|
147
|
-
</div>
|
|
148
|
-
</section>);
|
|
149
|
-
};
|
|
150
|
-
exports.default = ReactPerfDeep;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ReactPerfNative.d.ts","sourceRoot":"","sources":["../../../../../../../../src/test/frontend/astro-app/src/components/perf/react/ReactPerfNative.tsx"],"names":[],"mappings":"AAAA,OAAO,KAMN,MAAM,OAAO,CAAC;AA4Ef,QAAA,MAAM,eAAe,EAAE,KAAK,CAAC,EA8I5B,CAAC;AAEF,eAAe,eAAe,CAAC"}
|