@lynx-js/web-core 0.9.0 → 0.10.0

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 (39) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/README.md +18 -2
  3. package/dist/apis/LynxView.d.ts +9 -15
  4. package/dist/apis/LynxView.js +16 -98
  5. package/dist/apis/createLynxView.d.ts +1 -1
  6. package/dist/apis/createLynxView.js +2 -2
  7. package/dist/apis/inShadowRootStyles.d.ts +1 -1
  8. package/dist/apis/inShadowRootStyles.js +9 -6
  9. package/dist/index.d.ts +0 -1
  10. package/dist/index.js +0 -1
  11. package/dist/uiThread/bootWorkers.js +8 -8
  12. package/dist/uiThread/crossThreadHandlers/queryNodes.d.ts +1 -1
  13. package/dist/uiThread/crossThreadHandlers/queryNodes.js +4 -4
  14. package/dist/uiThread/crossThreadHandlers/registerDispatchLynxViewEventHandler.d.ts +2 -0
  15. package/dist/uiThread/crossThreadHandlers/registerDispatchLynxViewEventHandler.js +15 -0
  16. package/dist/uiThread/crossThreadHandlers/registerFlushElementTreeHandler.d.ts +3 -12
  17. package/dist/uiThread/crossThreadHandlers/registerFlushElementTreeHandler.js +15 -88
  18. package/dist/uiThread/crossThreadHandlers/registerInvokeUIMethodHandler.d.ts +1 -1
  19. package/dist/uiThread/crossThreadHandlers/registerInvokeUIMethodHandler.js +6 -5
  20. package/dist/uiThread/crossThreadHandlers/registerSelectComponentHandler.d.ts +1 -1
  21. package/dist/uiThread/crossThreadHandlers/registerSelectComponentHandler.js +2 -2
  22. package/dist/uiThread/crossThreadHandlers/registerSetNativePropsHandler.d.ts +1 -1
  23. package/dist/uiThread/crossThreadHandlers/registerSetNativePropsHandler.js +2 -2
  24. package/dist/uiThread/crossThreadHandlers/registerTriggerComponentEventHandler.d.ts +1 -1
  25. package/dist/uiThread/crossThreadHandlers/registerTriggerComponentEventHandler.js +2 -2
  26. package/dist/uiThread/startUIThread.d.ts +1 -1
  27. package/dist/uiThread/startUIThread.js +19 -19
  28. package/index.css +2 -39
  29. package/package.json +6 -5
  30. package/dist/types/RuntimePropertyOnElement.d.ts +0 -17
  31. package/dist/types/RuntimePropertyOnElement.js +0 -2
  32. package/dist/uiThread/crossThreadHandlers/bootTimingSystem.d.ts +0 -5
  33. package/dist/uiThread/crossThreadHandlers/bootTimingSystem.js +0 -51
  34. package/dist/uiThread/crossThreadHandlers/createExposureService.d.ts +0 -2
  35. package/dist/uiThread/crossThreadHandlers/createExposureService.js +0 -55
  36. package/dist/uiThread/decodeElementOperation.d.ts +0 -12
  37. package/dist/uiThread/decodeElementOperation.js +0 -175
  38. package/dist/utils/createCrossThreadEvent.d.ts +0 -2
  39. package/dist/utils/createCrossThreadEvent.js +0 -43
package/CHANGELOG.md CHANGED
@@ -1,5 +1,58 @@
1
1
  # @lynx-js/web-core
2
2
 
