Revision: 4222
Author: metaweta
Date: Fri Aug 6 12:27:35 2010
Log: Fix some SES bugs.
http://codereview.appspot.com/1664059
Exposes more of the ___ API in preparation for working
with Domita, fixes some bugs.
[email protected]
http://code.google.com/p/google-caja/source/detail?r=4222
Modified:
/trunk/src/com/google/caja/ses.js
=======================================
--- /trunk/src/com/google/caja/ses.js Tue Aug 3 22:08:45 2010
+++ /trunk/src/com/google/caja/ses.js Fri Aug 6 12:27:35 2010
@@ -38,7 +38,7 @@
var ___, ses, safeJSON, AS_TAMED___, AS_FERAL___;
(function () {
- // ES5/3 does not support FF2 or 3.0 because of
+ // ES5/3 does not support FF2 thru 3.5 because of
// https://bugzilla.mozilla.org/show_bug.cgi?id=507453
if (arguments[-2] !== void 0) {
// TODO: Make this an error.
@@ -46,12 +46,14 @@
'on arguments are not supported.');
}
- // Provide original definitions for closures.
+ // Provide original definitions for safe use.
var Object___ = Object;
var Array___ = Array;
var String___ = String;
var Number___ = Number;
var Boolean___ = Boolean;
+ var Error___ = Error;
+ var TypeError___ = TypeError;
/**
* Caja-specific properties
@@ -173,11 +175,11 @@
function tamesTo(f, t) {
var ftype = typeof f;
if (!f || (ftype !== 'function' && ftype !== 'object')) {
- throw new TypeError('Unexpected feral primitive: ', f);
+ throw new TypeError___('Unexpected feral primitive: ', f);
}
var ttype = typeof t;
if (!t || (ttype !== 'function' && ttype !== 'object')) {
- throw new TypeError('Unexpected tame primitive: ', t);
+ throw new TypeError___('Unexpected tame primitive: ', t);
}
if (f.TAMED_TWIN___ === t && t.FERAL_TWIN___ === f) {
@@ -194,16 +196,16 @@
// the backpointing rather than hasOwnProp below.
if (f.TAMED_TWIN___ && f.hasOwnProperty___('TAMED_TWIN___')) {
- throw new TypeError('Already tames to something: ', f);
+ throw new TypeError___('Already tames to something: ', f);
}
if (t.FERAL_TWIN___ && t.hasOwnProperty___('FERAL_TWIN___')) {
- throw new TypeError('Already untames to something: ', t);
+ throw new TypeError___('Already untames to something: ', t);
}
if (f.FERAL_TWIN___ && f.hasOwnProperty___('FERAL_TWIN___')) {
- throw new TypeError('Already tame: ', f);
+ throw new TypeError___('Already tame: ', f);
}
if (t.TAMED_TWIN___ && t.hasOwnProperty___('TAMED_TWIN___')) {
- throw new TypeError('Already feral: ', t);
+ throw new TypeError___('Already feral: ', t);
}
f.TAMED_TWIN___ = t;
@@ -222,7 +224,7 @@
function tamesToSelf(obj) {
var otype = typeof obj;
if (!obj || (otype !== 'function' && otype !== 'object')) {
- throw new TypeError('Unexpected primitive: ', obj);
+ throw new TypeError___('Unexpected primitive: ', obj);
}
if (obj.TAMED_TWIN___ === obj && obj.FERAL_TWIN___ === obj) {
// Just a transient diagnostic until we understand how often
@@ -237,10 +239,10 @@
// could decide to more delicately rely on this invariant and test
// the backpointing rather than hasOwnProp below.
if (obj.TAMED_TWIN___ && obj.hasOwnProperty___('TAMED_TWIN___')) {
- throw new TypeError('Already tames to something: ', obj);
+ throw new TypeError___('Already tames to something: ', obj);
}
if (obj.FERAL_TWIN___ && obj.hasOwnProperty___('FERAL_TWIN___')) {
- throw new TypeError('Already untames to something: ', obj);
+ throw new TypeError___('Already untames to something: ', obj);
}
obj.TAMED_TWIN___ = obj.FERAL_TWIN___ = obj;
@@ -357,17 +359,90 @@
}
return undefined;
}
+
+ /**
+ * Initialize argument constructor <i>feralCtor</i> so that it
+ * represents a "subclass" of argument constructor <i>someSuper</i>,
+ * and return a non-invokable taming of <i>feralCtor</i>.
+ *
+ * Given:
+ *
+ * function FeralFoo() { ... some uncajoled constructor ... }
+ * var Foo = extend(FeralFoo, FeralSuper, 'Foo');
+ *
+ * it will be the case that:
+ *
+ * new FeralFoo() instanceof Foo
+ *
+ * however -- and this is the crucial property -- cajoled code will get
an
+ * error if it invokes either of:
+ *
+ * new Foo()
+ * Foo()
+ *
+ * This allows us to expose the tame Foo to cajoled code, allowing
+ * it to sense that all the FeralFoo instances we give it are
+ * instanceof Foo, without granting to cajoled code the means to
+ * create any new such instances.
+ *
+ * extend() also sets <i>feralCtor</i>.prototype to set up the
+ * prototype chain so that
+ *
+ * new FeralFoo() instanceof FeralSuper
+ * and
+ * new FeralFoo() instanceof Super
+ *
+ * @param feralCtor An feral-only uncajoled constructor. This must
+ * NOT be exposed to cajoled code by any other mechanism.
+ * @param someSuper Some constructor representing the
+ * superclass. This can be <ul>
+ * <li>a feralCtor that had been provided as a first argument
+ * in a previous call to extend(),
+ * <li>an inertCtor as returned by a previous call to
+ * extend(), or
+ * <li>a constructor that has been marked as such by
___.markCtor().
+ * </ul>
+ * In all cases, someSuper.prototype.constructor must be
+ * a constructor that has been marked as such by
+ * ___.markCtor().
+ * @param opt_name If the returned inert constructor is made
+ * available this should be the property name used.
+ *
+ * @return a tame inert class constructor as described above.
+ */
+ function extend(feralCtor, someSuper, opt_name) {
+ if (!('function' === typeof feralCtor)) {
+ fail('Internal: Feral constructor is not a function');
+ }
+ someSuper = someSuper.prototype.constructor;
+ var noop = function () {};
+ if (someSuper.new___ === noop.new___) {
+ throw new TypeError___('Internal: toxic function encountered!');
+ }
+ noop.prototype = someSuper.prototype;
+ feralCtor.prototype = new noop();
+ feralCtor.prototype.Prototype___ = someSuper.prototype;
+
+ var inert = function() {
+ throw new TypeError___('This constructor cannot be called
directly.');
+ };
+
+ inert.prototype = feralCtor.prototype;
+ feralCtor.prototype.constructor = inert;
+ tamesTo(feralCtor, inert);
+ return markFuncFreeze(inert);
+ }
////////////////////////////////////////////////////////////////////////
// Taming helpers to be called only by tame() and untame().
////////////////////////////////////////////////////////////////////////
AS_TAMED___ = function() {
- throw new Error('Internal: global object almost leaked');
+ throw new Error___('Internal: global object almost leaked');
};
AS_FERAL___ = function() {
- var err = new Error('Internal: global object leaked');
+ var err = new Error___('Internal: global object leaked');
err.UNCATCHABLE___ = true;
throw err;
};
@@ -467,7 +542,7 @@
Array.prototype.length_s___ = function (val) {
// Freezing an array needs to freeze the length property.
if (this.z___ === this) {
- throw new TypeError('Cannot change the length of a frozen array.');
+ throw new TypeError___('Cannot change the length of a frozen
array.');
}
val = ToUint32(val);
// Since increasing the length does not add properties,
@@ -480,7 +555,7 @@
if (!this.hasNumerics___() || this.NUM____c___ === this) {
return this.length = val;
}
- throw new TypeError(
+ throw new TypeError___(
'Shortening the array may delete non-configurable elements.');
};
@@ -532,7 +607,7 @@
if (dis === null || dis === void 0) { return USELESS; }
if (Type(dis) !== 'Object') { return dis; }
if ('___' in dis) {
- var err = new Error('Internal: toxic global!');
+ var err = new Error___('Internal: toxic global!');
err.UNCATCHABLE___ = true;
throw err;
}
@@ -564,12 +639,12 @@
function assertValidPropertyName(P) {
if (endsWith__.test(P)) {
- throw new TypeError('Properties may not end in double underscore.');
+ throw new TypeError___('Properties may not end in double
underscore.');
}
}
function callFault(var_args) {
- var err = new Error('Internal: toxic function encountered!');
+ var err = new Error___('Internal: toxic function encountered!');
err.UNCATCHABLE___ = true;
throw err;
}
@@ -697,7 +772,7 @@
// Array.prototype.peek = function () { return this[0]; }
function markFunc(fn) {
if (!isFunction(fn)) {
- throw new TypeError('Expected a function.');
+ throw new TypeError___('Expected a function.');
}
fn.f___ = fn.apply___;
fn.new___ = fn;
@@ -987,7 +1062,7 @@
stringify: markFunc(function (obj, opt_replacer, opt_space) {
switch (typeof opt_space) {
case 'number': case 'string': case 'undefined': break;
- default: throw new TypeError('space must be a number or string');
+ default: throw new TypeError___('space must be a number or
string');
}
var replacer;
if (opt_replacer) {
@@ -1060,7 +1135,7 @@
* </pre>
*/
function enforce(test, var_args) {
- if (!test) { throw new Error(Array___.slice___(arguments,
1).join('')); }
+ if (!test) { throw new Error___(Array___.slice___(arguments,
1).join('')); }
return true;
}
@@ -1074,9 +1149,9 @@
* specimen used only to generate friendlier error messages.
*/
function enforceType(specimen, typename, opt_name) {
- if (typeOf(specimen) !== typename) {
- throw new TypeError('expected ' + typename + ' instead of ' +
- typeOf(specimen) + ': ' + (opt_name || specimen));
+ if (typeof specimen !== typename) {
+ throw new TypeError___('expected ' + typename + ' instead of ' +
+ typeof specimen + ': ' + (opt_name || specimen));
}
return specimen;
}
@@ -1091,18 +1166,18 @@
function enforceNat(specimen) {
enforceType(specimen, 'number');
if (Math.floor(specimen) !== specimen) {
- throw new TypeError('Must be integral: ' + specimen);
+ throw new TypeError___('Must be integral: ' + specimen);
}
if (specimen < 0) {
- throw new TypeError('Must not be negative: ' + specimen);
+ throw new TypeError___('Must not be negative: ' + specimen);
}
// Could pre-compute precision limit, but probably not faster
// enough to be worth it.
if (Math.floor(specimen - 1) !== specimen - 1) {
- throw new TypeError('Beyond precision limit: ' + specimen);
+ throw new TypeError___('Beyond precision limit: ' + specimen);
}
if (Math.floor(specimen - 1) >= specimen) {
- throw new TypeError('Must not be infinite: ' + specimen);
+ throw new TypeError___('Must not be infinite: ' + specimen);
}
return specimen;
}
@@ -1177,7 +1252,7 @@
function setOnKey(key, value) {
var ktype = typeof key;
if (!key || (ktype !== 'function' && ktype !== 'object')) {
- throw new TypeError("Can't use key lifetime on primitive keys: " +
key);
+ throw new TypeError___("Can't use key lifetime on primitive
keys: " + key);
}
var list = key[myMagicIndexName];
// To distinguish key from objects that derive from it,
@@ -1203,7 +1278,7 @@
function getOnKey(key) {
var ktype = typeof key;
if (!key || (ktype !== 'function' && ktype !== 'object')) {
- throw new TypeError("Can't use key lifetime on primitive keys: " +
key);
+ throw new TypeError___("Can't use key lifetime on primitive
keys: " + key);
}
var list = key[myMagicIndexName];
if (!list || list[0] !== key) {
@@ -1289,6 +1364,78 @@
get: markFuncFreeze(getOnTable)
});
}
+
+ var registeredImports = [];
+
+ /**
+ * Gets or assigns the id associated with this (assumed to be)
+ * imports object, registering it so that
+ * <tt>getImports(getId(imports)) === imports</tt>.
+ * <p>
+ * This system of registration and identification allows us to
+ * cajole html such as
+ * <pre><a onmouseover="alert(1)">Mouse here</a></pre>
+ * into html-writing JavaScript such as<pre>
+ * ___IMPORTS___.document.innerHTML = "
+ * <a onmouseover=\"
+ * (function(___IMPORTS___) {
+ * ___IMPORTS___.alert(1);
+ * })(___.getImports(" + ___.getId(___IMPORTS___) + "))
+ * \">Mouse here</a>
+ * ";
+ * </pre>
+ * If this is executed by a plugin whose imports is assigned id 42,
+ * it generates html with the same meaning as<pre>
+ * <a onmouseover="___.getImports(42).alert(1)">Mouse
here</a>
+ * </pre>
+ * <p>
+ * An imports is not registered and no id is assigned to it until the
+ * first call to <tt>getId</tt>. This way, an imports that is never
+ * registered, or that has been <tt>unregister</tt>ed since the last
+ * time it was registered, will still be garbage collectable.
+ */
+ function getId(imports) {
+ enforceType(imports, 'object', 'imports');
+ var id;
+ if ('id___' in imports) {
+ id = enforceType(imports.id___, 'number', 'id');
+ } else {
+ id = imports.id___ = registeredImports.length;
+ }
+ registeredImports[id] = imports;
+ return id;
+ }
+
+ /**
+ * Gets the imports object registered under this id.
+ * <p>
+ * If it has been <tt>unregistered</tt> since the last
+ * <tt>getId</tt> on it, then <tt>getImports</tt> will fail.
+ */
+ function getImports(id) {
+ var result = registeredImports[enforceType(id, 'number', 'id')];
+ if (result === void 0) {
+ throw new Error___('Internal: imports#', id, ' unregistered');
+ }
+ return result;
+ }
+
+ /**
+ * If you know that this <tt>imports</tt> no longer needs to be
+ * accessed by <tt>getImports</tt>, then you should
+ * <tt>unregister</tt> it so it can be garbage collected.
+ * <p>
+ * After unregister()ing, the id is not reassigned, and the imports
+ * remembers its id. If asked for another <tt>getId</tt>, it
+ * reregisters itself at its old id.
+ */
+ function unregister(imports) {
+ enforceType(imports, 'object', 'imports');
+ if ('id___' in imports) {
+ var id = enforceType(imports.id___, 'number', 'id');
+ registeredImports[id] = void 0;
+ }
+ }
////////////////////////////////////////////////////////////////////////
// Guards and Trademarks
@@ -1356,7 +1503,7 @@
var stash = void 0;
function ejector(result) {
if (disabled) {
- throw new Error('ejector disabled');
+ throw new Error___('ejector disabled');
} else {
// don't disable here.
stash = result;
@@ -1389,9 +1536,9 @@
function eject(opt_ejector, result) {
if (opt_ejector) {
callPub(opt_ejector, 'call', [USELESS, result]);
- throw new Error('Ejector did not exit: ', opt_ejector);
+ throw new Error___('Ejector did not exit: ', opt_ejector);
} else {
- throw new Error(result);
+ throw new Error___(result);
}
}
@@ -1511,10 +1658,10 @@
*/
function stamp(stamps, record) {
if (!isRecord(record)) {
- throw new TypeError('Can only stamp records: ' + record);
+ throw new TypeError___('Can only stamp records: ' + record);
}
if (isFrozen(record)) {
- throw new TypeError("Can't stamp frozen objects: " + record);
+ throw new TypeError___("Can't stamp frozen objects: " + record);
}
stamps = Array___.slice___(stamps, 0);
var numStamps = stamps.length >>> 0;
@@ -1522,7 +1669,7 @@
// the record.
for (var i = 0; i < numStamps; i++) {
if (!('mark___' in stamps[i])) {
- throw new TypeError("Can't stamp with a non-stamp: " + stamps[i]);
+ throw new TypeError___("Can't stamp with a non-stamp: " +
stamps[i]);
}
}
// Looping again over the same untrusted stamps alleged-array is safe
@@ -1564,7 +1711,7 @@
function unseal(box) {
var payload = table.get(box);
if (payload === void 0) {
- throw new TypeError('Sealer/Unsealer mismatch');
+ throw new TypeError___('Sealer/Unsealer mismatch');
} else if (payload === undefinedStandin) {
return void 0;
} else {
@@ -1626,7 +1773,7 @@
case 'object': {
if (ex === null) { return null; }
if (ex.throwable___) { return ex; }
- if (isError(ex)) {
+ if (isError___(ex)) {
return freeze(ex);
}
return '' + ex;
@@ -1728,7 +1875,7 @@
// 8.7.1
function GetValue(obj, name) {
if (obj === null || obj === void 0) {
- throw new TypeError(obj + ' has no properties.');
+ throw new TypeError___(obj + ' has no properties.');
}
return obj.Get___(name);
}
@@ -1736,7 +1883,7 @@
// 8.7.2
function PutValue(obj, name, val) {
if (obj === null || obj === void 0) {
- throw new TypeError(obj + ' has no properties.');
+ throw new TypeError___(obj + ' has no properties.');
}
return obj.Put___(name, val);
}
@@ -1832,9 +1979,9 @@
// 8.10.5
function ToPropertyDescriptor(Obj) {
- // 1. If Type(Obj) is not Object throw a TypeError exception.
+ // 1. If Type(Obj) is not Object throw a TypeError___ exception.
if (Type(Obj) !== 'Object') {
- throw new TypeError('Expected an object.');
+ throw new TypeError___('Expected an object.');
}
// 2. Let desc be the result of creating a new Property
// Descriptor that initially has no fields.
@@ -1878,9 +2025,9 @@
// internal method of Obj with argument "get".
var getter = GetValue(Obj, 'get');
// b. If IsCallable(getter) is false and getter is not
- // undefined, then throw a TypeError exception.
+ // undefined, then throw a TypeError___ exception.
if (!isFunction(getter) && getter !== void 0) {
- throw new TypeError('Getter attributes must be functions or
undef.');
+ throw new TypeError___('Getter attributes must be functions or
undef.');
}
// c. Set the [[Get]] field of desc to getter.
desc.get = getter;
@@ -1892,9 +2039,9 @@
// internal method of Obj with argument "set".
var setter = GetValue(Obj, 'set');
// b. If IsCallable(setter) is false and setter is not
- // undefined, then throw a TypeError exception.
+ // undefined, then throw a TypeError___ exception.
if (!isFunction(setter) && setter !== void 0) {
- throw new TypeError('Setter attributes must be functions or
undef.');
+ throw new TypeError___('Setter attributes must be functions or
undef.');
}
// c. Set the [[Set]] field of desc to setter.
desc.set = setter;
@@ -1902,12 +2049,12 @@
// 9. If either desc.[[Get]] or desc.[[Set]] are present, then
if ('set' in desc || 'get' in desc) {
// a. If either desc.[[Value]] or desc.[[Writable]] are present,
- // then throw a TypeError exception.
+ // then throw a TypeError___ exception.
if ('value' in desc) {
- throw new TypeError('Accessor properties must not have a value.');
+ throw new TypeError___('Accessor properties must not have a
value.');
}
if ('writable' in desc) {
- throw new TypeError('Accessor properties must not be writable.');
+ throw new TypeError___('Accessor properties must not be
writable.');
}
}
// 10. Return desc.
@@ -1984,7 +2131,7 @@
assertValidPropertyName(P);
if (!thisExtensible) {
if (wouldExtend(this, P)) {
- throw new TypeError("Could not create the property '" +
+ throw new TypeError___("Could not create the property '" +
P + "': " + this + " is not extensible.");
}
}
@@ -1996,7 +2143,7 @@
if (isWritable(this, 'NUM___') || !this.hasNumerics___()) {
return this[P] = V;
} else {
- throw new TypeError("The property '" + P + "' is not writable.");
+ throw new TypeError___("The property '" + P + "' is not
writable.");
}
}
assertValidPropertyName(this, P);
@@ -2019,7 +2166,7 @@
});
return V;
}
- throw new TypeError("The property '" + P + "' is not writable.");
+ throw new TypeError___("The property '" + P + "' is not writable.");
};
// 8.12.6
@@ -2060,9 +2207,9 @@
// b. Return true.
return true;
}
- // 4. Else if Throw, then throw a TypeError exception.
+ // 4. Else if Throw, then throw a TypeError___ exception.
// [This is strict mode, so Throw is always true.]
- throw new TypeError("Cannot delete '" + P + "' on " + obj);
+ throw new TypeError___("Cannot delete '" + P + "' on " + obj);
// 5. Return false.
};
@@ -2072,7 +2219,7 @@
// P is a number or a string.
Object.prototype.DefineOwnProperty___ = function (P, Desc) {
if (isNumericName(P)) {
- throw new TypeError('Cannot define numeric properties.');
+ throw new TypeError___('Cannot define numeric properties.');
}
var O = this;
// 1. Let current be the result of calling the [[GetOwnProperty]]
@@ -2083,7 +2230,7 @@
var extensible = isExtensible(O);
// 3. If current is undefined and extensible is false, then Reject.
if (!current && !extensible) {
- throw new TypeError('This object is not extensible.');
+ throw new TypeError___('This object is not extensible.');
}
// 4. If current is undefined and extensible is true, then
if (!current && extensible) {
@@ -2152,14 +2299,14 @@
if (!current.configurable) {
// a. Reject, if the [Cofigurable]] field of Desc is true.
if (Desc.configurable) {
- throw new TypeError("The property '" + P +
+ throw new TypeError___("The property '" + P +
"' is not configurable.");
}
// b. Reject, if the [[Enumerable]] field of Desc is present
// and the [[Enumerable]] fields of current and Desc are
// the Boolean negation of each other.
if ('enumerable' in Desc && Desc.enumerable !==
current.enumerable) {
- throw new TypeError("The property '" + P +
+ throw new TypeError___("The property '" + P +
"' is not configurable.");
}
}
@@ -2175,7 +2322,7 @@
else if (iddCurrent !== iddDesc) {
// a. Reject, if the [[Configurable]] field of current is false.
if (!current.configurable) {
- throw new TypeError("The property '" + P +
+ throw new TypeError___("The property '" + P +
"' is not configurable.");
}
// b. If IsDataDescriptor(current) is true, then
@@ -2220,7 +2367,7 @@
// i. Reject, if the [[Writable]] field of current is false
// and the [[Writable]] field of Desc is true.
if (!current.writable && Desc.writable) {
- throw new TypeError("The property '" + P +
+ throw new TypeError___("The property '" + P +
"' is not configurable.");
}
// ii. If the [[Writable]] field of current is false, then
@@ -2228,7 +2375,7 @@
// 1. Reject, if the [[Value]] field of Desc is present and
// SameValue(Desc.[[Value]], current.[[Value]]) is false.
if ('value' in Desc && !SameValue(Desc.value, current.value)) {
- throw new TypeError("The property '" + P +
+ throw new TypeError___("The property '" + P +
"' is not writable.");
}
}
@@ -2247,7 +2394,7 @@
// SameValue(Desc.[[Get]], current.[[Get]]) is false.
if (('set' in Desc && !SameValue(Desc.set, current.set)) ||
('get' in Desc && !SameValue(Desc.get, current.get))) {
- throw new TypeError("The property '" + P +
+ throw new TypeError___("The property '" + P +
"' is not configurable.");
}
}
@@ -2289,7 +2436,7 @@
switch(t) {
case 'Undefined':
case 'Null':
- throw new TypeError();
+ throw new TypeError___();
case 'Boolean':
return new Boolean___.new___(input);
case 'Number':
@@ -2327,7 +2474,7 @@
*/
function asFirstClass(value) {
if (isFunction(value) && value.f___ === Function.prototype.f___) {
- var err = new Error('Internal: toxic function encountered!');
+ var err = new Error___('Internal: toxic function encountered!');
err.UNCATCHABLE___ = true;
throw err;
}
@@ -2363,13 +2510,13 @@
// 11.2.3
/**
- * Makes a [[ThrowTypeError]] function, as defined in section 13.2.3
+ * Makes a [[ThrowTypeError___]] function, as defined in section 13.2.3
* of the ES5 spec.
*
- * <p>The informal name for the [[ThrowTypeError]] function, defined
+ * <p>The informal name for the [[ThrowTypeError___]] function, defined
* in section 13.2.3 of the ES5 spec, is the "poison pill". The poison
* pill is simply a no-argument function that, when called, always
- * throws a TypeError. Since we wish this TypeError to carry useful
+ * throws a TypeError___. Since we wish this TypeError___ to carry useful
* diagnostic info, we violate the ES5 spec by defining 4 poison
* pills with 4 distinct identities.
*
@@ -2382,7 +2529,7 @@
*/
function makePoisonPill(badThing) {
function poisonPill() {
- throw new TypeError('' + badThing + ' is forbidden by ES5/strict');
+ throw new TypeError___('' + badThing + ' is forbidden by
ES5/strict');
}
return markFunc(poisonPill);
}
@@ -2494,7 +2641,7 @@
function isIn(name, obj) {
var t = Type(obj);
if (t !== 'Object') {
- throw new TypeError('Invalid "in" operand: ' + obj);
+ throw new TypeError___('Invalid "in" operand: ' + obj);
}
return obj.HasProperty___(name);
}
@@ -2534,16 +2681,13 @@
// 15.2.3.2
Object.getPrototypeOf = function (obj) {
if (!Object___.hasOwnProperty___('Prototype___')) {
- // I know I said not to feature test for __proto__. But if we're
- // feature testing for getOwnProperty anyway, we may as well
- // feature test for __proto__ also.
if ({}.__proto__ === Object___.prototype) {
obj.Prototype___ = obj.__proto__;
} else {
// FIXME: Adapt tricks from cajita.js to find the prototype
// and, if successful, store the result on obj.Prototype___.
// Otherwise throw.
- throw new Error("Not supported in this browser.");
+ throw new Error___("Not supported on this platform.");
}
}
return obj.Prototype___;
@@ -2552,9 +2696,9 @@
// 15.2.3.3
Object.getOwnPropertyDescriptor = function(obj, P) {
- // 1. If Type(object) is not Object throw a TypeError exception.
+ // 1. If Type(object) is not Object throw a TypeError___ exception.
if (Type(obj) !== 'Object') {
- throw new TypeError('Expected an object.');
+ throw new TypeError___('Expected an object.');
}
// 2. Let name be ToString(P).
var name = '' + P;
@@ -2574,10 +2718,10 @@
*/
function beget(proto) {
if (proto === null) {
- throw new TypeError('Cannot beget from null.');
+ throw new TypeError___('Cannot beget from null.');
}
if (proto === (void 0)) {
- throw new TypeError('Cannot beget from undefined.');
+ throw new TypeError___('Cannot beget from undefined.');
}
function F() {}
F.prototype = proto;
@@ -2588,10 +2732,10 @@
// The algorithm below doesn't care whether Properties is absent
// or undefined, so we can simplify.
Object.create = function (O, opt_Properties) {
- // 1. If Type(O) is not Object or Null throw a TypeError exception.
+ // 1. If Type(O) is not Object or Null throw a TypeError___
exception.
// (ES3 doesn't support null prototypes.)
if (Type(obj) !== 'Object') {
- throw new TypeError('Expected an object.');
+ throw new TypeError___('Expected an object.');
}
// 2. Let obj be the result of creating a new object
// as if by the expression new Object() where Object
@@ -2611,9 +2755,9 @@
// 15.2.3.6
Object.defineProperty = function (O, P, Attributes) {
- // 1. If Type(O) is not Object throw a TypeError exception.
+ // 1. If Type(O) is not Object throw a TypeError___ exception.
if (Type(O) !== 'Object') {
- throw new TypeError('Expected an object.');
+ throw new TypeError___('Expected an object.');
}
// 2. Let name be ToString(P).
var name = '' + P;
@@ -2630,9 +2774,9 @@
// 15.2.3.7
Object.defineProperties = function (O, Properties) {
- // 1. If Type(O) is not Object throw a TypeError exception.
+ // 1. If Type(O) is not Object throw a TypeError___ exception.
if (Type(O) !== 'Object') {
- throw new TypeError('Expected an object.');
+ throw new TypeError___('Expected an object.');
}
// 2. Let props be ToObject(Properties).
var props = ToObject(Properties);
@@ -2676,9 +2820,9 @@
// 15.2.3.8
Object.seal = function (O) {
- // 1. If Type(O) is not Object throw a TypeError exception.
+ // 1. If Type(O) is not Object throw a TypeError___ exception.
if (Type(O) !== 'Object') {
- throw new TypeError('Only objects may be sealed.');
+ throw new TypeError___('Only objects may be sealed.');
}
// 2. For each own property name P of O,
var keys = ownKeys(O), len = keys.length;
@@ -2712,7 +2856,7 @@
// 15.2.3.9
function freeze(obj) {
if (Type(obj) !== 'Object') {
- throw new TypeError('Only objects may be frozen.');
+ throw new TypeError___('Only objects may be frozen.');
}
// Frozen means all the properties are neither writable nor
// configurable, and the object itself is not extensible.
@@ -2784,9 +2928,9 @@
// 15.2.3.11
Object.isSealed = function (O) {
- // 1. If Type(O) is not Object throw a TypeError exception.
+ // 1. If Type(O) is not Object throw a TypeError___ exception.
if (Type(O) !== 'Object') {
- throw new TypeError('Only objects may be frozen.');
+ throw new TypeError___('Only objects may be frozen.');
}
// 2. For each named own property name P of O,
// a. Let desc be the result of calling the [[GetOwnProperty]]
@@ -2857,7 +3001,7 @@
}),
set: markFunc(function (val) {
if (!isFunction(val)) {
- throw new TypeError('Expected a function.');
+ throw new TypeError___('Expected a function.');
}
val = asFirstClass(val);
this.toString = markFunc(function (var_args) {
@@ -2877,7 +3021,7 @@
}),
set: markFunc(function (val) {
if (!isFunction(val)) {
- throw new TypeError('Expected a function.');
+ throw new TypeError___('Expected a function.');
}
val = asFirstClass(val);
this.valueOf = markFunc(function (var_args) {
@@ -2896,7 +3040,7 @@
// 15.2.4.6
Object.prototype.isPrototypeOf = function(V) {
- throw new Error('isPrototypeOf is not supported.');
+ throw new Error___('isPrototypeOf is not supported.');
};
// 15.2.4.7
@@ -2931,7 +3075,7 @@
// 15.3 Function
var FakeFunction = function () {
throw new
- Error('Internal: FakeFunction should not be directly
invocable.');
+ Error___('Internal: FakeFunction should not be directly
invocable.');
};
FakeFunction.toString = (function (str) {
@@ -2942,12 +3086,12 @@
// 15.3.1
Function.f___ = FakeFunction.f___ = markFunc(function() {
- throw new Error('Invoking the Function constructor is unsupported.');
+ throw new Error___('Invoking the Function constructor is
unsupported.');
});
// 15.3.2
Function.new___ = FakeFunction.new___ = markFunc(function () {
- throw new Error('Constructing functions dynamically is
unsupported.');
+ throw new Error___('Constructing functions dynamically is
unsupported.');
});
// 15.3.3.1
@@ -3034,12 +3178,12 @@
// This taming assumes that sort only modifies {...@code this},
// even though it may read numeric properties on the prototype chain.
if (!isWritable(this, 'NUM___')) {
- throw new TypeError(
+ throw new TypeError___(
'Cannot sort an object whose ' +
'numeric properties are not writable.');
}
if (!isExtensible(this)) {
- throw new TypeError(
+ throw new TypeError___(
'Cannot sort an object that is not extensible.');
}
return comparefn ?
@@ -3150,7 +3294,7 @@
createOrWrap(Array.prototype, 'map', function (fun, thisp) {
var len = this.length >>> 0;
if (!isFunction(fun)) {
- throw new TypeError('Expected a function.');
+ throw new TypeError___('Expected a function.');
}
var res = new Array(len);
for (var i = 0; i < len; i++) {
@@ -3181,11 +3325,11 @@
var len = this.length >>> 0;
if (Type(fun) !== 'Function') {
// As you've defined it, Type(x) will never return 'Function'
- throw new TypeError('Expected a function.');
+ throw new TypeError___('Expected a function.');
}
// no value to return if no initial value and an empty array
if (len === 0 && arguments.length === 1) {
- throw new TypeError('Expected an initial value or a non-empty
array.');
+ throw new TypeError___('Expected an initial value or a non-empty
array.');
}
var i = 0;
if (arguments.length >= 2) {
@@ -3198,7 +3342,7 @@
}
// if array contains no values, no initial value to return
if (++i >= len) {
- throw new TypeError('Expected non-empty array.');
+ throw new TypeError___('Expected non-empty array.');
}
} while (true);
}
@@ -3216,11 +3360,11 @@
var len = this.length >>> 0;
if (Type(fun) !== 'Function') {
// As you've defined it, Type(x) will never return 'Function'
- throw new TypeError('Expected a function.');
+ throw new TypeError___('Expected a function.');
}
// no value to return if no initial value, empty array
if (len === 0 && arguments.length === 1) {
- throw new TypeError('Expected an initial value or a non-empty
array.');
+ throw new TypeError___('Expected an initial value or a non-empty
array.');
}
var i = len - 1;
if (arguments.length >= 2) {
@@ -3233,7 +3377,7 @@
}
// if array contains no values, no initial value to return
if (--i < 0) {
- throw new TypeError('Expected a non-empty array.');
+ throw new TypeError___('Expected a non-empty array.');
}
} while (true);
}
@@ -3328,7 +3472,7 @@
function enforceMatchable(regexp) {
if (regexp instanceof RegExp) {
if (isFrozen(regexp)) {
- throw new Error("Can't match with frozen RegExp: " + regexp);
+ throw new Error___("Can't match with frozen RegExp: " + regexp);
}
return false;
}
@@ -3837,7 +3981,7 @@
// See the HTML5 discussion for the reasons behind this rule.
if (!isFunction(onerror)) {
- throw new TypeError('Expected onerror to be a function.');
+ throw new TypeError___('Expected onerror to be a function.');
}
var shouldReport = onerror.f___(
USELESS,
@@ -3996,7 +4140,7 @@
}
var m = this.Get___(name);
if (!m) {
- throw new TypeError(
+ throw new TypeError___(
"The property '" + name + "' is falsey, thus not a function.");
}
// Fastpath the method on the object pointed to by name_v___
@@ -4014,6 +4158,7 @@
tameException: tameException,
args: args,
wrap: wrap,
+ copy: copy,
i: isIn,
beget: beget,
iM: initializeMap,
@@ -4021,6 +4166,11 @@
markFuncFreeze: markFuncFreeze,
Trademark: Trademark,
makeSealerUnsealerPair: makeSealerUnsealerPair,
+ getId: getId,
+ getImports: getImports,
+ unregister: unregister,
+ newTable: newTable,
+ extend: extend,
// Module loading
getNewModuleHandler: getNewModuleHandler,
setNewModuleHandler: setNewModuleHandler,