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, DONT_ENUM);
    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     "AddBoundMethod",
    185     "ArrayToString",
    186     "AsyncFunctionNext",
    187     "AsyncFunctionThrow",
    188     "ErrorToString",
    189     "GetIterator",
    190     "GetMethod",
    191     "IntlParseDate",
    192     "IntlParseNumber",
    193     "IsNaN",
    194     "MakeError",
    195     "MakeRangeError",
    196     "MakeTypeError",
    197     "MapEntries",
    198     "MapIterator",
    199     "MapIteratorNext",
    200     "MaxSimple",
    201     "MinSimple",
    202     "NumberIsInteger",
    203     "PromiseChain",
    204     "PromiseDefer",
    205     "PromiseAccept",
    206     "PromiseCreateRejected",
    207     "PromiseCreateResolved",
    208     "PromiseThen",
    209     "RegExpSubclassExecJS",
    210     "RegExpSubclassMatch",
    211     "RegExpSubclassReplace",
    212     "RegExpSubclassSearch",
    213     "RegExpSubclassSplit",
    214     "RegExpSubclassTest",
    215     "SetIterator",
    216     "SetIteratorNext",
    217     "SetValues",
    218     "SymbolToString",
    219     "ToLocaleLowerCaseI18N",
    220     "ToLocaleUpperCaseI18N",
    221     "ToLowerCaseI18N",
    222     "ToPositiveInteger",
    223     "ToUpperCaseI18N",
    224     // From runtime:
    225     "is_concat_spreadable_symbol",
    226     "iterator_symbol",
    227     "promise_result_symbol",
    228     "promise_state_symbol",
    229     "object_freeze",
    230     "object_is_frozen",
    231     "object_is_sealed",
    232     "reflect_apply",
    233     "reflect_construct",
    234     "regexp_flags_symbol",
    235     "to_string_tag_symbol",
    236     "object_to_string",
    237     "species_symbol",
    238     "match_symbol",
    239     "replace_symbol",
    240     "search_symbol",
    241     "split_symbol",
    242   ];
    243 
    244   var filtered_exports = {};
    245   %OptimizeObjectForAddingMultipleProperties(
    246       filtered_exports, expose_list.length);
    247   for (var key of expose_list) {
    248     filtered_exports[key] = exports_container[key];
    249   }
    250   %ToFastProperties(filtered_exports);
    251   exports_container = filtered_exports;
    252 
    253   utils.PostNatives = UNDEFINED;
    254   utils.ImportFromExperimental = UNDEFINED;
    255 }
    256 
    257 
    258 function PostExperimentals(utils) {
    259   %CheckIsBootstrapping();
    260   %ExportExperimentalFromRuntime(exports_container);
    261   for ( ; !IS_UNDEFINED(imports); imports = imports.next) {
    262     imports(exports_container);
    263   }
    264   for ( ; !IS_UNDEFINED(imports_from_experimental);
    265           imports_from_experimental = imports_from_experimental.next) {
    266     imports_from_experimental(exports_container);
    267   }
    268 
    269   utils.Export = UNDEFINED;
    270   utils.PostDebug = UNDEFINED;
    271   utils.PostExperimentals = UNDEFINED;
    272   typed_array_setup = UNDEFINED;
    273 }
    274 
    275 
    276 function PostDebug(utils) {
    277   for ( ; !IS_UNDEFINED(imports); imports = imports.next) {
    278     imports(exports_container);
    279   }
    280 
    281   exports_container = UNDEFINED;
    282 
    283   utils.Export = UNDEFINED;
    284   utils.Import = UNDEFINED;
    285   utils.ImportNow = UNDEFINED;
    286   utils.PostDebug = UNDEFINED;
    287   utils.PostExperimentals = UNDEFINED;
    288   typed_array_setup = UNDEFINED;
    289 }
    290 
    291 
    292 function InitializeBuiltinTypedArrays(utils, rng_state, rempio2result) {
    293   var setup_list =  typed_array_setup;
    294 
    295   for ( ; !IS_UNDEFINED(setup_list); setup_list = setup_list.next) {
    296     setup_list(rng_state, rempio2result);
    297   }
    298 }
    299 
    300 
    301 // -----------------------------------------------------------------------
    302 
    303 %OptimizeObjectForAddingMultipleProperties(utils, 14);
    304 
    305 utils.Import = Import;
    306 utils.ImportNow = ImportNow;
    307 utils.Export = Export;
    308 utils.ImportFromExperimental = ImportFromExperimental;
    309 utils.SetFunctionName = SetFunctionName;
    310 utils.InstallConstants = InstallConstants;
    311 utils.InstallFunctions = InstallFunctions;
    312 utils.InstallGetter = InstallGetter;
    313 utils.InstallGetterSetter = InstallGetterSetter;
    314 utils.OverrideFunction = OverrideFunction;
    315 utils.SetUpLockedPrototype = SetUpLockedPrototype;
    316 utils.PostNatives = PostNatives;
    317 utils.PostExperimentals = PostExperimentals;
    318 utils.PostDebug = PostDebug;
    319 
    320 %ToFastProperties(utils);
    321 
    322 // -----------------------------------------------------------------------
    323 
    324 %OptimizeObjectForAddingMultipleProperties(extrasUtils, 5);
    325 
    326 extrasUtils.logStackTrace = function logStackTrace() {
    327   %DebugTrace();
    328 };
    329 
    330 extrasUtils.log = function log() {
    331   let message = '';
    332   for (const arg of arguments) {
    333     message += arg;
    334   }
    335 
    336   %GlobalPrint(message);
    337 };
    338 
    339 // Extras need the ability to store private state on their objects without
    340 // exposing it to the outside world.
    341 
    342 extrasUtils.createPrivateSymbol = function createPrivateSymbol(name) {
    343   return %CreatePrivateSymbol(name);
    344 };
    345 
    346 // These functions are key for safe meta-programming:
    347 // http://wiki.ecmascript.org/doku.php?id=conventions:safe_meta_programming
    348 //
    349 // Technically they could all be derived from combinations of
    350 // Function.prototype.{bind,call,apply} but that introduces lots of layers of
    351 // indirection and slowness given how un-optimized bind is.
    352 
    353 extrasUtils.simpleBind = function simpleBind(func, thisArg) {
    354   return function(...args) {
    355     return %reflect_apply(func, thisArg, args);
    356   };
    357 };
    358 
    359 extrasUtils.uncurryThis = function uncurryThis(func) {
    360   return function(thisArg, ...args) {
    361     return %reflect_apply(func, thisArg, args);
    362   };
    363 };
    364 
    365 %ToFastProperties(extrasUtils);
    366 
    367 })
    368