3
+ ## 0.10.0
4
+
5
+ ### Minor Changes
6
+
7
+ - feat: rewrite the main thread Element PAPIs ([#343](https://github.com/lynx-family/lynx-stack/pull/343))
8
+
9
+ In this commit we've rewritten the main thread apis.
10
+
11
+ The most highlighted change is that
12
+
13
+ - Before this commit we send events directly to bts
14
+ - After this change, we send events to mts then send them to bts with some data combined.
15
+
16
+ ### Patch Changes
17
+
18
+ - refactor: timing system ([#378](https://github.com/lynx-family/lynx-stack/pull/378))
19
+
20
+ Now we moved the timing system to the background thread.
21
+
22
+ - feat: support `defaultOverflowVisible` config ([#406](https://github.com/lynx-family/lynx-stack/pull/406))
23
+
24
+ - fix(web): rsbuild will bundle 2 exactly same chunk for two same `new Worker` stmt ([#372](https://github.com/lynx-family/lynx-stack/pull/372))
25
+
26
+ the bundle size will be optimized about 28.2KB
27
+
28
+ - fix: inline style will be removed for value number `0` ([#368](https://github.com/lynx-family/lynx-stack/pull/368))
29
+
30
+ the inline style value could be incorrectly removed for number value `0`;
31
+
32
+ For example, `flex-shrink:0` may be ignored.
33
+
34
+ - feat: The onNapiModulesCall function of lynx-view provides the fourth parameter: `lynxView`, which is the actual lynx-view DOM. ([#350](https://github.com/lynx-family/lynx-stack/pull/350))
35
+
36
+ - fix: publicComponentEvent args order ([#401](https://github.com/lynx-family/lynx-stack/pull/401))
37
+
38
+ - Updated dependencies [[`3a8dabd`](https://github.com/lynx-family/lynx-stack/commit/3a8dabd877084c15db1404c912dd8a19c7a0fc59), [`a521759`](https://github.com/lynx-family/lynx-stack/commit/a5217592f5aebea4b17860e729d523ecabb5f691), [`890c6c5`](https://github.com/lynx-family/lynx-stack/commit/890c6c51470c82104abb1049681f55e5d97cf9d6)]:
39
+ - @lynx-js/web-worker-runtime@0.10.0
40
+ - @lynx-js/web-constants@0.10.0
41
+ - @lynx-js/web-worker-rpc@0.10.0
42
+
43
+ ## 0.9.1
44
+
45
+ ### Patch Changes
46
+
47
+ - feat: remove extra div #lynx-view-root ([#311](https://github.com/lynx-family/lynx-stack/pull/311))
48
+
49
+ In this commit we've re-implemented the lynx-view's auto-size. Now we use the `contain:content` instead of `resizeObserver`.
50
+
51
+ - Updated dependencies []:
52
+ - @lynx-js/web-constants@0.9.1
53
+ - @lynx-js/web-worker-rpc@0.9.1
54
+ - @lynx-js/web-worker-runtime@0.9.1
55
+
3
56
  ## 0.9.0
4
57
 
5
58
  ### Minor Changes
package/README.md CHANGED
@@ -10,8 +10,24 @@ import '@lynx-js/web-core/index.css';
10
10
 
11
11
  document.body.innerHTML = `
12
12
  <lynx-view
13
- style="height:100vh; width:100vw;"
14
- url="http://localhost:3000/main/main-thread.js"
13
+ style="height:100vh; width:100vw;"
14
+ url="http://localhost:3000/main/main-thread.js"
15
+ >
16
+ </lynx-view>`;
17
+ ```
18
+
19
+ If you use Lynx elements (view, text, image, etc.), you need to import `@lynx-js/web-elements`:
20
+
21
+ ```javascript
22
+ import '@lynx-js/web-core';
23
+ import '@lynx-js/web-core/index.css';
24
+ import '@lynx-js/web-elements/all';
25
+ import '@lynx-js/web-elements/index.css';
26
+
27
+ document.body.innerHTML = `
28
+ <lynx-view
29
+ style="height:100vh; width:100vw;"
30
+ url="http://localhost:3000/main/main-thread.js"
15
31
  >
16
32
  </lynx-view>`;
17
33
  ```
@@ -1,4 +1,11 @@
1
1
  import { type Cloneable, type NapiModulesCall, type NapiModulesMap, type NativeModulesCall, type NativeModulesMap, type UpdateDataType } from '@lynx-js/web-constants';
2
+ export type INapiModulesCall = (name: string, data: any, moduleName: string, lynxView: LynxView) => Promise<{
3
+ data: unknown;
4
+ transfer?: Transferable[];
5
+ }> | {
6
+ data: unknown;
7
+ transfer?: Transferable[];
8
+ } | undefined;
2
9
  /**
3
10
  * Based on our experiences, these elements are almost used in all lynx cards.
4
11
  */
@@ -12,7 +19,7 @@ import { type Cloneable, type NapiModulesCall, type NapiModulesMap, type NativeM
12
19
  * @param {"auto" | null} height [optional] set it to "auto" for height auto-sizing
13
20
  * @param {"auto" | null} width [optional] set it to "auto" for width auto-sizing
14
21
  * @param {NapiModulesMap} napiModulesMap [optional] the napiModule which is called in lynx-core. key is module-name, value is esm url.
15
- * @param {NapiModulesCall} onNapiModulesCall [optional] the NapiModule value handler.
22
+ * @param {INapiModulesCall} onNapiModulesCall [optional] the NapiModule value handler.
16
23
  * @param {"false" | "true" | null} injectHeadLinks [optional] @default true set it to "false" to disable injecting the <link href="" ref="stylesheet"> styles into shadowroot
17
24
  *
18
25
  * @event error lynx card fired an error
@@ -95,19 +102,7 @@ export declare class LynxView extends HTMLElement {
95
102
  * @property
96
103
  */
97
104
  get onNapiModulesCall(): NapiModulesCall | undefined;
98
- set onNapiModulesCall(handler: NapiModulesCall);
99
- /**
100
- * @public
101
- * "auto" for auto calculated height
102
- */
103
- get height(): string | null;
104
- /**
105
- * @public
106
- * "auto" for auto calculated width
107
- */
108
- get width(): string | null;
109
- set height(val: string | null);
110
- set width(val: string | null);
105
+ set onNapiModulesCall(handler: INapiModulesCall);
111
106
  /**
112
107
  * @public
113
108
  * @method
@@ -145,5 +140,4 @@ export declare class LynxView extends HTMLElement {
145
140
  * @private
146
141
  */
147
142
  connectedCallback(): void;
148
- private cleanupResizeObserver;
149
143
  }
@@ -2,7 +2,7 @@
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
4
  import { createLynxView, } from './createLynxView.js';
5
- import { lynxViewRootDomId, } from '@lynx-js/web-constants';
5
+ import {} from '@lynx-js/web-constants';
6
6
  import { inShadowRootStyles } from './inShadowRootStyles.js';
7
7
  /**
8
8
  * Based on our experiences, these elements are almost used in all lynx cards.
@@ -17,7 +17,7 @@ import { inShadowRootStyles } from './inShadowRootStyles.js';
17
17
  * @param {"auto" | null} height [optional] set it to "auto" for height auto-sizing
18
18
  * @param {"auto" | null} width [optional] set it to "auto" for width auto-sizing
19
19
  * @param {NapiModulesMap} napiModulesMap [optional] the napiModule which is called in lynx-core. key is module-name, value is esm url.
20
- * @param {NapiModulesCall} onNapiModulesCall [optional] the NapiModule value handler.
20
+ * @param {INapiModulesCall} onNapiModulesCall [optional] the NapiModule value handler.
21
21
  * @param {"false" | "true" | null} injectHeadLinks [optional] @default true set it to "false" to disable injecting the <link href="" ref="stylesheet"> styles into shadowroot
22
22
  *
23
23
  * @event error lynx card fired an error
@@ -167,75 +167,9 @@ export class LynxView extends HTMLElement {
167
167
  return this.#onNapiModulesCall;
168
168
  }
169
169
  set onNapiModulesCall(handler) {
170
- this.#onNapiModulesCall = handler;
171
- }
172
- #autoHeight = false;
173
- #autoWidth = false;
174
- #currentWidth = 0;
175
- #currentHeight = 0;
176
- /**
177
- * @public
178
- * "auto" for auto calculated height
179
- */
180
- get height() {
181
- return this.#autoHeight ? 'auto' : null;
182
- }
183
- /**
184
- * @public
185
- * "auto" for auto calculated width
186
- */
187
- get width() {
188
- return this.#autoWidth ? 'auto' : null;
189
- }
190
- set height(val) {
191
- this.#handleAutoSize();
192
- this.#autoHeight = val === 'auto' ? true : false;
193
- }
194
- set width(val) {
195
- this.#handleAutoSize();
196
- this.#autoWidth = val === 'auto' ? true : false;
197
- }
198
- #handleAutoSize() {
199
- if (this.#autoHeight || this.#autoWidth) {
200
- if (this.#instance && !this.#instance.resizeObserver) {
201
- this.#instance.resizeObserver = new ResizeObserver((sizes) => {
202
- const size = sizes[0];
203
- if (size) {
204
- const { width, height } = size.contentRect;
205
- if (this.#autoWidth) {
206
- if (this.#currentWidth !== width) {
207
- this.#currentWidth = width;
208
- this.style.setProperty('--lynx-view-width', `${width}px`);
209
- }
210
- }
211
- if (this.#autoHeight) {
212
- if (this.#currentHeight !== height) {
213
- this.#currentHeight = height;
214
- this.style.setProperty('--lynx-view-height', `${height}px`);
215
- }
216
- }
217
- }
218
- });
219
- this.#instance.resizeObserver.observe(this.#instance.rootDom);
220
- }
221
- }
222
- else {
223
- if (this.#instance?.resizeObserver) {
224
- this.#instance.resizeObserver.disconnect();
225
- }
226
- }
227
- if (this.#autoHeight) {
228
- this.setAttribute('height', 'auto');
229
- }
230
- else {
231
- this.removeAttribute('height');
232
- }
233
- if (this.#autoWidth) {
234
- this.setAttribute('width', 'auto');
235
- }
236
- else {
237
- this.removeAttribute('width');
238
- }
170
+ this.#onNapiModulesCall = (name, data, moduleName) => {
171
+ return handler(name, data, moduleName, this);
172
+ };
239
173
  }
240
174
  /**
241
175
  * @public
@@ -243,7 +177,7 @@ export class LynxView extends HTMLElement {
243
177
  * update the `__initData` and trigger essential flow
244
178
  */
245
179
  updateData(data, updateDataType, callback) {
246
- this.#instance?.lynxView.updateData(data, updateDataType, callback);
180
+ this.#instance?.updateData(data, updateDataType, callback);
247
181
  }
248
182
  /**
249
183
  * @public
@@ -251,7 +185,7 @@ export class LynxView extends HTMLElement {
251
185
  * send global events, which can be listened to using the GlobalEventEmitter
252
186
  */
253
187
  sendGlobalEvent(eventName, params) {
254
- this.#instance?.lynxView.sendGlobalEvent(eventName, params);
188
+ this.#instance?.sendGlobalEvent(eventName, params);
255
189
  }
256
190
  /**
257
191
  * @public
@@ -291,11 +225,7 @@ export class LynxView extends HTMLElement {
291
225
  * @private
292
226
  */
293
227
  disconnectedCallback() {
294
- this.cleanupResizeObserver();
295
- if (this.#instance) {
296
- this.#instance.lynxView.dispose();
297
- this.#instance.rootDom.remove();
298
- }
228
+ this.#instance?.dispose();
299
229
  this.#instance = undefined;
300
230
  if (this.shadowRoot) {
301
231
  this.shadowRoot.innerHTML = '';
@@ -317,9 +247,6 @@ export class LynxView extends HTMLElement {
317
247
  this.disconnectedCallback();
318
248
  }
319
249
  if (this.#url) {
320
- const rootDom = document.createElement('div');
321
- rootDom.id = lynxViewRootDomId;
322
- rootDom.setAttribute('part', lynxViewRootDomId);
323
250
  const tagMap = {
324
251
  'page': 'div',
325
252
  'view': 'x-view',
@@ -329,9 +256,12 @@ export class LynxView extends HTMLElement {
329
256
  'svg': 'x-svg',
330
257
  ...this.overrideLynxTagToHTMLTagMap,
331
258
  };
259
+ if (!this.shadowRoot) {
260
+ this.attachShadow({ mode: 'open' });
261
+ }
332
262
  const lynxView = createLynxView({
333
263
  tagMap,
334
- rootDom,
264
+ shadowRoot: this.shadowRoot,
335
265
  templateUrl: this.#url,
336
266
  globalProps: this.#globalProps,
337
267
  initData: this.#initData,
@@ -357,18 +287,13 @@ export class LynxView extends HTMLElement {
357
287
  },
358
288
  },
359
289
  });
360
- this.#instance = {
361
- lynxView,
362
- rootDom,
363
- };
364
- this.#handleAutoSize();
365
- if (!this.shadowRoot) {
366
- this.attachShadow({ mode: 'open' });
367
- }
290
+ this.#instance = lynxView;
368
291
  const styleElement = document.createElement('style');
369
292
  this.shadowRoot.append(styleElement);
370
293
  const styleSheet = styleElement.sheet;
371
- styleSheet.insertRule(inShadowRootStyles);
294
+ for (const rule of inShadowRootStyles) {
295
+ styleSheet.insertRule(rule);
296
+ }
372
297
  const injectHeadLinks = this.getAttribute('inject-head-links') !== 'false';
373
298
  if (injectHeadLinks) {
374
299
  document.head.querySelectorAll('link[rel="stylesheet"]').forEach((linkElement) => {
@@ -376,7 +301,6 @@ export class LynxView extends HTMLElement {
376
301
  styleSheet.insertRule(`@import url("${href}");`);
377
302
  });
378
303
  }
379
- this.shadowRoot.append(rootDom);
380
304
  }
381
305
  });
382
306
  }
@@ -387,12 +311,6 @@ export class LynxView extends HTMLElement {
387
311
  connectedCallback() {
388
312
  this.#render();
389
313
  }
390
- cleanupResizeObserver() {
391
- if (this.#instance?.resizeObserver) {
392
- this.#instance.resizeObserver.disconnect();
393
- this.#instance.resizeObserver = undefined;
394
- }
395
- }
396
314
  }
397
315
  if (customElements.get(LynxView.tag)) {
398
316
  console.warn(`[${LynxView.tag}] has already been defined`);
@@ -5,7 +5,7 @@ export interface LynxViewConfigs {
5
5
  templateUrl: string;
6
6
  initData: Cloneable;
7
7
  globalProps: Cloneable;
8
- rootDom: HTMLElement;
8
+ shadowRoot: ShadowRoot;
9
9
  callbacks: Parameters<typeof startUIThread>[3];
10
10
  nativeModulesMap: NativeModulesMap;
11
11
  napiModulesMap: NapiModulesMap;
@@ -3,7 +3,7 @@
3
3
  // LICENSE file in the root directory of this source tree.
4
4
  import { startUIThread } from '../uiThread/startUIThread.js';
5
5
  export function createLynxView(configs) {
6
- const { rootDom, callbacks, templateUrl, globalProps, initData, nativeModulesMap, napiModulesMap, tagMap, } = configs;
6
+ const { shadowRoot, callbacks, templateUrl, globalProps, initData, nativeModulesMap, napiModulesMap, tagMap, } = configs;
7
7
  return startUIThread(templateUrl, {
8
8
  tagMap,
9
9
  initData,
@@ -11,6 +11,6 @@ export function createLynxView(configs) {
11
11
  nativeModulesMap,
12
12
  napiModulesMap,
13
13
  browserConfig: {},
14
- }, rootDom, callbacks);
14
+ }, shadowRoot, callbacks);
15
15
  }
16
16
  //# sourceMappingURL=createLynxView.js.map
@@ -1 +1 @@
1
- export declare const inShadowRootStyles = "\n[lynx-default-display-linear=\"false\"] * {\n --lynx-display: flex;\n --lynx-display-toggle: var(--lynx-display-flex);\n}\n";
1
+ export declare const inShadowRootStyles: string[];
@@ -1,7 +1,10 @@
1
- export const inShadowRootStyles = `
2
- [lynx-default-display-linear="false"] * {
3
- --lynx-display: flex;
4
- --lynx-display-toggle: var(--lynx-display-flex);
5
- }
6
- `;
1
+ export const inShadowRootStyles = [
2
+ ` [lynx-default-display-linear="false"] * {
3
+ --lynx-display: flex;
4
+ --lynx-display-toggle: var(--lynx-display-flex);
5
+ }`,
6
+ `[lynx-default-overflow-visible="true"] x-view{
7
+ overflow: visible;
8
+ }`,
9
+ ];
7
10
  //# sourceMappingURL=inShadowRootStyles.js.map
package/dist/index.d.ts CHANGED
@@ -1,3 +1,2 @@
1
1
  export { createLynxView } from './apis/createLynxView.js';
2
2
  export { LynxView } from './apis/LynxView.js';
3
- export { lynxRuntimeValue } from '@lynx-js/web-constants';
package/dist/index.js CHANGED
@@ -3,5 +3,4 @@
3
3
  // LICENSE file in the root directory of this source tree.
4
4
  export { createLynxView } from './apis/createLynxView.js';
5
5
  export { LynxView } from './apis/LynxView.js';
6
- export { lynxRuntimeValue } from '@lynx-js/web-constants';
7
6
  //# sourceMappingURL=index.js.map
@@ -19,10 +19,7 @@ export function bootWorkers() {
19
19
  function createMainWorker() {
20
20
  const channelToMainThread = new MessageChannel();
21
21
  const channelMainThreadWithBackground = new MessageChannel();
22
- const mainThreadWorker = new Worker(new URL('@lynx-js/web-worker-runtime', import.meta.url), {
23
- type: 'module',
24
- name: `lynx-main`,
25
- });
22
+ const mainThreadWorker = createWebWorker();
26
23
  const mainThreadMessage = {
27
24
  mode: 'main',
28
25
  toUIThread: channelToMainThread.port2,
@@ -42,10 +39,7 @@ function createMainWorker() {
42
39
  }
43
40
  function createBackgroundWorker(channelMainThreadWithBackground) {
44
41
  const channelToBackground = new MessageChannel();
45
- const backgroundThreadWorker = new Worker(new URL('@lynx-js/web-worker-runtime', import.meta.url), {
46
- type: 'module',
47
- name: `lynx-bg`,
48
- });
42
+ const backgroundThreadWorker = createWebWorker();
49
43
  const backgroundThreadMessage = {
50
44
  mode: 'background',
51
45
  toUIThread: channelToBackground.port2,
@@ -59,4 +53,10 @@ function createBackgroundWorker(channelMainThreadWithBackground) {
59
53
  const backgroundRpc = new Rpc(channelToBackground.port1, 'ui-to-bg');
60
54
  return { backgroundRpc, backgroundThreadWorker };
61
55
  }
56
+ function createWebWorker() {
57
+ return new Worker(new URL('@lynx-js/web-worker-runtime', import.meta.url), {
58
+ type: 'module',
59
+ name: `lynx-web`,
60
+ });
61
+ }
62
62
  //# sourceMappingURL=bootWorkers.js.map
@@ -1,2 +1,2 @@
1
1
  import { ErrorCode, IdentifierType } from '@lynx-js/web-constants';
2
- export declare function queryNodes(rootDom: Element, type: IdentifierType, identifier: string, component_id: string, first_only: boolean, root_unique_id: number | undefined, callback: (dom: Element) => void, error?: (code: ErrorCode) => void): void;
2
+ export declare function queryNodes(shadowRoot: ShadowRoot, type: IdentifierType, identifier: string, component_id: string, first_only: boolean, root_unique_id: number | undefined, callback: (dom: Element) => void, error?: (code: ErrorCode) => void): void;
@@ -2,10 +2,10 @@
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
4
  import { componentIdAttribute, ErrorCode, IdentifierType, lynxUniqueIdAttribute, } from '@lynx-js/web-constants';
5
- export function queryNodes(rootDom, type, identifier, component_id, first_only, root_unique_id, callback, error) {
6
- let queryRoot = rootDom;
5
+ export function queryNodes(shadowRoot, type, identifier, component_id, first_only, root_unique_id, callback, error) {
6
+ let queryRoot = shadowRoot;
7
7
  if (root_unique_id) {
8
- const root = rootDom.querySelector(`[${lynxUniqueIdAttribute}="${root_unique_id}"]`);
8
+ const root = shadowRoot.querySelector(`[${lynxUniqueIdAttribute}="${root_unique_id}"]`);
9
9
  if (root) {
10
10
  queryRoot = root;
11
11
  }
@@ -16,7 +16,7 @@ export function queryNodes(rootDom, type, identifier, component_id, first_only,
16
16
  }
17
17
  }
18
18
  else if (component_id) {
19
- const root = rootDom.querySelector(`[${componentIdAttribute}="${component_id}"]`);
19
+ const root = shadowRoot.querySelector(`[${componentIdAttribute}="${component_id}"]`);
20
20
  if (root) {
21
21
  queryRoot = root;
22
22
  }
@@ -0,0 +1,2 @@
1
+ import type { Rpc } from '@lynx-js/web-worker-rpc';
2
+ export declare function registerDispatchLynxViewEventHandler(rpc: Rpc, shadowRoot: ShadowRoot): void;
@@ -0,0 +1,15 @@
1
+ // Copyright 2023 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 { dispatchLynxViewEventEndpoint } from '@lynx-js/web-constants';
5
+ export function registerDispatchLynxViewEventHandler(rpc, shadowRoot) {
6
+ rpc.registerHandler(dispatchLynxViewEventEndpoint, (eventType, detail) => {
7
+ shadowRoot.dispatchEvent(new CustomEvent(eventType, {
8
+ detail,
9
+ bubbles: true,
10
+ cancelable: true,
11
+ composed: true,
12
+ }));
13
+ });
14
+ }
15
+ //# sourceMappingURL=registerDispatchLynxViewEventHandler.js.map
@@ -1,15 +1,6 @@
1
- import { type PageConfig, type flushElementTreeEndpoint } from '@lynx-js/web-constants';
2
1
  import type { Rpc } from '@lynx-js/web-worker-rpc';
3
- import type { RuntimePropertyOnElement } from '../../types/RuntimePropertyOnElement.js';
4
- export declare function registerFlushElementTreeHandler(mainThreadRpc: Rpc, endpoint: typeof flushElementTreeEndpoint, options: {
5
- pageConfig: PageConfig;
6
- backgroundRpc: Rpc;
7
- rootDom: HTMLElement;
2
+ export declare function registerFlushElementTreeHandler(mainThreadRpc: Rpc, options: {
3
+ shadowRoot: ShadowRoot;
8
4
  }, onCommit: (info: {
9
- pipelineId: string | undefined;
10
- timingFlags: string[];
11
5
  isFP: boolean;
12
- }) => void, markTimingInternal: (timingKey: string, pipelineId?: string, timeStamp?: number) => void): {
13
- uniqueIdToElement: WeakRef<HTMLElement & RuntimePropertyOnElement>[];
14
- uniqueIdToCssInJsRule: WeakRef<CSSStyleRule>[];
15
- };
6
+ }) => void): void;
@@ -1,97 +1,24 @@
1
1
  // Copyright 2023 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 { componentIdAttribute, lynxDefaultDisplayLinearAttribute, lynxRuntimeValue, lynxTagAttribute, lynxUniqueIdAttribute, parentComponentUniqueIdAttribute, postMainThreadEvent, publicComponentEventEndpoint, publishEventEndpoint, } from '@lynx-js/web-constants';
5
- import { decodeElementOperation } from '../decodeElementOperation.js';
6
- import { createCrossThreadEvent } from '../../utils/createCrossThreadEvent.js';
7
- function applyPageAttributes(page, pageConfig) {
8
- if (pageConfig.defaultDisplayLinear === false) {
9
- page.setAttribute(lynxDefaultDisplayLinearAttribute, 'false');
10
- }
11
- }
12
- export function registerFlushElementTreeHandler(mainThreadRpc, endpoint, options, onCommit, markTimingInternal) {
13
- const { pageConfig, backgroundRpc, rootDom, } = options;
14
- const uniqueIdToElement = [];
15
- const uniqueIdToCssInJsRule = [];
16
- const rootStyleElementForCssInJs = document.createElement('style');
17
- if (!pageConfig.enableCSSSelector) {
18
- rootDom.append(rootStyleElementForCssInJs);
19
- }
20
- const createElementImpl = (tag) => {
21
- const element = document.createElement(tag);
22
- element[lynxRuntimeValue] = {
23
- dataset: {},
24
- eventHandler: {},
25
- };
26
- return element;
27
- };
28
- const createStyleRuleImpl = (uniqueId, initialStyle) => {
29
- const commonStyleSheetText = `[${lynxUniqueIdAttribute}="${uniqueId.toString()}"]{${initialStyle}}`;
30
- const idx = rootStyleElementForCssInJs.sheet.insertRule(commonStyleSheetText);
31
- return rootStyleElementForCssInJs.sheet.cssRules[idx];
32
- };
33
- const mtsHandler = (event) => {
34
- const crossThreadEvent = createCrossThreadEvent(event);
35
- mainThreadRpc.invoke(postMainThreadEvent, [crossThreadEvent]);
36
- };
37
- const btsHandler = (event) => {
38
- const crossThreadEvent = createCrossThreadEvent(event);
39
- const currentTarget = event.currentTarget;
40
- const parentComponentUniqueId = currentTarget.getAttribute(parentComponentUniqueIdAttribute) ?? '0';
41
- const componentTargetDom = rootDom.querySelector(`[${lynxUniqueIdAttribute}="${parentComponentUniqueId}"]`);
42
- const componentId = componentTargetDom?.getAttribute(lynxTagAttribute) !== 'page'
43
- ? componentTargetDom?.getAttribute(componentIdAttribute) ?? undefined
44
- : undefined;
45
- const hname = currentTarget[lynxRuntimeValue]
46
- .eventHandler[crossThreadEvent.type].hname;
47
- if (componentId) {
48
- backgroundRpc.invoke(publicComponentEventEndpoint, [
49
- componentId,
50
- hname,
51
- crossThreadEvent,
52
- ]);
53
- }
54
- else {
55
- backgroundRpc.invoke(publishEventEndpoint, [
56
- hname,
57
- crossThreadEvent,
58
- ]);
59
- }
60
- };
61
- mainThreadRpc.registerHandler(endpoint, (operations, options, cardCss, timingFlags) => {
62
- const { pipelineOptions } = options;
63
- const pipelineId = pipelineOptions?.pipelineID;
64
- markTimingInternal('dispatch_start', pipelineId);
65
- markTimingInternal('layout_start', pipelineId);
66
- markTimingInternal('ui_operation_flush_start', pipelineId);
67
- const page = decodeElementOperation(operations, {
68
- uniqueIdToElement,
69
- uniqueIdToCssInJsRule,
70
- createElementImpl,
71
- createStyleRuleImpl,
72
- eventHandler: {
73
- mtsHandler,
74
- btsHandler,
75
- },
76
- });
77
- markTimingInternal('ui_operation_flush_end', pipelineId);
78
- const isFP = !!page;
79
- if (isFP) {
80
- // on FP
81
- const styleElement = document.createElement('style');
82
- styleElement.innerHTML = cardCss;
83
- rootDom.append(styleElement);
84
- rootDom.append(page);
85
- applyPageAttributes(page, pageConfig);
86
- }
87
- markTimingInternal('layout_end', pipelineId);
88
- markTimingInternal('dispatch_end', pipelineId);
4
+ import { flushElementTreeEndpoint, postOffscreenEventEndpoint, } from '@lynx-js/web-constants';
5
+ import { initOffscreenDocument } from '@lynx-js/offscreen-document/main';
6
+ export function registerFlushElementTreeHandler(mainThreadRpc, options, onCommit) {
7
+ const { shadowRoot, } = options;
8
+ const onEvent = mainThreadRpc.createCall(postOffscreenEventEndpoint);
9
+ const { decodeOperation } = initOffscreenDocument({
10
+ shadowRoot,
11
+ onEvent,
12
+ });
13
+ let isFP = true;
14
+ mainThreadRpc.registerHandler(flushElementTreeEndpoint, (operations) => {
15
+ decodeOperation(operations);
89
16
  onCommit({
90
- pipelineId,
91
- timingFlags,
92
17
  isFP,
93
18
  });
19
+ if (isFP) {
20
+ isFP = false;
21
+ }
94
22
  });
95
- return { uniqueIdToElement, uniqueIdToCssInJsRule };
96
23
  }
97
24
  //# sourceMappingURL=registerFlushElementTreeHandler.js.map
@@ -1,2 +1,2 @@
1
1
  import { Rpc } from '@lynx-js/web-worker-rpc';
2
- export declare function registerInvokeUIMethodHandler(rpc: Rpc, rootDom: Element): void;
2
+ export declare function registerInvokeUIMethodHandler(rpc: Rpc, shadowRoot: ShadowRoot): void;
@@ -1,13 +1,14 @@
1
+ // Copyright 2023 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.
1
4
  import { Rpc } from '@lynx-js/web-worker-rpc';
2
5
  import { queryNodes } from './queryNodes.js';
3
- import { ErrorCode, lynxRuntimeValue, invokeUIMethodEndpoint, } from '@lynx-js/web-constants';
6
+ import { ErrorCode, invokeUIMethodEndpoint } from '@lynx-js/web-constants';
4
7
  const methodAlias = {
5
8
  'boundingClientRect': (element) => {
6
9
  const rect = element.getBoundingClientRect();
7
10
  return {
8
11
  id: element.id,
9
- dataset: element[lynxRuntimeValue]
10
- .dataset,
11
12
  width: rect.width,
12
13
  height: rect.height,
13
14
  left: rect.left,
@@ -17,11 +18,11 @@ const methodAlias = {
17
18
  };
18
19
  },
19
20
  };
20
- export function registerInvokeUIMethodHandler(rpc, rootDom) {
21
+ export function registerInvokeUIMethodHandler(rpc, shadowRoot) {
21
22
  let code = ErrorCode.UNKNOWN;
22
23
  let data = undefined;
23
24
  rpc.registerHandler(invokeUIMethodEndpoint, (type, identifier, component_id, method, params, root_unique_id) => {
24
- queryNodes(rootDom, type, identifier, component_id, true, root_unique_id, (element) => {
25
+ queryNodes(shadowRoot, type, identifier, component_id, true, root_unique_id, (element) => {
25
26
  try {
26
27
  const aliasMethod = methodAlias[method];
27
28
  const hasDomMethod = typeof element[method] === 'function';
@@ -1,2 +1,2 @@
1
1
  import type { Rpc } from '@lynx-js/web-worker-rpc';
2
- export declare function registerSelectComponentHandler(rpc: Rpc, rootDom: Element): void;
2
+ export declare function registerSelectComponentHandler(rpc: Rpc, shadowRoot: ShadowRoot): void;
@@ -3,10 +3,10 @@
3
3
  // LICENSE file in the root directory of this source tree.
4
4
  import { componentIdAttribute, IdentifierType, selectComponentEndpoint, } from '@lynx-js/web-constants';
5
5
  import { queryNodes } from './queryNodes.js';
6
- export function registerSelectComponentHandler(rpc, rootDom) {
6
+ export function registerSelectComponentHandler(rpc, shadowRoot) {
7
7
  let element;
8
8
  rpc.registerHandler(selectComponentEndpoint, (componentId, idSelector, single) => {
9
- queryNodes(rootDom, IdentifierType.ID_SELECTOR, idSelector, componentId === 'card' ? '0' : componentId, single, undefined, (ele) => {
9
+ queryNodes(shadowRoot, IdentifierType.ID_SELECTOR, idSelector, componentId === 'card' ? '0' : componentId, single, undefined, (ele) => {
10
10
  element = ele;
11
11
  });
12
12
  return [element?.getAttribute(componentIdAttribute) ?? undefined];
@@ -1,2 +1,2 @@
1
1
  import { Rpc } from '@lynx-js/web-worker-rpc';
2
- export declare function registerNativePropsHandler(rpc: Rpc, rootDom: Element): void;
2
+ export declare function registerNativePropsHandler(rpc: Rpc, shadowRoot: ShadowRoot): void;
@@ -22,9 +22,9 @@ function applyNativeProps(element, nativeProps) {
22
22
  }
23
23
  }
24
24
  }
25
- export function registerNativePropsHandler(rpc, rootDom) {
25
+ export function registerNativePropsHandler(rpc, shadowRoot) {
26
26
  rpc.registerHandler(setNativePropsEndpoint, (type, identifier, component_id, first_only, native_props, root_unique_id) => {
27
- queryNodes(rootDom, type, identifier, component_id, first_only, root_unique_id, (element) => {
27
+ queryNodes(shadowRoot, type, identifier, component_id, first_only, root_unique_id, (element) => {
28
28
  applyNativeProps(element, native_props);
29
29
  });
30
30
  });
@@ -1,2 +1,2 @@
1
1
  import type { Rpc } from '@lynx-js/web-worker-rpc';
2
- export declare function registerTriggerComponentEventHandler(rpc: Rpc, rootDom: Element): void;
2
+ export declare function registerTriggerComponentEventHandler(rpc: Rpc, shadowRoot: ShadowRoot): void;
@@ -2,9 +2,9 @@
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
4
  import { componentIdAttribute, triggerComponentEventEndpoint, } from '@lynx-js/web-constants';
5
- export function registerTriggerComponentEventHandler(rpc, rootDom) {
5
+ export function registerTriggerComponentEventHandler(rpc, shadowRoot) {
6
6
  rpc.registerHandler(triggerComponentEventEndpoint, (id, params) => {
7
- const componentDom = rootDom.querySelector(`[${componentIdAttribute}="${params.componentId}"]`);
7
+ const componentDom = shadowRoot.querySelector(`[${componentIdAttribute}="${params.componentId}"]`);
8
8
  componentDom?.dispatchEvent(new CustomEvent(id, {
9
9
  ...params.eventOption,
10
10
  detail: params.eventDetail,
@@ -1,6 +1,6 @@
1
1
  import type { LynxView } from '../apis/createLynxView.js';
2
2
  import { type MainThreadStartConfigs, type NapiModulesCall, type NativeModulesCall } from '@lynx-js/web-constants';
3
- export declare function startUIThread(templateUrl: string, configs: Omit<MainThreadStartConfigs, 'template'>, rootDom: HTMLElement, callbacks: {
3
+ export declare function startUIThread(templateUrl: string, configs: Omit<MainThreadStartConfigs, 'template'>, shadowRoot: ShadowRoot, callbacks: {
4
4
  nativeModulesCall: NativeModulesCall;
5
5
  napiModulesCall: NapiModulesCall;
6
6
  onError?: () => void;
@@ -1,7 +1,6 @@
1
1
  // Copyright 2023 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 { createExposureService } from './crossThreadHandlers/createExposureService.js';
5
4
  import { registerInvokeUIMethodHandler } from './crossThreadHandlers/registerInvokeUIMethodHandler.js';
6
5
  import { registerNativePropsHandler } from './crossThreadHandlers/registerSetNativePropsHandler.js';
7
6
  import { registerNativeModulesCallHandler } from './crossThreadHandlers/registerNativeModulesCallHandler.js';
@@ -9,21 +8,26 @@ import { bootWorkers } from './bootWorkers.js';
9
8
  import { registerReportErrorHandler } from './crossThreadHandlers/registerReportErrorHandler.js';
10
9
  import { registerFlushElementTreeHandler } from './crossThreadHandlers/registerFlushElementTreeHandler.js';
11
10
  import { createDispose } from './crossThreadHandlers/createDispose.js';
12
- import { bootTimingSystem } from './crossThreadHandlers/bootTimingSystem.js';
13
11
  import { registerTriggerComponentEventHandler } from './crossThreadHandlers/registerTriggerComponentEventHandler.js';
14
12
  import { registerSelectComponentHandler } from './crossThreadHandlers/registerSelectComponentHandler.js';
15
- import { flushElementTreeEndpoint, mainThreadChunkReadyEndpoint, mainThreadStartEndpoint, sendGlobalEventEndpoint, uiThreadFpReadyEndpoint, } from '@lynx-js/web-constants';
13
+ import { mainThreadChunkReadyEndpoint, mainThreadStartEndpoint, markTimingEndpoint, sendGlobalEventEndpoint, uiThreadFpReadyEndpoint, } from '@lynx-js/web-constants';
16
14
  import { loadTemplate } from '../utils/loadTemplate.js';
17
15
  import { createUpdateData } from './crossThreadHandlers/createUpdateData.js';
18
16
  import { registerNapiModulesCallHandler } from './crossThreadHandlers/registerNapiModulesCallHandler.js';
19
- export function startUIThread(templateUrl, configs, rootDom, callbacks) {
17
+ import { registerDispatchLynxViewEventHandler } from './crossThreadHandlers/registerDispatchLynxViewEventHandler.js';
18
+ export function startUIThread(templateUrl, configs, shadowRoot, callbacks) {
20
19
  const createLynxStartTiming = performance.now() + performance.timeOrigin;
21
20
  const { nativeModulesMap, napiModulesMap } = configs;
22
21
  const { mainThreadRpc, backgroundRpc, terminateWorkers, } = bootWorkers();
23
22
  const sendGlobalEvent = backgroundRpc.createCall(sendGlobalEventEndpoint);
24
23
  const uiThreadFpReady = backgroundRpc.createCall(uiThreadFpReadyEndpoint);
25
24
  const mainThreadStart = mainThreadRpc.createCall(mainThreadStartEndpoint);
26
- const { markTimingInternal, sendTimingResult } = bootTimingSystem(mainThreadRpc, backgroundRpc, rootDom);
25
+ const markTiming = backgroundRpc.createCall(markTimingEndpoint);
26
+ const markTimingInternal = (timingKey, pipelineId, timeStamp) => {
27
+ if (!timeStamp)
28
+ timeStamp = performance.now() + performance.timeOrigin;
29
+ markTiming(timingKey, pipelineId, timeStamp);
30
+ };
27
31
  markTimingInternal('create_lynx_start', undefined, createLynxStartTiming);
28
32
  markTimingInternal('load_template_start');
29
33
  loadTemplate(templateUrl).then((template) => {
@@ -36,24 +40,20 @@ export function startUIThread(templateUrl, configs, rootDom, callbacks) {
36
40
  });
37
41
  });
38
42
  registerReportErrorHandler(mainThreadRpc, callbacks.onError);
39
- mainThreadRpc.registerHandler(mainThreadChunkReadyEndpoint, (mainChunkInfo) => {
40
- const { pageConfig } = mainChunkInfo;
41
- registerFlushElementTreeHandler(mainThreadRpc, flushElementTreeEndpoint, {
42
- pageConfig,
43
- backgroundRpc,
44
- rootDom,
43
+ registerDispatchLynxViewEventHandler(backgroundRpc, shadowRoot);
44
+ mainThreadRpc.registerHandler(mainThreadChunkReadyEndpoint, () => {
45
+ registerFlushElementTreeHandler(mainThreadRpc, {
46
+ shadowRoot,
45
47
  }, (info) => {
46
- const { pipelineId, timingFlags, isFP } = info;
48
+ const { isFP } = info;
47
49
  if (isFP) {
48
- registerInvokeUIMethodHandler(backgroundRpc, rootDom);
49
- registerNativePropsHandler(backgroundRpc, rootDom);
50
- registerTriggerComponentEventHandler(backgroundRpc, rootDom);
51
- registerSelectComponentHandler(backgroundRpc, rootDom);
52
- createExposureService(backgroundRpc, rootDom);
50
+ registerInvokeUIMethodHandler(backgroundRpc, shadowRoot);
51
+ registerNativePropsHandler(backgroundRpc, shadowRoot);
52
+ registerTriggerComponentEventHandler(backgroundRpc, shadowRoot);
53
+ registerSelectComponentHandler(backgroundRpc, shadowRoot);
53
54
  uiThreadFpReady();
54
55
  }
55
- sendTimingResult(pipelineId, timingFlags, isFP);
56
- }, markTimingInternal);
56
+ });
57
57
  });
58
58
  registerNativeModulesCallHandler(backgroundRpc, callbacks.nativeModulesCall);
59
59
  registerNapiModulesCallHandler(backgroundRpc, callbacks.napiModulesCall);
package/index.css CHANGED
@@ -9,54 +9,17 @@ lynx-view {
9
9
  display: flex;
10
10
  }
11
11
 
12
- lynx-view::part(lynx-view-root) {
13
- display: contents;
14
- width: 100%;
15
- height: 100%;
16
- }
17
-
18
- lynx-view[height="auto"] {
19
- --lynx-view-height: 100%;
20
- height: var(--lynx-view-height);
21
- block-size: var(--lynx-view-height);
22
- }
23
- lynx-view[height="auto"]::part(lynx-view-root) {
24
- height: unset;
25
- }
26
-
27
12
  lynx-view[width="auto"] {
28
13
  --lynx-view-width: 100%;
29
14
  width: var(--lynx-view-width);
30
15
  inline-size: var(--lynx-view-width);
31
16
  }
32
- lynx-view[width="auto"]::part(lynx-view-root) {
33
- width: unset;
34
- }
35
17
 
36
18
  lynx-view[height="auto"], lynx-view[width="auto"] {
37
- contain-intrinsic-size: var(--lynx-view-width) var(--lynx-view-height);
38
- }
39
- lynx-view[height="auto"]::part(lynx-view-root),
40
- lynx-view[width="auto"]::part(lynx-view-root) {
41
- display: unset;
42
- position: fixed;
43
- top: 0;
44
- left: 0;
45
- }
46
-
47
- @property --lynx-view-width {
48
- syntax: "<length> | <percentage>";
49
- inherits: false;
50
- initial-value: 100%;
51
- }
52
-
53
- @property --lynx-view-height {
54
- syntax: "<length> | <percentage>";
55
- inherits: false;
56
- initial-value: 100%;
19
+ contain: content;
57
20
  }
58
21
 
59
- lynx-view:not([width="auto"]):not([height="auto"])::part(page) {
22
+ lynx-view::part(page) {
60
23
  height: 100%;
61
24
  width: 100%;
62
25
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lynx-js/web-core",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "private": false,
5
5
  "description": "",
6
6
  "keywords": [],
@@ -24,13 +24,14 @@
24
24
  "**/*.css"
25
25
  ],
26
26
  "dependencies": {
27
- "@lynx-js/web-constants": "0.9.0",
28
- "@lynx-js/web-worker-rpc": "0.9.0",
29
- "@lynx-js/web-worker-runtime": "0.9.0"
27
+ "@lynx-js/offscreen-document": "0.0.0",
28
+ "@lynx-js/web-constants": "0.10.0",
29
+ "@lynx-js/web-worker-rpc": "0.10.0",
30
+ "@lynx-js/web-worker-runtime": "0.10.0"
30
31
  },
31
32
  "devDependencies": {
32
33
  "@lynx-js/lynx-core": "0.1.0",
33
- "@lynx-js/web-elements": "0.5.0"
34
+ "@lynx-js/web-elements": "0.5.2"
34
35
  },
35
36
  "peerDependencies": {
36
37
  "@lynx-js/lynx-core": "0.1.0",
@@ -1,17 +0,0 @@
1
- import type { LynxEventType, Cloneable } from '@lynx-js/web-constants';
2
- import { lynxRuntimeValue } from '@lynx-js/web-constants';
3
- type RuntimeValue = {
4
- dataset: {
5
- [key: string]: Cloneable;
6
- };
7
- eventHandler: Record<string, {
8
- type: LynxEventType;
9
- handler: (ev: Event) => void;
10
- hname: string;
11
- } | undefined>;
12
- [key: string]: any;
13
- };
14
- export type RuntimePropertyOnElement = {
15
- [lynxRuntimeValue]: RuntimeValue;
16
- };
17
- export {};
@@ -1,2 +0,0 @@
1
- import { lynxRuntimeValue } from '@lynx-js/web-constants';
2
- //# sourceMappingURL=RuntimePropertyOnElement.js.map
@@ -1,5 +0,0 @@
1
- import type { Rpc } from '@lynx-js/web-worker-rpc';
2
- export declare function bootTimingSystem(mainThreadRpc: Rpc, backgroundThreadRpc: Rpc, rootDom: HTMLElement): {
3
- markTimingInternal: (timingKey: string, pipelineId?: string, timeStamp?: number) => void;
4
- sendTimingResult: (pipelineId: string | undefined, timingFlags: string[], isFp: boolean) => void;
5
- };
@@ -1,51 +0,0 @@
1
- // Copyright 2023 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 { postTimingInfoFromBackgroundThread, postTimingInfoFromMainThread, postTimingResult, } from '@lynx-js/web-constants';
5
- export function bootTimingSystem(mainThreadRpc, backgroundThreadRpc, rootDom) {
6
- const setupTiming = {};
7
- const pipelineIdToTiming = new Map();
8
- let commonTimingFlags = [];
9
- function markTimingInternal(timingKey, pipelineId, timeStamp) {
10
- if (!timeStamp)
11
- timeStamp = performance.now() + performance.timeOrigin;
12
- if (!pipelineId) {
13
- setupTiming[timingKey] = timeStamp;
14
- return;
15
- }
16
- if (!pipelineIdToTiming.has(pipelineId)) {
17
- pipelineIdToTiming.set(pipelineId, {});
18
- }
19
- const timingInfo = pipelineIdToTiming.get(pipelineId);
20
- timingInfo[timingKey] = timeStamp;
21
- }
22
- function sendTimingResult(pipelineId, timingFlags, isFp) {
23
- const timingInfo = (pipelineId ? pipelineIdToTiming.get(pipelineId) : undefined) ?? {};
24
- if (!pipelineId)
25
- commonTimingFlags = commonTimingFlags.concat(timingFlags);
26
- else
27
- timingFlags = timingFlags.concat(commonTimingFlags);
28
- backgroundThreadRpc.invoke(postTimingResult, [
29
- pipelineId,
30
- timingInfo,
31
- timingFlags,
32
- isFp ? setupTiming : undefined,
33
- ]);
34
- rootDom.dispatchEvent(new CustomEvent('timing', {
35
- detail: isFp ? setupTiming : timingInfo,
36
- bubbles: true,
37
- cancelable: true,
38
- composed: true,
39
- }));
40
- if (pipelineId) {
41
- pipelineIdToTiming.delete(pipelineId);
42
- }
43
- }
44
- mainThreadRpc.registerHandler(postTimingInfoFromMainThread, markTimingInternal);
45
- backgroundThreadRpc.registerHandler(postTimingInfoFromBackgroundThread, markTimingInternal);
46
- return {
47
- markTimingInternal,
48
- sendTimingResult,
49
- };
50
- }
51
- //# sourceMappingURL=bootTimingSystem.js.map
@@ -1,2 +0,0 @@
1
- import type { Rpc } from '@lynx-js/web-worker-rpc';
2
- export declare function createExposureService(rpc: Rpc, rootDom: Element): void;
@@ -1,55 +0,0 @@
1
- import { lynxUniqueIdAttribute, postExposureEndpoint, switchExposureService, } from '@lynx-js/web-constants';
2
- import { createCrossThreadEvent } from '../../utils/createCrossThreadEvent.js';
3
- export function createExposureService(rpc, rootDom) {
4
- let working = true;
5
- let exposureCache = [];
6
- let disexposureCache = [];
7
- const onScreen = new Map();
8
- async function exposureEventHandler(ev) {
9
- const exposureEvent = createCrossThreadEvent(ev);
10
- exposureEvent.detail['unique-id'] = parseFloat(ev.target.getAttribute(lynxUniqueIdAttribute));
11
- const exposureID = exposureEvent.exposureID;
12
- if (ev.type === 'exposure') {
13
- exposureCache.push(exposureEvent);
14
- onScreen.set(exposureID, exposureEvent);
15
- }
16
- else {
17
- disexposureCache.push(exposureEvent);
18
- onScreen.delete(exposureID);
19
- }
20
- }
21
- setInterval(() => {
22
- if (exposureCache.length > 0 || disexposureCache.length > 0) {
23
- const currentExposure = exposureCache;
24
- const currentDisexposure = disexposureCache;
25
- exposureCache = [];
26
- disexposureCache = [];
27
- rpc.invoke(postExposureEndpoint, [{
28
- exposures: currentExposure,
29
- disExposures: currentDisexposure,
30
- }]);
31
- }
32
- }, 1000 / 20);
33
- rootDom.addEventListener('exposure', exposureEventHandler, { passive: true });
34
- rootDom.addEventListener('disexposure', exposureEventHandler, {
35
- passive: true,
36
- });
37
- rpc.registerHandler(switchExposureService, async (enable, sendEvent) => {
38
- if (enable && !working) {
39
- // send all onScreen info
40
- rpc.invoke(postExposureEndpoint, [{
41
- exposures: [...onScreen.values()],
42
- disExposures: [],
43
- }]);
44
- }
45
- else if (!enable && working) {
46
- if (sendEvent) {
47
- rpc.invoke(postExposureEndpoint, [{
48
- exposures: [],
49
- disExposures: [...onScreen.values()],
50
- }]);
51
- }
52
- }
53
- });
54
- }
55
- //# sourceMappingURL=createExposureService.js.map
@@ -1,12 +0,0 @@
1
- import type { ElementOperation } from '@lynx-js/web-constants';
2
- import type { RuntimePropertyOnElement } from '../types/RuntimePropertyOnElement.js';
3
- export declare function decodeElementOperation<T extends HTMLElement & RuntimePropertyOnElement>(operations: ElementOperation[], options: {
4
- uniqueIdToElement: (WeakRef<T> | undefined)[];
5
- uniqueIdToCssInJsRule: (WeakRef<CSSStyleRule> | undefined)[];
6
- createElementImpl: (tag: string) => T;
7
- createStyleRuleImpl: (uniqueId: number, initialStyle: string) => CSSStyleRule;
8
- eventHandler: {
9
- mtsHandler: (event: Event) => void;
10
- btsHandler: (event: Event) => void;
11
- };
12
- }): T | undefined;
@@ -1,175 +0,0 @@
1
- // Copyright 2023 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 { cssIdAttribute, lynxUniqueIdAttribute, OperationType, lynxRuntimeValue, LynxEventNameToW3cByTagName, LynxEventNameToW3cCommon, W3cEventNameToLynx, __lynx_timing_flag, lynxTagAttribute, } from '@lynx-js/web-constants';
5
- function getElement(uniqueId, uniqueIdToElement) {
6
- const element = uniqueIdToElement[uniqueId]?.deref();
7
- if (element) {
8
- return element;
9
- }
10
- else {
11
- throw new Error(`[lynx-web] cannot find element with uniqueId: ${uniqueId}`);
12
- }
13
- }
14
- function createElement(tag, uniqueId, uniqueIdToElement, createElementImpl) {
15
- const current = uniqueIdToElement[uniqueId]?.deref();
16
- if (current) {
17
- throw new Error(`[lynx-web] uniqueid is occupied: cannot create new element ${tag} with uniqueId: ${uniqueId}`);
18
- }
19
- const element = createElementImpl(tag);
20
- element.setAttribute(lynxUniqueIdAttribute, uniqueId.toString());
21
- uniqueIdToElement[uniqueId] = new WeakRef(element);
22
- return element;
23
- }
24
- function handleHtmlEvent(event) {
25
- const currentTarget = event.currentTarget;
26
- if (!currentTarget)
27
- return;
28
- const { eventHandler, } = currentTarget[lynxRuntimeValue];
29
- const lynxEventName = W3cEventNameToLynx[event.type] ?? event.type;
30
- const eventHandlerInfo = eventHandler[lynxEventName];
31
- if (eventHandlerInfo) {
32
- const { type: eventType, handler } = eventHandlerInfo;
33
- const isCatch = eventType === 'catchEvent' || eventType === 'capture-catch';
34
- handler(event);
35
- if (isCatch) {
36
- event.stopPropagation();
37
- }
38
- }
39
- }
40
- export function decodeElementOperation(operations, options) {
41
- const { uniqueIdToElement, uniqueIdToCssInJsRule, createElementImpl, createStyleRuleImpl, eventHandler, } = options;
42
- let pageElement;
43
- for (const op of operations) {
44
- if (op.type === OperationType.Create) {
45
- const element = createElement(op.tag, op.uid, uniqueIdToElement, createElementImpl);
46
- if (typeof op.cssId === 'number') {
47
- element.setAttribute(cssIdAttribute, op.cssId.toString());
48
- }
49
- }
50
- else {
51
- const target = getElement(op.uid, uniqueIdToElement);
52
- switch (op.type) {
53
- case OperationType.Append:
54
- {
55
- const children = op.cid.map(id => getElement(id, uniqueIdToElement));
56
- target.append(...children);
57
- }
58
- break;
59
- case OperationType.InsertBefore:
60
- {
61
- const child = getElement(op.cid, uniqueIdToElement);
62
- const ref = op.ref ? getElement(op.ref, uniqueIdToElement) : null;
63
- target.insertBefore(child, ref);
64
- }
65
- break;
66
- case OperationType.Remove:
67
- {
68
- for (const kidId of op.cid) {
69
- const kid = getElement(kidId, uniqueIdToElement);
70
- target.removeChild(kid);
71
- }
72
- }
73
- break;
74
- case OperationType.Replace:
75
- {
76
- const newElements = op.nid.map(id => getElement(id, uniqueIdToElement));
77
- target.replaceWith(...newElements);
78
- }
79
- break;
80
- case OperationType.SetAttribute:
81
- {
82
- if (op.value === null) {
83
- target.removeAttribute(op.key);
84
- }
85
- else {
86
- target.setAttribute(op.key, op.value);
87
- if (op.key === lynxTagAttribute && op.value === 'page') {
88
- pageElement = target;
89
- }
90
- }
91
- }
92
- break;
93
- case OperationType.SwapElement:
94
- {
95
- const targetB = getElement(op.tid, uniqueIdToElement);
96
- const temp = document.createElement('div');
97
- target.replaceWith(temp);
98
- targetB.replaceWith(target);
99
- temp.replaceWith(targetB);
100
- }
101
- break;
102
- case OperationType.SetProperty:
103
- target[lynxRuntimeValue][op.key] = op.value;
104
- if (op.key === 'dataset') {
105
- if (op.value) {
106
- for (const [key, value] of Object.entries(op.value)) {
107
- if (value) {
108
- target.setAttribute(`data-${key}`, value.toString());
109
- }
110
- else {
111
- target.removeAttribute(`data-${key}`);
112
- }
113
- }
114
- }
115
- else {
116
- target[lynxRuntimeValue]['dataset'] = {};
117
- }
118
- }
119
- break;
120
- case OperationType.SetDatasetProperty:
121
- target[lynxRuntimeValue].dataset[op.key] = op.value;
122
- if (op.value) {
123
- target.setAttribute(`data-${op.key}`, op.value.toString());
124
- }
125
- else {
126
- target.removeAttribute(`data-${op.key}`);
127
- }
128
- break;
129
- case OperationType.RegisterEventHandler:
130
- const isMtsHandler = op.hname === null;
131
- const lynxEventName = op.ename.toLowerCase();
132
- const htmlEventName = LynxEventNameToW3cByTagName[target.tagName]?.[lynxEventName]
133
- ?? LynxEventNameToW3cCommon[lynxEventName] ?? lynxEventName;
134
- const currentHandlerInfo = target[lynxRuntimeValue].eventHandler[lynxEventName];
135
- if (currentHandlerInfo) {
136
- target.removeEventListener(htmlEventName, handleHtmlEvent);
137
- }
138
- const isCaptureEvent = op.eventType === 'capture-bind'
139
- || op.eventType === 'capture-catch';
140
- if (op.hname === undefined) {
141
- target[lynxRuntimeValue].eventHandler[lynxEventName] = undefined;
142
- }
143
- else {
144
- target.addEventListener(htmlEventName, handleHtmlEvent, {
145
- passive: true,
146
- capture: isCaptureEvent,
147
- });
148
- target[lynxRuntimeValue].eventHandler[lynxEventName] = {
149
- type: op.eventType,
150
- handler: isMtsHandler
151
- ? eventHandler.mtsHandler
152
- : eventHandler.btsHandler,
153
- hname: op.hname ?? '',
154
- };
155
- }
156
- break;
157
- case OperationType.SetStyleProperty:
158
- target.style.setProperty(op.key, op.value, op.im ? '!important' : undefined);
159
- break;
160
- case OperationType.UpdateCssInJs:
161
- let rule = uniqueIdToCssInJsRule[op.uid]?.deref();
162
- if (rule) {
163
- rule.style.cssText = op.classStyleStr;
164
- }
165
- else {
166
- rule = createStyleRuleImpl(op.uid, op.classStyleStr);
167
- uniqueIdToCssInJsRule[op.uid] = new WeakRef(rule);
168
- }
169
- break;
170
- }
171
- }
172
- }
173
- return pageElement;
174
- }
175
- //# sourceMappingURL=decodeElementOperation.js.map
@@ -1,2 +0,0 @@
1
- import { type LynxCrossThreadEvent } from '@lynx-js/web-constants';
2
- export declare function createCrossThreadEvent(domEvent: Event): LynxCrossThreadEvent;
@@ -1,43 +0,0 @@
1
- // Copyright 2023 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 { lynxRuntimeValue, lynxUniqueIdAttribute, W3cEventNameToLynx, } from '@lynx-js/web-constants';
5
- export function createCrossThreadEvent(domEvent) {
6
- const targetElement = domEvent.target;
7
- const currentTargetElement = domEvent
8
- .currentTarget;
9
- const type = domEvent.type;
10
- const params = {};
11
- if (type.match(/^transition/)) {
12
- Object.assign(params, {
13
- 'animation_type': 'keyframe-animation',
14
- 'animation_name': domEvent.propertyName,
15
- new_animator: true, // we support the new_animator only
16
- });
17
- }
18
- else if (type.match(/animation/)) {
19
- Object.assign(params, {
20
- 'animation_type': 'keyframe-animation',
21
- 'animation_name': domEvent.animationName,
22
- new_animator: true, // we support the new_animator only
23
- });
24
- }
25
- return {
26
- type: W3cEventNameToLynx[type] ?? type,
27
- timestamp: domEvent.timeStamp,
28
- target: {
29
- id: targetElement.id,
30
- dataset: targetElement[lynxRuntimeValue].dataset,
31
- uniqueId: parseFloat(targetElement.getAttribute(lynxUniqueIdAttribute)),
32
- },
33
- currentTarget: {
34
- id: currentTargetElement.id,
35
- dataset: currentTargetElement[lynxRuntimeValue]?.dataset ?? {},
36
- uniqueId: parseFloat(currentTargetElement.getAttribute(lynxUniqueIdAttribute)),
37
- },
38
- // @ts-expect-error
39
- detail: domEvent.detail ?? {},
40
- params,
41
- };
42
- }
43
- //# sourceMappingURL=createCrossThreadEvent.js.map