Skip to content

Commit 20137ed

Browse files
authored
Merge pull request #16 from johnsonjo4531/master
Optimize Transferables
2 parents e6f1790 + 1fee8ba commit 20137ed

File tree

3 files changed

+25
-8
lines changed

3 files changed

+25
-8
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
/dist
22
/node_modules
33
/package-lock.json
4+
/npm-debug.log

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ console.log(await getName('developit'))
4848

4949
[🔄 **Run this example on JSFiddle**](https://jsfiddle.net/developit/mf9fbma5/)
5050

51+
52+
## Transferable ready
53+
54+
Greenlet will even accept and optimize [transferables](https://developer.mozilla.org/en-US/docs/Web/API/Transferable) as arguments to and from a greenlet worker function.
55+
56+
5157
## Browser support
5258

5359
Thankfully, Web Workers have been around for a while and [are broadly supported](https://caniuse.com/#feat=webworkers) by Chrome, Firefox, Safari, Edge, and Internet Explorer 10+.
@@ -62,7 +68,6 @@ if (window.Worker) {
6268
}
6369
```
6470

65-
6671
## License & Credits
6772

6873
> In addition to the contributors, credit goes to [@sgb-io](https://github.com/sgb-io) for his annotated exploration of Greenlet's source. This prompted a refactor that clarified the code and allowed for further size optimizations.

greenlet.js

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
export default function greenlet(asyncFunction) {
66
// Create an "inline" worker (1:1 at definition time)
77
let worker = new Worker(
8-
// The URL is a pointer to a stringified function (as a blob object)
8+
// The URL is a pointer to a stringified function (as a blob object)
99
URL.createObjectURL(
1010
new Blob([
1111
// Register our wrapper function as the message handler
@@ -17,9 +17,15 @@ export default function greenlet(asyncFunction) {
1717
userFunc.apply.bind(userFunc, userFunc)
1818
).then(
1919
// success handler - callback(id, SUCCESS(0), result)
20-
d => { postMessage([e.data[0], 0, d]); },
20+
// if `d` is transferable transfer zero-copy
21+
d => {
22+
postMessage([e.data[0], 0, d], (
23+
d instanceof ArrayBuffer ||
24+
d instanceof MessagePort ||
25+
d instanceof ImageBitmap) ? [d] : []);
26+
},
2127
// error handler - callback(id, ERROR(1), error)
22-
e => { postMessage([e.data[0], 1, ''+e]); }
28+
er => { postMessage([e.data[0], 1, '' + er]); }
2329
);
2430
}
2531
) + ')(' + asyncFunction + ')' // pass user-supplied function to the closure
@@ -48,14 +54,19 @@ export default function greenlet(asyncFunction) {
4854
};
4955

5056
// Return a proxy function that forwards calls to the worker & returns a promise for the result.
51-
return function(args) {
57+
return function (args) {
5258
args = [].slice.call(arguments);
53-
return new Promise(function() {
59+
return new Promise(function () {
5460
// Add the promise controller to the registry
5561
promises[++currentId] = arguments;
5662

5763
// Send an RPC call to the worker - call(id, params)
58-
worker.postMessage([currentId, args]);
64+
// The filter is to provide a list of transferables to send zero-copy
65+
worker.postMessage([currentId, args], args.filter(x => (
66+
x instanceof ArrayBuffer ||
67+
x instanceof MessagePort ||
68+
x instanceof ImageBitmap
69+
)));
5970
});
6071
};
61-
}
72+
}

0 commit comments

Comments
 (0)