blob: f9589a51c2fda9fe985a3953b889accbf117f4d8 [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
Ben Murdochda12d292016-06-02 14:46:10 +0100129function OverrideFunction(object, name, f, afterInitialBootstrap) {
130 %CheckIsBootstrapping();
131 %ObjectDefineProperty(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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000141// 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 "ArrayToString",
185 "ErrorToString",
186 "GetIterator",
187 "GetMethod",
188 "IsNaN",
189 "MakeError",
Ben Murdochda12d292016-06-02 14:46:10 +0100190 "MakeRangeError",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000191 "MakeTypeError",
192 "MapEntries",
193 "MapIterator",
194 "MapIteratorNext",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000195 "MaxSimple",
196 "MinSimple",
Ben Murdochda12d292016-06-02 14:46:10 +0100197 "NumberIsInteger",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000198 "ObjectDefineProperty",
199 "ObserveArrayMethods",
200 "ObserveObjectMethods",
201 "PromiseChain",
202 "PromiseDeferred",
203 "PromiseResolved",
Ben Murdochda12d292016-06-02 14:46:10 +0100204 "RegExpSubclassExecJS",
205 "RegExpSubclassMatch",
206 "RegExpSubclassReplace",
207 "RegExpSubclassSearch",
208 "RegExpSubclassSplit",
209 "RegExpSubclassTest",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000210 "SetIterator",
211 "SetIteratorNext",
212 "SetValues",
213 "SymbolToString",
214 "ToPositiveInteger",
215 // From runtime:
216 "is_concat_spreadable_symbol",
217 "iterator_symbol",
218 "promise_status_symbol",
219 "promise_value_symbol",
220 "object_freeze",
221 "object_is_frozen",
222 "object_is_sealed",
223 "reflect_apply",
224 "reflect_construct",
225 "regexp_flags_symbol",
226 "to_string_tag_symbol",
227 "object_to_string",
228 "species_symbol",
Ben Murdochda12d292016-06-02 14:46:10 +0100229 "match_symbol",
230 "replace_symbol",
231 "search_symbol",
232 "split_symbol",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000233 ];
234
235 var filtered_exports = {};
236 %OptimizeObjectForAddingMultipleProperties(
237 filtered_exports, expose_list.length);
238 for (var key of expose_list) {
239 filtered_exports[key] = exports_container[key];
240 }
241 %ToFastProperties(filtered_exports);
242 exports_container = filtered_exports;
243
244 utils.PostNatives = UNDEFINED;
245 utils.ImportFromExperimental = UNDEFINED;
246}
247
248
249function PostExperimentals(utils) {
250 %CheckIsBootstrapping();
251 %ExportExperimentalFromRuntime(exports_container);
252 for ( ; !IS_UNDEFINED(imports); imports = imports.next) {
253 imports(exports_container);
254 }
255 for ( ; !IS_UNDEFINED(imports_from_experimental);
256 imports_from_experimental = imports_from_experimental.next) {
257 imports_from_experimental(exports_container);
258 }
259
260 utils.CreateDoubleResultArray();
261 utils.CreateDoubleResultArray = UNDEFINED;
262
263 utils.Export = UNDEFINED;
264 utils.PostDebug = UNDEFINED;
265 utils.PostExperimentals = UNDEFINED;
266 typed_array_setup = UNDEFINED;
267}
268
269
270function PostDebug(utils) {
271 for ( ; !IS_UNDEFINED(imports); imports = imports.next) {
272 imports(exports_container);
273 }
274
275 utils.CreateDoubleResultArray();
276 utils.CreateDoubleResultArray = UNDEFINED;
277
278 exports_container = UNDEFINED;
279
280 utils.Export = UNDEFINED;
281 utils.Import = UNDEFINED;
282 utils.ImportNow = UNDEFINED;
283 utils.PostDebug = UNDEFINED;
284 utils.PostExperimentals = UNDEFINED;
285 typed_array_setup = UNDEFINED;
286}
287
288
289function InitializeBuiltinTypedArrays(utils, rng_state, rempio2result) {
290 var setup_list = typed_array_setup;
291
292 for ( ; !IS_UNDEFINED(setup_list); setup_list = setup_list.next) {
293 setup_list(rng_state, rempio2result);
294 }
295}
296
297
298// -----------------------------------------------------------------------
299
300%OptimizeObjectForAddingMultipleProperties(utils, 14);
301
302utils.Import = Import;
303utils.ImportNow = ImportNow;
304utils.Export = Export;
305utils.ImportFromExperimental = ImportFromExperimental;
306utils.SetFunctionName = SetFunctionName;
307utils.InstallConstants = InstallConstants;
308utils.InstallFunctions = InstallFunctions;
309utils.InstallGetter = InstallGetter;
310utils.InstallGetterSetter = InstallGetterSetter;
Ben Murdochda12d292016-06-02 14:46:10 +0100311utils.OverrideFunction = OverrideFunction;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000312utils.SetUpLockedPrototype = SetUpLockedPrototype;
313utils.PostNatives = PostNatives;
314utils.PostExperimentals = PostExperimentals;
315utils.PostDebug = PostDebug;
316
317%ToFastProperties(utils);
318
319// -----------------------------------------------------------------------
320
321%OptimizeObjectForAddingMultipleProperties(extrasUtils, 5);
322
323extrasUtils.logStackTrace = function logStackTrace() {
324 %DebugTrace();
325};
326
327extrasUtils.log = function log() {
328 let message = '';
329 for (const arg of arguments) {
330 message += arg;
331 }
332
333 %GlobalPrint(message);
334};
335
336// Extras need the ability to store private state on their objects without
337// exposing it to the outside world.
338
339extrasUtils.createPrivateSymbol = function createPrivateSymbol(name) {
340 return %CreatePrivateSymbol(name);
341};
342
343// These functions are key for safe meta-programming:
344// http://wiki.ecmascript.org/doku.php?id=conventions:safe_meta_programming
345//
346// Technically they could all be derived from combinations of
347// Function.prototype.{bind,call,apply} but that introduces lots of layers of
348// indirection and slowness given how un-optimized bind is.
349
350extrasUtils.simpleBind = function simpleBind(func, thisArg) {
Ben Murdochda12d292016-06-02 14:46:10 +0100351 return function(...args) {
352 return %reflect_apply(func, thisArg, args);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000353 };
354};
355
356extrasUtils.uncurryThis = function uncurryThis(func) {
Ben Murdochda12d292016-06-02 14:46:10 +0100357 return function(thisArg, ...args) {
358 return %reflect_apply(func, thisArg, args);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000359 };
360};
361
362%ToFastProperties(extrasUtils);
363
364})