
Research
Two Malicious Rust Crates Impersonate Popular Logger to Steal Wallet Keys
Socket uncovers malicious Rust crates impersonating fast_log to steal Solana and Ethereum wallet keys from source code.
prevent-undefined
Advanced tools
prevent-undefined let you know when your code refers a non-existing propery
prevent-undefined
throws an error to let you know that you accidentally refer
an undefined propery on your object.
It also displays dump of the refered object for your convenience. See below :
const { preventUndefined } = require("prevent-undefined" );
// or
import { preventUndefined } from "prevent-undefined";
// foo.js
const someObj = {
hello : {
world : {
foo : {
bar : {
baz : "HELLO",
},
}
}
}
};
preventUndefined( someObj ).hello.world.foo.bar.VAZ;
// SOME TYPO ^^^
then, you'll get:
> node foo.js
ReferenceError: obj.hello.world.foo.bar.VAZ is not defined in {
hello: {
world: { foo: { bar: { baz: 'HELLO' } } }
}
}
preventUndefined
The major usecase of preventUndefined
is checking validity of named parameter
values:
function someFunc(args){
const {foo,bar} = preventUndefined(args);
console.error("foo:",foo);
}
someFunc({wrongArg1:"foo", wrongArg2:"bar";});
> ReferenceError: obj.foo is not defined in {
> "wrongArg1": "foo",
> "wrongArg2": "bar"
> }
Sometimes, you will want to unprevent your objects especially when you want to use optional chaining:
const { preventUndefined } = require('prevent-undefined');
const someObj = {
hello : {
world : {
foo : {
bar : {
baz : {
message : "HELLO",
}
},
}
}
}
};
const o = preventUndefined( someObj );
function proc(o){
return o.hello?.world?.foo?.bar?.baz?.value ?? "hello world";
}
proc(o);
you'll get
ReferenceError: obj.hello.world.foo.bar.baz.value is not defined in {
hello: {
world: {
foo: { bar: { baz: { message: 'HELLO' } } }
}
}
}
at Object.get (/.../common.js:91:17)
which you definitely don't want.
Use unprevent()
const { unprevent } = require("prevent-undefined");
function proc(o){
o=unprevent(o);
return o.hello?.world?.foo?.bar?.baz?.value ?? "hello world";
}
proc(o); // you'll get "hello world" as expected.
recursivelyUnprevent()
recursively unprevent the specified object, literally.
Currently recursivelyUnprevent()
is in the beta state; therefore, please use
this with care. Currently, this does not check any circular references.
recursivelyUnprevent()
was ADDED v0.2.19.
The basic idea is :
// There is a func as :
function someFunc({foo,bar}){
console.error("foo:",foo);
console.error("bar:",bar);
// note that `baz` is not used at all.
}
var foo = 'foo';
var bar = 'bar';
var baz = 'baz';
// `baz` a property which the caller thinks it is valid but actually isn't.
someFunc({foo,bar,baz});
> foo: foo
> bar: bar
// You'll get `foo` `bar` without getting any error that sucks.
In order to prevent such tiredness, use preventUnusedProperties()
.
const { preventUnusedProperties } = require("prevent-undefined");
function someFunc(args){
// Prevent undefined on the `args` object before destructuring it.
const {foo,bar} = preventUndefined(args);
// After destructured the `args` object, call `preventUnusedProperties()`
preventUnusedProperties(args);
console.error("foo:",foo);
console.error("bar:",bar);
}
var foo = 'foo';
var bar = 'bar';
var baz = 'baz';
someFunc({foo,bar,baz});
> ReferenceError: the field [baz] was not referred in
> {
> "foo": "foo",
> "bar": "bar",
> "baz": "baz"
> }
preventUnusedProperties()
has been added v0.2.20.
isUndefinedPrevented()
function returns true if a specified object is
protected by preventUndefined()
function.
isUndefinedPrevented()
has been added on v0.2.31
preventUndefined()
protects the specified object and all of its properties as
well. As default, it protects all of descendants recursively. You can limit its
maximum recursive level.
const obj = {
foo: {
bar : {
baz :{
data:1
},
},
},
};
test( 'maxRecursiveLevel ... base ', ()=>{
const po = preventUndefined( obj );
expect( isUndefinedPrevented( po.foo )).toBe( true );
expect( isUndefinedPrevented( po.foo.bar )).toBe( true );
expect( isUndefinedPrevented( po.foo.bar.baz )).toBe( true );
});
test( 'maxRecursiveLevel ...0 ', ()=>{
const po = preventUndefined( obj, {maxRecursiveLevel:0 } );
expect( isUndefinedPrevented( po )).toBe( false );
expect( isUndefinedPrevented( po.foo )).toBe( false );
expect( isUndefinedPrevented( po.foo.bar )).toBe( false );
expect( isUndefinedPrevented( po.foo.bar.baz )).toBe( false );
});
test( 'maxRecursiveLevel ...1 ', ()=>{
const po = preventUndefined( obj, {maxRecursiveLevel:1 } );
expect( isUndefinedPrevented( po )).toBe( true );
expect( isUndefinedPrevented( po.foo )).toBe( false );
expect( isUndefinedPrevented( po.foo.bar )).toBe( false );
expect( isUndefinedPrevented( po.foo.bar.baz )).toBe( false );
});
test( 'maxRecursiveLevel ...2 ', ()=>{
const po = preventUndefined( obj, {maxRecursiveLevel:2 } );
expect( isUndefinedPrevented( po )).toBe( true );
expect( isUndefinedPrevented( po.foo )).toBe( true );
expect( isUndefinedPrevented( po.foo.bar )).toBe( false );
expect( isUndefinedPrevented( po.foo.bar.baz )).toBe( false );
});
test( 'maxRecursiveLevel ...3 ', ()=>{
const po = preventUndefined( obj, {maxRecursiveLevel:3 } );
expect( isUndefinedPrevented( po )).toBe( true );
expect( isUndefinedPrevented( po.foo )).toBe( true );
expect( isUndefinedPrevented( po.foo.bar )).toBe( true );
expect( isUndefinedPrevented( po.foo.bar.baz )).toBe( false );
});
ADDED v0.2.33 (Sat, 07 Jan 2023 17:51:53 +0900)
If you set a validator to the second parameter of preventUndefined()
, it monitors
every modification on the object to keep consistency of the object.
const validator = (o)=>typeof o?.foo?.bar?.value === 'number';
const obj = preventUndefined({
foo : {
bar : {
value : 100,
},
}
}, validator);
obj.foo.bar.value = 'BUMMER! NOT A NUMBER';
> ReferenceError: detected defining an invalid property value to obj.foo.bar.value on
> {
> "foo": {
> "bar": {
> "value": "BUMMER! NOT A NUMBER"
> }
> }
> }
validator
is a function which receives an argument and returns a boolean
value.
The only argument is the value to be validated. Return true
if the target
object is valid; otherwise return false.
A validator
function should not throw an error; if the validator throws an
error, that causes the process that invokes the validation to throw the error.
( You might expect that throwing any error is treated as invalid state of the target object since if the validation process interrupts the main process, it could interrupt entire process; but this behavior is intentional because it is important to let the user know the validator encounters something that the user did not expect. )
I recommend you to use a non-opinionated validator Vanilla Schema Validator; though it is not mandatory.
Validators have been added in v0.2.23.
onError
Started from v0.2.27, you can specify an event handler when you call
preventUndefined()
:
const obj = preventUndefined({
foo: 'foo',
bar: 'bar',
}, {
onError: (info)=>{
console.error( 'called ' + info.propPath );
}
});
console.error( "peekaboo! ", obj.wrongProp );
> "called wrongProp"
>
> ReferenceError: [prevent-undefined] obj.wrongProp is not defined in {
> "foo": "foo",
> "bar": "bar"
> }
> [stacktrace]
> ...
Some information about the error which has just occured is available as the properties on the first argument of the event handler.
propPath
propPath
property is an array object which consists the property names.
const onError(info)=>{
console.error(info.propPath); //
};
const someObj = {
hello : {
world : {
foo : {
bar : {
baz : "HELLO",
},
}
}
}
};
preventUndefined( someObj,{onError}).hello.world.foo.bar.VAZ;
// SOME TYPO AGAIN ^^^
then, you'll get
> hello.world.foo.bar.VAZ
target
target
property is the target object which you specify as the first argument
when you call preventUndefined()
.
message
message
property is the string value on the message property on the error
object which is thrown.
stackOnCreated
stackOnCreated
is an array object which consists the stacktrace when
preventUndefined()
is called.
stackOnOccured
stackOnOccured
is an array object which consists the stacktrace when the
illegal access on the target object is occured.
event handler
started from v0.2.27
errorIfUndefined()
is a perfect fancy mascot to implement
''prevent-undefined way'' of named parameters. When you call errorIfUndefined()
,
it simply throws ReferenceError(). Its only use case is as following :
function strictFunc({foo=errorIfUndefined('foo')}) {
console.error(foo);
}
strictFunc({ foo_WITH_TYPO: 'foo' });
> ReferenceError: the parameter value of foo was undefined; any reference to an undefined value is strictly prohibited on this object.
errorIfUndefined
takes only one parameter : name
which is to specify the name of the parameter.
errorIfUndefined()
has been added in v0.2.19.
DEPRECATED v0.2.33 This feature will be removed in near future.
prevent-undefined
IMHO, undefined
is always evil:
// you defined some procedures :
function showName(name){
if (name.length<10) {
console.error( "a short name", name );
} else {
console.error( "a long name", name );
}
}
function foo(guy) {
showName(guy.name);
}
// then, you have some data:
const guy1 = getYourDataFromResource('john');
const guy2 = getYourDataFromResource('paul');
// then, you want to exec the procedures with your data:
foo(guy1)
foo(guy2);
// and if you misteriously get ReferenceError as
> TypeError: Cannot read properties of undefined (reading 'length')
> at showName (..) file.js:17:14
> ...
At this point, you have no clue where the problem came from. At this point, you will never notice that some specific unenthusiastic programmer made a function as following:
const JOHN ={
name:'John',
age: 18,
};
const PAUL ={
name:'Paul',
age: 23,
};
function getYourDataFromResource(id) {
if ( id === 'john' ) {
return {
name : JOHN.nameeeeeeeeeeeeeeeeee;
}
} else if ( id ==='paul' ) {
return {
name : PAUL.naaaaaaaaaaaame;
}
} else {
// wat
}
}
Even though the problem is obviously occured inside the function
getYourDataFromResource()
you will only get the error from a totaly
irrelevant function showName()
which is very confusing and annoying.
The language should actually throw an Error where the undefined
comes out.
IMHO, undefined
is always poisoneous; the language system should have never
allow the existence of undefined
. In spite of the difficulty, the current
specification of ECMA Script cannot detect undefined properties even if you
enable 'use strict'.
This is where prevent-undefined
come in.
const JOHN = preventUndefined({
NAME:'John',
AGE: 18,
});
const PAUL = preventUndefined({
NAME:'Paul',
AGE: 23,
});
function getYourDataFromResource(id) {
if ( id === 'john' ) {
return {
name : JOHN.namee; // this throws error.
}
} else if ( id ==='PaUL' ) {
return {
name : PAUL.naame; // this throws error, too.
}
}
}
When you applied prevent-undefined
in this way, you can easily indicate where
the problematic undefined
comes from.
IMHO, you should always avoid referencing undefined properties for any form.
Write not like this:
if ( o.foo ) {
console.error( 'foo exists' );
}
Write like this:
if ( 'foo' in o ) {
console.error( 'foo exists' );
}
Because the conditional check o.foo
implicitly references undefined
which
makes detecting undefined
very difficult.
// if the o was get preventUndefined()ed somewhere before:
if ( o.foo ) { // this throws ReferenceError()
console.error( 'foo exists' );
}
Unfortunately some functions from the standard JavaScript library use implicit
referencing undefined
; for example,
const o = preventUndefined( {hello:1})
// The following code will end up ReferenceError which led our `preventUndefined()` to
// ignore `then` with some hard-coding.
Promise.resolve( o );
That is, if you have found some standard functions that implicitly refers
undefined
it is necessary to add the name of the property to the ignore list
which is hard-coded in prevent-undefined
module.
This didn't work; it didn't support common.js.
(may) supports both common.js and es6 module.
Special thanks goes to How to Create a Hybrid NPM Module for ESM and CommonJS. This site helped a lot. Thank you very much.
(Fri, 14 Oct 2022 19:53:18 +0900)
Supported unpreventing null
unprevent( null ) == null
Fixed an issue that it throws TypeError when a symbol property is accessed.
Added keywords to ignore such as toJSON, Symbol.toStringTag
,
Symbol.toPrimitive
, etc.
Added $$typeof
to the ignore keyword list to let prevent-undefined
work
cooperatively with React.js
.
This very informative article Why Do React Elements Have a $$typeof Property? helped me to understand the problem. Thank you very much.
v0.2.11
does not work as an ES6 module due to my carelessness. The problem
was fixed n this version.
Skipped the version v0.2.13
via fear of Friday the 13th. This version have
never been released.
In the version v0.2.11
, I documented, commented, and tested it without
modifying the actual code. Believe me, this time I actually modified.
const i = a[Symbol.iterator];
if (i === undefined ) {
// ...
}
which is not a preferable behavior for this module.
Changed the way to check if the object is a symbol or not.
(Mon, 24 Oct 2022 17:40:53 +0900)
Added '@@iterator' to the ignore list in order to avoid an issue that will
occur when use this module with React.js
.
(Thu, 03 Nov 2022 17:11:29 +0900) Removed a unnecessarily left unremoved debug logging output.
(Mon, 07 Nov 2022 16:17:06 +0900)
Added recursivelyUnprevent()
and errorIfUndefined()
(Wed, 09 Nov 2022 15:52:32 +0900)
Added preventUnusedProperties()
Updated README.md; added a section The Basic Idea of preventUndefined()
.
(Wed, 09 Nov 2022 16:01:54 +0900) Updated README.md.
(Wed, 09 Nov 2022 16:11:21 +0900) Updated README.md.
(Mon, 14 Nov 2022 17:25:30 +0900) Supported validators.
(Tue, 15 Nov 2022 16:03:18 +0900)
Supported rtti
.
(Tue, 15 Nov 2022 16:08:53 +0900)
rtti
is renamed to typesafe
.
(Wed, 23 Nov 2022 19:15:59 +0900)
Now preventUndefined
displays the stacktrace not only where the illegal
access is occured but where the object is protected by preventUndefined()
,
too. Hopefully this will let you know where your problematic object comes from.
Added the error handler onError()
.
(Fri, 30 Dec 2022 11:44:22 +0900) Removed unnecessary files from the package.
(Fri, 30 Dec 2022 14:02:41 +0900)
Deprecated typesafe
.
README.md
; changed the link to the recommended library for validation
from rtti.js
to vanilla-schema-validator
due to deprecation of rtti.js
.prevent-undefined
.
(Thu, 05 Jan 2023 11:45:45 +0900)script
propety, show its content on validation
fail.'ownKeys' on proxy: trap returned duplicate entries`
This is caused by either a bug in Node.js or incorrect usage of Node.js internals.
Please open an issue with this stack trace at https://github.com/nodejs/node/issues`
Intercepting getOwnPropertyDescriptor()
and ownKeys() by using Proxy
sometimes makes Node.js crash; I am not sure what exactly causes the problem
but it surely causes it to crash.
(Sat, 07 Jan 2023 17:51:53 +0900)
maxRecursiveLevel
feature(Fri, 20 Jan 2023 19:40:35 +0900)
debugger
directive(Fri, 20 Jan 2023 19:58:25 +0900) fixed the issue that the package could not be loaded; v0.2.34 was broken.
(Wed, 25 Jan 2023 14:42:54 +0900)
(Wed, 25 Jan 2023 16:31:47 +0900)
thisArg
via call()
/ apply()
.(Tue, 21 Feb 2023 10:35:08 +0900)
(Tue, 21 Feb 2023 17:27:43 +0900)
(Mon, 08 May 2023 13:50:28 +0900) (Though, actual modification was done on May 2 2023)
(Mon, 31 Jul 2023 19:15:26 +0900)
Buffer
to the excluding class list.peerDependencies
.(Fri, 24 May 2024 20:17:33 +0900)
! ( 'propertyName' in obj )
and
typeof obj.propertyName === 'undefined'
; only throw
an error when the specified property does not exist.
(not released)(Thu, 13 Jun 2024 14:50:09 +0900)
inspect
function returns a string value "undefined" when it
inspects undefined
; note that JSON.stringify returns a undefined
value not
a string value when it receives undefined
value. (not released)(Thu, 05 Sep 2024 18:17:04 +0900)
prevent-undefined
was released as v3.0.4 on Sep 5 2024.That's all. Thank you very much.
FAQs
prevent-undefined let you know when your code refers a non-existing propery
We found that prevent-undefined demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Socket uncovers malicious Rust crates impersonating fast_log to steal Solana and Ethereum wallet keys from source code.
Research
A malicious package uses a QR code as steganography in an innovative technique.
Research
/Security News
Socket identified 80 fake candidates targeting engineering roles, including suspected North Korean operators, exposing the new reality of hiring as a security function.