-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 27a396c
Showing
9 changed files
with
247 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
node_modules |
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,19 @@ | ||
Copyright (c) 2023 Bryan English | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
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,44 @@ | ||
# is-really-node | ||
|
||
Sometimes you want to make sure that the JavaScript runtime you're expecting to | ||
be running on is the one you're actually running on. With this library, you can | ||
detect whether you're actually running inside Node.js, and not Deno or Bun. A | ||
single (default) export is provided, and it's a boolean that's true if we're | ||
definitely running inside Node.js. | ||
|
||
This is done by first checking verious globals, and then attempting to alter v8 | ||
options, and testing those options have been altered. This is only currently | ||
possible in Node.js. The aim is to never have false negatives, and also load | ||
quickly if the globals-checking gives us a negative. | ||
|
||
## Some Details (FAQ) | ||
|
||
* Why not TypeScript or at least JSDoc? | ||
* The module is very small, and the code does some things that would probably | ||
piss off `tsc`. | ||
* I don't use TypeScript in my day job, so I tend not to default to it. Don't | ||
worry, I'm not one of those haters you see on Twitter. | ||
* Submit a PR that works correctly and I'll add it. | ||
* Okay, but why no `.d.ts`? | ||
* I'm lazy and Keep forgetting how to do that for default exports, since I | ||
don't use TypeScript in my day job. Submit a PR and I'll add it. | ||
* Do you just hate Bun and Deno? Are you some Node.js purist? They're both | ||
Node.js compatible anyway! | ||
* No. A lot of code I work with targets very specific runtime things that | ||
only work in Node.js, so I want an easy way to bail early if that stuff | ||
isn't going to work, even if the runtime is trying to fake that it's | ||
Node.js. That's all. Please feel free to create `is-really-bun` or | ||
`is-really-deno` if that suits your work. | ||
* Isn't checking the globals alone enough? | ||
* Nope. If folks are trying to fake that they're in Node.js, they can always | ||
mess with the globals. Instead we need to do something that's _truly_ | ||
impossible in the other platforms, like messing with v8 options. | ||
* Why no CommonJS? | ||
* Deno doesn't support CommonJS, AFAIK. | ||
* That's a bad excuse though. Really I should make this work with `require` | ||
on platforms that support it. Submit a PR that handles this and I'll add | ||
it. | ||
|
||
## License | ||
|
||
The MIT License. See LICENSE.txt |
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,78 @@ | ||
/** | ||
* First of all, this is a CommonJS module. These aren't supported by Deno, | ||
* but that can be worked around with various bundling techniques, etc. | ||
*/ | ||
|
||
/** | ||
* Let's check for some basic globals. If these aren't present, game over. | ||
*/ | ||
function hasNodeGlobals() { | ||
return typeof global === 'object' && | ||
typeof globalThis === 'object' && | ||
global === globalThis && | ||
global.global === global && | ||
globalThis.globalThis === globalThis && | ||
typeof process === 'object' | ||
} | ||
|
||
/** | ||
* Now, we check for the Bun global object. The Bun object is | ||
* non-configurable, so it would be very hard to get past this if trying to | ||
* pretend to be Node.js. | ||
*/ | ||
function hasBunGlobal() { | ||
return typeof Bun !== 'undefined' || | ||
typeof global.Bun !== 'undefined' | ||
} | ||
|
||
/** | ||
* We'll do the same here for Deno. The Deno object _can_ be delted, so this | ||
* could be faked around, so we need the subsequent test as well. | ||
*/ | ||
function hasDenoGlobal() { | ||
return typeof Deno === 'object' || | ||
typeof global.Deno === 'object' | ||
} | ||
|
||
/** | ||
* V8 has "natives syntax" which allows us to do some sneaky things. We'll now | ||
* test that those sneaky things are there and working. If it works, then | ||
* we're definitely not in Bun, which uses JSC. If it does, we'll try to | ||
* disable it, ruling out Deno. | ||
*/ | ||
async function isNodeIshV8() { | ||
let v8 | ||
try { | ||
v8 = await import('node:v8') | ||
} catch { | ||
return false | ||
} | ||
|
||
function privateSymbol() { | ||
try { | ||
const sym = eval('%CreatePrivateSymbol("testing")') | ||
const obj = {} | ||
obj[sym] = 3 | ||
return !Reflect.ownKeys(obj).includes(sym) && obj[sym] === 3 | ||
} catch { | ||
return false | ||
} | ||
} | ||
|
||
// JSC/Bun doesn't support V8's native syntax. | ||
if (privateSymbol()) { | ||
// Natives syntax was on. Try turning it off. That' won't work in Deno. | ||
v8.setFlagsFromString('--no-allow-natives-syntax') | ||
return !privateSymbol() | ||
} | ||
|
||
// Deno "supports" this, but it does nothing. So if it failed before, it | ||
// will fail again. | ||
v8.setFlagsFromString('--allow-natives-syntax') | ||
return privateSymbol() | ||
} | ||
|
||
export default hasNodeGlobals() && | ||
!hasBunGlobal() && | ||
!hasDenoGlobal() && | ||
await isNodeIshV8() |
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,27 @@ | ||
{ | ||
"name": "is-really-node", | ||
"version": "1.0.0", | ||
"description": "Determine whether the current runtime is _really_ Node.js, or some impostor.", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "node test" | ||
}, | ||
"type": "module", | ||
"repository": { | ||
"type": "git", | ||
"url": "git+ssh://[email protected]/bengl/is-really-node.git" | ||
}, | ||
"keywords": [ | ||
"Node.js", | ||
"Bun", | ||
"Deno", | ||
"detect", | ||
"environment" | ||
], | ||
"author": "Bryan English <[email protected]>", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/bengl/is-really-node/issues" | ||
}, | ||
"homepage": "https://github.com/bengl/is-really-node#readme" | ||
} |
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,61 @@ | ||
import { exec } from 'child_process' | ||
import test from 'node:test' | ||
import assert from 'assert' | ||
|
||
function run(...args) { | ||
return new Promise((resolve, reject) => { | ||
exec(...args, (err, stdout, stderr) => { | ||
if (err) reject(err) | ||
resolve({ stdout, stderr }) | ||
}) | ||
}) | ||
} | ||
|
||
test('Node.js', async () => { | ||
await run('node test/node-test.js') | ||
}) | ||
|
||
test('Node.js (allow-natives-syntax)', async () => { | ||
await run('node --allow-natives-syntax test/node-test.js') | ||
}) | ||
|
||
test('Node.js (no-allow-natives-syntax)', async () => { | ||
await run('node --no-allow-natives-syntax test/node-test.js') | ||
}) | ||
|
||
test('Deno', async () => { | ||
await assert.rejects( | ||
() => run('deno run test/node-test.js') | ||
) | ||
}) | ||
|
||
test('Deno (faking Node.js)', async () => { | ||
await assert.rejects( | ||
() => run('deno run test/deno-test.js') | ||
) | ||
}) | ||
|
||
test('Deno (faking Node.js) (allow-natives-syntax)', async () => { | ||
await assert.rejects( | ||
() => run('deno run --v8-flags="--allow-natives-syntax" test/deno-test.js') | ||
) | ||
}) | ||
|
||
test('Deno (faking Node.js) (no-allow-natives-syntax)', async () => { | ||
await assert.rejects( | ||
() => run('deno run --v8-flags="--allow-natives-syntax" test/deno-test.js') | ||
) | ||
}) | ||
|
||
test('Bun', async () => { | ||
await assert.rejects( | ||
() => run('deno run test/node-test.js') | ||
) | ||
}) | ||
|
||
test('Bun (faking Node.js)', async () => { | ||
await assert.rejects( | ||
() => run('deno run test/deno-test.js') | ||
) | ||
}) | ||
|
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,6 @@ | ||
globalThis.global = globalThis | ||
|
||
//// Not possible in Bun | ||
// delete globalThis.Bun | ||
|
||
import('./node-test.js') |
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,7 @@ | ||
globalThis.global = globalThis | ||
|
||
globalThis.process = {} | ||
|
||
delete globalThis.Deno | ||
|
||
import('./node-test.js') |
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,4 @@ | ||
import isNode from '../index.js' | ||
import assert from 'node:assert' | ||
|
||
assert.strictEqual(true, isNode) |