| // Copyright 2006-2008 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // This files contains runtime support implemented in JavaScript. |
| |
| // CAUTION: Some of the functions specified in this file are called |
| // directly from compiled code. These are the functions with names in |
| // ALL CAPS. The compiled code passes the first argument in 'this'. |
| |
| |
| // The following declarations are shared with other native JS files. |
| // They are all declared at this one spot to avoid redeclaration errors. |
| |
| (function(global, utils) { |
| |
| %CheckIsBootstrapping(); |
| |
| var FLAG_harmony_species; |
| var GlobalArray = global.Array; |
| var GlobalBoolean = global.Boolean; |
| var GlobalString = global.String; |
| var MakeRangeError; |
| var MakeTypeError; |
| var speciesSymbol; |
| |
| utils.Import(function(from) { |
| MakeRangeError = from.MakeRangeError; |
| MakeTypeError = from.MakeTypeError; |
| speciesSymbol = from.species_symbol; |
| }); |
| |
| utils.ImportFromExperimental(function(from) { |
| FLAG_harmony_species = from.FLAG_harmony_species; |
| }); |
| |
| // ---------------------------------------------------------------------------- |
| |
| /* ----------------------------- |
| - - - H e l p e r s - - - |
| ----------------------------- |
| */ |
| |
| function CONCAT_ITERABLE_TO_ARRAY(iterable) { |
| return %concat_iterable_to_array(this, iterable); |
| }; |
| |
| |
| /* ------------------------------------- |
| - - - C o n v e r s i o n s - - - |
| ------------------------------------- |
| */ |
| |
| // ES5, section 9.12 |
| function SameValue(x, y) { |
| if (typeof x != typeof y) return false; |
| if (IS_NUMBER(x)) { |
| if (NUMBER_IS_NAN(x) && NUMBER_IS_NAN(y)) return true; |
| // x is +0 and y is -0 or vice versa. |
| if (x === 0 && y === 0 && %_IsMinusZero(x) != %_IsMinusZero(y)) { |
| return false; |
| } |
| } |
| if (IS_SIMD_VALUE(x)) return %SimdSameValue(x, y); |
| return x === y; |
| } |
| |
| |
| // ES6, section 7.2.4 |
| function SameValueZero(x, y) { |
| if (typeof x != typeof y) return false; |
| if (IS_NUMBER(x)) { |
| if (NUMBER_IS_NAN(x) && NUMBER_IS_NAN(y)) return true; |
| } |
| if (IS_SIMD_VALUE(x)) return %SimdSameValueZero(x, y); |
| return x === y; |
| } |
| |
| |
| function ConcatIterableToArray(target, iterable) { |
| var index = target.length; |
| for (var element of iterable) { |
| AddIndexedProperty(target, index++, element); |
| } |
| return target; |
| } |
| |
| |
| /* --------------------------------- |
| - - - U t i l i t i e s - - - |
| --------------------------------- |
| */ |
| |
| |
| // This function should be called rather than %AddElement in contexts where the |
| // argument might not be less than 2**32-1. ES2015 ToLength semantics mean that |
| // this is a concern at basically all callsites. |
| function AddIndexedProperty(obj, index, value) { |
| if (index === TO_UINT32(index) && index !== kMaxUint32) { |
| %AddElement(obj, index, value); |
| } else { |
| %AddNamedProperty(obj, TO_STRING(index), value, NONE); |
| } |
| } |
| %SetForceInlineFlag(AddIndexedProperty); |
| |
| |
| function ToPositiveInteger(x, rangeErrorIndex) { |
| var i = TO_INTEGER_MAP_MINUS_ZERO(x); |
| if (i < 0) throw MakeRangeError(rangeErrorIndex); |
| return i; |
| } |
| |
| |
| function MaxSimple(a, b) { |
| return a > b ? a : b; |
| } |
| |
| |
| function MinSimple(a, b) { |
| return a > b ? b : a; |
| } |
| |
| |
| %SetForceInlineFlag(MaxSimple); |
| %SetForceInlineFlag(MinSimple); |
| |
| |
| // ES2015 7.3.20 |
| // For the fallback with --harmony-species off, there are two possible choices: |
| // - "conservative": return defaultConstructor |
| // - "not conservative": return object.constructor |
| // This fallback path is only needed in the transition to ES2015, and the |
| // choice is made simply to preserve the previous behavior so that we don't |
| // have a three-step upgrade: old behavior, unspecified intermediate behavior, |
| // and ES2015. |
| // In some cases, we were "conservative" (e.g., ArrayBuffer, RegExp), and in |
| // other cases we were "not conservative (e.g., TypedArray, Promise). |
| function SpeciesConstructor(object, defaultConstructor, conservative) { |
| if (FLAG_harmony_species) { |
| var constructor = object.constructor; |
| if (IS_UNDEFINED(constructor)) { |
| return defaultConstructor; |
| } |
| if (!IS_RECEIVER(constructor)) { |
| throw MakeTypeError(kConstructorNotReceiver); |
| } |
| var species = constructor[speciesSymbol]; |
| if (IS_NULL_OR_UNDEFINED(species)) { |
| return defaultConstructor; |
| } |
| if (%IsConstructor(species)) { |
| return species; |
| } |
| throw MakeTypeError(kSpeciesNotConstructor); |
| } else { |
| return conservative ? defaultConstructor : object.constructor; |
| } |
| } |
| |
| //---------------------------------------------------------------------------- |
| |
| // NOTE: Setting the prototype for Array must take place as early as |
| // possible due to code generation for array literals. When |
| // generating code for a array literal a boilerplate array is created |
| // that is cloned when running the code. It is essential that the |
| // boilerplate gets the right prototype. |
| %FunctionSetPrototype(GlobalArray, new GlobalArray(0)); |
| |
| // ---------------------------------------------------------------------------- |
| // Exports |
| |
| utils.Export(function(to) { |
| to.AddIndexedProperty = AddIndexedProperty; |
| to.MaxSimple = MaxSimple; |
| to.MinSimple = MinSimple; |
| to.SameValue = SameValue; |
| to.SameValueZero = SameValueZero; |
| to.ToPositiveInteger = ToPositiveInteger; |
| to.SpeciesConstructor = SpeciesConstructor; |
| }); |
| |
| %InstallToContext([ |
| "concat_iterable_to_array_builtin", CONCAT_ITERABLE_TO_ARRAY, |
| ]); |
| |
| %InstallToContext([ |
| "concat_iterable_to_array", ConcatIterableToArray, |
| ]); |
| |
| }) |