--- 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"),