Remove frozen realm
MODIFY
.travis.yml
.travis.yml
@@ -8,9 +8,9 @@ node_js:
sudo: false
script:
- - yarn lint-shim
- - yarn build-shim
- - yarn test-shim
+ - yarn shim:lint
+ - yarn shim:build
+ - yarn shim:test
branches:
only:

MODIFY
README.md
README.md
@@ -20,7 +20,7 @@ You can view the spec rendered as [HTML](https://rawgit.com/tc39/proposal-realms
A shim implementation of the Realm API can be found [here](shim/README.md).
-You can play around with the current version of the shim in a Realm [here](https://rawgit.com/tc39/proposal-realms/master/shim/examples/simple.html) and in a Frozen Realm [here](https://rawgit.com/tc39/proposal-realms/master/shim/examples/frozen.html).
+You can play around with the current version of the shim in a Realm [here](https://rawgit.com/tc39/proposal-realms/master/shim/examples/simple.html).
# Realms

MODIFY
package.json
package.json
"scripts": {
"build": "ecmarkup spec/index.emu index.html --css ecmarkup.css --js ecmarkup.js",
"watch": "ecmarkup --watch spec/index.emu index.html --css ecmarkup.css --js ecmarkup.js",
- "build-shim": "yarn build-shim-dev && yarn build-shim-prod",
- "build-shim-watch": "yarn run build-shim-dev --watch",
- "build-shim-dev": "cross-env NODE_ENV=development rollup -c shim/rollup.config.js",
- "build-shim-prod": "cross-env NODE_ENV=production rollup -c shim/rollup.config.js",
- "lint-shim": "eslint ./shim/src/**/*.js ./shim/test/**/*.js",
- "prettier-shim": "prettier --config ./shim/.prettierrc --write ./shim/src/**/*.js ./shim/test/**/*.js",
- "test-shim": "tape -r esm ./shim/test/**/*.js"
+ "shim:build": "yarn shim:build:dev && yarn shim:build:prod",
+ "shim:watch": "yarn run shim:build:dev --watch",
+ "shim:build:dev": "cross-env NODE_ENV=development rollup -c shim/rollup.config.js",
+ "shim:build:prod": "cross-env NODE_ENV=production rollup -c shim/rollup.config.js",
+ "shim:lint": "eslint ./shim/src/**/*.js ./shim/test/**/*.js",
+ "shim:prettier": "prettier --config ./shim/.prettierrc --write ./shim/src/**/*.js ./shim/test/**/*.js",
+ "shim:test": "tape -r esm ./shim/test/**/*.js"
},
"repository": {
"type": "git",

MODIFY
shim/README.md
shim/README.md
@@ -95,28 +95,6 @@ r.global === this; // false
r.global.JSON === JSON; // true
```
-### Example 4: Frozen realm
-
-To create a frozen realm:
-
-```js
-const r = new Realm(); // root realm
-r.freeze();
-'use strict'; // disable silent errors
-r.evaluate('[].__proto__.slice = function(){}'); // TypeError: Cannot assign to read only property 'parse'
-```
-
-### Example 5: Frozen realm from current Realm (careful)
-
-To create a frozen realm compartment from the current execution context (which will also become frozen):
-
-```js
-const r = new Realm({ intrinsics: 'inherit' }); // realm compartment
-r.freeze()
-'use strict'; // disable silent errors
-[].__proto__.slice = function(){}; // TypeError: Cannot assign to read only property 'slice'
-```
-
[travis-svg]: https://travis-ci.com/tc39/proposal-realms.svg?branch=master
[travis-url]: https://travis-ci.com/tc39/proposal-realms
[license-image]: https://img.shields.io/badge/License-Apache%202.0-blue.svg

DELETE
shim/examples/frozen.html
-<html>
- <header>
- <script src="../dist/realm-shim.js"></script>
- </header>
- <body>
- <h1>Frozen Realm Shim</h1>
- <p>
- This demo show allow you to evaluate code inside a frozen Realm:
- </p>
- Input:<br />
- <textarea id="sourceText" rows="20" cols="80"></textarea><br />
- <button id="run">Evaluate</button><br />
- Output:<br />
- <textarea id="output" disabled="disabled" rows="20" cols="80"></textarea>
- <p>
- <small>Note: you can look in the console to inspect the original output of the evaluation.</small>
- </p>
- <script src="frozen.js"></script>
- </body>
-</html>
\ No newline at end of file

DELETE
shim/examples/frozen.js
-/* global Realm */
-/* eslint no-self-compare: "off" */
-
-// basic sanity check: they all should output true or error
-const r = new Realm();
-r.freeze();
-
-console.log(1, r.evaluate(`try { [].__proto__.slice = function(){} } catch(e) { e }`));
-console.log(2, r.evaluate(`typeof Array.prototype.foo === 'function';`));
-console.log(3, r.evaluate(`try { Map.prototype.set = function(){} } catch(e) { e }`));
-
-document.getElementById('run').addEventListener('click', () => {
- const sourceText = document.getElementById('sourceText').value;
- let result, output;
- try {
- result = r.evaluate(sourceText);
- } catch (e) {
- result = `Error: ${e}`;
- }
- try {
- output = typeof result === 'function' ? result.toString() : JSON.stringify(result);
- } catch (e) {
- output = `Error trying to serialize the result: ${e}\nOriginal Object: ${result}`;
- }
- console.log(result);
- document.getElementById('output').value = output;
-});

DELETE
shim/src/deep-freeze.js
-// Adapted from SES/Caja - Copyright (C) 2011 Google Inc.
-// https://github.com/google/caja/blob/master/src/com/google/caja/ses/startSES.js
-// https://github.com/google/caja/blob/master/src/com/google/caja/ses/repairES5.js
-
-// Mitigate proxy-related security issues
-// https://github.com/tc39/ecma262/issues/272
-
-import { freeze, getOwnPropertyDescriptors, getPrototypeOf, ownKeys } from './commons';
-
-// Objects that are deeply frozen.
-const frozenSet = new WeakSet();
-
-/**
- * "deepFreeze()" acts like "Object.freeze()", except that:
- *
- * To deepFreeze an object is to freeze it and all objects transitively
- * reachable from it via transitive reflective property and prototype
- * traversal.
- */
-export function deepFreeze(node) {
- // Objects that we have frozen in this round.
- const freezingSet = new Set();
-
- // If val is something we should be freezing but aren't yet,
- // add it to freezingSet.
- function enqueue(val) {
- if (Object(val) !== val) {
- // ignore primitives
- return;
- }
- const type = typeof val;
- if (type !== 'object' && type !== 'function') {
- // future proof: break until someone figures out what it should do
- throw new TypeError(`Unexpected typeof: ${type}`);
- }
- if (frozenSet.has(val) || freezingSet.has(val)) {
- // Ignore if already frozen or freezing
- return;
- }
- freezingSet.add(val);
- }
-
- function doFreeze(obj) {
- // Immediately freeze the object to ensure reactive
- // objects such as proxies won't add properties
- // during traversal, before they get frozen.
-
- // Object are verified before being enqueued,
- // therefore this is a valid candidate.
- // Throws if this fails (strict mode).
- freeze(obj);
-
- enqueue(getPrototypeOf(obj));
- const descs = getOwnPropertyDescriptors(obj);
- ownKeys(descs).forEach(name => {
- const desc = descs[name];
- if ('value' in desc) {
- enqueue(desc.value);
- } else {
- enqueue(desc.get);
- enqueue(desc.set);
- }
- });
- }
-
- function dequeue() {
- // New values added before forEach() has finished will be visited.
- freezingSet.forEach(doFreeze);
- }
-
- function commit() {
- freezingSet.forEach(frozenSet.add, frozenSet);
- }
-
- enqueue(node);
- dequeue();
- commit();
-}

MODIFY
shim/src/realm.js
shim/src/realm.js
@@ -2,8 +2,6 @@ import { createContextRec, getCurrentContextRec } from './context';
import { getDirectEvalEvaluator, getFunctionEvaluator } from './evaluators';
import { getStdLib } from './stdlib';
import { getIntrinsics } from './intrinsics';
-import { tamperProofDataProperties } from './tamper-proof';
-import { deepFreeze } from './deep-freeze';
import { IsCallable } from './utils';
import { assign, create, defineProperty, defineProperties, getPrototypeOf } from './commons';
import { Intrinsics, GlobalObject, IsDirectEvalTrap, ContextRec } from './symbols';
@@ -161,21 +159,6 @@ export default class Realm {
const evaluator = realmRec[IsDirectEvalTrap];
return evaluator(x);
}
- // This is a temporary addition, currenly being evaluated.
- freeze() {
- const O = this;
- if (typeof O !== 'object') throw new TypeError();
- if (!Realm2RealmRec.has(O)) throw new TypeError();
- const realmRec = Realm2RealmRec.get(O);
-
- // Copy the intrinsics into a plain object to avoid
- // freezing the object itself.
- const obj = create(null);
- const intrinsics = realmRec[Intrinsics];
- assign(obj, intrinsics);
- tamperProofDataProperties(obj);
- deepFreeze(obj);
- }
}
RealmProto2ContextRec.set(Realm.prototype, getCurrentContextRec());

DELETE
shim/src/tamper-proof.js
-// Adapted from SES/Caja
-// Copyright (C) 2011 Google Inc.
-// https://github.com/google/caja/blob/master/src/com/google/caja/ses/startSES.js
-// https://github.com/google/caja/blob/master/src/com/google/caja/ses/repairES5.js
-
-import {
- defineProperty,
- getOwnPropertyDescriptor,
- getOwnPropertyDescriptors,
- objectHasOwnProperty
-} from './commons';
-
-/**
- * For a special set of properties (defined below), it ensures that the
- * effect of freezing does not suppress the ability to override these
- * properties on derived objects by simple assignment.
- *
- * Because of lack of sufficient foresight at the time, ES5 unfortunately
- * specified that a simple assignment to a non-existent property must fail if
- * it would override a non-writable data property of the same name. (In
- * retrospect, this was a mistake, but it is now too late and we must live
- * with the consequences.) As a result, simply freezing an object to make it
- * tamper proof has the unfortunate side effect of breaking previously correct
- * code that is considered to have followed JS best practices, if this
- * previous code used assignment to override.
- *
- * To work around this mistake, deepFreeze(), prior to freezing, replaces
- * selected configurable own data properties with accessor properties which
- * simulate what we should have specified -- that assignments to derived
- * objects succeed if otherwise possible.
- */
-function tamperProof(obj, prop, desc) {
- if ('value' in desc && desc.configurable) {
- const value = desc.value;
-
- // eslint-disable-next-line no-inner-declarations
- function getter() {
- return value;
- }
-
- // Re-attach the data property on the object so
- // it can be found by the deep-freeze traversal process.
- getter.value = value;
-
- // eslint-disable-next-line no-inner-declarations
- function setter(newValue) {
- if (obj === this) {
- throw new TypeError(`Cannot assign to read only property '${prop}' of object '${obj}'`);
- }
- if (objectHasOwnProperty.call(this, prop)) {
- this[prop] = newValue;
- } else {
- defineProperty(this, prop, {
- value: newValue,
- writable: true,
- enumerable: desc.enumerable,
- configurable: desc.configurable
- });
- }
- }
-
- defineProperty(obj, prop, {
- get: getter,
- set: setter,
- enumerable: desc.enumerable,
- configurable: desc.configurable
- });
- }
-}
-
-function tamperProofProperties(obj) {
- const descs = getOwnPropertyDescriptors(obj);
- for (const prop in descs) {
- const desc = descs[prop];
- tamperProof(obj, prop, desc);
- }
-}
-
-function tamperProofProperty(obj, prop) {
- const desc = getOwnPropertyDescriptor(obj, prop);
- tamperProof(obj, prop, desc);
-}
-
-/**
- * These properties are subject to the override mistake
- * and must be converted before freezing.
- */
-export function tamperProofDataProperties(intrinsics) {
- const i = intrinsics;
-
- [i.ObjectPrototype, i.ArrayPrototype, i.FunctionPrototype].forEach(tamperProofProperties);
-
- // Intentionally avoid loops and data structures.
- tamperProofProperty(i.ErrorPrototype, 'message');
- tamperProofProperty(i.EvalErrorPrototype, 'message');
- tamperProofProperty(i.RangeErrorPrototype, 'message');
- tamperProofProperty(i.ReferenceErrorPrototype, 'message');
- tamperProofProperty(i.SyntaxErrorPrototype, 'message');
- tamperProofProperty(i.TypeErrorPrototype, 'message');
- tamperProofProperty(i.URIErrorPrototype, 'message');
-}

Remove frozen realm