Skip to content

Commit 9ed2f9f

Browse files
committed
transferrables added
1 parent 4107e60 commit 9ed2f9f

File tree

3 files changed

+89
-7
lines changed

3 files changed

+89
-7
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ console.log(await getName('developit'))
4848

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

51+
## Transferable ready
52+
53+
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 functions.
54+
5155
## License & Credits
5256

5357
> 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: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,55 @@
1+
/**
2+
* Checks whether an object implements a Transferable interface
3+
* @param {*} obj
4+
* obj to check for Transferable interface
5+
*/
6+
function isTransferable(obj) {
7+
// https://developer.mozilla.org/en-US/docs/Web/API/Transferable
8+
return (
9+
obj instanceof ArrayBuffer ||
10+
obj instanceof MessagePort ||
11+
obj instanceof ImageBitmap
12+
);
13+
}
14+
115
/** Move an async function into its own thread.
216
* @param {Function} asyncFunction An (async) function to run in a Worker.
317
* @public
418
*/
519
export default function greenlet(asyncFunction) {
620
// Create an "inline" worker (1:1 at definition time)
721
let worker = new Worker(
8-
// The URL is a pointer to a stringified function (as a blob object)
22+
// The URL is a pointer to a stringified function (as a blob object)
923
URL.createObjectURL(
1024
new Blob([
1125
// Register our wrapper function as the message handler
1226
'onmessage=(' + (
1327
// userFunc() is the user-supplied async function
1428
userFunc => e => {
29+
// To check whether an obj is transferable
30+
function isTransferable(obj) {
31+
// https://developer.mozilla.org/en-US/docs/Web/API/Transferable
32+
return (
33+
obj instanceof ArrayBuffer ||
34+
obj instanceof MessagePort ||
35+
obj instanceof ImageBitmap
36+
);
37+
}
1538
// Invoking within then() captures exceptions in userFunc() as rejections
1639
Promise.resolve(e.data[1]).then(
1740
userFunc.apply.bind(userFunc, userFunc)
1841
).then(
1942
// success handler - callback(id, SUCCESS(0), result)
20-
d => { postMessage([e.data[0], 0, d]); },
43+
d => {
44+
if (isTransferable(d)) {
45+
postMessage([e.data[0], 0, d], [d]);
46+
}
47+
else {
48+
postMessage([e.data[0], 0, d]);
49+
}
50+
},
2151
// error handler - callback(id, ERROR(1), error)
22-
e => { postMessage([e.data[0], 1, ''+e]); }
52+
er => { postMessage([e.data[0], 1, '' + er]); }
2353
);
2454
}
2555
) + ')(' + asyncFunction + ')' // pass user-supplied function to the closure
@@ -48,14 +78,14 @@ export default function greenlet(asyncFunction) {
4878
};
4979

5080
// Return a proxy function that forwards calls to the worker & returns a promise for the result.
51-
return function(args) {
81+
return function (args) {
5282
args = [].slice.call(arguments);
53-
return new Promise(function() {
83+
return new Promise(function () {
5484
// Add the promise controller to the registry
5585
promises[++currentId] = arguments;
5686

5787
// Send an RPC call to the worker - call(id, params)
58-
worker.postMessage([currentId, args]);
88+
worker.postMessage([currentId, args], args.filter(x => isTransferable(x)));
5989
});
6090
};
61-
}
91+
}

npm-debug.log

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
0 info it worked if it ends with ok
2+
1 verbose cli [ '/Users/johnjohnson/.nvm/versions/node/v6.10.1/bin/node',
3+
1 verbose cli '/Users/johnjohnson/.nvm/versions/node/v6.10.1/bin/npm',
4+
1 verbose cli 'run',
5+
1 verbose cli 'test' ]
6+
2 info using [email protected]
7+
3 info using [email protected]
8+
4 verbose run-script [ 'pretest', 'test', 'posttest' ]
9+
5 info lifecycle [email protected]~pretest: [email protected]
10+
6 silly lifecycle [email protected]~pretest: no script for pretest, continuing
11+
7 info lifecycle [email protected]~test: [email protected]
12+
8 verbose lifecycle [email protected]~test: unsafe-perm in lifecycle true
13+
9 verbose lifecycle [email protected]~test: PATH: /Users/johnjohnson/.nvm/versions/node/v6.10.1/lib/node_modules/npm/bin/node-gyp-bin:/Users/johnjohnson/Documents/code/javascript/bins/greenlet-test/greenlet-fork/greenlet/node_modules/.bin:/Users/johnjohnson/.nvm/versions/node/v6.10.1/bin:/Applications/CMake.app/Contents/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/TeX/texbin:/usr/local/share/dotnet:/opt/X11/bin:/Library/Frameworks/Mono.framework/Versions/Current/Commands:/Applications/Wireshark.app/Contents/MacOS:/Applications/CMake.app/Contents/bin:/usr/local/share/scala/scala-2.12.1/bin:/Users/johnjohnson/bin:/usr/local/share/scala/scala-2.12.1/bin:/Users/johnjohnson/bin
14+
10 verbose lifecycle [email protected]~test: CWD: /Users/johnjohnson/Documents/code/javascript/bins/greenlet-test/greenlet-fork/greenlet
15+
11 silly lifecycle [email protected]~test: Args: [ '-c', 'eslint *.js && npm run -s prepare && karmatic' ]
16+
12 silly lifecycle [email protected]~test: Returned: code: 1 signal: null
17+
13 info lifecycle [email protected]~test: Failed to exec test script
18+
14 verbose stack Error: [email protected] test: `eslint *.js && npm run -s prepare && karmatic`
19+
14 verbose stack Exit status 1
20+
14 verbose stack at EventEmitter.<anonymous> (/Users/johnjohnson/.nvm/versions/node/v6.10.1/lib/node_modules/npm/lib/utils/lifecycle.js:255:16)
21+
14 verbose stack at emitTwo (events.js:106:13)
22+
14 verbose stack at EventEmitter.emit (events.js:191:7)
23+
14 verbose stack at ChildProcess.<anonymous> (/Users/johnjohnson/.nvm/versions/node/v6.10.1/lib/node_modules/npm/lib/utils/spawn.js:40:14)
24+
14 verbose stack at emitTwo (events.js:106:13)
25+
14 verbose stack at ChildProcess.emit (events.js:191:7)
26+
14 verbose stack at maybeClose (internal/child_process.js:886:16)
27+
14 verbose stack at Process.ChildProcess._handle.onexit (internal/child_process.js:226:5)
28+
15 verbose pkgid [email protected]
29+
16 verbose cwd /Users/johnjohnson/Documents/code/javascript/bins/greenlet-test/greenlet-fork/greenlet
30+
17 error Darwin 17.3.0
31+
18 error argv "/Users/johnjohnson/.nvm/versions/node/v6.10.1/bin/node" "/Users/johnjohnson/.nvm/versions/node/v6.10.1/bin/npm" "run" "test"
32+
19 error node v6.10.1
33+
20 error npm v3.10.10
34+
21 error code ELIFECYCLE
35+
22 error [email protected] test: `eslint *.js && npm run -s prepare && karmatic`
36+
22 error Exit status 1
37+
23 error Failed at the [email protected] test script 'eslint *.js && npm run -s prepare && karmatic'.
38+
23 error Make sure you have the latest version of node.js and npm installed.
39+
23 error If you do, this is most likely a problem with the greenlet package,
40+
23 error not with npm itself.
41+
23 error Tell the author that this fails on your system:
42+
23 error eslint *.js && npm run -s prepare && karmatic
43+
23 error You can get information on how to open an issue for this project with:
44+
23 error npm bugs greenlet
45+
23 error Or if that isn't available, you can get their info via:
46+
23 error npm owner ls greenlet
47+
23 error There is likely additional logging output above.
48+
24 verbose exit [ 1, true ]

0 commit comments

Comments
 (0)