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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .changeset/puny-pens-cry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
"@lynx-js/web-worker-runtime": patch
"@lynx-js/web-constants": patch
"@lynx-js/web-core": patch
---

feat: support load bts chunk from remote address

- re-support chunk splitting
- support lynx.requireModule with a json file
- support lynx.requireModule, lynx.requireModuleAsync with a remote url
- support to add a breakpoint in chrome after reloading the web page
41 changes: 41 additions & 0 deletions packages/web-platform/web-constants/src/types/LynxModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,47 @@ export interface LynxTemplate {
appType: 'card' | 'lazy';
}

export type BTSChunkEntry = (
postMessage: undefined,
module: { exports: unknown },
exports: unknown,
lynxCoreInject: unknown,
Card: unknown,
setTimeout: unknown,
setInterval: unknown,
clearInterval: unknown,
clearTimeout: unknown,
NativeModules: unknown,
Component: unknown,
ReactLynx: unknown,
nativeAppId: unknown,
Behavior: unknown,
LynxJSBI: unknown,
lynx: unknown,
// BOM API
window: unknown,
document: unknown,
frames: unknown,
location: unknown,
navigator: unknown,
localStorage: unknown,
history: unknown,
Caches: unknown,
screen: unknown,
alert: unknown,
confirm: unknown,
prompt: unknown,
fetch: unknown,
XMLHttpRequest: unknown,
webkit: unknown,
Reporter: unknown,
print: unknown,
global: unknown,
// Lynx API
requestAnimationFrame: unknown,
cancelAnimationFrame: unknown,
) => unknown;

