noderJS API

This page details the public API exposed by noderJS.

Module variables

Inside a module loaded with noderJS, the following variables are automatically available. They are compatible with the corresponding variables available from a module loaded in Node.js:

noder global variable

noderJS creates a global variable called noder (its name is configurable). This variable corresponds to the root module that is automatically created by noderJS. All the properties usually available on the module variable in a module (and listed in the previous section) are also available on the noder global variable. Moreover, the following shortcuts are also available for convenience (most of them are documented later in this page):

  • noder.asyncRequire = noder.require("noder-js/asyncRequire")
  • noder.define = noder.require("noder-js/currentContext").define
  • noder.execute = noder.require("noder-js/currentContext").jsModuleExecute
  • noder.createContext = noder.require("noder-js/context").createContext
  • noder.updatePackagesMap: the map provided as a parameter will be recursively merged with the existing one (it is normally provided in the configuration). This method can be useful when you want noder to be able to load modules from packages. For more information on packaging, see here.

The noder global variable is especially intended to be used from any JavaScript code in the page that is not loaded through noderJS (and thus does not have access to its own module and require variables). Unless there is a good reason, it should not be used inside a module loaded through noderJS, as, for better compatibility with CommonJS standards, it is better to use the local module and require variables.

Note that the noder global variable is especially useful for debugging: you can inspect the noderJS cache and access all modules through noder.require.cache.

Asynchronous module loading

Usage

In addition to the basic synchronous standard version of require (which is equivalent to a static dependency), noderJS provides a promises-based asyncRequire method to load a module asynchronously:

asyncRequire (modulePath1, modulePath2...) : Promise

asyncRequire accepts any number of module paths as parameters and returns a promise giving access to the array of the exports objects of all requested modules.

It can be used in the following way:

var asyncRequire = require('noder-js/asyncRequire');

// asyncRequire preloads and executes the modules given as parameters and returns a promise.
// As the promise result is an array, it is possible to use "spread" to get each array item
// as a different argument of the given handler function:
asyncRequire("myFirstModule", "mySecondModule").spread(function (myFirstModule, mySecondModule){
    // Do something with myFirstModule and mySecondModule
}, function (error) {
    // Do something in case of failure
});

Relative paths

If you want to use relative paths in asyncRequire (i.e. paths which are relative to the current module, in the same way as it is possible with the synchronous require), you can either convert them to absolute paths with require.resolve or you can create a local version of the asyncRequire method, as shown in the following two equivalent examples:

var asyncRequire = require('noder-js/asyncRequire');

// Use require.resolve to convert the relative path into an absolute path:
asyncRequire(require.resolve("./myRelativeModule")).spread(function (myRelativeModule) { /* ... */ });
// Use the create method to create a local version of the asyncRequire method which accepts relative paths:
var asyncRequire = require('noder-js/asyncRequire').create(module);

// Then relative paths can be used directly:
asyncRequire("./myRelativeModule").spread(function (myRelativeModule) { /* ... */ });

Shortcut

For convenience, the asyncRequire method is also available on the noder global variable, so that it is easy to load some modules asynchronously, even from code which was not loaded through noderJS:

noder.asyncRequire("myModule").spread(function (myModule){ /* ... */ }, function (error) { /* ... */ });

Loader plugins

Before a module can be executed in noderJS, it has to be preloaded. The preload process consists in downloading the module file, parsing it to detect its static dependencies, and preloading those dependencies. The preload process is usually asynchronous, as it usually involves one or more XHR requests (which, by default, are configured to be asynchronous).

noderJS provides the ability to add custom actions to the preload process, by implementing a loader plugin. This is especially useful to preload additional dependencies which cannot be automatically detected because they are not static. These include, for example, language-dependent resources or browser-dependent code.

For example, let's consider our sample.js module which depends on a language-dependent resource. The code could look like the following example:

var language = require("resourcesManager").language;
var myResources = require("./myRes_"+language);
// ...

