@lynx-js/react 0.116.3 → 0.116.5

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.
Files changed (57) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/package.json +2 -2
  3. package/refresh/.turbo/turbo-build.log +1 -1
  4. package/runtime/lib/alog/elementPAPICall.js +1 -1
  5. package/runtime/lib/alog/elementPAPICall.js.map +1 -1
  6. package/runtime/lib/backgroundSnapshot.js +198 -95
  7. package/runtime/lib/backgroundSnapshot.js.map +1 -1
  8. package/runtime/lib/debug/profile.d.ts +4 -1
  9. package/runtime/lib/debug/profile.js +21 -126
  10. package/runtime/lib/debug/profile.js.map +1 -1
  11. package/runtime/lib/debug/profileHooks.d.ts +1 -0
  12. package/runtime/lib/debug/profileHooks.js +200 -0
  13. package/runtime/lib/debug/profileHooks.js.map +1 -0
  14. package/runtime/lib/debug/vnodeSource.d.ts +4 -0
  15. package/runtime/lib/debug/vnodeSource.js +61 -0
  16. package/runtime/lib/debug/vnodeSource.js.map +1 -0
  17. package/runtime/lib/hooks/react.d.ts +11 -10
  18. package/runtime/lib/hooks/react.js +101 -14
  19. package/runtime/lib/hooks/react.js.map +1 -1
  20. package/runtime/lib/hydrate.js +1 -1
  21. package/runtime/lib/hydrate.js.map +1 -1
  22. package/runtime/lib/lifecycle/destroy.js +1 -1
  23. package/runtime/lib/lifecycle/destroy.js.map +1 -1
  24. package/runtime/lib/lifecycle/event/jsReady.js +1 -1
  25. package/runtime/lib/lifecycle/event/jsReady.js.map +1 -1
  26. package/runtime/lib/lifecycle/patch/commit.js +1 -1
  27. package/runtime/lib/lifecycle/patch/commit.js.map +1 -1
  28. package/runtime/lib/lifecycle/reload.js +1 -1
  29. package/runtime/lib/lifecycle/reload.js.map +1 -1
  30. package/runtime/lib/lifecycle/render.js +1 -1
  31. package/runtime/lib/lifecycle/render.js.map +1 -1
  32. package/runtime/lib/list.js +4 -0
  33. package/runtime/lib/list.js.map +1 -1
  34. package/runtime/lib/listUpdateInfo.js +1 -1
  35. package/runtime/lib/listUpdateInfo.js.map +1 -1
  36. package/runtime/lib/lynx/env.js +1 -1
  37. package/runtime/lib/lynx/env.js.map +1 -1
  38. package/runtime/lib/lynx/tt.js +11 -5
  39. package/runtime/lib/lynx/tt.js.map +1 -1
  40. package/runtime/lib/lynx-api.js +1 -1
  41. package/runtime/lib/lynx-api.js.map +1 -1
  42. package/runtime/lib/lynx.js +7 -2
  43. package/runtime/lib/lynx.js.map +1 -1
  44. package/runtime/lib/renderToOpcodes/constants.d.ts +4 -0
  45. package/runtime/lib/renderToOpcodes/constants.js +5 -0
  46. package/runtime/lib/renderToOpcodes/constants.js.map +1 -1
  47. package/runtime/lib/snapshot/list.js +14 -2
  48. package/runtime/lib/snapshot/list.js.map +1 -1
  49. package/runtime/lib/snapshot.js +10 -0
  50. package/runtime/lib/snapshot.js.map +1 -1
  51. package/testing-library/dist/pure.js +1 -2
  52. package/testing-library/dist/rslib-runtime.js +0 -10
  53. package/transform/dist/wasm.cjs +1 -1
  54. package/worklet-runtime/dist/main.js +1 -1
  55. package/runtime/lib/debug/utils.d.ts +0 -2
  56. package/runtime/lib/debug/utils.js +0 -20
  57. package/runtime/lib/debug/utils.js.map +0 -1
@@ -1,134 +1,29 @@
1
1
  // Copyright 2024 The Lynx Authors. All rights reserved.
2
2
  // Licensed under the Apache License Version 2.0 that can be found in the
3
3
  // LICENSE file in the root directory of this source tree.