export interface LynxJSModule {
exports?: (lynx_runtime: any) => unknown;
}
3 changes: 3 additions & 0 deletions packages/web-platform/web-constants/src/types/NativeApp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,14 @@ export interface NativeApp {

cancelAnimationFrame: (id: number) => void;

readScript: (sourceURL: string, entryName?: string) => string;

loadScript: (sourceURL: string, entryName?: string) => BundleInitReturnObj;

loadScriptAsync(
sourceURL: string,
callback: (message: string | null, exports?: BundleInitReturnObj) => void,
entryName?: string,
): void;
nativeModuleProxy: Record<string, any>;

Expand Down
95 changes: 25 additions & 70 deletions packages/web-platform/web-constants/src/utils/generateTemplate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,69 +5,27 @@
import type { LynxTemplate } from '../types/LynxModule.js';

const currentSupportedTemplateVersion = 2;
const globalDisallowedVars = ['navigator', 'postMessage'];
const globalDisallowedVars = ['navigator', 'postMessage', 'window'];
type templateUpgrader = (template: LynxTemplate) => LynxTemplate;
const templateUpgraders: templateUpgrader[] = [
(template) => {
const defaultInjectStr = [
'Card',
'setTimeout',
'setInterval',
'clearInterval',
'clearTimeout',
'NativeModules',
'Component',
'ReactLynx',
'nativeAppId',
'Behavior',
'LynxJSBI',
'lynx',

// BOM API
'window',
'document',
'frames',
'location',
'navigator',
'localStorage',
'history',
'Caches',
'screen',
'alert',
'confirm',
'prompt',
'fetch',
'XMLHttpRequest',
'__WebSocket__', // We would provide `WebSocket` using `ProvidePlugin`
'webkit',
'Reporter',
'print',
'global',

// Lynx API
'requestAnimationFrame',
'cancelAnimationFrame',
].join(',');
template.appType = template.appType ?? (template.lepusCode.root.startsWith(
'(function (globDynamicComponentEntry',
)
? 'lazy'
: 'card');
/**
* The template version 1 has no module wrapper for bts code
*/
template.manifest = Object.fromEntries(
Object.entries(template.manifest).map(([key, value]) => [
key,
`module.exports={init: (lynxCoreInject) => { var {${defaultInjectStr}} = lynxCoreInject.tt; var module = {exports:{}}; var exports=module.exports; ${value}\n return module.exports; } }`,
]),
) as typeof template.manifest;
template.version = 2;
template.lepusCode = Object.fromEntries(
Object.entries(template.lepusCode).filter(([_, content]) =>
typeof content === 'string'
),
) as typeof template.lepusCode;
return template;
},
];

const generateModuleContent = (
fileName: string,
content: string,
eager: boolean,
appType: 'card' | 'lazy',
Expand All @@ -90,30 +48,34 @@ const generateModuleContent = (
appType !== 'card' ? 'module.exports=\n' : '',
content,
'\n})()',
'\n//# sourceURL=',
fileName,
].join('');

async function generateJavascriptUrl<T extends Record<string, string | {}>>(
obj: T,
createJsModuleUrl: (content: string, name: string) => Promise<string>,
eager: boolean,
appType: 'card' | 'lazy',
templateName?: string,
templateName: string,
): Promise<T> {
const processEntry = async ([name, content]: [string, string]) => [
name,
await createJsModuleUrl(
generateModuleContent(
content,
eager,
appType,
),
`${templateName}-${name.replaceAll('/', '')}.js`,
),
];
return Promise.all(
(Object.entries(obj).filter(([_, content]) =>
typeof content === 'string'
) as [string, string][]).map(processEntry),
) as [string, string][]).map(async ([name, content]) => {
return [
name,
await createJsModuleUrl(
generateModuleContent(
`${templateName}/${name.replaceAll('/', '_')}.js`,
content,
eager,
appType,
),
`${templateName}-${name.replaceAll('/', '_')}.js`,
),
];
}),
).then(
Object.fromEntries,
);
Expand All @@ -124,7 +86,7 @@ export async function generateTemplate(
createJsModuleUrl:
| ((content: string, name: string) => Promise<string>)
| ((content: string) => string),
templateName?: string,
templateName: string,
): Promise<LynxTemplate> {
template.version = template.version ?? 1;
if (template.version > currentSupportedTemplateVersion) {
Expand All @@ -148,12 +110,5 @@ export async function generateTemplate(
template.appType!,
templateName,
),
manifest: await generateJavascriptUrl(
template.manifest,
createJsModuleUrl as (content: string, name: string) => Promise<string>,
false,
template.appType!,
templateName,
),
};
}
1 change: 1 addition & 0 deletions packages/web-platform/web-core/src/utils/loadTemplate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export function createTemplateLoader(
const decodedTemplate = await generateTemplate(
template,
createJsModuleUrl,
encodeURIComponent(url),
);
resolve(decodedTemplate);
} catch (e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"manifest": {
"/app-service.js": "globalThis.runtime = lynxCoreInject.tt; globalThis.__lynx_worker_type = 'background'",
"/manifest-chunk.js": "module.exports = 'hello';",
"/manifest-chunk2.js": "module.exports = 'world';"
"/manifest-chunk2.js": "module.exports = 'world';",
"/json": "{}"
},
"customSections": {},
"cardType": "react",
Expand Down
4 changes: 2 additions & 2 deletions packages/web-platform/web-tests/tests/react.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -876,7 +876,7 @@
await goto(page, title);
await wait(100);
const target = page.locator('#target');
await expect(target).toHaveCSS('background-color', 'rgb(0, 128, 0)'); // green

Check failure on line 879 in packages/web-platform/web-tests/tests/react.spec.ts

View workflow job for this annotation

GitHub Actions / Playwright ALL_ON_UI-CSR (2/4) / check

[chromium] › tests/react.spec.ts:874:5 › reactlynx3 tests › apis › api-custom-template-loader

2) [chromium] › tests/react.spec.ts:874:5 › reactlynx3 tests › apis › api-custom-template-loader ─ Error: expect(locator).toHaveCSS(expected) failed Locator: locator('#target') Expected string: "rgb(0, 128, 0)" Received: <element(s) not found> Timeout: 5000ms Call log: - Expect "toHaveCSS" with timeout 5000ms - waiting for locator('#target') 877 | await wait(100); 878 | const target = page.locator('#target'); > 879 | await expect(target).toHaveCSS('background-color', 'rgb(0, 128, 0)'); // green | ^ 880 | }); 881 | test('api-animation-event', async ({ page }, { title }) => { 882 | await goto(page, title); at /__w/lynx-stack/lynx-stack/packages/web-platform/web-tests/tests/react.spec.ts:879:28
});
test('api-animation-event', async ({ page }, { title }) => {
await goto(page, title);
Expand Down Expand Up @@ -1872,7 +1872,7 @@
test(
'config-splitchunk-split-by-experience',
async ({ page }, { title }) => {
test.skip(true, 'incorrectly implemented test case');
test.skip(isSSR, 'incorrectly implemented test case');
await goto(page, title, undefined, true);
await wait(1500);
const target = page.locator('#target');
Expand All @@ -1882,7 +1882,7 @@
test(
'config-splitchunk-split-by-module',
async ({ page }, { title }) => {
test.skip(true, 'incorrectly implemented test case');
test.skip(isSSR, 'incorrectly implemented test case');
await goto(page, title, undefined, true);
await wait(1500);
const target = page.locator('#target');
Expand Down
18 changes: 18 additions & 0 deletions packages/web-platform/web-tests/tests/web-core.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,24 @@ test.describe('web core tests', () => {
expect(success).toBe(true);
expect(fail).toBe(false);
});

test('api-nativeApp-readScript', async ({ page, browserName }) => {
// firefox dose not support this.
test.skip(browserName === 'firefox');
await goto(page);
const mainWorker = await getMainThreadWorker(page);
await mainWorker.evaluate(() => {
globalThis.runtime.renderPage = () => {};
});
await wait(3000);
const backWorker = await getBackgroundThreadWorker(page);
const jsonContent = await backWorker.evaluate(() => {
const nativeApp = globalThis.runtime.lynx.getNativeApp();
return nativeApp.readScript('json');
});
await wait(100);
expect(jsonContent).toBe('{}');
});
test('registerDataProcessor-as-global-var-update', async ({ page, browserName }) => {
await goto(page);
const mainWorker = await getMainThreadWorker(page);
Expand Down
Loading
Loading