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 115// Helper function to install a getter/setter accessor property. 116function 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// Prevents changes to the prototype of a built-in function. 130// The "prototype" property of the function object is made non-configurable, 131// and the prototype object is made non-extensible. The latter prevents 132// changing the __proto__ property. 133function SetUpLockedPrototype( 134 constructor, fields, methods) { 135 %CheckIsBootstrapping(); 136 var prototype = constructor.prototype; 137 // Install functions first, because this function is used to initialize 138 // PropertyDescriptor itself. 139 var property_count = (methods.length >> 1) + (fields ? fields.length : 0); 140 if (property_count >= 4) { 141 %OptimizeObjectForAddingMultipleProperties(prototype, property_count); 142 } 143 if (fields) { 144 for (var i = 0; i < fields.length; i++) { 145 %AddNamedProperty(prototype, fields[i], 146 UNDEFINED, DONT_ENUM | DONT_DELETE); 147 } 148 } 149 for (var i = 0; i < methods.length; i += 2) { 150 var key = methods[i]; 151 var f = methods[i + 1]; 152 %AddNamedProperty(prototype, key, f, DONT_ENUM | DONT_DELETE | READ_ONLY); 153 %SetNativeFlag(f); 154 } 155 %InternalSetPrototype(prototype, null); 156 %ToFastProperties(prototype); 157} 158 159 160// ----------------------------------------------------------------------- 161// To be called by bootstrapper 162 163function PostNatives(utils) { 164 %CheckIsBootstrapping(); 165 166 for ( ; !IS_UNDEFINED(imports); imports = imports.next) { 167 imports(exports_container); 168 } 169 170 // Whitelist of exports from normal natives to experimental natives and debug. 171 var expose_list = [ 172 "ArrayToString", 173 "ErrorToString", 174 "GetIterator", 175 "GetMethod", 176 "IsNaN", 177 "MakeError", 178 "MakeTypeError", 179 "MapEntries", 180 "MapIterator", 181 "MapIteratorNext", 182 "MathMax", 183 "MathMin", 184 "MaxSimple", 185 "MinSimple", 186 "ObjectDefineProperty", 187 "ObserveArrayMethods", 188 "ObserveObjectMethods", 189 "PromiseChain", 190 "PromiseDeferred", 191 "PromiseResolved", 192 "SameValueZero", 193 "SetIterator", 194 "SetIteratorNext", 195 "SetValues", 196 "SymbolToString", 197 "ToPositiveInteger", 198 // From runtime: 199 "is_concat_spreadable_symbol", 200 "iterator_symbol", 201 "promise_status_symbol", 202 "promise_value_symbol", 203 "object_freeze", 204 "object_is_frozen", 205 "object_is_sealed", 206 "reflect_apply", 207 "reflect_construct", 208 "regexp_flags_symbol", 209 "to_string_tag_symbol", 210 "object_to_string", 211 "species_symbol", 212 ]; 213 214 var filtered_exports = {}; 215 %OptimizeObjectForAddingMultipleProperties( 216 filtered_exports, expose_list.length); 217 for (var key of expose_list) { 218 filtered_exports[key] = exports_container[key]; 219 } 220 %ToFastProperties(filtered_exports); 221 exports_container = filtered_exports; 222 223 utils.PostNatives = UNDEFINED; 224 utils.ImportFromExperimental = UNDEFINED; 225} 226 227 228function PostExperimentals(utils) { 229 %CheckIsBootstrapping(); 230 %ExportExperimentalFromRuntime(exports_container); 231 for ( ; !IS_UNDEFINED(imports); imports = imports.next) { 232 imports(exports_container); 233 } 234 for ( ; !IS_UNDEFINED(imports_from_experimental); 235 imports_from_experimental = imports_from_experimental.next) { 236 imports_from_experimental(exports_container); 237 } 238 239 utils.CreateDoubleResultArray(); 240 utils.CreateDoubleResultArray = UNDEFINED; 241 242 utils.Export = UNDEFINED; 243 utils.PostDebug = UNDEFINED; 244 utils.PostExperimentals = UNDEFINED; 245 typed_array_setup = UNDEFINED; 246} 247 248 249function PostDebug(utils) { 250 for ( ; !IS_UNDEFINED(imports); imports = imports.next) { 251 imports(exports_container); 252 } 253 254 utils.CreateDoubleResultArray(); 255 utils.CreateDoubleResultArray = UNDEFINED; 256 257 exports_container = UNDEFINED; 258 259 utils.Export = UNDEFINED; 260 utils.Import = UNDEFINED; 261 utils.ImportNow = UNDEFINED; 262 utils.PostDebug = UNDEFINED; 263 utils.PostExperimentals = UNDEFINED; 264 typed_array_setup = UNDEFINED; 265} 266 267 268function InitializeBuiltinTypedArrays(utils, rng_state, rempio2result) { 269 var setup_list = typed_array_setup; 270 271 for ( ; !IS_UNDEFINED(setup_list); setup_list = setup_list.next) { 272 setup_list(rng_state, rempio2result); 273 } 274} 275 276 277// ----------------------------------------------------------------------- 278 279%OptimizeObjectForAddingMultipleProperties(utils, 14); 280 281utils.Import = Import; 282utils.ImportNow = ImportNow; 283utils.Export = Export; 284utils.ImportFromExperimental = ImportFromExperimental; 285utils.SetFunctionName = SetFunctionName; 286utils.InstallConstants = InstallConstants; 287utils.InstallFunctions = InstallFunctions; 288utils.InstallGetter = InstallGetter; 289utils.InstallGetterSetter = InstallGetterSetter; 290utils.SetUpLockedPrototype = SetUpLockedPrototype; 291utils.PostNatives = PostNatives; 292utils.PostExperimentals = PostExperimentals; 293utils.PostDebug = PostDebug; 294 295%ToFastProperties(utils); 296 297// ----------------------------------------------------------------------- 298 299%OptimizeObjectForAddingMultipleProperties(extrasUtils, 5); 300 301extrasUtils.logStackTrace = function logStackTrace() { 302 %DebugTrace(); 303}; 304 305extrasUtils.log = function log() { 306 let message = ''; 307 for (const arg of arguments) { 308 message += arg; 309 } 310 311 %GlobalPrint(message); 312}; 313 314// Extras need the ability to store private state on their objects without 315// exposing it to the outside world. 316 317extrasUtils.createPrivateSymbol = function createPrivateSymbol(name) { 318 return %CreatePrivateSymbol(name); 319}; 320 321// These functions are key for safe meta-programming: 322// http://wiki.ecmascript.org/doku.php?id=conventions:safe_meta_programming 323// 324// Technically they could all be derived from combinations of 325// Function.prototype.{bind,call,apply} but that introduces lots of layers of 326// indirection and slowness given how un-optimized bind is. 327 328extrasUtils.simpleBind = function simpleBind(func, thisArg) { 329 return function() { 330 return %Apply(func, thisArg, arguments, 0, arguments.length); 331 }; 332}; 333 334extrasUtils.uncurryThis = function uncurryThis(func) { 335 return function(thisArg) { 336 return %Apply(func, thisArg, arguments, 1, arguments.length - 1); 337 }; 338}; 339 340%ToFastProperties(extrasUtils); 341 342}) 343