When parsing this file, noderJS will find resourcesManager as a static dependency, but will be unable know the other file to preload as it depends on the language variable, whose value is unknown at the time the file is parsed (as it is not executed yet). As a result, when later executing this file, the second require will probably fail because the dependency will not have been preloaded and it will most likely not be possible to preload it synchronously (if XHR requests are configured to be asynchronous).

To solve this kind of issues, or to execute any other custom actions asynchronously, support for loader plugins was implemented. The parser detects the pattern require("loaderPluginPath/$loaderPluginName").methodName(arg1, arg2...) in the file to be preloaded, and executes the loader plugin module at preloading time. It calls the $preload method on the methodName property of the object exported by the loader plugin and executes it with the parsed arguments (which must be either string literals or the special __dirname, __filename and module variable, or null). The $preload method can return a promise. If it is the case, the preload process will wait for the promise to be fulfilled before marking the module as preloaded.

Now our sample.js module depending on a language-dependent resource can be re-written in the following way:

var myResources = require("$resourcesLoader").getResource(__dirname, "./myRes");
// ...

The loader plugin, called $resourcesLoader.js could look like this:

var asyncRequire = require("noder-js/asyncRequire");
var language = require("resourcesManager").language;
exports.getResource = function(directory, resource) {
   // this method is executed when sample.js is executed
   // it is synchronous
   return require(directory + "/" + resource);
};
exports.getResource.$preload = function(directory, resource) {
   // this method is automatically executed when sample.js is preloaded
   // it can be asynchronous by returning a promise
   return asyncRequire(directory + "/" + resource);
};

Promises library

Promises/A+ logo

noderJS heavily relies on promises. It includes a lightweight promise library which is compliant with the Promises/A+ specifications version 1.1.1.

The integrated promise library can be accessed with:

var Promise = require("noder-js/promise");

Promise constructor

new Promise (factoryFunction : function(resolve, reject)) : Promise

Creates a new promise. The given factoryFunction gets a reference to the resolve and reject methods which allow to resolve or reject the promise. If the factoryFunction raises an exception before calling resolve or reject, the promise is rejected with the exception as the reason.

Here is a sample implementing a promise-based version of setTimeout:

var Promise = require("noder-js/promise");

var setTimeoutWithPromise = function (delay) {
   return new Promise(function(resolve, reject) {
      setTimeout(function() {
         resolve(7);
      }, delay);
   });
};

console.log("Before calling setTimeoutWithPromise");
setTimeoutWithPromise(1000).then(function (result) {
   console.log("In the callback. The result is: " + result)
});
console.log("After calling setTimeoutWithPromise");

// The console should contain:
// Before calling setTimeoutWithPromise
// After calling setTimeoutWithPromise
// In the callback. The result is: 7

Using the Promise constructor is the recommended way to create a promise. Alternatively, it is also possible to use the Promise.defer method below.

Promise.defer()

Promise.defer () : Defer

Creates a new defer. A defer is an object with 3 properties:

{
   promise: promise, /* Promise instance object (with the 'then' method) */
   resolve: resolve, /* Function to resolve the promise, with the specified value. */
   reject: reject /* Function to reject the promise, with the specified reason. */
}

Here is a sample re-implementing the setTimeoutWithPromise function from the previous section, but using Promise.defer() instead of the promise constructor.

var Promise = require("noder-js/promise");

var setTimeoutWithPromise = function (delay) {
   var defer = Promise.defer();
   setTimeout(function() {
      defer.resolve(7);
   }, delay);
   return defer.promise;
};

Promise.resolve()

Promise.resolve(valueOrPromise) : Promise

If valueOrPromise is a noder-js promise, Promise.resolve returns it directly.

If valueOrPromise is an object or a function with a thenSync or then method, it is considered as a promise and Promise.resolve returns an equivalent noderJS promise.

Otherwise, Promise.resolve returns an already fulfilled promise, whose fulfillment value is valueOrPromise.

var Promise = require("noder-js/promise");

var promiseInstance = Promise.resolve(7);
promiseInstance.then(function (value) { /* here, value == 7 */ });
Promise.resolve(promiseInstance) // this call returns promiseInstance
Promise.resolve({
   then: function (resolve, reject) {
      resolve(7);
   }
}).then(function(value) { /* here, value == 7 */ });

Promise.reject()

Promise.reject(reason) : Promise

Promise.reject returns a rejected promise with the given reason.

var Promise = require("noder-js/promise");

Promise.reject("error").catch(function (reason) { /* here, reason == "error" */ });

Promise.done

Promise.done : Promise

Promise.done is a reference to an already resolved promise, whose fulfillment value is undefined.

It is defined by:

Promise.done = Promise.resolve();

It can be used instead of Promise.resolve(undefined) to avoid creating a new promise instance.

Promise.all() and Promise.allSettled()

Promise.all (promiseOrValueArray : Array) : Promise

Promise.allSettled (promiseOrValueArray : Array) : Promise

Promise.all and Promise.allSettled return a promise that is fulfilled when all the given promises are fulfilled.

Promise.all is the fail-fast version of Promise.allSettled:

  • the promise returned by Promise.allSettled is rejected only when all promises are either fulfilled or rejected.
  • the promise returned by Promise.all is rejected as soon as any promise is rejected, without waiting for other promises to either be fulfilled or rejected.

Apart from that timing difference, Promise.all and Promise.allSettled are otherwise fully equivalent.

Here is an example showing how to use Promise.all:

var Promise = require("noder-js/promise");
var asyncRequire = require("noder-js/asyncRequire");

Promise.all(["simple value", asyncRequire("myModule1", "myModule2")]).spread(function (simpleValue, myModules) {
   // here:
   // simpleValue == "simple value"
   // myModules is an array containing the exports objects of myModule1 and myModule2
}, function (error) {
   // this function is called in case there is an error while loading myModule1 or myModule2
});

promiseInstance.then() and its shortcuts

promiseInstance.then(onFulfilled : function (value), onRejected : function (reason)) : Promise

promiseInstance.then adds a fulfillment and a rejection handler to the promise, and returns a new promise resolving to the return value of the called handler.

If onFulfilled is null (or not a function), and promiseInstance is fulfilled, the returned promise is fulfilled with the same fulfillment value.

If onRejected is null (or not a function), and promiseInstance is rejected, the returned promise is rejected with the same reason.

If both onFulfilled and onRejected are null (or not functions), promiseInstance itself is returned.

The following shortcuts for promiseInstance.then are available:

promiseInstance.catch(onRejected : function (reason)) : Promise

promiseInstance.catch(onRejected);
// is equivalent to:
promiseInstance.then(null, onRejected);

promiseInstance.finally(handler : function (value)) : Promise

promiseInstance.finally(handler);
// is equivalent to:
promiseInstance.then(handler, handler);

promiseInstance.spread(onFulfilled : function (value1, value2 ...), onRejected : function (reason)) : Promise

promiseInstance.spread can be used when the fulfillment value is expected to be an array.

promiseInstance.spread(onFulfilled, onRejected);
// is equivalent to:
promiseInstance.then(function(array) {
  // each item of the array is passed as a different argument to onFulfilled:
  return onFulfilled.apply(null, array);
}, onRejected);

promiseInstance.done(onFulfilled : function (value), onRejected : function (reason))

The done method is equivalent to then except that it does not return a new promise, and it reports any error by throwing it asynchronously. It is often used without any argument to end a promises chain so that any unhandled error in the chain is properly reported instead of being silently ignored.

For example, with the folling code, if an error occurs when loading myModule, or in the function which uses myModule, the error is silently ignored:

var asyncRequire = require("noder-js/asyncRequire");

asyncRequire("myModule").spread(function (myModule) {
  // do something with myModule
}); // without .done(), errors in this promises chain are silently ignored

Adding .done() at the end of the promises chain makes sure any unhandled error happening in the promises chain is properly reported:

var asyncRequire = require("noder-js/asyncRequire");

asyncRequire("myModule").spread(function (myModule) {
  // do something with myModule
}).done(); // with .done(), errors are properly reported

promiseInstance.thenSync() and its shortcuts

Following the Promises/A+ specifications, the promiseInstance.then method never calls its handlers synchronously. The same applies to the associated spread, catch, finally and done shortcuts.

However, in some cases, it can be useful to avoid code duplication by handling both the asynchronous and the synchronous cases with the same code. For example, noderJS itself can be configured to use either synchronous or asynchronous XHR requests and uses the same code to handle both cases, without adding asynchronism uselessly.

For this to be possible, noderJS provides the thenSync, spreadSync, catchSync, finallySync and doneSync methods which behave exactly as their then, spread, catch, finally and done counterparts, except that, in case the promise is already fulfilled or rejected at the time the xSync method is called, the corresponding handler is called synchronously.

Here is an example which shows the difference between then and thenSync:

var thenValue, thenSyncValue;
var Promise = require("noder-js/promise");
var myPromise = Promise.resolve(7);

// myPromise is already fulfilled
myPromise.then(function (value) { thenValue = value; });
myPromise.thenSync(function (value) { thenSyncValue = value; });
console.log("thenValue = " + thenValue);
console.log("thenSyncValue = " + thenSyncValue);

// The result in the console is:
// thenValue = undefined
// thenSyncValue = 7

Note that the behavior of thenSync only differs from the one of then if it is called on an already fulfilled or rejected promise. In the following sample, both then and thenSync behave in the same way because the promise is still pending when then and thenSync are called:

var thenValue, thenSyncValue;
var Promise = require("noder-js/promise");
var defer = Promise.defer();
var myPromise = defer.promise;

// myPromise is not yet fulfilled
myPromise.then(function (value) { thenValue = value; });
myPromise.thenSync(function (value) { thenSyncValue = value; });

defer.resolve(7); // now it is fulfilled, but the handlers will be called asynchronously
console.log("thenValue = " + thenValue);
console.log("thenSyncValue = " + thenSyncValue);

// The result in the console is:
// thenValue = undefined
// thenSyncValue = undefined

Note that thenSync is not (yet?) standard. There was a request to better integrate Promises/A+ specifications with synchronous code, but it was unfortunately rejected.

promiseInstance.isFulfilled() and promiseInstance.isRejected()

promiseInstance.isFulfilled() : Boolean

Returns true if promiseInstance is fulfilled, and false otherwise.

promiseInstance.isRejected() : Boolean

Returns true if promiseInstance is rejected, and false otherwise.

If both promiseInstance.isFulfilled() and promiseInstance.isRejected() return false, the promise is still pending. promiseInstance.isFulfilled() and promiseInstance.isRejected() never both return true for the same promise instance.

var Promise = require("noder-js/promise");
Promise.resolve(7).isFulfilled() // returns true
Promise.resolve(7).isRejected() // returns false
Promise.reject(7).isFulfilled() // returns false
Promise.reject(7).isRejected() // returns true
Promise.defer().promise.isFulfilled() // returns false
Promise.defer().promise.isRejected() // returns false

promiseInstance.result()

promiseInstance.result()

If promiseInstance is fulfilled, promiseInstance.result() returns the fulfillment value.

If promiseInstance is rejected, promiseInstance.result() returns the rejection reason.

Otherwise (i.e. promiseInstance is still pending), promiseInstance.result() returns undefined.

var Promise = require("noder-js/promise");
Promise.resolve(7).result() // returns 7
Promise.reject(7).result() // returns 7
Promise.defer().promise.result() // returns undefined

Request utility

noderJS contains a small promises-based utility to make network requests:

var request = require("noder-js/request");

It is a simple wrapper around XMLHttpRequest that hides some of the differences between browsers and makes it easy to request files.

request (url: String, options: Object) : Promise

This method sends a request to the server for the specified url and returns a promise.

The options object is optional. Here is the list of accepted options:

options : {
   headers : {
      // Headers to be included in the request, for example:
      "Content-Type": "text/plain"
   },
   data : "My Request is...", // String - Body of the request
   sync : false, // Boolean - Specifies if the request is synchronous or not (default: false)
   method : "POST" // String - Type of request (default: "GET")
}

Here is an example, which posts a json object to the server, and parses the response as json:

var request = require("noder-js/request");

request("/api/", {
   method: "POST",
   headers: {
     "Content-Type": "application/json"
   },
   data: JSON.stringify(myJsonObjectToSend)
}).then(function (xhr) {
   // Success callback
   // Parses the response as JSON:
   var responseText = xhr.responseText;
   var responseJson = JSON.parse(responseText);
   // ...
}).catch(function(error) {
   // error callback handling cases when either the request fails or parsing the response JSON fails
   // ...
});

Context

A noderJS context is automatically created when noderJS is loaded. noderJS also provides an API to create new contexts. Each noderJS context has its own configuration and its own cache of modules.

Inside the same context, when the same module is required twice, the corresponding module is in fact loaded only once and the reference is shared.

However, if the same module is required from two different contexts, two different instances of the module will be loaded and will be independent from one another.

It can be useful to create a new context when testing a module. The tested module can be put in a mocked environment by exposing mocks in the new context, so that the tested module will access mocks instead of the original modules when calling the usual require method.

Getting a context instance

New context

Here is how to create a new context:

var Context = require("noder-js/context");
var contextInstance = new Context({
   /* context configuration */
});

The context configuration object is described in the configuration page.

It is also possible to create a new context with the createContext method, which returns the root module of the new context:

var Context = require("noder-js/context");
var contextRootModule = Context.createContext({
   /* context configuration */
});

Current context

Here is how to get a reference to the current context:

var contextInstance = require("noder-js/currentContext");

Context instance methods

Context instance methods whose name start with module expect a module object as their first argument. Module objects are stored in the cache (accessible from require.cache and contextInstance.cache). They can also be retrieved with the contextInstance.getModule method, and, inside a module, the module variable refers to the current module object.

contextInstance.getModule(moduleFilename: String) : Module

If the moduleFilename argument is provided, this function retrieves the corresponding module object from the cache and returns it. If the module object for this file name does not exist yet in the cache, it is created and stored in the cache. Note that the moduleFilename argument must exactly correspond to the filename property of the desired module object (which is the full path of the module, including the extension, as returned by the require.resolve method).

If moduleFilename is not provided, a new anonymous module is returned. Anonymous modules are not stored in the cache.

var myModule = contextInstance.getModule(module.filename);
// here: myModule === module (if the context of module is contextInstance)

contextInstance.modulePreload(module: Module, parent: Module) : Promise

Preloads the given module, if it is not already preloaded. Preloading a module means loading its definition and preloading its static dependencies.

The parent argument should usually not be defined when calling modulePreload. It is used internally for recursive calls, to detect circular dependencies. In case a circular dependency is detected, modulePreload returns an already resolved promise even if the module is not fully preloaded yet.

The fulfillment value of the returned promise is undefined, unless the promise is rejected with an error.

contextInstance.moduleLoadDefinition(module: Module) : Promise

Requests and loads the definition of the given module from the server, if it is not already loaded.

The fulfillment value of the returned promise is undefined, unless the promise is rejected with an error.

contextInstance.moduleResolve(module: Module, dependency: String) : String

Resolves the given dependency as if it was used in the given module, and returns the resulting path. Especially, if the dependency is expressed as a relative path, or without any extension, this function returns the corresponding absolute path, including the extension.

Note that the resolver can be configured to redirect some paths to other locations. You can check the resolver part of the configuration.

contextInstance.moduleResolve(myModuleFromContextInstance, myDependency); // is equivalent to:
myModuleFromContextInstance.require.resolve(myDependency);

contextInstance.moduleResolve(contextInstance.getModule("a/b/c.js"), "../f"); // returns "a/f.js"
contextInstance.moduleResolve(contextInstance.getModule("d/e/f.js"), "../f"); // returns "d/f.js"

contextInstance.moduleProcessPlugin(module: Module, pluginDef: Object) : Promise

Executes the $preload method of the given plugin for the given module.

The structure of the pluginDef object corresponds to the one which can be found in the array returned by the findRequires parser when it is given a truthy detectLoaderPlugins argument.

pluginDef is an object with the module (string), method (string) and args (array) properties. Each item in the args properties is either a string (corresponding to a string literal argument), or an array with a single string element (corresponding to a non-quoted argument like module or null).

This method resolves the pluginDef.module module (in the context of module) and executes it. It then looks for a method with the given name on its exports object, and accesses its $preload property. If this is a function, it is called with the given arguments.

//The following line does the equivalent of: module.require("$loaderPlugin").myMethod.$preload("arg1", module)
contextInstance.moduleProcessPlugin(module, {
   module: "$loaderPlugin",
   method: "myMethod",
   args: ["arg1", ["module"]]
});

contextInstance.modulePreloadDependencies(module: Module, dependencies: Array) : Promise

Preloads the given dependencies of the given module. Each item in the dependencies array can be either a string (in which case the corresponding dependency is resolved and preloaded) or a plugin definition object (in which case the plugin is precessed with moduleProcessPlugin).

contextInstance.moduleExecuteSync(module: Module) : Object

Executes the given module if it was not executed yet and returns its exports object.

For this function to succeed, the given module has to be already preloaded, or to be preloadable synchronously. If it is not the case, an exception is thrown.

contextInstance.moduleExecute(module: Module) : Promise

Preloads and executes the given module if it was not executed yet. The fulfillment value of the returned promise is the exports object of the module.

contextInstance.moduleAsyncRequire(module: Module, dependencies: Array) : Promise

Preloads and executes all the given dependencies. The fulfillment value of the returned promise is the array of the exports object of each dependency.

contextInstance.moduleAsyncRequire(getModule("a/b/c.js"), ["./d", "a/e.js"]).spread(function (d, e) {
   // here, d and e refer to the exports objects of ./d and a/e.js
});

contextInstance.moduleRequire(module: Module, dependency: String) : Object

Resolves and executes the given dependency of the module. The dependency has to be already preloaded or to be preloadable synchronously. If it is not the case, an exception is thrown.

contextInstance.moduleDefine(module: Module, dependencies: Array, body: Function) : Module

Sets the dependencies and the definition function of the given module, if the module was not already defined. This method returns its first parameter.

contextInstance.define(contextInstance.getModule("a/b/c.js"), [], function(module, global) {
   module.exports = {
      hello: function () {
         alert("Hello World!");
      }
   };
});

contextInstance.define(moduleFilename: String, dependencies: Array, body: Function)

Defines the moduleFilename module, if it was not already defined. It is a shortcut for: contextInstance.moduleDefine(contextInstance.getModule(moduleFilename), dependencies, body). Note that, unlike moduleDefine, this method does not return anything.

For convenience, this method is also available on the noder variable (and, more generally, on the root module of any context). It is also the method called to define modules from a package.

noder.define("a/b/c.js", [], function(module, global) {
   module.exports = {
      hello: function () {
         alert("Hello World!");
      }
   };
});
noder.define("a/b/d.js", ["./c"], function(module, global) {
   var require = module.require;
   module.exports = require("./c").hello;
});

contextInstance.jsModuleEval(jsCode: String, url: String) : Function

Wraps jsCode in a module definition function, evaluates the resulting code and returns the corresponding function. Note that the content of jsCode itself is not executed until the returned function is called.

If provided, the given url is used in a sourceURL comment (to give a name to the evaluated code, for compatible debuggers).

// creates a module definition function from a simple module source code:
var moduleDefinition = contextInstance.jsModuleEval("module.exports = { hello: function() { alert('Hello World!'); }};");
// defines it as the body of a module with no dependency:
var myModule = contextInstance.moduleDefine(contextInstance.getModule("a/b/c.js"), [], moduleDefinition);
// executes the module synchronously:
var myModuleExports = contextInstance.moduleExecuteSync(myModule);
myModuleExports.hello();

contextInstance.jsModuleDefine(jsCode: String, moduleFilename: String, url: String)

Defines jsCode as the JavaScript code of the moduleFilename module (if the module was not already defined).

The given url is used in the sourceURL comment (to give a name to the evaluated code, for compatible debuggers). If no url is provided, moduleFilename is used as the url.

Returns the module object corresponding to the module.

// defines a simple module:
var myModule = contextInstance.jsModuleDefine("module.exports = { hello: function() { alert('Hello World!'); }};", "a/b/c.js");
// then executes it synchronously:
var myModuleExports = contextInstance.moduleExecuteSync(myModule);
myModuleExports.hello();

contextInstance.jsModuleExecute(jsCode: String, moduleFilename: String, url: String) : Promise

Defines jsCode as the JavaScript code of the moduleFilename module (if the module was not already defined), preloads its dependencies and executes it (if it was not already executed).

The given url is used in the sourceURL comment (to give a name to the evaluated code, for compatible debuggers). If no url is provided, moduleFilename is used as the url.

The fulfillment value of the returned promise is the exports object of the module.

For convenience, this method is also available as the execute method on the noder variable (and, more generally, on the root module of any context).

// defines and executes a simple module:
contextInstance.jsModuleExecute("module.exports = { hello: function() { alert('Hello World!'); }};", "a/b/c.js").then(function(myModuleExports){
    myModuleExports.hello();
});

contextInstance.execModuleCall(modulePath: String) : Promise

Preloads and executes the module at the given path. The path is resolved from the root module. The fulfillment value of the returned promise is the exports object of the module.

contextInstance.expose(path: String, object: Object)

Exposes the given object at the given path in the contextInstance context. This means that, the next time a module with that path has to be loaded in the context, the usual loading method will be bypassed and the given object will be used as the export object.

Note that this method does not unload any already loaded module at the given path. If a module with the given path is already loaded when this method is called, it is still accessible until it is deleted from the cache.

For example:

var myObject = {};
contextInstance.expose("myModule.js", myObject);

var myModule = contextInstance.require("myModule");
delete contextInstance.require.cache["myModule.js"];
var myReloadedModule = contextInstance.require("myModule");

// Here, we always have:
// myObject === myReloadedModule

// We can also have:
// myObject === myModule
// but only if myModule.js was not loaded before the call to the expose method.

Note that there is a static version of this method which exposes the given object at the given path for all contexts (both already created and created later). If both the static and the instance versions of this method are called for the same path, the object passed to the instance version of the expose function will be used rather than the object passed to the static version of expose (the most specific call wins).

Context instance properties

contextInstance.config

A reference to the configuration of the context.

contextInstance.cache

A map of cached modules. It is the same object as the one available in require.cache from modules loaded from this context. The key in the map is the the full path of the module, including the extension, as returned by the require.resolve method and corresponding to the filename property on the module object. The value is the corresponding module object.

contextInstance.rootModule

A special module created when the context is created.

contextInstance.builtinModules

An object containing all built-in modules (also including modules exposed through the expose method).

contextInstance.resolver

Reference to the resolver.

contextInstance.loader

Reference to the loader.

Context static methods

Context.createContext(config)

Creates a new context and returns its rootModule.

var myRootModule = new Context(myConfig).rootModule;

// is equivalent to:

var myRootModule = Context.createContext(myConfig);

Context.expose(name, exports)

Exposes the given object at the given path for all contexts (both already created and created later). See contextInstance.expose for more information.

asyncCall

noder-js exposes an asyncCall module with some utility functions to call functions asynchronously or synchronously.

var asyncCall = require("noder-js/asyncCall");

asyncCall.nextTick(f : function())

Registers a function to be executed asynchronously. The function is called with no scope and no argument. Functions are executed in the same order as they are registered.

The implementation of this function in the browser version of noderJS relies on setTimeout. To improve performance, multiple consecutive calls to asyncCall.nextTick in the same event loop turn lead to at most one call to setTimeout. Calling async.nextTick from a function called with asyncCall.nextTick simply adds the new function to the list of functions to be executed, without any call to setTimeout, and the function is executed at the end of the same event loop turn.

var asyncCall = require("noder-js/asyncCall");
var myCounter = 0;
asyncCall.nextTick(function () {
  myCounter++;
  console.log("First function: " + myCounter);
});
asyncCall.nextTick(function () {
  myCounter++;
  console.log("Second function: " + myCounter);
});
console.log("Main: " + myCounter);

// The console will have the following output:
// Main: 0
// First function: 1
// Second function: 2

asyncCall.syncCall(f : function())

Executes the given function synchronously. In case an error happens in the callback, it is thrown again asynchronously, so that the caller of asyncCall.syncCall is not affected.

This function has the same signature as asyncCall.nextTick. This way, it is possible to parameterize an algorithm with a reference to a callback executor, which can be set to be either asyncCall.nextTick to call callbacks asynchronously, or asyncCall.syncCall to call callbacks synchronously. This is done internally for the implementation of the then and thenSync promise methods.

asyncCall.nextTickCalls(arrayOfFunctions : Array)

Registers an array of functions to be executed later asynchronously. The functions are called in the order in which they appear in the array.

Note that this function modifies the array: the first item of the array is removed, then the corresponding function is executed, then the new first item of the array is removed, ... until there is no remaining item in the array. Also note that, if the array is changed outside of asyncCall.nextTickCalls before the execution of all array items is finished, it has an impact on the functions which are actually executed.

asyncCall.syncCalls(arrayOfFunctions : Array)

Synchronous version of asyncCall.nextTickCalls. Executes each function in the array, in order, synchronously.

asyncCall.syncTick()

Executes synchronously all the functions currently planned to be executed asynchronously (and registered with asyncCall.nextTick). Note that this method should never be called from application code. However, it can be useful to use it from tests to execute asynchronous code synchronously and improve performance for tests execution.

var asyncCall = require("noder-js/asyncCall");
var methodCalled = false;
asyncCall.nextTick(function () {
   methodCalled = true;
});
// here, methodCalled = false
asyncCall.syncTick(); // this calls ALL the functions previously registered with asyncCall.nextTick and not yet executed
// here, methodCalled = true

findRequires parser

noderJS includes a small parser for JavaScript code which extracts calls to the require method. It is exposed as noder-js/findRequires:

var findRequires = require("noder-js/findRequires");

findRequires(jsCode : String, detectLoaderPlugins : Boolean)

  • jsCode: JavaScript code to be parsed.
  • detectLoaderPlugins: whether to return information about loader plugins.

findRequires returns an array. Each item in the array can be:

  • a string, which is the string literal used in a call to require.
  • (only if detectLoaderPlugins is true) an object with the module (string), method (string) and args (array) properties, corresponding to a call to a loader plugin. Note that for each loader plugin detected, a string entry is also present in the array in addition to the object. Each item in the args properties is either a string (corresponding to a string literal argument), or an array with a single string element (corresponding to a non-quoted argument like module or null).

Each string corresponds to a call to require in the source code.

var findRequires = require("noder-js/findRequires");

findRequires("var myModule = require('myModule')"); // returns ["myModule"]
findRequires("var myModule = require( /* comment1 */ 'myModule' /* 'comment2' */ )"); // returns ["myModule"]

// The following 3 calls all return [] (an empty array)
findRequires("var myModule = require('my' + 'Module')"); // expressions are not included
findRequires("var myModule = module.require('myModule')"); // calls to module.require are not included
findRequires("var myString = \"require('myModule')\""); // the content of string literals is not included

// Loader plugins:
findRequires("require('$loaderPlugin').myMethod('arg1', module)"); // returns ['$loaderPlugin']
findRequires("require('$loaderPlugin').myMethod('arg1', module)", true);
// The previous line returns:
[ '$loaderPlugin',
  { module: '$loaderPlugin',
    method: 'myMethod',
    args: [ 'arg1', ["module"] ] } ]