@lynx-js/web-core 0.7.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 +597 -0
- package/LICENSE.txt +202 -0
- package/Notice.txt +1 -0
- package/README.md +21 -0
- package/dist/apis/LynxView.d.ts +137 -0
- package/dist/apis/LynxView.js +368 -0
- package/dist/apis/createLynxView.d.ts +18 -0
- package/dist/apis/createLynxView.js +17 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +7 -0
- package/dist/types/LynxExposureModule.d.ts +4 -0
- package/dist/types/LynxExposureModule.js +5 -0
- package/dist/types/RuntimePropertyOnElement.d.ts +17 -0
- package/dist/types/RuntimePropertyOnElement.js +2 -0
- package/dist/types/UpdatePageCallback.d.ts +7 -0
- package/dist/types/UpdatePageCallback.js +2 -0
- package/dist/uiThread/bootWorkers.d.ts +8 -0
- package/dist/uiThread/bootWorkers.js +60 -0
- package/dist/uiThread/crossThreadHandlers/bootTimingSystem.d.ts +5 -0
- package/dist/uiThread/crossThreadHandlers/bootTimingSystem.js +50 -0
- package/dist/uiThread/crossThreadHandlers/createDispose.d.ts +3 -0
- package/dist/uiThread/crossThreadHandlers/createDispose.js +11 -0
- package/dist/uiThread/crossThreadHandlers/createExposureService.d.ts +2 -0
- package/dist/uiThread/crossThreadHandlers/createExposureService.js +55 -0
- package/dist/uiThread/crossThreadHandlers/createUpdateData.d.ts +3 -0
- package/dist/uiThread/crossThreadHandlers/createUpdateData.js +14 -0
- package/dist/uiThread/crossThreadHandlers/queryNodes.d.ts +2 -0
- package/dist/uiThread/crossThreadHandlers/queryNodes.js +65 -0
- package/dist/uiThread/crossThreadHandlers/registerFlushElementTreeHandler.d.ts +18 -0
- package/dist/uiThread/crossThreadHandlers/registerFlushElementTreeHandler.js +116 -0
- package/dist/uiThread/crossThreadHandlers/registerInvokeUIMethodHandler.d.ts +2 -0
- package/dist/uiThread/crossThreadHandlers/registerInvokeUIMethodHandler.js +51 -0
- package/dist/uiThread/crossThreadHandlers/registerLoadNewTagHandler.d.ts +3 -0
- package/dist/uiThread/crossThreadHandlers/registerLoadNewTagHandler.js +7 -0
- package/dist/uiThread/crossThreadHandlers/registerNativeModulesCallHandler.d.ts +3 -0
- package/dist/uiThread/crossThreadHandlers/registerNativeModulesCallHandler.js +5 -0
- package/dist/uiThread/crossThreadHandlers/registerReportErrorHandler.d.ts +2 -0
- package/dist/uiThread/crossThreadHandlers/registerReportErrorHandler.js +10 -0
- package/dist/uiThread/crossThreadHandlers/registerSelectComponentHandler.d.ts +2 -0
- package/dist/uiThread/crossThreadHandlers/registerSelectComponentHandler.js +15 -0
- package/dist/uiThread/crossThreadHandlers/registerSetNativePropsHandler.d.ts +2 -0
- package/dist/uiThread/crossThreadHandlers/registerSetNativePropsHandler.js +32 -0
- package/dist/uiThread/crossThreadHandlers/registerTriggerComponentEventHandler.d.ts +2 -0
- package/dist/uiThread/crossThreadHandlers/registerTriggerComponentEventHandler.js +14 -0
- package/dist/uiThread/decodeElementOperation.d.ts +13 -0
- package/dist/uiThread/decodeElementOperation.js +183 -0
- package/dist/uiThread/getElementTag.d.ts +1 -0
- package/dist/uiThread/getElementTag.js +20 -0
- package/dist/uiThread/startUIThread.d.ts +7 -0
- package/dist/uiThread/startUIThread.js +78 -0
- package/dist/utils/browser.d.ts +3 -0
- package/dist/utils/browser.js +9 -0
- package/dist/utils/createCrossThreadEvent.d.ts +2 -0
- package/dist/utils/createCrossThreadEvent.js +43 -0
- package/dist/utils/loadTemplate.d.ts +2 -0
- package/dist/utils/loadTemplate.js +53 -0
- package/index.css +66 -0
- package/package.json +34 -0
|
@@ -0,0 +1,368 @@
|
|
|
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 { createLynxView, } from './createLynxView.js';
|
|
5
|
+
import { cardIdAttribute, lynxViewEntryIdPrefix, lynxViewRootDomId, } from '@lynx-js/web-constants';
|
|
6
|
+
import { loadElement } from '@lynx-js/web-elements/lazy';
|
|
7
|
+
/**
|
|
8
|
+
* Based on our experiences, these elements are almost used in all lynx cards.
|
|
9
|
+
*/
|
|
10
|
+
loadElement('lynx-wrapper');
|
|
11
|
+
loadElement('x-view');
|
|
12
|
+
loadElement('x-text');
|
|
13
|
+
loadElement('x-image');
|
|
14
|
+
loadElement('scroll-view');
|
|
15
|
+
/**
|
|
16
|
+
* @param {string} url [required] The url of the entry of your Lynx card
|
|
17
|
+
* @param {Cloneable} globalProps [optional] The globalProps value of this Lynx card
|
|
18
|
+
* @param {Cloneable} initData [oprional] The initial data of this Lynx card
|
|
19
|
+
* @param {Record<string,string>} overrideLynxTagToHTMLTagMap [optional] use this property/attribute to override the lynx tag -> html tag map
|
|
20
|
+
* @param {string} nativeModulesUrl [optional] It is a esm url, use to customize NativeModules.
|
|
21
|
+
* @param {INativeModulesCall} onNativeModulesCall [optional] the NativeModules value handler. Arguments will be cached before this property is assigned.
|
|
22
|
+
* @param {"auto" | null} height [optional] set it to "auto" for height auto-sizing
|
|
23
|
+
* @param {"auto" | null} width [optional] set it to "auto" for width auto-sizing
|
|
24
|
+
*
|
|
25
|
+
* @property entryId the currently Lynx view entryId.
|
|
26
|
+
*
|
|
27
|
+
* @event error lynx card fired an error
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* HTML Exmaple
|
|
31
|
+
*
|
|
32
|
+
* Note that you should declarae the size of lynx-view
|
|
33
|
+
*
|
|
34
|
+
* ```html
|
|
35
|
+
* <lynx-view url="https://path/to/main-thread.js" rawData="{}" globalProps="{}" style="height:300px;width:300px">
|
|
36
|
+
* </lynx-view>
|
|
37
|
+
* ```
|
|
38
|
+
*
|
|
39
|
+
* React 19 Example
|
|
40
|
+
* ```jsx
|
|
41
|
+
* <lynx-view url={myLynxCardUrl} rawData={{}} globalProps={{}} style={{height:'300px', width:'300px'}}>
|
|
42
|
+
* </lynx-vew>
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export class LynxView extends HTMLElement {
|
|
46
|
+
static lynxViewCount = 0;
|
|
47
|
+
static tag = 'lynx-view';
|
|
48
|
+
static observedAttributeAsProperties = [
|
|
49
|
+
'url',
|
|
50
|
+
'globalProps',
|
|
51
|
+
'initData',
|
|
52
|
+
'overrideLynxTagToHTMLTagMap',
|
|
53
|
+
'nativeModulesUrl',
|
|
54
|
+
];
|
|
55
|
+
static attributeCamelCaseMap = Object.fromEntries(this.observedAttributeAsProperties.map((nm) => [nm.toLocaleLowerCase(), nm]));
|
|
56
|
+
/**
|
|
57
|
+
* @private
|
|
58
|
+
*/
|
|
59
|
+
static observedAttributes = LynxView.observedAttributeAsProperties.map(nm => nm.toLowerCase());
|
|
60
|
+
#instance;
|
|
61
|
+
#url;
|
|
62
|
+
/**
|
|
63
|
+
* @public
|
|
64
|
+
* @property the url of lynx view output entry file
|
|
65
|
+
*/
|
|
66
|
+
get url() {
|
|
67
|
+
return this.#url;
|
|
68
|
+
}
|
|
69
|
+
set url(val) {
|
|
70
|
+
this.#url = val;
|
|
71
|
+
this.#render();
|
|
72
|
+
}
|
|
73
|
+
#globalProps = {};
|
|
74
|
+
/**
|
|
75
|
+
* @public
|
|
76
|
+
* @property globalProps
|
|
77
|
+
* @default {}
|
|
78
|
+
*/
|
|
79
|
+
get globalProps() {
|
|
80
|
+
return this.#globalProps;
|
|
81
|
+
}
|
|
82
|
+
set globalProps(val) {
|
|
83
|
+
if (typeof val === 'string') {
|
|
84
|
+
this.#globalProps = JSON.parse(val);
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
this.#globalProps = val;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
#initData = {};
|
|
91
|
+
/**
|
|
92
|
+
* @public
|
|
93
|
+
* @property initData
|
|
94
|
+
* @default {}
|
|
95
|
+
*/
|
|
96
|
+
get initData() {
|
|
97
|
+
return this.#initData;
|
|
98
|
+
}
|
|
99
|
+
set initData(val) {
|
|
100
|
+
if (typeof val === 'string') {
|
|
101
|
+
this.#initData = JSON.parse(val);
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
this.#initData = val;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
#entryId;
|
|
108
|
+
/**
|
|
109
|
+
* @public
|
|
110
|
+
* @readonly
|
|
111
|
+
* @property
|
|
112
|
+
* The random generated entryId of current lynxview
|
|
113
|
+
*/
|
|
114
|
+
get entryId() {
|
|
115
|
+
return this.#entryId;
|
|
116
|
+
}
|
|
117
|
+
#overrideLynxTagToHTMLTagMap = { 'page': 'div' };
|
|
118
|
+
/**
|
|
119
|
+
* @public
|
|
120
|
+
* @property
|
|
121
|
+
* @default {page: 'div'}
|
|
122
|
+
*/
|
|
123
|
+
get overrideLynxTagToHTMLTagMap() {
|
|
124
|
+
return this.#overrideLynxTagToHTMLTagMap;
|
|
125
|
+
}
|
|
126
|
+
set overrideLynxTagToHTMLTagMap(val) {
|
|
127
|
+
if (typeof val === 'string') {
|
|
128
|
+
this.#overrideLynxTagToHTMLTagMap = JSON.parse(val);
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
this.#overrideLynxTagToHTMLTagMap = val;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
#cachedNativeModulesCall = [];
|
|
135
|
+
#onNativeModulesCall;
|
|
136
|
+
/**
|
|
137
|
+
* @param
|
|
138
|
+
* @property
|
|
139
|
+
*/
|
|
140
|
+
get onNativeModulesCall() {
|
|
141
|
+
return this.#onNativeModulesCall;
|
|
142
|
+
}
|
|
143
|
+
set onNativeModulesCall(handler) {
|
|
144
|
+
this.#onNativeModulesCall = handler;
|
|
145
|
+
if (this.#cachedNativeModulesCall) {
|
|
146
|
+
for (const callInfo of this.#cachedNativeModulesCall) {
|
|
147
|
+
handler.apply(undefined, callInfo);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
#nativeModulesUrl;
|
|
152
|
+
/**
|
|
153
|
+
* @public
|
|
154
|
+
* @property nativeModules
|
|
155
|
+
*/
|
|
156
|
+
get nativeModulesUrl() {
|
|
157
|
+
return this.#nativeModulesUrl;
|
|
158
|
+
}
|
|
159
|
+
set nativeModulesUrl(val) {
|
|
160
|
+
this.#nativeModulesUrl = val;
|
|
161
|
+
}
|
|
162
|
+
#autoHeight = false;
|
|
163
|
+
#autoWidth = false;
|
|
164
|
+
#currentWidth = 0;
|
|
165
|
+
#currentHeight = 0;
|
|
166
|
+
/**
|
|
167
|
+
* @public
|
|
168
|
+
* "auto" for auto calculated height
|
|
169
|
+
*/
|
|
170
|
+
get height() {
|
|
171
|
+
return this.#autoHeight ? 'auto' : null;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* @public
|
|
175
|
+
* "auto" for auto calculated width
|
|
176
|
+
*/
|
|
177
|
+
get width() {
|
|
178
|
+
return this.#autoWidth ? 'auto' : null;
|
|
179
|
+
}
|
|
180
|
+
set height(val) {
|
|
181
|
+
this.#handleAutoSize();
|
|
182
|
+
this.#autoHeight = val === 'auto' ? true : false;
|
|
183
|
+
}
|
|
184
|
+
set width(val) {
|
|
185
|
+
this.#handleAutoSize();
|
|
186
|
+
this.#autoWidth = val === 'auto' ? true : false;
|
|
187
|
+
}
|
|
188
|
+
#handleAutoSize() {
|
|
189
|
+
if (this.#autoHeight || this.#autoWidth) {
|
|
190
|
+
if (this.#instance && !this.#instance.resizeObserver) {
|
|
191
|
+
this.#instance.resizeObserver = new ResizeObserver((sizes) => {
|
|
192
|
+
const size = sizes[0];
|
|
193
|
+
if (size) {
|
|
194
|
+
const { width, height } = size.contentRect;
|
|
195
|
+
if (this.#autoWidth) {
|
|
196
|
+
if (this.#currentWidth !== width) {
|
|
197
|
+
this.#currentWidth = width;
|
|
198
|
+
this.style.setProperty('--lynx-view-width', `${width}px`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
if (this.#autoHeight) {
|
|
202
|
+
if (this.#currentHeight !== height) {
|
|
203
|
+
this.#currentHeight = height;
|
|
204
|
+
this.style.setProperty('--lynx-view-height', `${height}px`);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
this.#instance.resizeObserver.observe(this.#instance.rootDom);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
if (this.#instance?.resizeObserver) {
|
|
214
|
+
this.#instance.resizeObserver.disconnect();
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
if (this.#autoHeight) {
|
|
218
|
+
this.setAttribute('height', 'auto');
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
this.removeAttribute('height');
|
|
222
|
+
}
|
|
223
|
+
if (this.#autoWidth) {
|
|
224
|
+
this.setAttribute('width', 'auto');
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
this.removeAttribute('width');
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* @public
|
|
232
|
+
* @method
|
|
233
|
+
* update the `__initData` and trigger essential flow
|
|
234
|
+
*/
|
|
235
|
+
updateData(data, updateDataType, callback) {
|
|
236
|
+
this.#instance?.lynxView.updateData(data, updateDataType, callback);
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* @public
|
|
240
|
+
* @method
|
|
241
|
+
* send global events, which can be listened to using the GlobalEventEmitter
|
|
242
|
+
*/
|
|
243
|
+
sendGlobalEvent(eventName, params) {
|
|
244
|
+
this.#instance?.lynxView.sendGlobalEvent(eventName, params);
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* @public
|
|
248
|
+
* @method
|
|
249
|
+
* reload the current page
|
|
250
|
+
*/
|
|
251
|
+
reload() {
|
|
252
|
+
this.#render();
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* @override
|
|
256
|
+
* "false" value will be omitted
|
|
257
|
+
*
|
|
258
|
+
* {@inheritdoc HTMLElement.setAttribute}
|
|
259
|
+
*/
|
|
260
|
+
setAttribute(qualifiedName, value) {
|
|
261
|
+
if (value === 'false') {
|
|
262
|
+
this.removeAttribute(qualifiedName);
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
super.setAttribute(qualifiedName, value);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* @private
|
|
270
|
+
*/
|
|
271
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
|
272
|
+
if (oldValue !== newValue) {
|
|
273
|
+
name = LynxView.attributeCamelCaseMap[name] ?? name;
|
|
274
|
+
if (name in this) {
|
|
275
|
+
// @ts-expect-error
|
|
276
|
+
this[name] = newValue;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* @private
|
|
282
|
+
*/
|
|
283
|
+
disconnectedCallback() {
|
|
284
|
+
if (this.#instance) {
|
|
285
|
+
this.#instance.resizeObserver?.disconnect();
|
|
286
|
+
this.#instance.lynxView.dispose();
|
|
287
|
+
this.#instance.rootDom.remove();
|
|
288
|
+
}
|
|
289
|
+
this.#instance = undefined;
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* @private the flag to group all changes into one render operation
|
|
293
|
+
*/
|
|
294
|
+
#rendering = false;
|
|
295
|
+
/**
|
|
296
|
+
* @private
|
|
297
|
+
*/
|
|
298
|
+
#render() {
|
|
299
|
+
if (!this.#rendering) {
|
|
300
|
+
this.#rendering = true;
|
|
301
|
+
queueMicrotask(() => {
|
|
302
|
+
this.#rendering = false;
|
|
303
|
+
if (this.#instance) {
|
|
304
|
+
this.disconnectedCallback();
|
|
305
|
+
}
|
|
306
|
+
if (this.#url) {
|
|
307
|
+
const rootDom = document.createElement('div');
|
|
308
|
+
rootDom.id = lynxViewRootDomId;
|
|
309
|
+
const entryId = `${lynxViewEntryIdPrefix}-${LynxView
|
|
310
|
+
.lynxViewCount++}`;
|
|
311
|
+
this.#entryId = entryId;
|
|
312
|
+
rootDom.setAttribute(cardIdAttribute, entryId);
|
|
313
|
+
rootDom.setAttribute('part', lynxViewRootDomId);
|
|
314
|
+
const commonEventDetail = {
|
|
315
|
+
entryId,
|
|
316
|
+
};
|
|
317
|
+
const lynxView = createLynxView({
|
|
318
|
+
entryId,
|
|
319
|
+
rootDom,
|
|
320
|
+
templateUrl: this.#url,
|
|
321
|
+
globalProps: this.#globalProps,
|
|
322
|
+
initData: this.#initData,
|
|
323
|
+
overrideLynxTagToHTMLTagMap: this.#overrideLynxTagToHTMLTagMap,
|
|
324
|
+
nativeModulesUrl: this.#nativeModulesUrl,
|
|
325
|
+
callbacks: {
|
|
326
|
+
loadNewTag: loadElement,
|
|
327
|
+
nativeModulesCall: (...args) => {
|
|
328
|
+
if (this.#onNativeModulesCall) {
|
|
329
|
+
return this.#onNativeModulesCall(...args);
|
|
330
|
+
}
|
|
331
|
+
else if (this.#cachedNativeModulesCall) {
|
|
332
|
+
this.#cachedNativeModulesCall.push(args);
|
|
333
|
+
}
|
|
334
|
+
else {
|
|
335
|
+
this.#cachedNativeModulesCall = [args];
|
|
336
|
+
}
|
|
337
|
+
},
|
|
338
|
+
onError: () => {
|
|
339
|
+
this.dispatchEvent(new CustomEvent('error', {
|
|
340
|
+
detail: commonEventDetail,
|
|
341
|
+
}));
|
|
342
|
+
},
|
|
343
|
+
},
|
|
344
|
+
});
|
|
345
|
+
this.#instance = {
|
|
346
|
+
lynxView,
|
|
347
|
+
rootDom,
|
|
348
|
+
};
|
|
349
|
+
this.#handleAutoSize();
|
|
350
|
+
this.append(rootDom);
|
|
351
|
+
}
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* @private
|
|
357
|
+
*/
|
|
358
|
+
connectedCallback() {
|
|
359
|
+
this.#render();
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
if (customElements.get(LynxView.tag)) {
|
|
363
|
+
console.warn(`[${LynxView.tag}] has already been defined`);
|
|
364
|
+
}
|
|
365
|
+
else {
|
|
366
|
+
customElements.define(LynxView.tag, LynxView);
|
|
367
|
+
}
|
|
368
|
+
//# sourceMappingURL=LynxView.js.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Cloneable, UpdateDataType } from '@lynx-js/web-constants';
|
|
2
|
+
import { startUIThread } from '../uiThread/startUIThread.js';
|
|
3
|
+
export interface LynxViewConfigs {
|
|
4
|
+
templateUrl: string;
|
|
5
|
+
initData: Cloneable;
|
|
6
|
+
globalProps: Cloneable;
|
|
7
|
+
entryId: string;
|
|
8
|
+
rootDom: HTMLElement;
|
|
9
|
+
callbacks: Parameters<typeof startUIThread>[3];
|
|
10
|
+
overrideLynxTagToHTMLTagMap?: Record<string, string>;
|
|
11
|
+
nativeModulesUrl: string | undefined;
|
|
12
|
+
}
|
|
13
|
+
export interface LynxView {
|
|
14
|
+
updateData(data: Cloneable, updateDataType: UpdateDataType, callback?: () => void): void;
|
|
15
|
+
dispose(): Promise<void>;
|
|
16
|
+
sendGlobalEvent(name: string, params?: Cloneable[]): void;
|
|
17
|
+
}
|
|
18
|
+
export declare function createLynxView(configs: LynxViewConfigs): LynxView;
|
|
@@ -0,0 +1,17 @@
|
|
|
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 { startUIThread } from '../uiThread/startUIThread.js';
|
|
5
|
+
import { supportAtScope } from '../utils/browser.js';
|
|
6
|
+
export function createLynxView(configs) {
|
|
7
|
+
const { rootDom, callbacks, templateUrl, globalProps, entryId, initData, overrideLynxTagToHTMLTagMap, nativeModulesUrl, } = configs;
|
|
8
|
+
return startUIThread(templateUrl, {
|
|
9
|
+
initData,
|
|
10
|
+
globalProps,
|
|
11
|
+
entryId,
|
|
12
|
+
browserConfig: {
|
|
13
|
+
supportAtScope,
|
|
14
|
+
},
|
|
15
|
+
}, rootDom, callbacks, overrideLynxTagToHTMLTagMap, nativeModulesUrl);
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=createLynxView.js.map
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
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
|
+
export { createLynxView } from './apis/createLynxView.js';
|
|
5
|
+
export { LynxView } from './apis/LynxView.js';
|
|
6
|
+
export { lynxRuntimeValue } from '@lynx-js/web-constants';
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
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 {};
|
|
@@ -0,0 +1,60 @@
|
|
|
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 { Rpc } from '@lynx-js/web-worker-rpc';
|
|
5
|
+
let preHeatedMainWorker = createMainWorker();
|
|
6
|
+
export function bootWorkers() {
|
|
7
|
+
const curMainWorker = preHeatedMainWorker;
|
|
8
|
+
const curBackgroundWorker = createBackgroundWorker(curMainWorker.channelMainThreadWithBackground);
|
|
9
|
+
preHeatedMainWorker = createMainWorker();
|
|
10
|
+
return {
|
|
11
|
+
mainThreadRpc: curMainWorker.mainThreadRpc,
|
|
12
|
+
backgroundRpc: curBackgroundWorker.backgroundRpc,
|
|
13
|
+
terminateWorkers: () => {
|
|
14
|
+
curMainWorker.mainThreadWorker.terminate();
|
|
15
|
+
curBackgroundWorker.backgroundThreadWorker.terminate();
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function createMainWorker() {
|
|
20
|
+
const channelToMainThread = new MessageChannel();
|
|
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
|
+
});
|
|
26
|
+
const mainThreadMessage = {
|
|
27
|
+
mode: 'main',
|
|
28
|
+
toUIThread: channelToMainThread.port2,
|
|
29
|
+
toPeerThread: channelMainThreadWithBackground.port1,
|
|
30
|
+
};
|
|
31
|
+
mainThreadWorker.postMessage(mainThreadMessage, [
|
|
32
|
+
channelToMainThread.port2,
|
|
33
|
+
channelMainThreadWithBackground.port1,
|
|
34
|
+
]);
|
|
35
|
+
const mainThreadRpc = new Rpc(channelToMainThread.port1, 'ui-to-main');
|
|
36
|
+
return {
|
|
37
|
+
mainThreadRpc,
|
|
38
|
+
mainThreadWorker,
|
|
39
|
+
channelMainThreadWithBackground,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function createBackgroundWorker(channelMainThreadWithBackground) {
|
|
43
|
+
const channelToBackground = new MessageChannel();
|
|
44
|
+
const backgroundThreadWorker = new Worker(new URL('@lynx-js/web-worker-runtime', import.meta.url), {
|
|
45
|
+
type: 'module',
|
|
46
|
+
name: `lynx-bg`,
|
|
47
|
+
});
|
|
48
|
+
const backgroundThreadMessage = {
|
|
49
|
+
mode: 'background',
|
|
50
|
+
toUIThread: channelToBackground.port2,
|
|
51
|
+
toPeerThread: channelMainThreadWithBackground.port2,
|
|
52
|
+
};
|
|
53
|
+
backgroundThreadWorker.postMessage(backgroundThreadMessage, [
|
|
54
|
+
channelToBackground.port2,
|
|
55
|
+
channelMainThreadWithBackground.port2,
|
|
56
|
+
]);
|
|
57
|
+
const backgroundRpc = new Rpc(channelToBackground.port1, 'ui-to-bg');
|
|
58
|
+
return { backgroundRpc, backgroundThreadWorker };
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=bootWorkers.js.map
|
|
@@ -0,0 +1,5 @@
|
|
|
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
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
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
|
+
}));
|
|
39
|
+
if (pipelineId) {
|
|
40
|
+
pipelineIdToTiming.delete(pipelineId);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
mainThreadRpc.registerHandler(postTimingInfoFromMainThread, markTimingInternal);
|
|
44
|
+
backgroundThreadRpc.registerHandler(postTimingInfoFromBackgroundThread, markTimingInternal);
|
|
45
|
+
return {
|
|
46
|
+
markTimingInternal,
|
|
47
|
+
sendTimingResult,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=bootTimingSystem.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
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 { disposeEndpoint } from '@lynx-js/web-constants';
|
|
5
|
+
export function createDispose(rpc, terminateWorkers) {
|
|
6
|
+
return async () => {
|
|
7
|
+
await rpc.invoke(disposeEndpoint, []);
|
|
8
|
+
terminateWorkers();
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=createDispose.js.map
|
|
@@ -0,0 +1,55 @@
|
|
|
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
|