Your browser doesn't support the features required by impress.js, so you are presented with a simplified version of this presentation.

For the best experience please use the latest Chrome, Safari or Firefox browser.

JavaScript in JavaScript (js.js)

Sandboxing Third-Party Scripts

Jeff Terrace, Stephen R. Beard, and Naga Praveen Kumar Katta

Princeton University

Third-party Scripts

Hello, World!

Third-party Scripts

Hello, World!

Scripts Included

  • https://connect.facebook.net/en_US/all.js

Third-party Scripts

Hello, World!

Scripts Included

  • https://connect.facebook.net/en_US/all.js
  • https://apis.google.com/js/plusone.js

Third-party Scripts

Hello, World!

Scripts Included

  • https://connect.facebook.net/en_US/all.js
  • https://apis.google.com/js/plusone.js
  • https://platform.twitter.com/widgets.js

Third-party Scripts

Hello, World!


Scripts Included

  • https://connect.facebook.net/en_US/all.js
  • https://apis.google.com/js/plusone.js
  • https://platform.twitter.com/widgets.js
  • http://code.jquery.com/jquery-1.7.2.min.js

Third-party Scripts

Hello, World!


Scripts Included

  • https://connect.facebook.net/en_US/all.js
  • https://apis.google.com/js/plusone.js
  • https://platform.twitter.com/widgets.js
  • http://code.jquery.com/jquery-1.7.2.min.js

Goals

  1. Fine-grained access control
  2. Full JavaScript support
    • Including eval and with.
  3. Browser Compatibility
    • All major browsers without plugins or modifications
  4. Resilient to attacks
    • Spin loops, memory exhaustion, page redirection, DOM modifications

Existing Solutions

js.js

Emscripten

IsLeapYear C++

static inline bool
IsLeapYear(jsint year)
{
    return year % 4 == 0 &&
           (year % 100 || (year % 400 == 0));
}

IsLeapYear LLVM

define internal fastcc zeroext i1 @_ZL10IsLeapYeari(i32 %year) nounwind readnone inlinehint {
entry:
  %rem3 = and i32 %year, 3, !dbg !804097
  %cmp = icmp eq i32 %rem3, 0, !dbg !804097
  br i1 %cmp, label %land.rhs, label %land.end, !dbg !804097
land.rhs:
  %rem1 = srem i32 %year, 100, !dbg !804097
  %tobool = icmp eq i32 %rem1, 0, !dbg !804097
  br i1 %tobool, label %lor.rhs, label %land.end, !dbg !804097
lor.rhs:
  %rem2 = srem i32 %year, 400, !dbg !804097
  %cmp3 = icmp eq i32 %rem2, 0, !dbg !804097
  br label %land.end, !dbg !804097
land.end:
  %0 = phi i1 [ false, %entry ], [ true, %land.rhs ],
              [ %cmp3, %lor.rhs ]
  ret i1 %0, !dbg !804099
}

IsLeapYear JavaScript

function __ZL10IsLeapYeari($year) {
  var $cmp = ($year & 3 | 0) == 0;
  do {
    if ($cmp) {
      if (($year % 100 | 0) != 0) {
        var $0 = 1;
        break;
      }
      var $0 = ($year % 400 | 0) == 0;
    } else {
      var $0 = 0;
    }
  } while (0);
  var $0;
  return $0;
  return null;
}

IsLeapYear JavaScript

function __ZL10IsLeapYeari(a) {
  return 0 == (a & 3 | 0) ? 0 != (a % 100 | 0) ?
              1 : 0 == (a % 400 | 0) : 0
}

IsLeapYear JavaScript

function __ZL10IsLeapYeari(a) {
  return 0 == (a & 3 | 0) ? 0 != (a % 100 | 0) ?
              1 : 0 == (a % 400 | 0) : 0
}
static inline bool
IsLeapYear(jsint year)
{
    return year % 4 == 0 &&
           (year % 100 || (year % 400 == 0));
}

Creating js.js

js.js Demo - 1+1

var jsObjs = JSJS.Init();

var compiledObj = JSJS.CompileScript(
                     jsObjs.cx, jsObjs.glob, "1 + 1");

var rval = JSJS.ExecuteScript(
                 jsObjs.cx, jsObjs.glob, compiledObj);

var d = JSJS.ValueToNumber(jsObjs.cx, rval);
console.log(d);

js.js Demo - communication

function nativeAdd(d1, d2) {
  return d1 + d2;
}
var wrappedNativeFunc = JSJS.wrapFunction({
  func: nativeAdd,
  args: [JSJS.Types['double'], JSJS.Types['double']],
  returns: JSJS.Types['double']});

JSJS.DefineFunction(jsObjs.cx, jsObjs.glob,
            "nativeAdd", wrappedNativeFunc, 2, 0);

var rval = JSJS.EvaluateScript(jsObjs.cx, jsObjs.glob,
                   "nativeAdd(17, 2.4);");

js.js Demo - Fibonacci

function fibonacci(n) {
  if (n==0 || n==1) {
    return n;
  }
  var prev2 = 0, prev1 = 1, fib = 1, i;
  for (i=2; i<=n; i++) {
    fib = prev1 + prev2;
    prev2 = prev1;
    prev1 = fib;
  }
  return fib;
}

js.js Demo - Twitter Button

http://platform.twitter.com/widgets.js

47KB of complicated, closure-compiled JavaScript.

Sunspider Benchmark

Sunspider Benchmark

Microbenchmark

Operation Mean Execution Time (ms)
libjs.min.js load 84.9
NewRuntime 25.2
NewContext 35.8
GlobalClassInit 15.5
StandardClassesInit 60.1
Execute 1+1 70.6
DestroyContext 33.3
DestroyRuntime 1.8

js.js

Papertinyurl.com/js-js-paper
Blog Posttinyurl.com/js-js-blog-post
Sourcegithub.com/jterrace/js.js
Demosjterrace.github.com/js.js
Twitter@jterrace

Thanks! Questions?