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 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 "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 258function 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 276function 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 292function 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 305utils.Import = Import; 306utils.ImportNow = ImportNow; 307utils.Export = Export; 308utils.ImportFromExperimental = ImportFromExperimental; 309utils.SetFunctionName = SetFunctionName; 310utils.InstallConstants = InstallConstants; 311utils.InstallFunctions = InstallFunctions; 312utils.InstallGetter = InstallGetter; 313utils.InstallGetterSetter = InstallGetterSetter; 314utils.OverrideFunction = OverrideFunction; 315utils.SetUpLockedPrototype = SetUpLockedPrototype; 316utils.PostNatives = PostNatives; 317utils.PostExperimentals = PostExperimentals; 318utils.PostDebug = PostDebug; 319 320%ToFastProperties(utils); 321 322// ----------------------------------------------------------------------- 323 324%OptimizeObjectForAddingMultipleProperties(extrasUtils, 5); 325 326extrasUtils.logStackTrace = function logStackTrace() { 327 %DebugTrace(); 328}; 329 330extrasUtils.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 342extrasUtils.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 353extrasUtils.simpleBind = function simpleBind(func, thisArg) { 354 return function(...args) { 355 return %reflect_apply(func, thisArg, args); 356 }; 357}; 358 359extrasUtils.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