npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

quarks

v0.1.2

Published

A library that exposes V8 API inside javascript code.

Downloads

18

Readme

node-quarks

Build Status Coverage Status

A library that exposes V8 API inside javascript code.

The V8 API has many useful function and object that helps V8 C++ embedder. NodeJS allow to embed C++ modules with the "require" implementation. However writing C++ code to use the V8 API is somehow too tedious. This library provide pure in-javascript access to some V8 API features. Be warned that not all features are suitable for in-javascript access. Also not all features works as expected.

Brief introduction to API

This section provides required terminology to read the API and the issues. Although exposure is wrapped in "secured" functions, so no call will fall to C++ exception and destroy the NodeJS process, there are cases that doesn't work as expected. If you are familiar with internals of V8 engine version 3.14 and newer, you can skip this section.

Object

Objects in javascript are map from key to something. There are three types of properties:

  1. Data Property
  2. Accessor Property
  3. Interceptors

Note: Interceptors are intentionally not called "properties".

Data Property

That is the usual value property, it can be any javascript value - primitive, null, undefined, object, function, etc.

Accessor Property

Properties of this type does not contain value, but has a pair of functions knows as getter and setter. The getter is called each time someone trying to get the value of that property. The setter (if exists) is called each time someone is trying to set a value to that property.

Example:

document.body.innerHTML = "<b>asd</b>";

This calls internal function of HTMLElement which does not store the string directly, but parses it and modify the DOM tree.

Object.defineProperty(MyClass.prototype, "flag", {
    "get": function() {
        return this._storage.flag;
    },
    "set": function(value) {
        this._storage.flag = !!value;
    }
});

This is one way to define accessor purely in javascript from ECMAScript5.1 version and above. Instances of MyClass will have a property flag, that when set to any value, will convert it to boolean before store it.

Interceptors

These are not really a properties, but a callback functions set on object. These callbacks are called to determine what properties the object has, when someone trying to get or set property value or even to determine if property is configurable, enumerable or read-only. These are quite useful, when determining the properties of an object are dependent on something external to the object.

There are no way to use interceptors purely in javascript. Interceptors are provided by V8 API and currently have a lot of issues.

[[Local]] and [[Prototype]]

Each object in javascript has two source of properties. The local storage of properties is known as "own properties", "local properties" and so on. We will call the storage for local properties - [[Local]]. The prototype storage of properties is known as "prototype properties", "properties on __proto__" and so on. We will call the storage for prototype properties - [[Prototype]]. The square brackets are intentional, because all function have a special property prototype, which although connected to [[Prototype]] it is not the same.

So how this storage spaces are mixed? Each time someone is trying to access a property of an object that property is searched in [[Local]]. If the property is not found in [[Local]] it is searched on [[Prototype]]. The [[Prototype]] storage however is an javascript object (the [[Local]] is not). Searching a javascript object repeat the process by looking that javascript object [[Local]] first, then its [[Prototype]]. This search completes when a property is found or when a point is reached that there is no [[Prototype]]. The Object.prototype object has null value for [[Prototype]].

Where the [[Local]] and [[Prototype]] comes from? The [[Local]] is internally created when an object is created.

var o = {};
//Now o has [[Local]] storage.

The [[Prototype]] however is the very same object that is given by prototype property of the function used to construct the object:

var literal = {};
var object = new Object();
//Now "literal" and "object" has Object.prototype for [[Prototype]].
var MyClass = function() {}
var myObject = new MyClass();
//Now "myObject" has MyClass.prototype for [[Prototype]].
//Note: If not modified, the MyClass.prototype has Object.prototype for [[Prototype]].

Because [[Local]] is checked first, the local properties could shadow the prototype properties.

var MyClass = function() {}
MyClass.prototype.foo = "bar";
var myObject = new MyClass();
myObject.foo = "baz";
console.log(myObject.foo);          //baz
console.log(MyClass.prototype.foo); //bar
//Now myObject.foo shadows the property with the same name coming from MyClass.prototype

Interceptors and local properties

Once an object has an interceptors callback set, they shadow the [[Local]]. However interceptors are API only and they could return empty handles. These are not handles to any javascript value, including undefined or null. Returning an empty handle means that "this property is not found within the interceptors". If that is the case, the search continue with [[Local]] and [[Prototype]] as described above.

Be warned that interceptors are not stored within the object, it stores only callbacks and properties are retrieved by calling the respective callback instead of searching the [[Local]] or [[Prototype]] storage. Thus this properties are not real, none of the functions of object containing Real in their name will retrieve those properties (e.g. Object::HasRealNamedProperty and etc).

Issues

  1. Callback handlers set on object cannot be called with Function.prototype.apply or Function.prototype.call. Thus using ObjectTemplate::SetCallAsFunctionHandler should be used with care. The result of template is an Object and not a Function. It means that typeof object === "object is true and quarks.Value.isFunction(object) is false.
  2. Interceptors may not work as expected. While though "normal usage" of an object interceptors are called as expected, following cases has pitfalls:
  3. The Object.getOwnPropertyDescriptor method does not call interceptors and searches the [[Local]] directly.
  4. The for...in loop calls enumerate and query interceptors, but ignore DONT_ENUM property attribute.
  5. The Object.keys method calls only enumerate interceptor and thus ignore DONT_ENUM property attribute.
  6. The Object.defineProperty method doesn't call any interceptors and set attribute to [[Local]] directly.
  7. The quarks.Object.setAccessor and quarks.ObjectTemplate.prototype.setAccessor calls Object::SetAccessor and ObjectTemplate::SetAccessor respectively. Because those methods are exposed to call C++ functions and not javascript functions, Object.getOwnPropertyDescriptor will not retrieve the callbacks given. Instead the descriptor will contain a value property which will be the value returned by the getter.