Bug 1377007 - JS shell bindings for bindjs-ref;r?jorendorff,arai draft
authorDavid Teller <dteller@mozilla.com>
Tue, 05 Sep 2017 14:52:30 +0200
changeset 659085 8e28daca586244b02e2ddc8c95c0286e6fefaf40
parent 659084 6e39bf6d7d83a6f65a25532c7302c7b0cb3412b4
child 729874 1f4414d661cfef0065b706bc3cbc72d6a9e7260f
push id78004
push userdteller@mozilla.com
push dateTue, 05 Sep 2017 13:32:18 +0000
reviewersjorendorff, arai
bugs1377007
milestone57.0a1
Bug 1377007 - JS shell bindings for bindjs-ref;r?jorendorff,arai MozReview-Commit-ID: LlOmuIm2FRN
js/src/frontend/FoldConstants.cpp
js/src/jsapi.h
js/src/shell/js.cpp
--- a/js/src/frontend/FoldConstants.cpp
+++ b/js/src/frontend/FoldConstants.cpp
@@ -1924,15 +1924,18 @@ template<typename CharT>
 bool
 frontend::FoldConstants(JSContext* cx, ParseNode** pnp, Parser<FullParseHandler, CharT>* parser)
 {
     // Don't constant-fold inside "use asm" code, as this could create a parse
     // tree that doesn't type-check as asm.js.
     if (parser->pc->useAsmOrInsideUseAsm())
         return true;
 
+    if (!parser->options().foldConstants)
+        return true;
+
     AutoTraceLog traceLog(TraceLoggerForCurrentThread(cx), TraceLogger_BytecodeFoldConstants);
     return Fold(cx, pnp, *parser, false);
 }
 
 template bool
 frontend::FoldConstants(JSContext* cx, ParseNode** pnp,
                         Parser<FullParseHandler, char16_t>* parser);
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -4097,17 +4097,18 @@ class JS_FRIEND_API(ReadOnlyCompileOptio
 
   protected:
     ReadOnlyCompileOptions()
       : TransitiveCompileOptions(),
         lineno(1),
         column(0),
         scriptSourceOffset(0),
         isRunOnce(false),
-        noScriptRval(false)
+        noScriptRval(false),
+        foldConstants(true)
     { }
 
     // Set all POD options (those not requiring reference counts, copies,
     // rooting, or other hand-holding) to their values in |rhs|.
     void copyPODOptions(const ReadOnlyCompileOptions& rhs);
 
   public:
     // Read-only accessors for non-POD options. The proper way to set these
@@ -4134,16 +4135,19 @@ class JS_FRIEND_API(ReadOnlyCompileOptio
     // starting and ending offsets within the full text. This
     // scriptSourceOffset field lets the frontend convert between these
     // offsets and offsets within the substring presented for compilation.
     unsigned scriptSourceOffset;
     // isRunOnce only applies to non-function scripts.
     bool isRunOnce;
     bool noScriptRval;
 
+    // If `true`, proceed to fold constants.
+    bool foldConstants;
+
   private:
     void operator=(const ReadOnlyCompileOptions&) = delete;
 };
 
 /**
  * Compilation options, with dynamic lifetime. An instance of this type
  * makes a copy of / holds / roots all dynamically allocated resources
  * (principals; elements; strings) that it refers to. Its destructor frees
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -59,16 +59,17 @@
 #ifdef XP_WIN
 # include "jswin.h"
 #endif
 #include "jswrapper.h"
 #include "shellmoduleloader.out.h"
 
 #include "builtin/ModuleObject.h"
 #include "builtin/TestingFunctions.h"
+#include "frontend/BinSource.h"
 #include "frontend/Parser.h"
 #include "gc/GCInternals.h"
 #include "jit/arm/Simulator-arm.h"
 #include "jit/InlinableNatives.h"
 #include "jit/Ion.h"
 #include "jit/JitcodeMap.h"
 #include "jit/OptimizationTracking.h"
 #include "js/Debug.h"
@@ -4260,16 +4261,80 @@ GetModuleLoadPath(JSContext* cx, unsigne
         args.rval().setString(str);
     } else {
         args.rval().setNull();
     }
     return true;
 }
 
 static bool
+BinParse(JSContext* cx, unsigned argc, Value* vp)
+{
+    using namespace js::frontend;
+
+    CallArgs args = CallArgsFromVp(argc, vp);
+
+    if (args.length() < 1) {
+        JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_MORE_ARGS_NEEDED,
+                                  "parse", "0", "s");
+        return false;
+    }
+    if (!args[0].isObject()) {
+        const char* typeName = InformalValueTypeName(args[0]);
+        JS_ReportErrorASCII(cx, "expected object (typed array) to parse, got %s", typeName);
+        return false;
+    }
+
+    RootedObject obj(cx, &args[0].toObject());
+    if (!JS_IsTypedArrayObject(obj)) {
+        const char* typeName = InformalValueTypeName(args[0]);
+        JS_ReportErrorASCII(cx, "expected typed array to parse, got %s", typeName);
+        return false;
+    }
+
+    uint32_t buf_length = 0;
+    bool buf_isSharedMemory = false;
+    uint8_t* buf_data = nullptr;
+    GetArrayBufferViewLengthAndData(obj, &buf_length, &buf_isSharedMemory, &buf_data);
+    MOZ_ASSERT(buf_data);
+
+    CompileOptions options(cx);
+    options.setIntroductionType("js shell bin parse")
+           .setFileAndLine("<ArrayBuffer>", 1);
+
+    UsedNameTracker usedNames(cx);
+    if (!usedNames.init()) {
+        return false;
+    }
+
+    BinASTParser reader(cx, cx->tempLifoAlloc(), usedNames, options);
+    char* start = reinterpret_cast<char*>(buf_data);
+    char* end   = start + buf_length;
+
+    fprintf(stderr, "DEBUG: Parse starts\n");
+    Maybe<BinASTParser::UniqueNode> parsed = reader.parse(start, end);
+    if (!parsed) {
+        fprintf(stderr, "DEBUG: Parse failed\n");
+        MOZ_CRASH();
+        return false;
+    }
+    fprintf(stderr, "DEBUG: Parse succeeded\n");
+
+#ifdef DEBUG
+    fprintf(stderr, "<DUMP BEGINS>\n");
+    DumpParseTree(parsed->get());
+    fputc('\n', stderr);
+    fprintf(stderr, "<DUMP ENDS>\n");
+#endif
+
+    args.rval().setUndefined();
+    return true;
+}
+
+static bool
 Parse(JSContext* cx, unsigned argc, Value* vp)
 {
     using namespace js::frontend;
 
     CallArgs args = CallArgsFromVp(argc, vp);
 
     if (args.length() < 1) {
         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_MORE_ARGS_NEEDED,
@@ -4291,31 +4356,34 @@ Parse(JSContext* cx, unsigned argc, Valu
         return false;
 
     size_t length = scriptContents->length();
     const char16_t* chars = stableChars.twoByteRange().begin().get();
 
     CompileOptions options(cx);
     options.setIntroductionType("js shell parse")
            .setFileAndLine("<string>", 1);
+    options.foldConstants = false;
     UsedNameTracker usedNames(cx);
     if (!usedNames.init())
         return false;
     Parser<FullParseHandler, char16_t> parser(cx, cx->tempLifoAlloc(), options, chars, length,
-                                              /* foldConstants = */ true, usedNames, nullptr,
+                                              /* foldConstants = */ false, usedNames, nullptr,
                                               nullptr);
     if (!parser.checkOptions())
         return false;
 
