Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 0 additions & 1 deletion .cargo/nextest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" },
Expand Down
15 changes: 15 additions & 0 deletions .changeset/giant-seas-leave.md
Original file line number Diff line number Diff line change
@@ -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
<lynx-view thread-strategy="all-on-ui"></lynx-view>
```

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.
3 changes: 3 additions & 0 deletions .changeset/hip-seals-read.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---

---
1 change: 1 addition & 0 deletions .changeset/rude-pears-open.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
---

---
5 changes: 5 additions & 0 deletions .changeset/slow-tools-ring.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@lynx-js/offscreen-document": patch
---

feat: support parentNode
1 change: 1 addition & 0 deletions .changeset/small-friends-grin.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
---

---
7 changes: 7 additions & 0 deletions .changeset/soft-baths-scream.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@lynx-js/web-elements": patch
---

fix: the scroll-x field of scroll-view needs to be handled correctly.

Before this, scroll-x of '' would result in no scrolling along x-axis.
18 changes: 10 additions & 8 deletions .dprint.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
},
"toml": {
},
// cSpell:disable-next-line
"malva": {
},
"markup": {
Expand Down Expand Up @@ -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",
],
}
16 changes: 16 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -270,6 +285,7 @@ jobs:
needs:
- code-style-check
- playwright-linux
- playwright-linux-all-on-ui
- test-plugins
- test-publish
- test-react
Expand Down
2 changes: 2 additions & 0 deletions cspell.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@
],
// Glob
"ignorePaths": [
// cSpell:disable-next-line
".cargo/nextest.toml",
".gitignore",
// Tests
"coverage",
Expand Down
21 changes: 4 additions & 17 deletions packages/testing-library/test-environment/src/lynx/ElementPAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down Expand Up @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
1 change: 1 addition & 0 deletions packages/web-platform/web-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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:*"
},
Expand Down
21 changes: 21 additions & 0 deletions packages/web-platform/web-core/src/apis/LynxView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 <link href="" ref="stylesheet"> 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<LynxTemplate>} customTemplateLoader [optional] the custom template loader, which is used to load the template
*
* @event error lynx card fired an error
Expand Down Expand Up @@ -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
*/
Expand Down Expand Up @@ -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,
Expand Down
10 changes: 8 additions & 2 deletions packages/web-platform/web-core/src/apis/createLynxView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,23 @@ 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 {
templateUrl: string;
initData: Cloneable;
globalProps: Cloneable;
shadowRoot: ShadowRoot;
callbacks: Parameters<typeof startUIThread>[4];
callbacks: StartUIThreadCallbacks;
nativeModulesMap: NativeModulesMap;
napiModulesMap: NapiModulesMap;
tagMap: Record<string, string>;
lynxGroupId: number | undefined;
threadStrategy: 'all-on-ui' | 'multi-thread';
}

export interface LynxView {
Expand All @@ -45,6 +49,7 @@ export function createLynxView(configs: LynxViewConfigs): LynxView {
napiModulesMap,
tagMap,
lynxGroupId,
threadStrategy = 'multi-thread',
} = configs;
return startUIThread(
templateUrl,
Expand All @@ -60,6 +65,7 @@ export function createLynxView(configs: LynxViewConfigs): LynxView {
},
shadowRoot,
lynxGroupId,
threadStrategy,
callbacks,
);
}
30 changes: 25 additions & 5 deletions packages/web-platform/web-core/src/uiThread/bootWorkers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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) {
Expand All @@ -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();
Expand Down
Original file line number Diff line number Diff line change
@@ -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<typeof updateDataEndpoint> = async (
...args
) => {
runtime.updatePage?.(...args);
};
return {
start,
updateDataMainThread,
};
}
Loading