From ce0c5eadb2765342e4af2eb950aa16dfcd2fd095 Mon Sep 17 00:00:00 2001 From: Yiming Li Date: Sun, 27 Apr 2025 11:44:03 +0800 Subject: [PATCH 1/4] fix(testing-library): correct link in tsdoc (#623) ## Summary Markdown is not supported well by api-documenter, so fix it using `@link`: image See latest doc at: https://github.com/lynx-family/lynx-website/pull/117 ## Checklist - [ ] Tests updated (or **not required**). - [x] Documentation updated (or not required). --- .changeset/hip-seals-read.md | 2 ++ .../test-environment/src/lynx/ElementPAPI.ts | 21 ++++--------------- 2 files changed, 6 insertions(+), 17 deletions(-) create mode 100644 .changeset/hip-seals-read.md diff --git a/.changeset/hip-seals-read.md b/.changeset/hip-seals-read.md new file mode 100644 index 0000000000..a845151cc8 --- /dev/null +++ b/.changeset/hip-seals-read.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/packages/testing-library/test-environment/src/lynx/ElementPAPI.ts b/packages/testing-library/test-environment/src/lynx/ElementPAPI.ts index 5d5ea24991..2a65fe5bc7 100644 --- a/packages/testing-library/test-environment/src/lynx/ElementPAPI.ts +++ b/packages/testing-library/test-environment/src/lynx/ElementPAPI.ts @@ -7,24 +7,11 @@ /** * Any Lynx Element, such as `view`, `text`, `image`, etc. * - * [Lynx Spec Reference](https://lynxjs.org/living-spec/index.html?ts=1743416098203#element%E2%91%A0) + * {@link https://lynxjs.org/living-spec/index.html?ts=1743416098203#element%E2%91%A0 | Lynx Spec Reference} * * @public */ export interface LynxElement extends HTMLElement { - // /** - // * The props of the element. - // */ - // props: { - // cssId?: string; - // event?: { - // [key: string]: any; - // }; - // gesture?: { - // [key: string]: any; - // }; - // [key: string]: any; - // }; /** * The unique id of the element. * @@ -56,19 +43,19 @@ export interface LynxElement extends HTMLElement { /** * Returns the first child. * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Node/firstChild) + * {@link https://developer.mozilla.org/docs/Web/API/Node/firstChild | MDN Reference} */ firstChild: LynxElement; /** * Returns the next sibling. * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Node/nextSibling) + * {@link https://developer.mozilla.org/docs/Web/API/Node/nextSibling | MDN Reference} */ nextSibling: LynxElement; /** * Returns the parent. * - * [MDN Reference](https://developer.mozilla.org/docs/Web/API/Node/parentNode) + * {@link https://developer.mozilla.org/docs/Web/API/Node/parentNode | MDN Reference} */ parentNode: LynxElement; } From 74b5bd15339b70107a7c42525494da46e8f8f6bd Mon Sep 17 00:00:00 2001 From: PupilTong <12288479+PupilTong@users.noreply.github.com> Date: Sun, 27 Apr 2025 12:56:08 +0800 Subject: [PATCH 2/4] feat: support thread strategy all on ui (#625) ```html ``` This will make the lynx's main-thread run on the UA's main thread. Note that the `all-on-ui` dose not support the HMR & chunk splitting yet, related tests are disabled. --------- Signed-off-by: PupilTong <12288479+PupilTong@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .changeset/giant-seas-leave.md | 15 +++ .changeset/slow-tools-ring.md | 5 + .github/workflows/test.yml | 16 ++++ .../src/webworker/OffscreenNode.ts | 4 + packages/web-platform/web-core/package.json | 1 + .../web-core/src/apis/LynxView.ts | 21 +++++ .../web-core/src/apis/createLynxView.ts | 10 +- .../web-core/src/uiThread/bootWorkers.ts | 30 +++++- .../src/uiThread/createRenderAllOnUI.ts | 54 +++++++++++ .../src/uiThread/createRenderMultiThread.ts | 32 +++++++ .../crossThreadHandlers/createUpdateData.ts | 10 +- .../web-core/src/uiThread/startBackground.ts | 59 ++++++++++++ .../web-core/src/uiThread/startUIThread.ts | 92 +++++++------------ .../src/MainThreadRuntime.ts | 26 ++---- .../web-mainthread-apis/src/loadMainThread.ts | 23 ++++- .../web-tests/playwright.config.ts | 2 + .../web-platform/web-tests/rspack.config.js | 3 + .../web-tests/shell-project/index.ts | 2 + .../web-tests/shell-project/web-core.ts | 2 + .../web-tests/tests/react.spec.ts | 8 +- .../web-tests/tests/web-core.test.ts | 23 +++-- .../web-platform/web-worker-rpc/src/Rpc.ts | 2 +- .../src/mainThread/startMainThread.ts | 2 +- pnpm-lock.yaml | 3 + 24 files changed, 340 insertions(+), 105 deletions(-) create mode 100644 .changeset/giant-seas-leave.md create mode 100644 .changeset/slow-tools-ring.md create mode 100644 packages/web-platform/web-core/src/uiThread/createRenderAllOnUI.ts create mode 100644 packages/web-platform/web-core/src/uiThread/createRenderMultiThread.ts create mode 100644 packages/web-platform/web-core/src/uiThread/startBackground.ts diff --git a/.changeset/giant-seas-leave.md b/.changeset/giant-seas-leave.md new file mode 100644 index 0000000000..e664237fe3 --- /dev/null +++ b/.changeset/giant-seas-leave.md @@ -0,0 +1,15 @@ +--- +"@lynx-js/web-mainthread-apis": patch +"@lynx-js/web-worker-runtime": patch +"@lynx-js/web-core": patch +--- + +feat: support thread strategy `all-on-ui` + +```html + +``` + +This will make the lynx's main-thread run on the UA's main thread. + +Note that the `all-on-ui` does not support the HMR & chunk splitting yet. diff --git a/.changeset/slow-tools-ring.md b/.changeset/slow-tools-ring.md new file mode 100644 index 0000000000..444b16c5ca --- /dev/null +++ b/.changeset/slow-tools-ring.md @@ -0,0 +1,5 @@ +--- +"@lynx-js/offscreen-document": patch +--- + +feat: support parentNode diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 40444334cc..78f7a0f6b5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -221,6 +221,21 @@ jobs: export PLAYWRIGHT_JUNIT_OUTPUT_NAME=test-report.junit.xml pnpm --filter @lynx-js/web-tests run test --reporter='github,dot,junit,html' pnpm --filter @lynx-js/web-tests run coverage:ci + playwright-linux-all-on-ui: + needs: build + uses: ./.github/workflows/workflow-test.yml + secrets: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + with: + runs-on: lynx-ubuntu-24.04-xlarge + is-web: true + codecov-flags: "e2e" + run: | + export NODE_OPTIONS="--max-old-space-size=32768" + export PLAYWRIGHT_JUNIT_OUTPUT_NAME=test-report.junit.xml + export ALL_ON_UI=true + pnpm --filter @lynx-js/web-tests run test --reporter='github,dot,junit,html' + pnpm --filter @lynx-js/web-tests run coverage:ci lighthouse: needs: build uses: ./.github/workflows/workflow-test.yml @@ -270,6 +285,7 @@ jobs: needs: - code-style-check - playwright-linux + - playwright-linux-all-on-ui - test-plugins - test-publish - test-react diff --git a/packages/web-platform/offscreen-document/src/webworker/OffscreenNode.ts b/packages/web-platform/offscreen-document/src/webworker/OffscreenNode.ts index 1b4d7cebfd..0ee66e1d47 100644 --- a/packages/web-platform/offscreen-document/src/webworker/OffscreenNode.ts +++ b/packages/web-platform/offscreen-document/src/webworker/OffscreenNode.ts @@ -28,6 +28,10 @@ export class OffscreenNode extends EventTarget { return this._parentElement; } + get parentNode(): OffscreenNode | null { + return this._parentElement; + } + get firstElementChild(): OffscreenNode | null { return this._children[0] ?? null; } diff --git a/packages/web-platform/web-core/package.json b/packages/web-platform/web-core/package.json index 09537f6acc..28b1c59a1e 100644 --- a/packages/web-platform/web-core/package.json +++ b/packages/web-platform/web-core/package.json @@ -26,6 +26,7 @@ "dependencies": { "@lynx-js/offscreen-document": "workspace:*", "@lynx-js/web-constants": "workspace:*", + "@lynx-js/web-mainthread-apis": "workspace:*", "@lynx-js/web-worker-rpc": "workspace:*", "@lynx-js/web-worker-runtime": "workspace:*" }, diff --git a/packages/web-platform/web-core/src/apis/LynxView.ts b/packages/web-platform/web-core/src/apis/LynxView.ts index 43020fee2d..f8eb5b97df 100644 --- a/packages/web-platform/web-core/src/apis/LynxView.ts +++ b/packages/web-platform/web-core/src/apis/LynxView.ts @@ -45,6 +45,7 @@ export type INapiModulesCall = ( * @property {INapiModulesCall} onNapiModulesCall [optional] the NapiModule value handler. * @property {"false" | "true" | null} injectHeadLinks [optional] @default true set it to "false" to disable injecting the styles into shadowroot * @property {number} lynxGroupId [optional] (attribute: "lynx-group-id") the background shared context id, which is used to share webworker between different lynx cards + * @property {"all-on-ui" | "multi-thread"} threadStrategy [optional] @default "multi-thread" (attribute: "thread-strategy") controls the thread strategy for current lynx view * @property {(string)=>Promise} customTemplateLoader [optional] the custom template loader, which is used to load the template * * @event error lynx card fired an error @@ -284,6 +285,22 @@ export class LynxView extends HTMLElement { } } + /** + * @param + * @property + */ + get threadStrategy(): 'all-on-ui' | 'multi-thread' { + // @ts-expect-error + return this.getAttribute('thread-strategy'); + } + set threadStrategy(val: 'all-on-ui' | 'multi-thread') { + if (val) { + this.setAttribute('thread-strategy', val); + } else { + this.removeAttribute('thread-strategy'); + } + } + /** * @private */ @@ -332,7 +349,11 @@ export class LynxView extends HTMLElement { this.attachShadow({ mode: 'open' }); } const lynxGroupId = this.lynxGroupId; + const threadStrategy = (this.threadStrategy ?? 'multi-thread') as + | 'all-on-ui' + | 'multi-thread'; const lynxView = createLynxView({ + threadStrategy, tagMap, shadowRoot: this.shadowRoot!, templateUrl: this.#url, diff --git a/packages/web-platform/web-core/src/apis/createLynxView.ts b/packages/web-platform/web-core/src/apis/createLynxView.ts index ef0d4cb35a..468aa2f862 100644 --- a/packages/web-platform/web-core/src/apis/createLynxView.ts +++ b/packages/web-platform/web-core/src/apis/createLynxView.ts @@ -9,7 +9,10 @@ import type { sendGlobalEventEndpoint, UpdateDataType, } from '@lynx-js/web-constants'; -import { startUIThread } from '../uiThread/startUIThread.js'; +import { + startUIThread, + type StartUIThreadCallbacks, +} from '../uiThread/startUIThread.js'; import type { RpcCallType } from '@lynx-js/web-worker-rpc'; export interface LynxViewConfigs { @@ -17,11 +20,12 @@ export interface LynxViewConfigs { initData: Cloneable; globalProps: Cloneable; shadowRoot: ShadowRoot; - callbacks: Parameters[4]; + callbacks: StartUIThreadCallbacks; nativeModulesMap: NativeModulesMap; napiModulesMap: NapiModulesMap; tagMap: Record; lynxGroupId: number | undefined; + threadStrategy: 'all-on-ui' | 'multi-thread'; } export interface LynxView { @@ -45,6 +49,7 @@ export function createLynxView(configs: LynxViewConfigs): LynxView { napiModulesMap, tagMap, lynxGroupId, + threadStrategy = 'multi-thread', } = configs; return startUIThread( templateUrl, @@ -60,6 +65,7 @@ export function createLynxView(configs: LynxViewConfigs): LynxView { }, shadowRoot, lynxGroupId, + threadStrategy, callbacks, ); } diff --git a/packages/web-platform/web-core/src/uiThread/bootWorkers.ts b/packages/web-platform/web-core/src/uiThread/bootWorkers.ts index 2abf7d049f..e3662fcda4 100644 --- a/packages/web-platform/web-core/src/uiThread/bootWorkers.ts +++ b/packages/web-platform/web-core/src/uiThread/bootWorkers.ts @@ -15,12 +15,21 @@ const backgroundWorkerContextCount: number[] = []; const contextIdToBackgroundWorker: (Worker | undefined)[] = []; let preHeatedMainWorker = createMainWorker(); - export function bootWorkers( lynxGroupId: number | undefined, + allOnUI?: boolean, ): LynxViewRpc { - const curMainWorker = preHeatedMainWorker; - preHeatedMainWorker = createMainWorker(); + let curMainWorker: { + mainThreadRpc: Rpc; + mainThreadWorker?: Worker; + channelMainThreadWithBackground: MessageChannel; + }; + if (allOnUI) { + curMainWorker = createUIChannel(); + } else { + curMainWorker = preHeatedMainWorker; + preHeatedMainWorker = createMainWorker(); + } const curBackgroundWorker = createBackgroundWorker( lynxGroupId, curMainWorker.channelMainThreadWithBackground, @@ -32,12 +41,11 @@ export function bootWorkers( backgroundWorkerContextCount[lynxGroupId] = 1; } } - return { mainThreadRpc: curMainWorker.mainThreadRpc, backgroundRpc: curBackgroundWorker.backgroundRpc, terminateWorkers: () => { - curMainWorker.mainThreadWorker.terminate(); + curMainWorker.mainThreadWorker?.terminate(); if (lynxGroupId === undefined) { curBackgroundWorker.backgroundThreadWorker.terminate(); } else if (backgroundWorkerContextCount[lynxGroupId] === 1) { @@ -49,6 +57,18 @@ export function bootWorkers( }; } +function createUIChannel() { + const channelMainThreadWithBackground = new MessageChannel(); + const mainThreadRpc = new Rpc( + channelMainThreadWithBackground.port1, + 'main-to-bg', + ); + return { + mainThreadRpc, + channelMainThreadWithBackground, + }; +} + function createMainWorker() { const channelToMainThread = new MessageChannel(); const channelMainThreadWithBackground = new MessageChannel(); diff --git a/packages/web-platform/web-core/src/uiThread/createRenderAllOnUI.ts b/packages/web-platform/web-core/src/uiThread/createRenderAllOnUI.ts new file mode 100644 index 0000000000..cf5ce26955 --- /dev/null +++ b/packages/web-platform/web-core/src/uiThread/createRenderAllOnUI.ts @@ -0,0 +1,54 @@ +import type { + MainThreadStartConfigs, + RpcCallType, + updateDataEndpoint, +} from '@lynx-js/web-constants'; +import type { MainThreadRuntime } from '@lynx-js/web-mainthread-apis'; +import { Rpc } from '@lynx-js/web-worker-rpc'; + +const { + loadMainThread, +} = await import('@lynx-js/web-mainthread-apis'); + +export function createRenderAllOnUI( + mainToBackgroundRpc: Rpc, + shadowRoot: ShadowRoot, + markTimingInternal: ( + timingKey: string, + pipelineId?: string, + timeStamp?: number, + ) => void, + callbacks: { + onError?: () => void; + }, +) { + if (!globalThis.module) { + Object.assign(globalThis, { module: {} }); + } + const docu = Object.assign(shadowRoot, { + createElement: document.createElement.bind(document), + }); + const { startMainThread } = loadMainThread( + mainToBackgroundRpc, + docu, + () => {}, + markTimingInternal, + () => { + callbacks.onError?.(); + }, + ); + let runtime!: MainThreadRuntime; + const start = async (configs: MainThreadStartConfigs) => { + const mainThreadRuntime = startMainThread(configs); + runtime = await mainThreadRuntime; + }; + const updateDataMainThread: RpcCallType = async ( + ...args + ) => { + runtime.updatePage?.(...args); + }; + return { + start, + updateDataMainThread, + }; +} diff --git a/packages/web-platform/web-core/src/uiThread/createRenderMultiThread.ts b/packages/web-platform/web-core/src/uiThread/createRenderMultiThread.ts new file mode 100644 index 0000000000..88df0697c0 --- /dev/null +++ b/packages/web-platform/web-core/src/uiThread/createRenderMultiThread.ts @@ -0,0 +1,32 @@ +import { + mainThreadStartEndpoint, + updateDataEndpoint, +} from '@lynx-js/web-constants'; +import type { Rpc } from '@lynx-js/web-worker-rpc'; +import { registerReportErrorHandler } from './crossThreadHandlers/registerReportErrorHandler.js'; +import { registerFlushElementTreeHandler } from './crossThreadHandlers/registerFlushElementTreeHandler.js'; + +export function createRenderMultiThread( + mainThreadRpc: Rpc, + shadowRoot: ShadowRoot, + callbacks: { + onError?: () => void; + }, +) { + registerReportErrorHandler( + mainThreadRpc, + callbacks.onError, + ); + registerFlushElementTreeHandler( + mainThreadRpc, + { + shadowRoot, + }, + ); + const start = mainThreadRpc.createCall(mainThreadStartEndpoint); + const updateDataMainThread = mainThreadRpc.createCall(updateDataEndpoint); + return { + start, + updateDataMainThread, + }; +} diff --git a/packages/web-platform/web-core/src/uiThread/crossThreadHandlers/createUpdateData.ts b/packages/web-platform/web-core/src/uiThread/crossThreadHandlers/createUpdateData.ts index 403d87a673..10e2206210 100644 --- a/packages/web-platform/web-core/src/uiThread/crossThreadHandlers/createUpdateData.ts +++ b/packages/web-platform/web-core/src/uiThread/crossThreadHandlers/createUpdateData.ts @@ -2,7 +2,7 @@ // Licensed under the Apache License Version 2.0 that can be found in the // LICENSE file in the root directory of this source tree. -import type { Rpc } from '@lynx-js/web-worker-rpc'; +import type { RpcCallType } from '@lynx-js/web-worker-rpc'; import type { LynxView } from '../../apis/createLynxView.js'; import { updateDataEndpoint, @@ -11,8 +11,8 @@ import { } from '@lynx-js/web-constants'; export function createUpdateData( - mainThreadRpc: Rpc, - backgroundRpc: Rpc, + updateDataMainThread: RpcCallType, + updateDataBackground: RpcCallType, ): LynxView['updateData'] { return ( data: Cloneable, @@ -21,8 +21,8 @@ export function createUpdateData( ) => { Promise.all([ // There is no need to process options for now, as they have default values. - mainThreadRpc.invoke(updateDataEndpoint, [data, {}]), - backgroundRpc.invoke(updateDataEndpoint, [data, {}]), + updateDataMainThread(data, {}), + updateDataBackground(data, {}), ]).then(() => callback?.()); }; } diff --git a/packages/web-platform/web-core/src/uiThread/startBackground.ts b/packages/web-platform/web-core/src/uiThread/startBackground.ts new file mode 100644 index 0000000000..9d05459cf7 --- /dev/null +++ b/packages/web-platform/web-core/src/uiThread/startBackground.ts @@ -0,0 +1,59 @@ +import { + markTimingEndpoint, + sendGlobalEventEndpoint, + updateDataEndpoint, + type NapiModulesCall, + type NativeModulesCall, +} from '@lynx-js/web-constants'; +import type { Rpc } from '@lynx-js/web-worker-rpc'; +import { registerInvokeUIMethodHandler } from './crossThreadHandlers/registerInvokeUIMethodHandler.js'; +import { registerNativePropsHandler } from './crossThreadHandlers/registerSetNativePropsHandler.js'; +import { registerNativeModulesCallHandler } from './crossThreadHandlers/registerNativeModulesCallHandler.js'; +import { registerTriggerComponentEventHandler } from './crossThreadHandlers/registerTriggerComponentEventHandler.js'; +import { registerSelectComponentHandler } from './crossThreadHandlers/registerSelectComponentHandler.js'; +import { registerNapiModulesCallHandler } from './crossThreadHandlers/registerNapiModulesCallHandler.js'; +import { registerDispatchLynxViewEventHandler } from './crossThreadHandlers/registerDispatchLynxViewEventHandler.js'; + +export function startBackground( + backgroundRpc: Rpc, + shadowRoot: ShadowRoot, + callbacks: { + nativeModulesCall: NativeModulesCall; + napiModulesCall: NapiModulesCall; + }, +) { + registerInvokeUIMethodHandler( + backgroundRpc, + shadowRoot, + ); + registerNativePropsHandler( + backgroundRpc, + shadowRoot, + ); + registerTriggerComponentEventHandler( + backgroundRpc, + shadowRoot, + ); + registerSelectComponentHandler( + backgroundRpc, + shadowRoot, + ); + registerNativeModulesCallHandler( + backgroundRpc, + callbacks.nativeModulesCall, + ); + registerNapiModulesCallHandler( + backgroundRpc, + callbacks.napiModulesCall, + ); + registerDispatchLynxViewEventHandler(backgroundRpc, shadowRoot); + + const sendGlobalEvent = backgroundRpc.createCall(sendGlobalEventEndpoint); + const markTiming = backgroundRpc.createCall(markTimingEndpoint); + const updateDataBackground = backgroundRpc.createCall(updateDataEndpoint); + return { + sendGlobalEvent, + markTiming, + updateDataBackground, + }; +} diff --git a/packages/web-platform/web-core/src/uiThread/startUIThread.ts b/packages/web-platform/web-core/src/uiThread/startUIThread.ts index af8e9b49aa..48fffecded 100644 --- a/packages/web-platform/web-core/src/uiThread/startUIThread.ts +++ b/packages/web-platform/web-core/src/uiThread/startUIThread.ts @@ -3,19 +3,9 @@ // LICENSE file in the root directory of this source tree. import type { LynxView } from '../apis/createLynxView.js'; -import { registerInvokeUIMethodHandler } from './crossThreadHandlers/registerInvokeUIMethodHandler.js'; -import { registerNativePropsHandler } from './crossThreadHandlers/registerSetNativePropsHandler.js'; -import { registerNativeModulesCallHandler } from './crossThreadHandlers/registerNativeModulesCallHandler.js'; import { bootWorkers } from './bootWorkers.js'; -import { registerReportErrorHandler } from './crossThreadHandlers/registerReportErrorHandler.js'; -import { registerFlushElementTreeHandler } from './crossThreadHandlers/registerFlushElementTreeHandler.js'; import { createDispose } from './crossThreadHandlers/createDispose.js'; -import { registerTriggerComponentEventHandler } from './crossThreadHandlers/registerTriggerComponentEventHandler.js'; -import { registerSelectComponentHandler } from './crossThreadHandlers/registerSelectComponentHandler.js'; import { - mainThreadStartEndpoint, - markTimingEndpoint, - sendGlobalEventEndpoint, type LynxTemplate, type MainThreadStartConfigs, type NapiModulesCall, @@ -23,30 +13,37 @@ import { } from '@lynx-js/web-constants'; import { loadTemplate } from '../utils/loadTemplate.js'; import { createUpdateData } from './crossThreadHandlers/createUpdateData.js'; -import { registerNapiModulesCallHandler } from './crossThreadHandlers/registerNapiModulesCallHandler.js'; -import { registerDispatchLynxViewEventHandler } from './crossThreadHandlers/registerDispatchLynxViewEventHandler.js'; +import { startBackground } from './startBackground.js'; +import { createRenderMultiThread } from './createRenderMultiThread.js'; +import { createRenderAllOnUI } from './createRenderAllOnUI.js'; + +export type StartUIThreadCallbacks = { + nativeModulesCall: NativeModulesCall; + napiModulesCall: NapiModulesCall; + onError?: () => void; + customTemplateLoader?: (url: string) => Promise; +}; export function startUIThread( templateUrl: string, configs: Omit, shadowRoot: ShadowRoot, lynxGroupId: number | undefined, - callbacks: { - nativeModulesCall: NativeModulesCall; - napiModulesCall: NapiModulesCall; - onError?: () => void; - customTemplateLoader?: (url: string) => Promise; - }, + threadStrategy: 'all-on-ui' | 'multi-thread', + callbacks: StartUIThreadCallbacks, ): LynxView { const createLynxStartTiming = performance.now() + performance.timeOrigin; + const allOnUI = threadStrategy === 'all-on-ui'; const { mainThreadRpc, backgroundRpc, terminateWorkers, - } = bootWorkers(lynxGroupId); - const sendGlobalEvent = backgroundRpc.createCall(sendGlobalEventEndpoint); - const mainThreadStart = mainThreadRpc.createCall(mainThreadStartEndpoint); - const markTiming = backgroundRpc.createCall(markTimingEndpoint); + } = bootWorkers(lynxGroupId, allOnUI); + const { markTiming, sendGlobalEvent, updateDataBackground } = startBackground( + backgroundRpc, + shadowRoot, + callbacks, + ); const markTimingInternal = ( timingKey: string, pipelineId?: string, @@ -55,52 +52,29 @@ export function startUIThread( if (!timeStamp) timeStamp = performance.now() + performance.timeOrigin; markTiming(timingKey, pipelineId, timeStamp); }; + const { start, updateDataMainThread } = allOnUI + ? createRenderAllOnUI( + /* main-to-bg rpc*/ mainThreadRpc, + shadowRoot, + markTimingInternal, + callbacks, + ) + : createRenderMultiThread( + /* main-to-ui rpc*/ mainThreadRpc, + shadowRoot, + callbacks, + ); markTimingInternal('create_lynx_start', undefined, createLynxStartTiming); markTimingInternal('load_template_start'); loadTemplate(templateUrl, callbacks.customTemplateLoader).then((template) => { markTimingInternal('load_template_end'); - mainThreadStart({ + start({ ...configs, template, }); }); - registerReportErrorHandler( - mainThreadRpc, - callbacks.onError, - ); - registerDispatchLynxViewEventHandler(backgroundRpc, shadowRoot); - registerFlushElementTreeHandler( - mainThreadRpc, - { - shadowRoot, - }, - ); - registerInvokeUIMethodHandler( - backgroundRpc, - shadowRoot, - ); - registerNativePropsHandler( - backgroundRpc, - shadowRoot, - ); - registerTriggerComponentEventHandler( - backgroundRpc, - shadowRoot, - ); - registerSelectComponentHandler( - backgroundRpc, - shadowRoot, - ); - registerNativeModulesCallHandler( - backgroundRpc, - callbacks.nativeModulesCall, - ); - registerNapiModulesCallHandler( - backgroundRpc, - callbacks.napiModulesCall, - ); return { - updateData: createUpdateData(mainThreadRpc, backgroundRpc), + updateData: createUpdateData(updateDataMainThread, updateDataBackground), dispose: createDispose( backgroundRpc, terminateWorkers, diff --git a/packages/web-platform/web-mainthread-apis/src/MainThreadRuntime.ts b/packages/web-platform/web-mainthread-apis/src/MainThreadRuntime.ts index a459d733e5..efd9e0ef6e 100644 --- a/packages/web-platform/web-mainthread-apis/src/MainThreadRuntime.ts +++ b/packages/web-platform/web-mainthread-apis/src/MainThreadRuntime.ts @@ -57,7 +57,7 @@ export interface MainThreadConfig { callbacks: MainThreadRuntimeCallbacks; styleInfo: StyleInfo; customSections: LynxTemplate['customSections']; - lepusCode: LynxTemplate['lepusCode']; + lepusCode: Record; browserConfig: BrowserConfig; tagMap: Record; docu: Pick; @@ -226,24 +226,14 @@ export class MainThreadRuntime { __OnLifecycleEvent: (lifeCycleEvent: Cloneable) => void; __LoadLepusChunk: (path: string) => boolean = (path) => { - try { - // @ts-expect-error - if (self.WorkerGlobalScope) { - const lepusChunkUrl = this.config.lepusCode[`${path}`]; - if (lepusChunkUrl) path = lepusChunkUrl; - // @ts-expect-error - importScripts(path); - const entry = (globalThis.module as LynxJSModule).exports; - entry?.(this); - } else { - throw new Error( - 'importing scripts synchronously is only available for the multi-thread running mode', - ); - } + const lepusModule = this.config.lepusCode[`${path}`]; + if (lepusModule) { + const entry = lepusModule.exports; + entry?.(this); return true; - } catch { + } else { + return false; } - return false; }; __FlushElementTree = ( @@ -252,7 +242,7 @@ export class MainThreadRuntime { ) => { const timingFlags = this._timingFlags; this._timingFlags = []; - if (this._page && !this._page.parentElement) { + if (this._page && !this._page.parentNode) { this._rootDom.append(this._page); } this.config.callbacks.flushElementTree(options, timingFlags); diff --git a/packages/web-platform/web-mainthread-apis/src/loadMainThread.ts b/packages/web-platform/web-mainthread-apis/src/loadMainThread.ts index 2f3fbc9446..a1062e2ce6 100644 --- a/packages/web-platform/web-mainthread-apis/src/loadMainThread.ts +++ b/packages/web-platform/web-mainthread-apis/src/loadMainThread.ts @@ -25,6 +25,8 @@ import { switchExposureService, } from './MainThreadRuntime.js'; +const moduleCache: Record = {}; + export function loadMainThread( backgroundThreadRpc: Rpc, docu: Pick, @@ -61,10 +63,23 @@ export function loadMainThread( const { styleInfo, pageConfig, customSections, cardType, lepusCode } = template; markTimingInternal('decode_start'); - await import( - /* webpackIgnore: true */ template.lepusCode.root + const lepusCodeEntries = await Promise.all( + Object.entries(lepusCode).map(async ([name, url]) => { + const cachedModule = moduleCache[name]; + if (cachedModule) { + return [name, cachedModule] as [string, LynxJSModule]; + } else { + Object.assign(globalThis, { module: {} }); + await import(/* webpackIgnore: true */ url); + const module = globalThis.module as LynxJSModule; + Object.assign(globalThis, { module: {} }); + moduleCache[name] = module; + return [name, module] as [string, LynxJSModule]; + } + }), ); - const entry = (globalThis.module as LynxJSModule).exports!; + const lepusCodeLoaded = Object.fromEntries(lepusCodeEntries); + const entry = lepusCodeLoaded['root']!.exports; const jsContext = new LynxCrossThreadContext({ rpc: backgroundThreadRpc, receiveEventEndpoint: dispatchJSContextOnMainThreadEndpoint, @@ -78,7 +93,7 @@ export function loadMainThread( globalProps, pageConfig, styleInfo, - lepusCode, + lepusCode: lepusCodeLoaded, docu, callbacks: { mainChunkReady: () => { diff --git a/packages/web-platform/web-tests/playwright.config.ts b/packages/web-platform/web-tests/playwright.config.ts index 456b5c8187..34c80a9b38 100644 --- a/packages/web-platform/web-tests/playwright.config.ts +++ b/packages/web-platform/web-tests/playwright.config.ts @@ -7,6 +7,7 @@ import { defineConfig, devices } from '@playwright/test'; process.env['LIBGL_ALWAYS_SOFTWARE'] = 'true'; // https://github.com/microsoft/playwright/issues/32151 process.env['GALLIUM_HUD_SCALE'] = '1'; const isCI = !!process.env.CI; +const ALL_ON_UI = !!process.env.ALL_ON_UI; const port = process.env.PORT ?? 3080; const workerLimit = process.env['cpu_limit'] ? Math.floor(parseFloat(process.env['cpu_limit']) / 2) @@ -25,6 +26,7 @@ export default defineConfig({ /** global timeout https://playwright.dev/docs/test-timeouts#global-timeout */ globalTimeout: 20 * 60 * 1000, testDir: './tests', + testMatch: ALL_ON_UI ? '**/{react,web-core}.{test,spec}.ts' : undefined, /* Run tests in files in parallel */ fullyParallel: true, workers: isCI ? workerLimit : undefined, diff --git a/packages/web-platform/web-tests/rspack.config.js b/packages/web-platform/web-tests/rspack.config.js index baa7c793f6..5630b319f5 100644 --- a/packages/web-platform/web-tests/rspack.config.js +++ b/packages/web-platform/web-tests/rspack.config.js @@ -26,6 +26,9 @@ const config = { }, }, plugins: [ + new rspack.DefinePlugin({ + 'process.env.ALL_ON_UI': JSON.stringify(process.env.ALL_ON_UI), + }), new rspack.HtmlRspackPlugin({ title: 'lynx-for-web-test', meta: { diff --git a/packages/web-platform/web-tests/shell-project/index.ts b/packages/web-platform/web-tests/shell-project/index.ts index 35afdcdce5..50bcec71f1 100644 --- a/packages/web-platform/web-tests/shell-project/index.ts +++ b/packages/web-platform/web-tests/shell-project/index.ts @@ -5,6 +5,7 @@ import type { LynxTemplate } from '@lynx-js/web-core'; import { lynxViewTests } from './lynx-view.ts'; +const ALL_ON_UI = !!process.env.ALL_ON_UI; const nativeModulesMap = { CustomModule: URL.createObjectURL( new Blob( @@ -33,6 +34,7 @@ if (casename) { const dir2 = `/dist/${casename2}${hasdir ? `/${casename2}` : ''}`; lynxViewTests(lynxView => { lynxView.setAttribute('url', `${dir}/index.web.json`); + if (ALL_ON_UI) lynxView.setAttribute('thread-strategy', `all-on-ui`); lynxView.nativeModulesMap = nativeModulesMap; lynxView.id = 'lynxview1'; if (casename2) { diff --git a/packages/web-platform/web-tests/shell-project/web-core.ts b/packages/web-platform/web-tests/shell-project/web-core.ts index 2158e01305..6af86c16c3 100644 --- a/packages/web-platform/web-tests/shell-project/web-core.ts +++ b/packages/web-platform/web-tests/shell-project/web-core.ts @@ -8,6 +8,7 @@ import '@lynx-js/web-elements-compat/LinearContainer'; import '@lynx-js/web-core/index.css'; import './index.css'; +const ALL_ON_UI = !!process.env.ALL_ON_UI; const color_environment = URL.createObjectURL( new Blob( [`export default function(NapiModules, NapiModulesCall) { @@ -62,6 +63,7 @@ async function run() { const lepusjs = '/resources/web-core.main-thread.json'; const lynxView = document.createElement('lynx-view') as LynxView; lynxView.setAttribute('url', lepusjs); + if (ALL_ON_UI) lynxView.setAttribute('thread-strategy', `all-on-ui`); lynxView.initData = { mockData: 'mockData' }; lynxView.globalProps = { pink: 'pink' }; lynxView.height = 'auto'; diff --git a/packages/web-platform/web-tests/tests/react.spec.ts b/packages/web-platform/web-tests/tests/react.spec.ts index 7d800bb66b..0a3bb4ce3c 100644 --- a/packages/web-platform/web-tests/tests/react.spec.ts +++ b/packages/web-platform/web-tests/tests/react.spec.ts @@ -4,6 +4,7 @@ import { swipe, dragAndHold } from './utils.js'; import { test, expect } from './coverage-fixture.js'; import type { Page } from '@playwright/test'; +const ALL_ON_UI = !!process.env['ALL_ON_UI']; const wait = async (ms: number) => { await new Promise((resolve) => { @@ -577,14 +578,14 @@ test.describe('reactlynx3 tests', () => { await goto(page, title); const target = page.locator('#target'); await expect(target).toHaveCSS('background-color', 'rgb(255, 192, 203)'); // pink - expect(page.workers().length).toStrictEqual(3); + expect(page.workers().length).toStrictEqual(ALL_ON_UI ? 2 : 3); }); test('api-preheat-at-least-one', async ({ page }, { title }) => { await goto(page, title); const target = page.locator('#target'); await expect(target).toHaveCSS('background-color', 'rgb(255, 192, 203)'); // pink - expect(page.workers().length).toBe(3); + expect(page.workers().length).toBe(ALL_ON_UI ? 2 : 3); await page.evaluate(() => { document.body.querySelector('lynx-view')?.remove(); }); @@ -1064,6 +1065,7 @@ test.describe('reactlynx3 tests', () => { test( 'config-splitchunk-single-vendor', async ({ page }, { title }) => { + test.skip(ALL_ON_UI, 'main thread do not support importScript'); await goto(page, title, undefined, true); await wait(1500); const target = page.locator('#target'); @@ -1073,6 +1075,7 @@ test.describe('reactlynx3 tests', () => { test( 'config-splitchunk-split-by-experience', async ({ page }, { title }) => { + test.skip(ALL_ON_UI, 'main thread do not support importScript'); await goto(page, title, undefined, true); await wait(1500); const target = page.locator('#target'); @@ -1082,6 +1085,7 @@ test.describe('reactlynx3 tests', () => { test( 'config-splitchunk-split-by-module', async ({ page }, { title }) => { + test.skip(ALL_ON_UI, 'main thread do not support importScript'); await goto(page, title, undefined, true); await wait(1500); const target = page.locator('#target'); diff --git a/packages/web-platform/web-tests/tests/web-core.test.ts b/packages/web-platform/web-tests/tests/web-core.test.ts index b329abdf7c..72bc6f0f51 100644 --- a/packages/web-platform/web-tests/tests/web-core.test.ts +++ b/packages/web-platform/web-tests/tests/web-core.test.ts @@ -5,6 +5,7 @@ import { test, expect } from './coverage-fixture.js'; import type { Page, Worker } from '@playwright/test'; +const ALL_ON_UI = !!process.env.ALL_ON_UI; const wait = async (ms: number) => { await new Promise((resolve) => { setTimeout(resolve, ms); @@ -18,16 +19,22 @@ const goto = async (page: Page) => { await wait(500); }; -async function getMainThreadWorker(page: Page): Promise { +async function getMainThreadWorker( + page: Page, +): Promise { await wait(100); - for (const i of page.workers()) { - const isActive = await i.evaluate(() => { - return globalThis.runtime !== undefined - && globalThis.__lynx_worker_type === 'main'; - }); + if (ALL_ON_UI) { + return page; + } else { + for (const i of page.workers()) { + const isActive = await i.evaluate(() => { + return globalThis.runtime !== undefined + && globalThis.__lynx_worker_type === 'main'; + }); - if (isActive) { - return i; + if (isActive) { + return i; + } } } } diff --git a/packages/web-platform/web-worker-rpc/src/Rpc.ts b/packages/web-platform/web-worker-rpc/src/Rpc.ts index bd4e2856ae..18cbf08ddc 100644 --- a/packages/web-platform/web-worker-rpc/src/Rpc.ts +++ b/packages/web-platform/web-worker-rpc/src/Rpc.ts @@ -93,7 +93,7 @@ export class Rpc { ) => void = async ( message, ) => { - console.warn(`[rpc] on ${this.name} received ${message.name}`, message); + // console.warn(`[rpc] on ${this.name} received ${message.name}`, message); const handler = this.#handlerMap.get(message.name); if (handler) { const lockViewer = message.sync diff --git a/packages/web-platform/web-worker-runtime/src/mainThread/startMainThread.ts b/packages/web-platform/web-worker-runtime/src/mainThread/startMainThread.ts index 41e03ba381..4918e458d3 100644 --- a/packages/web-platform/web-worker-runtime/src/mainThread/startMainThread.ts +++ b/packages/web-platform/web-worker-runtime/src/mainThread/startMainThread.ts @@ -9,11 +9,11 @@ import { reportErrorEndpoint, } from '@lynx-js/web-constants'; import { Rpc } from '@lynx-js/web-worker-rpc'; -import { loadMainThread } from '@lynx-js/web-mainthread-apis'; import { createMarkTimingInternal } from './crossThreadHandlers/createMainthreadMarkTimingInternal.js'; import { OffscreenDocument } from '@lynx-js/offscreen-document/webworker'; import { _onEvent } from '@lynx-js/offscreen-document/webworker'; import { registerUpdateDataHandler } from './crossThreadHandlers/registerUpdateDataHandler.js'; +const { loadMainThread } = await import('@lynx-js/web-mainthread-apis'); export function startMainThread( uiThreadPort: MessagePort, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 589539edb1..457d127367 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -646,6 +646,9 @@ importers: '@lynx-js/web-constants': specifier: workspace:* version: link:../web-constants + '@lynx-js/web-mainthread-apis': + specifier: workspace:* + version: link:../web-mainthread-apis '@lynx-js/web-worker-rpc': specifier: workspace:* version: link:../web-worker-rpc From d2e3bf2bcc766ccd891be148c659ef5acace7160 Mon Sep 17 00:00:00 2001 From: Qingyu Wang <40660121+colinaaa@users.noreply.github.com> Date: Sun, 27 Apr 2025 15:45:02 +0800 Subject: [PATCH 3/4] chore: bump dprint plugins (#476) ## Summary ## Checklist - [ ] Tests updated (or not required). - [ ] Documentation updated (or not required). --- .cargo/nextest.toml | 1 - .changeset/hip-seals-read.md | 1 + .changeset/rude-pears-open.md | 1 + .changeset/small-friends-grin.md | 1 + .dprint.jsonc | 18 ++-- cspell.jsonc | 2 + .../web-elements/src/common-css/linear.css | 18 ++-- packages/web-platform/web-explorer/index.html | 81 ++++++++--------- .../filter-image/basic-placeholder.html | 2 +- .../web-elements/filter-image/basic.html | 2 +- .../filter-image/blur-radius.html | 2 +- .../filter-image/drop-shadow.html | 2 +- .../filter-image/event-error.html | 16 ++-- .../web-elements/filter-image/event-load.html | 18 ++-- .../mode-aspectfill-placeholder.html | 2 +- .../filter-image/mode-aspectfill.html | 2 +- .../mode-aspectfit-placeholder.html | 2 +- .../filter-image/mode-aspectfit.html | 2 +- .../filter-image/mode-center-placeholder.html | 2 +- .../filter-image/mode-center.html | 2 +- .../layout/flex-lynx-computed-direction.html | 12 +-- .../layout/flex-lynx-computed-grow.html | 4 +- .../layout/flex-lynx-computed-shrink.html | 8 +- .../lynx-display-do-not-use-flatten-tree.html | 8 +- .../percentage-cyclic-sibiling-linear.html | 12 +-- .../layout/percentage-cyclic-sibiling.html | 12 +-- .../layout/percentage-cyclic-text.html | 4 +- .../layout/percentage-cyclic.html | 9 +- .../performance/div-10000-fp.html | 12 +-- .../web-elements/performance/div-10000.html | 12 +-- .../web-elements/performance/p-10000.html | 16 ++-- .../performance/raw-text-large.html | 10 ++- .../react-10000-div-with-layouteffect.html | 59 ++++++------ .../performance/react-10000-div.html | 18 ++-- .../web-elements/performance/set-lycss.html | 10 +-- .../performance/simple-append-two-dom.html | 6 +- .../performance/x-list-waterfall-1000.html | 42 ++++----- .../performance/x-text-large.html | 16 ++-- .../performance/x-text-with-font.html | 8 +- .../performance/x-view-10000-fp.html | 12 +-- .../performance/x-view-10000.html | 12 +-- .../tests/web-elements/scroll-view/basic.html | 20 ++--- .../scroll-view/bounces-false.html | 10 +-- .../scroll-view/event-scroll.html | 8 +- .../scroll-view/event-scrollend.html | 8 +- .../scroll-view/event-scrolltolower.html | 22 +++-- .../scroll-view/fading-edge-length.html | 10 +-- .../scroll-view/method-auto-scroll.html | 8 +- .../scroll-view/scroll-into-view-basic-x.html | 44 ++++----- .../scroll-view/scroll-into-view-basic.html | 50 +++++------ .../scroll-into-view-nested-scroll-view.html | 22 ++--- .../scroll-view/scroll-into-view-text-x.html | 44 ++++----- .../scroll-view/scroll-into-view-text.html | 50 +++++------ .../web-elements/scroll-view/scroll-left.html | 18 ++-- .../scroll-view/scroll-to-index.html | 10 +-- .../web-elements/scroll-view/scroll-to.html | 18 ++-- .../web-elements/scroll-view/scroll-top.html | 18 ++-- .../scroll-view/scroll-view-absolute-kid.html | 10 ++- .../scroll-view-item-percentage-size.html | 12 +-- .../scroll-view-linear-gravity-scroll.html | 82 ++++++++--------- .../scroll-view-linear-gravity.html | 82 ++++++++--------- .../scroll-view/scroll-view-must-linear.html | 7 +- .../scroll-view-overwrite-direction.html | 10 +-- .../scroll-view/scroll-view-padding.html | 10 +-- .../scroll-view-size-in-flex-column.html | 10 +-- .../scroll-view-size-in-flex-row.html | 10 +-- ...rollable-even-inline-overflow-visible.html | 10 +-- .../x-audio-tt/attribute-interval.html | 12 +-- .../x-audio-tt/attribute-loop-close.html | 21 +++-- .../x-audio-tt/attribute-loop.html | 9 +- .../x-audio-tt/attribute-pause-on-hide.html | 9 +- .../x-audio-tt/attribute-src-change.html | 35 +++++--- .../x-audio-tt/event-error-playback.html | 15 ++-- .../x-audio-tt/event-error-src-json.html | 19 ++-- .../x-audio-tt/event-error-src.html | 15 ++-- .../x-audio-tt/event-finished.html | 15 ++-- .../event-playbackstatechanged.html | 33 ++++--- .../web-elements/x-audio-tt/event-seek.html | 26 ++++-- .../event-srcloadingstatechanged.html | 12 +-- .../web-elements/x-audio-tt/method-mute.html | 9 +- .../web-elements/x-audio-tt/method-pause.html | 18 ++-- .../web-elements/x-audio-tt/method-play.html | 9 +- .../x-audio-tt/method-player-info.html | 18 ++-- .../x-audio-tt/method-prepare.html | 28 +++--- .../x-audio-tt/method-resume.html | 27 ++++-- .../web-elements/x-audio-tt/method-seek.html | 20 +++-- .../x-audio-tt/method-set-volume.html | 22 +++-- .../web-elements/x-audio-tt/method-stop.html | 18 ++-- .../tests/web-elements/x-blur-view/basic.html | 6 +- .../x-foldview-ng/basic-fling.html | 28 +++--- .../basic-with-lynx-wrapper.html | 26 +++--- .../web-elements/x-foldview-ng/basic.html | 26 +++--- .../event-offset-granularity.html | 26 +++--- ...e-controled-by-parent-flex-cross-axis.html | 10 +-- .../size-header-could-from-children.html | 28 +++--- .../size-header-height-enough.html | 28 +++--- .../size-parent-grow-children-specific.html | 28 +++--- .../size-toolbar-and-slot-size-lager.html | 28 +++--- .../size-toolbar-could-from-children.html | 30 +++---- ...size-toolbar-slot-defines-parent-size.html | 28 +++--- .../size-toolbar-slot-share-flex-parent.html | 28 +++--- .../x-foldview-ng/swipe-basic.html | 26 +++--- .../swipe-with-x-scroll-view.html | 26 +++--- .../x-foldview-ng/with-x-refresh-view.html | 34 +++---- .../with-x-viewpager-ng-pan-both-x-and-y.html | 28 +++--- .../x-foldview-ng/with-x-viewpager-ng.html | 28 +++--- .../web-elements/x-image/basic-inherit.html | 2 +- .../x-image/basic-placeholder.html | 2 +- .../tests/web-elements/x-image/basic.html | 2 +- .../web-elements/x-image/blur-radius.html | 2 +- .../web-elements/x-image/border-radius.html | 2 +- .../web-elements/x-image/event-error.html | 16 ++-- .../web-elements/x-image/event-load.html | 18 ++-- .../x-image/mode-aspectfill-placeholder.html | 2 +- .../web-elements/x-image/mode-aspectfill.html | 2 +- .../x-image/mode-aspectfit-placeholder.html | 2 +- .../web-elements/x-image/mode-aspectfit.html | 2 +- .../x-image/mode-center-placeholder.html | 2 +- .../web-elements/x-image/mode-center.html | 2 +- ...der-src-change-with-placeholder-exist.html | 2 +- .../x-image/placeholder-src-do-exist.html | 2 +- .../x-image/placeholder-src-not-exist.html | 2 +- .../web-elements/x-image/position-basic.html | 6 +- .../tests/web-elements/x-image/position.html | 6 +- .../x-input/attribute-confirm-type-done.html | 2 +- .../x-input/attribute-confirm-type-go.html | 2 +- .../x-input/attribute-confirm-type-next.html | 2 +- .../attribute-confirm-type-search.html | 2 +- .../x-input/attribute-confirm-type-send.html | 2 +- .../x-input/attribute-disabled.html | 2 +- ...-maxlength-change-do-not-change-value.html | 2 +- ...bute-maxlength-first-screen-cut-value.html | 2 +- .../x-input/attribute-readonly.html | 2 +- .../x-input/attribute-spell-check.html | 2 +- .../x-input/attribute-type-digit.html | 2 +- .../x-input/attribute-type-email.html | 2 +- .../x-input/attribute-type-number.html | 2 +- .../x-input/attribute-type-tel.html | 2 +- .../x-input/attribute-type-text.html | 2 +- .../web-elements/x-input/attribute-value.html | 2 +- .../web-elements/x-input/event-confirm.html | 2 +- .../x-input/event-focus-blur.html | 2 +- .../x-input/event-input-number-dot.html | 2 +- .../web-elements/x-input/event-input.html | 2 +- .../tests/web-elements/x-input/method.html | 2 +- .../x-input/placeholder-color.html | 2 +- .../x-input/placeholder-weight.html | 2 +- .../web-elements/x-input/placeholder.html | 2 +- .../press-enter-do-not-submit-value.html | 2 +- .../x-input/style-background-color.html | 8 +- .../x-input/style-inherit-color.html | 8 +- .../x-input/style-inherit-margin.html | 8 +- .../web-elements/x-input/type-password.html | 2 +- .../x-input/type-value-do-not-show-input.html | 2 +- .../web-elements/x-list/auto-scroll.html | 61 +++++++------ .../x-list/axios-gap-waterfall.html | 26 +++--- .../web-elements/x-list/axis-gap-flow.html | 90 +++++++++---------- .../tests/web-elements/x-list/axis-gap.html | 90 +++++++++---------- .../tests/web-elements/x-list/basic-flow.html | 46 +++++----- .../web-elements/x-list/basic-waterfall.html | 26 +++--- .../tests/web-elements/x-list/basic.html | 40 ++++----- .../web-elements/x-list/enable-scroll.html | 40 ++++----- .../x-list/event-layoutcomplete.html | 49 +++++----- .../x-list/event-lower-load-more.html | 65 +++++++------- .../event-lower-threshold-item-count.html | 58 ++++++------ .../web-elements/x-list/event-scroll.html | 58 ++++++------ .../x-list/event-scrolltolower.html | 49 +++++----- .../event-scrolltoupper-tolower-flow.html | 64 +++++++------ ...event-scrolltoupper-tolower-waterfall.html | 44 +++++---- .../x-list/event-scrolltoupper.html | 49 +++++----- .../tests/web-elements/x-list/event-snap.html | 44 ++++----- .../x-list/full-span-waterfall.html | 26 +++--- .../tests/web-elements/x-list/full-span.html | 90 +++++++++---------- .../x-list/get-scroll-container-info.html | 40 ++++----- .../x-list/get-visible-cells.html | 40 ++++----- .../x-list/initial-scroll-index.html | 40 ++++----- .../tests/web-elements/x-list/item-snap.html | 40 ++++----- .../x-list/need-visible-item-info.html | 67 ++++++++------ .../x-list/scroll-orientation-flow.html | 46 +++++----- .../x-list/scroll-orientation-waterfall.html | 2 +- .../x-list/scroll-orientation.html | 82 ++++++++--------- .../x-list/scroll-to-position.html | 51 ++++++----- .../web-elements/x-list/sticky-flow.html | 46 +++++----- .../web-elements/x-list/sticky-offset.html | 44 ++++----- .../web-elements/x-list/sticky-waterfall.html | 26 +++--- .../tests/web-elements/x-list/sticky.html | 40 ++++----- .../x-overlay-ng/basic-z-index.html | 11 +-- .../x-overlay-ng/event-layoutchange.html | 13 +-- .../web-elements/x-refresh-view/basic.html | 11 ++- .../enable-auto-loadmore-false.html | 20 +++-- .../enable-auto-loadmore-true.html | 20 +++-- .../x-refresh-view/enable-loadmore-false.html | 32 ++++--- .../x-refresh-view/enable-refresh-false.html | 32 ++++--- .../x-refresh-view/event-footerreleased.html | 20 +++-- .../x-refresh-view/event-headeroffset.html | 20 +++-- .../x-refresh-view/event-headerreleased.html | 20 +++-- .../x-refresh-view/event-headershow.html | 20 +++-- .../x-refresh-view/header-methods.html | 32 ++++--- .../web-elements/x-refresh-view/pull.html | 32 ++++--- .../x-swiper-basic-autoplay-interval.html | 8 +- .../x-swiper/x-swiper-basic-autoplay.html | 8 +- .../x-swiper-basic-circular-autoplay.html | 8 +- .../x-swiper/x-swiper-basic-circular.html | 8 +- ...ic-default-justify-content-flex-start.html | 10 +-- .../web-elements/x-swiper/x-swiper-basic.html | 16 ++-- .../x-swiper/x-swiper-circular-click.html | 40 ++++----- .../x-swiper/x-swiper-circular-coverflow.html | 8 +- .../x-swiper/x-swiper-current-change.html | 8 +- .../x-swiper-indicator-active-color.html | 8 +- .../x-swiper/x-swiper-indicator-basic.html | 8 +- .../x-swiper/x-swiper-indicator-color.html | 8 +- .../x-swiper/x-swiper-initial-current.html | 16 ++-- .../x-swiper-mode-carousel-page-margin.html | 8 +- .../x-swiper/x-swiper-mode-carousel.html | 8 +- .../x-swiper/x-swiper-mode-carry.html | 12 +-- .../x-swiper-mode-coverflow-circular.html | 12 +-- .../x-swiper/x-swiper-mode-coverflow.html | 12 +-- .../x-swiper-mode-flat-coverflow.html | 12 +-- .../x-swiper-mode-normal-page-margin.html | 8 +- .../x-swiper-set-curren-smooth-scroll.html | 32 +++---- .../x-swiper/x-swiper-set-current.html | 8 +- .../x-text/event-layoutchange.html | 19 ++-- .../inline-image-padding-and-margin.html | 4 +- .../inline-image-with-lynx-wrapper.html | 2 +- .../web-elements/x-text/inline-image.html | 2 +- .../x-text/inline-text-with-lynx-wrapper.html | 4 +- .../web-elements/x-text/inline-text.html | 4 +- .../inline-truncation-with-inline-image.html | 4 +- .../x-text/nested-view-in-text.html | 4 +- .../x-text/raw-text-with-lynx-wrapper.html | 2 +- .../tests/web-elements/x-text/raw-text.html | 2 +- .../x-text/text-baseline-alignment.html | 12 +-- .../text-clipped-display-important.html | 4 +- .../x-text/text-in-text-fault-torrent.html | 4 +- .../web-elements/x-text/text-in-text.html | 4 +- .../x-text/text-is-block-element.html | 2 +- .../x-text/text-maxlength-with-raw-text.html | 7 +- ...xlength-with-tail-color-convert-false.html | 2 +- ...ext-maxlength-with-tail-color-convert.html | 10 +-- .../web-elements/x-text/text-maxlength.html | 2 +- .../x-text/text-maxline-1-instrict-size.html | 4 +- .../text-maxline-basic-with-lynx-wrapper.html | 24 ++--- .../x-text/text-maxline-basic.html | 24 ++--- ...ust-fit-do-not-show-custom-truncation.html | 4 +- .../text-maxline-with-custom-truncation.html | 30 +++---- .../x-text/text-maxline-with-padding.html | 8 +- .../x-text/text-maxline-with-raw-text.html | 6 +- ...maxline-with-tail-color-convert-false.html | 24 ++--- .../text-not-resize-detect-new-line.html | 12 +-- .../x-text/text-overflow-inherit.html | 4 +- .../x-text/text-sizing-in-flex-container.html | 6 +- .../truncation-first-element-is-image.html | 10 +-- .../x-text/view-flex-in-text.html | 2 +- .../web-elements/x-text/view-in-text.html | 2 +- .../attribute-confirm-type-done.html | 2 +- .../x-textarea/attribute-confirm-type-go.html | 2 +- .../attribute-confirm-type-next.html | 2 +- .../attribute-confirm-type-search.html | 2 +- .../attribute-confirm-type-send.html | 2 +- .../x-textarea/attribute-disabled.html | 2 +- ...-maxlength-change-do-not-change-value.html | 2 +- ...bute-maxlength-first-screen-cut-value.html | 2 +- .../x-textarea/attribute-readonly.html | 2 +- .../x-textarea/attribute-spell-check.html | 6 +- .../x-textarea/attribute-value.html | 2 +- .../x-textarea/background-color-inherit.html | 2 +- .../x-textarea/event-confirm.html | 2 +- .../x-textarea/event-focus-blur.html | 2 +- .../web-elements/x-textarea/event-input.html | 11 ++- .../tests/web-elements/x-textarea/method.html | 2 +- .../x-textarea/outline-color-inherit.html | 2 +- .../x-textarea/placeholder-color.html | 2 +- .../x-textarea/placeholder-weight.html | 2 +- .../web-elements/x-textarea/placeholder.html | 2 +- .../press-enter-do-not-submit-value.html | 2 +- .../x-view/event-layoutchange.html | 19 ++-- .../basic-with-lynx-wrapper.html | 31 ++++--- .../web-elements/x-viewpager-ng/basic.html | 28 +++--- .../web-elements/x-viewpager-ng/bounces.html | 28 +++--- ...-response-to-select-index-on-dragging.html | 28 +++--- .../event-offsetchange-offset-value.html | 28 +++--- .../x-viewpager-ng/method-selectTab.html | 28 +++--- .../x-viewpager-ng/select-index-0.html | 28 +++--- .../x-viewpager-ng/select-index.html | 28 +++--- .../selecttab-method-default-smooth.html | 28 +++--- .../selecttab-method-not-smooth.html | 28 +++--- ...viewpager-size-cyclic-percentage-size.html | 21 +++-- 287 files changed, 2605 insertions(+), 2241 deletions(-) diff --git a/.cargo/nextest.toml b/.cargo/nextest.toml index 1b6b9d85ff..8f952573ae 100644 --- a/.cargo/nextest.toml +++ b/.cargo/nextest.toml @@ -93,7 +93,6 @@ leak-timeout = "100ms" # To address this, "archive.include" specifies additional paths that will be included in the archive. archive.include = [ - # Examples: # # { path = "application-data", relative-to = "target" }, diff --git a/.changeset/hip-seals-read.md b/.changeset/hip-seals-read.md index a845151cc8..853d812bb3 100644 --- a/.changeset/hip-seals-read.md +++ b/.changeset/hip-seals-read.md @@ -1,2 +1,3 @@ --- + --- diff --git a/.changeset/rude-pears-open.md b/.changeset/rude-pears-open.md index a845151cc8..853d812bb3 100644 --- a/.changeset/rude-pears-open.md +++ b/.changeset/rude-pears-open.md @@ -1,2 +1,3 @@ --- + --- diff --git a/.changeset/small-friends-grin.md b/.changeset/small-friends-grin.md index a845151cc8..853d812bb3 100644 --- a/.changeset/small-friends-grin.md +++ b/.changeset/small-friends-grin.md @@ -1,2 +1,3 @@ --- + --- diff --git a/.dprint.jsonc b/.dprint.jsonc index 29a4073ebd..5e6b903786 100644 --- a/.dprint.jsonc +++ b/.dprint.jsonc @@ -22,6 +22,7 @@ }, "toml": { }, + // cSpell:disable-next-line "malva": { }, "markup": { @@ -57,13 +58,14 @@ "packages/**/test/**/hotCases/**", ], "plugins": [ - "https://plugins.dprint.dev/exec-0.5.0.json@8d9972eee71fa1590e04873540421f3eda7674d0f1aae3d7c788615e7b7413d0", - "https://plugins.dprint.dev/typescript-0.91.3.wasm", - "https://plugins.dprint.dev/json-0.19.3.wasm", - "https://plugins.dprint.dev/markdown-0.17.1.wasm", - "https://plugins.dprint.dev/toml-0.6.2.wasm", - "https://plugins.dprint.dev/g-plane/malva-v0.5.1.wasm", - "https://plugins.dprint.dev/g-plane/markup_fmt-v0.10.0.wasm", - "https://plugins.dprint.dev/g-plane/pretty_yaml-v0.3.0.wasm", + "https://plugins.dprint.dev/dockerfile-0.3.2.wasm", + "https://plugins.dprint.dev/exec-0.5.1.json@492414e39dea4dccc07b4af796d2f4efdb89e84bae2bd4e1e924c0cc050855bf", + "https://plugins.dprint.dev/typescript-0.94.0.wasm", + "https://plugins.dprint.dev/json-0.20.0.wasm", + "https://plugins.dprint.dev/markdown-0.18.0.wasm", + "https://plugins.dprint.dev/toml-0.7.0.wasm", + "https://plugins.dprint.dev/g-plane/malva-v0.11.2.wasm", + "https://plugins.dprint.dev/g-plane/markup_fmt-v0.19.0.wasm", + "https://plugins.dprint.dev/g-plane/pretty_yaml-v0.5.0.wasm", ], } diff --git a/cspell.jsonc b/cspell.jsonc index e239b41a65..c656c84e0c 100644 --- a/cspell.jsonc +++ b/cspell.jsonc @@ -138,6 +138,8 @@ ], // Glob "ignorePaths": [ + // cSpell:disable-next-line + ".cargo/nextest.toml", ".gitignore", // Tests "coverage", diff --git a/packages/web-platform/web-elements/src/common-css/linear.css b/packages/web-platform/web-elements/src/common-css/linear.css index a0f8c69064..8f0f77976b 100644 --- a/packages/web-platform/web-elements/src/common-css/linear.css +++ b/packages/web-platform/web-elements/src/common-css/linear.css @@ -196,14 +196,16 @@ x-refresh-view, x-swiper-item, x-viewpager-item-ng, x-viewpager-ng { - flex-wrap: var(--lynx-display-linear, nowrap) var( - --lynx-display-flex, - var(--flex-wrap) - ); - flex-direction: var(--lynx-display-linear, var(--linear-flex-direction)) var( - --lynx-display-flex, - var(--flex-direction) - ); + flex-wrap: var(--lynx-display-linear, nowrap) + var( + --lynx-display-flex, + var(--flex-wrap) + ); + flex-direction: var(--lynx-display-linear, var(--linear-flex-direction)) + var( + --lynx-display-flex, + var(--flex-direction) + ); justify-content: var(--lynx-display-linear, var(--linear-justify-content)); } diff --git a/packages/web-platform/web-explorer/index.html b/packages/web-platform/web-explorer/index.html index ae99654830..c36042d4ec 100644 --- a/packages/web-platform/web-explorer/index.html +++ b/packages/web-platform/web-explorer/index.html @@ -8,9 +8,7 @@ Lynx Explorer on Web Platform - + - -
+ +