summaryrefslogtreecommitdiffstats
path: root/js/src/builtin/Utilities.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/builtin/Utilities.js')
-rw-r--r--js/src/builtin/Utilities.js242
1 files changed, 242 insertions, 0 deletions
diff --git a/js/src/builtin/Utilities.js b/js/src/builtin/Utilities.js
new file mode 100644
index 0000000000..dad4e26bb9
--- /dev/null
+++ b/js/src/builtin/Utilities.js
@@ -0,0 +1,242 @@
+/* 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";
+ };
+}