Bug 769872 - Add utilities for self-hosted JavaScript code. r=till
authorNorbert Lindenberg <mozilladev@lindenbergsoftware.com>
Tue, 18 Dec 2012 18:44:43 -0500
changeset 125567 256ff2b72064
parent 125566 e88bfc91fb9a
child 125568 3c01cb463c00
push id2151
push userlsblakk@mozilla.com
push dateTue, 19 Feb 2013 18:06:57 +0000
treeherdermozilla-beta@4952e88741ec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstill
bugs769872
milestone20.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 769872 - Add utilities for self-hosted JavaScript code. r=till
js/src/Makefile.in
js/src/builtin/Array.js
js/src/builtin/Utilities.js
js/src/builtin/array.js
js/src/vm/SelfHosting.cpp
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -899,17 +899,18 @@ ifdef HAVE_LINUX_PERF_EVENT_H
 pm_linux.$(OBJ_SUFFIX): CXXFLAGS += $(LINUX_HEADERS_INCLUDES)
 endif
 
 # Prepare self-hosted JS code for embedding
 export:: selfhosting
 selfhosting:: selfhosted.out.h
 
 selfhosting_srcs := \
-  $(srcdir)/builtin/array.js \
+  $(srcdir)/builtin/Utilities.js \
+  $(srcdir)/builtin/Array.js \
   $(NULL)
 
 selfhosted_out_h_deps := \
   $(selfhosting_srcs) \
   $(srcdir)/js.msg \
   $(srcdir)/builtin/macros.py \
   $(srcdir)/builtin/js2c.py \
   $(srcdir)/builtin/embedjs.py
rename from js/src/builtin/array.js
rename to js/src/builtin/Array.js
new file mode 100644
--- /dev/null
+++ b/js/src/builtin/Utilities.js
@@ -0,0 +1,93 @@
+/* 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/. */
+
+/*jshint bitwise: true, camelcase: false, curly: false, eqeqeq: true, forin: true,
+         immed: true, indent: 4, latedef: false, newcap: false, noarg: true,
+         noempty: true, nonew: true, plusplus: false, quotmark: false, regexp: true,
+         undef: true, unused: false, strict: false, trailing: true,
+*/
+
+/*global ToObject: false, ToInteger: false, IsCallable: false, ThrowError: false,
+         AssertionFailed: false, MakeConstructible: false, DecompileArg: false,
+         callFunction: false,
+         IS_UNDEFINED: false, TO_UINT32: false,
+         JSMSG_NOT_FUNCTION: false, JSMSG_MISSING_FUN_ARG: false,
+         JSMSG_EMPTY_ARRAY_REDUCE: false,
+*/
+
+
+/* cache built-in functions before applications can change them */
+var std_ArrayIndexOf = ArrayIndexOf;
+var std_ArrayJoin = Array.prototype.join;
+var std_ArrayPush = Array.prototype.push;
+var std_ArraySlice = Array.prototype.slice;
+var std_ArraySort = Array.prototype.sort;
+var std_ObjectCreate = Object.create;
+var std_String = String;
+
+
+/********** List specification type **********/
+
+
+/* Spec: ECMAScript Language Specification, 5.1 edition, 8.8 */
+function List() {
+    if (IS_UNDEFINED(List.prototype)) {
+        var proto = std_ObjectCreate(null);
+        proto.indexOf = std_ArrayIndexOf;
+        proto.join = std_ArrayJoin;
+        proto.push = std_ArrayPush;
+        proto.slice = std_ArraySlice;
+        proto.sort = std_ArraySort;
+        List.prototype = proto;
+    }
+}
+MakeConstructible(List);
+
+
+/********** Record specification type **********/
+
+
+/* Spec: ECMAScript Internationalization API Specification, draft, 5 */
+function Record() {
+    return std_ObjectCreate(null);
+}
+MakeConstructible(Record);
+
+
+/********** Abstract operations defined in ECMAScript Language Specification **********/
+
+
+/* Spec: ECMAScript Language Specification, 5.1 edition, 8.12.6 and 11.8.7 */
+function HasProperty(o, p) {
+    return p in o;
+}
+
+
+/* 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;
+}
+
+
+/* Spec: ECMAScript Language Specification, 5.1 edition, 9.8 and 15.2.1.1 */
+function ToString(v) {
+    assert(arguments.length > 0, "__toString");
+    return std_String(v);
+}
+
+
+/********** Assertions **********/
+
+
+function assert(b, info) {
+    if (!b)
+        AssertionFailed(info);
+}
+
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -98,16 +98,42 @@ intrinsic_ThrowError(JSContext *cx, unsi
 
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, errorNumber,
                          errorArgs[0], errorArgs[1], errorArgs[2]);
     for (unsigned i = 0; i < 3; i++)
         js_free(errorArgs[i]);
     return false;
 }
 
+/**
+ * Handles an assertion failure in self-hosted code just like an assertion
+ * failure in C++ code. Information about the failure can be provided in args[0].
+ */
+static JSBool
+intrinsic_AssertionFailed(JSContext *cx, unsigned argc, Value *vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+#ifdef DEBUG
+    if (argc > 0) {
+        // try to dump the informative string
+        JSString *str = ToString(cx, args[0]);
+        if (str) {
+            const jschar *chars = str->getChars(cx);
+            if (chars) {
+                fprintf(stderr, "Self-hosted JavaScript assertion info: ");
+                JSString::dumpChars(chars, str->length());
+                fputc('\n', stderr);
+            }
+        }
+    }
+#endif
+    JS_ASSERT(false);
+    return false;
+}
+
 /*
  * Used to decompile values in the nearest non-builtin stack frame, falling
  * back to decompiling in the current frame. Helpful for printing higher-order
  * function arguments.
  *
  * The user must supply the argument number of the value in question; it
  * _cannot_ be automatically determined.
  */
@@ -139,20 +165,22 @@ intrinsic_MakeConstructible(JSContext *c
     return true;
 }
 
 JSFunctionSpec intrinsic_functions[] = {
     JS_FN("ToObject",           intrinsic_ToObject,             1,0),
     JS_FN("ToInteger",          intrinsic_ToInteger,            1,0),
     JS_FN("IsCallable",         intrinsic_IsCallable,           1,0),
     JS_FN("ThrowError",         intrinsic_ThrowError,           4,0),
+    JS_FN("AssertionFailed",    intrinsic_AssertionFailed,      1,0),
     JS_FN("MakeConstructible",  intrinsic_MakeConstructible,    1,0),
     JS_FN("DecompileArg",       intrinsic_DecompileArg,         2,0),
     JS_FS_END
 };
+
 bool
 JSRuntime::initSelfHosting(JSContext *cx)
 {
     JS_ASSERT(!selfHostingGlobal_);
     RootedObject savedGlobal(cx, JS_GetGlobalObject(cx));
     if (!(selfHostingGlobal_ = JS_NewGlobalObject(cx, &self_hosting_global_class, NULL)))
         return false;
     JS_SetGlobalObject(cx, selfHostingGlobal_);