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 14var imports = UNDEFINED; 15var imports_from_experimental = UNDEFINED; 16var exports_container = %ExportFromRuntime({}); 17var typed_array_setup = UNDEFINED; 18 19// Register context value to be initialized with a typed array in 20// Genesis::InitializeBuiltinTypedArrays. 21function 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. 30function 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. 42function 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. 51function ImportNow(name) { 52 return exports_container[name]; 53} 54 55 56// In normal natives, import from experimental natives. 57// Not callable from experimental natives. 58function ImportFromExperimental(f) { 59 f.next = imports_from_experimental; 60 imports_from_experimental = f; 61} 62 63 64function 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 76function 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 89function 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. 105function 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 115function 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. 131function 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 161function 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 202function 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 219function 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 235function 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 248utils.Import = Import; 249utils.ImportNow = ImportNow; 250utils.Export = Export; 251utils.ImportFromExperimental = ImportFromExperimental; 252utils.SetFunctionName = SetFunctionName; 253utils.InstallConstants = InstallConstants; 254utils.InstallFunctions = InstallFunctions; 255utils.InstallGetter = InstallGetter; 256utils.OverrideFunction = OverrideFunction; 257utils.SetUpLockedPrototype = SetUpLockedPrototype; 258utils.PostNatives = PostNatives; 259utils.PostExperimentals = PostExperimentals; 260utils.PostDebug = PostDebug; 261 262%ToFastProperties(utils); 263 264// ----------------------------------------------------------------------- 265 266%OptimizeObjectForAddingMultipleProperties(extrasUtils, 7); 267 268extrasUtils.logStackTrace = function logStackTrace() { 269 %DebugTrace(); 270}; 271 272extrasUtils.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 284extrasUtils.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 295extrasUtils.simpleBind = function simpleBind(func, thisArg) { 296 return function(...args) { 297 return %reflect_apply(func, thisArg, args); 298 }; 299}; 300 301extrasUtils.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. 308extrasUtils.rejectPromise = function rejectPromise(promise, reason) { 309 %promise_internal_reject(promise, reason, true); 310} 311 312extrasUtils.markPromiseAsHandled = function markPromiseAsHandled(promise) { 313 %PromiseMarkAsHandled(promise); 314}; 315 316%ToFastProperties(extrasUtils); 317 318}) 319