Index: frontend/node_modules/harmony-reflect/README.md
===================================================================
--- frontend/node_modules/harmony-reflect/README.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/harmony-reflect/README.md	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,170 @@
+[![NPM version](https://badge.fury.io/js/harmony-reflect.svg)](http://badge.fury.io/js/harmony-reflect) [![Dependencies](https://david-dm.org/tvcutsem/harmony-reflect.png)](https://david-dm.org/tvcutsem/harmony-reflect)
+
+This is a shim for the ECMAScript 6 [Reflect](http://www.ecma-international.org/ecma-262/6.0/#sec-reflect-object) and [Proxy](http://www.ecma-international.org/ecma-262/6.0/#sec-proxy-objects) objects.
+
+This library does two things:
+
+  - It defines an ES6-compliant `Reflect` global object that exports the ECMAScript 6 reflection API.
+  - If harmony-era (pre-ES6) `Proxy` support is available, it patches `Proxy` to be up-to-date with the [ES6 spec](http://www.ecma-international.org/ecma-262/6.0/).
+
+**July 2016 update**: the most recent version of all major browsers and node.js now [support fully
+ES6-compliant](http://kangax.github.io/compat-table/es6/#test-Proxy) `Reflect` and `Proxy` objects. This shim is primarily useful if you want ES6 `Reflect`
+support on older browsers or versions of node.js < v6.0.0, or if you want
+ES6 `Proxy` support on versions of node.js < v6.0.0.
+
+**May 2016 update**: the recently released [V8 v4.9](http://v8project.blogspot.com.au/2016/01/v8-release-49.html) includes native support for ES2015 Proxies and Reflect, making this library obsolete for environments that embed V8 4.9 or newer (like Chrome 49 and Node v6.0). Node v5.10.x or lower still requires this polyfill for proper ES6 Proxy support.
+
+Read [Why should I use this library?](https://github.com/tvcutsem/harmony-reflect/wiki)
+
+Installation
+============
+
+For node.js, install via [npm](http://npmjs.org):
+
+    npm install harmony-reflect
+
+Then:
+
+    node --harmony-proxies
+    > var Reflect = require('harmony-reflect');
+
+See [release notes](https://github.com/tvcutsem/harmony-reflect/blob/master/RELNOTES.md) for changes to the npm releases.
+
+To use in a browser, just download the single reflect.js file. After loading
+
+    <script src="reflect.js"></script>
+
+a global object `Reflect` is defined that contains reflection methods as defined in the [ES6 spec](http://www.ecma-international.org/ecma-262/6.0/#sec-reflect-object).
+
+This library also updates the "harmony-era" `Proxy` object in the V8 engine
+(also used in node.js) to follow the latest [ECMAScript 2015](http://www.ecma-international.org/ecma-262/6.0/) spec.
+To create such a proxy, call:
+
+    var proxy = new Proxy(target, handler);
+
+See below for a list of spec incompatibilities and other gotcha's.
+
+API Docs
+========
+
+This module exports an object named `Reflect` and updates the global `Proxy` object (if it exists) to be compatible with the latest ECMAScript 6 spec.
+
+The ECMAScript 6 Proxy API allows one to intercept various operations on Javascript objects.
+
+  * Overview of all [supported traps](https://github.com/tvcutsem/harmony-reflect/tree/master/doc/traps.md) on proxies
+  * The [Reflect API](https://github.com/tvcutsem/harmony-reflect/tree/master/doc/api.md) 
+  * The Proxy [Handler API](https://github.com/tvcutsem/harmony-reflect/tree/master/doc/handler_api.md)
+  
+Compatibility
+=============
+
+The `Reflect` API, with support for proxies, was tested on:
+
+  * Firefox (>= v4.0)
+  * `node --harmony_proxies` (>= v0.7.8)
+  * `iojs --harmony_proxies` (>= 2.3.0)
+  * `v8 --harmony_proxies` (>= v3.6)
+  * Any recent `js` spidermonkey shell
+
+If you need only `Reflect` and not an up-to-date `Proxy` object, this
+library should work on any modern ES5 engine (including all browsers).
+
+Compatibility notes:
+
+  * Chrome (>= v19 && <= v37) used to support proxies behind a flag
+    (`chrome://flags/#enable-javascript-harmony`) but Chrome v38  [removed](https://code.google.com/p/v8/issues/detail?id=1543#c44) the `Proxy` constructor. As a result, this library cannot patch the harmony-era `Proxy` object on Chrome v38 or above. If you're working with Chromium directly, it's still possible to enable proxies using `chromium-browser --js-flags="--harmony_proxies"`.
+  * In older versions of V8, the `Proxy` constructor was enabled by
+    default when starting V8 with `--harmony`. For recent versions of V8,
+    `Proxy` must be explicitly enabled with `--harmony_proxies`.
+
+Dependencies
+============
+
+  *  ECMAScript 5/strict
+  *  To emulate direct proxies:
+    *  old Harmony [Proxies](http://wiki.ecmascript.org/doku.php?id=harmony:proxies)
+    *  Harmony [WeakMaps](http://wiki.ecmascript.org/doku.php?id=harmony:weak_maps)
+
+After loading `reflect.js` into your page or other JS environment, be aware that the following globals are patched to be able to recognize emulated direct proxies:
+
+    Object.getOwnPropertyDescriptor
+    Object.defineProperty
+    Object.defineProperties
+    Object.getOwnPropertyNames
+    Object.getOwnPropertySymbols
+    Object.keys
+    Object.{get,set}PrototypeOf
+    Object.assign
+    Object.{freeze,seal,preventExtensions}
+    Object.{isFrozen,isSealed,isExtensible}
+    Object.prototype.valueOf
+    Object.prototype.isPrototypeOf
+    Object.prototype.toString
+    Object.prototype.hasOwnProperty
+    Function.prototype.toString
+    Date.prototype.toString
+    Array.isArray
+    Array.prototype.concat
+    Proxy
+    Reflect
+
+:warning: In node.js, when you `require('harmony-reflect')`, only the current
+module's globals are patched. If you pass an emulated direct proxy to an external module, and that module uses the unpatched globals, the module may not interact with the proxy according to the latest ES6 Proxy API, instead falling
+back on the old pre-ES6 Proxy API. This can cause bugs, e.g. the built-in `Array.isArray` will return `false` when passed a proxy-for-array, while the
+patched `Array.isArray` will return true. I know of no good fix to reliably patch the globals for all node modules. If you do, let me know.
+
+Examples
+========
+
+The [examples](https://github.com/tvcutsem/harmony-reflect/tree/master/examples) directory contains a number of examples demonstrating the use of proxies:
+
+  * membranes: wrappers that transitively isolate two object-graphs.
+  * observer: a self-hosted implementation of the ES7 `Object.observe` notification mechanism.
+  * profiler: a simple profiler to collect usage statistics of an object.
+
+Other example uses of proxies (not done by me, but using this library):
+
+  * supporting [negative array indices](https://github.com/sindresorhus/negative-array) a la Python
+  * [tpyo](https://github.com/mathiasbynens/tpyo): using proxies to correct typo's in JS property names
+  * [persistent objects](http://tagtree.tv/es6-proxies): shows how one might go about using proxies to save updates to objects in a database incrementally
+  * [defaultdict](https://github.com/greenify/defaultdict2): default values for new keys in objects (as known from Python)
+
+For more examples of proxies, and a good overview of their design rationale, I recommend reading [Axel Rauschmayer's blog post on proxies](http://www.2ality.com/2014/12/es6-proxies.html).
+
+Proxy Handler API
+=================
+
+The sister project [proxy-handlers](https://github.com/tvcutsem/proxy-handlers)
+defines a number of predefined Proxy handlers as "abstract classes" that your 
+code can "subclass" The goal is to minimize the number of traps that your proxy
+handlers must implement.
+
+Spec Incompatibilities and other gotcha's
+=========================================
+
+This library differs from the [ECMAScript 2016 spec](http://www.ecma-international.org/ecma-262/7.0/index.html) as follows:
+
+  * In ES7, the `enumerate()` trap, and the corresponding `Reflect.enumerate()` method, have been [removed](https://github.com/tc39/ecma262/issues/161).
+    This shim still supports the trap.
+  * The ES7 (and ES6) spec contains a 
+    [bug](https://github.com/tc39/ecma262/pull/666) that leads to missing
+    invariant checks in the getOwnPropertyDescriptor, defineProperty and deleteProperty traps. This library already contains the patch referred
+    to in [this issue](https://github.com/tc39/ecma262/pull/666).
+
+This library differs from the [ECMAScript 2015 spec](http://www.ecma-international.org/ecma-262/6.0/) as follows:
+
+  * In ES6, `Proxy` is a constructor function that _requires_ the use
+    of `new`. That is, you must write `new Proxy(target, handler)`. This library
+    exports `Proxy` as an ordinary function which may be called with or without using the `new` operator.
+    
+  * In ES6, `Function.prototype.toString` and `Date.prototype.toString` do not
+    operate transparently on Proxies. This shim patches those functions so that
+    stringifying a Proxy-for-a-function or a Proxy-for-a-date "unwraps" the
+    proxy and instead stringifies the target of the Proxy. This behavior may
+    change in the future to be more spec-compatible.
+    
+  * This library does not shim [Symbol objects](http://www.ecma-international.org/ecma-262/6.0/#sec-symbol-objects).
+    On modern V8 or io.js which supports Symbol objects natively, due to a bug in V8, Symbols and Proxies
+    don't play well together. [Read more](https://github.com/tvcutsem/harmony-reflect/issues/57).
+  
+  * Proxies-for-arrays are serialized as JSON objects rather than as JSON arrays. That is, `JSON.stringify(new Proxy([], {}))` returns "{}" rather than "[]". [Read more]( https://github.com/tvcutsem/harmony-reflect/issues/13#issuecomment-17249465).
Index: frontend/node_modules/harmony-reflect/index.d.ts
===================================================================
--- frontend/node_modules/harmony-reflect/index.d.ts	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/harmony-reflect/index.d.ts	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,20 @@
+declare type PropertyKey = string | number | symbol;
+
+declare namespace Reflect {
+    function apply(target: Function, thisArgument: any, argumentsList: ArrayLike<any>): any;
+    function construct(target: Function, argumentsList: ArrayLike<any>, newTarget?: any): any;
+    function defineProperty(target: any, propertyKey: PropertyKey, attributes: PropertyDescriptor): boolean;
+    function deleteProperty(target: any, propertyKey: PropertyKey): boolean;
+    function get(target: any, propertyKey: PropertyKey, receiver?: any): any;
+    function getOwnPropertyDescriptor(target: any, propertyKey: PropertyKey): PropertyDescriptor;
+    function getPrototypeOf(target: any): any;
+    function has(target: any, propertyKey: string): boolean;
+    function has(target: any, propertyKey: symbol): boolean;
+    function isExtensible(target: any): boolean;
+    function ownKeys(target: any): Array<PropertyKey>;
+    function preventExtensions(target: any): boolean;
+    function set(target: any, propertyKey: PropertyKey, value: any, receiver?: any): boolean;
+    function setPrototypeOf(target: any, proto: any): boolean;
+}
+
+export = Reflect;
Index: frontend/node_modules/harmony-reflect/package.json
===================================================================
--- frontend/node_modules/harmony-reflect/package.json	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/harmony-reflect/package.json	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,21 @@
+{
+  "name": "harmony-reflect",
+  "version": "1.6.2",
+  "description": "ES5 shim for ES6 (ECMAScript 6) Reflect and Proxy objects",
+  "main": "reflect.js",
+  "keywords": [
+    "reflection",
+    "proxies",
+    "proxy",
+    "reflect",
+    "harmony",
+    "es6"
+  ],
+  "license": "(Apache-2.0 OR MPL-1.1)",
+  "homepage": "https://github.com/tvcutsem/harmony-reflect",
+  "typings": "index.d.ts",
+  "repository" : {
+    "type" : "git",
+    "url" : "https://tvcutsem@github.com/tvcutsem/harmony-reflect.git"
+  } 
+}
Index: frontend/node_modules/harmony-reflect/reflect.js
===================================================================
--- frontend/node_modules/harmony-reflect/reflect.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
+++ frontend/node_modules/harmony-reflect/reflect.js	(revision 9af201e94b5a79beb92a30858fc54de4bc3b9449)
@@ -0,0 +1,2200 @@
+// Copyright (C) 2011-2012 Software Languages Lab, Vrije Universiteit Brussel
+// This code is dual-licensed under both the Apache License and the MPL
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/* Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is a shim for the ES-Harmony reflection module
+ *
+ * The Initial Developer of the Original Code is
+ * Tom Van Cutsem, Vrije Universiteit Brussel.
+ * Portions created by the Initial Developer are Copyright (C) 2011-2012
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ */
+
+ // ----------------------------------------------------------------------------
+
+ // This file is a polyfill for the upcoming ECMAScript Reflect API,
+ // including support for Proxies. See the draft specification at:
+ // http://wiki.ecmascript.org/doku.php?id=harmony:reflect_api
+ // http://wiki.ecmascript.org/doku.php?id=harmony:direct_proxies
+
+ // For an implementation of the Handler API, see handlers.js, which implements:
+ // http://wiki.ecmascript.org/doku.php?id=harmony:virtual_object_api
+
+ // This implementation supersedes the earlier polyfill at:
+ // code.google.com/p/es-lab/source/browse/trunk/src/proxies/DirectProxies.js
+
+ // This code was tested on tracemonkey / Firefox 12
+//  (and should run fine on older Firefox versions starting with FF4)
+ // The code also works correctly on
+ //   v8 --harmony_proxies --harmony_weakmaps (v3.6.5.1)
+
+ // Language Dependencies:
+ //  - ECMAScript 5/strict
+ //  - "old" (i.e. non-direct) Harmony Proxies
+ //  - Harmony WeakMaps
+ // Patches:
+ //  - Object.{freeze,seal,preventExtensions}
+ //  - Object.{isFrozen,isSealed,isExtensible}
+ //  - Object.getPrototypeOf
+ //  - Object.keys
+ //  - Object.prototype.valueOf
+ //  - Object.prototype.isPrototypeOf
+ //  - Object.prototype.toString
+ //  - Object.prototype.hasOwnProperty
+ //  - Object.getOwnPropertyDescriptor
+ //  - Object.defineProperty
+ //  - Object.defineProperties
+ //  - Object.getOwnPropertyNames
+ //  - Object.getOwnPropertySymbols
+ //  - Object.getPrototypeOf
+ //  - Object.setPrototypeOf
+ //  - Object.assign
+ //  - Function.prototype.toString
+ //  - Date.prototype.toString
+ //  - Array.isArray
+ //  - Array.prototype.concat
+ //  - Proxy
+ // Adds new globals:
+ //  - Reflect
+
+ // Direct proxies can be created via Proxy(target, handler)
+
+ // ----------------------------------------------------------------------------
+
+(function(global){ // function-as-module pattern
+"use strict";
+
+// === Direct Proxies: Invariant Enforcement ===
+
+// Direct proxies build on non-direct proxies by automatically wrapping
+// all user-defined proxy handlers in a Validator handler that checks and
+// enforces ES5 invariants.
+
+// A direct proxy is a proxy for an existing object called the target object.
+
+// A Validator handler is a wrapper for a target proxy handler H.
+// The Validator forwards all operations to H, but additionally
+// performs a number of integrity checks on the results of some traps,
+// to make sure H does not violate the ES5 invariants w.r.t. non-configurable
+// properties and non-extensible, sealed or frozen objects.
+
+// For each property that H exposes as own, non-configurable
+// (e.g. by returning a descriptor from a call to getOwnPropertyDescriptor)
+// the Validator handler defines those properties on the target object.
+// When the proxy becomes non-extensible, also configurable own properties
+// are checked against the target.
+// We will call properties that are defined on the target object
+// "fixed properties".
+
+// We will name fixed non-configurable properties "sealed properties".
+// We will name fixed non-configurable non-writable properties "frozen
+// properties".
+
+// The Validator handler upholds the following invariants w.r.t. non-configurability:
+// - getOwnPropertyDescriptor cannot report sealed properties as non-existent
+// - getOwnPropertyDescriptor cannot report incompatible changes to the
+//   attributes of a sealed property (e.g. reporting a non-configurable
+//   property as configurable, or reporting a non-configurable, non-writable
+//   property as writable)
+// - getPropertyDescriptor cannot report sealed properties as non-existent
+// - getPropertyDescriptor cannot report incompatible changes to the
+//   attributes of a sealed property. It _can_ report incompatible changes
+//   to the attributes of non-own, inherited properties.
+// - defineProperty cannot make incompatible changes to the attributes of
+//   sealed properties
+// - deleteProperty cannot report a successful deletion of a sealed property
+// - hasOwn cannot report a sealed property as non-existent
+// - has cannot report a sealed property as non-existent
+// - get cannot report inconsistent values for frozen data
+//   properties, and must report undefined for sealed accessors with an
+//   undefined getter
+// - set cannot report a successful assignment for frozen data
+//   properties or sealed accessors with an undefined setter.
+// - get{Own}PropertyNames lists all sealed properties of the target.
+// - keys lists all enumerable sealed properties of the target.
+// - enumerate lists all enumerable sealed properties of the target.
+// - if a property of a non-extensible proxy is reported as non-existent,
+//   then it must forever be reported as non-existent. This applies to
+//   own and inherited properties and is enforced in the
+//   deleteProperty, get{Own}PropertyDescriptor, has{Own},
+//   get{Own}PropertyNames, keys and enumerate traps
+
+// Violation of any of these invariants by H will result in TypeError being
+// thrown.
+
+// Additionally, once Object.preventExtensions, Object.seal or Object.freeze
+// is invoked on the proxy, the set of own property names for the proxy is
+// fixed. Any property name that is not fixed is called a 'new' property.
+
+// The Validator upholds the following invariants regarding extensibility:
+// - getOwnPropertyDescriptor cannot report new properties as existent
+//   (it must report them as non-existent by returning undefined)
+// - defineProperty cannot successfully add a new property (it must reject)
+// - getOwnPropertyNames cannot list new properties
+// - hasOwn cannot report true for new properties (it must report false)
+// - keys cannot list new properties
+
+// Invariants currently not enforced:
+// - getOwnPropertyNames lists only own property names
+// - keys lists only enumerable own property names
+// Both traps may list more property names than are actually defined on the
+// target.
+
+// Invariants with regard to inheritance are currently not enforced.
+// - a non-configurable potentially inherited property on a proxy with
+//   non-mutable ancestry cannot be reported as non-existent
+// (An object with non-mutable ancestry is a non-extensible object whose
+// [[Prototype]] is either null or an object with non-mutable ancestry.)
+
+// Changes in Handler API compared to previous harmony:proxies, see:
+// http://wiki.ecmascript.org/doku.php?id=strawman:direct_proxies
+// http://wiki.ecmascript.org/doku.php?id=harmony:direct_proxies
+
+// ----------------------------------------------------------------------------
+
+// ---- WeakMap polyfill ----
+
+// TODO: find a proper WeakMap polyfill
+
+// define an empty WeakMap so that at least the Reflect module code
+// will work in the absence of WeakMaps. Proxy emulation depends on
+// actual WeakMaps, so will not work with this little shim.
+if (typeof WeakMap === "undefined") {
+  global.WeakMap = function(){};
+  global.WeakMap.prototype = {
+    get: function(k) { return undefined; },
+    set: function(k,v) { throw new Error("WeakMap not supported"); }
+  };
+}
+
+// ---- Normalization functions for property descriptors ----
+
+function isStandardAttribute(name) {
+  return /^(get|set|value|writable|enumerable|configurable)$/.test(name);
+}
+
+// Adapted from ES5 section 8.10.5
+function toPropertyDescriptor(obj) {
+  if (Object(obj) !== obj) {
+    throw new TypeError("property descriptor should be an Object, given: "+
+                        obj);
+  }
+  var desc = {};
+  if ('enumerable' in obj) { desc.enumerable = !!obj.enumerable; }
+  if ('configurable' in obj) { desc.configurable = !!obj.configurable; }
+  if ('value' in obj) { desc.value = obj.value; }
+  if ('writable' in obj) { desc.writable = !!obj.writable; }
+  if ('get' in obj) {
+    var getter = obj.get;
+    if (getter !== undefined && typeof getter !== "function") {
+      throw new TypeError("property descriptor 'get' attribute must be "+
+                          "callable or undefined, given: "+getter);
+    }
+    desc.get = getter;
+  }
+  if ('set' in obj) {
+    var setter = obj.set;
+    if (setter !== undefined && typeof setter !== "function") {
+      throw new TypeError("property descriptor 'set' attribute must be "+
+                          "callable or undefined, given: "+setter);
+    }
+    desc.set = setter;
+  }
+  if ('get' in desc || 'set' in desc) {
+    if ('value' in desc || 'writable' in desc) {
+      throw new TypeError("property descriptor cannot be both a data and an "+
+                          "accessor descriptor: "+obj);
+    }
+  }
+  return desc;
+}
+
+function isAccessorDescriptor(desc) {
+  if (desc === undefined) return false;
+  return ('get' in desc || 'set' in desc);
+}
+function isDataDescriptor(desc) {
+  if (desc === undefined) return false;
+  return ('value' in desc || 'writable' in desc);
+}
+function isGenericDescriptor(desc) {
+  if (desc === undefined) return false;
+  return !isAccessorDescriptor(desc) && !isDataDescriptor(desc);
+}
+
+function toCompletePropertyDescriptor(desc) {
+  var internalDesc = toPropertyDescriptor(desc);
+  if (isGenericDescriptor(internalDesc) || isDataDescriptor(internalDesc)) {
+    if (!('value' in internalDesc)) { internalDesc.value = undefined; }
+    if (!('writable' in internalDesc)) { internalDesc.writable = false; }
+  } else {
+    if (!('get' in internalDesc)) { internalDesc.get = undefined; }
+    if (!('set' in internalDesc)) { internalDesc.set = undefined; }
+  }
+  if (!('enumerable' in internalDesc)) { internalDesc.enumerable = false; }
+  if (!('configurable' in internalDesc)) { internalDesc.configurable = false; }
+  return internalDesc;
+}
+
+function isEmptyDescriptor(desc) {
+  return !('get' in desc) &&
+         !('set' in desc) &&
+         !('value' in desc) &&
+         !('writable' in desc) &&
+         !('enumerable' in desc) &&
+         !('configurable' in desc);
+}
+
+function isEquivalentDescriptor(desc1, desc2) {
+  return sameValue(desc1.get, desc2.get) &&
+         sameValue(desc1.set, desc2.set) &&
+         sameValue(desc1.value, desc2.value) &&
+         sameValue(desc1.writable, desc2.writable) &&
+         sameValue(desc1.enumerable, desc2.enumerable) &&
+         sameValue(desc1.configurable, desc2.configurable);
+}
+
+// copied from http://wiki.ecmascript.org/doku.php?id=harmony:egal
+function sameValue(x, y) {
+  if (x === y) {
+    // 0 === -0, but they are not identical
+    return x !== 0 || 1 / x === 1 / y;
+  }
+
+  // NaN !== NaN, but they are identical.
+  // NaNs are the only non-reflexive value, i.e., if x !== x,
+  // then x is a NaN.
+  // isNaN is broken: it converts its argument to number, so
+  // isNaN("foo") => true
+  return x !== x && y !== y;
+}
+
+/**
+ * Returns a fresh property descriptor that is guaranteed
+ * to be complete (i.e. contain all the standard attributes).
+ * Additionally, any non-standard enumerable properties of
+ * attributes are copied over to the fresh descriptor.
+ *
+ * If attributes is undefined, returns undefined.
+ *
+ * See also: http://wiki.ecmascript.org/doku.php?id=harmony:proxies_semantics
+ */
+function normalizeAndCompletePropertyDescriptor(attributes) {
+  if (attributes === undefined) { return undefined; }
+  var desc = toCompletePropertyDescriptor(attributes);
+  // Note: no need to call FromPropertyDescriptor(desc), as we represent
+  // "internal" property descriptors as proper Objects from the start
+  for (var name in attributes) {
+    if (!isStandardAttribute(name)) {
+      Object.defineProperty(desc, name,
+        { value: attributes[name],
+          writable: true,
+          enumerable: true,
+          configurable: true });
+    }
+  }
+  return desc;
+}
+
+/**
+ * Returns a fresh property descriptor whose standard
+ * attributes are guaranteed to be data properties of the right type.
+ * Additionally, any non-standard enumerable properties of
+ * attributes are copied over to the fresh descriptor.
+ *
+ * If attributes is undefined, will throw a TypeError.
+ *
+ * See also: http://wiki.ecmascript.org/doku.php?id=harmony:proxies_semantics
+ */
+function normalizePropertyDescriptor(attributes) {
+  var desc = toPropertyDescriptor(attributes);
+  // Note: no need to call FromGenericPropertyDescriptor(desc), as we represent
+  // "internal" property descriptors as proper Objects from the start
+  for (var name in attributes) {
+    if (!isStandardAttribute(name)) {
+      Object.defineProperty(desc, name,
+        { value: attributes[name],
+          writable: true,
+          enumerable: true,
+          configurable: true });
+    }
+  }
+  return desc;
+}
+
+// store a reference to the real ES5 primitives before patching them later
+var prim_preventExtensions =        Object.preventExtensions,
+    prim_seal =                     Object.seal,
+    prim_freeze =                   Object.freeze,
+    prim_isExtensible =             Object.isExtensible,
+    prim_isSealed =                 Object.isSealed,
+    prim_isFrozen =                 Object.isFrozen,
+    prim_getPrototypeOf =           Object.getPrototypeOf,
+    prim_getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor,
+    prim_defineProperty =           Object.defineProperty,
+    prim_defineProperties =         Object.defineProperties,
+    prim_keys =                     Object.keys,
+    prim_getOwnPropertyNames =      Object.getOwnPropertyNames,
+    prim_getOwnPropertySymbols =    Object.getOwnPropertySymbols,
+    prim_assign =                   Object.assign,
+    prim_isArray =                  Array.isArray,
+    prim_concat =                   Array.prototype.concat,
+    prim_isPrototypeOf =            Object.prototype.isPrototypeOf,
+    prim_hasOwnProperty =           Object.prototype.hasOwnProperty;
+
+// these will point to the patched versions of the respective methods on
+// Object. They are used within this module as the "intrinsic" bindings
+// of these methods (i.e. the "original" bindings as defined in the spec)
+var Object_isFrozen,
+    Object_isSealed,
+    Object_isExtensible,
+    Object_getPrototypeOf,
+    Object_getOwnPropertyNames;
+
+/**
+ * A property 'name' is fixed if it is an own property of the target.
+ */
+function isFixed(name, target) {
+  return ({}).hasOwnProperty.call(target, name);
+}
+function isSealed(name, target) {
+  var desc = Object.getOwnPropertyDescriptor(target, name);
+  if (desc === undefined) { return false; }
+  return desc.configurable === false;
+}
+function isSealedDesc(desc) {
+  return desc !== undefined && desc.configurable === false;
+}
+
+/**
+ * Performs all validation that Object.defineProperty performs,
+ * without actually defining the property. Returns a boolean
+ * indicating whether validation succeeded.
+ *
+ * Implementation transliterated from ES5.1 section 8.12.9
+ */
+function isCompatibleDescriptor(extensible, current, desc) {
+  if (current === undefined && extensible === false) {
+    return false;
+  }
+  if (current === undefined && extensible === true) {
+    return true;
+  }
+  if (isEmptyDescriptor(desc)) {
+    return true;
+  }
+  if (isEquivalentDescriptor(current, desc)) {
+    return true;
+  }
+  if (current.configurable === false) {
+    if (desc.configurable === true) {
+      return false;
+    }
+    if ('enumerable' in desc && desc.enumerable !== current.enumerable) {
+      return false;
+    }
+  }
+  if (isGenericDescriptor(desc)) {
+    return true;
+  }
+  if (isDataDescriptor(current) !== isDataDescriptor(desc)) {
+    if (current.configurable === false) {
+      return false;
+    }
+    return true;
+  }
+  if (isDataDescriptor(current) && isDataDescriptor(desc)) {
+    if (current.configurable === false) {
+      if (current.writable === false && desc.writable === true) {
+        return false;
+      }
+      if (current.writable === false) {
+        if ('value' in desc && !sameValue(desc.value, current.value)) {
+          return false;
+        }
+      }
+    }
+    return true;
+  }
+  if (isAccessorDescriptor(current) && isAccessorDescriptor(desc)) {
+    if (current.configurable === false) {
+      if ('set' in desc && !sameValue(desc.set, current.set)) {
+        return false;
+      }
+      if ('get' in desc && !sameValue(desc.get, current.get)) {
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
+// ES6 7.3.11 SetIntegrityLevel
+// level is one of "sealed" or "frozen"
+function setIntegrityLevel(target, level) {
+  var ownProps = Object_getOwnPropertyNames(target);
+  var pendingException = undefined;
+  if (level === "sealed") {
+    var l = +ownProps.length;
+    var k;
+    for (var i = 0; i < l; i++) {
+      k = String(ownProps[i]);
+      try {
+        Object.defineProperty(target, k, { configurable: false });
+      } catch (e) {
+        if (pendingException === undefined) {
+          pendingException = e;
+        }
+      }
+    }
+  } else {
+    // level === "frozen"
+    var l = +ownProps.length;
+    var k;
+    for (var i = 0; i < l; i++) {
+      k = String(ownProps[i]);
+      try {
+        var currentDesc = Object.getOwnPropertyDescriptor(target, k);
+        if (currentDesc !== undefined) {
+          var desc;
+          if (isAccessorDescriptor(currentDesc)) {
+            desc = { configurable: false }
+          } else {
+            desc = { configurable: false, writable: false }
+          }
+          Object.defineProperty(target, k, desc);
+        }        
+      } catch (e) {
+        if (pendingException === undefined) {
+          pendingException = e;
+        }
+      }
+    }
+  }
+  if (pendingException !== undefined) {
+    throw pendingException;
+  }
+  return Reflect.preventExtensions(target);
+}
+
+// ES6 7.3.12 TestIntegrityLevel
+// level is one of "sealed" or "frozen"
+function testIntegrityLevel(target, level) {
+  var isExtensible = Object_isExtensible(target);
+  if (isExtensible) return false;
+  
+  var ownProps = Object_getOwnPropertyNames(target);
+  var pendingException = undefined;
+  var configurable = false;
+  var writable = false;
+  
+  var l = +ownProps.length;
+  var k;
+  var currentDesc;
+  for (var i = 0; i < l; i++) {
+    k = String(ownProps[i]);
+    try {
+      currentDesc = Object.getOwnPropertyDescriptor(target, k);
+      configurable = configurable || currentDesc.configurable;
+      if (isDataDescriptor(currentDesc)) {
+        writable = writable || currentDesc.writable;
+      }
+    } catch (e) {
+      if (pendingException === undefined) {
+        pendingException = e;
+        configurable = true;
+      }
+    }
+  }
+  if (pendingException !== undefined) {
+    throw pendingException;
+  }
+  if (level === "frozen" && writable === true) {
+    return false;
+  }
+  if (configurable === true) {
+    return false;
+  }
+  return true;
+}
+
+// ---- The Validator handler wrapper around user handlers ----
+
+/**
+ * @param target the object wrapped by this proxy.
+ * As long as the proxy is extensible, only non-configurable properties
+ * are checked against the target. Once the proxy becomes non-extensible,
+ * invariants w.r.t. non-extensibility are also enforced.
+ *
+ * @param handler the handler of the direct proxy. The object emulated by
+ * this handler is validated against the target object of the direct proxy.
+ * Any violations that the handler makes against the invariants
+ * of the target will cause a TypeError to be thrown.
+ *
+ * Both target and handler must be proper Objects at initialization time.
+ */
+function Validator(target, handler) {
+  // for non-revokable proxies, these are const references
+  // for revokable proxies, on revocation:
+  // - this.target is set to null
+  // - this.handler is set to a handler that throws on all traps
+  this.target  = target;
+  this.handler = handler;
+}
+
+Validator.prototype = {
+
+  /**
+   * If getTrap returns undefined, the caller should perform the
+   * default forwarding behavior.
+   * If getTrap returns normally otherwise, the return value
+   * will be a callable trap function. When calling the trap function,
+   * the caller is responsible for binding its |this| to |this.handler|.
+   */
+  getTrap: function(trapName) {
+    var trap = this.handler[trapName];
+    if (trap === undefined) {
+      // the trap was not defined,
+      // perform the default forwarding behavior
+      return undefined;
+    }
+
+    if (typeof trap !== "function") {
+      throw new TypeError(trapName + " trap is not callable: "+trap);
+    }
+
+    return trap;
+  },
+
+  // === fundamental traps ===
+
+  /**
+   * If name denotes a fixed property, check:
+   *   - whether targetHandler reports it as existent
+   *   - whether the returned descriptor is compatible with the fixed property
+   * If the proxy is non-extensible, check:
+   *   - whether name is not a new property
+   * Additionally, the returned descriptor is normalized and completed.
+   */
+  getOwnPropertyDescriptor: function(name) {
+    "use strict";
+
+    var trap = this.getTrap("getOwnPropertyDescriptor");
+    if (trap === undefined) {
+      return Reflect.getOwnPropertyDescriptor(this.target, name);
+    }
+
+    name = String(name);
+    var desc = trap.call(this.handler, this.target, name);
+    desc = normalizeAndCompletePropertyDescriptor(desc);
+
+    var targetDesc = Object.getOwnPropertyDescriptor(this.target, name);
+    var extensible = Object.isExtensible(this.target);
+
+    if (desc === undefined) {
+      if (isSealedDesc(targetDesc)) {
+        throw new TypeError("cannot report non-configurable property '"+name+
+                            "' as non-existent");
+      }
+      if (!extensible && targetDesc !== undefined) {
+          // if handler is allowed to return undefined, we cannot guarantee
+          // that it will not return a descriptor for this property later.
+          // Once a property has been reported as non-existent on a non-extensible
+          // object, it should forever be reported as non-existent
+          throw new TypeError("cannot report existing own property '"+name+
+                              "' as non-existent on a non-extensible object");
+      }
+      return undefined;
+    }
+
+    // at this point, we know (desc !== undefined), i.e.
+    // targetHandler reports 'name' as an existing property
+
+    // Note: we could collapse the following two if-tests into a single
+    // test. Separating out the cases to improve error reporting.
+
+    if (!extensible) {
+      if (targetDesc === undefined) {
+        throw new TypeError("cannot report a new own property '"+
+                            name + "' on a non-extensible object");
+      }
+    }
+
+    if (name !== undefined) {
+      if (!isCompatibleDescriptor(extensible, targetDesc, desc)) {
+        throw new TypeError("cannot report incompatible property descriptor "+
+                            "for property '"+name+"'");
+      }
+    }
+    
+    if (desc.configurable === false) {
+      if (targetDesc === undefined || targetDesc.configurable === true) {
+        // if the property is configurable or non-existent on the target,
+        // but is reported as a non-configurable property, it may later be
+        // reported as configurable or non-existent, which violates the
+        // invariant that if the property might change or disappear, the
+        // configurable attribute must be true.
+        throw new TypeError(
+          "cannot report a non-configurable descriptor " +
+          "for configurable or non-existent property '" + name + "'");
+      }
+      if ('writable' in desc && desc.writable === false) {
+        if (targetDesc.writable === true) {
+          // if the property is non-configurable, writable on the target,
+          // but is reported as non-configurable, non-writable, it may later
+          // be reported as non-configurable, writable again, which violates
+          // the invariant that a non-configurable, non-writable property
+          // may not change state.
+          throw new TypeError(
+            "cannot report non-configurable, writable property '" + name +
+            "' as non-configurable, non-writable");
+        }
+      }
+    }
+
+    return desc;
+  },
+
+  /**
+   * In the direct proxies design with refactored prototype climbing,
+   * this trap is deprecated. For proxies-as-prototypes, instead
+   * of calling this trap, the get, set, has or enumerate traps are
+   * called instead.
+   *
+   * In this implementation, we "abuse" getPropertyDescriptor to
+   * support trapping the get or set traps for proxies-as-prototypes.
+   * We do this by returning a getter/setter pair that invokes
+   * the corresponding traps.
+   *
+   * While this hack works for inherited property access, it has some
+   * quirks:
+   *
+   * In Firefox, this trap is only called after a prior invocation
+   * of the 'has' trap has returned true. Hence, expect the following
+   * behavior:
+   * <code>
+   * var child = Object.create(Proxy(target, handler));
+   * child[name] // triggers handler.has(target, name)
+   * // if that returns true, triggers handler.get(target, name, child)
+   * </code>
+   *
+   * On v8, the 'in' operator, when applied to an object that inherits
+   * from a proxy, will call getPropertyDescriptor and walk the proto-chain.
+   * That calls the below getPropertyDescriptor trap on the proxy. The
+   * result of the 'in'-operator is then determined by whether this trap
+   * returns undefined or a property descriptor object. That is why
+   * we first explicitly trigger the 'has' trap to determine whether
+   * the property exists.
+   *
+   * This has the side-effect that when enumerating properties on
+   * an object that inherits from a proxy in v8, only properties
+   * for which 'has' returns true are returned:
+   *
+   * <code>
+   * var child = Object.create(Proxy(target, handler));
+   * for (var prop in child) {
+   *   // only enumerates prop if (prop in child) returns true
+   * }
+   * </code>
+   */
+  getPropertyDescriptor: function(name) {
+    var handler = this;
+
+    if (!handler.has(name)) return undefined;
+
+    return {
+      get: function() {
+        return handler.get(this, name);
+      },
+      set: function(val) {
+        if (handler.set(this, name, val)) {
+          return val;
+        } else {
+          throw new TypeError("failed assignment to "+name);
+        }
+      },
+      enumerable: true,
+      configurable: true
+    };
+  },
+
+  /**
+   * If name denotes a fixed property, check for incompatible changes.
+   * If the proxy is non-extensible, check that new properties are rejected.
+   */
+  defineProperty: function(name, desc) {
+    // TODO(tvcutsem): the current tracemonkey implementation of proxies
+    // auto-completes 'desc', which is not correct. 'desc' should be
+    // normalized, but not completed. Consider:
+    // Object.defineProperty(proxy, 'foo', {enumerable:false})
+    // This trap will receive desc =
+    //  {value:undefined,writable:false,enumerable:false,configurable:false}
+    // This will also set all other attributes to their default value,
+    // which is unexpected and different from [[DefineOwnProperty]].
+    // Bug filed: https://bugzilla.mozilla.org/show_bug.cgi?id=601329
+
+    var trap = this.getTrap("defineProperty");
+    if (trap === undefined) {
+      // default forwarding behavior
+      return Reflect.defineProperty(this.target, name, desc);
+    }
+
+    name = String(name);
+    var descObj = normalizePropertyDescriptor(desc);
+    var success = trap.call(this.handler, this.target, name, descObj);
+    success = !!success; // coerce to Boolean
+
+    if (success === true) {
+
+      var targetDesc = Object.getOwnPropertyDescriptor(this.target, name);
+      var extensible = Object.isExtensible(this.target);
+
+      // Note: we could collapse the following two if-tests into a single
+      // test. Separating out the cases to improve error reporting.
+
+      if (!extensible) {
+        if (targetDesc === undefined) {
+          throw new TypeError("cannot successfully add a new property '"+
+                              name + "' to a non-extensible object");
+        }
+      }
+
+      if (targetDesc !== undefined) {
+        if (!isCompatibleDescriptor(extensible, targetDesc, desc)) {
+          throw new TypeError("cannot define incompatible property "+
+                              "descriptor for property '"+name+"'");
+        }
+        if (isDataDescriptor(targetDesc) &&
+            targetDesc.configurable === false &&
+            targetDesc.writable === true) {
+            if (desc.configurable === false && desc.writable === false) {
+              // if the property is non-configurable, writable on the target
+              // but was successfully reported to be updated to
+              // non-configurable, non-writable, it can later be reported
+              // again as non-configurable, writable, which violates
+              // the invariant that non-configurable, non-writable properties
+              // cannot change state
+              throw new TypeError(
+                "cannot successfully define non-configurable, writable " +
+                " property '" + name + "' as non-configurable, non-writable");
+            }
+          }
+      }
+
+      if (desc.configurable === false && !isSealedDesc(targetDesc)) {
+        // if the property is configurable or non-existent on the target,
+        // but is successfully being redefined as a non-configurable property,
+        // it may later be reported as configurable or non-existent, which violates
+        // the invariant that if the property might change or disappear, the
+        // configurable attribute must be true.
+        throw new TypeError(
+          "cannot successfully define a non-configurable " +
+          "descriptor for configurable or non-existent property '" +
+          name + "'");
+      }
+
+    }
+
+    return success;
+  },
+
+  /**
+   * On success, check whether the target object is indeed non-extensible.
+   */
+  preventExtensions: function() {
+    var trap = this.getTrap("preventExtensions");
+    if (trap === undefined) {
+      // default forwarding behavior
+      return Reflect.preventExtensions(this.target);
+    }
+
+    var success = trap.call(this.handler, this.target);
+    success = !!success; // coerce to Boolean
+    if (success) {
+      if (Object_isExtensible(this.target)) {
+        throw new TypeError("can't report extensible object as non-extensible: "+
+                            this.target);
+      }
+    }
+    return success;
+  },
+
+  /**
+   * If name denotes a sealed property, check whether handler rejects.
+   */
+  delete: function(name) {
+    "use strict";
+    var trap = this.getTrap("deleteProperty");
+    if (trap === undefined) {
+      // default forwarding behavior
+      return Reflect.deleteProperty(this.target, name);
+    }
+
+    name = String(name);
+    var res = trap.call(this.handler, this.target, name);
+    res = !!res; // coerce to Boolean
+
+    var targetDesc;
+    if (res === true) {
+      targetDesc = Object.getOwnPropertyDescriptor(this.target, name);
+      if (targetDesc !== undefined && targetDesc.configurable === false) {
+        throw new TypeError("property '" + name + "' is non-configurable "+
+                            "and can't be deleted");
+      }
+      if (targetDesc !== undefined && !Object_isExtensible(this.target)) {
+        // if the property still exists on a non-extensible target but
+        // is reported as successfully deleted, it may later be reported
+        // as present, which violates the invariant that an own property,
+        // deleted from a non-extensible object cannot reappear.
+        throw new TypeError(
+          "cannot successfully delete existing property '" + name +
+          "' on a non-extensible object");
+      }
+    }
+
+    return res;
+  },
+
+  /**
+   * The getOwnPropertyNames trap was replaced by the ownKeys trap,
+   * which now also returns an array (of strings or symbols) and
+   * which performs the same rigorous invariant checks as getOwnPropertyNames
+   *
+   * See issue #48 on how this trap can still get invoked by external libs
+   * that don't use the patched Object.getOwnPropertyNames function.
+   */
+  getOwnPropertyNames: function() {
+    // Note: removed deprecation warning to avoid dependency on 'console'
+    // (and on node, should anyway use util.deprecate). Deprecation warnings
+    // can also be annoying when they are outside of the user's control, e.g.
+    // when an external library calls unpatched Object.getOwnPropertyNames.
+    // Since there is a clean fallback to `ownKeys`, the fact that the
+    // deprecated method is still called is mostly harmless anyway.
+    // See also issues #65 and #66.
+    // console.warn("getOwnPropertyNames trap is deprecated. Use ownKeys instead");
+    return this.ownKeys();
+  },
+
+  /**
+   * Checks whether the trap result does not contain any new properties
+   * if the proxy is non-extensible.
+   *
+   * Any own non-configurable properties of the target that are not included
+   * in the trap result give rise to a TypeError. As such, we check whether the
+   * returned result contains at least all sealed properties of the target
+   * object.
+   *
+   * Additionally, the trap result is normalized.
+   * Instead of returning the trap result directly:
+   *  - create and return a fresh Array,
+   *  - of which each element is coerced to a String
+   *
+   * This trap is called a.o. by Reflect.ownKeys, Object.getOwnPropertyNames
+   * and Object.keys (the latter filters out only the enumerable own properties).
+   */
+  ownKeys: function() {
+    var trap = this.getTrap("ownKeys");
+    if (trap === undefined) {
+      // default forwarding behavior
+      return Reflect.ownKeys(this.target);
+    }
+
+    var trapResult = trap.call(this.handler, this.target);
+
+    // propNames is used as a set of strings
+    var propNames = Object.create(null);
+    var numProps = +trapResult.length;
+    var result = new Array(numProps);
+
+    for (var i = 0; i < numProps; i++) {
+      var s = String(trapResult[i]);
+      if (!Object.isExtensible(this.target) && !isFixed(s, this.target)) {
+        // non-extensible proxies don't tolerate new own property names
+        throw new TypeError("ownKeys trap cannot list a new "+
+                            "property '"+s+"' on a non-extensible object");
+      }
+
+      propNames[s] = true;
+      result[i] = s;
+    }
+
+    var ownProps = Object_getOwnPropertyNames(this.target);
+    var target = this.target;
+    ownProps.forEach(function (ownProp) {
+      if (!propNames[ownProp]) {
+        if (isSealed(ownProp, target)) {
+          throw new TypeError("ownKeys trap failed to include "+
+                              "non-configurable property '"+ownProp+"'");
+        }
+        if (!Object.isExtensible(target) &&
+            isFixed(ownProp, target)) {
+            // if handler is allowed to report ownProp as non-existent,
+            // we cannot guarantee that it will never later report it as
+            // existent. Once a property has been reported as non-existent
+            // on a non-extensible object, it should forever be reported as
+            // non-existent
+            throw new TypeError("ownKeys trap cannot report existing own property '"+
+                                ownProp+"' as non-existent on a non-extensible object");
+        }
+      }
+    });
+
+    return result;
+  },
+
+  /**
+   * Checks whether the trap result is consistent with the state of the
+   * wrapped target.
+   */
+  isExtensible: function() {
+    var trap = this.getTrap("isExtensible");
+    if (trap === undefined) {
+      // default forwarding behavior
+      return Reflect.isExtensible(this.target);
+    }
+
+    var result = trap.call(this.handler, this.target);
+    result = !!result; // coerce to Boolean
+    var state = Object_isExtensible(this.target);
+    if (result !== state) {
+      if (result) {
+        throw new TypeError("cannot report non-extensible object as extensible: "+
+                             this.target);
+      } else {
+        throw new TypeError("cannot report extensible object as non-extensible: "+
+                             this.target);
+      }
+    }
+    return state;
+  },
+
+  /**
+   * Check whether the trap result corresponds to the target's [[Prototype]]
+   */
+  getPrototypeOf: function() {
+    var trap = this.getTrap("getPrototypeOf");
+    if (trap === undefined) {
+      // default forwarding behavior
+      return Reflect.getPrototypeOf(this.target);
+    }
+
+    var allegedProto = trap.call(this.handler, this.target);
+
+    if (!Object_isExtensible(this.target)) {
+      var actualProto = Object_getPrototypeOf(this.target);
+      if (!sameValue(allegedProto, actualProto)) {
+        throw new TypeError("prototype value does not match: " + this.target);
+      }
+    }
+
+    return allegedProto;
+  },
+
+  /**
+   * If target is non-extensible and setPrototypeOf trap returns true,
+   * check whether the trap result corresponds to the target's [[Prototype]]
+   */
+  setPrototypeOf: function(newProto) {
+    var trap = this.getTrap("setPrototypeOf");
+    if (trap === undefined) {
+      // default forwarding behavior
+      return Reflect.setPrototypeOf(this.target, newProto);
+    }
+
+    var success = trap.call(this.handler, this.target, newProto);
+
+    success = !!success;
+    if (success && !Object_isExtensible(this.target)) {
+      var actualProto = Object_getPrototypeOf(this.target);
+      if (!sameValue(newProto, actualProto)) {
+        throw new TypeError("prototype value does not match: " + this.target);
+      }
+    }
+
+    return success;
+  },
+
+  /**
+   * In the direct proxies design with refactored prototype climbing,
+   * this trap is deprecated. For proxies-as-prototypes, for-in will
+   * call the enumerate() trap. If that trap is not defined, the
+   * operation is forwarded to the target, no more fallback on this
+   * fundamental trap.
+   */
+  getPropertyNames: function() {
+    throw new TypeError("getPropertyNames trap is deprecated");
+  },
+
+  // === derived traps ===
+
+  /**
+   * If name denotes a fixed property, check whether the trap returns true.
+   */
+  has: function(name) {
+    var trap = this.getTrap("has");
+    if (trap === undefined) {
+      // default forwarding behavior
+      return Reflect.has(this.target, name);
+    }
+
+    name = String(name);
+    var res = trap.call(this.handler, this.target, name);
+    res = !!res; // coerce to Boolean
+
+    if (res === false) {
+      if (isSealed(name, this.target)) {
+        throw new TypeError("cannot report existing non-configurable own "+
+                            "property '"+ name + "' as a non-existent "+
+                            "property");
+      }
+      if (!Object.isExtensible(this.target) &&
+          isFixed(name, this.target)) {
+          // if handler is allowed to return false, we cannot guarantee
+          // that it will not return true for this property later.
+          // Once a property has been reported as non-existent on a non-extensible
+          // object, it should forever be reported as non-existent
+          throw new TypeError("cannot report existing own property '"+name+
+                              "' as non-existent on a non-extensible object");
+      }
+    }
+
+    // if res === true, we don't need to check for extensibility
+    // even for a non-extensible proxy that has no own name property,
+    // the property may have been inherited
+
+    return res;
+  },
+
+  /**
+   * If name denotes a fixed non-configurable, non-writable data property,
+   * check its return value against the previously asserted value of the
+   * fixed property.
+   */
+  get: function(receiver, name) {
+
+    // experimental support for invoke() trap on platforms that
+    // support __noSuchMethod__
+    /*
+    if (name === '__noSuchMethod__') {
+      var handler = this;
+      return function(name, args) {
+        return handler.invoke(receiver, name, args);
+      }
+    }
+    */
+
+    var trap = this.getTrap("get");
+    if (trap === undefined) {
+      // default forwarding behavior
+      return Reflect.get(this.target, name, receiver);
+    }
+
+    name = String(name);
+    var res = trap.call(this.handler, this.target, name, receiver);
+
+    var fixedDesc = Object.getOwnPropertyDescriptor(this.target, name);
+    // check consistency of the returned value
+    if (fixedDesc !== undefined) { // getting an existing property
+      if (isDataDescriptor(fixedDesc) &&
+          fixedDesc.configurable === false &&
+          fixedDesc.writable === false) { // own frozen data property
+        if (!sameValue(res, fixedDesc.value)) {
+          throw new TypeError("cannot report inconsistent value for "+
+                              "non-writable, non-configurable property '"+
+                              name+"'");
+        }
+      } else { // it's an accessor property
+        if (isAccessorDescriptor(fixedDesc) &&
+            fixedDesc.configurable === false &&
+            fixedDesc.get === undefined) {
+          if (res !== undefined) {
+            throw new TypeError("must report undefined for non-configurable "+
+                                "accessor property '"+name+"' without getter");
+          }
+        }
+      }
+    }
+
+    return res;
+  },
+
+  /**
+   * If name denotes a fixed non-configurable, non-writable data property,
+   * check that the trap rejects the assignment.
+   */
+  set: function(receiver, name, val) {
+    var trap = this.getTrap("set");
+    if (trap === undefined) {
+      // default forwarding behavior
+      return Reflect.set(this.target, name, val, receiver);
+    }
+
+    name = String(name);
+    var res = trap.call(this.handler, this.target, name, val, receiver);
+    res = !!res; // coerce to Boolean
+
+    // if success is reported, check whether property is truly assignable
+    if (res === true) {
+      var fixedDesc = Object.getOwnPropertyDescriptor(this.target, name);
+      if (fixedDesc !== undefined) { // setting an existing property
+        if (isDataDescriptor(fixedDesc) &&
+            fixedDesc.configurable === false &&
+            fixedDesc.writable === false) {
+          if (!sameValue(val, fixedDesc.value)) {
+            throw new TypeError("cannot successfully assign to a "+
+                                "non-writable, non-configurable property '"+
+                                name+"'");
+          }
+        } else {
+          if (isAccessorDescriptor(fixedDesc) &&
+              fixedDesc.configurable === false && // non-configurable
+              fixedDesc.set === undefined) {      // accessor with undefined setter
+            throw new TypeError("setting a property '"+name+"' that has "+
+                                " only a getter");
+          }
+        }
+      }
+    }
+
+    return res;
+  },
+
+  /**
+   * Any own enumerable non-configurable properties of the target that are not
+   * included in the trap result give rise to a TypeError. As such, we check
+   * whether the returned result contains at least all sealed enumerable properties
+   * of the target object.
+   *
+   * The trap should return an iterator.
+   *
+   * However, as implementations of pre-direct proxies still expect enumerate
+   * to return an array of strings, we convert the iterator into an array.
+   */
+  enumerate: function() {
+    var trap = this.getTrap("enumerate");
+    if (trap === undefined) {
+      // default forwarding behavior
+      var trapResult = Reflect.enumerate(this.target);
+      var result = [];
+      var nxt = trapResult.next();
+      while (!nxt.done) {
+        result.push(String(nxt.value));
+        nxt = trapResult.next();
+      }
+      return result;
+    }
+
+    var trapResult = trap.call(this.handler, this.target);
+    
+    if (trapResult === null ||
+        trapResult === undefined ||
+        trapResult.next === undefined) {
+      throw new TypeError("enumerate trap should return an iterator, got: "+
+                          trapResult);    
+    }
+    
+    // propNames is used as a set of strings
+    var propNames = Object.create(null);
+    
+    // var numProps = +trapResult.length;
+    var result = []; // new Array(numProps);
+    
+    // trapResult is supposed to be an iterator
+    // drain iterator to array as current implementations still expect
+    // enumerate to return an array of strings
+    var nxt = trapResult.next();
+    
+    while (!nxt.done) {
+      var s = String(nxt.value);
+      if (propNames[s]) {
+        throw new TypeError("enumerate trap cannot list a "+
+                            "duplicate property '"+s+"'");
+      }
+      propNames[s] = true;
+      result.push(s);
+      nxt = trapResult.next();
+    }
+    
+    /*for (var i = 0; i < numProps; i++) {
+      var s = String(trapResult[i]);
+      if (propNames[s]) {
+        throw new TypeError("enumerate trap cannot list a "+
+                            "duplicate property '"+s+"'");
+      }
+
+      propNames[s] = true;
+      result[i] = s;
+    } */
+
+    var ownEnumerableProps = Object.keys(this.target);
+    var target = this.target;
+    ownEnumerableProps.forEach(function (ownEnumerableProp) {
+      if (!propNames[ownEnumerableProp]) {
+        if (isSealed(ownEnumerableProp, target)) {
+          throw new TypeError("enumerate trap failed to include "+
+                              "non-configurable enumerable property '"+
+                              ownEnumerableProp+"'");
+        }
+        if (!Object.isExtensible(target) &&
+            isFixed(ownEnumerableProp, target)) {
+            // if handler is allowed not to report ownEnumerableProp as an own
+            // property, we cannot guarantee that it will never report it as
+            // an own property later. Once a property has been reported as
+            // non-existent on a non-extensible object, it should forever be
+            // reported as non-existent
+            throw new TypeError("cannot report existing own property '"+
+                                ownEnumerableProp+"' as non-existent on a "+
+                                "non-extensible object");
+        }
+      }
+    });
+
+    return result;
+  },
+
+  /**
+   * The iterate trap is deprecated by the enumerate trap.
+   */
+  iterate: Validator.prototype.enumerate,
+
+  /**
+   * Any own non-configurable properties of the target that are not included
+   * in the trap result give rise to a TypeError. As such, we check whether the
+   * returned result contains at least all sealed properties of the target
+   * object.
+   *
+   * The trap result is normalized.
+   * The trap result is not returned directly. Instead:
+   *  - create and return a fresh Array,
+   *  - of which each element is coerced to String,
+   *  - which does not contain duplicates
+   *
+   * FIXME: keys trap is deprecated
+   */
+  /*
+  keys: function() {
+    var trap = this.getTrap("keys");
+    if (trap === undefined) {
+      // default forwarding behavior
+      return Reflect.keys(this.target);
+    }
+
+    var trapResult = trap.call(this.handler, this.target);
+
+    // propNames is used as a set of strings
+    var propNames = Object.create(null);
+    var numProps = +trapResult.length;
+    var result = new Array(numProps);
+
+    for (var i = 0; i < numProps; i++) {
+     var s = String(trapResult[i]);
+     if (propNames[s]) {
+       throw new TypeError("keys trap cannot list a "+
+                           "duplicate property '"+s+"'");
+     }
+     if (!Object.isExtensible(this.target) && !isFixed(s, this.target)) {
+       // non-extensible proxies don't tolerate new own property names
+       throw new TypeError("keys trap cannot list a new "+
+                           "property '"+s+"' on a non-extensible object");
+     }
+
+     propNames[s] = true;
+     result[i] = s;
+    }
+
+    var ownEnumerableProps = Object.keys(this.target);
+    var target = this.target;
+    ownEnumerableProps.forEach(function (ownEnumerableProp) {
+      if (!propNames[ownEnumerableProp]) {
+        if (isSealed(ownEnumerableProp, target)) {
+          throw new TypeError("keys trap failed to include "+
+                              "non-configurable enumerable property '"+
+                              ownEnumerableProp+"'");
+        }
+        if (!Object.isExtensible(target) &&
+            isFixed(ownEnumerableProp, target)) {
+            // if handler is allowed not to report ownEnumerableProp as an own
+            // property, we cannot guarantee that it will never report it as
+            // an own property later. Once a property has been reported as
+            // non-existent on a non-extensible object, it should forever be
+            // reported as non-existent
+            throw new TypeError("cannot report existing own property '"+
+                                ownEnumerableProp+"' as non-existent on a "+
+                                "non-extensible object");
+        }
+      }
+    });
+
+    return result;
+  },
+  */
+  
+  /**
+   * New trap that reifies [[Call]].
+   * If the target is a function, then a call to
+   *   proxy(...args)
+   * Triggers this trap
+   */
+  apply: function(target, thisBinding, args) {
+    var trap = this.getTrap("apply");
+    if (trap === undefined) {
+      return Reflect.apply(target, thisBinding, args);
+    }
+
+    if (typeof this.target === "function") {
+      return trap.call(this.handler, target, thisBinding, args);
+    } else {
+      throw new TypeError("apply: "+ target + " is not a function");
+    }
+  },
+
+  /**
+   * New trap that reifies [[Construct]].
+   * If the target is a function, then a call to
+   *   new proxy(...args)
+   * Triggers this trap
+   */
+  construct: function(target, args, newTarget) {
+    var trap = this.getTrap("construct");
+    if (trap === undefined) {
+      return Reflect.construct(target, args, newTarget);
+    }
+
+    if (typeof target !== "function") {
+      throw new TypeError("new: "+ target + " is not a function");
+    }
+
+    if (newTarget === undefined) {
+      newTarget = target;
+    } else {
+      if (typeof newTarget !== "function") {
+        throw new TypeError("new: "+ newTarget + " is not a function");
+      }      
+    }
+    return trap.call(this.handler, target, args, newTarget);
+  }
+};
+
+// ---- end of the Validator handler wrapper handler ----
+
+// In what follows, a 'direct proxy' is a proxy
+// whose handler is a Validator. Such proxies can be made non-extensible,
+// sealed or frozen without losing the ability to trap.
+
+// maps direct proxies to their Validator handlers
+var directProxies = new WeakMap();
+
+// patch Object.{preventExtensions,seal,freeze} so that
+// they recognize fixable proxies and act accordingly
+Object.preventExtensions = function(subject) {
+  var vhandler = directProxies.get(subject);
+  if (vhandler !== undefined) {
+    if (vhandler.preventExtensions()) {
+      return subject;
+    } else {
+      throw new TypeError("preventExtensions on "+subject+" rejected");
+    }
+  } else {
+    return prim_preventExtensions(subject);
+  }
+};
+Object.seal = function(subject) {
+  setIntegrityLevel(subject, "sealed");
+  return subject;
+};
+Object.freeze = function(subject) {
+  setIntegrityLevel(subject, "frozen");
+  return subject;
+};
+Object.isExtensible = Object_isExtensible = function(subject) {
+  var vHandler = directProxies.get(subject);
+  if (vHandler !== undefined) {
+    return vHandler.isExtensible();
+  } else {
+    return prim_isExtensible(subject);
+  }
+};
+Object.isSealed = Object_isSealed = function(subject) {
+  return testIntegrityLevel(subject, "sealed");
+};
+Object.isFrozen = Object_isFrozen = function(subject) {
+  return testIntegrityLevel(subject, "frozen");
+};
+Object.getPrototypeOf = Object_getPrototypeOf = function(subject) {
+  var vHandler = directProxies.get(subject);
+  if (vHandler !== undefined) {
+    return vHandler.getPrototypeOf();
+  } else {
+    return prim_getPrototypeOf(subject);
+  }
+};
+
+// patch Object.getOwnPropertyDescriptor to directly call
+// the Validator.prototype.getOwnPropertyDescriptor trap
+// This is to circumvent an assertion in the built-in Proxy
+// trapping mechanism of v8, which disallows that trap to
+// return non-configurable property descriptors (as per the
+// old Proxy design)
+Object.getOwnPropertyDescriptor = function(subject, name) {
+  var vhandler = directProxies.get(subject);
+  if (vhandler !== undefined) {
+    return vhandler.getOwnPropertyDescriptor(name);
+  } else {
+    return prim_getOwnPropertyDescriptor(subject, name);
+  }
+};
+
+// patch Object.defineProperty to directly call
+// the Validator.prototype.defineProperty trap
+// This is to circumvent two issues with the built-in
+// trap mechanism:
+// 1) the current tracemonkey implementation of proxies
+// auto-completes 'desc', which is not correct. 'desc' should be
+// normalized, but not completed. Consider:
+// Object.defineProperty(proxy, 'foo', {enumerable:false})
+// This trap will receive desc =
+//  {value:undefined,writable:false,enumerable:false,configurable:false}
+// This will also set all other attributes to their default value,
+// which is unexpected and different from [[DefineOwnProperty]].
+// Bug filed: https://bugzilla.mozilla.org/show_bug.cgi?id=601329
+// 2) the current spidermonkey implementation does not
+// throw an exception when this trap returns 'false', but instead silently
+// ignores the operation (this is regardless of strict-mode)
+// 2a) v8 does throw an exception for this case, but includes the rather
+//     unhelpful error message:
+// 'Proxy handler #<Object> returned false from 'defineProperty' trap'
+Object.defineProperty = function(subject, name, desc) {
+  var vhandler = directProxies.get(subject);
+  if (vhandler !== undefined) {
+    var normalizedDesc = normalizePropertyDescriptor(desc);
+    var success = vhandler.defineProperty(name, normalizedDesc);
+    if (success === false) {
+      throw new TypeError("can't redefine property '"+name+"'");
+    }
+    return subject;
+  } else {
+    return prim_defineProperty(subject, name, desc);
+  }
+};
+
+Object.defineProperties = function(subject, descs) {
+  var vhandler = directProxies.get(subject);
+  if (vhandler !== undefined) {
+    var names = Object.keys(descs);
+    for (var i = 0; i < names.length; i++) {
+      var name = names[i];
+      var normalizedDesc = normalizePropertyDescriptor(descs[name]);
+      var success = vhandler.defineProperty(name, normalizedDesc);
+      if (success === false) {
+        throw new TypeError("can't redefine property '"+name+"'");
+      }
+    }
+    return subject;
+  } else {
+    return prim_defineProperties(subject, descs);
+  }
+};
+
+Object.keys = function(subject) {
+  var vHandler = directProxies.get(subject);
+  if (vHandler !== undefined) {
+    var ownKeys = vHandler.ownKeys();
+    var result = [];
+    for (var i = 0; i < ownKeys.length; i++) {
+      var k = String(ownKeys[i]);
+      var desc = Object.getOwnPropertyDescriptor(subject, k);
+      if (desc !== undefined && desc.enumerable === true) {
+        result.push(k);
+      }
+    }
+    return result;
+  } else {
+    return prim_keys(subject);
+  }
+}
+
+Object.getOwnPropertyNames = Object_getOwnPropertyNames = function(subject) {
+  var vHandler = directProxies.get(subject);
+  if (vHandler !== undefined) {
+    return vHandler.ownKeys();
+  } else {
+    return prim_getOwnPropertyNames(subject);
+  }
+}
+
+// fixes issue #71 (Calling Object.getOwnPropertySymbols() on a Proxy
+// throws an error)
+if (prim_getOwnPropertySymbols !== undefined) {
+  Object.getOwnPropertySymbols = function(subject) {
+    var vHandler = directProxies.get(subject);
+    if (vHandler !== undefined) {
+      // as this shim does not support symbols, a Proxy never advertises
+      // any symbol-valued own properties
+      return [];
+    } else {
+      return prim_getOwnPropertySymbols(subject);
+    }
+  };
+}
+
+// fixes issue #72 ('Illegal access' error when using Object.assign)
+// Object.assign polyfill based on a polyfill posted on MDN: 
+// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/\
+//  Global_Objects/Object/assign
+// Note that this polyfill does not support Symbols, but this Proxy Shim
+// does not support Symbols anyway.
+if (prim_assign !== undefined) {
+  Object.assign = function (target) {
+    
+    // check if any argument is a proxy object
+    var noProxies = true;
+    for (var i = 0; i < arguments.length; i++) {
+      var vHandler = directProxies.get(arguments[i]);
+      if (vHandler !== undefined) {
+        noProxies = false;
+        break;
+      }
+    }
+    if (noProxies) {
+      // not a single argument is a proxy, perform built-in algorithm
+      return prim_assign.apply(Object, arguments);
+    }
+    
+    // there is at least one proxy argument, use the polyfill
+    
+    if (target === undefined || target === null) {
+      throw new TypeError('Cannot convert undefined or null to object');
+    }
+
+    var output = Object(target);
+    for (var index = 1; index < arguments.length; index++) {
+      var source = arguments[index];
+      if (source !== undefined && source !== null) {
+        for (var nextKey in source) {
+          if (source.hasOwnProperty(nextKey)) {
+            output[nextKey] = source[nextKey];
+          }
+        }
+      }
+    }
+    return output;
+  };
+}
+
+// returns whether an argument is a reference to an object,
+// which is legal as a WeakMap key.
+function isObject(arg) {
+  var type = typeof arg;
+  return (type === 'object' && arg !== null) || (type === 'function');
+};
+
+// a wrapper for WeakMap.get which returns the undefined value
+// for keys that are not objects (in which case the underlying
+// WeakMap would have thrown a TypeError).
+function safeWeakMapGet(map, key) {
+  return isObject(key) ? map.get(key) : undefined;
+};
+
+// returns a new function of zero arguments that recursively
+// unwraps any proxies specified as the |this|-value.
+// The primitive is assumed to be a zero-argument method
+// that uses its |this|-binding.
+function makeUnwrapping0ArgMethod(primitive) {
+  return function builtin() {
+    var vHandler = safeWeakMapGet(directProxies, this);
+    if (vHandler !== undefined) {
+      return builtin.call(vHandler.target);
+    } else {
+      return primitive.call(this);
+    }
+  }
+};
+
+// returns a new function of 1 arguments that recursively
+// unwraps any proxies specified as the |this|-value.
+// The primitive is assumed to be a 1-argument method
+// that uses its |this|-binding.
+function makeUnwrapping1ArgMethod(primitive) {
+  return function builtin(arg) {
+    var vHandler = safeWeakMapGet(directProxies, this);
+    if (vHandler !== undefined) {
+      return builtin.call(vHandler.target, arg);
+    } else {
+      return primitive.call(this, arg);
+    }
+  }
+};
+
+Object.prototype.valueOf =
+  makeUnwrapping0ArgMethod(Object.prototype.valueOf);
+Object.prototype.toString =
+  makeUnwrapping0ArgMethod(Object.prototype.toString);
+Function.prototype.toString =
+  makeUnwrapping0ArgMethod(Function.prototype.toString);
+Date.prototype.toString =
+  makeUnwrapping0ArgMethod(Date.prototype.toString);
+
+Object.prototype.isPrototypeOf = function builtin(arg) {
+  // bugfix thanks to Bill Mark:
+  // built-in isPrototypeOf does not unwrap proxies used
+  // as arguments. So, we implement the builtin ourselves,
+  // based on the ECMAScript 6 spec. Our encoding will
+  // make sure that if a proxy is used as an argument,
+  // its getPrototypeOf trap will be called.
+  while (true) {
+    var vHandler2 = safeWeakMapGet(directProxies, arg);
+    if (vHandler2 !== undefined) {
+      arg = vHandler2.getPrototypeOf();
+      if (arg === null) {
+        return false;
+      } else if (sameValue(arg, this)) {
+        return true;
+      }
+    } else {
+      return prim_isPrototypeOf.call(this, arg);
+    }
+  }
+};
+
+Array.isArray = function(subject) {
+  var vHandler = safeWeakMapGet(directProxies, subject);
+  if (vHandler !== undefined) {
+    return Array.isArray(vHandler.target);
+  } else {
+    return prim_isArray(subject);
+  }
+};
+
+function isProxyArray(arg) {
+  var vHandler = safeWeakMapGet(directProxies, arg);
+  if (vHandler !== undefined) {
+    return Array.isArray(vHandler.target);
+  }
+  return false;
+}
+
+// Array.prototype.concat internally tests whether one of its
+// arguments is an Array, by checking whether [[Class]] == "Array"
+// As such, it will fail to recognize proxies-for-arrays as arrays.
+// We patch Array.prototype.concat so that it "unwraps" proxies-for-arrays
+// by making a copy. This will trigger the exact same sequence of
+// traps on the proxy-for-array as if we would not have unwrapped it.
+// See <https://github.com/tvcutsem/harmony-reflect/issues/19> for more.
+Array.prototype.concat = function(/*...args*/) {
+  var length;
+  for (var i = 0; i < arguments.length; i++) {
+    if (isProxyArray(arguments[i])) {
+      length = arguments[i].length;
+      arguments[i] = Array.prototype.slice.call(arguments[i], 0, length);
+    }
+  }
+  return prim_concat.apply(this, arguments);
+};
+
+// setPrototypeOf support on platforms that support __proto__
+
+var prim_setPrototypeOf = Object.setPrototypeOf;
+
+// patch and extract original __proto__ setter
+var __proto__setter = (function() {
+  var protoDesc = prim_getOwnPropertyDescriptor(Object.prototype,'__proto__');
+  if (protoDesc === undefined ||
+      typeof protoDesc.set !== "function") {
+    return function() {
+      throw new TypeError("setPrototypeOf not supported on this platform");
+    }
+  }
+
+  // see if we can actually mutate a prototype with the generic setter
+  // (e.g. Chrome v28 doesn't allow setting __proto__ via the generic setter)
+  try {
+    protoDesc.set.call({},{});
+  } catch (e) {
+    return function() {
+      throw new TypeError("setPrototypeOf not supported on this platform");
+    }
+  }
+
+  prim_defineProperty(Object.prototype, '__proto__', {
+    set: function(newProto) {
+      return Object.setPrototypeOf(this, Object(newProto));
+    }
+  });
+
+  return protoDesc.set;
+}());
+
+Object.setPrototypeOf = function(target, newProto) {
+  var handler = directProxies.get(target);
+  if (handler !== undefined) {
+    if (handler.setPrototypeOf(newProto)) {
+      return target;
+    } else {
+      throw new TypeError("proxy rejected prototype mutation");
+    }
+  } else {
+    if (!Object_isExtensible(target)) {
+      throw new TypeError("can't set prototype on non-extensible object: " +
+                          target);
+    }
+    if (prim_setPrototypeOf)
+      return prim_setPrototypeOf(target, newProto);
+
+    if (Object(newProto) !== newProto || newProto === null) {
+      throw new TypeError("Object prototype may only be an Object or null: " +
+                         newProto);
+      // throw new TypeError("prototype must be an object or null")
+    }
+    __proto__setter.call(target, newProto);
+    return target;
+  }
+}
+
+Object.prototype.hasOwnProperty = function(name) {
+  var handler = safeWeakMapGet(directProxies, this);
+  if (handler !== undefined) {
+    var desc = handler.getOwnPropertyDescriptor(name);
+    return desc !== undefined;
+  } else {
+    return prim_hasOwnProperty.call(this, name);
+  }
+}
+
+// ============= Reflection module =============
+// see http://wiki.ecmascript.org/doku.php?id=harmony:reflect_api
+
+var Reflect = {
+  getOwnPropertyDescriptor: function(target, name) {
+    return Object.getOwnPropertyDescriptor(target, name);
+  },
+  defineProperty: function(target, name, desc) {
+
+    // if target is a proxy, invoke its "defineProperty" trap
+    var handler = directProxies.get(target);
+    if (handler !== undefined) {
+      return handler.defineProperty(target, name, desc);
+    }
+
+    // Implementation transliterated from [[DefineOwnProperty]]
+    // see ES5.1 section 8.12.9
+    // this is the _exact same algorithm_ as the isCompatibleDescriptor
+    // algorithm defined above, except that at every place it
+    // returns true, this algorithm actually does define the property.
+    var current = Object.getOwnPropertyDescriptor(target, name);
+    var extensible = Object.isExtensible(target);
+    if (current === undefined && extensible === false) {
+      return false;
+    }
+    if (current === undefined && extensible === true) {
+      Object.defineProperty(target, name, desc); // should never fail
+      return true;
+    }
+    if (isEmptyDescriptor(desc)) {
+      return true;
+    }
+    if (isEquivalentDescriptor(current, desc)) {
+      return true;
+    }
+    if (current.configurable === false) {
+      if (desc.configurable === true) {
+        return false;
+      }
+      if ('enumerable' in desc && desc.enumerable !== current.enumerable) {
+        return false;
+      }
+    }
+    if (isGenericDescriptor(desc)) {
+      // no further validation necessary
+    } else if (isDataDescriptor(current) !== isDataDescriptor(desc)) {
+      if (current.configurable === false) {
+        return false;
+      }
+    } else if (isDataDescriptor(current) && isDataDescriptor(desc)) {
+      if (current.configurable === false) {
+        if (current.writable === false && desc.writable === true) {
+          return false;
+        }
+        if (current.writable === false) {
+          if ('value' in desc && !sameValue(desc.value, current.value)) {
+            return false;
+          }
+        }
+      }
+    } else if (isAccessorDescriptor(current) && isAccessorDescriptor(desc)) {
+      if (current.configurable === false) {
+        if ('set' in desc && !sameValue(desc.set, current.set)) {
+          return false;
+        }
+        if ('get' in desc && !sameValue(desc.get, current.get)) {
+          return false;
+        }
+      }
+    }
+    Object.defineProperty(target, name, desc); // should never fail
+    return true;
+  },
+  deleteProperty: function(target, name) {
+    var handler = directProxies.get(target);
+    if (handler !== undefined) {
+      return handler.delete(name);
+    }
+    
+    var desc = Object.getOwnPropertyDescriptor(target, name);
+    if (desc === undefined) {
+      return true;
+    }
+    if (desc.configurable === true) {
+      delete target[name];
+      return true;
+    }
+    return false;    
+  },
+  getPrototypeOf: function(target) {
+    return Object.getPrototypeOf(target);
+  },
+  setPrototypeOf: function(target, newProto) {
+    
+    var handler = directProxies.get(target);
+    if (handler !== undefined) {
+      return handler.setPrototypeOf(newProto);
+    }
+    
+    if (Object(newProto) !== newProto || newProto === null) {
+      throw new TypeError("Object prototype may only be an Object or null: " +
+                         newProto);
+    }
+    
+    if (!Object_isExtensible(target)) {
+      return false;
+    }
+    
+    var current = Object.getPrototypeOf(target);
+    if (sameValue(current, newProto)) {
+      return true;
+    }
+    
+    if (prim_setPrototypeOf) {
+      try {
+        prim_setPrototypeOf(target, newProto);
+        return true;
+      } catch (e) {
+        return false;
+      }
+    }
+
+    __proto__setter.call(target, newProto);
+    return true;
+  },
+  preventExtensions: function(target) {
+    var handler = directProxies.get(target);
+    if (handler !== undefined) {
+      return handler.preventExtensions();
+    }
+    prim_preventExtensions(target);
+    return true;
+  },
+  isExtensible: function(target) {
+    return Object.isExtensible(target);
+  },
+  has: function(target, name) {
+    return name in target;
+  },
+  get: function(target, name, receiver) {
+    receiver = receiver || target;
+
+    // if target is a proxy, invoke its "get" trap
+    var handler = directProxies.get(target);
+    if (handler !== undefined) {
+      return handler.get(receiver, name);
+    }
+
+    var desc = Object.getOwnPropertyDescriptor(target, name);
+    if (desc === undefined) {
+      var proto = Object.getPrototypeOf(target);
+      if (proto === null) {
+        return undefined;
+      }
+      return Reflect.get(proto, name, receiver);
+    }
+    if (isDataDescriptor(desc)) {
+      return desc.value;
+    }
+    var getter = desc.get;
+    if (getter === undefined) {
+      return undefined;
+    }
+    return desc.get.call(receiver);
+  },
+  // Reflect.set implementation based on latest version of [[SetP]] at
+  // http://wiki.ecmascript.org/doku.php?id=harmony:proto_climbing_refactoring
+  set: function(target, name, value, receiver) {
+    receiver = receiver || target;
+
+    // if target is a proxy, invoke its "set" trap
+    var handler = directProxies.get(target);
+    if (handler !== undefined) {
+      return handler.set(receiver, name, value);
+    }
+
+    // first, check whether target has a non-writable property
+    // shadowing name on receiver
+    var ownDesc = Object.getOwnPropertyDescriptor(target, name);
+
+    if (ownDesc === undefined) {
+      // name is not defined in target, search target's prototype
+      var proto = Object.getPrototypeOf(target);
+
+      if (proto !== null) {
+        // continue the search in target's prototype
+        return Reflect.set(proto, name, value, receiver);
+      }
+
+      // Rev16 change. Cf. https://bugs.ecmascript.org/show_bug.cgi?id=1549
+      // target was the last prototype, now we know that 'name' is not shadowed
+      // by an existing (accessor or data) property, so we can add the property
+      // to the initial receiver object
+      // (this branch will intentionally fall through to the code below)
+      ownDesc =
+        { value: undefined,
+          writable: true,
+          enumerable: true,
+          configurable: true };
+    }
+
+    // we now know that ownDesc !== undefined
+    if (isAccessorDescriptor(ownDesc)) {
+      var setter = ownDesc.set;
+      if (setter === undefined) return false;
+      setter.call(receiver, value); // assumes Function.prototype.call
+      return true;
+    }
+    // otherwise, isDataDescriptor(ownDesc) must be true
+    if (ownDesc.writable === false) return false;
+    // we found an existing writable data property on the prototype chain.
+    // Now update or add the data property on the receiver, depending on
+    // whether the receiver already defines the property or not.
+    var existingDesc = Object.getOwnPropertyDescriptor(receiver, name);
+    if (existingDesc !== undefined) {
+      var updateDesc =
+        { value: value,
+          // FIXME: it should not be necessary to describe the following
+          // attributes. Added to circumvent a bug in tracemonkey:
+          // https://bugzilla.mozilla.org/show_bug.cgi?id=601329
+          writable:     existingDesc.writable,
+          enumerable:   existingDesc.enumerable,
+          configurable: existingDesc.configurable };
+      Object.defineProperty(receiver, name, updateDesc);
+      return true;
+    } else {
+      if (!Object.isExtensible(receiver)) return false;
+      var newDesc =
+        { value: value,
+          writable: true,
+          enumerable: true,
+          configurable: true };
+      Object.defineProperty(receiver, name, newDesc);
+      return true;
+    }
+  },
+  /*invoke: function(target, name, args, receiver) {
+    receiver = receiver || target;
+
+    var handler = directProxies.get(target);
+    if (handler !== undefined) {
+      return handler.invoke(receiver, name, args);
+    }
+
+    var fun = Reflect.get(target, name, receiver);
+    return Function.prototype.apply.call(fun, receiver, args);
+  },*/
+  enumerate: function(target) {
+    var handler = directProxies.get(target);
+    var result;
+    if (handler !== undefined) {
+      // handler.enumerate should return an iterator directly, but the
+      // iterator gets converted to an array for backward-compat reasons,
+      // so we must re-iterate over the array
+      result = handler.enumerate(handler.target);
+    } else {
+      result = [];
+      for (var name in target) { result.push(name); };      
+    }
+    var l = +result.length;
+    var idx = 0;
+    return {
+      next: function() {
+        if (idx === l) return { done: true };
+        return { done: false, value: result[idx++] };
+      }
+    };
+  },
+  // imperfect ownKeys implementation: in ES6, should also include
+  // symbol-keyed properties.
+  ownKeys: function(target) {
+    return Object_getOwnPropertyNames(target);
+  },
+  apply: function(target, receiver, args) {
+    // target.apply(receiver, args)
+    return Function.prototype.apply.call(target, receiver, args);
+  },
+  construct: function(target, args, newTarget) {
+    // return new target(...args);
+
+    // if target is a proxy, invoke its "construct" trap
+    var handler = directProxies.get(target);
+    if (handler !== undefined) {
+      return handler.construct(handler.target, args, newTarget);
+    }
+    
+    if (typeof target !== "function") {
+      throw new TypeError("target is not a function: " + target);
+    }
+    if (newTarget === undefined || newTarget === target) {
+      // If newTarget is undefined, then newTarget is set to `target` and
+      // `Reflect.construct(target, ...args)` becomes equivalent to
+      // `new target(...args)`
+      // if `target` is an ES2015 Class constructor, it must be called using
+      // the `new` operator. Hence we use the new operator on a bound function
+      // to trigger the [[Construct]] internal method. This technique will work 
+      // for both plain constructor functions and ES2015 classes
+      return new (Function.prototype.bind.apply(target, [null].concat(args)));
+    } else {
+      if (typeof newTarget !== "function") {
+        throw new TypeError("newTarget is not a function: " + target);
+      }
+      // if newTarget is a *different* constructor function, we need to
+      // emulate [[Construct]] by falling back to [[Call]] with a hand-crafted
+      // new instance inheriting from newTarget.prototype
+      // Unfortunately this won't work if target is an ES2015 Constructor
+      // function, whose [[Call]] method throws an error (it must be invoked
+      // using the `new` operator)
+      var proto = newTarget.prototype;
+      var instance = (Object(proto) === proto) ? Object.create(proto) : {};
+      var result = Function.prototype.apply.call(target, instance, args);
+      return Object(result) === result ? result : instance;
+    }
+  }
+};
+
+// feature-test whether the Reflect global exists
+if (global.Reflect !== undefined) {
+  // Reflect exists, add/override the shimmed methods
+  Object.getOwnPropertyNames(Reflect).forEach(function (key) {
+    global.Reflect[key] = Reflect[key];
+  });
+} else {
+  // Reflect doesn't exist, define it as the shimmed Reflect object
+  global.Reflect = Reflect;
+}
+
+// feature-test whether the Proxy global exists, with
+// the harmony-era Proxy.create API
+if (typeof Proxy !== "undefined" &&
+    typeof Proxy.create !== "undefined") {
+
+  var primCreate = Proxy.create,
+      primCreateFunction = Proxy.createFunction;
+
+  var revokedHandler = primCreate({
+    get: function() { throw new TypeError("proxy is revoked"); }
+  });
+
+  global.Proxy = function(target, handler) {
+    // check that target is an Object
+    if (Object(target) !== target) {
+      throw new TypeError("Proxy target must be an Object, given "+target);
+    }
+    // check that handler is an Object
+    if (Object(handler) !== handler) {
+      throw new TypeError("Proxy handler must be an Object, given "+handler);
+    }
+
+    var vHandler = new Validator(target, handler);
+    var proxy;
+    if (typeof target === "function") {
+      proxy = primCreateFunction(vHandler,
+        // call trap
+        function() {
+          var args = Array.prototype.slice.call(arguments);
+          return vHandler.apply(target, this, args);
+        },
+        // construct trap
+        function() {
+          var args = Array.prototype.slice.call(arguments);
+          return vHandler.construct(target, args);
+        });
+    } else {
+      proxy = primCreate(vHandler, Object.getPrototypeOf(target));
+    }
+    directProxies.set(proxy, vHandler);
+    return proxy;
+  };
+
+  global.Proxy.revocable = function(target, handler) {
+    var proxy = new Proxy(target, handler);
+    var revoke = function() {
+      var vHandler = directProxies.get(proxy);
+      if (vHandler !== null) {
+        vHandler.target  = null;
+        vHandler.handler = revokedHandler;
+      }
+      return undefined;
+    };
+    return {proxy: proxy, revoke: revoke};
+  }
+  
+  // add the old Proxy.create and Proxy.createFunction methods
+  // so old code that still depends on the harmony-era Proxy object
+  // is not broken. Also ensures that multiple versions of this
+  // library should load fine
+  global.Proxy.create = primCreate;
+  global.Proxy.createFunction = primCreateFunction;
+
+} else {
+  // Proxy global not defined, or old API not available
+  if (typeof Proxy === "undefined") {
+    // Proxy global not defined, add a Proxy function stub
+    global.Proxy = function(_target, _handler) {
+      throw new Error("proxies not supported on this platform. On v8/node/iojs, make sure to pass the --harmony_proxies flag");
+    };
+  }
+  // Proxy global defined but old API not available
+  // presumably Proxy global already supports new API, leave untouched
+}
+
+// for node.js modules, export every property in the Reflect object
+// as part of the module interface
+if (typeof exports !== 'undefined') {
+  Object.keys(Reflect).forEach(function (key) {
+    exports[key] = Reflect[key];
+  });
+}
+
+// function-as-module pattern
+}(typeof exports !== 'undefined' ? global : this));
