Source code

Revision control

Copy as Markdown

Other Tools

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "SelfHostingDefines.h"
// Assertions and debug printing, defined here instead of in the header above
// to make `assert` invisible to C++.
#ifdef DEBUG
#define assert(b, info) \
do { \
if (!(b)) { \
AssertionFailed(__FILE__ + ":" + __LINE__ + ": " + info) \
} \
} while (false)
#define dbg(msg) \
do { \
DumpMessage(callFunction(std_Array_pop, \
StringSplitString(__FILE__, '/')) + \
'#' + __LINE__ + ': ' + msg) \
} while (false)
#else
#define assert(b, info) ; // Elided assertion.
#define dbg(msg) ; // Elided debugging output.
#endif
// All C++-implemented standard builtins library functions used in self-hosted
// code are installed via the std_functions JSFunctionSpec[] in
// SelfHosting.cpp.
/********** Specification types **********/
// A "Record" is an internal type used in the ECMAScript spec to define a struct
// made up of key / values. It is never exposed to user script, but we use a
// simple Object (with null prototype) as a convenient implementation.
function new_Record() {
return std_Object_create(null);
}
/********** Abstract operations defined in ECMAScript Language Specification **********/
/* Spec: ECMAScript Language Specification, 5.1 edition, 9.2 and 11.4.9 */
function ToBoolean(v) {
return !!v;
}
/* Spec: ECMAScript Language Specification, 5.1 edition, 9.3 and 11.4.6 */
function ToNumber(v) {
return +v;
}
// ES2017 draft rev aebf014403a3e641fb1622aec47c40f051943527
// 7.2.10 SameValueZero ( x, y )
function SameValueZero(x, y) {
return x === y || (x !== x && y !== y);
}
// ES 2017 draft (April 6, 2016) 7.3.9
function GetMethod(V, P) {
// Step 1.
assert(IsPropertyKey(P), "Invalid property key");
// Step 2.
var func = V[P];
// Step 3.
if (IsNullOrUndefined(func)) {
return undefined;
}
// Step 4.
if (!IsCallable(func)) {
ThrowTypeError(JSMSG_NOT_FUNCTION, typeof func);
}
// Step 5.
return func;
}
/* Spec: ECMAScript Draft, 6th edition Dec 24, 2014, 7.2.7 */
function IsPropertyKey(argument) {
var type = typeof argument;
return type === "string" || type === "symbol";
}
#define TO_PROPERTY_KEY(name) \
(typeof name !== "string" && typeof name !== "number" && typeof name !== "symbol" ? ToPropertyKey(name) : name)
// ES 2016 draft Mar 25, 2016 7.3.20.
function SpeciesConstructor(obj, defaultConstructor) {
// Step 1.
assert(IsObject(obj), "not passed an object");
// Step 2.
var ctor = obj.constructor;
// Step 3.
if (ctor === undefined) {
return defaultConstructor;
}
// Step 4.
if (!IsObject(ctor)) {
ThrowTypeError(JSMSG_OBJECT_REQUIRED, "object's 'constructor' property");
}
// Steps 5.
var s = ctor[GetBuiltinSymbol("species")];
// Step 6.
if (IsNullOrUndefined(s)) {
return defaultConstructor;
}
// Step 7.
if (IsConstructor(s)) {
return s;
}
// Step 8.
ThrowTypeError(
JSMSG_NOT_CONSTRUCTOR,
"@@species property of object's constructor"
);
}
function GetTypeError(...args) {
try {
FUN_APPLY(ThrowTypeError, undefined, args);
} catch (e) {
return e;
}
assert(false, "the catch block should've returned from this function.");
}
function GetAggregateError(...args) {
try {
FUN_APPLY(ThrowAggregateError, undefined, args);
} catch (e) {
return e;
}
assert(false, "the catch block should've returned from this function.");
}
function GetInternalError(...args) {
try {
FUN_APPLY(ThrowInternalError, undefined, args);
} catch (e) {
return e;
}
assert(false, "the catch block should've returned from this function.");
}
// To be used when a function is required but calling it shouldn't do anything.
function NullFunction() {}
// ES2019 draft rev 4c2df13f4194057f09b920ee88712e5a70b1a556
// 7.3.23 CopyDataProperties (target, source, excludedItems)
function CopyDataProperties(target, source, excludedItems) {
// Step 1.
assert(IsObject(target), "target is an object");
// Step 2.
assert(IsObject(excludedItems), "excludedItems is an object");
// Steps 3 and 7.
if (IsNullOrUndefined(source)) {
return;
}
// Step 4.
var from = ToObject(source);
// Step 5.
var keys = CopyDataPropertiesOrGetOwnKeys(target, from, excludedItems);
// Return if we copied all properties in native code.
if (keys === null) {
return;
}
// Step 6.
for (var index = 0; index < keys.length; index++) {
var key = keys[index];
// We abbreviate this by calling propertyIsEnumerable which is faster
// and returns false for not defined properties.
if (
!hasOwn(key, excludedItems) &&
callFunction(std_Object_propertyIsEnumerable, from, key)
) {
DefineDataProperty(target, key, from[key]);
}
}
// Step 7 (Return).
}
// ES2019 draft rev 4c2df13f4194057f09b920ee88712e5a70b1a556
// 7.3.23 CopyDataProperties (target, source, excludedItems)
function CopyDataPropertiesUnfiltered(target, source) {
// Step 1.
assert(IsObject(target), "target is an object");
// Step 2 (Not applicable).
// Steps 3 and 7.
if (IsNullOrUndefined(source)) {
return;
}
// Step 4.
var from = ToObject(source);
// Step 5.
var keys = CopyDataPropertiesOrGetOwnKeys(target, from, null);
// Return if we copied all properties in native code.
if (keys === null) {
return;
}
// Step 6.
for (var index = 0; index < keys.length; index++) {
var key = keys[index];
// We abbreviate this by calling propertyIsEnumerable which is faster
// and returns false for not defined properties.
if (callFunction(std_Object_propertyIsEnumerable, from, key)) {
DefineDataProperty(target, key, from[key]);
}
}
// Step 7 (Return).
}
/*************************************** Testing functions ***************************************/
function outer() {
return function inner() {
return "foo";
};
}