| 'use strict'; | 
 |  | 
 | var has = require('has'); | 
 | var toPrimitive = require('es-to-primitive/es6'); | 
 | var keys = require('object-keys'); | 
 | var inspect = require('object-inspect'); | 
 |  | 
 | var GetIntrinsic = require('./GetIntrinsic'); | 
 |  | 
 | var $TypeError = GetIntrinsic('%TypeError%'); | 
 | var $RangeError = GetIntrinsic('%RangeError%'); | 
 | var $SyntaxError = GetIntrinsic('%SyntaxError%'); | 
 | var $Array = GetIntrinsic('%Array%'); | 
 | var $ArrayPrototype = $Array.prototype; | 
 | var $String = GetIntrinsic('%String%'); | 
 | var $Object = GetIntrinsic('%Object%'); | 
 | var $Number = GetIntrinsic('%Number%'); | 
 | var $Symbol = GetIntrinsic('%Symbol%', true); | 
 | var $RegExp = GetIntrinsic('%RegExp%'); | 
 | var $Date = GetIntrinsic('%Date%'); | 
 | var $Function = GetIntrinsic('%Function%'); | 
 | var $preventExtensions = $Object.preventExtensions; | 
 |  | 
 | var hasSymbols = require('has-symbols')(); | 
 |  | 
 | var assertRecord = require('./helpers/assertRecord'); | 
 | var $isNaN = require('./helpers/isNaN'); | 
 | var $isFinite = require('./helpers/isFinite'); | 
 | var MAX_ARRAY_LENGTH = Math.pow(2, 32) - 1; | 
 | var MAX_SAFE_INTEGER = require('./helpers/maxSafeInteger'); | 
 |  | 
 | var assign = require('./helpers/assign'); | 
 | var sign = require('./helpers/sign'); | 
 | var mod = require('./helpers/mod'); | 
 | var isPrimitive = require('./helpers/isPrimitive'); | 
 | var forEach = require('./helpers/forEach'); | 
 | var every = require('./helpers/every'); | 
 | var isSamePropertyDescriptor = require('./helpers/isSamePropertyDescriptor'); | 
 | var isPropertyDescriptor = require('./helpers/isPropertyDescriptor'); | 
 | var parseInteger = parseInt; | 
 | var callBound = require('./helpers/callBound'); | 
 | var regexTester = require('./helpers/regexTester'); | 
 | var getIteratorMethod = require('./helpers/getIteratorMethod'); | 
 | var getSymbolDescription = require('./helpers/getSymbolDescription'); | 
 |  | 
 | var $PromiseThen = callBound('Promise.prototype.then', true); | 
 | var arraySlice = callBound('Array.prototype.slice'); | 
 | var strSlice = callBound('String.prototype.slice'); | 
 | var $indexOf = callBound('Array.prototype.indexOf'); | 
 | var $push = callBound('Array.prototype.push'); | 
 |  | 
 | var isBinary = regexTester(/^0b[01]+$/i); | 
 | var isOctal = regexTester(/^0o[0-7]+$/i); | 
 | var isDigit = regexTester(/^[0-9]$/); | 
 | var regexExec = callBound('RegExp.prototype.exec'); | 
 | var nonWS = ['\u0085', '\u200b', '\ufffe'].join(''); | 
 | var nonWSregex = new $RegExp('[' + nonWS + ']', 'g'); | 
 | var hasNonWS = regexTester(nonWSregex); | 
 | var isInvalidHexLiteral = regexTester(/^[-+]0x[0-9a-f]+$/i); | 
 | var $charCodeAt = callBound('String.prototype.charCodeAt'); | 
 | var $isEnumerable = callBound('Object.prototype.propertyIsEnumerable'); | 
 |  | 
 | var toStr = callBound('Object.prototype.toString'); | 
 |  | 
 | var $NumberValueOf = callBound('Number.prototype.valueOf'); | 
 | var $BooleanValueOf = callBound('Boolean.prototype.valueOf'); | 
 | var $StringValueOf = callBound('String.prototype.valueOf'); | 
 | var $DateValueOf = callBound('Date.prototype.valueOf'); | 
 | var $SymbolToString = callBound('Symbol.prototype.toString', true); | 
 |  | 
 | var $floor = Math.floor; | 
 | var $abs = Math.abs; | 
 |  | 
 | var $ObjectCreate = $Object.create; | 
 | var $gOPD = $Object.getOwnPropertyDescriptor; | 
 | var $gOPN = $Object.getOwnPropertyNames; | 
 | var $gOPS = $Object.getOwnPropertySymbols; | 
 | var $isExtensible = $Object.isExtensible; | 
 | var $defineProperty = $Object.defineProperty; | 
 | var $setProto = require('./helpers/setProto'); | 
 |  | 
 | var DefineOwnProperty = function DefineOwnProperty(ES, O, P, desc) { | 
 | 	if (!$defineProperty) { | 
 | 		if (!ES.IsDataDescriptor(desc)) { | 
 | 			// ES3 does not support getters/setters | 
 | 			return false; | 
 | 		} | 
 | 		if (!desc['[[Configurable]]'] || !desc['[[Writable]]']) { | 
 | 			return false; | 
 | 		} | 
 |  | 
 | 		// fallback for ES3 | 
 | 		if (P in O && $isEnumerable(O, P) !== !!desc['[[Enumerable]]']) { | 
 | 			// a non-enumerable existing property | 
 | 			return false; | 
 | 		} | 
 |  | 
 | 		// property does not exist at all, or exists but is enumerable | 
 | 		var V = desc['[[Value]]']; | 
 | 		O[P] = V; // will use [[Define]] | 
 | 		return ES.SameValue(O[P], V); | 
 | 	} | 
 | 	$defineProperty(O, P, ES.FromPropertyDescriptor(desc)); | 
 | 	return true; | 
 | }; | 
 |  | 
 | // whitespace from: https://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 = callBound('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(inspect(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` or Proxy | 
 | 	}, | 
 |  | 
 | 	// https://people.mozilla.org/~jorendorff/es6-draft.html#sec-isextensible-o | 
 | 	IsExtensible: $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, got ' + inspect(P)); | 
 | 		} | 
 | 		// 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://www.ecma-international.org/ecma-262/6.0/#sec-frompropertydescriptor | 
 | 	FromPropertyDescriptor: function FromPropertyDescriptor(Desc) { | 
 | 		if (typeof Desc === 'undefined') { | 
 | 			return Desc; | 
 | 		} | 
 |  | 
 | 		assertRecord(this, 'Property Descriptor', 'Desc', Desc); | 
 |  | 
 | 		var obj = {}; | 
 | 		if ('[[Value]]' in Desc) { | 
 | 			obj.value = Desc['[[Value]]']; | 
 | 		} | 
 | 		if ('[[Writable]]' in Desc) { | 
 | 			obj.writable = Desc['[[Writable]]']; | 
 | 		} | 
 | 		if ('[[Get]]' in Desc) { | 
 | 			obj.get = Desc['[[Get]]']; | 
 | 		} | 
 | 		if ('[[Set]]' in Desc) { | 
 | 			obj.set = Desc['[[Set]]']; | 
 | 		} | 
 | 		if ('[[Enumerable]]' in Desc) { | 
 | 			obj.enumerable = Desc['[[Enumerable]]']; | 
 | 		} | 
 | 		if ('[[Configurable]]' in Desc) { | 
 | 			obj.configurable = Desc['[[Configurable]]']; | 
 | 		} | 
 | 		return obj; | 
 | 	}, | 
 |  | 
 | 	// 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) { | 
 | 		var actualMethod = method; | 
 | 		if (arguments.length < 2) { | 
 | 			actualMethod = getIteratorMethod(this, obj); | 
 | 		} | 
 | 		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 || this.IsExtensible(O); | 
 | 		var immutable = oldDesc && (!oldDesc.writable || !oldDesc.configurable); | 
 | 		if (immutable || !extensible) { | 
 | 			return false; | 
 | 		} | 
 | 		return DefineOwnProperty(this, O, P, { | 
 | 			'[[Configurable]]': true, | 
 | 			'[[Enumerable]]': true, | 
 | 			'[[Value]]': V, | 
 | 			'[[Writable]]': 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 DefineOwnProperty(this, 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'); | 
 | 		} | 
 |  | 
 | 		var Desc = isPropertyDescriptor(this, desc) ? desc : this.ToPropertyDescriptor(desc); | 
 | 		if (!isPropertyDescriptor(this, Desc)) { | 
 | 			throw new $TypeError('Assertion failed: Desc is not a valid Property Descriptor'); | 
 | 		} | 
 |  | 
 | 		return DefineOwnProperty(this, 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); | 
 | 	}, | 
 |  | 
 | 	// https://www.ecma-international.org/ecma-262/6.0/#sec-setintegritylevel | 
 | 	SetIntegrityLevel: function SetIntegrityLevel(O, level) { | 
 | 		if (this.Type(O) !== 'Object') { | 
 | 			throw new $TypeError('Assertion failed: Type(O) is not Object'); | 
 | 		} | 
 | 		if (level !== 'sealed' && level !== 'frozen') { | 
 | 			throw new $TypeError('Assertion failed: `level` must be `"sealed"` or `"frozen"`'); | 
 | 		} | 
 | 		if (!$preventExtensions) { | 
 | 			throw new $SyntaxError('SetIntegrityLevel requires native `Object.preventExtensions` support'); | 
 | 		} | 
 | 		var status = $preventExtensions(O); | 
 | 		if (!status) { | 
 | 			return false; | 
 | 		} | 
 | 		if (!$gOPN) { | 
 | 			throw new $SyntaxError('SetIntegrityLevel requires native `Object.getOwnPropertyNames` support'); | 
 | 		} | 
 | 		var theKeys = $gOPN(O); | 
 | 		var ES = this; | 
 | 		if (level === 'sealed') { | 
 | 			forEach(theKeys, function (k) { | 
 | 				ES.DefinePropertyOrThrow(O, k, { configurable: false }); | 
 | 			}); | 
 | 		} else if (level === 'frozen') { | 
 | 			forEach(theKeys, function (k) { | 
 | 				var currentDesc = $gOPD(O, k); | 
 | 				if (typeof currentDesc !== 'undefined') { | 
 | 					var desc; | 
 | 					if (ES.IsAccessorDescriptor(ES.ToPropertyDescriptor(currentDesc))) { | 
 | 						desc = { configurable: false }; | 
 | 					} else { | 
 | 						desc = { configurable: false, writable: false }; | 
 | 					} | 
 | 					ES.DefinePropertyOrThrow(O, k, desc); | 
 | 				} | 
 | 			}); | 
 | 		} | 
 | 		return true; | 
 | 	}, | 
 |  | 
 | 	// https://www.ecma-international.org/ecma-262/6.0/#sec-testintegritylevel | 
 | 	TestIntegrityLevel: function TestIntegrityLevel(O, level) { | 
 | 		if (this.Type(O) !== 'Object') { | 
 | 			throw new $TypeError('Assertion failed: Type(O) is not Object'); | 
 | 		} | 
 | 		if (level !== 'sealed' && level !== 'frozen') { | 
 | 			throw new $TypeError('Assertion failed: `level` must be `"sealed"` or `"frozen"`'); | 
 | 		} | 
 | 		var status = this.IsExtensible(O); | 
 | 		if (status) { | 
 | 			return false; | 
 | 		} | 
 | 		var theKeys = $gOPN(O); | 
 | 		var ES = this; | 
 | 		return theKeys.length === 0 || every(theKeys, function (k) { | 
 | 			var currentDesc = $gOPD(O, k); | 
 | 			if (typeof currentDesc !== 'undefined') { | 
 | 				if (currentDesc.configurable) { | 
 | 					return false; | 
 | 				} | 
 | 				if (level === 'frozen' && ES.IsDataDescriptor(ES.ToPropertyDescriptor(currentDesc)) && currentDesc.writable) { | 
 | 					return false; | 
 | 				} | 
 | 			} | 
 | 			return true; | 
 | 		}); | 
 | 	}, | 
 |  | 
 | 	// https://www.ecma-international.org/ecma-262/6.0/#sec-ordinaryhasinstance | 
 | 	OrdinaryHasInstance: function OrdinaryHasInstance(C, O) { | 
 | 		if (this.IsCallable(C) === false) { | 
 | 			return false; | 
 | 		} | 
 | 		if (this.Type(O) !== 'Object') { | 
 | 			return false; | 
 | 		} | 
 | 		var P = this.Get(C, 'prototype'); | 
 | 		if (this.Type(P) !== 'Object') { | 
 | 			throw new $TypeError('OrdinaryHasInstance called on an object with an invalid prototype property.'); | 
 | 		} | 
 | 		return O instanceof C; | 
 | 	}, | 
 |  | 
 | 	// https://www.ecma-international.org/ecma-262/6.0/#sec-ordinaryhasproperty | 
 | 	OrdinaryHasProperty: function OrdinaryHasProperty(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: P must be a Property Key'); | 
 | 		} | 
 | 		return P in O; | 
 | 	}, | 
 |  | 
 | 	// https://www.ecma-international.org/ecma-262/6.0/#sec-instanceofoperator | 
 | 	InstanceofOperator: function InstanceofOperator(O, C) { | 
 | 		if (this.Type(O) !== 'Object') { | 
 | 			throw new $TypeError('Assertion failed: Type(O) is not Object'); | 
 | 		} | 
 | 		var instOfHandler = hasSymbols && $Symbol.hasInstance ? this.GetMethod(C, $Symbol.hasInstance) : void 0; | 
 | 		if (typeof instOfHandler !== 'undefined') { | 
 | 			return this.ToBoolean(this.Call(instOfHandler, C, [O])); | 
 | 		} | 
 | 		if (!this.IsCallable(C)) { | 
 | 			throw new $TypeError('`C` is not Callable'); | 
 | 		} | 
 | 		return this.OrdinaryHasInstance(C, O); | 
 | 	}, | 
 |  | 
 | 	// https://www.ecma-international.org/ecma-262/6.0/#sec-ispromise | 
 | 	IsPromise: function IsPromise(x) { | 
 | 		if (this.Type(x) !== 'Object') { | 
 | 			return false; | 
 | 		} | 
 | 		if (!$PromiseThen) { // Promises are not supported | 
 | 			return false; | 
 | 		} | 
 | 		try { | 
 | 			$PromiseThen(x); // throws if not a promise | 
 | 		} catch (e) { | 
 | 			return false; | 
 | 		} | 
 | 		return true; | 
 | 	}, | 
 |  | 
 | 	// https://www.ecma-international.org/ecma-262/6.0/#sec-abstract-equality-comparison | 
 | 	'Abstract Equality Comparison': function AbstractEqualityComparison(x, y) { | 
 | 		var xType = this.Type(x); | 
 | 		var yType = this.Type(y); | 
 | 		if (xType === yType) { | 
 | 			return x === y; // ES6+ specified this shortcut anyways. | 
 | 		} | 
 | 		if (x == null && y == null) { | 
 | 			return true; | 
 | 		} | 
 | 		if (xType === 'Number' && yType === 'String') { | 
 | 			return this['Abstract Equality Comparison'](x, this.ToNumber(y)); | 
 | 		} | 
 | 		if (xType === 'String' && yType === 'Number') { | 
 | 			return this['Abstract Equality Comparison'](this.ToNumber(x), y); | 
 | 		} | 
 | 		if (xType === 'Boolean') { | 
 | 			return this['Abstract Equality Comparison'](this.ToNumber(x), y); | 
 | 		} | 
 | 		if (yType === 'Boolean') { | 
 | 			return this['Abstract Equality Comparison'](x, this.ToNumber(y)); | 
 | 		} | 
 | 		if ((xType === 'String' || xType === 'Number' || xType === 'Symbol') && yType === 'Object') { | 
 | 			return this['Abstract Equality Comparison'](x, this.ToPrimitive(y)); | 
 | 		} | 
 | 		if (xType === 'Object' && (yType === 'String' || yType === 'Number' || yType === 'Symbol')) { | 
 | 			return this['Abstract Equality Comparison'](this.ToPrimitive(x), y); | 
 | 		} | 
 | 		return false; | 
 | 	}, | 
 |  | 
 | 	// eslint-disable-next-line max-lines-per-function, max-statements, id-length, max-params | 
 | 	ValidateAndApplyPropertyDescriptor: function ValidateAndApplyPropertyDescriptor(O, P, extensible, Desc, current) { | 
 | 		// this uses the ES2017+ logic, since it fixes a number of bugs in the ES2015 logic. | 
 | 		var oType = this.Type(O); | 
 | 		if (oType !== 'Undefined' && oType !== 'Object') { | 
 | 			throw new $TypeError('Assertion failed: O must be undefined or an Object'); | 
 | 		} | 
 | 		if (this.Type(extensible) !== 'Boolean') { | 
 | 			throw new $TypeError('Assertion failed: extensible must be a Boolean'); | 
 | 		} | 
 | 		if (!isPropertyDescriptor(this, Desc)) { | 
 | 			throw new $TypeError('Assertion failed: Desc must be a Property Descriptor'); | 
 | 		} | 
 | 		if (this.Type(current) !== 'Undefined' && !isPropertyDescriptor(this, current)) { | 
 | 			throw new $TypeError('Assertion failed: current must be a Property Descriptor, or undefined'); | 
 | 		} | 
 | 		if (oType !== 'Undefined' && !this.IsPropertyKey(P)) { | 
 | 			throw new $TypeError('Assertion failed: if O is not undefined, P must be a Property Key'); | 
 | 		} | 
 | 		if (this.Type(current) === 'Undefined') { | 
 | 			if (!extensible) { | 
 | 				return false; | 
 | 			} | 
 | 			if (this.IsGenericDescriptor(Desc) || this.IsDataDescriptor(Desc)) { | 
 | 				if (oType !== 'Undefined') { | 
 | 					DefineOwnProperty(this, O, P, { | 
 | 						'[[Configurable]]': Desc['[[Configurable]]'], | 
 | 						'[[Enumerable]]': Desc['[[Enumerable]]'], | 
 | 						'[[Value]]': Desc['[[Value]]'], | 
 | 						'[[Writable]]': Desc['[[Writable]]'] | 
 | 					}); | 
 | 				} | 
 | 			} else { | 
 | 				if (!this.IsAccessorDescriptor(Desc)) { | 
 | 					throw new $TypeError('Assertion failed: Desc is not an accessor descriptor'); | 
 | 				} | 
 | 				if (oType !== 'Undefined') { | 
 | 					return DefineOwnProperty(this, O, P, Desc); | 
 | 				} | 
 | 			} | 
 | 			return true; | 
 | 		} | 
 | 		if (this.IsGenericDescriptor(Desc) && !('[[Configurable]]' in Desc) && !('[[Enumerable]]' in Desc)) { | 
 | 			return true; | 
 | 		} | 
 | 		if (isSamePropertyDescriptor(this, Desc, current)) { | 
 | 			return true; // removed by ES2017, but should still be correct | 
 | 		} | 
 | 		// "if every field in Desc is absent, return true" can't really match the assertion that it's a Property Descriptor | 
 | 		if (!current['[[Configurable]]']) { | 
 | 			if (Desc['[[Configurable]]']) { | 
 | 				return false; | 
 | 			} | 
 | 			if ('[[Enumerable]]' in Desc && !Desc['[[Enumerable]]'] === !!current['[[Enumerable]]']) { | 
 | 				return false; | 
 | 			} | 
 | 		} | 
 | 		if (this.IsGenericDescriptor(Desc)) { | 
 | 			// no further validation is required. | 
 | 		} else if (this.IsDataDescriptor(current) !== this.IsDataDescriptor(Desc)) { | 
 | 			if (!current['[[Configurable]]']) { | 
 | 				return false; | 
 | 			} | 
 | 			if (this.IsDataDescriptor(current)) { | 
 | 				if (oType !== 'Undefined') { | 
 | 					DefineOwnProperty(this, O, P, { | 
 | 						'[[Configurable]]': current['[[Configurable]]'], | 
 | 						'[[Enumerable]]': current['[[Enumerable]]'], | 
 | 						'[[Get]]': undefined | 
 | 					}); | 
 | 				} | 
 | 			} else if (oType !== 'Undefined') { | 
 | 				DefineOwnProperty(this, O, P, { | 
 | 					'[[Configurable]]': current['[[Configurable]]'], | 
 | 					'[[Enumerable]]': current['[[Enumerable]]'], | 
 | 					'[[Value]]': undefined | 
 | 				}); | 
 | 			} | 
 | 		} else if (this.IsDataDescriptor(current) && this.IsDataDescriptor(Desc)) { | 
 | 			if (!current['[[Configurable]]'] && !current['[[Writable]]']) { | 
 | 				if ('[[Writable]]' in Desc && Desc['[[Writable]]']) { | 
 | 					return false; | 
 | 				} | 
 | 				if ('[[Value]]' in Desc && !this.SameValue(Desc['[[Value]]'], current['[[Value]]'])) { | 
 | 					return false; | 
 | 				} | 
 | 				return true; | 
 | 			} | 
 | 		} else if (this.IsAccessorDescriptor(current) && this.IsAccessorDescriptor(Desc)) { | 
 | 			if (!current['[[Configurable]]']) { | 
 | 				if ('[[Set]]' in Desc && !this.SameValue(Desc['[[Set]]'], current['[[Set]]'])) { | 
 | 					return false; | 
 | 				} | 
 | 				if ('[[Get]]' in Desc && !this.SameValue(Desc['[[Get]]'], current['[[Get]]'])) { | 
 | 					return false; | 
 | 				} | 
 | 				return true; | 
 | 			} | 
 | 		} else { | 
 | 			throw new $TypeError('Assertion failed: current and Desc are not both data, both accessors, or one accessor and one data.'); | 
 | 		} | 
 | 		if (oType !== 'Undefined') { | 
 | 			return DefineOwnProperty(this, O, P, Desc); | 
 | 		} | 
 | 		return true; | 
 | 	}, | 
 |  | 
 | 	// https://www.ecma-international.org/ecma-262/6.0/#sec-ordinarydefineownproperty | 
 | 	OrdinaryDefineOwnProperty: function OrdinaryDefineOwnProperty(O, P, Desc) { | 
 | 		if (this.Type(O) !== 'Object') { | 
 | 			throw new $TypeError('Assertion failed: O must be an Object'); | 
 | 		} | 
 | 		if (!this.IsPropertyKey(P)) { | 
 | 			throw new $TypeError('Assertion failed: P must be a Property Key'); | 
 | 		} | 
 | 		if (!isPropertyDescriptor(this, Desc)) { | 
 | 			throw new $TypeError('Assertion failed: Desc must be a Property Descriptor'); | 
 | 		} | 
 | 		var desc = $gOPD(O, P); | 
 | 		var current = desc && this.ToPropertyDescriptor(desc); | 
 | 		var extensible = this.IsExtensible(O); | 
 | 		return this.ValidateAndApplyPropertyDescriptor(O, P, extensible, Desc, current); | 
 | 	}, | 
 |  | 
 | 	// https://www.ecma-international.org/ecma-262/6.0/#sec-ordinarygetownproperty | 
 | 	OrdinaryGetOwnProperty: function OrdinaryGetOwnProperty(O, P) { | 
 | 		if (this.Type(O) !== 'Object') { | 
 | 			throw new $TypeError('Assertion failed: O must be an Object'); | 
 | 		} | 
 | 		if (!this.IsPropertyKey(P)) { | 
 | 			throw new $TypeError('Assertion failed: P must be a Property Key'); | 
 | 		} | 
 | 		if (!has(O, P)) { | 
 | 			return void 0; | 
 | 		} | 
 | 		if (!$gOPD) { | 
 | 			// ES3 fallback | 
 | 			var arrayLength = this.IsArray(O) && P === 'length'; | 
 | 			var regexLastIndex = this.IsRegExp(O) && P === 'lastIndex'; | 
 | 			return { | 
 | 				'[[Configurable]]': !(arrayLength || regexLastIndex), | 
 | 				'[[Enumerable]]': $isEnumerable(O, P), | 
 | 				'[[Value]]': O[P], | 
 | 				'[[Writable]]': true | 
 | 			}; | 
 | 		} | 
 | 		return this.ToPropertyDescriptor($gOPD(O, P)); | 
 | 	}, | 
 |  | 
 | 	// https://www.ecma-international.org/ecma-262/6.0/#sec-arraycreate | 
 | 	ArrayCreate: function ArrayCreate(length) { | 
 | 		if (!this.IsInteger(length) || length < 0) { | 
 | 			throw new $TypeError('Assertion failed: `length` must be an integer Number >= 0'); | 
 | 		} | 
 | 		if (length > MAX_ARRAY_LENGTH) { | 
 | 			throw new $RangeError('length is greater than (2**32 - 1)'); | 
 | 		} | 
 | 		var proto = arguments.length > 1 ? arguments[1] : $ArrayPrototype; | 
 | 		var A = []; // steps 5 - 7, and 9 | 
 | 		if (proto !== $ArrayPrototype) { // step 8 | 
 | 			if (!$setProto) { | 
 | 				throw new $SyntaxError('ArrayCreate: a `proto` argument that is not `Array.prototype` is not supported in an environment that does not support setting the [[Prototype]]'); | 
 | 			} | 
 | 			$setProto(A, proto); | 
 | 		} | 
 | 		if (length !== 0) { // bypasses the need for step 2 | 
 | 			A.length = length; | 
 | 		} | 
 | 		/* step 10, the above as a shortcut for the below | 
 | 		this.OrdinaryDefineOwnProperty(A, 'length', { | 
 | 			'[[Configurable]]': false, | 
 | 			'[[Enumerable]]': false, | 
 | 			'[[Value]]': length, | 
 | 			'[[Writable]]': true | 
 | 		}); | 
 | 		*/ | 
 | 		return A; | 
 | 	}, | 
 |  | 
 | 	// eslint-disable-next-line max-statements, max-lines-per-function | 
 | 	ArraySetLength: function ArraySetLength(A, Desc) { | 
 | 		if (!this.IsArray(A)) { | 
 | 			throw new $TypeError('Assertion failed: A must be an Array'); | 
 | 		} | 
 | 		if (!isPropertyDescriptor(this, Desc)) { | 
 | 			throw new $TypeError('Assertion failed: Desc must be a Property Descriptor'); | 
 | 		} | 
 | 		if (!('[[Value]]' in Desc)) { | 
 | 			return this.OrdinaryDefineOwnProperty(A, 'length', Desc); | 
 | 		} | 
 | 		var newLenDesc = assign({}, Desc); | 
 | 		var newLen = this.ToUint32(Desc['[[Value]]']); | 
 | 		var numberLen = this.ToNumber(Desc['[[Value]]']); | 
 | 		if (newLen !== numberLen) { | 
 | 			throw new $RangeError('Invalid array length'); | 
 | 		} | 
 | 		newLenDesc['[[Value]]'] = newLen; | 
 | 		var oldLenDesc = this.OrdinaryGetOwnProperty(A, 'length'); | 
 | 		if (!this.IsDataDescriptor(oldLenDesc)) { | 
 | 			throw new $TypeError('Assertion failed: an array had a non-data descriptor on `length`'); | 
 | 		} | 
 | 		var oldLen = oldLenDesc['[[Value]]']; | 
 | 		if (newLen >= oldLen) { | 
 | 			return this.OrdinaryDefineOwnProperty(A, 'length', newLenDesc); | 
 | 		} | 
 | 		if (!oldLenDesc['[[Writable]]']) { | 
 | 			return false; | 
 | 		} | 
 | 		var newWritable; | 
 | 		if (!('[[Writable]]' in newLenDesc) || newLenDesc['[[Writable]]']) { | 
 | 			newWritable = true; | 
 | 		} else { | 
 | 			newWritable = false; | 
 | 			newLenDesc['[[Writable]]'] = true; | 
 | 		} | 
 | 		var succeeded = this.OrdinaryDefineOwnProperty(A, 'length', newLenDesc); | 
 | 		if (!succeeded) { | 
 | 			return false; | 
 | 		} | 
 | 		while (newLen < oldLen) { | 
 | 			oldLen -= 1; | 
 | 			var deleteSucceeded = delete A[this.ToString(oldLen)]; | 
 | 			if (!deleteSucceeded) { | 
 | 				newLenDesc['[[Value]]'] = oldLen + 1; | 
 | 				if (!newWritable) { | 
 | 					newLenDesc['[[Writable]]'] = false; | 
 | 					this.OrdinaryDefineOwnProperty(A, 'length', newLenDesc); | 
 | 					return false; | 
 | 				} | 
 | 			} | 
 | 		} | 
 | 		if (!newWritable) { | 
 | 			return this.OrdinaryDefineOwnProperty(A, 'length', { '[[Writable]]': false }); | 
 | 		} | 
 | 		return true; | 
 | 	}, | 
 |  | 
 | 	// https://www.ecma-international.org/ecma-262/6.0/#sec-createhtml | 
 | 	CreateHTML: function CreateHTML(string, tag, attribute, value) { | 
 | 		if (this.Type(tag) !== 'String' || this.Type(attribute) !== 'String') { | 
 | 			throw new $TypeError('Assertion failed: `tag` and `attribute` must be strings'); | 
 | 		} | 
 | 		var str = this.RequireObjectCoercible(string); | 
 | 		var S = this.ToString(str); | 
 | 		var p1 = '<' + tag; | 
 | 		if (attribute !== '') { | 
 | 			var V = this.ToString(value); | 
 | 			var escapedV = $replace(V, /\x22/g, '"'); | 
 | 			p1 += '\x20' + attribute + '\x3D\x22' + escapedV + '\x22'; | 
 | 		} | 
 | 		return p1 + '>' + S + '</' + tag + '>'; | 
 | 	}, | 
 |  | 
 | 	// https://www.ecma-international.org/ecma-262/6.0/#sec-getownpropertykeys | 
 | 	GetOwnPropertyKeys: function GetOwnPropertyKeys(O, Type) { | 
 | 		if (this.Type(O) !== 'Object') { | 
 | 			throw new $TypeError('Assertion failed: Type(O) is not Object'); | 
 | 		} | 
 | 		if (Type === 'Symbol') { | 
 | 			return hasSymbols && $gOPS ? $gOPS(O) : []; | 
 | 		} | 
 | 		if (Type === 'String') { | 
 | 			if (!$gOPN) { | 
 | 				return keys(O); | 
 | 			} | 
 | 			return $gOPN(O); | 
 | 		} | 
 | 		throw new $TypeError('Assertion failed: `Type` must be `"String"` or `"Symbol"`'); | 
 | 	}, | 
 |  | 
 | 	// https://www.ecma-international.org/ecma-262/6.0/#sec-symboldescriptivestring | 
 | 	SymbolDescriptiveString: function SymbolDescriptiveString(sym) { | 
 | 		if (this.Type(sym) !== 'Symbol') { | 
 | 			throw new $TypeError('Assertion failed: `sym` must be a Symbol'); | 
 | 		} | 
 | 		return $SymbolToString(sym); | 
 | 	}, | 
 |  | 
 | 	// https://www.ecma-international.org/ecma-262/6.0/#sec-getsubstitution | 
 | 	// eslint-disable-next-line max-statements, max-params, max-lines-per-function | 
 | 	GetSubstitution: function GetSubstitution(matched, str, position, captures, replacement) { | 
 | 		if (this.Type(matched) !== 'String') { | 
 | 			throw new $TypeError('Assertion failed: `matched` must be a String'); | 
 | 		} | 
 | 		var matchLength = matched.length; | 
 |  | 
 | 		if (this.Type(str) !== 'String') { | 
 | 			throw new $TypeError('Assertion failed: `str` must be a String'); | 
 | 		} | 
 | 		var stringLength = str.length; | 
 |  | 
 | 		if (!this.IsInteger(position) || position < 0 || position > stringLength) { | 
 | 			throw new $TypeError('Assertion failed: `position` must be a nonnegative integer, and less than or equal to the length of `string`, got ' + inspect(position)); | 
 | 		} | 
 |  | 
 | 		var ES = this; | 
 | 		var isStringOrHole = function (capture, index, arr) { return ES.Type(capture) === 'String' || !(index in arr); }; | 
 | 		if (!this.IsArray(captures) || !every(captures, isStringOrHole)) { | 
 | 			throw new $TypeError('Assertion failed: `captures` must be a List of Strings, got ' + inspect(captures)); | 
 | 		} | 
 |  | 
 | 		if (this.Type(replacement) !== 'String') { | 
 | 			throw new $TypeError('Assertion failed: `replacement` must be a String'); | 
 | 		} | 
 |  | 
 | 		var tailPos = position + matchLength; | 
 | 		var m = captures.length; | 
 |  | 
 | 		var result = ''; | 
 | 		for (var i = 0; i < replacement.length; i += 1) { | 
 | 			// if this is a $, and it's not the end of the replacement | 
 | 			var current = replacement[i]; | 
 | 			var isLast = (i + 1) >= replacement.length; | 
 | 			var nextIsLast = (i + 2) >= replacement.length; | 
 | 			if (current === '$' && !isLast) { | 
 | 				var next = replacement[i + 1]; | 
 | 				if (next === '$') { | 
 | 					result += '$'; | 
 | 					i += 1; | 
 | 				} else if (next === '&') { | 
 | 					result += matched; | 
 | 					i += 1; | 
 | 				} else if (next === '`') { | 
 | 					result += position === 0 ? '' : strSlice(str, 0, position - 1); | 
 | 					i += 1; | 
 | 				} else if (next === "'") { | 
 | 					result += tailPos >= stringLength ? '' : strSlice(str, tailPos); | 
 | 					i += 1; | 
 | 				} else { | 
 | 					var nextNext = nextIsLast ? null : replacement[i + 2]; | 
 | 					if (isDigit(next) && next !== '0' && (nextIsLast || !isDigit(nextNext))) { | 
 | 						// $1 through $9, and not followed by a digit | 
 | 						var n = parseInteger(next, 10); | 
 | 						// if (n > m, impl-defined) | 
 | 						result += (n <= m && this.Type(captures[n - 1]) === 'Undefined') ? '' : captures[n - 1]; | 
 | 						i += 1; | 
 | 					} else if (isDigit(next) && (nextIsLast || isDigit(nextNext))) { | 
 | 						// $00 through $99 | 
 | 						var nn = next + nextNext; | 
 | 						var nnI = parseInteger(nn, 10) - 1; | 
 | 						// if nn === '00' or nn > m, impl-defined | 
 | 						result += (nn <= m && this.Type(captures[nnI]) === 'Undefined') ? '' : captures[nnI]; | 
 | 						i += 2; | 
 | 					} else { | 
 | 						result += '$'; | 
 | 					} | 
 | 				} | 
 | 			} else { | 
 | 				// the final $, or else not a $ | 
 | 				result += replacement[i]; | 
 | 			} | 
 | 		} | 
 | 		return result; | 
 | 	}, | 
 |  | 
 | 	// https://ecma-international.org/ecma-262/6.0/#sec-todatestring | 
 | 	ToDateString: function ToDateString(tv) { | 
 | 		if (this.Type(tv) !== 'Number') { | 
 | 			throw new $TypeError('Assertion failed: `tv` must be a Number'); | 
 | 		} | 
 | 		if ($isNaN(tv)) { | 
 | 			return 'Invalid Date'; | 
 | 		} | 
 | 		return $Date(tv); | 
 | 	}, | 
 |  | 
 | 	// https://ecma-international.org/ecma-262/6.0/#sec-createlistfromarraylike | 
 | 	CreateListFromArrayLike: function CreateListFromArrayLike(obj) { | 
 | 		var elementTypes = arguments.length > 1 | 
 | 			? arguments[1] | 
 | 			: ['Undefined', 'Null', 'Boolean', 'String', 'Symbol', 'Number', 'Object']; | 
 |  | 
 | 		if (this.Type(obj) !== 'Object') { | 
 | 			throw new $TypeError('Assertion failed: `obj` must be an Object'); | 
 | 		} | 
 | 		if (!this.IsArray(elementTypes)) { | 
 | 			throw new $TypeError('Assertion failed: `elementTypes`, if provided, must be an array'); | 
 | 		} | 
 | 		var len = this.ToLength(this.Get(obj, 'length')); | 
 | 		var list = []; | 
 | 		var index = 0; | 
 | 		while (index < len) { | 
 | 			var indexName = this.ToString(index); | 
 | 			var next = this.Get(obj, indexName); | 
 | 			var nextType = this.Type(next); | 
 | 			if ($indexOf(elementTypes, nextType) < 0) { | 
 | 				throw new $TypeError('item type ' + nextType + ' is not a valid elementType'); | 
 | 			} | 
 | 			$push(list, next); | 
 | 			index += 1; | 
 | 		} | 
 | 		return list; | 
 | 	}, | 
 |  | 
 | 	// https://ecma-international.org/ecma-262/6.0/#sec-getprototypefromconstructor | 
 | 	GetPrototypeFromConstructor: function GetPrototypeFromConstructor(constructor, intrinsicDefaultProto) { | 
 | 		var intrinsic = GetIntrinsic(intrinsicDefaultProto); // throws if not a valid intrinsic | 
 | 		if (!this.IsConstructor(constructor)) { | 
 | 			throw new $TypeError('Assertion failed: `constructor` must be a constructor'); | 
 | 		} | 
 | 		var proto = this.Get(constructor, 'prototype'); | 
 | 		if (this.Type(proto) !== 'Object') { | 
 | 			if (!(constructor instanceof $Function)) { | 
 | 				// ignore other realms, for now | 
 | 				throw new $TypeError('cross-realm constructors not currently supported'); | 
 | 			} | 
 | 			proto = intrinsic; | 
 | 		} | 
 | 		return proto; | 
 | 	}, | 
 |  | 
 | 	// https://ecma-international.org/ecma-262/6.0/#sec-setfunctionname | 
 | 	SetFunctionName: function SetFunctionName(F, name) { | 
 | 		if (typeof F !== 'function') { | 
 | 			throw new $TypeError('Assertion failed: `F` must be a function'); | 
 | 		} | 
 | 		if (!this.IsExtensible(F) || has(F, 'name')) { | 
 | 			throw new $TypeError('Assertion failed: `F` must be extensible, and must not have a `name` own property'); | 
 | 		} | 
 | 		var nameType = this.Type(name); | 
 | 		if (nameType !== 'Symbol' && nameType !== 'String') { | 
 | 			throw new $TypeError('Assertion failed: `name` must be a Symbol or a String'); | 
 | 		} | 
 | 		if (nameType === 'Symbol') { | 
 | 			var description = getSymbolDescription(name); | 
 | 			// eslint-disable-next-line no-param-reassign | 
 | 			name = typeof description === 'undefined' ? '' : '[' + description + ']'; | 
 | 		} | 
 | 		if (arguments.length > 2) { | 
 | 			var prefix = arguments[2]; | 
 | 			// eslint-disable-next-line no-param-reassign | 
 | 			name = prefix + ' ' + name; | 
 | 		} | 
 | 		return this.DefinePropertyOrThrow(F, 'name', { | 
 | 			'[[Value]]': name, | 
 | 			'[[Writable]]': false, | 
 | 			'[[Enumerable]]': false, | 
 | 			'[[Configurable]]': true | 
 | 		}); | 
 | 	} | 
 | }); | 
 |  | 
 | delete ES6.CheckObjectCoercible; // renamed in ES6 to RequireObjectCoercible | 
 |  | 
 | module.exports = ES6; |