• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
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})
343