791 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			791 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|  | 'use strict'; | ||
|  | 
 | ||
|  | var has = require('has'); | ||
|  | var toPrimitive = require('es-to-primitive/es6'); | ||
|  | var keys = require('object-keys'); | ||
|  | 
 | ||
|  | var GetIntrinsic = require('./GetIntrinsic'); | ||
|  | 
 | ||
|  | var $TypeError = GetIntrinsic('%TypeError%'); | ||
|  | var $SyntaxError = GetIntrinsic('%SyntaxError%'); | ||
|  | var $Array = GetIntrinsic('%Array%'); | ||
|  | var $String = GetIntrinsic('%String%'); | ||
|  | var $Object = GetIntrinsic('%Object%'); | ||
|  | var $Number = GetIntrinsic('%Number%'); | ||
|  | var $Symbol = GetIntrinsic('%Symbol%', true); | ||
|  | var $RegExp = GetIntrinsic('%RegExp%'); | ||
|  | 
 | ||
|  | var hasSymbols = !!$Symbol; | ||
|  | 
 | ||
|  | var assertRecord = require('./helpers/assertRecord'); | ||
|  | var $isNaN = require('./helpers/isNaN'); | ||
|  | var $isFinite = require('./helpers/isFinite'); | ||
|  | var MAX_SAFE_INTEGER = $Number.MAX_SAFE_INTEGER || Math.pow(2, 53) - 1; | ||
|  | 
 | ||
|  | var assign = require('./helpers/assign'); | ||
|  | var sign = require('./helpers/sign'); | ||
|  | var mod = require('./helpers/mod'); | ||
|  | var isPrimitive = require('./helpers/isPrimitive'); | ||
|  | var parseInteger = parseInt; | ||
|  | var bind = require('function-bind'); | ||
|  | var arraySlice = bind.call(Function.call, $Array.prototype.slice); | ||
|  | var strSlice = bind.call(Function.call, $String.prototype.slice); | ||
|  | var isBinary = bind.call(Function.call, $RegExp.prototype.test, /^0b[01]+$/i); | ||
|  | var isOctal = bind.call(Function.call, $RegExp.prototype.test, /^0o[0-7]+$/i); | ||
|  | var regexExec = bind.call(Function.call, $RegExp.prototype.exec); | ||
|  | var nonWS = ['\u0085', '\u200b', '\ufffe'].join(''); | ||
|  | var nonWSregex = new $RegExp('[' + nonWS + ']', 'g'); | ||
|  | var hasNonWS = bind.call(Function.call, $RegExp.prototype.test, nonWSregex); | ||
|  | var invalidHexLiteral = /^[-+]0x[0-9a-f]+$/i; | ||
|  | var isInvalidHexLiteral = bind.call(Function.call, $RegExp.prototype.test, invalidHexLiteral); | ||
|  | var $charCodeAt = bind.call(Function.call, $String.prototype.charCodeAt); | ||
|  | 
 | ||
|  | var toStr = bind.call(Function.call, Object.prototype.toString); | ||
|  | 
 | ||
|  | var $NumberValueOf = bind.call(Function.call, GetIntrinsic('%NumberPrototype%').valueOf); | ||
|  | var $BooleanValueOf = bind.call(Function.call, GetIntrinsic('%BooleanPrototype%').valueOf); | ||
|  | var $StringValueOf = bind.call(Function.call, GetIntrinsic('%StringPrototype%').valueOf); | ||
|  | var $DateValueOf = bind.call(Function.call, GetIntrinsic('%DatePrototype%').valueOf); | ||
|  | 
 | ||
|  | var $floor = Math.floor; | ||
|  | var $abs = Math.abs; | ||
|  | 
 | ||
|  | var $ObjectCreate = Object.create; | ||
|  | var $gOPD = $Object.getOwnPropertyDescriptor; | ||
|  | 
 | ||
|  | var $isExtensible = $Object.isExtensible; | ||
|  | 
 | ||
|  | var $defineProperty = $Object.defineProperty; | ||
|  | 
 | ||
|  | // whitespace from: http://es5.github.io/#x15.5.4.20
 | ||
|  | // implementation from https://github.com/es-shims/es5-shim/blob/v3.4.0/es5-shim.js#L1304-L1324
 | ||
|  | var ws = [ | ||
|  | 	'\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003', | ||
|  | 	'\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028', | ||
|  | 	'\u2029\uFEFF' | ||
|  | ].join(''); | ||
|  | var trimRegex = new RegExp('(^[' + ws + ']+)|([' + ws + ']+$)', 'g'); | ||
|  | var replace = bind.call(Function.call, $String.prototype.replace); | ||
|  | var trim = function (value) { | ||
|  | 	return replace(value, trimRegex, ''); | ||
|  | }; | ||
|  | 
 | ||
