// Copyright 2015 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. (function(global, utils, extrasUtils) { "use strict"; %CheckIsBootstrapping(); // ----------------------------------------------------------------------- // Utils var imports = UNDEFINED; var exports_container = %ExportFromRuntime({}); // Export to other scripts. function Export(f) { f(exports_container); } // Import from other scripts. The actual importing happens in PostNatives so // that we can import from scripts executed later. However, that means that // the import is not available until the very end. If the import needs to be // available immediately, use ImportNow. function Import(f) { f.next = imports; imports = f; } // Import immediately from exports of previous scripts. We need this for // functions called during bootstrapping. Hooking up imports in PostNatives // would be too late. function ImportNow(name) { return exports_container[name]; } function InstallConstants(object, constants) { %CheckIsBootstrapping(); %OptimizeObjectForAddingMultipleProperties(object, constants.length >> 1); var attributes = DONT_ENUM | DONT_DELETE | READ_ONLY; for (var i = 0; i < constants.length; i += 2) { var name = constants[i]; var k = constants[i + 1]; %AddNamedProperty(object, name, k, attributes); } %ToFastProperties(object); } // Prevents changes to the prototype of a built-in function. // The "prototype" property of the function object is made non-configurable, // and the prototype object is made non-extensible. The latter prevents // changing the __proto__ property. function SetUpLockedPrototype( constructor, fields, methods) { %CheckIsBootstrapping(); var prototype = constructor.prototype; // Install functions first, because this function is used to initialize // PropertyDescriptor itself. var property_count = (methods.length >> 1) + (fields ? fields.length : 0); if (property_count >= 4) { %OptimizeObjectForAddingMultipleProperties(prototype, property_count); } if (fields) { for (var i = 0; i < fields.length; i++) { %AddNamedProperty(prototype, fields[i], UNDEFINED, DONT_ENUM | DONT_DELETE); } } for (var i = 0; i < methods.length; i += 2) { var key = methods[i]; var f = methods[i + 1]; %AddNamedProperty(prototype, key, f, DONT_ENUM | DONT_DELETE | READ_ONLY); %SetNativeFlag(f); } %InternalSetPrototype(prototype, null); %ToFastProperties(prototype); } // ----------------------------------------------------------------------- // To be called by bootstrapper function PostNatives(utils) { %CheckIsBootstrapping(); for ( ; !IS_UNDEFINED(imports); imports = imports.next) { imports(exports_container); } exports_container = UNDEFINED; utils.Export = UNDEFINED; utils.Import = UNDEFINED; utils.ImportNow = UNDEFINED; utils.PostNatives = UNDEFINED; } // ----------------------------------------------------------------------- %OptimizeObjectForAddingMultipleProperties(utils, 14); utils.Import = Import; utils.ImportNow = ImportNow; utils.Export = Export; utils.InstallConstants = InstallConstants; utils.SetUpLockedPrototype = SetUpLockedPrototype; utils.PostNatives = PostNatives; %ToFastProperties(utils); // ----------------------------------------------------------------------- %OptimizeObjectForAddingMultipleProperties(extrasUtils, 11); extrasUtils.logStackTrace = function logStackTrace() { %DebugTrace(); }; extrasUtils.log = function log() { let message = ''; for (const arg of arguments) { message += arg; } %GlobalPrint(message); }; // Extras need the ability to store private state on their objects without // exposing it to the outside world. extrasUtils.createPrivateSymbol = function createPrivateSymbol(name) { return %CreatePrivateSymbol(name); }; // These functions are key for safe meta-programming: // http://wiki.ecmascript.org/doku.php?id=conventions:safe_meta_programming // // Technically they could all be derived from combinations of // Function.prototype.{bind,call,apply} but that introduces lots of layers of // indirection. extrasUtils.uncurryThis = function uncurryThis(func) { return function(thisArg, ...args) { return %reflect_apply(func, thisArg, args); }; }; extrasUtils.markPromiseAsHandled = function markPromiseAsHandled(promise) { %PromiseMarkAsHandled(promise); }; extrasUtils.promiseState = function promiseState(promise) { return %PromiseStatus(promise); }; // [[PromiseState]] values (for extrasUtils.promiseState()) // These values should be kept in sync with PromiseStatus in globals.h extrasUtils.kPROMISE_PENDING = 0; extrasUtils.kPROMISE_FULFILLED = 1; extrasUtils.kPROMISE_REJECTED = 2; %ToFastProperties(extrasUtils); })