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 function OverrideFunction(object, name, f, afterInitialBootstrap) {
    116   %CheckIsBootstrapping();
    117   %object_define_property(object, name, { value: f,
    118                                           writeable: true,
    119                                           configurable: true,
    120                                           enumerable: false });
    121   SetFunctionName(f, name);
    122   if (!afterInitialBootstrap) %FunctionRemovePrototype(f);
    123   %SetNativeFlag(f);
    124 }
    125 
    126 
    127 // Prevents changes to the prototype of a built-in function.
    128 // The "prototype" property of the function object is made non-configurable,
    129 // and the prototype object is made non-extensible. The latter prevents
    130 // changing the __proto__ property.
    131 function SetUpLockedPrototype(
    132     constructor, fields, methods) {
    133   %CheckIsBootstrapping();
    134   var prototype = constructor.prototype;
    135   // Install functions first, because this function is used to initialize
    136   // PropertyDescriptor itself.
    137   var property_count = (methods.length >> 1) + (fields ? fields.length : 0);
    138   if (property_count >= 4) {
    139     %OptimizeObjectForAddingMultipleProperties(prototype, property_count);
    140   }
    141   if (fields) {
    142     for (var i = 0; i < fields.length; i++) {
    143       %AddNamedProperty(prototype, fields[i],
    144                         UNDEFINED, DONT_ENUM | DONT_DELETE);
    145     }
    146   }
    147   for (var i = 0; i < methods.length; i += 2) {
    148     var key = methods[i];
    149     var f = methods[i + 1];
    150     %AddNamedProperty(prototype, key, f, DONT_ENUM | DONT_DELETE | READ_ONLY);
    151     %SetNativeFlag(f);
    152   }
    153   %InternalSetPrototype(prototype, null);
    154   %ToFastProperties(prototype);
    155 }
    156 
    157 
    158 // -----------------------------------------------------------------------
    159 // To be called by bootstrapper
    160 
    161 function PostNatives(utils) {
    162   %CheckIsBootstrapping();
    163 
    164   for ( ; !IS_UNDEFINED(imports); imports = imports.next) {
    165     imports(exports_container);
    166   }
    167 
    168   // Whitelist of exports from normal natives to experimental natives and debug.
    169   var expose_list = [
    170     "FormatDateToParts",
    171     "MapEntries",
    172     "MapIteratorNext",
    173     "MaxSimple",
    174     "MinSimple",
    175     "SetIteratorNext",
    176     "SetValues",
    177     "ToLocaleLowerCaseI18N",
    178     "ToLocaleUpperCaseI18N",
    179     "ToLowerCaseI18N",
    180     "ToUpperCaseI18N",
    181     // From runtime:
    182     "promise_result_symbol",
    183     "promise_state_symbol",
    184     "reflect_apply",
    185     "to_string_tag_symbol",
    186   ];
    187 
    188   var filtered_exports = {};
    189   %OptimizeObjectForAddingMultipleProperties(
    190       filtered_exports, expose_list.length);
    191   for (var key of expose_list) {
    192     filtered_exports[key] = exports_container[key];
    193   }
    194   %ToFastProperties(filtered_exports);
    195   exports_container = filtered_exports;
    196 
    197   utils.PostNatives = UNDEFINED;
    198   utils.ImportFromExperimental = UNDEFINED;
    199 }
    200 
    201 
    202 function PostExperimentals(utils) {
    203   %CheckIsBootstrapping();
    204   for ( ; !IS_UNDEFINED(imports); imports = imports.next) {
    205     imports(exports_container);
    206   }
    207   for ( ; !IS_UNDEFINED(imports_from_experimental);
    208           imports_from_experimental = imports_from_experimental.next) {
    209     imports_from_experimental(exports_container);
    210   }
    211 
    212   utils.Export = UNDEFINED;
    213   utils.PostDebug = UNDEFINED;
    214   utils.PostExperimentals = UNDEFINED;
    215   typed_array_setup = UNDEFINED;
    216 }
    217 
    218 
    219 function PostDebug(utils) {
    220   for ( ; !IS_UNDEFINED(imports); imports = imports.next) {
    221     imports(exports_container);
    222   }
    223 
    224   exports_container = UNDEFINED;
    225 
    226   utils.Export = UNDEFINED;
    227   utils.Import = UNDEFINED;
    228   utils.ImportNow = UNDEFINED;
    229   utils.PostDebug = UNDEFINED;
    230   utils.PostExperimentals = UNDEFINED;
    231   typed_array_setup = UNDEFINED;
    232 }
    233 
    234 
    235 function InitializeBuiltinTypedArrays(utils, rng_state, rempio2result) {
    236   var setup_list =  typed_array_setup;
    237 
    238   for ( ; !IS_UNDEFINED(setup_list); setup_list = setup_list.next) {
    239     setup_list(rng_state, rempio2result);
    240   }
    241 }
    242 
    243 
    244 // -----------------------------------------------------------------------
    245 
    246 %OptimizeObjectForAddingMultipleProperties(utils, 14);
    247 
    248 utils.Import = Import;
    249 utils.ImportNow = ImportNow;
    250 utils.Export = Export;
    251 utils.ImportFromExperimental = ImportFromExperimental;
    252 utils.SetFunctionName = SetFunctionName;
    253 utils.InstallConstants = InstallConstants;
    254 utils.InstallFunctions = InstallFunctions;
    255 utils.InstallGetter = InstallGetter;
    256 utils.OverrideFunction = OverrideFunction;
    257 utils.SetUpLockedPrototype = SetUpLockedPrototype;
    258 utils.PostNatives = PostNatives;
    259 utils.PostExperimentals = PostExperimentals;
    260 utils.PostDebug = PostDebug;
    261 
    262 %ToFastProperties(utils);
    263 
    264 // -----------------------------------------------------------------------
    265 
    266 %OptimizeObjectForAddingMultipleProperties(extrasUtils, 7);
    267 
    268 extrasUtils.logStackTrace = function logStackTrace() {
    269   %DebugTrace();
    270 };
    271 
    272 extrasUtils.log = function log() {
    273   let message = '';
    274   for (const arg of arguments) {
    275     message += arg;
    276   }
    277 
    278   %GlobalPrint(message);
    279 };
    280 
    281 // Extras need the ability to store private state on their objects without
    282 // exposing it to the outside world.
    283 
    284 extrasUtils.createPrivateSymbol = function createPrivateSymbol(name) {
    285   return %CreatePrivateSymbol(name);
    286 };
    287 
    288 // These functions are key for safe meta-programming:
    289 // http://wiki.ecmascript.org/doku.php?id=conventions:safe_meta_programming
    290 //
    291 // Technically they could all be derived from combinations of
    292 // Function.prototype.{bind,call,apply} but that introduces lots of layers of
    293 // indirection and slowness given how un-optimized bind is.
    294 
    295 extrasUtils.simpleBind = function simpleBind(func, thisArg) {
    296   return function(...args) {
    297     return %reflect_apply(func, thisArg, args);
    298   };
    299 };
    300 
    301 extrasUtils.uncurryThis = function uncurryThis(func) {
    302   return function(thisArg, ...args) {
    303     return %reflect_apply(func, thisArg, args);
    304   };
    305 };
    306 
    307 // We pass true to trigger the debugger's on exception handler.
    308 extrasUtils.rejectPromise = function rejectPromise(promise, reason) {
    309   %promise_internal_reject(promise, reason, true);
    310 }
    311 
    312 extrasUtils.markPromiseAsHandled = function markPromiseAsHandled(promise) {
    313   %PromiseMarkAsHandled(promise);
    314 };
    315 
    316 %ToFastProperties(extrasUtils);
    317 
    318 })
    319