Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Native JavaScript API for Bindings.
NJS-API is a header-only C++ library that abstracts APIs of JavaScript virtual machines (VMs) into a single API that can be used by embedders to write bindings compatible with multiple JS engines. The motivation to start the project were breaking changes of V8 engine and the way V8 bindings are written (too verbose and too annoying to handle all possible error conditions). In addition, attempt to port node.js to use Chakra javascript engine instead of V8 contributed to the idea of creating a single API that can target multiple JS engines, not just V8.
NJS is a WORK-IN-PROGRESS that has been published to validate the initial ideas and to design the API with more people. The library started as a separate project when developing blend2d-js to make bindings easier to write, easier to maintain, and also more secure.
Classes provided by NJS-API:
njs::Result
- 32-bit unsigned integer representing result-codenjs::Utf8Ref
- Tagged reference to UTF-8 stringnjs::Utf16Ref
- Tagged reference to UTF-16 stringnjs::Latin1Ref
- Tagged reference to LATIN1 stringnjs::Range<T>
- Minimum and maximum value, that can be used to restrict JS to C++ value conversionnjs::Value
- Local javascript value (wraps v8::Local<v8::Value>
)njs::Persistent
- A persistent javascript value (wraps v8::Persistent<v8::Value>
)njs::HandleScope
- Handle scope, currently maps to v8::HandleScope
njs::Runtime
- Runtime is mapped to the underlying VM runtime / heapnjs::Context
- Javascript context
njs::ScopedContext
- Composition of Context
and HandleScope
njs::ExecutionContext
- Javascript context constructed during executionnjs::FunctionCallContext
- Function call contextnjs::ConstructCallContext
- Constructor call contextnjs::GetPropertyContext
- Property getter contextnjs::SetPropertyContext
- Property setter contextNamespaces provided by NJS-API:
njs::Globals
- Provides constants and limitsnjs::Internal
- Private namespace used by the implementation// A struct (or class) we want to wrap.
struct Point {
double x, y;
bool operator==(const Point& other) const noexcept { return x == other.x && y == other.y; }
bool operator!=(const Point& other) const noexcept { return x == other.x && y == other.y; }
Point& translate(double tx, double ty) noexcept {
x += tx;
y += ty;
return *this;
}
static Point vectorOf(const Point& a, const Point& b) noexcept {
return Point { b.x - a.x, b.y - a.y };
}
};
// Wrapped object.
//
// This can actually be in header if you plan to share the interface
// with other objects or want to provide it for other libraries.
class PointWrap {
public:
// Adds some data into `PointWrap` that will be used and implemented
// in the next step. The last argument is signature, which should be
// unique.
NJS_BASE_CLASS(PointWrap, "Point", 0x01)
// Native data.
Point data;
// You should always provide constructors that should match JS side.
inline PointWrap() noexcept
: data {} {}
inline PointWrap(double x, double y) noexcept
: data { x, y} {}
};
// Wrapped object bindings - should be always in `.cpp` file.
NJS_BIND_CLASS(PointWrap) {
// Every function has an implicit context - use it to access stuff.
NJS_BIND_CONSTURCTOR() {
unsigned int argc = ctx.argumentsLength();
if (argc == 0) {
return ctx.returnNew<PointWrap>();
}
if (argc == 2) {
// Unpack arguments from the calling context
double x, y;
// NJS_CHECK returns error immediately if something fails.
NJS_CHECK(ctx.unpackArgument(0, x);
NJS_CHECK(ctx.unpackArgument(1, y);
return ctx.returnNew<PointWrap>(x, y);
}
return ctx.invalidArgumentsLength();
}
// Bindings methods, getters, and setters is easy. The bound method has
// already setup CallContext and can access `self` that is `PointerWrap*`.
// Unpacking the pointer to `PointWrap*` is done automatically by NJS-API.
// If you plan to bind both getters and setters of the same property they
// must be next to each other (a limitation that maybe we can relax in the
// future).
NJS_BIND_GET(x) {
return ctx.returnValue(self->data.x);
}
NJS_BIND_SET(x) {
double x;
NJS_CHECK(ctx.unpackValue(x));
self->data.x = x;
// Setters return no value, you must use njs::ResultCode.
return njs::Globals::kResultOk;
}
NJS_BIND_GET(y) {
return ctx.returnValue(self->data.y);
}
NJS_BIND_SET(y) {
double y;
NJS_CHECK(ctx.unpackValue(y));
self->data.y = y;
return njs::Globals::kResultOk;
}
// You can bind methods too...
NJS_BIND_METHOD(translate) {
double tx, ty;
NJS_CHECK(ctx.verifyArgumentsLength(2));
NJS_CHECK(ctx.unpackArgument(0, tx));
NJS_CHECK(ctx.unpackArgument(1, ty));
// Perform the operation on native data.
self->data.translate(tx, ty);
// Return `this`.
return ctx.returnValue(ctx.This());
}
// This shows how to unpack a wrapped object.
NJS_BIND_METHOD(equals) {
PointWrap* other;
NJS_CHECK(ctx.verifyArgumentsLength(1));
NJS_CHECK(ctx.unwrapArgument<PointWrap>(0, &other));
return ctx.returnValue(self->data == other->data);
}
// Static functions can be bound too.
NJS_BIND_STATIC(vectorOf) {
PointWrap* a;
PointWrap* b;
NJS_CHECK(ctx.verifyArgumentsLength(2));
NJS_CHECK(ctx.unwrapArgument<PointWrap>(0, &a));
NJS_CHECK(ctx.unwrapArgument<PointWrap>(1, &b));
// There is no reference to the class in the call context, however,
// NJS-API wrapper always adds the module into the function data field.
njs::Value PointClass = ctx.propertyOf(ctx.data(), njs::Latin1Ref("Point"));
NJS_CHECK(PointClass);
njs::Value instance = ctx.newInstance(PointClass);
NJS_CHECK(instance);
PointWrap* instObj = ctx.unwrapUnsafe<PointWrap>(instance);
instObj->data = Point::vectorOf(a->data, b->data);
return instance;
}
};
// This would create a module that is context-aware by default.
NJS_MODULE(mylib) {
// Each class must be added to `exports`.
NJS_INIT_CLASS(PointWrap, exports);
}
Write more documentation and examples.
FAQs
Nautral JavaScript Interface
We found that njs-api demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer 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
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.