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, attributes); 124 %SetNativeFlag(getter); 125 %SetNativeFlag(setter); 126} 127 128 129function 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. 145function 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 175function 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 218function 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 236function 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 252function 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 265utils.Import = Import; 266utils.ImportNow = ImportNow; 267utils.Export = Export; 268utils.ImportFromExperimental = ImportFromExperimental; 269utils.SetFunctionName = SetFunctionName; 270utils.InstallConstants = InstallConstants; 271utils.InstallFunctions = InstallFunctions; 272utils.InstallGetter = InstallGetter; 273utils.InstallGetterSetter = InstallGetterSetter; 274utils.OverrideFunction = OverrideFunction; 275utils.SetUpLockedPrototype = SetUpLockedPrototype; 276utils.PostNatives = PostNatives; 277utils.PostExperimentals = PostExperimentals; 278utils.PostDebug = PostDebug; 279 280%ToFastProperties(utils); 281 282// ----------------------------------------------------------------------- 283 284%OptimizeObjectForAddingMultipleProperties(extrasUtils, 5); 285 286extrasUtils.logStackTrace = function logStackTrace() { 287 %DebugTrace(); 288}; 289 290extrasUtils.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 302extrasUtils.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 313extrasUtils.simpleBind = function simpleBind(func, thisArg) { 314 return function(...args) { 315 return %reflect_apply(func, thisArg, args); 316 }; 317}; 318 319extrasUtils.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