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