0.0.6 • Published 11 years ago

vm-shim v0.0.6

Weekly downloads
3
License
MIT
Repository
github
Last release
11 years ago

vm-shim

Build Status

This began as a wan attempt to reproduce/polyfill/infill the Node.JS vm#runIn<Some?>Context() methods in browsers. It has transformed into the present tan muscular self-assured and smiling project before you.

I'd wanted to show that shimming vm in the browser really could be done directly, partly to avoid iframes (which vm-browserify uses) to create and clone globals and contexts, and partly to side-step Node.js's contra-normative implementations of runInContext methods.

It's actually a "why didn't I think of that?" solution to problems such as -

  • why don't vm methods accept functions as arguments, not just strings?
  • why don't eval() and Function() accept functions as arguments?
  • why do eval() and Function() leak un-var'd symbols to the global scope, in browser & node.js environments?
  • how can we inspect items defined in closures?
  • how can we override (or mock) them?

methods provided (so far)

  • vm#runInContext(code, context)
  • vm#runInNewContext(code, context)
  • vm#runInThisContext(code)

not provided (yet)

  • vm#.createContext
  • vm#.createScript
  • script.runInThisContext()
  • script.runInNewContext([sandbox])

install

npm install vm-shim

git clone https://github.com/dfkaye/vm-shim.git    
 

implementation

Starting with vm.runInContext(code, context), the Function() constructor is at the core. The code param may be either a string or a function. The context param is a simple object with key-value mappings. For any key on the context, a new var for that key is prefixed to the code. The code is passed in to Function() so that the keynames can't leak outside the new function's scope.

Refactored 8 Nov 2013: a lot of little things involved - biggest is that runInThisContext now uses eval() internally, and the other two use with() inside of Function(). Who says you can't use with()?

10 Nov Having discovered that eval() leaks globals (!?!) if symbols are not var'd, all methods rely on a helper method to scrape EVERY global added by its internal eval() (or Function()) call.

10 Dec: removed use of with.

example tests

The unit tests demonstrate how runInContext and runInNewContext methods work by passing a context param containing a reference to the test's expectation object or function.

Example runInContext test passes the expect function via context argument:

it("overrides external scope vars with context attrs", function() {

  var attr = "shouldn't see this";
  
  var context = {
    attr: 'ok', 
    expect: expect  // <-- pass expect here
  };
  
  vm.runInContext(function(){
    expect(attr).toBe('ok');
    expect(attr).not.toBe('should not see this');
  }, context); 
  
});

Example runInNewContext test to verify context is returned:

it('should return context object', function () {
  var context = { name: 'test' };
  
  var result = vm.runInNewContext('', context);
  
  expect(result).toBe(context);
  expect(result.name).toBe('test');
});

Example runInThisContext test to verify accidental is not placed on global scope:

it("should not leak accidental (un-var'd) globals", function() {

  vm.runInThisContext(function(){
    accidental = 'defined';
  });
  
  expect(global.accidental).not.toBeDefined();
});

node tests

Using Misko Hevery's jasmine-node to run command line tests on node (even though this project initially aimed at a browser shim).

The package.json file defines three test script commands to run the tests via jasmine-node without the browsers:

npm test 
# => jasmine-node --verbose ./test/suite.spec.js

npm run test-vm 
# => jasmine-node --verbose ./test/vm-shim.spec.js

browser tests

Using @pivotallabs' jasmine-2.0.0 for the browser suite.

The jasmine2 browser test page is viewable on rawgit.

Using Toby Ho's MAGNIFICENT testemjs to drive tests in multiple browsers for jasmine-2.0.0 (see how to hack testem for jasmine 2), as well as jasmine-node. The testem.json file uses the standalone test page above, and also uses a custom launcher for jasmine-node (v 1.3.1).

View both test types at the console by running:

testem -l j

history

Just noting for the record:

  • Original idea emerged late at night 17 SEPT 2013
  • First implemented with rawgit approach 18 SEPT,
  • Full success including objects as properties of the context argument 19 SEPT.
  • Breaking the usual TDD procedure:
    • Started with console statements and prayer ~ removed both for real unit tests
    • Tape tests added 20 SEPT.
    • Jasmine tests/page added 20 SEPT.
  • Error, and leakage tests added 21 SEPT.
  • runInNewContext, runInThisContext methods added; runInContext refactored 4 OCT 2013
  • CoffeeScript test with jasmine-node added 6 OCT
  • tape test written in CoffeeScript test added 7 OCT
  • scope injection tests started 21 OCT
  • scope injection: spec started, tests updated, testem.json added 6 NOV 2013
  • massive refactoring 8 NOV 2013
    • certain cases were just wrong (needed 'eval()' for 'runInThisContext()', e.g.)
    • new/completed bdd specs for both vm-shim and scope mocking (temp name is 'mockScope')
  • last global leakage fixed 10 NOV
  • deleted CoffeeScript and tape tests (fun but extra work for now) 11 NOV
  • rawgit-viewable test page that also works with testem 12 NOV
  • moved mock scope stuff to metafunction project 18 NOV
0.0.6

11 years ago

0.0.5

11 years ago

0.0.4

11 years ago

0.0.3

12 years ago

0.0.2

12 years ago

0.0.1

12 years ago