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 |