blob: 79fe9b7726ed29e4cf6012b3d3ee2a57996bd0b6 [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();
Ben Murdochc5610432016-08-08 18:44:38 +0100131 %object_define_property(object, name, { value: f,
132 writeable: true,
133 configurable: true,
134 enumerable: false });
Ben Murdochda12d292016-06-02 14:46:10 +0100135 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 = [
Ben Murdochc5610432016-08-08 18:44:38 +0100184 "AddBoundMethod",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000185 "ArrayToString",
Ben Murdochc5610432016-08-08 18:44:38 +0100186 "AsyncFunctionNext",
187 "AsyncFunctionThrow",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000188 "ErrorToString",
189 "GetIterator",
190 "GetMethod",
Ben Murdochc5610432016-08-08 18:44:38 +0100191 "IntlParseDate",
192 "IntlParseNumber",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000193 "IsNaN",
194 "MakeError",
Ben Murdochda12d292016-06-02 14:46:10 +0100195 "MakeRangeError",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000196 "MakeTypeError",
197 "MapEntries",
198 "MapIterator",
199 "MapIteratorNext",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000200 "MaxSimple",
201 "MinSimple",
Ben Murdochda12d292016-06-02 14:46:10 +0100202 "NumberIsInteger",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000203 "PromiseChain",
Ben Murdochc5610432016-08-08 18:44:38 +0100204 "PromiseDefer",
205 "PromiseAccept",
206 "PromiseCreateRejected",
207 "PromiseCreateResolved",
208 "PromiseThen",
Ben Murdochda12d292016-06-02 14:46:10 +0100209 "RegExpSubclassExecJS",
210 "RegExpSubclassMatch",
211 "RegExpSubclassReplace",
212 "RegExpSubclassSearch",
213 "RegExpSubclassSplit",
214 "RegExpSubclassTest",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000215 "SetIterator",
216 "SetIteratorNext",
217 "SetValues",
218 "SymbolToString",
Ben Murdochc5610432016-08-08 18:44:38 +0100219 "ToLocaleLowerCaseI18N",
220 "ToLocaleUpperCaseI18N",
221 "ToLowerCaseI18N",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000222 "ToPositiveInteger",
Ben Murdochc5610432016-08-08 18:44:38 +0100223 "ToUpperCaseI18N",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000224 // From runtime:
225 "is_concat_spreadable_symbol",
226 "iterator_symbol",
Ben Murdochc5610432016-08-08 18:44:38 +0100227 "promise_result_symbol",
228 "promise_state_symbol",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000229 "object_freeze",
230 "object_is_frozen",
231 "object_is_sealed",
232 "reflect_apply",
233 "reflect_construct",
234 "regexp_flags_symbol",
235 "to_string_tag_symbol",
236 "object_to_string",
237 "species_symbol",
Ben Murdochda12d292016-06-02 14:46:10 +0100238 "match_symbol",
239 "replace_symbol",
240 "search_symbol",
241 "split_symbol",
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000242 ];
243
244 var filtered_exports = {};
245 %OptimizeObjectForAddingMultipleProperties(
246 filtered_exports, expose_list.length);
247 for (var key of expose_list) {
248 filtered_exports[key] = exports_container[key];
249 }
250 %ToFastProperties(filtered_exports);
251 exports_container = filtered_exports;
252
253 utils.PostNatives = UNDEFINED;
254 utils.ImportFromExperimental = UNDEFINED;
255}
256
257
258function PostExperimentals(utils) {
259 %CheckIsBootstrapping();
260 %ExportExperimentalFromRuntime(exports_container);
261 for ( ; !IS_UNDEFINED(imports); imports = imports.next) {
262 imports(exports_container);
263 }
264 for ( ; !IS_UNDEFINED(imports_from_experimental);
265 imports_from_experimental = imports_from_experimental.next) {
266 imports_from_experimental(exports_container);
267 }
268
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000269 utils.Export = UNDEFINED;
270 utils.PostDebug = UNDEFINED;
271 utils.PostExperimentals = UNDEFINED;
272 typed_array_setup = UNDEFINED;
273}
274
275
276function PostDebug(utils) {
277 for ( ; !IS_UNDEFINED(imports); imports = imports.next) {
278 imports(exports_container);
279 }
280
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000281 exports_container = UNDEFINED;
282
283 utils.Export = UNDEFINED;
284 utils.Import = UNDEFINED;
285 utils.ImportNow = UNDEFINED;
286 utils.PostDebug = UNDEFINED;
287 utils.PostExperimentals = UNDEFINED;
288 typed_array_setup = UNDEFINED;
289}
290
291
292function InitializeBuiltinTypedArrays(utils, rng_state, rempio2result) {
293 var setup_list = typed_array_setup;
294
295 for ( ; !IS_UNDEFINED(setup_list); setup_list = setup_list.next) {
296 setup_list(rng_state, rempio2result);
297 }
298}
299
300
301// -----------------------------------------------------------------------
302
303%OptimizeObjectForAddingMultipleProperties(utils, 14);
304
305utils.Import = Import;
306utils.ImportNow = ImportNow;
307utils.Export = Export;
308utils.ImportFromExperimental = ImportFromExperimental;
309utils.SetFunctionName = SetFunctionName;
310utils.InstallConstants = InstallConstants;
311utils.InstallFunctions = InstallFunctions;
312utils.InstallGetter = InstallGetter;
313utils.InstallGetterSetter = InstallGetterSetter;
Ben Murdochda12d292016-06-02 14:46:10 +0100314utils.OverrideFunction = OverrideFunction;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000315utils.SetUpLockedPrototype = SetUpLockedPrototype;
316utils.PostNatives = PostNatives;
317utils.PostExperimentals = PostExperimentals;
318utils.PostDebug = PostDebug;
319
320%ToFastProperties(utils);
321
322// -----------------------------------------------------------------------
323
324%OptimizeObjectForAddingMultipleProperties(extrasUtils, 5);
325
326extrasUtils.logStackTrace = function logStackTrace() {
327 %DebugTrace();
328};
329
330extrasUtils.log = function log() {
331 let message = '';
332 for (const arg of arguments) {
333 message += arg;
334 }
335
336 %GlobalPrint(message);
337};
338
339// Extras need the ability to store private state on their objects without
340// exposing it to the outside world.
341
342extrasUtils.createPrivateSymbol = function createPrivateSymbol(name) {
343 return %CreatePrivateSymbol(name);
344};
345
346// These functions are key for safe meta-programming:
347// http://wiki.ecmascript.org/doku.php?id=conventions:safe_meta_programming
348//
349// Technically they could all be derived from combinations of
350// Function.prototype.{bind,call,apply} but that introduces lots of layers of
351// indirection and slowness given how un-optimized bind is.
352
353extrasUtils.simpleBind = function simpleBind(func, thisArg) {
Ben Murdochda12d292016-06-02 14:46:10 +0100354 return function(...args) {
355 return %reflect_apply(func, thisArg, args);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000356 };
357};
358
359extrasUtils.uncurryThis = function uncurryThis(func) {
Ben Murdochda12d292016-06-02 14:46:10 +0100360 return function(thisArg, ...args) {
361 return %reflect_apply(func, thisArg, args);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000362 };
363};
364
365%ToFastProperties(extrasUtils);
366
367})