From d9b3f4ab03e248072b42a0ae8deab3167774126e Mon Sep 17 00:00:00 2001 From: Brian Hackett Date: Wed, 16 Jan 2019 11:59:34 -1000 Subject: [PATCH] Bug 1447244 Part 3 - Track source ID in JSErrorReport and ErrorObject, r=jimb. --HG-- extra : rebase_source : 474f8ebd0c15a00a5358edb3b189570d1bb68a69 --- js/public/ErrorReport.h | 13 ++++++++++--- js/src/frontend/Parser.cpp | 4 ++-- js/src/frontend/TokenStream.cpp | 3 ++- js/src/jsapi.cpp | 16 ++++++++++++---- js/src/jsexn.cpp | 24 ++++++++++++++++++------ js/src/vm/ErrorObject-inl.h | 5 +++++ js/src/vm/ErrorObject.cpp | 10 +++++++--- js/src/vm/ErrorObject.h | 10 ++++++---- js/src/vm/JSContext.cpp | 3 +++ js/src/wasm/WasmJS.cpp | 4 ++-- 10 files changed, 67 insertions(+), 25 deletions(-) diff --git a/js/public/ErrorReport.h b/js/public/ErrorReport.h index 67f2104e8d96..e8a1a30a3ac3 100644 --- a/js/public/ErrorReport.h +++ b/js/public/ErrorReport.h @@ -93,6 +93,9 @@ class JSErrorBase { // Source file name, URL, etc., or null. const char* filename; + // Unique identifier for the script source. + unsigned sourceId; + // Source line number. unsigned lineno; @@ -108,6 +111,7 @@ class JSErrorBase { public: JSErrorBase() : filename(nullptr), + sourceId(0), lineno(0), column(0), errorNumber(0), @@ -149,13 +153,16 @@ class JSErrorNotes { ~JSErrorNotes(); // Add an note to the given position. - bool addNoteASCII(JSContext* cx, const char* filename, unsigned lineno, + bool addNoteASCII(JSContext* cx, const char* filename, + unsigned sourceId, unsigned lineno, unsigned column, JSErrorCallback errorCallback, void* userRef, const unsigned errorNumber, ...); - bool addNoteLatin1(JSContext* cx, const char* filename, unsigned lineno, + bool addNoteLatin1(JSContext* cx, const char* filename, + unsigned sourceId, unsigned lineno, unsigned column, JSErrorCallback errorCallback, void* userRef, const unsigned errorNumber, ...); - bool addNoteUTF8(JSContext* cx, const char* filename, unsigned lineno, + bool addNoteUTF8(JSContext* cx, const char* filename, + unsigned sourceId, unsigned lineno, unsigned column, JSErrorCallback errorCallback, void* userRef, const unsigned errorNumber, ...); diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index 0ba5874c3a8f..504e9d3bef0b 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -464,7 +464,7 @@ void GeneralParser::reportMissingClosing( char lineNumber[MaxWidth]; SprintfLiteral(lineNumber, "%" PRIu32, line); - if (!notes->addNoteASCII(pc_->sc()->cx_, getFilename(), line, column, + if (!notes->addNoteASCII(pc_->sc()->cx_, getFilename(), 0, line, column, GetErrorMessage, nullptr, noteNumber, lineNumber, columnNumber)) { return; @@ -503,7 +503,7 @@ void GeneralParser::reportRedeclaration( char lineNumber[MaxWidth]; SprintfLiteral(lineNumber, "%" PRIu32, line); - if (!notes->addNoteASCII(pc_->sc()->cx_, getFilename(), line, column, + if (!notes->addNoteASCII(pc_->sc()->cx_, getFilename(), 0, line, column, GetErrorMessage, nullptr, JSMSG_REDECLARED_PREV, lineNumber, columnNumber)) { return; diff --git a/js/src/frontend/TokenStream.cpp b/js/src/frontend/TokenStream.cpp index c0a57c1105ae..becdfe9f8873 100644 --- a/js/src/frontend/TokenStream.cpp +++ b/js/src/frontend/TokenStream.cpp @@ -759,7 +759,8 @@ MOZ_COLD void TokenStreamChars::internalEncodingError( uint32_t line, column; computeLineAndColumn(offset, &line, &column); - if (!notes->addNoteASCII(anyChars.cx, anyChars.getFilename(), line, column, + if (!notes->addNoteASCII(anyChars.cx, anyChars.getFilename(), + 0, line, column, GetErrorMessage, nullptr, JSMSG_BAD_CODE_UNITS, badUnitsStr)) { break; diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 3c7cbf1413d8..14675e7200a6 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -5300,7 +5300,8 @@ JSErrorNotes::JSErrorNotes() : notes_() {} JSErrorNotes::~JSErrorNotes() {} static UniquePtr CreateErrorNoteVA( - JSContext* cx, const char* filename, unsigned lineno, unsigned column, + JSContext* cx, const char* filename, unsigned sourceId, + unsigned lineno, unsigned column, JSErrorCallback errorCallback, void* userRef, const unsigned errorNumber, ErrorArgumentsType argumentsType, va_list ap) { auto note = MakeUnique(); @@ -5311,6 +5312,7 @@ static UniquePtr CreateErrorNoteVA( note->errorNumber = errorNumber; note->filename = filename; + note->sourceId = sourceId; note->lineno = lineno; note->column = column; @@ -5323,12 +5325,14 @@ static UniquePtr CreateErrorNoteVA( } bool JSErrorNotes::addNoteASCII(JSContext* cx, const char* filename, + unsigned sourceId, unsigned lineno, unsigned column, JSErrorCallback errorCallback, void* userRef, const unsigned errorNumber, ...) { va_list ap; va_start(ap, errorNumber); - auto note = CreateErrorNoteVA(cx, filename, lineno, column, errorCallback, + auto note = CreateErrorNoteVA(cx, filename, sourceId, lineno, column, + errorCallback, userRef, errorNumber, ArgumentsAreASCII, ap); va_end(ap); @@ -5343,12 +5347,14 @@ bool JSErrorNotes::addNoteASCII(JSContext* cx, const char* filename, } bool JSErrorNotes::addNoteLatin1(JSContext* cx, const char* filename, + unsigned sourceId, unsigned lineno, unsigned column, JSErrorCallback errorCallback, void* userRef, const unsigned errorNumber, ...) { va_list ap; va_start(ap, errorNumber); - auto note = CreateErrorNoteVA(cx, filename, lineno, column, errorCallback, + auto note = CreateErrorNoteVA(cx, filename, sourceId, lineno, column, + errorCallback, userRef, errorNumber, ArgumentsAreLatin1, ap); va_end(ap); @@ -5363,12 +5369,14 @@ bool JSErrorNotes::addNoteLatin1(JSContext* cx, const char* filename, } bool JSErrorNotes::addNoteUTF8(JSContext* cx, const char* filename, + unsigned sourceId, unsigned lineno, unsigned column, JSErrorCallback errorCallback, void* userRef, const unsigned errorNumber, ...) { va_list ap; va_start(ap, errorNumber); - auto note = CreateErrorNoteVA(cx, filename, lineno, column, errorCallback, + auto note = CreateErrorNoteVA(cx, filename, sourceId, lineno, column, + errorCallback, userRef, errorNumber, ArgumentsAreUTF8, ap); va_end(ap); diff --git a/js/src/jsexn.cpp b/js/src/jsexn.cpp index 89d96bb41a3e..167aac573823 100644 --- a/js/src/jsexn.cpp +++ b/js/src/jsexn.cpp @@ -280,6 +280,7 @@ static UniquePtr CopyErrorHelper(JSContext* cx, T* report) { MOZ_ASSERT(cursor == (uint8_t*)copy.get() + mallocSize); /* Copy non-pointer members. */ + copy->sourceId = report->sourceId; copy->lineno = report->lineno; copy->column = report->column; copy->errorNumber = report->errorNumber; @@ -417,6 +418,7 @@ bool Error(JSContext* cx, unsigned argc, Value* vp) { NonBuiltinFrameIter iter(cx, cx->realm()->principals()); RootedString fileName(cx); + uint32_t sourceId = 0; if (args.length() > 1) { fileName = ToString(cx, args[1]); } else { @@ -425,6 +427,9 @@ bool Error(JSContext* cx, unsigned argc, Value* vp) { if (const char* cfilename = iter.filename()) { fileName = JS_NewStringCopyZ(cx, cfilename); } + if (iter.hasScript()) { + sourceId = iter.script()->scriptSource()->id(); + } } } if (!fileName) { @@ -447,8 +452,9 @@ bool Error(JSContext* cx, unsigned argc, Value* vp) { } RootedObject obj(cx, - ErrorObject::create(cx, exnType, stack, fileName, lineNumber, - columnNumber, nullptr, message, proto)); + ErrorObject::create(cx, exnType, stack, fileName, sourceId, + lineNumber, columnNumber, nullptr, + message, proto)); if (!obj) { return false; } @@ -649,6 +655,7 @@ void js::ErrorToException(JSContext* cx, JSErrorReport* reportp, return; } + uint32_t sourceId = reportp->sourceId; uint32_t lineNumber = reportp->lineno; uint32_t columnNumber = reportp->column; @@ -663,7 +670,7 @@ void js::ErrorToException(JSContext* cx, JSErrorReport* reportp, } ErrorObject* errObject = - ErrorObject::create(cx, exnType, stack, fileName, lineNumber, + ErrorObject::create(cx, exnType, stack, fileName, sourceId, lineNumber, columnNumber, std::move(report), messageStr); if (!errObject) { return; @@ -879,6 +886,7 @@ bool ErrorReport::init(JSContext* cx, HandleValue exn, ownedReport.lineno = lineno; ownedReport.exnType = JSEXN_INTERNALERR; ownedReport.column = column; + if (str) { // Note that using |str| for |message_| here is kind of wrong, // because |str| is supposed to be of the format @@ -950,6 +958,8 @@ bool ErrorReport::populateUncaughtExceptionReportUTF8VA(JSContext* cx, if (!iter.done()) { ownedReport.filename = iter.filename(); uint32_t column; + ownedReport.sourceId = + iter.script() ? iter.script()->scriptSource()->id() : 0; ownedReport.lineno = iter.computeLine(&column); ownedReport.column = FixupColumnForDisplay(column); ownedReport.isMuted = iter.mutedErrors(); @@ -987,13 +997,15 @@ JSObject* js::CopyErrorObject(JSContext* cx, Handle err) { if (!cx->compartment()->wrap(cx, &stack)) { return nullptr; } + uint32_t sourceId = err->sourceId(); uint32_t lineNumber = err->lineNumber(); uint32_t columnNumber = err->columnNumber(); JSExnType errorType = err->type(); // Create the Error object. - return ErrorObject::create(cx, errorType, stack, fileName, lineNumber, - columnNumber, std::move(copyReport), message); + return ErrorObject::create(cx, errorType, stack, fileName, sourceId, + lineNumber, columnNumber, + std::move(copyReport), message); } JS_PUBLIC_API bool JS::CreateError(JSContext* cx, JSExnType type, @@ -1013,7 +1025,7 @@ JS_PUBLIC_API bool JS::CreateError(JSContext* cx, JSExnType type, } JSObject* obj = - js::ErrorObject::create(cx, type, stack, fileName, lineNumber, + js::ErrorObject::create(cx, type, stack, fileName, 0, lineNumber, columnNumber, std::move(rep), message); if (!obj) { return false; diff --git a/js/src/vm/ErrorObject-inl.h b/js/src/vm/ErrorObject-inl.h index 2939cca77abe..aa80e0a4223a 100644 --- a/js/src/vm/ErrorObject-inl.h +++ b/js/src/vm/ErrorObject-inl.h @@ -16,6 +16,11 @@ inline JSString* js::ErrorObject::fileName(JSContext* cx) const { return slot.isString() ? slot.toString() : cx->names().empty; } +inline uint32_t js::ErrorObject::sourceId() const { + const HeapSlot& slot = getReservedSlotRef(SOURCEID_SLOT); + return slot.isInt32() ? slot.toInt32() : 0; +} + inline uint32_t js::ErrorObject::lineNumber() const { const HeapSlot& slot = getReservedSlotRef(LINENUMBER_SLOT); return slot.isInt32() ? slot.toInt32() : 0; diff --git a/js/src/vm/ErrorObject.cpp b/js/src/vm/ErrorObject.cpp index 3f2c8eb8bfdb..f899d8f116cd 100644 --- a/js/src/vm/ErrorObject.cpp +++ b/js/src/vm/ErrorObject.cpp @@ -46,7 +46,8 @@ using namespace js; JSExnType type, UniquePtr errorReport, HandleString fileName, - HandleObject stack, uint32_t lineNumber, + HandleObject stack, uint32_t sourceId, + uint32_t lineNumber, uint32_t columnNumber, HandleString message) { AssertObjectIsSavedFrameOrWrapper(cx, stack); @@ -95,6 +96,7 @@ using namespace js; if (message) { obj->setSlotWithType(cx, messageShape, StringValue(message)); } + obj->initReservedSlot(SOURCEID_SLOT, Int32Value(sourceId)); // When recording/replaying and running on the main thread, get a counter // which the devtools can use to warp to this point in the future. @@ -114,7 +116,8 @@ using namespace js; /* static */ ErrorObject* js::ErrorObject::create( JSContext* cx, JSExnType errorType, HandleObject stack, - HandleString fileName, uint32_t lineNumber, uint32_t columnNumber, + HandleString fileName, uint32_t sourceId, + uint32_t lineNumber, uint32_t columnNumber, UniquePtr report, HandleString message, HandleObject protoArg /* = nullptr */) { AssertObjectIsSavedFrameOrWrapper(cx, stack); @@ -139,7 +142,7 @@ using namespace js; } if (!ErrorObject::init(cx, errObject, errorType, std::move(report), fileName, - stack, lineNumber, columnNumber, message)) { + stack, sourceId, lineNumber, columnNumber, message)) { return nullptr; } @@ -167,6 +170,7 @@ JSErrorReport* js::ErrorObject::getOrCreateErrorReport(JSContext* cx) { report.filename = filenameStr.get(); // Coordinates. + report.sourceId = sourceId(); report.lineno = lineNumber(); report.column = columnNumber(); diff --git a/js/src/vm/ErrorObject.h b/js/src/vm/ErrorObject.h index 5d8f4ade4f20..7e175f4be133 100644 --- a/js/src/vm/ErrorObject.h +++ b/js/src/vm/ErrorObject.h @@ -31,7 +31,7 @@ class ErrorObject : public NativeObject { static bool init(JSContext* cx, Handle obj, JSExnType type, UniquePtr errorReport, HandleString fileName, - HandleObject stack, uint32_t lineNumber, + HandleObject stack, uint32_t sourceId, uint32_t lineNumber, uint32_t columnNumber, HandleString message); static const ClassSpec classSpecs[JSEXN_ERROR_LIMIT]; @@ -45,7 +45,8 @@ class ErrorObject : public NativeObject { static const uint32_t LINENUMBER_SLOT = FILENAME_SLOT + 1; static const uint32_t COLUMNNUMBER_SLOT = LINENUMBER_SLOT + 1; static const uint32_t MESSAGE_SLOT = COLUMNNUMBER_SLOT + 1; - static const uint32_t TIME_WARP_SLOT = MESSAGE_SLOT + 1; + static const uint32_t SOURCEID_SLOT = MESSAGE_SLOT + 1; + static const uint32_t TIME_WARP_SLOT = SOURCEID_SLOT + 1; static const uint32_t RESERVED_SLOTS = TIME_WARP_SLOT + 1; @@ -67,8 +68,8 @@ class ErrorObject : public NativeObject { // property with that value; otherwise the error will have no .message // property. static ErrorObject* create(JSContext* cx, JSExnType type, HandleObject stack, - HandleString fileName, uint32_t lineNumber, - uint32_t columnNumber, + HandleString fileName, uint32_t sourceId, + uint32_t lineNumber, uint32_t columnNumber, UniquePtr report, HandleString message, HandleObject proto = nullptr); @@ -95,6 +96,7 @@ class ErrorObject : public NativeObject { JSErrorReport* getOrCreateErrorReport(JSContext* cx); inline JSString* fileName(JSContext* cx) const; + inline uint32_t sourceId() const; inline uint32_t lineNumber() const; inline uint32_t columnNumber() const; inline JSObject* stack() const; diff --git a/js/src/vm/JSContext.cpp b/js/src/vm/JSContext.cpp index e0a7f34d7a82..6c1e4e906764 100644 --- a/js/src/vm/JSContext.cpp +++ b/js/src/vm/JSContext.cpp @@ -258,6 +258,9 @@ static void PopulateReportBlame(JSContext* cx, JSErrorReport* report) { } report->filename = iter.filename(); + if (iter.hasScript()) { + report->sourceId = iter.script()->scriptSource()->id(); + } uint32_t column; report->lineno = iter.computeLine(&column); report->column = FixupColumnForDisplay(column); diff --git a/js/src/wasm/WasmJS.cpp b/js/src/wasm/WasmJS.cpp index b19f107f5f6e..cf5ada69802d 100644 --- a/js/src/wasm/WasmJS.cpp +++ b/js/src/wasm/WasmJS.cpp @@ -2832,8 +2832,8 @@ static bool Reject(JSContext* cx, const CompileArgs& args, } RootedObject errorObj( - cx, ErrorObject::create(cx, JSEXN_WASMCOMPILEERROR, stack, filename, line, - 0, nullptr, message)); + cx, ErrorObject::create(cx, JSEXN_WASMCOMPILEERROR, stack, filename, 0, + line, 0, nullptr, message)); if (!errorObj) { return false; }