blob: 2779393bd195d1f3fdb08f2fde678bdb9661db63 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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
129// Prevents changes to the prototype of a built-in function.
130// The "prototype" property of the function object is made non-configurable,
131// and the prototype object is made non-extensible. The latter prevents
132// changing the __proto__ property.
133function SetUpLockedPrototype(
134 constructor, fields, methods) {
135 %CheckIsBootstrapping();
136 var prototype = constructor.prototype;
137 // Install functions first, because this function is used to initialize
138 // PropertyDescriptor itself.
139 var property_count = (methods.length >> 1) + (fields ? fields.length : 0);
140 if (property_count >= 4) {
141 %OptimizeObjectForAddingMultipleProperties(prototype, property_count);
142 }
143 if (fields) {
144 for (var i = 0; i < fields.length; i++) {
145 %AddNamedProperty(prototype, fields[i],
146 UNDEFINED, DONT_ENUM | DONT_DELETE);
147 }
148 }
149 for (var i = 0; i < methods.length; i += 2) {
150 var key = methods[i];
151 var f = methods[i + 1];
152 %AddNamedProperty(prototype, key, f, DONT_ENUM | DONT_DELETE | READ_ONLY);
153 %SetNativeFlag(f);
154 }
155 %InternalSetPrototype(prototype, null);
156 %ToFastProperties(prototype);
157}
158
159
160// -----------------------------------------------------------------------
161// To be called by bootstrapper
162
163function PostNatives(utils) {
164 %CheckIsBootstrapping();
165
166 for ( ; !IS_UNDEFINED(imports); imports = imports.next) {
167 imports(exports_container);
168 }
169
170 // Whitelist of exports from normal natives to experimental natives and debug.
171 var expose_list = [
172 "ArrayToString",
173 "ErrorToString",
174 "GetIterator",
175 "GetMethod",
176 "IsNaN",
177 "MakeError",
178 "MakeTypeError",
179 "MapEntries",
180 "MapIterator",
181 "MapIteratorNext",
182 "MathMax",
183 "MathMin",
184 "MaxSimple",
185 "MinSimple",
186 "ObjectDefineProperty",
187 "ObserveArrayMethods",
188 "ObserveObjectMethods",
189 "PromiseChain",
190 "PromiseDeferred",
191 "PromiseResolved",
192 "SameValueZero",
193 "SetIterator",
194 "SetIteratorNext",
195 "SetValues",
196 "SymbolToString",
197 "ToPositiveInteger",
198 // From runtime:
199 "is_concat_spreadable_symbol",
200 "iterator_symbol",
201 "promise_status_symbol",
202 "promise_value_symbol",
203 "object_freeze",
204 "object_is_frozen",
205 "object_is_sealed",
206 "reflect_apply",
207 "reflect_construct",
208 "regexp_flags_symbol",
209 "to_string_tag_symbol",
210 "object_to_string",
211 "species_symbol",
212 ];
213
214 var filtered_exports = {};
215 %OptimizeObjectForAddingMultipleProperties(
216 filtered_exports, expose_list.length);
217 for (var key of expose_list) {
218 filtered_exports[key] = exports_container[key];
219 }
220 %ToFastProperties(filtered_exports);
221 exports_container = filtered_exports;
222
223 utils.PostNatives = UNDEFINED;
224 utils.ImportFromExperimental = UNDEFINED;
225}
226
227
228function PostExperimentals(utils) {
229 %CheckIsBootstrapping();
230 %ExportExperimentalFromRuntime(exports_container);
231 for ( ; !IS_UNDEFINED(imports); imports = imports.next) {
232 imports(exports_container);
233 }
234 for ( ; !IS_UNDEFINED(imports_from_experimental);
235 imports_from_experimental = imports_from_experimental.next) {
236 imports_from_experimental(exports_container);
237 }
238
239 utils.CreateDoubleResultArray();
240 utils.CreateDoubleResultArray = UNDEFINED;
241
242 utils.Export = UNDEFINED;
243 utils.PostDebug = UNDEFINED;
244 utils.PostExperimentals = UNDEFINED;
245 typed_array_setup = UNDEFINED;
246}
247
248
249function PostDebug(utils) {
250 for ( ; !IS_UNDEFINED(imports); imports = imports.next) {
251 imports(exports_container);
252 }
253
254 utils.CreateDoubleResultArray();
255 utils.CreateDoubleResultArray = UNDEFINED;
256
257 exports_container = UNDEFINED;
258
259 utils.Export = UNDEFINED;
260 utils.Import = UNDEFINED;
261 utils.ImportNow = UNDEFINED;
262 utils.PostDebug = UNDEFINED;
263 utils.PostExperimentals = UNDEFINED;
264 typed_array_setup = UNDEFINED;
265}
266
267
268function InitializeBuiltinTypedArrays(utils, rng_state, rempio2result) {
269 var setup_list = typed_array_setup;
270
271 for ( ; !IS_UNDEFINED(setup_list); setup_list = setup_list.next) {
272 setup_list(rng_state, rempio2result);
273 }
274}
275
276
277// -----------------------------------------------------------------------
278
279%OptimizeObjectForAddingMultipleProperties(utils, 14);
280
281utils.Import = Import;
282utils.ImportNow = ImportNow;
283utils.Export = Export;
284utils.ImportFromExperimental = ImportFromExperimental;
285utils.SetFunctionName = SetFunctionName;
286utils.InstallConstants = InstallConstants;
287utils.InstallFunctions = InstallFunctions;
288utils.InstallGetter = InstallGetter;
289utils.InstallGetterSetter = InstallGetterSetter;
290utils.SetUpLockedPrototype = SetUpLockedPrototype;
291utils.PostNatives = PostNatives;
292utils.PostExperimentals = PostExperimentals;
293utils.PostDebug = PostDebug;
294
295%ToFastProperties(utils);
296
297// -----------------------------------------------------------------------
298
299%OptimizeObjectForAddingMultipleProperties(extrasUtils, 5);
300
301extrasUtils.logStackTrace = function logStackTrace() {
302 %DebugTrace();
303};
304
305extrasUtils.log = function log() {
306 let message = '';
307 for (const arg of arguments) {
308 message += arg;
309 }
310
311 %GlobalPrint(message);
312};
313
314// Extras need the ability to store private state on their objects without
315// exposing it to the outside world.
316
317extrasUtils.createPrivateSymbol = function createPrivateSymbol(name) {
318 return %CreatePrivateSymbol(name);
319};
320
321// These functions are key for safe meta-programming:
322// http://wiki.ecmascript.org/doku.php?id=conventions:safe_meta_programming
323//
324// Technically they could all be derived from combinations of
325// Function.prototype.{bind,call,apply} but that introduces lots of layers of
326// indirection and slowness given how un-optimized bind is.
327
328extrasUtils.simpleBind = function simpleBind(func, thisArg) {
329 return function() {
330 return %Apply(func, thisArg, arguments, 0, arguments.length);
331 };
332};
333
334extrasUtils.uncurryThis = function uncurryThis(func) {
335 return function(thisArg) {
336 return %Apply(func, thisArg, arguments, 1, arguments.length - 1);
337 };
338};
339
340%ToFastProperties(extrasUtils);
341
342})