4
- import { Component, options } from 'preact';
5
- import { globalPatchOptions } from '../lifecycle/patch/commit.js';
6
- import { __globalSnapshotPatch } from '../lifecycle/patch/snapshotPatch.js';
7
- import { COMMIT, COMPONENT, DIFF, DIFF2, DIFFED, DIRTY, NEXT_STATE, RENDER } from '../renderToOpcodes/constants.js';
8
- import { getDisplayName, hook } from '../utils.js';
9
- export function initProfileHook() {
10
- // early-exit if required profiling APIs are unavailable
4
+ /* eslint-disable @typescript-eslint/no-unnecessary-type-assertion */
5
+ export const isProfiling = /* @__PURE__ */ Boolean(lynx.performance?.isProfileRecording?.());
6
+ const noop = () => { };
7
+ const noopFlowId = () => 0;
8
+ export const profileStart = /* @__PURE__ */ ((() => {
11
9
  let p;
12
- /* v8 ignore start */
13
- if (!(p = lynx.performance)
14
- || typeof p.profileStart !== 'function'
15
- || typeof p.profileEnd !== 'function'
16
- || typeof p.profileMark !== 'function'
17
- || typeof p.profileFlowId !== 'function') {
18
- return;
10
+ if (!(p = lynx.performance) || typeof p.profileStart !== 'function') {
11
+ return noop;
19
12
  }
20
- /* v8 ignore stop */
21
- const profileStart = p.profileStart.bind(p);
22
- const profileEnd = p.profileEnd.bind(p);
23
- const profileMark = p.profileMark.bind(p);
24
- const profileFlowId = p.profileFlowId.bind(p);
25
- // for each setState call, we will add a profiling trace and
26
- // attach a flowId to the component instance.
27
- // This allows us to trace the flow of its diffing, committing and patching.
28
- {
29
- const sFlowID = Symbol('FLOW_ID');
30
- if (typeof __BACKGROUND__ !== 'undefined' && __BACKGROUND__) {
31
- function buildSetStateProfileMarkArgs(currentState, nextState) {
32
- const EMPTY_OBJ = {};
33
- currentState ??= EMPTY_OBJ;
34
- nextState ??= EMPTY_OBJ;
35
- return {
36
- 'current state keys': JSON.stringify(Object.keys(currentState)),
37
- 'next state keys': JSON.stringify(Object.keys(nextState)),
38
- 'changed (shallow diff) state keys': JSON.stringify(
39
- // the setState is in assign manner, we assume nextState is a superset of currentState
40
- Object.keys(nextState).filter(key => currentState[key] !== nextState[key])),
41
- };
42
- }
43
- hook(Component.prototype, 'setState', function (old, state, callback) {
44
- old?.call(this, state, callback);
45
- if (this[DIRTY]) {
46
- profileMark('ReactLynx::setState', {
47
- flowId: this[sFlowID] ??= profileFlowId(),
48
- args: buildSetStateProfileMarkArgs(this.state, this[NEXT_STATE]),
49
- });
50
- }
51
- });
52
- }
53
- hook(options, DIFF2, (old, vnode, oldVNode) => {
54
- // We only add profiling trace for Component
55
- if (typeof vnode.type === 'function') {
56
- const profileOptions = {};
57
- if (typeof __BACKGROUND__ !== 'undefined' && __BACKGROUND__) {
58
- const c = oldVNode[COMPONENT];
59
- if (c) {
60
- const flowId = c[sFlowID];
61
- delete c[sFlowID];
62
- if (flowId) {
63
- globalPatchOptions.flowIds ??= [];
64
- globalPatchOptions.flowIds.push(flowId);
65
- profileOptions.flowId = flowId;
66
- }
67
- }
68
- }
69
- profileStart(`ReactLynx::diff::${ /* #__INLINE__ */getDisplayName(vnode.type)}`, profileOptions);
70
- }
71
- old?.(vnode, oldVNode);
72
- });
73
- hook(options, DIFFED, (old, vnode) => {
74
- if (typeof vnode.type === 'function') {
75
- profileEnd(); // for options[DIFF]
76
- }
77
- old?.(vnode);
78
- });
79
- if (typeof __BACKGROUND__ !== 'undefined' && __BACKGROUND__) {
80
- hook(options, COMMIT, (old, vnode, commitQueue) => {
81
- profileStart('ReactLynx::commit', {
82
- ...globalPatchOptions.flowIds
83
- ? {
84
- flowId: globalPatchOptions.flowIds[0],
85
- flowIds: globalPatchOptions.flowIds,
86
- }
87
- : {},
88
- });
89
- old?.(vnode, commitQueue);
90
- profileEnd();
91
- });
92
- }
13
+ return p.profileStart.bind(p);
14
+ })());
15
+ export const profileEnd = /* @__PURE__ */ ((() => {
16
+ let p;
17
+ if (!(p = lynx.performance) || typeof p.profileEnd !== 'function') {
18
+ return noop;
93
19
  }
94
- // Profile the user-provided `render`.
95
- hook(options, RENDER, (old, vnode) => {
96
- // eslint-disable-next-line @typescript-eslint/unbound-method
97
- const originalRender = vnode[COMPONENT].render;
98
- vnode[COMPONENT].render = function render(props, state, context) {
99
- profileStart(`ReactLynx::render::${ /* #__INLINE__ */getDisplayName(vnode.type)}`);
100
- try {
101
- return originalRender.call(this, props, state, context);
102
- }
103
- finally {
104
- profileEnd();
105
- vnode[COMPONENT].render = originalRender;
106
- }
107
- };
108
- old?.(vnode);
109
- });
110
- if (typeof __BACKGROUND__ !== 'undefined' && __BACKGROUND__) {
111
- const sPatchLength = Symbol('PATCH_LENGTH');
112
- hook(options, DIFF, (old, vnode) => {
113
- if (typeof vnode.type === 'function' && __globalSnapshotPatch) {
114
- vnode[sPatchLength] = __globalSnapshotPatch.length;
115
- }
116
- old?.(vnode);
117
- });
118
- hook(options, DIFFED, (old, vnode) => {
119
- if (typeof vnode.type === 'function' && __globalSnapshotPatch) {
120
- if (vnode[sPatchLength] === __globalSnapshotPatch.length) {
121
- // "NoPatch" is a conventional name in Lynx
122
- profileMark('ReactLynx::diffFinishNoPatch', {
123
- args: {
124
- componentName: /* #__INLINE__ */ getDisplayName(vnode.type),
125
- },
126
- });
127
- }
128
- delete vnode[sPatchLength];
129
- }
130
- old?.(vnode);
131
- });
20
+ return p.profileEnd.bind(p);
21
+ })());
22
+ export const profileFlowId = /* @__PURE__ */ ((() => {
23
+ let p;
24
+ if (!(p = lynx.performance) || typeof p.profileFlowId !== 'function') {
25
+ return noopFlowId;
132
26
  }
133
- }
27
+ return p.profileFlowId.bind(p);
28
+ })());
134
29
  //# sourceMappingURL=profile.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"profile.js","sourceRoot":"","sources":["../../src/debug/profile.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"profile.js","sourceRoot":"","sources":["../../src/debug/profile.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,yEAAyE;AACzE,0DAA0D;AAE1D,qEAAqE;AAErE,MAAM,CAAC,MAAM,WAAW,GAAY,eAAe,CAAC,OAAO,CACzD,IAAI,CAAC,WAAW,EAAE,kBAAkB,EAAE,EAAE,CACzC,CAAC;AAEF,MAAM,IAAI,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC;AACtB,MAAM,UAAU,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC;AAE3B,MAAM,CAAC,MAAM,YAAY,GAAG,eAAe,CAAC,CAAC,CAAC,GAAG,EAAE;IACjD,IAAI,CAAC,CAAC;IACN,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,OAAO,CAAC,CAAC,YAAY,KAAK,UAAU,EAAE,CAAC;QACpE,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAChC,CAAC,CAAC,EAAE,CAAyC,CAAC;AAE9C,MAAM,CAAC,MAAM,UAAU,GAAG,eAAe,CAAC,CAAC,CAAC,GAAG,EAAE;IAC/C,IAAI,CAAC,CAAC;IACN,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,OAAO,CAAC,CAAC,UAAU,KAAK,UAAU,EAAE,CAAC;QAClE,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC9B,CAAC,CAAC,EAAE,CAAuC,CAAC;AAE5C,MAAM,CAAC,MAAM,aAAa,GAAG,eAAe,CAAC,CAAC,CAAC,GAAG,EAAE;IAClD,IAAI,CAAC,CAAC;IACN,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,OAAO,CAAC,CAAC,aAAa,KAAK,UAAU,EAAE,CAAC;QACrE,OAAO,UAAU,CAAC;IACpB,CAAC;IACD,OAAO,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACjC,CAAC,CAAC,EAAE,CAA0C,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function initProfileHook(): void;
@@ -0,0 +1,200 @@
1
+ // Copyright 2024 The Lynx Authors. All rights reserved.
2
+ // Licensed under the Apache License Version 2.0 that can be found in the
3
+ // LICENSE file in the root directory of this source tree.
4
+ import { Component, options } from 'preact';
5
+ import { globalPatchOptions } from '../lifecycle/patch/commit.js';
6
+ import { __globalSnapshotPatch } from '../lifecycle/patch/snapshotPatch.js';
7
+ import { COMMIT, COMPONENT, DIFF, DIFF2, DIFFED, DIRTY, HOOKS, LIST, NEXT_STATE, NEXT_VALUE, RENDER, VALUE, VNODE, } from '../renderToOpcodes/constants.js';
8
+ import { getDisplayName, hook } from '../utils.js';
9
+ const format = (val) => {
10
+ if (typeof val === 'function') {
11
+ return val.toString();
12
+ }
13
+ return val;
14
+ };
15
+ function safeJsonStringify(val) {
16
+ const seen = new WeakSet();
17
+ return JSON.stringify(val, function (_key, value) {
18
+ if (typeof value === 'object' && value !== null) {
19
+ if (seen.has(value)) {
20
+ return '[Unserializable: Circular]';
21
+ }
22
+ seen.add(value);
23
+ }
24
+ return value;
25
+ });
26
+ }
27
+ function buildSetStateProfileMarkArgs(type, currentState, nextState) {
28
+ const EMPTY_OBJ = {};
29
+ const currentStateObj = (currentState ?? EMPTY_OBJ);
30
+ const nextStateObj = (nextState ?? EMPTY_OBJ);
31
+ return {
32
+ componentName: (type && typeof type === 'function')
33
+ ? getDisplayName(type)
34
+ : 'Unknown',
35
+ 'current state keys': JSON.stringify(Object.keys(currentStateObj)),
36
+ 'next state keys': JSON.stringify(Object.keys(nextStateObj)),
37
+ 'changed (shallow diff) state keys': JSON.stringify(
38
+ // the setState is in assign manner, we assume nextState is a superset of currentState
39
+ Object.keys(nextStateObj).filter(key => currentStateObj[key] !== nextStateObj[key])),
40
+ currentValue: safeJsonStringify(format(currentState)),
41
+ nextValue: safeJsonStringify(format(nextState)),
42
+ };
43
+ }
44
+ export function initProfileHook() {
45
+ // early-exit if required profiling APIs are unavailable
46
+ let p;
47
+ /* v8 ignore start */
48
+ if (!(p = lynx.performance)
49
+ || typeof p.profileStart !== 'function'
50
+ || typeof p.profileEnd !== 'function'
51
+ || typeof p.profileMark !== 'function'
52
+ || typeof p.profileFlowId !== 'function') {
53
+ return;
54
+ }
55
+ /* v8 ignore stop */
56
+ const profileStart = p.profileStart.bind(p);
57
+ const profileEnd = p.profileEnd.bind(p);
58
+ const profileMark = p.profileMark.bind(p);
59
+ const profileFlowId = p.profileFlowId.bind(p);
60
+ // for each setState call, we will add a profiling trace and
61
+ // attach a flowId to the component instance.
62
+ // This allows us to trace the flow of its diffing, committing and patching.
63
+ {
64
+ const sFlowID = Symbol('FLOW_ID');
65
+ if (typeof __BACKGROUND__ !== 'undefined' && __BACKGROUND__) {
66
+ hook(Component.prototype, 'setState', function (old, state, callback) {
67
+ old?.call(this, state, callback);
68
+ if (this[DIRTY]) {
69
+ const type = this[VNODE].type;
70
+ const isClassComponent = typeof type === 'function' && ('prototype' in type)
71
+ && ('render' in type.prototype);
72
+ if (isClassComponent) {
73
+ profileMark('ReactLynx::setState', {
74
+ flowId: this[sFlowID] ??= profileFlowId(),
75
+ args: buildSetStateProfileMarkArgs(type, this.state, this[NEXT_STATE]),
76
+ });
77
+ }
78
+ }
79
+ });
80
+ }
81
+ hook(options, DIFF2, (old, vnode, oldVNode) => {
82
+ // We only add profiling trace for Component
83
+ if (typeof vnode.type === 'function') {
84
+ const profileOptions = {};
85
+ if (typeof __BACKGROUND__ !== 'undefined' && __BACKGROUND__) {
86
+ const c = oldVNode[COMPONENT];
87
+ if (c) {
88
+ const flowId = c[sFlowID];
89
+ delete c[sFlowID];
90
+ if (flowId) {
91
+ globalPatchOptions.flowIds ??= [];
92
+ globalPatchOptions.flowIds.push(flowId);
93
+ profileOptions.flowId = flowId;
94
+ }
95
+ }
96
+ }
97
+ profileStart(`ReactLynx::diff::${ /* #__INLINE__ */getDisplayName(vnode.type)}`, profileOptions);
98
+ }
99
+ old?.(vnode, oldVNode);
100
+ });
101
+ hook(options, DIFFED, (old, vnode) => {
102
+ if (typeof __BACKGROUND__ !== 'undefined' && __BACKGROUND__) {
103
+ const hooks = vnode[COMPONENT]?.[HOOKS];
104
+ const hookList = hooks?.[LIST];
105
+ if (Array.isArray(hookList)) {
106
+ hookList.forEach((hookState, hookIdx) => {
107
+ hookState['internalNextValue'] = hookState[NEXT_VALUE];
108
+ // define a setter for __N to track the next value of the hook
109
+ Object.defineProperty(hookState, NEXT_VALUE, {
110
+ get: () => hookState['internalNextValue'],
111
+ set: (value) => {
112
+ if (Array.isArray(value)) {
113
+ // hookState[VALUE] is [state, dispatch]
114
+ const currentValueTuple = hookState[VALUE];
115
+ const currentValue = currentValueTuple[0];
116
+ const [nextValue] = value;
117
+ const component = hookState[COMPONENT];
118
+ if (!component) {
119
+ hookState['internalNextValue'] = value;
120
+ return;
121
+ }
122
+ const type = component[VNODE].type;
123
+ const flowId = component[sFlowID] ??= profileFlowId();
124
+ profileMark('ReactLynx::hooks::setState', {
125
+ flowId,
126
+ args: {
127
+ hookIdx: String(hookIdx),
128
+ ...buildSetStateProfileMarkArgs(type, currentValue, nextValue),
129
+ },
130
+ });
131
+ }
132
+ hookState['internalNextValue'] = value;
133
+ },
134
+ configurable: true,
135
+ });
136
+ });
137
+ }
138
+ }
139
+ if (typeof vnode.type === 'function') {
140
+ profileEnd(); // for options[DIFF2]
141
+ }
142
+ old?.(vnode);
143
+ });
144
+ if (typeof __BACKGROUND__ !== 'undefined' && __BACKGROUND__) {
145
+ hook(options, COMMIT, (old, vnode, commitQueue) => {
146
+ profileStart('ReactLynx::commit', {
147
+ ...globalPatchOptions.flowIds
148
+ ? {
149
+ flowId: globalPatchOptions.flowIds[0],
150
+ flowIds: globalPatchOptions.flowIds,
151
+ }
152
+ : {},
153
+ });
154
+ old?.(vnode, commitQueue);
155
+ profileEnd();
156
+ });
157
+ }
158
+ }
159
+ // Profile the user-provided `render`.
160
+ hook(options, RENDER, (old, vnode) => {
161
+ // eslint-disable-next-line @typescript-eslint/unbound-method
162
+ const originalRender = vnode[COMPONENT].render;
163
+ vnode[COMPONENT].render = function render(props, state, context) {
164
+ profileStart(`ReactLynx::render::${ /* #__INLINE__ */getDisplayName(vnode.type)}`);
165
+ try {
166
+ return originalRender.call(this, props, state, context);
167
+ }
168
+ finally {
169
+ profileEnd();
170
+ vnode[COMPONENT].render = originalRender;
171
+ }
172
+ };
173
+ old?.(vnode);
174
+ });
175
+ if (typeof __BACKGROUND__ !== 'undefined' && __BACKGROUND__) {
176
+ const sPatchLength = Symbol('PATCH_LENGTH');
177
+ hook(options, DIFF, (old, vnode) => {
178
+ if (typeof vnode.type === 'function' && __globalSnapshotPatch) {
179
+ vnode[sPatchLength] = __globalSnapshotPatch.length;
180
+ }
181
+ old?.(vnode);
182
+ });
183
+ hook(options, DIFFED, (old, vnode) => {
184
+ if (typeof vnode.type === 'function') {
185
+ const patchLength = vnode[sPatchLength];
186
+ delete vnode[sPatchLength];
187
+ if (__globalSnapshotPatch && patchLength === __globalSnapshotPatch.length) {
188
+ // "NoPatch" is a conventional name in Lynx
189
+ profileMark('ReactLynx::diffFinishNoPatch', {
190
+ args: {
191
+ componentName: /* #__INLINE__ */ getDisplayName(vnode.type),
192
+ },
193
+ });
194
+ }
195
+ }
196
+ old?.(vnode);
197
+ });
198
+ }
199
+ }
200
+ //# sourceMappingURL=profileHooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profileHooks.js","sourceRoot":"","sources":["../../src/debug/profileHooks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare function setupVNodeSourceHook(): void;
2
+ export declare function moveSnapshotVNodeSource(oldId: number, newId: number): void;
3
+ export declare function getSnapshotVNodeSource(id: number): string | undefined;
4
+ export declare function clearSnapshotVNodeSource(): void;
@@ -0,0 +1,61 @@
1
+ // Copyright 2024 The Lynx Authors. All rights reserved.
2
+ // Licensed under the Apache License Version 2.0 that can be found in the
3
+ // LICENSE file in the root directory of this source tree.
4
+ import { options } from 'preact';
5
+ import { DIFFED, DOM } from '../renderToOpcodes/constants.js';
6
+ const snapshotVNodeSourceMap = new Map();
7
+ let hookInstalled = false;
8
+ function formatSource(source) {
9
+ if (!source.fileName) {
10
+ return undefined;
11
+ }
12
+ if (typeof source.lineNumber === 'number' && typeof source.columnNumber === 'number') {
13
+ return `${source.fileName}:${source.lineNumber}:${source.columnNumber}`;
14
+ }
15
+ if (typeof source.lineNumber === 'number') {
16
+ return `${source.fileName}:${source.lineNumber}`;
17
+ }
18
+ return source.fileName;
19
+ }
20
+ function captureVNodeSource(vnode) {
21
+ if (typeof vnode.type !== 'string') {
22
+ return;
23
+ }
24
+ const source = vnode.__source;
25
+ const id = vnode[DOM]?.__id;
26
+ if (!source || typeof id !== 'number') {
27
+ return;
28
+ }
29
+ const formattedSource = formatSource(source);
30
+ if (formattedSource) {
31
+ snapshotVNodeSourceMap.set(id, formattedSource);
32
+ }
33
+ }
34
+ export function setupVNodeSourceHook() {
35
+ if (hookInstalled) {
36
+ return;
37
+ }
38
+ hookInstalled = true;
39
+ const oldDiffed = options[DIFFED];
40
+ options[DIFFED] = (vnode) => {
41
+ captureVNodeSource(vnode);
42
+ oldDiffed?.(vnode);
43
+ };
44
+ }
45
+ export function moveSnapshotVNodeSource(oldId, newId) {
46
+ if (oldId === newId) {
47
+ return;
48
+ }
49
+ const source = snapshotVNodeSourceMap.get(oldId);
50
+ if (source) {
51
+ snapshotVNodeSourceMap.set(newId, source);
52
+ snapshotVNodeSourceMap.delete(oldId);
53
+ }
54
+ }
55
+ export function getSnapshotVNodeSource(id) {
56
+ return snapshotVNodeSourceMap.get(id);
57
+ }
58
+ export function clearSnapshotVNodeSource() {
59
+ snapshotVNodeSourceMap.clear();
60
+ }
61
+ //# sourceMappingURL=vnodeSource.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vnodeSource.js","sourceRoot":"","sources":["../../src/debug/vnodeSource.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,yEAAyE;AACzE,0DAA0D;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAGjC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,iCAAiC,CAAC;AAa9D,MAAM,sBAAsB,GAAwB,IAAI,GAAG,EAAE,CAAC;AAE9D,IAAI,aAAa,GAAG,KAAK,CAAC;AAE1B,SAAS,YAAY,CAAC,MAAkB;IACtC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACrB,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ,IAAI,OAAO,MAAM,CAAC,YAAY,KAAK,QAAQ,EAAE,CAAC;QACrF,OAAO,GAAG,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;IAC1E,CAAC;IACD,IAAI,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;QAC1C,OAAO,GAAG,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;IACnD,CAAC;IACD,OAAO,MAAM,CAAC,QAAQ,CAAC;AACzB,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAmB;IAC7C,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACnC,OAAO;IACT,CAAC;IACD,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC;IAC9B,MAAM,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC;IAC5B,IAAI,CAAC,MAAM,IAAI,OAAO,EAAE,KAAK,QAAQ,EAAE,CAAC;QACtC,OAAO;IACT,CAAC;IACD,MAAM,eAAe,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IAC7C,IAAI,eAAe,EAAE,CAAC;QACpB,sBAAsB,CAAC,GAAG,CAAC,EAAE,EAAE,eAAe,CAAC,CAAC;IAClD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,oBAAoB;IAClC,IAAI,aAAa,EAAE,CAAC;QAClB,OAAO;IACT,CAAC;IACD,aAAa,GAAG,IAAI,CAAC;IACrB,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAClC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE;QAC1B,kBAAkB,CAAC,KAAqB,CAAC,CAAC;QAC1C,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,KAAa,EAAE,KAAa;IAClE,IAAI,KAAK,KAAK,KAAK,EAAE,CAAC;QACpB,OAAO;IACT,CAAC;IACD,MAAM,MAAM,GAAG,sBAAsB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACjD,IAAI,MAAM,EAAE,CAAC;QACX,sBAAsB,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAC1C,sBAAsB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,EAAU;IAC/C,OAAO,sBAAsB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,wBAAwB;IACtC,sBAAsB,CAAC,KAAK,EAAE,CAAC;AACjC,CAAC"}
@@ -1,26 +1,27 @@
1
- import { useCallback, useContext, useDebugValue, useErrorBoundary, useId, useImperativeHandle, useMemo, useReducer, useRef, useState } from 'preact/hooks';
1
+ import { useCallback, useContext, useDebugValue, useErrorBoundary, useId, useImperativeHandle, useMemo, useState as usePreactState, useReducer, useRef } from 'preact/hooks';
2
2
  import type { DependencyList, EffectCallback } from 'react';
3
+ declare const useState: typeof usePreactState;
3
4
  /**
4
- * `useLayoutEffect` is now an alias of `useEffect`. Use `useEffect` instead.
5
- *
6
- * Accepts a function that contains imperative, possibly effectful code. The effects run after main thread dom update without blocking it.
5
+ * Accepts a function that contains imperative, possibly effectful code.
6
+ * The effects run after main thread dom update without blocking it.
7
7
  *
8
8
  * @param effect - Imperative function that can return a cleanup function
9
9
  * @param deps - If present, effect will only activate if the values in the list change (using ===).
10
10
  *
11
11
  * @public
12
- *
13
- * @deprecated `useLayoutEffect` in the background thread cannot offer the precise timing for reading layout information and synchronously re-render, which is different from React.
14
12
  */
15
- declare function useLayoutEffect(effect: EffectCallback, deps?: DependencyList): void;
13
+ declare const useEffect: (effect: EffectCallback, deps?: DependencyList) => void;
16
14
  /**
17
- * Accepts a function that contains imperative, possibly effectful code.
18
- * The effects run after main thread dom update without blocking it.
15
+ * `useLayoutEffect` is now an alias of `useEffect`. Use `useEffect` instead.
16
+ *
17
+ * Accepts a function that contains imperative, possibly effectful code. The effects run after main thread dom update without blocking it.
19
18
  *
20
19
  * @param effect - Imperative function that can return a cleanup function
21
20
  * @param deps - If present, effect will only activate if the values in the list change (using ===).
22
21
  *
23
22
  * @public
23
+ *
24
+ * @deprecated `useLayoutEffect` in the background thread cannot offer the precise timing for reading layout information and synchronously re-render, which is different from React.
24
25
  */
25
- declare function useEffect(effect: EffectCallback, deps?: DependencyList): void;
26
+ declare const useLayoutEffect: (effect: EffectCallback, deps?: DependencyList) => void;
26
27
  export { useState, useReducer, useRef, useImperativeHandle, useLayoutEffect, useEffect, useCallback, useMemo, useContext, useDebugValue, useErrorBoundary, useId, };
@@ -1,34 +1,121 @@
1
1
  // Copyright 2024 The Lynx Authors. All rights reserved.
2
2
  // Licensed under the Apache License Version 2.0 that can be found in the
3
3
  // LICENSE file in the root directory of this source tree.
4
- import { useCallback, useContext, useDebugValue, useErrorBoundary, useId, useImperativeHandle, useMemo, useEffect as usePreactEffect, useReducer, useRef, useState, } from 'preact/hooks';
4
+ import { useCallback, useContext, useDebugValue, useErrorBoundary, useId, useImperativeHandle, useMemo, useEffect as usePreactEffect, useState as usePreactState, useReducer, useRef, } from 'preact/hooks';
5
+ import { isProfiling, profileEnd, profileFlowId, profileStart } from '../debug/profile.js';
6
+ // Cache profiled wrappers by the original preact setter to preserve stable
7
+ // identity without introducing extra hooks in component render flow.
8
+ const stateSetterTraceCache = /* @__PURE__ */ isProfiling
9
+ ? new WeakMap()
10
+ : undefined;
11
+ function buildTraceOption(flowId, stack) {
12
+ if (!stack) {
13
+ return { flowId };
14
+ }
15
+ return {
16
+ flowId,
17
+ args: {
18
+ stack,
19
+ },
20
+ };
21
+ }
22
+ function withEffectProfile(effect, traceName, flowId, stack) {
23
+ const traceOption = buildTraceOption(flowId, stack);
24
+ return () => {
25
+ profileStart(traceName, traceOption);
26
+ try {
27
+ const cleanup = effect();
28
+ if (typeof cleanup !== 'function') {
29
+ return cleanup;
30
+ }
31
+ return () => {
32
+ profileStart(`${traceName}::cleanup`, traceOption);
33
+ try {
34
+ cleanup();
35
+ }
36
+ finally {
37
+ profileEnd();
38
+ }
39
+ };
40
+ }
41
+ finally {
42
+ profileEnd();
43
+ }
44
+ };
45
+ }
46
+ function useEffectWithProfile(effect, deps, traceName) {
47
+ const flowId = profileFlowId();
48
+ const stack = new Error().stack;
49
+ const traceOption = buildTraceOption(flowId, stack);
50
+ profileStart(traceName, traceOption);
51
+ try {
52
+ return usePreactEffect(withEffectProfile(effect, `${traceName}::callback`, flowId, stack), deps);
53
+ }
54
+ finally {
55
+ profileEnd();
56
+ }
57
+ }
58
+ function useLayoutEffectProfiled(effect, deps) {
59
+ return useEffectWithProfile(effect, deps, 'ReactLynx::hooks::useLayoutEffect');
60
+ }
61
+ function useEffectProfiled(effect, deps) {
62
+ return useEffectWithProfile(effect, deps, 'ReactLynx::hooks::useEffect');
63
+ }
64
+ function useStateWithProfile(initialState) {
65
+ const [state, setState] = (arguments.length === 0
66
+ ? usePreactState()
67
+ : usePreactState(initialState));
68
+ const genericSetState = setState;
69
+ const cachedTracedSetState = stateSetterTraceCache?.get(genericSetState);
70
+ if (cachedTracedSetState) {
71
+ return [state, cachedTracedSetState];
72
+ }
73
+ const tracedSetState = ((nextState) => {
74
+ const stack = new Error().stack;
75
+ const traceOption = stack
76
+ ? { args: { stack } }
77
+ : undefined;
78
+ profileStart('ReactLynx::hooks::useState::setter', traceOption);
79
+ try {
80
+ return setState(nextState);
81
+ }
82
+ finally {
83
+ profileEnd();
84
+ }
85
+ });
86
+ stateSetterTraceCache?.set(genericSetState, tracedSetState);
87
+ return [state, tracedSetState];
88
+ }
89
+ const useState = isProfiling
90
+ ? useStateWithProfile
91
+ : usePreactState;
5
92
  /**
6
- * `useLayoutEffect` is now an alias of `useEffect`. Use `useEffect` instead.
7
- *
8
- * Accepts a function that contains imperative, possibly effectful code. The effects run after main thread dom update without blocking it.
93
+ * Accepts a function that contains imperative, possibly effectful code.
94
+ * The effects run after main thread dom update without blocking it.
9
95
  *
10
96
  * @param effect - Imperative function that can return a cleanup function
11
97
  * @param deps - If present, effect will only activate if the values in the list change (using ===).
12
98
  *
13
99
  * @public
14
- *
15
- * @deprecated `useLayoutEffect` in the background thread cannot offer the precise timing for reading layout information and synchronously re-render, which is different from React.
16
100
  */
17
- function useLayoutEffect(effect, deps) {
18
- return usePreactEffect(effect, deps);
19
- }
101
+ const useEffect = isProfiling
102
+ ? useEffectProfiled
103
+ : usePreactEffect;
20
104
  /**
21
- * Accepts a function that contains imperative, possibly effectful code.
22
- * The effects run after main thread dom update without blocking it.
105
+ * `useLayoutEffect` is now an alias of `useEffect`. Use `useEffect` instead.
106
+ *
107
+ * Accepts a function that contains imperative, possibly effectful code. The effects run after main thread dom update without blocking it.
23
108
  *
24
109
  * @param effect - Imperative function that can return a cleanup function
25
110
  * @param deps - If present, effect will only activate if the values in the list change (using ===).
26
111
  *
27
112
  * @public
113
+ *
114
+ * @deprecated `useLayoutEffect` in the background thread cannot offer the precise timing for reading layout information and synchronously re-render, which is different from React.
28
115
  */
29
- function useEffect(effect, deps) {
30
- return usePreactEffect(effect, deps);
31
- }
116
+ const useLayoutEffect = isProfiling
117
+ ? useLayoutEffectProfiled
118
+ : usePreactEffect;
32
119
  export {
33
120
  // preact
34
121
  useState, useReducer, useRef, useImperativeHandle, useLayoutEffect, useEffect, useCallback, useMemo, useContext, useDebugValue, useErrorBoundary, useId, };