884 lines
35 KiB
JavaScript
884 lines
35 KiB
JavaScript
"use strict";
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports.ToImplementation = undefined;
|
||
|
||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /**
|
||
* Copyright (c) 2017-present, Facebook, Inc.
|
||
* All rights reserved.
|
||
*
|
||
* This source code is licensed under the BSD-style license found in the
|
||
* LICENSE file in the root directory of this source tree. An additional grant
|
||
* of patent rights can be found in the PATENTS file in the same directory.
|
||
*/
|
||
|
||
var _get = require("./get.js");
|
||
|
||
var _singletons = require("../singletons.js");
|
||
|
||
var _has = require("./has.js");
|
||
|
||
var _call = require("./call.js");
|
||
|
||
var _errors = require("../errors.js");
|
||
|
||
var _is = require("./is.js");
|
||
|
||
var _abstract = require("./abstract.js");
|
||
|
||
var _index = require("../values/index.js");
|
||
|
||
var _invariant = require("../invariant.js");
|
||
|
||
var _invariant2 = _interopRequireDefault(_invariant);
|
||
|
||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||
|
||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||
|
||
function modulo(x, y) {
|
||
return x < 0 ? x % y + y : x % y;
|
||
}
|
||
|
||
var ToImplementation = exports.ToImplementation = function () {
|
||
function ToImplementation() {
|
||
_classCallCheck(this, ToImplementation);
|
||
|
||
this.ElementConv = {
|
||
Int8: this.ToInt8.bind(this),
|
||
Int16: this.ToInt16.bind(this),
|
||
Int32: this.ToInt32.bind(this),
|
||
Uint8: this.ToUint8.bind(this),
|
||
Uint16: this.ToUint16.bind(this),
|
||
Uint32: this.ToUint32.bind(this),
|
||
Uint8Clamped: this.ToUint8Clamp.bind(this)
|
||
};
|
||
}
|
||
|
||
_createClass(ToImplementation, [{
|
||
key: "ToInt32",
|
||
|
||
|
||
// ECMA262 7.1.5
|
||
value: function ToInt32(realm, argument) {
|
||
// 1. Let number be ? ToNumber(argument).
|
||
var number = this.ToNumber(realm, argument);
|
||
|
||
// 2. If number is NaN, +0, -0, +∞, or -∞, return +0.
|
||
if (isNaN(number) || number === 0 || !isFinite(number)) return +0;
|
||
|
||
// 3. Let int be the mathematical value that is the same sign as number and whose magnitude is floor(abs(number)).
|
||
var int = number < 0 ? -Math.floor(Math.abs(number)) : Math.floor(Math.abs(number));
|
||
|
||
// 4. Let int16bit be int modulo 2^32.
|
||
var int32bit = modulo(int, Math.pow(2, 32));
|
||
|
||
// 5. If int32bit ≥ 2^31, return int32bit - 2^32; otherwise return int32bit.
|
||
return int32bit >= Math.pow(2, 31) ? int32bit - Math.pow(2, 32) : int32bit;
|
||
}
|
||
|
||
// ECMA262 7.1.6
|
||
|
||
}, {
|
||
key: "ToUint32",
|
||
value: function ToUint32(realm, argument) {
|
||
// 1. Let number be ? ToNumber(argument).
|
||
var number = this.ToNumber(realm, argument);
|
||
|
||
// 2. If number is NaN, +0, -0, +∞, or -∞, return +0.
|
||
if (isNaN(number) || number === 0 || !isFinite(number)) return +0;
|
||
|
||
// 3. Let int be the mathematical value that is the same sign as number and whose magnitude is floor(abs(number)).
|
||
var int = number < 0 ? -Math.floor(Math.abs(number)) : Math.floor(Math.abs(number));
|
||
|
||
// 4. Let int16bit be int modulo 2^32.
|
||
var int32bit = modulo(int, Math.pow(2, 32));
|
||
|
||
// 5. Return int32bit.
|
||
return int32bit;
|
||
}
|
||
|
||
// ECMA262 7.1.7
|
||
|
||
}, {
|
||
key: "ToInt16",
|
||
value: function ToInt16(realm, argument) {
|
||
// 1. Let number be ? ToNumber(argument).
|
||
var number = this.ToNumber(realm, argument);
|
||
|
||
// 2. If number is NaN, +0, -0, +∞, or -∞, return +0.
|
||
if (isNaN(number) || number === 0 || !isFinite(number)) return +0;
|
||
|
||
// 3. Let int be the mathematical value that is the same sign as number and whose magnitude is floor(abs(number)).
|
||
var int = number < 0 ? -Math.floor(Math.abs(number)) : Math.floor(Math.abs(number));
|
||
|
||
// 4. Let int16bit be int modulo 2^16.
|
||
var int16bit = modulo(int, Math.pow(2, 16));
|
||
|
||
// 5. If int16bit ≥ 2^15, return int16bit - 2^16; otherwise return int16bit.
|
||
return int16bit >= Math.pow(2, 15) ? int16bit - Math.pow(2, 16) : int16bit;
|
||
}
|
||
|
||
// ECMA262 7.1.8
|
||
|
||
}, {
|
||
key: "ToUint16",
|
||
value: function ToUint16(realm, argument) {
|
||
// 1. Let number be ? ToNumber(argument).
|
||
var number = this.ToNumber(realm, argument);
|
||
|
||
// 2. If number is NaN, +0, -0, +∞, or -∞, return +0.
|
||
if (isNaN(number) || number === 0 || !isFinite(number)) return +0;
|
||
|
||
// 3. Let int be the mathematical value that is the same sign as number and whose magnitude is floor(abs(number)).
|
||
var int = number < 0 ? -Math.floor(Math.abs(number)) : Math.floor(Math.abs(number));
|
||
|
||
// 4. Let int16bit be int modulo 2^16.
|
||
var int16bit = modulo(int, Math.pow(2, 16));
|
||
|
||
// 5. Return int16bit.
|
||
return int16bit;
|
||
}
|
||
|
||
// ECMA262 7.1.9
|
||
|
||
}, {
|
||
key: "ToInt8",
|
||
value: function ToInt8(realm, argument) {
|
||
// 1. Let number be ? ToNumber(argument).
|
||
var number = this.ToNumber(realm, argument);
|
||
|
||
// 2. If number is NaN, +0, -0, +∞, or -∞, return +0.
|
||
if (isNaN(number) || number === 0 || !isFinite(number)) return +0;
|
||
|
||
// 3. Let int be the mathematical value that is the same sign as number and whose magnitude is floor(abs(number)).
|
||
var int = number < 0 ? -Math.floor(Math.abs(number)) : Math.floor(Math.abs(number));
|
||
|
||
// 4. Let int8bit be int modulo 2^8.
|
||
var int8bit = modulo(int, Math.pow(2, 8));
|
||
|
||
// 5. If int8bit ≥ 2^7, return int8bit - 2^8; otherwise return int8bit.
|
||
return int8bit >= Math.pow(2, 7) ? int8bit - Math.pow(2, 8) : int8bit;
|
||
}
|
||
|
||
// ECMA262 7.1.10
|
||
|
||
}, {
|
||
key: "ToUint8",
|
||
value: function ToUint8(realm, argument) {
|
||
// 1. Let number be ? ToNumber(argument).
|
||
var number = this.ToNumber(realm, argument);
|
||
|
||
// 2. If number is NaN, +0, -0, +∞, or -∞, return +0.
|
||
if (isNaN(number) || number === 0 || !isFinite(number)) return +0;
|
||
|
||
// 3. Let int be the mathematical value that is the same sign as number and whose magnitude is floor(abs(number)).
|
||
var int = number < 0 ? -Math.floor(Math.abs(number)) : Math.floor(Math.abs(number));
|
||
|
||
// 4. Let int8bit be int modulo 2^8.
|
||
var int8bit = modulo(int, Math.pow(2, 8));
|
||
|
||
// 5. Return int8bit.
|
||
return int8bit;
|
||
}
|
||
|
||
// ECMA262 7.1.11
|
||
|
||
}, {
|
||
key: "ToUint8Clamp",
|
||
value: function ToUint8Clamp(realm, argument) {
|
||
// 1. Let number be ? ToNumber(argument).
|
||
var number = this.ToNumber(realm, argument);
|
||
|
||
// 2. If number is NaN, return +0.
|
||
if (isNaN(number)) return +0;
|
||
|
||
// 3. If number ≤ 0, return +0.
|
||
if (number <= 0) return +0;
|
||
|
||
// 4. If number ≥ 255, return 255.
|
||
if (number >= 255) return 255;
|
||
|
||
// 5. Let f be floor(number).
|
||
var f = Math.floor(number);
|
||
|
||
// 6. If f + 0.5 < number, return f + 1.
|
||
if (f + 0.5 < number) return f + 1;
|
||
|
||
// 7. If number < f + 0.5, return f.
|
||
if (number < f + 0.5) return f;
|
||
|
||
// 8. If f is odd, return f + 1.
|
||
if (f % 2 === 1) return f + 1;
|
||
|
||
// 9. Return f.
|
||
return f;
|
||
}
|
||
|
||
// ECMA262 19.3.3.1
|
||
|
||
}, {
|
||
key: "thisBooleanValue",
|
||
value: function thisBooleanValue(realm, value) {
|
||
// 1. If Type(value) is Boolean, return value.
|
||
if (value instanceof _index.BooleanValue) return value;
|
||
|
||
// 2. If Type(value) is Object and value has a [[BooleanData]] internal slot, then
|
||
if (value instanceof _index.ObjectValue && value.$BooleanData) {
|
||
var booleanData = value.$BooleanData.throwIfNotConcreteBoolean();
|
||
// a. Assert: value's [[BooleanData]] internal slot is a Boolean value.
|
||
(0, _invariant2.default)(booleanData instanceof _index.BooleanValue, "expected boolean data internal slot to be a boolean value");
|
||
|
||
// b. Return the value of value's [[BooleanData]] internal slot.
|
||
return booleanData;
|
||
}
|
||
|
||
value.throwIfNotConcrete();
|
||
|
||
// 3. Throw a TypeError exception.
|
||
throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError);
|
||
}
|
||
|
||
// ECMA262 20.1.3
|
||
|
||
}, {
|
||
key: "thisNumberValue",
|
||
value: function thisNumberValue(realm, value) {
|
||
// 1. If Type(value) is Number, return value.
|
||
if (value instanceof _index.NumberValue) return value;
|
||
|
||
// 2. If Type(value) is Object and value has a [[NumberData]] internal slot, then
|
||
if (value instanceof _index.ObjectValue && value.$NumberData) {
|
||
var numberData = value.$NumberData.throwIfNotConcreteNumber();
|
||
// a. Assert: value's [[NumberData]] internal slot is a Number value.
|
||
(0, _invariant2.default)(numberData instanceof _index.NumberValue, "expected number data internal slot to be a number value");
|
||
|
||
// b. Return the value of value's [[NumberData]] internal slot.
|
||
return numberData;
|
||
}
|
||
|
||
value = value.throwIfNotConcrete();
|
||
|
||
// 3. Throw a TypeError exception.
|
||
throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError);
|
||
}
|
||
|
||
// ECMA262 21.1.3
|
||
|
||
}, {
|
||
key: "thisStringValue",
|
||
value: function thisStringValue(realm, value) {
|
||
// 1. If Type(value) is String, return value.
|
||
if (value instanceof _index.StringValue) return value;
|
||
|
||
// 2. If Type(value) is Object and value has a [[StringData]] internal slot, then
|
||
if (value instanceof _index.ObjectValue && value.$StringData) {
|
||
var stringData = value.$StringData.throwIfNotConcreteString();
|
||
// a. Assert: value's [[StringData]] internal slot is a String value.
|
||
(0, _invariant2.default)(stringData instanceof _index.StringValue, "expected string data internal slot to be a string value");
|
||
|
||
// b. Return the value of value's [[StringData]] internal slot.
|
||
return stringData;
|
||
}
|
||
|
||
value = value.throwIfNotConcrete();
|
||
|
||
// 3. Throw a TypeError exception.
|
||
throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError);
|
||
}
|
||
|
||
// ECMA262 6.2.4.5
|
||
|
||
}, {
|
||
key: "ToPropertyDescriptor",
|
||
value: function ToPropertyDescriptor(realm, Obj) {
|
||
Obj = Obj.throwIfNotConcrete();
|
||
|
||
// 1. If Type(Obj) is not Object, throw a TypeError exception.
|
||
if (!(Obj instanceof _index.ObjectValue)) {
|
||
throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError);
|
||
}
|
||
|
||
// 2. Let desc be a new Property Descriptor that initially has no fields.
|
||
var desc = {};
|
||
|
||
// 3. Let hasEnumerable be ? HasProperty(Obj, "enumerable").
|
||
var hasEnumerable = (0, _has.HasProperty)(realm, Obj, "enumerable");
|
||
|
||
// 4. If hasEnumerable is true, then
|
||
if (hasEnumerable === true) {
|
||
// a. Let enum be ToBoolean(? Get(Obj, "enumerable")).
|
||
var enu = this.ToBooleanPartial(realm, (0, _get.Get)(realm, Obj, "enumerable"));
|
||
|
||
// b. Set the [[Enumerable]] field of desc to enum.
|
||
desc.enumerable = enu === true;
|
||
}
|
||
|
||
// 5. Let hasConfigurable be ? HasProperty(Obj, "configurable").
|
||
var hasConfigurable = (0, _has.HasProperty)(realm, Obj, "configurable");
|
||
|
||
// 6. If hasConfigurable is true, then
|
||
if (hasConfigurable === true) {
|
||
// a. Let conf be ToBoolean(? Get(Obj, "configurable")).
|
||
var conf = this.ToBooleanPartial(realm, (0, _get.Get)(realm, Obj, "configurable"));
|
||
|
||
// b. Set the [[Configurable]] field of desc to conf.
|
||
desc.configurable = conf === true;
|
||
}
|
||
|
||
// 7. Let hasValue be ? HasProperty(Obj, "value").
|
||
var hasValue = (0, _has.HasProperty)(realm, Obj, "value");
|
||
|
||
// 8. If hasValue is true, then
|
||
if (hasValue === true) {
|
||
// a. Let value be ? Get(Obj, "value").
|
||
var value = (0, _get.Get)(realm, Obj, "value");
|
||
|
||
// b. Set the [[Value]] field of desc to value.
|
||
desc.value = value;
|
||
}
|
||
|
||
// 9. Let hasWritable be ? HasProperty(Obj, "writable").
|
||
var hasWritable = (0, _has.HasProperty)(realm, Obj, "writable");
|
||
|
||
// 10. If hasWritable is true, then
|
||
if (hasWritable === true) {
|
||
// a. Let writable be ToBoolean(? Get(Obj, "writable")).
|
||
var writable = this.ToBooleanPartial(realm, (0, _get.Get)(realm, Obj, "writable"));
|
||
|
||
// b. Set the [[Writable]] field of desc to writable.
|
||
desc.writable = writable === true;
|
||
}
|
||
|
||
// 11. Let hasGet be ? HasProperty(Obj, "get").
|
||
var hasGet = (0, _has.HasProperty)(realm, Obj, "get");
|
||
|
||
// 12. If hasGet is true, then
|
||
if (hasGet === true) {
|
||
// a. Let getter be ? Get(Obj, "get").
|
||
var getter = (0, _get.Get)(realm, Obj, "get");
|
||
|
||
// b. If IsCallable(getter) is false and getter is not undefined, throw a TypeError exception.
|
||
if ((0, _is.IsCallable)(realm, getter) === false && !getter.mightBeUndefined()) {
|
||
throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError);
|
||
}
|
||
getter.throwIfNotConcrete();
|
||
|
||
// c. Set the [[Get]] field of desc to getter.
|
||
desc.get = getter;
|
||
}
|
||
|
||
// 13. Let hasSet be ? HasProperty(Obj, "set").
|
||
var hasSet = (0, _has.HasProperty)(realm, Obj, "set");
|
||
|
||
// 14. If hasSet is true, then
|
||
if (hasSet === true) {
|
||
// a. Let setter be ? Get(Obj, "set").
|
||
var setter = (0, _get.Get)(realm, Obj, "set");
|
||
|
||
// b. If IsCallable(setter) is false and setter is not undefined, throw a TypeError exception.
|
||
if ((0, _is.IsCallable)(realm, setter) === false && !setter.mightBeUndefined()) {
|
||
throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError);
|
||
}
|
||
setter.throwIfNotConcrete();
|
||
|
||
// c. Set the [[Set]] field of desc to setter.
|
||
desc.set = setter;
|
||
}
|
||
|
||
// 15. If either desc.[[Get]] or desc.[[Set]] is present, then
|
||
if (desc.get || desc.set) {
|
||
// a. If either desc.[[Value]] or desc.[[Writable]] is present, throw a TypeError exception.
|
||
if ("value" in desc || "writable" in desc) {
|
||
throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError);
|
||
}
|
||
}
|
||
|
||
// 16. Return desc.
|
||
return desc;
|
||
}
|
||
|
||
// ECMA262 7.1.13
|
||
|
||
}, {
|
||
key: "ToObject",
|
||
value: function ToObject(realm, arg) {
|
||
if (arg instanceof _index.UndefinedValue) {
|
||
throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError);
|
||
} else if (arg instanceof _index.NullValue) {
|
||
throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError);
|
||
} else if (arg instanceof _index.BooleanValue) {
|
||
var obj = new _index.ObjectValue(realm, realm.intrinsics.BooleanPrototype);
|
||
obj.$BooleanData = arg;
|
||
return obj;
|
||
} else if (arg instanceof _index.NumberValue) {
|
||
var _obj = new _index.ObjectValue(realm, realm.intrinsics.NumberPrototype);
|
||
_obj.$NumberData = arg;
|
||
return _obj;
|
||
} else if (arg instanceof _index.StringValue) {
|
||
var _obj2 = _singletons.Create.StringCreate(realm, arg, realm.intrinsics.StringPrototype);
|
||
return _obj2;
|
||
} else if (arg instanceof _index.SymbolValue) {
|
||
var _obj3 = new _index.ObjectValue(realm, realm.intrinsics.SymbolPrototype);
|
||
_obj3.$SymbolData = arg;
|
||
return _obj3;
|
||
} else if (arg instanceof _index.ObjectValue) {
|
||
return arg;
|
||
}
|
||
(0, _invariant2.default)(false);
|
||
}
|
||
}, {
|
||
key: "_WrapAbstractInObject",
|
||
value: function _WrapAbstractInObject(realm, arg) {
|
||
var obj = void 0;
|
||
switch (arg.types.getType()) {
|
||
case _index.NumberValue:
|
||
obj = new _index.ObjectValue(realm, realm.intrinsics.NumberPrototype);
|
||
obj.$NumberData = arg;
|
||
break;
|
||
|
||
case _index.StringValue:
|
||
obj = new _index.ObjectValue(realm, realm.intrinsics.StringPrototype);
|
||
obj.$StringData = arg;
|
||
break;
|
||
|
||
case _index.BooleanValue:
|
||
obj = new _index.ObjectValue(realm, realm.intrinsics.BooleanPrototype);
|
||
obj.$BooleanData = arg;
|
||
break;
|
||
|
||
case _index.SymbolValue:
|
||
obj = new _index.ObjectValue(realm, realm.intrinsics.SymbolPrototype);
|
||
obj.$SymbolData = arg;
|
||
break;
|
||
|
||
case _index.UndefinedValue:
|
||
case _index.NullValue:
|
||
throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError);
|
||
|
||
default:
|
||
obj = arg.throwIfNotConcreteObject();
|
||
break;
|
||
}
|
||
return obj;
|
||
}
|
||
}, {
|
||
key: "ToObjectPartial",
|
||
value: function ToObjectPartial(realm, arg) {
|
||
if (arg instanceof _index.AbstractObjectValue) return arg;
|
||
if (arg instanceof _index.AbstractValue) {
|
||
return this._WrapAbstractInObject(realm, arg);
|
||
}
|
||
arg = arg.throwIfNotConcrete();
|
||
return this.ToObject(realm, arg);
|
||
}
|
||
|
||
// ECMA262 7.1.15
|
||
|
||
}, {
|
||
key: "ToLength",
|
||
value: function ToLength(realm, argument) {
|
||
// Let len be ? ToInteger(argument).
|
||
var len = this.ToInteger(realm, argument);
|
||
|
||
// If len ≤ +0, return +0.
|
||
if (len <= 0) return +0;
|
||
|
||
// If len is +∞, return 2^53-1.
|
||
if (len === +Infinity) return Math.pow(2, 53) - 1;
|
||
|
||
// Return min(len, 2^53-1).
|
||
return Math.min(len, Math.pow(2, 53) - 1);
|
||
}
|
||
|
||
// ECMA262 7.1.4
|
||
|
||
}, {
|
||
key: "ToInteger",
|
||
value: function ToInteger(realm, argument) {
|
||
// 1. Let number be ? ToNumber(argument).
|
||
var number = this.ToNumber(realm, argument);
|
||
|
||
// 2. If number is NaN, return +0.
|
||
if (isNaN(number)) return +0;
|
||
|
||
// 3. If number is +0, -0, +∞, or -∞, return number.
|
||
if (!isFinite(number) || number === 0) return number;
|
||
|
||
// 4. Return the number value that is the same sign as number and whose magnitude is floor(abs(number)).
|
||
return number < 0 ? -Math.floor(Math.abs(number)) : Math.floor(Math.abs(number));
|
||
}
|
||
|
||
// ECMA262 7.1.17
|
||
|
||
}, {
|
||
key: "ToIndex",
|
||
value: function ToIndex(realm, value) {
|
||
var index = void 0;
|
||
// 1. If value is undefined, then
|
||
if (value instanceof _index.UndefinedValue) {
|
||
// a. Let index be 0.
|
||
index = 0;
|
||
} else {
|
||
// 2. Else,
|
||
// a. Let integerIndex be ? ToInteger(value).
|
||
var integerIndex = this.ToInteger(realm, value);
|
||
|
||
// b. If integerIndex < 0, throw a RangeError exception.
|
||
if (integerIndex < 0) {
|
||
throw realm.createErrorThrowCompletion(realm.intrinsics.RangeError, "integerIndex < 0");
|
||
}
|
||
|
||
// c. Let index be ! ToLength(integerIndex).
|
||
index = this.ToLength(realm, integerIndex);
|
||
|
||
// d. If SameValueZero(integerIndex, index) is false, throw a RangeError exception.
|
||
if ((0, _abstract.SameValueZero)(realm, new _index.NumberValue(realm, integerIndex), new _index.NumberValue(realm, index)) === false) {
|
||
throw realm.createErrorThrowCompletion(realm.intrinsics.RangeError, "integerIndex < 0");
|
||
}
|
||
}
|
||
// 3. Return index.
|
||
return index;
|
||
}
|
||
}, {
|
||
key: "ToIndexPartial",
|
||
value: function ToIndexPartial(realm, value) {
|
||
return this.ToIndex(realm, typeof value === "number" ? value : value.throwIfNotConcrete());
|
||
}
|
||
}, {
|
||
key: "ToNumber",
|
||
value: function ToNumber(realm, val) {
|
||
var num = this.ToNumberOrAbstract(realm, val);
|
||
if (typeof num !== "number") {
|
||
_index.AbstractValue.reportIntrospectionError(num);
|
||
throw new _errors.FatalError();
|
||
}
|
||
return num;
|
||
}
|
||
|
||
// ECMA262 7.1.3
|
||
|
||
}, {
|
||
key: "ToNumberOrAbstract",
|
||
value: function ToNumberOrAbstract(realm, val) {
|
||
if (typeof val === "number") {
|
||
return val;
|
||
} else if (val instanceof _index.AbstractValue) {
|
||
return val;
|
||
} else if (val instanceof _index.UndefinedValue) {
|
||
return NaN;
|
||
} else if (val instanceof _index.NullValue) {
|
||
return +0;
|
||
} else if (val instanceof _index.ObjectValue) {
|
||
var prim = this.ToPrimitiveOrAbstract(realm, val, "number");
|
||
return this.ToNumberOrAbstract(realm, prim);
|
||
} else if (val instanceof _index.BooleanValue) {
|
||
if (val.value === true) {
|
||
return 1;
|
||
} else {
|
||
// `val.value === false`
|
||
return 0;
|
||
}
|
||
} else if (val instanceof _index.NumberValue) {
|
||
return val.value;
|
||
} else if (val instanceof _index.StringValue) {
|
||
return Number(val.value);
|
||
} else if (val instanceof _index.SymbolValue) {
|
||
throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError);
|
||
} else {
|
||
(0, _invariant2.default)(false, "unexpected type of value");
|
||
}
|
||
}
|
||
}, {
|
||
key: "IsToNumberPure",
|
||
value: function IsToNumberPure(realm, val) {
|
||
if (val instanceof _index.Value) {
|
||
if (this.IsToPrimitivePure(realm, val)) {
|
||
var type = val.getType();
|
||
return type !== _index.SymbolValue && type !== _index.PrimitiveValue && type !== _index.Value;
|
||
}
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
// ECMA262 7.1.1
|
||
|
||
}, {
|
||
key: "ToPrimitive",
|
||
value: function ToPrimitive(realm, input, hint) {
|
||
return this.ToPrimitiveOrAbstract(realm, input, hint).throwIfNotConcretePrimitive();
|
||
}
|
||
}, {
|
||
key: "ToPrimitiveOrAbstract",
|
||
value: function ToPrimitiveOrAbstract(realm, input, hint) {
|
||
if (input instanceof _index.PrimitiveValue) {
|
||
return input;
|
||
}
|
||
|
||
// When Type(input) is Object, the following steps are taken
|
||
(0, _invariant2.default)(input instanceof _index.ObjectValue, "expected an object");
|
||
|
||
// 1. If PreferredType was not passed, let hint be "default".
|
||
hint = hint || "default";
|
||
|
||
// Following two steps are redundant since we just pass string hints.
|
||
// 2. Else if PreferredType is hint String, let hint be "string".
|
||
// 3. Else PreferredType is hint Number, let hint be "number".
|
||
|
||
// 4. Let exoticToPrim be ? GetMethod(input, @@toPrimitive).
|
||
var exoticToPrim = (0, _get.GetMethod)(realm, input, realm.intrinsics.SymbolToPrimitive);
|
||
|
||
// 5. If exoticToPrim is not undefined, then
|
||
if (!(exoticToPrim instanceof _index.UndefinedValue)) {
|
||
// a. Let result be ? Call(exoticToPrim, input, « hint »).
|
||
var result = (0, _call.Call)(realm, exoticToPrim, input, [new _index.StringValue(realm, hint)]);
|
||
|
||
// b. If Type(result) is not Object, return result.
|
||
if (!(result instanceof _index.ObjectValue)) {
|
||
(0, _invariant2.default)(result instanceof _index.PrimitiveValue);
|
||
return result;
|
||
}
|
||
|
||
// c. Throw a TypeError exception.
|
||
throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError);
|
||
}
|
||
|
||
// 6. If hint is "default", let hint be "number".
|
||
if (hint === "default") hint = "number";
|
||
|
||
// 7. Return ? OrdinaryToPrimitive(input, hint).
|
||
return this.OrdinaryToPrimitiveOrAbstract(realm, input, hint);
|
||
}
|
||
|
||
// Returns result type of ToPrimitive if it is pure (terminates, does not throw exception, does not read or write heap), otherwise undefined.
|
||
|
||
}, {
|
||
key: "GetToPrimitivePureResultType",
|
||
value: function GetToPrimitivePureResultType(realm, input) {
|
||
var type = input.getType();
|
||
if (input instanceof _index.PrimitiveValue) return type;
|
||
if (input instanceof _index.AbstractValue && _index.Value.isTypeCompatibleWith(type, _index.PrimitiveValue)) return type;
|
||
return undefined;
|
||
}
|
||
}, {
|
||
key: "IsToPrimitivePure",
|
||
value: function IsToPrimitivePure(realm, input) {
|
||
return this.GetToPrimitivePureResultType(realm, input) !== undefined;
|
||
}
|
||
|
||
// ECMA262 7.1.1
|
||
|
||
}, {
|
||
key: "OrdinaryToPrimitive",
|
||
value: function OrdinaryToPrimitive(realm, input, hint) {
|
||
return this.OrdinaryToPrimitiveOrAbstract(realm, input, hint).throwIfNotConcretePrimitive();
|
||
}
|
||
}, {
|
||
key: "OrdinaryToPrimitiveOrAbstract",
|
||
value: function OrdinaryToPrimitiveOrAbstract(realm, input, hint) {
|
||
var methodNames = void 0;
|
||
|
||
// 1. Assert: Type(O) is Object.
|
||
(0, _invariant2.default)(input instanceof _index.ObjectValue, "Expected object");
|
||
|
||
// 2. Assert: Type(hint) is String and its value is either "string" or "number".
|
||
(0, _invariant2.default)(hint === "string" || hint === "number", "Expected string or number hint");
|
||
|
||
// 3. If hint is "string", then
|
||
if (hint === "string") {
|
||
// a. Let methodNames be « "toString", "valueOf" ».
|
||
methodNames = ["toString", "valueOf"];
|
||
} else {
|
||
// 4. Else,
|
||
// a. Let methodNames be « "valueOf", "toString" ».
|
||
methodNames = ["valueOf", "toString"];
|
||
}
|
||
|
||
// 5. For each name in methodNames in List order, do
|
||
var _iteratorNormalCompletion = true;
|
||
var _didIteratorError = false;
|
||
var _iteratorError = undefined;
|
||
|
||
try {
|
||
for (var _iterator = methodNames[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
||
var name = _step.value;
|
||
|
||
// a. Let method be ? Get(O, name).
|
||
var method = (0, _get.Get)(realm, input, new _index.StringValue(realm, name));
|
||
|
||
// b. If IsCallable(method) is true, then
|
||
if ((0, _is.IsCallable)(realm, method)) {
|
||
// i. Let result be ? Call(method, O).
|
||
var result = (0, _call.Call)(realm, method, input);
|
||
var resultType = result.getType();
|
||
|
||
// ii. If Type(result) is not Object, return result.
|
||
if (_index.Value.isTypeCompatibleWith(resultType, _index.PrimitiveValue)) {
|
||
(0, _invariant2.default)(result instanceof _index.AbstractValue || result instanceof _index.PrimitiveValue);
|
||
return result;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 6. Throw a TypeError exception.
|
||
} catch (err) {
|
||
_didIteratorError = true;
|
||
_iteratorError = err;
|
||
} finally {
|
||
try {
|
||
if (!_iteratorNormalCompletion && _iterator.return) {
|
||
_iterator.return();
|
||
}
|
||
} finally {
|
||
if (_didIteratorError) {
|
||
throw _iteratorError;
|
||
}
|
||
}
|
||
}
|
||
|
||
throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError, "can't turn to primitive");
|
||
}
|
||
|
||
// ECMA262 7.1.12
|
||
|
||
}, {
|
||
key: "ToString",
|
||
value: function ToString(realm, val) {
|
||
if (typeof val === "string") {
|
||
return val;
|
||
} else if (val instanceof _index.StringValue) {
|
||
return val.value;
|
||
} else if (val instanceof _index.NumberValue) {
|
||
return val.value + "";
|
||
} else if (val instanceof _index.UndefinedValue) {
|
||
return "undefined";
|
||
} else if (val instanceof _index.NullValue) {
|
||
return "null";
|
||
} else if (val instanceof _index.SymbolValue) {
|
||
throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError);
|
||
} else if (val instanceof _index.BooleanValue) {
|
||
return val.value ? "true" : "false";
|
||
} else if (val instanceof _index.ObjectValue) {
|
||
var primValue = this.ToPrimitive(realm, val, "string");
|
||
return this.ToString(realm, primValue);
|
||
} else {
|
||
throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError, "unknown value type, can't coerce to string");
|
||
}
|
||
}
|
||
}, {
|
||
key: "ToStringPartial",
|
||
value: function ToStringPartial(realm, val) {
|
||
return this.ToString(realm, typeof val === "string" ? val : val.throwIfNotConcrete());
|
||
}
|
||
}, {
|
||
key: "ToStringValue",
|
||
value: function ToStringValue(realm, val) {
|
||
if (val.getType() === _index.StringValue) return val;
|
||
var str = void 0;
|
||
if (typeof val === "string") {
|
||
str = val;
|
||
} else if (val instanceof _index.NumberValue) {
|
||
str = val.value + "";
|
||
} else if (val instanceof _index.UndefinedValue) {
|
||
str = "undefined";
|
||
} else if (val instanceof _index.NullValue) {
|
||
str = "null";
|
||
} else if (val instanceof _index.SymbolValue) {
|
||
throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError);
|
||
} else if (val instanceof _index.BooleanValue) {
|
||
str = val.value ? "true" : "false";
|
||
} else if (val instanceof _index.ObjectValue) {
|
||
var primValue = this.ToPrimitiveOrAbstract(realm, val, "string");
|
||
if (primValue.getType() === _index.StringValue) return primValue;
|
||
str = this.ToStringPartial(realm, primValue);
|
||
} else {
|
||
throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError, "unknown value type, can't coerce to string");
|
||
}
|
||
return new _index.StringValue(realm, str);
|
||
}
|
||
|
||
// ECMA262 7.1.2
|
||
|
||
}, {
|
||
key: "ToBoolean",
|
||
value: function ToBoolean(realm, val) {
|
||
if (val instanceof _index.BooleanValue) {
|
||
return val.value;
|
||
} else if (val instanceof _index.UndefinedValue) {
|
||
return false;
|
||
} else if (val instanceof _index.NullValue) {
|
||
return false;
|
||
} else if (val instanceof _index.NumberValue) {
|
||
return val.value !== 0 && !isNaN(val.value);
|
||
} else if (val instanceof _index.StringValue) {
|
||
return val.value.length > 0;
|
||
} else if (val instanceof _index.ObjectValue) {
|
||
return true;
|
||
} else if (val instanceof _index.SymbolValue) {
|
||
return true;
|
||
} else {
|
||
(0, _invariant2.default)(!(val instanceof _index.AbstractValue));
|
||
throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError, "unknown value type, can't coerce to a boolean");
|
||
}
|
||
}
|
||
}, {
|
||
key: "ToBooleanPartial",
|
||
value: function ToBooleanPartial(realm, val) {
|
||
if (!val.mightNotBeObject()) return true;
|
||
return this.ToBoolean(realm, val.throwIfNotConcrete());
|
||
}
|
||
|
||
// ECMA262 7.1.14
|
||
|
||
}, {
|
||
key: "ToPropertyKey",
|
||
value: function ToPropertyKey(realm, arg) /* but not StringValue */{
|
||
// 1. Let key be ? ToPrimitive(argument, hint String).
|
||
var key = this.ToPrimitive(realm, arg, "string");
|
||
|
||
// 2. If Type(key) is Symbol, then
|
||
if (key instanceof _index.SymbolValue) {
|
||
// a. Return key.
|
||
return key;
|
||
}
|
||
|
||
// 3. Return ! ToString(key).
|
||
return this.ToString(realm, key);
|
||
}
|
||
}, {
|
||
key: "ToPropertyKeyPartial",
|
||
value: function ToPropertyKeyPartial(realm, arg) /* but not StringValue */{
|
||
if (arg instanceof _index.ConcreteValue) return this.ToPropertyKey(realm, arg);
|
||
if (arg.mightNotBeString() && arg.mightNotBeNumber()) arg.throwIfNotConcrete();
|
||
(0, _invariant2.default)(arg instanceof _index.AbstractValue);
|
||
return arg;
|
||
}
|
||
|
||
// ECMA262 7.1.16
|
||
|
||
}, {
|
||
key: "CanonicalNumericIndexString",
|
||
value: function CanonicalNumericIndexString(realm, argument) {
|
||
// 1. Assert: Type(argument) is String.
|
||
(0, _invariant2.default)(argument instanceof _index.StringValue);
|
||
|
||
// 2. If argument is "-0", return −0.
|
||
if (argument.value === "-0") return -0;
|
||
|
||
// 3. Let n be ToNumber(argument).
|
||
var n = this.ToNumber(realm, argument);
|
||
|
||
// 4. If SameValue(ToString(n), argument) is false, return undefined.
|
||
if ((0, _abstract.SameValue)(realm, new _index.StringValue(realm, this.ToString(realm, new _index.NumberValue(realm, n))), argument) === false) return undefined;
|
||
|
||
// 5. Return n.
|
||
return n;
|
||
}
|
||
}]);
|
||
|
||
return ToImplementation;
|
||
}();
|
||
//# sourceMappingURL=to.js.map
|