@lynx-js/web-core 0.7.0 → 0.8.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,163 @@
1
1
  # @lynx-js/web-core
2
2
 
3
+ ## 0.8.0
4
+
5
+ ### Minor Changes
6
+
7
+ - refactor: remove web-elements/lazy and loadNewTag ([#123](https://github.com/lynx-family/lynx-stack/pull/123))
8
+
9
+ - remove @lynx-js/web-elements/lazy
10
+ - remove loadElement
11
+ - remove loadNewTag callback
12
+
13
+ **This is a breaking change**
14
+
15
+ Now we removed the default lazy loading preinstalled in web-core
16
+
17
+ Please add the following statement in your web project
18
+
19
+ ```
20
+ import "@lynx-js/web-elements/all";
21
+ ```
22
+
23
+ - feat: use shadowroot to isolate one lynx-view ([#198](https://github.com/lynx-family/lynx-stack/pull/198))
24
+
25
+ Before this commit, we have been detecting if current browser supports the `@scope` rule.
26
+ This allows us to scope one lynx-view's styles.
27
+
28
+ After this commit we always create a shadowroot to scope then.
29
+
30
+ Also for the new shadowroot pattern, we add a new **attribute** `inject-head-links`.
31
+ By default, we will iterate all `<link rel="stylesheet">` in the `<head>`, and use `@import url()` to import them inside the shadowroot.
32
+ Developers could add a `inject-head-links="false"` to disable this behavior.
33
+
34
+ - feat: never add the x-enable-xx-event attributes ([#157](https://github.com/lynx-family/lynx-stack/pull/157))
35
+
36
+ After this commit, we update the reqirement of the version of `@lynx-js/web-elements` to `>=0.3.1`
37
+
38
+ ### Patch Changes
39
+
40
+ - feat: add pixelRatio of SystemInfo, now you can use `SystemInfo.pixelRatio`. ([#150](https://github.com/lynx-family/lynx-stack/pull/150))
41
+
42
+ - Improve LynxView resize observer cleanup ([#124](https://github.com/lynx-family/lynx-stack/pull/124))
43
+
44
+ - feat: add two prop of lynx-view about `napiLoader`: ([#173](https://github.com/lynx-family/lynx-stack/pull/173))
45
+
46
+ - `napiModulesMap`: [optional] the napiModule which is called in lynx-core. key is module-name, value is esm url.
47
+
48
+ - `onNapiModulesCall`: [optional] the NapiModule value handler.
49
+
50
+ **Warning:** This is the internal implementation of `@lynx-js/lynx-core`. In most cases, this API is not required for projects.
51
+
52
+ 1. The `napiModulesMap` value should be a esm url which export default a function with two parameters:
53
+
54
+ - `NapiModules`: oriented `napiModulesMap`, which you can use to call other Napi-Modules
55
+
56
+ - `NapiModulesCall`: trigger `onNapiModulesCall`
57
+
58
+ example:
59
+
60
+ ```js
61
+ const color_environment = URL.createObjectURL(
62
+ new Blob(
63
+ [
64
+ `export default function(NapiModules, NapiModulesCall) {
65
+ return {
66
+ getColor() {
67
+ NapiModules.color_methods.getColor({ color: 'green' }, color => {
68
+ console.log(color);
69
+ });
70
+ },
71
+ ColorEngine: class ColorEngine {
72
+ getColor(name) {
73
+ NapiModules.color_methods.getColor({ color: 'green' }, color => {
74
+ console.log(color);
75
+ });
76
+ }
77
+ },
78
+ };
79
+ };`,
80
+ ],
81
+ { type: 'text/javascript' },
82
+ ),
83
+ );
84
+
85
+ const color_methods = URL.createObjectURL(
86
+ new Blob(
87
+ [
88
+ `export default function(NapiModules, NapiModulesCall) {
89
+ return {
90
+ async getColor(data, callback) {
91
+ const color = await NapiModulesCall('getColor', data);
92
+ callback(color);
93
+ },
94
+ };
95
+ };`,
96
+ ],
97
+ { type: 'text/javascript' },
98
+ ),
99
+ );
100
+
101
+ lynxView.napiModuleMap = {
102
+ color_environment: color_environment,
103
+ color_methods: color_methods,
104
+ };
105
+ ```
106
+
107
+ 2. The `onNapiModulesCall` function has three parameters:
108
+
109
+ - `name`: the first parameter of `NapiModulesCall`, the function name
110
+ - `data`: the second parameter of `NapiModulesCall`, data
111
+ - `moduleName`: the module-name of the called napi-module
112
+
113
+ ```js
114
+ lynxView.onNapiModulesCall = (name, data, moduleName) => {
115
+ if (name === 'getColor' && moduleName === 'color_methods') {
116
+ return data.color;
117
+ }
118
+ };
119
+ ```
120
+
121
+ - Updated dependencies [[`eab1328`](https://github.com/lynx-family/lynx-stack/commit/eab1328a83797fc903255c984d9f39537b9138b9), [`e9e8370`](https://github.com/lynx-family/lynx-stack/commit/e9e8370e070a50cbf65a4ebc46c2e37ea1e0be40), [`ec4e1ce`](https://github.com/lynx-family/lynx-stack/commit/ec4e1ce0d7612d6c0701792a46c78cd52130bad4), [`f0a717c`](https://github.com/lynx-family/lynx-stack/commit/f0a717c630700e16ab0af7f1fe370fd60ac75b30)]:
122
+ - @lynx-js/web-worker-runtime@0.8.0
123
+ - @lynx-js/web-constants@0.8.0
124
+ - @lynx-js/web-worker-rpc@0.8.0
125
+
126
+ ## 0.7.1
127
+
128
+ ### Patch Changes
129
+
130
+ - Support NPM provenance. ([#30](https://github.com/lynx-family/lynx-stack/pull/30))
131
+
132
+ - fix: some valus should be updateable by global scope ([#130](https://github.com/lynx-family/lynx-stack/pull/130))
133
+
134
+ Now we add an allowlist to allow some identifiers could be updated by globalThis.
135
+
136
+ For those values in the allowlist:
137
+
138
+ ```
139
+ globalThis.foo = 'xx';
140
+ console.log(foo); //'xx'
141
+ ```
142
+
143
+ - refactor: isolate the globalThis in mts ([#90](https://github.com/lynx-family/lynx-stack/pull/90))
144
+
145
+ After this commit, developers' mts code won't be able to access the globalThis
146
+
147
+ The following usage will NOT work
148
+
149
+ ```
150
+ globalThis.foo = () =>{};
151
+ foo();//crash
152
+ ```
153
+
154
+ - refractor: improve some internal logic for element creating in MTS ([#71](https://github.com/lynx-family/lynx-stack/pull/71))
155
+
156
+ - Updated dependencies [[`c617453`](https://github.com/lynx-family/lynx-stack/commit/c617453aea967aba702967deb2916b5c883f03bb), [`2044571`](https://github.com/lynx-family/lynx-stack/commit/204457166531dae6e9f653db56b14187553b7666), [`7da7601`](https://github.com/lynx-family/lynx-stack/commit/7da7601f00407970c485046ad73eeb8534aaa4f6)]:
157
+ - @lynx-js/web-worker-runtime@0.7.1
158
+ - @lynx-js/web-worker-rpc@0.7.1
159
+ - @lynx-js/web-constants@0.7.1
160
+
3
161
  ## 0.7.0
4
162
 
5
163
  ### Minor Changes
@@ -1,4 +1,7 @@
1
- import { type Cloneable, type NativeModulesCall, type UpdateDataType } from '@lynx-js/web-constants';
1
+ import { type Cloneable, type NapiModulesCall, type NapiModulesMap, type NativeModulesCall, type UpdateDataType } from '@lynx-js/web-constants';
2
+ /**
3
+ * Based on our experiences, these elements are almost used in all lynx cards.
4
+ */
2
5
  /**
3
6
  * @param {string} url [required] The url of the entry of your Lynx card
4
7
  * @param {Cloneable} globalProps [optional] The globalProps value of this Lynx card
@@ -8,6 +11,9 @@ import { type Cloneable, type NativeModulesCall, type UpdateDataType } from '@ly
8
11
  * @param {INativeModulesCall} onNativeModulesCall [optional] the NativeModules value handler. Arguments will be cached before this property is assigned.
9
12
  * @param {"auto" | null} height [optional] set it to "auto" for height auto-sizing
10
13
  * @param {"auto" | null} width [optional] set it to "auto" for width auto-sizing
14
+ * @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.
16
+ * @param {"false" | "true" | null} injectHeadLinks [optional] @default true set it to "false" to disable injecting the <link href="" ref="stylesheet"> styles into shadowroot
11
17
  *
12
18
  * @property entryId the currently Lynx view entryId.
13
19
  *
@@ -85,6 +91,18 @@ export declare class LynxView extends HTMLElement {
85
91
  */
86
92
  get nativeModulesUrl(): string | undefined;
87
93
  set nativeModulesUrl(val: string);
94
+ /**
95
+ * @param
96
+ * @property
97
+ */
98
+ get napiModulesMap(): NapiModulesMap | undefined;
99
+ set napiModulesMap(map: NapiModulesMap);
100
+ /**
101
+ * @param
102
+ * @property
103
+ */
104
+ get onNapiModulesCall(): NapiModulesCall | undefined;
105
+ set onNapiModulesCall(handler: NapiModulesCall);
88
106
  /**
89
107
  * @public
90
108
  * "auto" for auto calculated height
@@ -134,4 +152,5 @@ export declare class LynxView extends HTMLElement {
134
152
  * @private
135
153
  */
136
154
  connectedCallback(): void;
155
+ private cleanupResizeObserver;
137
156
  }
@@ -3,15 +3,10 @@
3
3
  // LICENSE file in the root directory of this source tree.
4
4
  import { createLynxView, } from './createLynxView.js';
5
5
  import { cardIdAttribute, lynxViewEntryIdPrefix, lynxViewRootDomId, } from '@lynx-js/web-constants';
6
- import { loadElement } from '@lynx-js/web-elements/lazy';
6
+ import { inShadowRootStyles } from './inShadowRootStyles.js';
7
7
  /**
8
8
  * Based on our experiences, these elements are almost used in all lynx cards.
9
9
  */
10
- loadElement('lynx-wrapper');
11
- loadElement('x-view');
12
- loadElement('x-text');
13
- loadElement('x-image');
14
- loadElement('scroll-view');
15
10
  /**
16
11
  * @param {string} url [required] The url of the entry of your Lynx card
17
12
  * @param {Cloneable} globalProps [optional] The globalProps value of this Lynx card
@@ -21,6 +16,9 @@ loadElement('scroll-view');
21
16
  * @param {INativeModulesCall} onNativeModulesCall [optional] the NativeModules value handler. Arguments will be cached before this property is assigned.
22
17
  * @param {"auto" | null} height [optional] set it to "auto" for height auto-sizing
23
18
  * @param {"auto" | null} width [optional] set it to "auto" for width auto-sizing
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.
21
+ * @param {"false" | "true" | null} injectHeadLinks [optional] @default true set it to "false" to disable injecting the <link href="" ref="stylesheet"> styles into shadowroot
24
22
  *
25
23
  * @property entryId the currently Lynx view entryId.
26
24
  *
@@ -159,6 +157,28 @@ export class LynxView extends HTMLElement {
159
157
  set nativeModulesUrl(val) {
160
158
  this.#nativeModulesUrl = val;
161
159
  }
160
+ #napiModulesMap = {};
161
+ /**
162
+ * @param
163
+ * @property
164
+ */
165
+ get napiModulesMap() {
166
+ return this.#napiModulesMap;
167
+ }
168
+ set napiModulesMap(map) {
169
+ this.#napiModulesMap = map;
170
+ }
171
+ #onNapiModulesCall;
172
+ /**
173
+ * @param
174
+ * @property
175
+ */
176
+ get onNapiModulesCall() {
177
+ return this.#onNapiModulesCall;
178
+ }
179
+ set onNapiModulesCall(handler) {
180
+ this.#onNapiModulesCall = handler;
181
+ }
162
182
  #autoHeight = false;
163
183
  #autoWidth = false;
164
184
  #currentWidth = 0;
@@ -281,12 +301,15 @@ export class LynxView extends HTMLElement {
281
301
  * @private
282
302
  */
283
303
  disconnectedCallback() {
304
+ this.cleanupResizeObserver();
284
305
  if (this.#instance) {
285
- this.#instance.resizeObserver?.disconnect();
286
306
  this.#instance.lynxView.dispose();
287
307
  this.#instance.rootDom.remove();
288
308
  }
289
309
  this.#instance = undefined;
310
+ if (this.shadowRoot) {
311
+ this.shadowRoot.innerHTML = '';
312
+ }
290
313
  }
291
314
  /**
292
315
  * @private the flag to group all changes into one render operation
@@ -322,8 +345,8 @@ export class LynxView extends HTMLElement {
322
345
  initData: this.#initData,
323
346
  overrideLynxTagToHTMLTagMap: this.#overrideLynxTagToHTMLTagMap,
324
347
  nativeModulesUrl: this.#nativeModulesUrl,
348
+ napiModulesMap: this.#napiModulesMap,
325
349
  callbacks: {
326
- loadNewTag: loadElement,
327
350
  nativeModulesCall: (...args) => {
328
351
  if (this.#onNativeModulesCall) {
329
352
  return this.#onNativeModulesCall(...args);
@@ -335,6 +358,9 @@ export class LynxView extends HTMLElement {
335
358
  this.#cachedNativeModulesCall = [args];
336
359
  }
337
360
  },
361
+ napiModulesCall: (...args) => {
362
+ return this.#onNapiModulesCall?.(...args);
363
+ },
338
364
  onError: () => {
339
365
  this.dispatchEvent(new CustomEvent('error', {
340
366
  detail: commonEventDetail,
@@ -347,7 +373,21 @@ export class LynxView extends HTMLElement {
347
373
  rootDom,
348
374
  };
349
375
  this.#handleAutoSize();
350
- this.append(rootDom);
376
+ if (!this.shadowRoot) {
377
+ this.attachShadow({ mode: 'open' });
378
+ }
379
+ const styleElement = document.createElement('style');
380
+ this.shadowRoot.append(styleElement);
381
+ const styleSheet = styleElement.sheet;
382
+ styleSheet.insertRule(inShadowRootStyles);
383
+ const injectHeadLinks = this.getAttribute('inject-head-links') !== 'false';
384
+ if (injectHeadLinks) {
385
+ document.head.querySelectorAll('link[rel="stylesheet"]').forEach((linkElement) => {
386
+ const href = linkElement.href;
387
+ styleSheet.insertRule(`@import url("${href}");`);
388
+ });
389
+ }
390
+ this.shadowRoot.append(rootDom);
351
391
  }
352
392
  });
353
393
  }
@@ -358,6 +398,12 @@ export class LynxView extends HTMLElement {
358
398
  connectedCallback() {
359
399
  this.#render();
360
400
  }
401
+ cleanupResizeObserver() {
402
+ if (this.#instance?.resizeObserver) {
403
+ this.#instance.resizeObserver.disconnect();
404
+ this.#instance.resizeObserver = undefined;
405
+ }
406
+ }
361
407
  }
362
408
  if (customElements.get(LynxView.tag)) {
363
409
  console.warn(`[${LynxView.tag}] has already been defined`);
@@ -1,4 +1,4 @@
1
- import type { Cloneable, UpdateDataType } from '@lynx-js/web-constants';
1
+ import type { Cloneable, NapiModulesMap, UpdateDataType } from '@lynx-js/web-constants';
2
2
  import { startUIThread } from '../uiThread/startUIThread.js';
3
3
  export interface LynxViewConfigs {
4
4
  templateUrl: string;
@@ -9,6 +9,7 @@ export interface LynxViewConfigs {
9
9
  callbacks: Parameters<typeof startUIThread>[3];
10
10
  overrideLynxTagToHTMLTagMap?: Record<string, string>;
11
11
  nativeModulesUrl: string | undefined;
12
+ napiModulesMap: NapiModulesMap;
12
13
  }
13
14
  export interface LynxView {
14
15
  updateData(data: Cloneable, updateDataType: UpdateDataType, callback?: () => void): void;
@@ -2,16 +2,14 @@
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 { startUIThread } from '../uiThread/startUIThread.js';
5
- import { supportAtScope } from '../utils/browser.js';
6
5
  export function createLynxView(configs) {
7
- const { rootDom, callbacks, templateUrl, globalProps, entryId, initData, overrideLynxTagToHTMLTagMap, nativeModulesUrl, } = configs;
6
+ const { rootDom, callbacks, templateUrl, globalProps, entryId, initData, overrideLynxTagToHTMLTagMap, nativeModulesUrl, napiModulesMap, } = configs;
8
7
  return startUIThread(templateUrl, {
9
8
  initData,
10
9
  globalProps,
11
10
  entryId,
12
- browserConfig: {
13
- supportAtScope,
14
- },
11
+ napiModulesMap,
12
+ browserConfig: {},
15
13
  }, rootDom, callbacks, overrideLynxTagToHTMLTagMap, nativeModulesUrl);
16
14
  }
17
15
  //# sourceMappingURL=createLynxView.js.map
@@ -0,0 +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";
@@ -0,0 +1,7 @@
1
+ export const inShadowRootStyles = `
2
+ [lynx-default-display-linear="false"] * {
3
+ --lynx-display: flex;
4
+ --lynx-display-toggle: var(--lynx-display-flex);
5
+ }
6
+ `;
7
+ //# sourceMappingURL=inShadowRootStyles.js.map
@@ -27,6 +27,7 @@ function createMainWorker() {
27
27
  mode: 'main',
28
28
  toUIThread: channelToMainThread.port2,
29
29
  toPeerThread: channelMainThreadWithBackground.port1,
30
+ pixelRatio: window.devicePixelRatio,
30
31
  };
31
32
  mainThreadWorker.postMessage(mainThreadMessage, [
32
33
  channelToMainThread.port2,
@@ -49,6 +50,7 @@ function createBackgroundWorker(channelMainThreadWithBackground) {
49
50
  mode: 'background',
50
51
  toUIThread: channelToBackground.port2,
51
52
  toPeerThread: channelMainThreadWithBackground.port2,
53
+ pixelRatio: window.devicePixelRatio,
52
54
  };
53
55
  backgroundThreadWorker.postMessage(backgroundThreadMessage, [
54
56
  channelToBackground.port2,
@@ -35,6 +35,7 @@ export function bootTimingSystem(mainThreadRpc, backgroundThreadRpc, rootDom) {
35
35
  detail: isFp ? setupTiming : timingInfo,
36
36
  bubbles: true,
37
37
  cancelable: true,
38
+ composed: true,
38
39
  }));
39
40
  if (pipelineId) {
40
41
  pipelineIdToTiming.delete(pipelineId);
@@ -7,7 +7,6 @@ export declare function registerFlushElementTreeHandler(mainThreadRpc: Rpc, endp
7
7
  backgroundRpc: Rpc;
8
8
  rootDom: HTMLElement;
9
9
  entryId: string;
10
- currentLoadingTags: Promise<void>[];
11
10
  }, onCommit: (info: {
12
11
  pipelineId: string | undefined;
13
12
  timingFlags: string[];
@@ -5,7 +5,6 @@ import { cardIdAttribute, componentIdAttribute, lynxDefaultDisplayLinearAttribut
5
5
  import { decodeElementOperation } from '../decodeElementOperation.js';
6
6
  import { getElementTag } from '../getElementTag.js';
7
7
  import { createCrossThreadEvent } from '../../utils/createCrossThreadEvent.js';
8
- import { isWebkit, supportAtScope } from '../../utils/browser.js';
9
8
  function applyPageAttributes(page, pageConfig, entryId) {
10
9
  page.setAttribute(cardIdAttribute, entryId);
11
10
  if (pageConfig.defaultDisplayLinear === false) {
@@ -13,18 +12,13 @@ function applyPageAttributes(page, pageConfig, entryId) {
13
12
  }
14
13
  }
15
14
  export function registerFlushElementTreeHandler(mainThreadRpc, endpoint, options, onCommit, markTimingInternal) {
16
- const { pageConfig, overrideTagMap, backgroundRpc, rootDom, entryId, currentLoadingTags, } = options;
15
+ const { pageConfig, overrideTagMap, backgroundRpc, rootDom, entryId, } = options;
17
16
  const uniqueIdToElement = [];
18
17
  const uniqueIdToCssInJsRule = [];
19
18
  const rootStyleElementForCssInJs = document.createElement('style');
20
19
  if (!pageConfig.enableCSSSelector) {
21
- rootStyleElementForCssInJs.innerHTML = `/* enableCSSSelector: false */ ${supportAtScope && !isWebkit ? '@scope { :scope{} }' : ''}`;
22
- // safari testing needs this :scope{} see: https://github.com/microsoft/playwright/issues/33647
23
- // for 18.2 the :scope{} placeholder dose not work neither. we fired an issue for this https://bugs.webkit.org/show_bug.cgi?id=285130
24
20
  rootDom.append(rootStyleElementForCssInJs);
25
21
  }
26
- // dom must connected to get the sheet property
27
- const rootScopeRule = rootStyleElementForCssInJs?.sheet?.cssRules[0];
28
22
  const createElementImpl = (tag) => {
29
23
  const htmlTag = getElementTag(tag, overrideTagMap);
30
24
  const element = document.createElement(htmlTag);
@@ -36,14 +30,8 @@ export function registerFlushElementTreeHandler(mainThreadRpc, endpoint, options
36
30
  };
37
31
  const createStyleRuleImpl = (uniqueId, initialStyle) => {
38
32
  const commonStyleSheetText = `[${lynxUniqueIdAttribute}="${uniqueId.toString()}"]{${initialStyle}}`;
39
- if (rootScopeRule) {
40
- const idx = rootScopeRule.insertRule(commonStyleSheetText);
41
- return rootScopeRule.cssRules[idx];
42
- }
43
- else {
44
- const idx = rootStyleElementForCssInJs.sheet.insertRule(`[${cardIdAttribute}="${entryId}"] ${commonStyleSheetText}`);
45
- return rootStyleElementForCssInJs.sheet.cssRules[idx];
46
- }
33
+ const idx = rootStyleElementForCssInJs.sheet.insertRule(commonStyleSheetText);
34
+ return rootStyleElementForCssInJs.sheet.cssRules[idx];
47
35
  };
48
36
  const mtsHandler = (event) => {
49
37
  const crossThreadEvent = createCrossThreadEvent(event);
@@ -78,37 +66,35 @@ export function registerFlushElementTreeHandler(mainThreadRpc, endpoint, options
78
66
  const pipelineId = pipelineOptions?.pipelineID;
79
67
  const timingFlags = [];
80
68
  markTimingInternal('dispatch_start', pipelineId);
81
- Promise.all(currentLoadingTags).then(() => {
82
- markTimingInternal('layout_start', pipelineId);
83
- markTimingInternal('ui_operation_flush_start', pipelineId);
84
- const page = decodeElementOperation(operations, {
85
- timingFlags,
86
- uniqueIdToElement,
87
- uniqueIdToCssInJsRule,
88
- createElementImpl,
89
- createStyleRuleImpl,
90
- eventHandler: {
91
- mtsHandler,
92
- btsHandler,
93
- },
94
- });
95
- markTimingInternal('ui_operation_flush_end', pipelineId);
96
- const isFP = !!page;
97
- if (isFP) {
98
- // on FP
99
- const styleElement = document.createElement('style');
100
- styleElement.innerHTML = cardCss;
101
- rootDom.append(styleElement);
102
- rootDom.append(page);
103
- applyPageAttributes(page, pageConfig, entryId);
104
- }
105
- markTimingInternal('layout_end', pipelineId);
106
- markTimingInternal('dispatch_end', pipelineId);
107
- onCommit({
108
- pipelineId,
109
- timingFlags,
110
- isFP,
111
- });
69
+ markTimingInternal('layout_start', pipelineId);
70
+ markTimingInternal('ui_operation_flush_start', pipelineId);
71
+ const page = decodeElementOperation(operations, {
72
+ timingFlags,
73
+ uniqueIdToElement,
74
+ uniqueIdToCssInJsRule,
75
+ createElementImpl,
76
+ createStyleRuleImpl,
77
+ eventHandler: {
78
+ mtsHandler,
79
+ btsHandler,
80
+ },
81
+ });
82
+ markTimingInternal('ui_operation_flush_end', pipelineId);
83
+ const isFP = !!page;
84
+ if (isFP) {
85
+ // on FP
86
+ const styleElement = document.createElement('style');
87
+ styleElement.innerHTML = cardCss;
88
+ rootDom.append(styleElement);
89
+ rootDom.append(page);
90
+ applyPageAttributes(page, pageConfig, entryId);
91
+ }
92
+ markTimingInternal('layout_end', pipelineId);
93
+ markTimingInternal('dispatch_end', pipelineId);
94
+ onCommit({
95
+ pipelineId,
96
+ timingFlags,
97
+ isFP,
112
98
  });
113
99
  });
114
100
  return { uniqueIdToElement, uniqueIdToCssInJsRule };
@@ -0,0 +1,3 @@
1
+ import type { Rpc } from '@lynx-js/web-worker-rpc';
2
+ import { type NapiModulesCall } from '@lynx-js/web-constants';
3
+ export declare function registerNapiModulesCallHandler(rpc: Rpc, napiModulesCall: NapiModulesCall): void;
@@ -0,0 +1,5 @@
1
+ import { napiModulesCallEndpoint, } from '@lynx-js/web-constants';
2
+ export function registerNapiModulesCallHandler(rpc, napiModulesCall) {
3
+ rpc.registerHandler(napiModulesCallEndpoint, napiModulesCall);
4
+ }
5
+ //# sourceMappingURL=registerNapiModulesCallHandler.js.map
@@ -1,7 +1,7 @@
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 { cssIdAttribute, lynxTagAttribute, lynxUniqueIdAttribute, OperationType, lynxRuntimeValue, LynxEventNameToW3cByTagName, LynxEventNameToW3cCommon, W3cEventNameToLynx, parentComponentUniqueIdAttribute, __lynx_timing_flag, } from '@lynx-js/web-constants';
4
+ import { cssIdAttribute, lynxTagAttribute, lynxUniqueIdAttribute, OperationType, lynxRuntimeValue, LynxEventNameToW3cByTagName, LynxEventNameToW3cCommon, W3cEventNameToLynx, __lynx_timing_flag, } from '@lynx-js/web-constants';
5
5
  function getElement(uniqueId, uniqueIdToElement) {
6
6
  const element = uniqueIdToElement[uniqueId]?.deref();
7
7
  if (element) {
@@ -47,9 +47,6 @@ export function decodeElementOperation(operations, options) {
47
47
  if (typeof op.cssId === 'number') {
48
48
  element.setAttribute(cssIdAttribute, op.cssId.toString());
49
49
  }
50
- if (op.puid) {
51
- element.setAttribute(parentComponentUniqueIdAttribute, op.puid);
52
- }
53
50
  if (op.tag === 'page')
54
51
  pageElement = element;
55
52
  }
@@ -144,11 +141,9 @@ export function decodeElementOperation(operations, options) {
144
141
  const isCaptureEvent = op.eventType === 'capture-bind'
145
142
  || op.eventType === 'capture-catch';
146
143
  if (op.hname === undefined) {
147
- target.removeAttribute(`x-enable-${lynxEventName}-event`);
148
144
  target[lynxRuntimeValue].eventHandler[lynxEventName] = undefined;
149
145
  }
150
146
  else {
151
- target.setAttribute(`x-enable-${lynxEventName}-event`, '');
152
147
  target.addEventListener(htmlEventName, handleHtmlEvent, {
153
148
  passive: true,
154
149
  capture: isCaptureEvent,
@@ -1,7 +1,7 @@
1
1
  import type { LynxView } from '../apis/createLynxView.js';
2
- import { type MainThreadStartConfigs, type NativeModulesCall } from '@lynx-js/web-constants';
2
+ import { type MainThreadStartConfigs, type NapiModulesCall, type NativeModulesCall } from '@lynx-js/web-constants';
3
3
  export declare function startUIThread(templateUrl: string, configs: Omit<MainThreadStartConfigs, 'template'>, rootDom: HTMLElement, callbacks: {
4
- loadNewTag?: (tag: string) => void;
5
4
  nativeModulesCall: NativeModulesCall;
5
+ napiModulesCall: NapiModulesCall;
6
6
  onError?: () => void;
7
7
  }, overrideTagMap: Record<string, string> | undefined, nativeModulesUrl: string | undefined): LynxView;
@@ -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 { registerLoadNewTagHandler } from './crossThreadHandlers/registerLoadNewTagHandler.js';
5
4
  import { createExposureService } from './crossThreadHandlers/createExposureService.js';
6
5
  import { registerInvokeUIMethodHandler } from './crossThreadHandlers/registerInvokeUIMethodHandler.js';
7
6
  import { registerNativePropsHandler } from './crossThreadHandlers/registerSetNativePropsHandler.js';
@@ -13,13 +12,13 @@ import { createDispose } from './crossThreadHandlers/createDispose.js';
13
12
  import { bootTimingSystem } from './crossThreadHandlers/bootTimingSystem.js';
14
13
  import { registerTriggerComponentEventHandler } from './crossThreadHandlers/registerTriggerComponentEventHandler.js';
15
14
  import { registerSelectComponentHandler } from './crossThreadHandlers/registerSelectComponentHandler.js';
16
- import { flushElementTreeEndpoint, loadNewTagEndpoint, mainThreadChunkReadyEndpoint, mainThreadStartEndpoint, sendGlobalEventEndpoint, uiThreadFpReadyEndpoint, } from '@lynx-js/web-constants';
15
+ import { flushElementTreeEndpoint, mainThreadChunkReadyEndpoint, mainThreadStartEndpoint, sendGlobalEventEndpoint, uiThreadFpReadyEndpoint, } from '@lynx-js/web-constants';
17
16
  import { loadTemplate } from '../utils/loadTemplate.js';
18
17
  import { createUpdateData } from './crossThreadHandlers/createUpdateData.js';
18
+ import { registerNapiModulesCallHandler } from './crossThreadHandlers/registerNapiModulesCallHandler.js';
19
19
  export function startUIThread(templateUrl, configs, rootDom, callbacks, overrideTagMap = {}, nativeModulesUrl) {
20
20
  const createLynxStartTiming = performance.now() + performance.timeOrigin;
21
- const { entryId } = configs;
22
- const currentLoadingTags = [];
21
+ const { entryId, napiModulesMap } = configs;
23
22
  const { mainThreadRpc, backgroundRpc, terminateWorkers, } = bootWorkers();
24
23
  const sendGlobalEvent = backgroundRpc.createCall(sendGlobalEventEndpoint);
25
24
  const uiThreadFpReady = backgroundRpc.createCall(uiThreadFpReadyEndpoint);
@@ -33,18 +32,9 @@ export function startUIThread(templateUrl, configs, rootDom, callbacks, override
33
32
  ...configs,
34
33
  template,
35
34
  nativeModulesUrl,
35
+ napiModulesMap,
36
36
  });
37
37
  });
38
- registerLoadNewTagHandler(mainThreadRpc, loadNewTagEndpoint, (tag) => {
39
- if (callbacks.loadNewTag) {
40
- callbacks.loadNewTag(tag);
41
- }
42
- else {
43
- if (!customElements.get(tag) && tag.includes('-')) {
44
- throw new Error(`[lynx-web] cannot find custom element ${tag}`);
45
- }
46
- }
47
- }, overrideTagMap, currentLoadingTags);
48
38
  registerReportErrorHandler(mainThreadRpc, callbacks.onError);
49
39
  mainThreadRpc.registerHandler(mainThreadChunkReadyEndpoint, (mainChunkInfo) => {
50
40
  const { pageConfig } = mainChunkInfo;
@@ -54,7 +44,6 @@ export function startUIThread(templateUrl, configs, rootDom, callbacks, override
54
44
  backgroundRpc,
55
45
  rootDom,
56
46
  entryId,
57
- currentLoadingTags,
58
47
  }, (info) => {
59
48
  const { pipelineId, timingFlags, isFP } = info;
60
49
  if (isFP) {
@@ -69,6 +58,7 @@ export function startUIThread(templateUrl, configs, rootDom, callbacks, override
69
58
  }, markTimingInternal);
70
59
  });
71
60
  registerNativeModulesCallHandler(backgroundRpc, callbacks.nativeModulesCall);
61
+ registerNapiModulesCallHandler(backgroundRpc, callbacks.napiModulesCall);
72
62
  return {
73
63
  updateData: createUpdateData(mainThreadRpc, backgroundRpc),
74
64
  dispose: createDispose(backgroundRpc, terminateWorkers),
@@ -1,3 +1,2 @@
1
1
  export declare const isChromium: boolean;
2
2
  export declare const isWebkit: boolean;
3
- export declare const supportAtScope = true;
@@ -5,5 +5,4 @@ export const isWebkit = /\b(iPad|iPhone|iPod|OS X)\b/.test(UA)
5
5
  && /WebKit/.test(UA)
6
6
  // @ts-expect-error
7
7
  && !window.MSStream;
8
- export const supportAtScope = !!globalThis.CSSScopeRule;
9
8
  //# sourceMappingURL=browser.js.map
@@ -1,2 +1,2 @@
1
- import type { LynxTemplate } from '@lynx-js/web-constants';
1
+ import { type LynxTemplate } from '@lynx-js/web-constants';
2
2
  export declare function loadTemplate(url: string): Promise<LynxTemplate>;
@@ -1,25 +1,85 @@
1
+ import { globalMuteableVars } from '@lynx-js/web-constants';
1
2
  const TemplateCache = {};
2
3
  function createJsModuleUrl(content) {
3
4
  return URL.createObjectURL(new Blob([content], { type: 'text/javascript' }));
4
5
  }
5
- function generateJavascriptUrl(obj, injectVars, injectWithBind) {
6
+ function generateJavascriptUrl(obj, injectVars, injectWithBind, muteableVars) {
7
+ injectVars = injectVars.concat(muteableVars);
6
8
  return Object.fromEntries(Object.entries(obj).map(([name, content]) => {
7
9
  return [
8
10
  name,
9
- createJsModuleUrl(`globalThis.module.exports = function(lynx_runtime) {
10
- const module= {exports:{}};let exports = module.exports;
11
- var {${injectVars.join(',')}} = lynx_runtime;
12
- ${injectWithBind.map((nm) => `const ${nm} = lynx_runtime.${nm}?.bind(lynx_runtime)`).join(';')}
13
- var globDynamicComponentEntry = '__Card__';
14
- var {__globalProps} = lynx;
15
- ${content}
16
- return module.exports;}`),
11
+ createJsModuleUrl([
12
+ 'globalThis.module.exports = function(lynx_runtime) {',
13
+ 'const module= {exports:{}};let exports = module.exports;',
14
+ 'var {',
15
+ injectVars.join(','),
16
+ '} = lynx_runtime;',
17
+ ...injectWithBind.map((nm) => `const ${nm} = lynx_runtime.${nm}?.bind(lynx_runtime);`),
18
+ ';var globDynamicComponentEntry = \'__Card__\';',
19
+ 'var {__globalProps} = lynx;',
20
+ 'lynx_runtime._updateVars=()=>{',
21
+ ...muteableVars.map((nm) => `${nm} = lynx_runtime.__lynxGlobalBindingValues.${nm};`),
22
+ '};\n',
23
+ content,
24
+ '\n return module.exports;}',
25
+ ].join('')),
17
26
  ];
18
27
  }));
19
28
  }
20
29
  const mainThreadInjectVars = [
21
30
  'lynx',
22
31
  'globalThis',
32
+ '__AddConfig',
33
+ '__AddDataset',
34
+ '__GetAttributes',
35
+ '__GetComponentID',
36
+ '__GetDataByKey',
37
+ '__GetDataset',
38
+ '__GetElementConfig',
39
+ '__GetElementUniqueID',
40
+ '__GetID',
41
+ '__GetTag',
42
+ '__SetAttribute',
43
+ '__SetConfig',
44
+ '__SetDataset',
45
+ '__SetID',
46
+ '__UpdateComponentID',
47
+ '__GetConfig',
48
+ '__UpdateListCallbacks',
49
+ '__AppendElement',
50
+ '__ElementIsEqual',
51
+ '__FirstElement',
52
+ '__GetChildren',
53
+ '__GetParent',
54
+ '__InsertElementBefore',
55
+ '__LastElement',
56
+ '__NextElement',
57
+ '__RemoveElement',
58
+ '__ReplaceElement',
59
+ '__ReplaceElements',
60
+ '__SwapElement',
61
+ '__CreateComponent',
62
+ '__CreateElement',
63
+ '__CreatePage',
64
+ '__CreateView',
65
+ '__CreateText',
66
+ '__CreateRawText',
67
+ '__CreateImage',
68
+ '__CreateScrollView',
69
+ '__CreateWrapperElement',
70
+ '__CreateList',
71
+ '__AddEvent',
72
+ '__GetEvent',
73
+ '__GetEvents',
74
+ '__SetEvents',
75
+ '__AddClass',
76
+ '__SetClasses',
77
+ '__GetClasses',
78
+ '__AddInlineStyle',
79
+ '__SetInlineStyles',
80
+ '__SetCSSId',
81
+ '__OnLifecycleEvent',
82
+ '__FlushElementTree',
23
83
  ];
24
84
  const backgroundInjectVars = [
25
85
  'NativeModules',
@@ -40,8 +100,8 @@ export async function loadTemplate(url) {
40
100
  })).json());
41
101
  const decodedTemplate = {
42
102
  ...template,
43
- lepusCode: generateJavascriptUrl(template.lepusCode, mainThreadInjectVars, []),
44
- manifest: generateJavascriptUrl(template.manifest, backgroundInjectVars, backgroundInjectWithBind),
103
+ lepusCode: generateJavascriptUrl(template.lepusCode, mainThreadInjectVars, [], globalMuteableVars),
104
+ manifest: generateJavascriptUrl(template.manifest, backgroundInjectVars, backgroundInjectWithBind, []),
45
105
  };
46
106
  TemplateCache[url] = decodedTemplate;
47
107
  /**
package/index.css CHANGED
@@ -3,17 +3,13 @@
3
3
  // Licensed under the Apache License Version 2.0 that can be found in the
4
4
  // LICENSE file in the root directory of this source tree.
5
5
  */
6
- [lynx-default-display-linear="false"] * {
7
- --lynx-display: flex;
8
- --lynx-display-toggle: var(--lynx-display-flex);
9
- }
10
6
 
11
7
  lynx-view {
12
8
  contain: strict;
13
9
  display: flex;
14
10
  }
15
11
 
16
- lynx-view > #lynx-view-root {
12
+ lynx-view::part(lynx-view-root) {
17
13
  display: contents;
18
14
  width: 100%;
19
15
  height: 100%;
@@ -24,7 +20,7 @@ lynx-view[height="auto"] {
24
20
  height: var(--lynx-view-height);
25
21
  block-size: var(--lynx-view-height);
26
22
  }
27
- lynx-view[height="auto"] > #lynx-view-root {
23
+ lynx-view[height="auto"]::part(lynx-view-root) {
28
24
  height: unset;
29
25
  }
30
26
 
@@ -33,15 +29,15 @@ lynx-view[width="auto"] {
33
29
  width: var(--lynx-view-width);
34
30
  inline-size: var(--lynx-view-width);
35
31
  }
36
- lynx-view[width="auto"] > #lynx-view-root {
32
+ lynx-view[width="auto"]::part(lynx-view-root) {
37
33
  width: unset;
38
34
  }
39
35
 
40
36
  lynx-view[height="auto"], lynx-view[width="auto"] {
41
37
  contain-intrinsic-size: var(--lynx-view-width) var(--lynx-view-height);
42
38
  }
43
- lynx-view[height="auto"] > #lynx-view-root,
44
- lynx-view[width="auto"] > #lynx-view-root {
39
+ lynx-view[height="auto"]::part(lynx-view-root),
40
+ lynx-view[width="auto"]::part(lynx-view-root) {
45
41
  display: unset;
46
42
  position: fixed;
47
43
  top: 0;
@@ -60,7 +56,7 @@ lynx-view[width="auto"] > #lynx-view-root {
60
56
  initial-value: 100%;
61
57
  }
62
58
 
63
- lynx-view:not([width="auto"]):not([height="auto"]) [lynx-tag="page"] {
59
+ lynx-view:not([width="auto"]):not([height="auto"])::part(page) {
64
60
  height: 100%;
65
61
  width: 100%;
66
62
  }
package/package.json CHANGED
@@ -1,9 +1,14 @@
1
1
  {
2
2
  "name": "@lynx-js/web-core",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "private": false,
5
5
  "description": "",
6
6
  "keywords": [],
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/lynx-family/lynx-stack.git",
10
+ "directory": "packages/web-platform/web-core"
11
+ },
7
12
  "license": "Apache-2.0",
8
13
  "type": "module",
9
14
  "main": "dist/index.js",
@@ -19,16 +24,16 @@
19
24
  "**/*.css"
20
25
  ],
21
26
  "dependencies": {
22
- "@lynx-js/web-constants": "0.7.0",
23
- "@lynx-js/web-worker-rpc": "0.7.0",
24
- "@lynx-js/web-worker-runtime": "0.7.0"
27
+ "@lynx-js/web-constants": "0.8.0",
28
+ "@lynx-js/web-worker-rpc": "0.8.0",
29
+ "@lynx-js/web-worker-runtime": "0.8.0"
25
30
  },
26
31
  "devDependencies": {
27
32
  "@lynx-js/lynx-core": "0.1.0",
28
- "@lynx-js/web-elements": "0.2.4"
33
+ "@lynx-js/web-elements": "0.4.0"
29
34
  },
30
35
  "peerDependencies": {
31
36
  "@lynx-js/lynx-core": "0.1.0",
32
- "@lynx-js/web-elements": ">=0.1.0"
37
+ "@lynx-js/web-elements": ">=0.3.1"
33
38
  }
34
39
  }
@@ -1,3 +0,0 @@
1
- import type { Rpc } from '@lynx-js/web-worker-rpc';
2
- import type { loadNewTagEndpoint } from '@lynx-js/web-constants';
3
- export declare function registerLoadNewTagHandler(rpc: Rpc, endpoint: typeof loadNewTagEndpoint, loadTag: (tag: string) => void, tagMap: Record<string, string>, currentLoadingTags: Promise<any>[]): void;
@@ -1,7 +0,0 @@
1
- import { getElementTag } from '../getElementTag.js';
2
- export function registerLoadNewTagHandler(rpc, endpoint, loadTag, tagMap, currentLoadingTags) {
3
- rpc.registerHandler(endpoint, (tag) => {
4
- loadTag(getElementTag(tag, tagMap, currentLoadingTags));
5
- });
6
- }
7
- //# sourceMappingURL=registerLoadNewTagHandler.js.map