| OLD | NEW |
| (Empty) |
| 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 | |
| 18 // Export to other scripts. | |
| 19 // In normal natives, this exports functions to other normal natives. | |
| 20 // In experimental natives, this exports to other experimental natives and | |
| 21 // to normal natives that import using utils.ImportFromExperimental. | |
| 22 function Export(f) { | |
| 23 f(exports_container); | |
| 24 } | |
| 25 | |
| 26 | |
| 27 // Import from other scripts. The actual importing happens in PostNatives and | |
| 28 // PostExperimental so that we can import from scripts executed later. However, | |
| 29 // that means that the import is not available until the very end. If the | |
| 30 // import needs to be available immediate, use ImportNow. | |
| 31 // In normal natives, this imports from other normal natives. | |
| 32 // In experimental natives, this imports from other experimental natives and | |
| 33 // whitelisted exports from normal natives. | |
| 34 function Import(f) { | |
| 35 f.next = imports; | |
| 36 imports = f; | |
| 37 } | |
| 38 | |
| 39 | |
| 40 // Import immediately from exports of previous scripts. We need this for | |
| 41 // functions called during bootstrapping. Hooking up imports in PostNatives | |
| 42 // would be too late. | |
| 43 function ImportNow(name) { | |
| 44 return exports_container[name]; | |
| 45 } | |
| 46 | |
| 47 | |
| 48 // In normal natives, import from experimental natives. | |
| 49 // Not callable from experimental natives. | |
| 50 function ImportFromExperimental(f) { | |
| 51 f.next = imports_from_experimental; | |
| 52 imports_from_experimental = f; | |
| 53 } | |
| 54 | |
| 55 | |
| 56 function SetFunctionName(f, name, prefix) { | |
| 57 if (IS_SYMBOL(name)) { | |
| 58 name = "[" + %SymbolDescription(name) + "]"; | |
| 59 } | |
| 60 if (IS_UNDEFINED(prefix)) { | |
| 61 %FunctionSetName(f, name); | |
| 62 } else { | |
| 63 %FunctionSetName(f, prefix + " " + name); | |
| 64 } | |
| 65 } | |
| 66 | |
| 67 | |
| 68 function InstallConstants(object, constants) { | |
| 69 %CheckIsBootstrapping(); | |
| 70 %OptimizeObjectForAddingMultipleProperties(object, constants.length >> 1); | |
| 71 var attributes = DONT_ENUM | DONT_DELETE | READ_ONLY; | |
| 72 for (var i = 0; i < constants.length; i += 2) { | |
| 73 var name = constants[i]; | |
| 74 var k = constants[i + 1]; | |
| 75 %AddNamedProperty(object, name, k, attributes); | |
| 76 } | |
| 77 %ToFastProperties(object); | |
| 78 } | |
| 79 | |
| 80 | |
| 81 function InstallFunctions(object, attributes, functions) { | |
| 82 %CheckIsBootstrapping(); | |
| 83 %OptimizeObjectForAddingMultipleProperties(object, functions.length >> 1); | |
| 84 for (var i = 0; i < functions.length; i += 2) { | |
| 85 var key = functions[i]; | |
| 86 var f = functions[i + 1]; | |
| 87 SetFunctionName(f, key); | |
| 88 %FunctionRemovePrototype(f); | |
| 89 %AddNamedProperty(object, key, f, attributes); | |
| 90 %SetNativeFlag(f); | |
| 91 } | |
| 92 %ToFastProperties(object); | |
| 93 } | |
| 94 | |
| 95 | |
| 96 // Helper function to install a getter-only accessor property. | |
| 97 function InstallGetter(object, name, getter, attributes) { | |
| 98 %CheckIsBootstrapping(); | |
| 99 if (typeof attributes == "undefined") { | |
| 100 attributes = DONT_ENUM; | |
| 101 } | |
| 102 SetFunctionName(getter, name, "get"); | |
| 103 %FunctionRemovePrototype(getter); | |
| 104 %DefineAccessorPropertyUnchecked(object, name, getter, null, attributes); | |
| 105 %SetNativeFlag(getter); | |
| 106 } | |
| 107 | |
| 108 | |
| 109 // Helper function to install a getter/setter accessor property. | |
| 110 function InstallGetterSetter(object, name, getter, setter) { | |
| 111 %CheckIsBootstrapping(); | |
| 112 SetFunctionName(getter, name, "get"); | |
| 113 SetFunctionName(setter, name, "set"); | |
| 114 %FunctionRemovePrototype(getter); | |
| 115 %FunctionRemovePrototype(setter); | |
| 116 %DefineAccessorPropertyUnchecked(object, name, getter, setter, DONT_ENUM); | |
| 117 %SetNativeFlag(getter); | |
| 118 %SetNativeFlag(setter); | |
| 119 } | |
| 120 | |
| 121 | |
| 122 // Prevents changes to the prototype of a built-in function. | |
| 123 // The "prototype" property of the function object is made non-configurable, | |
| 124 // and the prototype object is made non-extensible. The latter prevents | |
| 125 // changing the __proto__ property. | |
| 126 function SetUpLockedPrototype( | |
| 127 constructor, fields, methods) { | |
| 128 %CheckIsBootstrapping(); | |
| 129 var prototype = constructor.prototype; | |
| 130 // Install functions first, because this function is used to initialize | |
| 131 // PropertyDescriptor itself. | |
| 132 var property_count = (methods.length >> 1) + (fields ? fields.length : 0); | |
| 133 if (property_count >= 4) { | |
| 134 %OptimizeObjectForAddingMultipleProperties(prototype, property_count); | |
| 135 } | |
| 136 if (fields) { | |
| 137 for (var i = 0; i < fields.length; i++) { | |
| 138 %AddNamedProperty(prototype, fields[i], | |
| 139 UNDEFINED, DONT_ENUM | DONT_DELETE); | |
| 140 } | |
| 141 } | |
| 142 for (var i = 0; i < methods.length; i += 2) { | |
| 143 var key = methods[i]; | |
| 144 var f = methods[i + 1]; | |
| 145 %AddNamedProperty(prototype, key, f, DONT_ENUM | DONT_DELETE | READ_ONLY); | |
| 146 %SetNativeFlag(f); | |
| 147 } | |
| 148 %InternalSetPrototype(prototype, null); | |
| 149 %ToFastProperties(prototype); | |
| 150 } | |
| 151 | |
| 152 | |
| 153 // ----------------------------------------------------------------------- | |
| 154 // To be called by bootstrapper | |
| 155 | |
| 156 function PostNatives(utils) { | |
| 157 %CheckIsBootstrapping(); | |
| 158 | |
| 159 for ( ; !IS_UNDEFINED(imports); imports = imports.next) { | |
| 160 imports(exports_container); | |
| 161 } | |
| 162 | |
| 163 // Whitelist of exports from normal natives to experimental natives and debug. | |
| 164 var expose_list = [ | |
| 165 "ArrayToString", | |
| 166 "FunctionSourceString", | |
| 167 "GetIterator", | |
| 168 "GetMethod", | |
| 169 "InnerArrayEvery", | |
| 170 "InnerArrayFilter", | |
| 171 "InnerArrayForEach", | |
| 172 "InnerArrayIndexOf", | |
| 173 "InnerArrayJoin", | |
| 174 "InnerArrayLastIndexOf", | |
| 175 "InnerArrayMap", | |
| 176 "InnerArrayReduce", | |
| 177 "InnerArrayReduceRight", | |
| 178 "InnerArrayReverse", | |
| 179 "InnerArraySome", | |
| 180 "InnerArraySort", | |
| 181 "InnerArrayToLocaleString", | |
| 182 "IsNaN", | |
| 183 "MathMax", | |
| 184 "MathMin", | |
| 185 "ObjectIsFrozen", | |
| 186 "ObjectDefineProperty", | |
| 187 "OwnPropertyKeys", | |
| 188 "SymbolToString", | |
| 189 "ToNameArray", | |
| 190 // From runtime: | |
| 191 "is_concat_spreadable_symbol", | |
| 192 "iterator_symbol", | |
| 193 "promise_status_symbol", | |
| 194 "promise_value_symbol", | |
| 195 "reflect_apply", | |
| 196 "reflect_construct", | |
| 197 "to_string_tag_symbol", | |
| 198 ]; | |
| 199 | |
| 200 var filtered_exports = {}; | |
| 201 %OptimizeObjectForAddingMultipleProperties( | |
| 202 filtered_exports, expose_list.length); | |
| 203 for (var key of expose_list) { | |
| 204 filtered_exports[key] = exports_container[key]; | |
| 205 } | |
| 206 %ToFastProperties(filtered_exports); | |
| 207 exports_container = filtered_exports; | |
| 208 | |
| 209 utils.PostNatives = UNDEFINED; | |
| 210 utils.ImportFromExperimental = UNDEFINED; | |
| 211 } | |
| 212 | |
| 213 | |
| 214 function PostExperimentals(utils) { | |
| 215 %CheckIsBootstrapping(); | |
| 216 %ExportExperimentalFromRuntime(exports_container); | |
| 217 for ( ; !IS_UNDEFINED(imports); imports = imports.next) { | |
| 218 imports(exports_container); | |
| 219 } | |
| 220 for ( ; !IS_UNDEFINED(imports_from_experimental); | |
| 221 imports_from_experimental = imports_from_experimental.next) { | |
| 222 imports_from_experimental(exports_container); | |
| 223 } | |
| 224 | |
| 225 exports_container = UNDEFINED; | |
| 226 | |
| 227 utils.PostExperimentals = UNDEFINED; | |
| 228 utils.PostDebug = UNDEFINED; | |
| 229 utils.Import = UNDEFINED; | |
| 230 utils.Export = UNDEFINED; | |
| 231 } | |
| 232 | |
| 233 | |
| 234 function PostDebug(utils) { | |
| 235 for ( ; !IS_UNDEFINED(imports); imports = imports.next) { | |
| 236 imports(exports_container); | |
| 237 } | |
| 238 | |
| 239 exports_container = UNDEFINED; | |
| 240 | |
| 241 utils.PostDebug = UNDEFINED; | |
| 242 utils.PostExperimentals = UNDEFINED; | |
| 243 utils.Import = UNDEFINED; | |
| 244 utils.Export = UNDEFINED; | |
| 245 } | |
| 246 | |
| 247 // ----------------------------------------------------------------------- | |
| 248 | |
| 249 %OptimizeObjectForAddingMultipleProperties(utils, 13); | |
| 250 | |
| 251 utils.Import = Import; | |
| 252 utils.ImportNow = ImportNow; | |
| 253 utils.Export = Export; | |
| 254 utils.ImportFromExperimental = ImportFromExperimental; | |
| 255 utils.SetFunctionName = SetFunctionName; | |
| 256 utils.InstallConstants = InstallConstants; | |
| 257 utils.InstallFunctions = InstallFunctions; | |
| 258 utils.InstallGetter = InstallGetter; | |
| 259 utils.InstallGetterSetter = InstallGetterSetter; | |
| 260 utils.SetUpLockedPrototype = SetUpLockedPrototype; | |
| 261 utils.PostNatives = PostNatives; | |
| 262 utils.PostExperimentals = PostExperimentals; | |
| 263 utils.PostDebug = PostDebug; | |
| 264 | |
| 265 %ToFastProperties(utils); | |
| 266 | |
| 267 // ----------------------------------------------------------------------- | |
| 268 | |
| 269 %OptimizeObjectForAddingMultipleProperties(extrasUtils, 5); | |
| 270 | |
| 271 extrasUtils.logStackTrace = function logStackTrace() { | |
| 272 %DebugTrace(); | |
| 273 }; | |
| 274 | |
| 275 extrasUtils.log = function log() { | |
| 276 let message = ''; | |
| 277 for (const arg of arguments) { | |
| 278 message += arg; | |
| 279 } | |
| 280 | |
| 281 %GlobalPrint(message); | |
| 282 }; | |
| 283 | |
| 284 // Extras need the ability to store private state on their objects without | |
| 285 // exposing it to the outside world. | |
| 286 | |
| 287 extrasUtils.createPrivateSymbol = function createPrivateSymbol(name) { | |
| 288 return %CreatePrivateSymbol(name); | |
| 289 }; | |
| 290 | |
| 291 // These functions are key for safe meta-programming: | |
| 292 // http://wiki.ecmascript.org/doku.php?id=conventions:safe_meta_programming | |
| 293 // | |
| 294 // Technically they could all be derived from combinations of | |
| 295 // Function.prototype.{bind,call,apply} but that introduces lots of layers of | |
| 296 // indirection and slowness given how un-optimized bind is. | |
| 297 | |
| 298 extrasUtils.simpleBind = function simpleBind(func, thisArg) { | |
| 299 return function() { | |
| 300 return %Apply(func, thisArg, arguments, 0, arguments.length); | |
| 301 }; | |
| 302 }; | |
| 303 | |
| 304 extrasUtils.uncurryThis = function uncurryThis(func) { | |
| 305 return function(thisArg) { | |
| 306 return %Apply(func, thisArg, arguments, 1, arguments.length - 1); | |
| 307 }; | |
| 308 }; | |
| 309 | |
| 310 %ToFastProperties(extrasUtils); | |
| 311 | |
| 312 }) | |
| OLD | NEW |