@kookapp/web-bridge 0.0.2 → 0.0.3
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/README.md +67 -15
- package/dist/child/ChildBridge.d.ts +2 -0
- package/dist/child/ChildBridge.d.ts.map +1 -1
- package/dist/child/ChildBridge.js +6 -1
- package/dist/parent/IframeChannel.d.ts +2 -0
- package/dist/parent/IframeChannel.d.ts.map +1 -1
- package/dist/parent/IframeChannel.js +12 -2
- package/dist/shared/MessageHandler.d.ts +2 -0
- package/dist/shared/MessageHandler.d.ts.map +1 -1
- package/dist/shared/MessageHandler.js +32 -14
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,7 +9,8 @@ A PostMessage-based bridge for iframe communication, providing symmetric callHan
|
|
|
9
9
|
- **Origin Validation**: Strict domain whitelist verification
|
|
10
10
|
- **Type-Safe**: Full TypeScript support with comprehensive type definitions
|
|
11
11
|
- **Promise & Callback**: Supports both async/await and callback patterns
|
|
12
|
-
- **
|
|
12
|
+
- **No Exceptions**: Errors returned via result values, never throws exceptions (like globalBridge)
|
|
13
|
+
- **Error Handling**: Comprehensive error reporting through return values
|
|
13
14
|
|
|
14
15
|
## Installation
|
|
15
16
|
|
|
@@ -39,10 +40,22 @@ bridge.registerHandler('getUserInfo', (data, callback) => {
|
|
|
39
40
|
const iframeElement = document.getElementById('myIframe') as HTMLIFrameElement
|
|
40
41
|
const channel = bridge.createChannel(iframeElement)
|
|
41
42
|
|
|
42
|
-
// Call a handler inside iframe
|
|
43
|
-
channel.callHandler('getIframeData', { type: 'user' })
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
// Call a handler inside iframe (using callback)
|
|
44
|
+
channel.callHandler('getIframeData', { type: 'user' }, (result) => {
|
|
45
|
+
if (result.error) {
|
|
46
|
+
console.error('Error:', result.error)
|
|
47
|
+
} else {
|
|
48
|
+
console.log('Result:', result)
|
|
49
|
+
}
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
// Or using async/await (without callback)
|
|
53
|
+
const result = await channel.callHandler('getIframeData', { type: 'user' })
|
|
54
|
+
if (result.error) {
|
|
55
|
+
console.error('Error:', result.error)
|
|
56
|
+
} else {
|
|
57
|
+
console.log('Result:', result)
|
|
58
|
+
}
|
|
46
59
|
|
|
47
60
|
// Clean up
|
|
48
61
|
// bridge.destroy()
|
|
@@ -64,10 +77,22 @@ bridge.registerHandler('getIframeData', (data, callback) => {
|
|
|
64
77
|
callback(response)
|
|
65
78
|
})
|
|
66
79
|
|
|
67
|
-
// Call a handler on parent
|
|
68
|
-
bridge.callHandler('getUserInfo', {})
|
|
69
|
-
|
|
70
|
-
|
|
80
|
+
// Call a handler on parent (using callback)
|
|
81
|
+
bridge.callHandler('getUserInfo', {}, (userInfo) => {
|
|
82
|
+
if (userInfo.error) {
|
|
83
|
+
console.error('Error:', userInfo.error)
|
|
84
|
+
} else {
|
|
85
|
+
console.log('User:', userInfo)
|
|
86
|
+
}
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
// Or using async/await
|
|
90
|
+
const userInfo = await bridge.callHandler('getUserInfo', {})
|
|
91
|
+
if (userInfo.error) {
|
|
92
|
+
console.error('Error:', userInfo.error)
|
|
93
|
+
} else {
|
|
94
|
+
console.log('User:', userInfo)
|
|
95
|
+
}
|
|
71
96
|
```
|
|
72
97
|
|
|
73
98
|
## API Reference
|
|
@@ -121,13 +146,40 @@ interface BridgeConfig {
|
|
|
121
146
|
|
|
122
147
|
## Error Handling
|
|
123
148
|
|
|
124
|
-
|
|
149
|
+
**WebBridge never throws exceptions** - all errors are returned through the result value, keeping behavior consistent with globalBridge.
|
|
150
|
+
|
|
151
|
+
All errors are returned as objects with an `error` property:
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
// Using callback
|
|
155
|
+
bridge.callHandler('someHandler', {}, (result) => {
|
|
156
|
+
if (result.error) {
|
|
157
|
+
// Handle error cases:
|
|
158
|
+
// - Handler not found
|
|
159
|
+
// - Request timeout
|
|
160
|
+
// - Invalid message
|
|
161
|
+
// - Connection issues
|
|
162
|
+
console.error('Error:', result.error)
|
|
163
|
+
} else {
|
|
164
|
+
console.log('Success:', result)
|
|
165
|
+
}
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
// Using Promise (never rejects!)
|
|
169
|
+
const result = await bridge.callHandler('someHandler', {})
|
|
170
|
+
if (result.error) {
|
|
171
|
+
console.error('Error:', result.error)
|
|
172
|
+
} else {
|
|
173
|
+
console.log('Success:', result)
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
**Common error types:**
|
|
178
|
+
- Handler not found: `{ error: 'Handler "handlerName" not found' }`
|
|
179
|
+
- Timeout: `{ error: 'Timeout: no response after 5000ms' }`
|
|
180
|
+
- Connection issues: `{ error: 'iframe contentWindow is not available' }`
|
|
125
181
|
|
|
126
|
-
|
|
127
|
-
- `ORIGIN_NOT_ALLOWED`: Message origin not in whitelist
|
|
128
|
-
- `TIMEOUT`: Request exceeded timeout
|
|
129
|
-
- `INVALID_MESSAGE`: Malformed message received
|
|
130
|
-
- `CONNECTION_LOST`: Connection to other side lost
|
|
182
|
+
See [ERROR_HANDLING.md](./ERROR_HANDLING.md) for complete documentation.
|
|
131
183
|
|
|
132
184
|
## Security
|
|
133
185
|
|
|
@@ -18,6 +18,8 @@ export declare class ChildBridge extends MessageHandler {
|
|
|
18
18
|
private notifyReady;
|
|
19
19
|
/**
|
|
20
20
|
* Call a handler on parent
|
|
21
|
+
* If callback is provided: calls callback with result (data or error object), returns Promise<undefined>
|
|
22
|
+
* If callback is not provided: returns Promise<result|error>
|
|
21
23
|
*/
|
|
22
24
|
callHandler(handlerName: string, data?: any, callback?: (result: any) => void): Promise<any>;
|
|
23
25
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChildBridge.d.ts","sourceRoot":"","sources":["../../src/child/ChildBridge.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAGxD,qBAAa,WAAY,SAAQ,cAAc;IAC7C,OAAO,CAAC,YAAY,CAAQ;IAC5B,OAAO,CAAC,YAAY,CAAQ;IAC5B,OAAO,CAAC,SAAS,CAAiB;gBAEtB,MAAM,EAAE,iBAAiB;IA+BrC;;OAEG;IACH,OAAO,CAAC,eAAe;IAyBvB;;OAEG;IACH,OAAO,CAAC,WAAW;IAgBnB
|
|
1
|
+
{"version":3,"file":"ChildBridge.d.ts","sourceRoot":"","sources":["../../src/child/ChildBridge.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAGxD,qBAAa,WAAY,SAAQ,cAAc;IAC7C,OAAO,CAAC,YAAY,CAAQ;IAC5B,OAAO,CAAC,YAAY,CAAQ;IAC5B,OAAO,CAAC,SAAS,CAAiB;gBAEtB,MAAM,EAAE,iBAAiB;IA+BrC;;OAEG;IACH,OAAO,CAAC,eAAe;IAyBvB;;OAEG;IACH,OAAO,CAAC,WAAW;IAgBnB;;;;OAIG;IACG,WAAW,CACf,WAAW,EAAE,MAAM,EACnB,IAAI,CAAC,EAAE,GAAG,EACV,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,GAC/B,OAAO,CAAC,GAAG,CAAC;IAaf;;OAEG;IACH,SAAS,CAAC,WAAW,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,IAAI;IAezE;;OAEG;IACH,SAAS,CAAC,eAAe,IAAI,MAAM;IAInC;;OAEG;IACH,WAAW,IAAI,OAAO;IAItB;;OAEG;IACH,OAAO,IAAI,IAAI;CAQhB"}
|
|
@@ -74,12 +74,17 @@ export class ChildBridge extends MessageHandler {
|
|
|
74
74
|
}
|
|
75
75
|
/**
|
|
76
76
|
* Call a handler on parent
|
|
77
|
+
* If callback is provided: calls callback with result (data or error object), returns Promise<undefined>
|
|
78
|
+
* If callback is not provided: returns Promise<result|error>
|
|
77
79
|
*/
|
|
78
80
|
async callHandler(handlerName, data, callback) {
|
|
79
81
|
const promise = this.callHandlerWithTimeout(this.parentOrigin, handlerName, data);
|
|
80
82
|
if (callback) {
|
|
81
|
-
|
|
83
|
+
// With callback: pass result to callback, return undefined
|
|
84
|
+
promise.then(callback);
|
|
85
|
+
return undefined;
|
|
82
86
|
}
|
|
87
|
+
// Without callback: return the promise with result or error object
|
|
83
88
|
return promise;
|
|
84
89
|
}
|
|
85
90
|
/**
|
|
@@ -14,6 +14,8 @@ export declare class IframeChannel extends MessageHandler implements IframeChann
|
|
|
14
14
|
private extractOrigin;
|
|
15
15
|
/**
|
|
16
16
|
* Call a handler in the iframe
|
|
17
|
+
* If callback is provided: calls callback with result (data or error object), returns Promise<undefined>
|
|
18
|
+
* If callback is not provided: returns Promise<result|error>
|
|
17
19
|
*/
|
|
18
20
|
callHandler(handlerName: string, data?: any, callback?: (result: any) => void): Promise<any>;
|
|
19
21
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IframeChannel.d.ts","sourceRoot":"","sources":["../../src/parent/IframeChannel.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAA;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAExD,qBAAa,aAAc,SAAQ,cAAe,YAAW,sBAAsB;IACjF,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,YAAY,CAAQ;IAC5B,OAAO,CAAC,SAAS,CAAiB;gBAGhC,MAAM,EAAE,iBAAiB,EACzB,cAAc,EAAE,MAAM,EAAE,EACxB,OAAO,GAAE,MAAa,EACtB,KAAK,GAAE,OAAe;IAmBxB;;OAEG;IACH,OAAO,CAAC,aAAa;IASrB
|
|
1
|
+
{"version":3,"file":"IframeChannel.d.ts","sourceRoot":"","sources":["../../src/parent/IframeChannel.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAA;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAExD,qBAAa,aAAc,SAAQ,cAAe,YAAW,sBAAsB;IACjF,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,YAAY,CAAQ;IAC5B,OAAO,CAAC,SAAS,CAAiB;gBAGhC,MAAM,EAAE,iBAAiB,EACzB,cAAc,EAAE,MAAM,EAAE,EACxB,OAAO,GAAE,MAAa,EACtB,KAAK,GAAE,OAAe;IAmBxB;;OAEG;IACH,OAAO,CAAC,aAAa;IASrB;;;;OAIG;IACG,WAAW,CACf,WAAW,EAAE,MAAM,EACnB,IAAI,CAAC,EAAE,GAAG,EACV,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,GAC/B,OAAO,CAAC,GAAG,CAAC;IAsBf;;OAEG;IACH,SAAS,CAAC,WAAW,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,IAAI;IAkBzE;;OAEG;IACH,SAAS,CAAC,eAAe,IAAI,MAAM;IAInC;;OAEG;IACH,SAAS,IAAI,iBAAiB;IAI9B;;OAEG;IACH,WAAW,IAAI,OAAO;IAItB;;OAEG;IACH,YAAY,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI;IAItC;;OAEG;IACH,OAAO,IAAI,IAAI;CAIhB"}
|
|
@@ -34,15 +34,25 @@ export class IframeChannel extends MessageHandler {
|
|
|
34
34
|
}
|
|
35
35
|
/**
|
|
36
36
|
* Call a handler in the iframe
|
|
37
|
+
* If callback is provided: calls callback with result (data or error object), returns Promise<undefined>
|
|
38
|
+
* If callback is not provided: returns Promise<result|error>
|
|
37
39
|
*/
|
|
38
40
|
async callHandler(handlerName, data, callback) {
|
|
39
41
|
if (!this.iframe.contentWindow) {
|
|
40
|
-
|
|
42
|
+
const error = { error: 'iframe contentWindow is not available' };
|
|
43
|
+
if (callback) {
|
|
44
|
+
callback(error);
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
return error;
|
|
41
48
|
}
|
|
42
49
|
const promise = this.callHandlerWithTimeout(this.iframeOrigin, handlerName, data);
|
|
43
50
|
if (callback) {
|
|
44
|
-
|
|
51
|
+
// With callback: pass result to callback, return undefined
|
|
52
|
+
promise.then(callback);
|
|
53
|
+
return undefined;
|
|
45
54
|
}
|
|
55
|
+
// Without callback: return the promise with result or error object
|
|
46
56
|
return promise;
|
|
47
57
|
}
|
|
48
58
|
/**
|
|
@@ -25,6 +25,7 @@ export declare abstract class MessageHandler {
|
|
|
25
25
|
unregisterHandler(handlerName: string): void;
|
|
26
26
|
/**
|
|
27
27
|
* Call a handler on the other side with timeout
|
|
28
|
+
* Never rejects - errors are resolved as {error: string}
|
|
28
29
|
*/
|
|
29
30
|
protected callHandlerWithTimeout(targetOrigin: string, handlerName: string, data?: any): Promise<any>;
|
|
30
31
|
/**
|
|
@@ -45,6 +46,7 @@ export declare abstract class MessageHandler {
|
|
|
45
46
|
private handleCall;
|
|
46
47
|
/**
|
|
47
48
|
* Handle incoming response message
|
|
49
|
+
* Never rejects - always resolves with data or error object
|
|
48
50
|
*/
|
|
49
51
|
private handleResponse;
|
|
50
52
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageHandler.d.ts","sourceRoot":"","sources":["../../src/shared/MessageHandler.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AACxE,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"MessageHandler.d.ts","sourceRoot":"","sources":["../../src/shared/MessageHandler.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AACxE,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAGlD,8BAAsB,cAAc;IAClC,SAAS,CAAC,QAAQ,EAAE,eAAe,CAAY;IAC/C,SAAS,CAAC,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAY;IAClE,SAAS,CAAC,YAAY,EAAE,YAAY,CAAqB;IACzD,SAAS,CAAC,eAAe,EAAE,eAAe,CAAA;IAC1C,SAAS,CAAC,WAAW,EAAE,WAAW,CAAoB;IACtD,SAAS,CAAC,OAAO,EAAE,MAAM,CAAA;IACzB,SAAS,CAAC,KAAK,EAAE,OAAO,CAAA;IACxB,SAAS,CAAC,eAAe,EAAE,CAAC,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC,GAAG,IAAI,CAAO;gBAE5D,cAAc,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,MAAwB,EAAE,KAAK,GAAE,OAAe;IAM/F;;OAEG;IACH,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,EAAE,QAAQ,KAAK,IAAI,GAAG,IAAI;IAO9F;;OAEG;IACH,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAO5C;;;OAGG;IACH,SAAS,CAAC,sBAAsB,CAC9B,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,EACnB,IAAI,CAAC,EAAE,GAAG,GACT,OAAO,CAAC,GAAG,CAAC;IAsCf;;OAEG;IACH,SAAS,CAAC,QAAQ,CAAC,WAAW,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,IAAI;IAElF;;OAEG;IACH,SAAS,CAAC,QAAQ,CAAC,eAAe,IAAI,MAAM;IAE5C;;OAEG;IACH,SAAS,CAAC,aAAa,CAAC,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAgCrE;;OAEG;YACW,UAAU;IAgDxB;;;OAGG;IACH,OAAO,CAAC,cAAc;IAsBtB;;OAEG;IACH,SAAS,CAAC,oBAAoB,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,GAAG,IAAI;IAK5E;;OAEG;IACH,SAAS,CAAC,qBAAqB,IAAI,IAAI;IAOvC;;OAEG;IACH,QAAQ,CAAC,WAAW,IAAI,OAAO;IAE/B;;OAEG;IACH,EAAE,CAAC,IAAI,EAAE,OAAO,GAAG,YAAY,GAAG,OAAO,EAAE,QAAQ,EAAE,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI;IAIhF;;OAEG;IACH,GAAG,CAAC,IAAI,EAAE,OAAO,GAAG,YAAY,GAAG,OAAO,EAAE,QAAQ,EAAE,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI;IAIjF;;OAEG;IACH,OAAO,IAAI,IAAI;CAOhB"}
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
import { EventEmitter } from '../shared/EventEmitter';
|
|
5
5
|
import { OriginValidator } from '../shared/OriginValidator';
|
|
6
6
|
import { IdGenerator } from '../shared/IdGenerator';
|
|
7
|
-
import { errorFactory } from '../errors/errorFactory';
|
|
8
7
|
import { DEFAULT_TIMEOUT } from '../constants';
|
|
9
8
|
export class MessageHandler {
|
|
10
9
|
constructor(allowedOrigins, timeout = DEFAULT_TIMEOUT, debug = false) {
|
|
@@ -37,19 +36,32 @@ export class MessageHandler {
|
|
|
37
36
|
}
|
|
38
37
|
/**
|
|
39
38
|
* Call a handler on the other side with timeout
|
|
39
|
+
* Never rejects - errors are resolved as {error: string}
|
|
40
40
|
*/
|
|
41
41
|
callHandlerWithTimeout(targetOrigin, handlerName, data) {
|
|
42
|
-
return new Promise((resolve
|
|
42
|
+
return new Promise((resolve) => {
|
|
43
43
|
const messageId = this.idGenerator.generate();
|
|
44
44
|
const timeoutHandle = setTimeout(() => {
|
|
45
45
|
this.pendingRequests.delete(messageId);
|
|
46
|
-
|
|
46
|
+
resolve({ error: `Timeout: no response after ${this.timeout}ms` });
|
|
47
47
|
}, this.timeout);
|
|
48
48
|
this.pendingRequests.set(messageId, {
|
|
49
49
|
id: messageId,
|
|
50
50
|
timeout: timeoutHandle,
|
|
51
|
-
resolve
|
|
52
|
-
|
|
51
|
+
resolve: (data) => {
|
|
52
|
+
// Wrap successful responses
|
|
53
|
+
if (data !== undefined && !data.error) {
|
|
54
|
+
resolve(data);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
resolve(data);
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
reject: (error) => {
|
|
61
|
+
// Never reject - resolve errors instead
|
|
62
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
63
|
+
resolve({ error: errorMessage });
|
|
64
|
+
}
|
|
53
65
|
});
|
|
54
66
|
const message = {
|
|
55
67
|
type: 'call',
|
|
@@ -109,16 +121,20 @@ export class MessageHandler {
|
|
|
109
121
|
return;
|
|
110
122
|
}
|
|
111
123
|
try {
|
|
112
|
-
|
|
124
|
+
let callbackCalled = false;
|
|
125
|
+
// Execute handler with callback function
|
|
113
126
|
const result = await Promise.resolve(handler(data, (response) => {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
127
|
+
if (!callbackCalled) {
|
|
128
|
+
callbackCalled = true;
|
|
129
|
+
this.sendMessage(origin, {
|
|
130
|
+
type: 'response',
|
|
131
|
+
id,
|
|
132
|
+
data: response
|
|
133
|
+
});
|
|
134
|
+
}
|
|
119
135
|
}));
|
|
120
|
-
// If handler returns a value
|
|
121
|
-
if (result !== undefined) {
|
|
136
|
+
// If handler returns a value and callback wasn't called, send the return value
|
|
137
|
+
if (!callbackCalled && result !== undefined) {
|
|
122
138
|
this.sendMessage(origin, {
|
|
123
139
|
type: 'response',
|
|
124
140
|
id,
|
|
@@ -137,6 +153,7 @@ export class MessageHandler {
|
|
|
137
153
|
}
|
|
138
154
|
/**
|
|
139
155
|
* Handle incoming response message
|
|
156
|
+
* Never rejects - always resolves with data or error object
|
|
140
157
|
*/
|
|
141
158
|
handleResponse(message) {
|
|
142
159
|
const { id, data, error } = message;
|
|
@@ -150,7 +167,8 @@ export class MessageHandler {
|
|
|
150
167
|
clearTimeout(pending.timeout);
|
|
151
168
|
this.pendingRequests.delete(id);
|
|
152
169
|
if (error) {
|
|
153
|
-
|
|
170
|
+
// Resolve with error object instead of rejecting
|
|
171
|
+
pending.resolve({ error });
|
|
154
172
|
}
|
|
155
173
|
else {
|
|
156
174
|
pending.resolve(data);
|