Home | History | Annotate | Download | only in js
      1 // Copyright 2015 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 (function(global, utils, extrasUtils) {
      6 
      7 "use strict";
      8 
      9 %CheckIsBootstrapping();
     10 
     11 // -----------------------------------------------------------------------
     12 // Utils
     13 
     14 var imports = UNDEFINED;
     15 var imports_from_experimental = UNDEFINED;
     16 var exports_container = %ExportFromRuntime({});
     17 var typed_array_setup = UNDEFINED;
     18 
     19 // Register context value to be initialized with a typed array in
     20 // Genesis::InitializeBuiltinTypedArrays.
     21 function SetupTypedArray(f) {
     22   f.next = typed_array_setup;
     23   typed_array_setup = f;
     24 }
     25 
     26 // Export to other scripts.
     27 // In normal natives, this exports functions to other normal natives.
     28 // In experimental natives, this exports to other experimental natives and
     29 // to normal natives that import using utils.ImportFromExperimental.
     30 function Export(f) {
     31   f(exports_container);
     32 }
     33 
     34 
     35 // Import from other scripts. The actual importing happens in PostNatives and
     36 // PostExperimental so that we can import from scripts executed later. However,
     37 // that means that the import is not available until the very end. If the
     38 // import needs to be available immediate, use ImportNow.
     39 // In normal natives, this imports from other normal natives.
     40 // In experimental natives, this imports from other experimental natives and
     41 // whitelisted exports from normal natives.
     42 function Import(f) {
     43   f.next = imports;
     44   imports = f;
     45 }
     46 
     47 
     48 // Import immediately from exports of previous scripts. We need this for
     49 // functions called during bootstrapping. Hooking up imports in PostNatives
     50 // would be too late.
     51 function ImportNow(name) {
     52   return exports_container[name];
     53 }
     54 
     55 
     56 // In normal natives, import from experimental natives.
     57 // Not callable from experimental natives.
     58 function ImportFromExperimental(f) {
     59   f.next = imports_from_experimental;
     60   imports_from_experimental = f;
     61 }
     62 
     63 
     64 function SetFunctionName(f, name, prefix) {
     65   if (IS_SYMBOL(name)) {
     66     name = "[" + %SymbolDescription(name) + "]";
     67   }
     68   if (IS_UNDEFINED(prefix)) {
     69     %FunctionSetName(f, name);
     70   } else {
     71     %FunctionSetName(f, prefix + " " + name);
     72   }
     73 }
     74 
     75 
     76 function InstallConstants(object, constants) {
     77   %CheckIsBootstrapping();
     78   %OptimizeObjectForAddingMultipleProperties(object, constants.length >> 1);
     79   var attributes = DONT_ENUM | DONT_DELETE | READ_ONLY;
     80   for (var i = 0; i < constants.length; i += 2) {
     81     var name = constants[i];
     82     var k = constants[i + 1];
     83     %AddNamedProperty(object, name, k, attributes);
     84   }
     85   %ToFastProperties(object);
     86 }
     87 
     88 
     89 function InstallFunctions(object, attributes, functions) {
     90   %CheckIsBootstrapping();
     91   %OptimizeObjectForAddingMultipleProperties(object, functions.length >> 1);
     92   for (var i = 0; i < functions.length; i += 2) {
     93     var key = functions[i];
     94     var f = functions[i + 1];
     95     SetFunctionName(f, key);
     96     %FunctionRemovePrototype(f);
     97     %AddNamedProperty(object, key, f, attributes);
     98     %SetNativeFlag(f);
     99   }
    100   %ToFastProperties(object);
    101 }
    102 
    103 
    104 // Helper function to install a getter-only accessor property.
    105 function InstallGetter(object, name, getter, attributes, prefix) {
    106   %CheckIsBootstrapping();
    107   if (IS_UNDEFINED(attributes)) attributes = DONT_ENUM;
    108   SetFunctionName(getter, name, IS_UNDEFINED(prefix) ? "get" : prefix);
    109   %FunctionRemovePrototype(getter);
    110   %DefineGetterPropertyUnchecked(object, name, getter, attributes);
    111   %SetNativeFlag(getter);
    112 }
    113 
    114 
    115 // Helper function to install a getter/setter accessor property.
    116 function InstallGetterSetter(object, name, getter, setter, attributes) {
    117   %CheckIsBootstrapping();
    118   if (IS_UNDEFINED(attributes)) attributes = DONT_ENUM;
    119   SetFunctionName(getter, name, "get");
    120   SetFunctionName(setter, name, "set");
    121   %FunctionRemovePrototype(getter);
    122   %FunctionRemovePrototype(setter);
    123   %DefineAccessorPropertyUnchecked(object, name, getter, setter, attributes);
    124   %SetNativeFlag(getter);
    125   %SetNativeFlag(setter);
    126 }
    127 
    128 
    129 function OverrideFunction(object, name, f, afterInitialBootstrap) {
    130   %CheckIsBootstrapping();
    131   %object_define_property(object, name, { value: f,
    132                                           writeable: true,
    133                                           configurable: true,
    134                                           enumerable: false });
    135   SetFunctionName(f, name);
    136   if (!afterInitialBootstrap) %FunctionRemovePrototype(f);
    137   %SetNativeFlag(f);
    138 }
    139 
    140 
    141 // Prevents changes to the prototype of a built-in function.
    142 // The "prototype" property of the function object is made non-configurable,
    143 // and the prototype object is made non-extensible. The latter prevents
    144 // changing the __proto__ property.
    145 function SetUpLockedPrototype(
    146     constructor, fields, methods) {
    147   %CheckIsBootstrapping();
    148   var prototype = constructor.prototype;
    149   // Install functions first, because this function is used to initialize
    150   // PropertyDescriptor itself.
    151   var property_count = (methods.length >> 1) + (fields ? fields.length : 0);
    152   if (property_count >= 4) {
    153     %OptimizeObjectForAddingMultipleProperties(prototype, property_count);
    154   }
    155   if (fields) {
    156     for (var i = 0; i < fields.length; i++) {
    157       %AddNamedProperty(prototype, fields[i],
    158                         UNDEFINED, DONT_ENUM | DONT_DELETE);
    159     }
    160   }
    161   for (var i = 0; i < methods.length; i += 2) {
    162     var key = methods[i];
    163     var f = methods[i + 1];
    164     %AddNamedProperty(prototype, key, f, DONT_ENUM | DONT_DELETE | READ_ONLY);
    165     %SetNativeFlag(f);
    166   }
    167   %InternalSetPrototype(prototype, null);
    168   %ToFastProperties(prototype);
    169 }
    170 
    171 
    172 // -----------------------------------------------------------------------
    173 // To be called by bootstrapper
    174 
    175 function PostNatives(utils) {
    176   %CheckIsBootstrapping();
    177 
    178   for ( ; !IS_UNDEFINED(imports); imports = imports.next) {
    179     imports(exports_container);
    180   }
    181 
    182   // Whitelist of exports from normal natives to experimental natives and debug.
    183   var expose_list = [
    184     "FormatDateToParts",
    185     "MapEntries",
    186     "MapIterator",
    187     "MapIteratorNext",
    188     "MaxSimple",
    189     "MinSimple",
    190     "SetIterator",
    191     "SetIteratorNext",
    192     "SetValues",
    193     "ToLocaleLowerCaseI18N",
    194     "ToLocaleUpperCaseI18N",
    195     "ToLowerCaseI18N",
    196     "ToUpperCaseI18N",
    197     // From runtime:
    198     "promise_result_symbol",
    199     "promise_state_symbol",
    200     "reflect_apply",
    201     "to_string_tag_symbol",
    202   ];
    203 
    204   var filtered_exports = {};
    205   %OptimizeObjectForAddingMultipleProperties(
    206       filtered_exports, expose_list.length);
    207   for (var key of expose_list) {
    208     filtered_exports[key] = exports_container[key];
    209   }
    210   %ToFastProperties(filtered_exports);
    211   exports_container = filtered_exports;
    212 
    213   utils.PostNatives = UNDEFINED;
    214   utils.ImportFromExperimental = UNDEFINED;
    215 }
    216 
    217 
    218 function PostExperimentals(utils) {
    219   %CheckIsBootstrapping();
    220   %ExportExperimentalFromRuntime(exports_container);
    221   for ( ; !IS_UNDEFINED(imports); imports = imports.next) {
    222     imports(exports_container);
    223   }
    224   for ( ; !IS_UNDEFINED(imports_from_experimental);
    225           imports_from_experimental = imports_from_experimental.next) {
    226     imports_from_experimental(exports_container);
    227   }
    228 
    229   utils.Export = UNDEFINED;
    230   utils.PostDebug = UNDEFINED;
    231   utils.PostExperimentals = UNDEFINED;
    232   typed_array_setup = UNDEFINED;
    233 }
    234 
    235 
    236 function PostDebug(utils) {
    237   for ( ; !IS_UNDEFINED(imports); imports = imports.next) {
    238     imports(exports_container);
    239   }
    240 
    241   exports_container = UNDEFINED;
    242 
    243   utils.Export = UNDEFINED;
    244   utils.Import = UNDEFINED;
    245   utils.ImportNow = UNDEFINED;
    246   utils.PostDebug = UNDEFINED;
    247   utils.PostExperimentals = UNDEFINED;
    248   typed_array_setup = UNDEFINED;
    249 }
    250 
    251 
    252 function InitializeBuiltinTypedArrays(utils, rng_state, rempio2result) {
    253   var setup_list =  typed_array_setup;
    254 
    255   for ( ; !IS_UNDEFINED(setup_list); setup_list = setup_list.next) {
    256     setup_list(rng_state, rempio2result);
    257   }
    258 }
    259 
    260 
    261 // -----------------------------------------------------------------------
    262 
    263 %OptimizeObjectForAddingMultipleProperties(utils, 14);
    264 
    265 utils.Import = Import;
    266 utils.ImportNow = ImportNow;
    267 utils.Export = Export;
    268 utils.ImportFromExperimental = ImportFromExperimental;
    269 utils.SetFunctionName = SetFunctionName;
    270 utils.InstallConstants = InstallConstants;
    271 utils.InstallFunctions = InstallFunctions;
    272 utils.InstallGetter = InstallGetter;
    273 utils.InstallGetterSetter = InstallGetterSetter;
    274 utils.OverrideFunction = OverrideFunction;
    275 utils.SetUpLockedPrototype = SetUpLockedPrototype;
    276 utils.PostNatives = PostNatives;
    277 utils.PostExperimentals = PostExperimentals;
    278 utils.PostDebug = PostDebug;
    279 
    280 %ToFastProperties(utils);
    281 
    282 // -----------------------------------------------------------------------
    283 
    284 %OptimizeObjectForAddingMultipleProperties(extrasUtils, 5);
    285 
    286 extrasUtils.logStackTrace = function logStackTrace() {
    287   %DebugTrace();
    288 };
    289 
    290 extrasUtils.log = function log() {
    291   let message = '';
    292   for (const arg of arguments) {
    293     message += arg;
    294   }
    295 
    296   %GlobalPrint(message);
    297 };
    298 
    299 // Extras need the ability to store private state on their objects without
    300 // exposing it to the outside world.
    301 
    302 extrasUtils.createPrivateSymbol = function createPrivateSymbol(name) {
    303   return %CreatePrivateSymbol(name);
    304 };
    305 
    306 // These functions are key for safe meta-programming:
    307 // http://wiki.ecmascript.org/doku.php?id=conventions:safe_meta_programming
    308 //
    309 // Technically they could all be derived from combinations of
    310 // Function.prototype.{bind,call,apply} but that introduces lots of layers of
    311 // indirection and slowness given how un-optimized bind is.
    312 
    313 extrasUtils.simpleBind = function simpleBind(func, thisArg) {
    314   return function(...args) {
    315     return %reflect_apply(func, thisArg, args);
    316   };
    317 };
    318 
    319 extrasUtils.uncurryThis = function uncurryThis(func) {
    320   return function(thisArg, ...args) {
    321     return %reflect_apply(func, thisArg, args);
    322   };
    323 };
    324 
    325 %ToFastProperties(extrasUtils);
    326 
    327 })
    328