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
19 changes: 19 additions & 0 deletions .changeset/new-beans-warn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
"@lynx-js/react": patch
---

Use error cause to simplify the error msg of lazy bundle loading. User can catch the error cause to get the original result:

```ts
const LazyComponent = lazy(async () => {
try {
const mod = await import('./lazy-bundle');
return mod.default;
} catch (error) {
console.error(`Lazy Bundle load failed message: ${error.message}`);
// User can catch the error cause to get the original result
console.error(`Lazy Bundle load failed result: ${error.cause}`);
throw error;
}
});
```
58 changes: 52 additions & 6 deletions packages/react/runtime/__test__/lynx/lazy-bundle.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ describe('loadLazyBundle', () => {

test('blocking QueryComponent with error', async () => {
QueryComponent.mockImplementation((source, callback) => {
callback({ code: 1, detail: { errMsg: 'error', source } });
callback({ code: 1, detail: { errMsg: 'error', schema: source } });
});

const { loadLazyBundle } = await import('../../src/lynx/lazy-bundle');
Expand All @@ -257,14 +257,14 @@ describe('loadLazyBundle', () => {
let catchCalled = false;
const promise3 = promise.catch((err) => {
expect(err).toMatchInlineSnapshot(
`[Error: Lazy bundle load failed: {"code":1,"detail":{"errMsg":"error","source":"foo"}}]`,
`[Error: Lazy bundle load failed, schema: foo]`,
);
catchCalled = true;
});
expect(catchCalled).toBe(false); // Should be non-blocking

await expect(promise2).rejects.toThrowErrorMatchingInlineSnapshot(
`[Error: Lazy bundle load failed: {"code":1,"detail":{"errMsg":"error","source":"foo"}}]`,
`[Error: Lazy bundle load failed, schema: foo]`,
);

await promise3;
Expand Down Expand Up @@ -447,7 +447,7 @@ describe('loadLazyBundle', () => {
test('non-blocking QueryComponent with rejections', async () => {
QueryComponent.mockImplementation((source, callback) => {
Promise.resolve().then(() => {
callback({ code: 1, detail: { errMsg: 'error', source } });
callback({ code: 1, detail: { errMsg: 'error', schema: source } });
});
});

Expand All @@ -462,15 +462,15 @@ describe('loadLazyBundle', () => {
expect.fail('promise should not resolve');
}, (err) => {
expect(err).toMatchInlineSnapshot(
`[Error: Lazy bundle load failed: {"code":1,"detail":{"errMsg":"error","source":"foo"}}]`,
`[Error: Lazy bundle load failed, schema: foo]`,
);
thenCalled = true;
return 'bar';
});
expect(thenCalled).toBe(false);

await expect(promise).rejects.toMatchInlineSnapshot(
`[Error: Lazy bundle load failed: {"code":1,"detail":{"errMsg":"error","source":"foo"}}]`,
`[Error: Lazy bundle load failed, schema: foo]`,
);
expect(thenCalled).toBe(true);

Expand All @@ -485,6 +485,52 @@ describe('loadLazyBundle', () => {
expect(thenCalled).toBe(true);
});

test('catch and process error of loadLazyBundle', async () => {
QueryComponent.mockImplementation((source, callback) => {
Promise.resolve().then(() => {
callback({ code: 1, detail: { errMsg: 'error', schema: source } });
});
});

const { loadLazyBundle } = await import('../../src/lynx/lazy-bundle');

const promise = loadLazyBundle('foo');

expect(QueryComponent).toBeCalledWith('foo', expect.any(Function));

let thenCalled = false;
const promise2 = promise.then(() => {
expect.fail('promise should not resolve');
}, (err) => {
const cause = err.cause;
expect(cause).toMatchInlineSnapshot(
`"{"code":1,"detail":{"errMsg":"error","schema":"foo"}}"`,
);
thenCalled = true;
return `Lazy Bundle load failed result: ${cause}`;
});
expect(thenCalled).toBe(false);

await expect(promise).rejects.toMatchInlineSnapshot(
`[Error: Lazy bundle load failed, schema: foo]`,
);
expect(thenCalled).toBe(true);

thenCalled = false;
promise2.then((data) => {
expect(data).toMatchInlineSnapshot(
`"Lazy Bundle load failed result: {"code":1,"detail":{"errMsg":"error","schema":"foo"}}"`,
);
thenCalled = true;
});
expect(thenCalled).toBe(false);

await expect(promise2).resolves.toMatchInlineSnapshot(
`"Lazy Bundle load failed result: {"code":1,"detail":{"errMsg":"error","schema":"foo"}}"`,
);
expect(thenCalled).toBe(true);
});

test('lynx.getNativeLynx().QueryComponent', async () => {
QueryComponent.mockImplementation((source, callback) => {
callback({ code: 0, detail: { schema: source } });
Expand Down
6 changes: 5 additions & 1 deletion packages/react/runtime/src/lynx/lazy-bundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,11 @@ export const loadLazyBundle: <
return;
}
}
resolver.reject(new Error('Lazy bundle load failed: ' + JSON.stringify(result)));
const e = new Error('Lazy bundle load failed, schema: ' + result.detail.schema);
// ES5 does not support new Error('message', { cause: 'detail' })
// So we set cause using `.cause` assignment
e.cause = JSON.stringify(result);
resolver.reject(e);
};
if (typeof lynx.QueryComponent === 'function') {
lynx.QueryComponent(source, callback);
Expand Down
Loading