|  | var ES5 = require('./es5'); | ||
|  | 
 | ||
|  | var hasRegExpMatcher = require('is-regex'); | ||
|  | 
 | ||
|  | // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-abstract-operations
 | ||
|  | var ES6 = assign(assign({}, ES5), { | ||
|  | 
 | ||
|  | 	// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-call-f-v-args
 | ||
|  | 	Call: function Call(F, V) { | ||
|  | 		var args = arguments.length > 2 ? arguments[2] : []; | ||
|  | 		if (!this.IsCallable(F)) { | ||
|  | 			throw new $TypeError(F + ' is not a function'); | ||
|  | 		} | ||
|  | 		return F.apply(V, args); | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-toprimitive
 | ||
|  | 	ToPrimitive: toPrimitive, | ||
|  | 
 | ||
|  | 	// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-toboolean
 | ||
|  | 	// ToBoolean: ES5.ToBoolean,
 | ||
|  | 
 | ||
|  | 	// https://ecma-international.org/ecma-262/6.0/#sec-tonumber
 | ||
|  | 	ToNumber: function ToNumber(argument) { | ||
|  | 		var value = isPrimitive(argument) ? argument : toPrimitive(argument, $Number); | ||
|  | 		if (typeof value === 'symbol') { | ||
|  | 			throw new $TypeError('Cannot convert a Symbol value to a number'); | ||
|  | 		} | ||
|  | 		if (typeof value === 'string') { | ||
|  | 			if (isBinary(value)) { | ||
|  | 				return this.ToNumber(parseInteger(strSlice(value, 2), 2)); | ||
|  | 			} else if (isOctal(value)) { | ||
|  | 				return this.ToNumber(parseInteger(strSlice(value, 2), 8)); | ||
|  | 			} else if (hasNonWS(value) || isInvalidHexLiteral(value)) { | ||
|  | 				return NaN; | ||
|  | 			} else { | ||
|  | 				var trimmed = trim(value); | ||
|  | 				if (trimmed !== value) { | ||
|  | 					return this.ToNumber(trimmed); | ||
|  | 				} | ||
|  | 			} | ||
|  | 		} | ||
|  | 		return $Number(value); | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tointeger
 | ||
|  | 	// ToInteger: ES5.ToNumber,
 | ||
|  | 
 | ||
|  | 	// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-toint32
 | ||
|  | 	// ToInt32: ES5.ToInt32,
 | ||
|  | 
 | ||
|  | 	// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-touint32
 | ||
|  | 	// ToUint32: ES5.ToUint32,
 | ||
|  | 
 | ||
|  | 	// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-toint16
 | ||
|  | 	ToInt16: function ToInt16(argument) { | ||
|  | 		var int16bit = this.ToUint16(argument); | ||
|  | 		return int16bit >= 0x8000 ? int16bit - 0x10000 : int16bit; | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-touint16
 | ||
|  | 	// ToUint16: ES5.ToUint16,
 | ||
|  | 
 | ||
|  | 	// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-toint8
 | ||
|  | 	ToInt8: function ToInt8(argument) { | ||
|  | 		var int8bit = this.ToUint8(argument); | ||
|  | 		return int8bit >= 0x80 ? int8bit - 0x100 : int8bit; | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-touint8
 | ||
|  | 	ToUint8: function ToUint8(argument) { | ||
|  | 		var number = this.ToNumber(argument); | ||
|  | 		if ($isNaN(number) || number === 0 || !$isFinite(number)) { return 0; } | ||
|  | 		var posInt = sign(number) * $floor($abs(number)); | ||
|  | 		return mod(posInt, 0x100); | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-touint8clamp
 | ||
|  | 	ToUint8Clamp: function ToUint8Clamp(argument) { | ||
|  | 		var number = this.ToNumber(argument); | ||
|  | 		if ($isNaN(number) || number <= 0) { return 0; } | ||
|  | 		if (number >= 0xFF) { return 0xFF; } | ||
|  | 		var f = $floor(argument); | ||
|  | 		if (f + 0.5 < number) { return f + 1; } | ||
|  | 		if (number < f + 0.5) { return f; } | ||
|  | 		if (f % 2 !== 0) { return f + 1; } | ||
|  | 		return f; | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tostring
 | ||
|  | 	ToString: function ToString(argument) { | ||
|  | 		if (typeof argument === 'symbol') { | ||
|  | 			throw new $TypeError('Cannot convert a Symbol value to a string'); | ||
|  | 		} | ||
|  | 		return $String(argument); | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-toobject
 | ||
|  | 	ToObject: function ToObject(value) { | ||
|  | 		this.RequireObjectCoercible(value); | ||
|  | 		return $Object(value); | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-topropertykey
 | ||
|  | 	ToPropertyKey: function ToPropertyKey(argument) { | ||
|  | 		var key = this.ToPrimitive(argument, $String); | ||
|  | 		return typeof key === 'symbol' ? key : this.ToString(key); | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength
 | ||
|  | 	ToLength: function ToLength(argument) { | ||
|  | 		var len = this.ToInteger(argument); | ||
|  | 		if (len <= 0) { return 0; } // includes converting -0 to +0
 | ||
|  | 		if (len > MAX_SAFE_INTEGER) { return MAX_SAFE_INTEGER; } | ||
|  | 		return len; | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://ecma-international.org/ecma-262/6.0/#sec-canonicalnumericindexstring
 | ||
|  | 	CanonicalNumericIndexString: function CanonicalNumericIndexString(argument) { | ||
|  | 		if (toStr(argument) !== '[object String]') { | ||
|  | 			throw new $TypeError('must be a string'); | ||
|  | 		} | ||
|  | 		if (argument === '-0') { return -0; } | ||
|  | 		var n = this.ToNumber(argument); | ||
|  | 		if (this.SameValue(this.ToString(n), argument)) { return n; } | ||
|  | 		return void 0; | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-requireobjectcoercible
 | ||
|  | 	RequireObjectCoercible: ES5.CheckObjectCoercible, | ||
|  | 
 | ||
|  | 	// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-isarray
 | ||
|  | 	IsArray: $Array.isArray || function IsArray(argument) { | ||
|  | 		return toStr(argument) === '[object Array]'; | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-iscallable
 | ||
|  | 	// IsCallable: ES5.IsCallable,
 | ||
|  | 
 | ||
|  | 	// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-isconstructor
 | ||
|  | 	IsConstructor: function IsConstructor(argument) { | ||
|  | 		return typeof argument === 'function' && !!argument.prototype; // unfortunately there's no way to truly check this without try/catch `new argument`
 | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-isextensible-o
 | ||
|  | 	IsExtensible: Object.preventExtensions | ||
|  | 		? function IsExtensible(obj) { | ||
|  | 			if (isPrimitive(obj)) { | ||
|  | 				return false; | ||
|  | 			} | ||
|  | 			return $isExtensible(obj); | ||
|  | 		} | ||
|  | 		: function isExtensible(obj) { return true; }, // eslint-disable-line no-unused-vars
 | ||
|  | 
 | ||
|  | 	// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-isinteger
 | ||
|  | 	IsInteger: function IsInteger(argument) { | ||
|  | 		if (typeof argument !== 'number' || $isNaN(argument) || !$isFinite(argument)) { | ||
|  | 			return false; | ||
|  | 		} | ||
|  | 		var abs = $abs(argument); | ||
|  | 		return $floor(abs) === abs; | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-ispropertykey
 | ||
|  | 	IsPropertyKey: function IsPropertyKey(argument) { | ||
|  | 		return typeof argument === 'string' || typeof argument === 'symbol'; | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://ecma-international.org/ecma-262/6.0/#sec-isregexp
 | ||
|  | 	IsRegExp: function IsRegExp(argument) { | ||
|  | 		if (!argument || typeof argument !== 'object') { | ||
|  | 			return false; | ||
|  | 		} | ||
|  | 		if (hasSymbols) { | ||
|  | 			var isRegExp = argument[$Symbol.match]; | ||
|  | 			if (typeof isRegExp !== 'undefined') { | ||
|  | 				return ES5.ToBoolean(isRegExp); | ||
|  | 			} | ||
|  | 		} | ||
|  | 		return hasRegExpMatcher(argument); | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevalue
 | ||
|  | 	// SameValue: ES5.SameValue,
 | ||
|  | 
 | ||
|  | 	// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero
 | ||
|  | 	SameValueZero: function SameValueZero(x, y) { | ||
|  | 		return (x === y) || ($isNaN(x) && $isNaN(y)); | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * 7.3.2 GetV (V, P) | ||
|  | 	 * 1. Assert: IsPropertyKey(P) is true. | ||
|  | 	 * 2. Let O be ToObject(V). | ||
|  | 	 * 3. ReturnIfAbrupt(O). | ||
|  | 	 * 4. Return O.[[Get]](P, V). | ||
|  | 	 */ | ||
|  | 	GetV: function GetV(V, P) { | ||
|  | 		// 7.3.2.1
 | ||
|  | 		if (!this.IsPropertyKey(P)) { | ||
|  | 			throw new $TypeError('Assertion failed: IsPropertyKey(P) is not true'); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		// 7.3.2.2-3
 | ||
|  | 		var O = this.ToObject(V); | ||
|  | 
 | ||
|  | 		// 7.3.2.4
 | ||
|  | 		return O[P]; | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * 7.3.9 - https://ecma-international.org/ecma-262/6.0/#sec-getmethod
 | ||
|  | 	 * 1. Assert: IsPropertyKey(P) is true. | ||
|  | 	 * 2. Let func be GetV(O, P). | ||
|  | 	 * 3. ReturnIfAbrupt(func). | ||
|  | 	 * 4. If func is either undefined or null, return undefined. | ||
|  | 	 * 5. If IsCallable(func) is false, throw a TypeError exception. | ||
|  | 	 * 6. Return func. | ||
|  | 	 */ | ||
|  | 	GetMethod: function GetMethod(O, P) { | ||
|  | 		// 7.3.9.1
 | ||
|  | 		if (!this.IsPropertyKey(P)) { | ||
|  | 			throw new $TypeError('Assertion failed: IsPropertyKey(P) is not true'); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		// 7.3.9.2
 | ||
|  | 		var func = this.GetV(O, P); | ||
|  | 
 | ||
|  | 		// 7.3.9.4
 | ||
|  | 		if (func == null) { | ||
|  | 			return void 0; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		// 7.3.9.5
 | ||
|  | 		if (!this.IsCallable(func)) { | ||
|  | 			throw new $TypeError(P + 'is not a function'); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		// 7.3.9.6
 | ||
|  | 		return func; | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	/** | ||
|  | 	 * 7.3.1 Get (O, P) - https://ecma-international.org/ecma-262/6.0/#sec-get-o-p
 | ||
|  | 	 * 1. Assert: Type(O) is Object. | ||
|  | 	 * 2. Assert: IsPropertyKey(P) is true. | ||
|  | 	 * 3. Return O.[[Get]](P, O). | ||
|  | 	 */ | ||
|  | 	Get: function Get(O, P) { | ||
|  | 		// 7.3.1.1
 | ||
|  | 		if (this.Type(O) !== 'Object') { | ||
|  | 			throw new $TypeError('Assertion failed: Type(O) is not Object'); | ||
|  | 		} | ||
|  | 		// 7.3.1.2
 | ||
|  | 		if (!this.IsPropertyKey(P)) { | ||
|  | 			throw new $TypeError('Assertion failed: IsPropertyKey(P) is not true'); | ||
|  | 		} | ||
|  | 		// 7.3.1.3
 | ||
|  | 		return O[P]; | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	Type: function Type(x) { | ||
|  | 		if (typeof x === 'symbol') { | ||
|  | 			return 'Symbol'; | ||
|  | 		} | ||
|  | 		return ES5.Type(x); | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://ecma-international.org/ecma-262/6.0/#sec-speciesconstructor
 | ||
|  | 	SpeciesConstructor: function SpeciesConstructor(O, defaultConstructor) { | ||
|  | 		if (this.Type(O) !== 'Object') { | ||
|  | 			throw new $TypeError('Assertion failed: Type(O) is not Object'); | ||
|  | 		} | ||
|  | 		var C = O.constructor; | ||
|  | 		if (typeof C === 'undefined') { | ||
|  | 			return defaultConstructor; | ||
|  | 		} | ||
|  | 		if (this.Type(C) !== 'Object') { | ||
|  | 			throw new $TypeError('O.constructor is not an Object'); | ||
|  | 		} | ||
|  | 		var S = hasSymbols && $Symbol.species ? C[$Symbol.species] : void 0; | ||
|  | 		if (S == null) { | ||
|  | 			return defaultConstructor; | ||
|  | 		} | ||
|  | 		if (this.IsConstructor(S)) { | ||
|  | 			return S; | ||
|  | 		} | ||
|  | 		throw new $TypeError('no constructor found'); | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://ecma-international.org/ecma-262/6.0/#sec-completepropertydescriptor
 | ||
|  | 	CompletePropertyDescriptor: function CompletePropertyDescriptor(Desc) { | ||
|  | 		assertRecord(this, 'Property Descriptor', 'Desc', Desc); | ||
|  | 
 | ||
|  | 		if (this.IsGenericDescriptor(Desc) || this.IsDataDescriptor(Desc)) { | ||
|  | 			if (!has(Desc, '[[Value]]')) { | ||
|  | 				Desc['[[Value]]'] = void 0; | ||
|  | 			} | ||
|  | 			if (!has(Desc, '[[Writable]]')) { | ||
|  | 				Desc['[[Writable]]'] = false; | ||
|  | 			} | ||
|  | 		} else { | ||
|  | 			if (!has(Desc, '[[Get]]')) { | ||
|  | 				Desc['[[Get]]'] = void 0; | ||
|  | 			} | ||
|  | 			if (!has(Desc, '[[Set]]')) { | ||
|  | 				Desc['[[Set]]'] = void 0; | ||
|  | 			} | ||
|  | 		} | ||
|  | 		if (!has(Desc, '[[Enumerable]]')) { | ||
|  | 			Desc['[[Enumerable]]'] = false; | ||
|  | 		} | ||
|  | 		if (!has(Desc, '[[Configurable]]')) { | ||
|  | 			Desc['[[Configurable]]'] = false; | ||
|  | 		} | ||
|  | 		return Desc; | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://ecma-international.org/ecma-262/6.0/#sec-set-o-p-v-throw
 | ||
|  | 	Set: function Set(O, P, V, Throw) { | ||
|  | 		if (this.Type(O) !== 'Object') { | ||
|  | 			throw new $TypeError('O must be an Object'); | ||
|  | 		} | ||
|  | 		if (!this.IsPropertyKey(P)) { | ||
|  | 			throw new $TypeError('P must be a Property Key'); | ||
|  | 		} | ||
|  | 		if (this.Type(Throw) !== 'Boolean') { | ||
|  | 			throw new $TypeError('Throw must be a Boolean'); | ||
|  | 		} | ||
|  | 		if (Throw) { | ||
|  | 			O[P] = V; | ||
|  | 			return true; | ||
|  | 		} else { | ||
|  | 			try { | ||
|  | 				O[P] = V; | ||
|  | 			} catch (e) { | ||
|  | 				return false; | ||
|  | 			} | ||
|  | 		} | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://ecma-international.org/ecma-262/6.0/#sec-hasownproperty
 | ||
|  | 	HasOwnProperty: function HasOwnProperty(O, P) { | ||
|  | 		if (this.Type(O) !== 'Object') { | ||
|  | 			throw new $TypeError('O must be an Object'); | ||
|  | 		} | ||
|  | 		if (!this.IsPropertyKey(P)) { | ||
|  | 			throw new $TypeError('P must be a Property Key'); | ||
|  | 		} | ||
|  | 		return has(O, P); | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://ecma-international.org/ecma-262/6.0/#sec-hasproperty
 | ||
|  | 	HasProperty: function HasProperty(O, P) { | ||
|  | 		if (this.Type(O) !== 'Object') { | ||
|  | 			throw new $TypeError('O must be an Object'); | ||
|  | 		} | ||
|  | 		if (!this.IsPropertyKey(P)) { | ||
|  | 			throw new $TypeError('P must be a Property Key'); | ||
|  | 		} | ||
|  | 		return P in O; | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://ecma-international.org/ecma-262/6.0/#sec-isconcatspreadable
 | ||
|  | 	IsConcatSpreadable: function IsConcatSpreadable(O) { | ||
|  | 		if (this.Type(O) !== 'Object') { | ||
|  | 			return false; | ||
|  | 		} | ||
|  | 		if (hasSymbols && typeof $Symbol.isConcatSpreadable === 'symbol') { | ||
|  | 			var spreadable = this.Get(O, Symbol.isConcatSpreadable); | ||
|  | 			if (typeof spreadable !== 'undefined') { | ||
|  | 				return this.ToBoolean(spreadable); | ||
|  | 			} | ||
|  | 		} | ||
|  | 		return this.IsArray(O); | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://ecma-international.org/ecma-262/6.0/#sec-invoke
 | ||
|  | 	Invoke: function Invoke(O, P) { | ||
|  | 		if (!this.IsPropertyKey(P)) { | ||
|  | 			throw new $TypeError('P must be a Property Key'); | ||
|  | 		} | ||
|  | 		var argumentsList = arraySlice(arguments, 2); | ||
|  | 		var func = this.GetV(O, P); | ||
|  | 		return this.Call(func, O, argumentsList); | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://ecma-international.org/ecma-262/6.0/#sec-getiterator
 | ||
|  | 	GetIterator: function GetIterator(obj, method) { | ||
|  | 		if (!hasSymbols) { | ||
|  | 			throw new SyntaxError('ES.GetIterator depends on native iterator support.'); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		var actualMethod = method; | ||
|  | 		if (arguments.length < 2) { | ||
|  | 			actualMethod = this.GetMethod(obj, $Symbol.iterator); | ||
|  | 		} | ||
|  | 		var iterator = this.Call(actualMethod, obj); | ||
|  | 		if (this.Type(iterator) !== 'Object') { | ||
|  | 			throw new $TypeError('iterator must return an object'); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		return iterator; | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://ecma-international.org/ecma-262/6.0/#sec-iteratornext
 | ||
|  | 	IteratorNext: function IteratorNext(iterator, value) { | ||
|  | 		var result = this.Invoke(iterator, 'next', arguments.length < 2 ? [] : [value]); | ||
|  | 		if (this.Type(result) !== 'Object') { | ||
|  | 			throw new $TypeError('iterator next must return an object'); | ||
|  | 		} | ||
|  | 		return result; | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://ecma-international.org/ecma-262/6.0/#sec-iteratorcomplete
 | ||
|  | 	IteratorComplete: function IteratorComplete(iterResult) { | ||
|  | 		if (this.Type(iterResult) !== 'Object') { | ||
|  | 			throw new $TypeError('Assertion failed: Type(iterResult) is not Object'); | ||
|  | 		} | ||
|  | 		return this.ToBoolean(this.Get(iterResult, 'done')); | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://ecma-international.org/ecma-262/6.0/#sec-iteratorvalue
 | ||
|  | 	IteratorValue: function IteratorValue(iterResult) { | ||
|  | 		if (this.Type(iterResult) !== 'Object') { | ||
|  | 			throw new $TypeError('Assertion failed: Type(iterResult) is not Object'); | ||
|  | 		} | ||
|  | 		return this.Get(iterResult, 'value'); | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://ecma-international.org/ecma-262/6.0/#sec-iteratorstep
 | ||
|  | 	IteratorStep: function IteratorStep(iterator) { | ||
|  | 		var result = this.IteratorNext(iterator); | ||
|  | 		var done = this.IteratorComplete(result); | ||
|  | 		return done === true ? false : result; | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://ecma-international.org/ecma-262/6.0/#sec-iteratorclose
 | ||
|  | 	IteratorClose: function IteratorClose(iterator, completion) { | ||
|  | 		if (this.Type(iterator) !== 'Object') { | ||
|  | 			throw new $TypeError('Assertion failed: Type(iterator) is not Object'); | ||
|  | 		} | ||
|  | 		if (!this.IsCallable(completion)) { | ||
|  | 			throw new $TypeError('Assertion failed: completion is not a thunk for a Completion Record'); | ||
|  | 		} | ||
|  | 		var completionThunk = completion; | ||
|  | 
 | ||
|  | 		var iteratorReturn = this.GetMethod(iterator, 'return'); | ||
|  | 
 | ||
|  | 		if (typeof iteratorReturn === 'undefined') { | ||
|  | 			return completionThunk(); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		var completionRecord; | ||
|  | 		try { | ||
|  | 			var innerResult = this.Call(iteratorReturn, iterator, []); | ||
|  | 		} catch (e) { | ||
|  | 			// if we hit here, then "e" is the innerResult completion that needs re-throwing
 | ||
|  | 
 | ||
|  | 			// if the completion is of type "throw", this will throw.
 | ||
|  | 			completionRecord = completionThunk(); | ||
|  | 			completionThunk = null; // ensure it's not called twice.
 | ||
|  | 
 | ||
|  | 			// if not, then return the innerResult completion
 | ||
|  | 			throw e; | ||
|  | 		} | ||
|  | 		completionRecord = completionThunk(); // if innerResult worked, then throw if the completion does
 | ||
|  | 		completionThunk = null; // ensure it's not called twice.
 | ||
|  | 
 | ||
|  | 		if (this.Type(innerResult) !== 'Object') { | ||
|  | 			throw new $TypeError('iterator .return must return an object'); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		return completionRecord; | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://ecma-international.org/ecma-262/6.0/#sec-createiterresultobject
 | ||
|  | 	CreateIterResultObject: function CreateIterResultObject(value, done) { | ||
|  | 		if (this.Type(done) !== 'Boolean') { | ||
|  | 			throw new $TypeError('Assertion failed: Type(done) is not Boolean'); | ||
|  | 		} | ||
|  | 		return { | ||
|  | 			value: value, | ||
|  | 			done: done | ||
|  | 		}; | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://ecma-international.org/ecma-262/6.0/#sec-regexpexec
 | ||
|  | 	RegExpExec: function RegExpExec(R, S) { | ||
|  | 		if (this.Type(R) !== 'Object') { | ||
|  | 			throw new $TypeError('R must be an Object'); | ||
|  | 		} | ||
|  | 		if (this.Type(S) !== 'String') { | ||
|  | 			throw new $TypeError('S must be a String'); | ||
|  | 		} | ||
|  | 		var exec = this.Get(R, 'exec'); | ||
|  | 		if (this.IsCallable(exec)) { | ||
|  | 			var result = this.Call(exec, R, [S]); | ||
|  | 			if (result === null || this.Type(result) === 'Object') { | ||
|  | 				return result; | ||
|  | 			} | ||
|  | 			throw new $TypeError('"exec" method must return `null` or an Object'); | ||
|  | 		} | ||
|  | 		return regexExec(R, S); | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://ecma-international.org/ecma-262/6.0/#sec-arrayspeciescreate
 | ||
|  | 	ArraySpeciesCreate: function ArraySpeciesCreate(originalArray, length) { | ||
|  | 		if (!this.IsInteger(length) || length < 0) { | ||
|  | 			throw new $TypeError('Assertion failed: length must be an integer >= 0'); | ||
|  | 		} | ||
|  | 		var len = length === 0 ? 0 : length; | ||
|  | 		var C; | ||
|  | 		var isArray = this.IsArray(originalArray); | ||
|  | 		if (isArray) { | ||
|  | 			C = this.Get(originalArray, 'constructor'); | ||
|  | 			// TODO: figure out how to make a cross-realm normal Array, a same-realm Array
 | ||
|  | 			// if (this.IsConstructor(C)) {
 | ||
|  | 			// 	if C is another realm's Array, C = undefined
 | ||
|  | 			// 	Object.getPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf(Array))) === null ?
 | ||
|  | 			// }
 | ||
|  | 			if (this.Type(C) === 'Object' && hasSymbols && $Symbol.species) { | ||
|  | 				C = this.Get(C, $Symbol.species); | ||
|  | 				if (C === null) { | ||
|  | 					C = void 0; | ||
|  | 				} | ||
|  | 			} | ||
|  | 		} | ||
|  | 		if (typeof C === 'undefined') { | ||
|  | 			return $Array(len); | ||
|  | 		} | ||
|  | 		if (!this.IsConstructor(C)) { | ||
|  | 			throw new $TypeError('C must be a constructor'); | ||
|  | 		} | ||
|  | 		return new C(len); // this.Construct(C, len);
 | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	CreateDataProperty: function CreateDataProperty(O, P, V) { | ||
|  | 		if (this.Type(O) !== 'Object') { | ||
|  | 			throw new $TypeError('Assertion failed: Type(O) is not Object'); | ||
|  | 		} | ||
|  | 		if (!this.IsPropertyKey(P)) { | ||
|  | 			throw new $TypeError('Assertion failed: IsPropertyKey(P) is not true'); | ||
|  | 		} | ||
|  | 		var oldDesc = $gOPD(O, P); | ||
|  | 		var extensible = oldDesc || (typeof $isExtensible !== 'function' || $isExtensible(O)); | ||
|  | 		var immutable = oldDesc && (!oldDesc.writable || !oldDesc.configurable); | ||
|  | 		if (immutable || !extensible) { | ||
|  | 			return false; | ||
|  | 		} | ||
|  | 		var newDesc = { | ||
|  | 			configurable: true, | ||
|  | 			enumerable: true, | ||
|  | 			value: V, | ||
|  | 			writable: true | ||
|  | 		}; | ||
|  | 		$defineProperty(O, P, newDesc); | ||
|  | 		return true; | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://ecma-international.org/ecma-262/6.0/#sec-createdatapropertyorthrow
 | ||
|  | 	CreateDataPropertyOrThrow: function CreateDataPropertyOrThrow(O, P, V) { | ||
|  | 		if (this.Type(O) !== 'Object') { | ||
|  | 			throw new $TypeError('Assertion failed: Type(O) is not Object'); | ||
|  | 		} | ||
|  | 		if (!this.IsPropertyKey(P)) { | ||
|  | 			throw new $TypeError('Assertion failed: IsPropertyKey(P) is not true'); | ||
|  | 		} | ||
|  | 		var success = this.CreateDataProperty(O, P, V); | ||
|  | 		if (!success) { | ||
|  | 			throw new $TypeError('unable to create data property'); | ||
|  | 		} | ||
|  | 		return success; | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://www.ecma-international.org/ecma-262/6.0/#sec-objectcreate
 | ||
|  | 	ObjectCreate: function ObjectCreate(proto, internalSlotsList) { | ||
|  | 		if (proto !== null && this.Type(proto) !== 'Object') { | ||
|  | 			throw new $TypeError('Assertion failed: proto must be null or an object'); | ||
|  | 		} | ||
|  | 		var slots = arguments.length < 2 ? [] : internalSlotsList; | ||
|  | 		if (slots.length > 0) { | ||
|  | 			throw new $SyntaxError('es-abstract does not yet support internal slots'); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		if (proto === null && !$ObjectCreate) { | ||
|  | 			throw new $SyntaxError('native Object.create support is required to create null objects'); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		return $ObjectCreate(proto); | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://ecma-international.org/ecma-262/6.0/#sec-advancestringindex
 | ||
|  | 	AdvanceStringIndex: function AdvanceStringIndex(S, index, unicode) { | ||
|  | 		if (this.Type(S) !== 'String') { | ||
|  | 			throw new $TypeError('S must be a String'); | ||
|  | 		} | ||
|  | 		if (!this.IsInteger(index) || index < 0 || index > MAX_SAFE_INTEGER) { | ||
|  | 			throw new $TypeError('Assertion failed: length must be an integer >= 0 and <= 2**53'); | ||
|  | 		} | ||
|  | 		if (this.Type(unicode) !== 'Boolean') { | ||
|  | 			throw new $TypeError('Assertion failed: unicode must be a Boolean'); | ||
|  | 		} | ||
|  | 		if (!unicode) { | ||
|  | 			return index + 1; | ||
|  | 		} | ||
|  | 		var length = S.length; | ||
|  | 		if ((index + 1) >= length) { | ||
|  | 			return index + 1; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		var first = $charCodeAt(S, index); | ||
|  | 		if (first < 0xD800 || first > 0xDBFF) { | ||
|  | 			return index + 1; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		var second = $charCodeAt(S, index + 1); | ||
|  | 		if (second < 0xDC00 || second > 0xDFFF) { | ||
|  | 			return index + 1; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		return index + 2; | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://www.ecma-international.org/ecma-262/6.0/#sec-createmethodproperty
 | ||
|  | 	CreateMethodProperty: function CreateMethodProperty(O, P, V) { | ||
|  | 		if (this.Type(O) !== 'Object') { | ||
|  | 			throw new $TypeError('Assertion failed: Type(O) is not Object'); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		if (!this.IsPropertyKey(P)) { | ||
|  | 			throw new $TypeError('Assertion failed: IsPropertyKey(P) is not true'); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		var newDesc = { | ||
|  | 			configurable: true, | ||
|  | 			enumerable: false, | ||
|  | 			value: V, | ||
|  | 			writable: true | ||
|  | 		}; | ||
|  | 		return !!$defineProperty(O, P, newDesc); | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://www.ecma-international.org/ecma-262/6.0/#sec-definepropertyorthrow
 | ||
|  | 	DefinePropertyOrThrow: function DefinePropertyOrThrow(O, P, desc) { | ||
|  | 		if (this.Type(O) !== 'Object') { | ||
|  | 			throw new $TypeError('Assertion failed: Type(O) is not Object'); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		if (!this.IsPropertyKey(P)) { | ||
|  | 			throw new $TypeError('Assertion failed: IsPropertyKey(P) is not true'); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		return !!$defineProperty(O, P, desc); | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://www.ecma-international.org/ecma-262/6.0/#sec-deletepropertyorthrow
 | ||
|  | 	DeletePropertyOrThrow: function DeletePropertyOrThrow(O, P) { | ||
|  | 		if (this.Type(O) !== 'Object') { | ||
|  | 			throw new $TypeError('Assertion failed: Type(O) is not Object'); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		if (!this.IsPropertyKey(P)) { | ||
|  | 			throw new $TypeError('Assertion failed: IsPropertyKey(P) is not true'); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		var success = delete O[P]; | ||
|  | 		if (!success) { | ||
|  | 			throw new TypeError('Attempt to delete property failed.'); | ||
|  | 		} | ||
|  | 		return success; | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://www.ecma-international.org/ecma-262/6.0/#sec-enumerableownnames
 | ||
|  | 	EnumerableOwnNames: function EnumerableOwnNames(O) { | ||
|  | 		if (this.Type(O) !== 'Object') { | ||
|  | 			throw new $TypeError('Assertion failed: Type(O) is not Object'); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		return keys(O); | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://ecma-international.org/ecma-262/6.0/#sec-properties-of-the-number-prototype-object
 | ||
|  | 	thisNumberValue: function thisNumberValue(value) { | ||
|  | 		if (this.Type(value) === 'Number') { | ||
|  | 			return value; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		return $NumberValueOf(value); | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://ecma-international.org/ecma-262/6.0/#sec-properties-of-the-boolean-prototype-object
 | ||
|  | 	thisBooleanValue: function thisBooleanValue(value) { | ||
|  | 		if (this.Type(value) === 'Boolean') { | ||
|  | 			return value; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		return $BooleanValueOf(value); | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://ecma-international.org/ecma-262/6.0/#sec-properties-of-the-string-prototype-object
 | ||
|  | 	thisStringValue: function thisStringValue(value) { | ||
|  | 		if (this.Type(value) === 'String') { | ||
|  | 			return value; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		return $StringValueOf(value); | ||
|  | 	}, | ||
|  | 
 | ||
|  | 	// https://ecma-international.org/ecma-262/6.0/#sec-properties-of-the-date-prototype-object
 | ||
|  | 	thisTimeValue: function thisTimeValue(value) { | ||
|  | 		return $DateValueOf(value); | ||
|  | 	} | ||
|  | }); | ||
|  | 
 | ||
|  | delete ES6.CheckObjectCoercible; // renamed in ES6 to RequireObjectCoercible
 | ||
|  | 
 | ||
|  | module.exports = ES6; |