-    ParseNode* pn = parser.parse();
+    ParseNode* pn = parser.parse(); // FIXME: Never deallocated?
     if (!pn)
         return false;
 #ifdef DEBUG
+    fprintf(stderr, "<DUMP BEGINS>\n");
     DumpParseTree(pn);
     fputc('\n', stderr);
+    fprintf(stderr, "<DUMP ENDS>\n");
 #endif
     args.rval().setUndefined();
     return true;
 }
 
 static bool
 SyntaxParse(JSContext* cx, unsigned argc, Value* vp)
 {
@@ -6414,16 +6482,20 @@ static const JSFunctionSpecWithHelp shel
 "  This hook is used to look up a previously loaded module object.  It should\n"
 "  be implemented by the module loader."),
 
     JS_FN_HELP("getModuleLoadPath", GetModuleLoadPath, 0, 0,
 "getModuleLoadPath()",
 "  Return any --module-load-path argument passed to the shell.  Used by the\n"
 "  module loader.\n"),
 
+JS_FN_HELP("parseBin", BinParse, 1, 0,
+"parseBin(arraybuffer)",
+"  Parses a Binary AST, potentially throwing."),
+
     JS_FN_HELP("parse", Parse, 1, 0,
 "parse(code)",
 "  Parses a string, potentially throwing."),
 
     JS_FN_HELP("syntaxParse", SyntaxParse, 1, 0,
 "syntaxParse(code)",
 "  Check the syntax of a string, returning success value"),