-
Notifications
You must be signed in to change notification settings - Fork 286
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(neon): Tag
Root
with an instance id and verify before using
Resolves #843
- Loading branch information
1 parent
f7ae61c
commit fdab374
Showing
7 changed files
with
214 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
const assert = require('assert'); | ||
const {Worker, isMainThread, parentPort} = require('worker_threads'); | ||
|
||
const addon = require('..'); | ||
|
||
// Receive a message, try that method and return the error message | ||
if (!isMainThread) { | ||
parentPort.once('message', (message) => { | ||
try { | ||
switch (message) { | ||
case 'get_and_replace': | ||
addon.get_and_replace({}); | ||
break; | ||
case 'get_or_init': | ||
addon.get_or_init(() => ({})); | ||
break; | ||
case 'get_or_init_clone': | ||
addon.get_or_init_clone(() => ({})); | ||
break; | ||
default: | ||
throw new Error(`Unexpected message: ${message}`); | ||
} | ||
|
||
throw new Error('Did not throw an exception'); | ||
} catch (err) { | ||
parentPort.postMessage(err); | ||
} | ||
}); | ||
|
||
return; | ||
} | ||
|
||
describe('Worker / Root Tagging Tests', () => { | ||
describe("Single Threaded", () => { | ||
it('should be able to stash a global with `get_and_replace`', () => { | ||
const first = {}; | ||
const second = {}; | ||
|
||
assert.strictEqual(addon.get_and_replace(first), undefined); | ||
assert.strictEqual(addon.get_and_replace(second), first); | ||
assert.strictEqual(addon.get_and_replace({}), second); | ||
}); | ||
|
||
it('should be able to lazily initialize with `get_or_init`', () => { | ||
const o = {}; | ||
|
||
assert.strictEqual(addon.get_or_init(() => o), o); | ||
assert.strictEqual(addon.get_or_init(() => ({})), o); | ||
assert.strictEqual(addon.get_or_init(), o); | ||
}); | ||
|
||
it('should be able to lazily initialize with `get_or_init_clone`', () => { | ||
const o = {}; | ||
|
||
assert.strictEqual(addon.get_or_init_clone(() => o), o); | ||
assert.strictEqual(addon.get_or_init_clone(() => ({})), o); | ||
assert.strictEqual(addon.get_or_init_clone(), o); | ||
}); | ||
}); | ||
|
||
// Note: These tests require that the previous set of tests have run or else they will fail | ||
describe("Multi-Threaded", () => { | ||
it('should fail to use `get_and_replace`', (cb) => { | ||
const worker = new Worker(__filename); | ||
|
||
worker.once('message', (message) => { | ||
assert.ok(/wrong module/.test(message)); | ||
cb(); | ||
}); | ||
|
||
worker.postMessage('get_and_replace'); | ||
}); | ||
|
||
it('should fail to use `get_or_init`', (cb) => { | ||
const worker = new Worker(__filename); | ||
|
||
worker.once('message', (message) => { | ||
assert.ok(/wrong module/.test(message)); | ||
cb(); | ||
}); | ||
|
||
worker.postMessage('get_or_init'); | ||
}); | ||
|
||
it('should fail to use `get_or_init`', (cb) => { | ||
const worker = new Worker(__filename); | ||
|
||
worker.once('message', (message) => { | ||
assert.ok(/wrong module/.test(message)); | ||
cb(); | ||
}); | ||
|
||
worker.postMessage('get_or_init_clone'); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
use std::sync::Mutex; | ||
|
||
use neon::prelude::*; | ||
use once_cell::sync::{Lazy, OnceCell}; | ||
|
||
pub fn get_and_replace(mut cx: FunctionContext) -> JsResult<JsValue> { | ||
static OBJECT: Lazy<Mutex<Option<Root<JsObject>>>> = Lazy::new(Default::default); | ||
|
||
let mut global = OBJECT.lock().unwrap_or_else(|err| err.into_inner()); | ||
let next = cx.argument::<JsObject>(0)?.root(&mut cx); | ||
let previous = global.replace(next); | ||
|
||
Ok(match previous { | ||
None => cx.undefined().upcast(), | ||
Some(previous) => previous.into_inner(&mut cx).upcast(), | ||
}) | ||
} | ||
|
||
pub fn get_or_init(mut cx: FunctionContext) -> JsResult<JsObject> { | ||
static OBJECT: OnceCell<Root<JsObject>> = OnceCell::new(); | ||
|
||
let o = OBJECT.get_or_try_init(|| { | ||
cx.argument::<JsFunction>(0)? | ||
.call_with(&cx) | ||
.apply::<JsObject, _>(&mut cx) | ||
.map(|v| v.root(&mut cx)) | ||
})?; | ||
|
||
Ok(o.to_inner(&mut cx)) | ||
} | ||
|
||
pub fn get_or_init_clone(mut cx: FunctionContext) -> JsResult<JsObject> { | ||
static OBJECT: OnceCell<Root<JsObject>> = OnceCell::new(); | ||
|
||
let o = OBJECT.get_or_try_init(|| { | ||
cx.argument::<JsFunction>(0)? | ||
.call_with(&cx) | ||
.apply::<JsObject, _>(&mut cx) | ||
.map(|v| v.root(&mut cx)) | ||
})?; | ||
|
||
// Note: This intentionally uses `clone` instead of `to_inner` in order to | ||
// test the `clone` method. | ||
Ok(o.clone(&mut cx).into_inner(&mut cx)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters