Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Create dynamic objects in a nodejs6 REPL with Proxy

#Create dynamic objects in a nodejs6 REPL with Proxy

Nodejs 6.x comes with ES6 Proxy support baked in. Just like Ruby's method-missing (aka ghost methods), you can intercept getters and setters on an object and, like ActiveRecord in Rails, write rich APIs that can take any method or property name you like.

They are particularly fun in a REPL, where you might want to handle undefined variables.

For example, say we started a nodejs REPL via:

const repl = require('repl')
const evaluator = require('./evaluator')
const replServer = repl.start({ prompt: '>', eval: evaluator })

Then we could intercept get requests in the REPL by a custom evaluator.js:

const vm = require('vm')

let sandbox

module.exports = (cmd, context, filename, callback) => {
    const contextProxy = {
        get(target, name) {
            // first check nodejs globals, and return if any
            if (name in global) return global[name]
            // failing that, if the target has the named property (in this case our REPL context), return it
            else if (name in target) return target[name]
            // otherwise, do whatever you want
            else // ...

    // memoize a new vm sandbox around a Proxy wrapping the context
    sandbox = sandbox || vm.createContext(new Proxy(context, contextProxy))
    // execute the command in context, and async return
    const result = vm.runInContext(cmd, sandbox)
    callback(null, result)

This excerpt comes from my node-keyboard project.

For a deep-dive into the power of Proxy, Symbol and Reflect, check out Keith Cirkel's great series:

###Caution! Use Proxy sparingly. Accessors are much slower than on regular objects. On some benchmarks I ran, they were 100x slower than regular object getters, and 30x slower than Object constructor getters.

Try for yourself

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.