summaryrefslogtreecommitdiffstats
path: root/js/src/jsexn.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jsexn.cpp')
-rw-r--r--js/src/jsexn.cpp114
1 files changed, 85 insertions, 29 deletions
diff --git a/js/src/jsexn.cpp b/js/src/jsexn.cpp
index 102e6fb34..b07d118b9 100644
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -201,28 +201,77 @@ ErrorObject::classes[JSEXN_ERROR_LIMIT] = {
IMPLEMENT_ERROR_CLASS(RuntimeError)
};
-JSErrorReport*
-js::CopyErrorReport(JSContext* cx, JSErrorReport* report)
+size_t
+ExtraMallocSize(JSErrorReport* report)
+{
+ if (report->linebuf())
+ return (report->linebufLength() + 1) * sizeof(char16_t);
+
+ return 0;
+}
+
+size_t
+ExtraMallocSize(JSErrorNotes::Note* note)
+{
+ return 0;
+}
+
+bool
+CopyExtraData(JSContext* cx, uint8_t** cursor, JSErrorReport* copy, JSErrorReport* report)
+{
+ if (report->linebuf()) {
+ size_t linebufSize = (report->linebufLength() + 1) * sizeof(char16_t);
+ const char16_t* linebufCopy = (const char16_t*)(*cursor);
+ js_memcpy(*cursor, report->linebuf(), linebufSize);
+ *cursor += linebufSize;
+ copy->initBorrowedLinebuf(linebufCopy, report->linebufLength(), report->tokenOffset());
+ }
+
+ /* Copy non-pointer members. */
+ copy->isMuted = report->isMuted;
+ copy->exnType = report->exnType;
+
+ /* Note that this is before it gets flagged with JSREPORT_EXCEPTION */
+ copy->flags = report->flags;
+
+ /* Deep copy notes. */
+ if (report->notes) {
+ auto copiedNotes = report->notes->copy(cx);
+ if (!copiedNotes)
+ return false;
+ copy->notes = Move(copiedNotes);
+ } else {
+ copy->notes.reset(nullptr);
+ }
+
+ return true;
+}
+
+bool
+CopyExtraData(JSContext* cx, uint8_t** cursor, JSErrorNotes::Note* copy, JSErrorNotes::Note* report)
+{
+ return true;
+}
+
+template <typename T>
+static T*
+CopyErrorHelper(JSContext* cx, T* report)
{
/*
- * We use a single malloc block to make a deep copy of JSErrorReport with
+ * We use a single malloc block to make a deep copy of JSErrorReport or
+ * JSErrorNotes::Note, except JSErrorNotes linked from JSErrorReport with
* the following layout:
- * JSErrorReport
+ * JSErrorReport or JSErrorNotes::Note
* char array with characters for message_
- * char16_t array with characters for linebuf
* char array with characters for filename
+ * char16_t array with characters for linebuf (only for JSErrorReport)
* Such layout together with the properties enforced by the following
* asserts does not need any extra alignment padding.
*/
- JS_STATIC_ASSERT(sizeof(JSErrorReport) % sizeof(const char*) == 0);
+ JS_STATIC_ASSERT(sizeof(T) % sizeof(const char*) == 0);
JS_STATIC_ASSERT(sizeof(const char*) % sizeof(char16_t) == 0);
-#define JS_CHARS_SIZE(chars) ((js_strlen(chars) + 1) * sizeof(char16_t))
-
size_t filenameSize = report->filename ? strlen(report->filename) + 1 : 0;
- size_t linebufSize = 0;
- if (report->linebuf())
- linebufSize = (report->linebufLength() + 1) * sizeof(char16_t);
size_t messageSize = 0;
if (report->message())
messageSize = strlen(report->message().c_str()) + 1;
@@ -231,13 +280,13 @@ js::CopyErrorReport(JSContext* cx, JSErrorReport* report)
* The mallocSize can not overflow since it represents the sum of the
* sizes of already allocated objects.
*/
- size_t mallocSize = sizeof(JSErrorReport) + messageSize + linebufSize + filenameSize;
+ size_t mallocSize = sizeof(T) + messageSize + filenameSize + ExtraMallocSize(report);
uint8_t* cursor = cx->pod_calloc<uint8_t>(mallocSize);
if (!cursor)
return nullptr;
- JSErrorReport* copy = (JSErrorReport*)cursor;
- cursor += sizeof(JSErrorReport);
+ T* copy = new (cursor) T();
+ cursor += sizeof(T);
if (report->message()) {
copy->initBorrowedMessage((const char*)cursor);
@@ -245,33 +294,40 @@ js::CopyErrorReport(JSContext* cx, JSErrorReport* report)
cursor += messageSize;
}
- if (report->linebuf()) {
- const char16_t* linebufCopy = (const char16_t*)cursor;
- js_memcpy(cursor, report->linebuf(), linebufSize);
- cursor += linebufSize;
- copy->initBorrowedLinebuf(linebufCopy, report->linebufLength(), report->tokenOffset());
- }
-
if (report->filename) {
copy->filename = (const char*)cursor;
js_memcpy(cursor, report->filename, filenameSize);
+ cursor += filenameSize;
+ }
+
+ if (!CopyExtraData(cx, &cursor, copy, report)) {
+ /* js_delete calls destructor for T and js_free for pod_calloc. */
+ js_delete(copy);
+ return nullptr;
}
- MOZ_ASSERT(cursor + filenameSize == (uint8_t*)copy + mallocSize);
+
+ MOZ_ASSERT(cursor == (uint8_t*)copy + mallocSize);
/* Copy non-pointer members. */
- copy->isMuted = report->isMuted;
copy->lineno = report->lineno;
copy->column = report->column;
copy->errorNumber = report->errorNumber;
- copy->exnType = report->exnType;
- /* Note that this is before it gets flagged with JSREPORT_EXCEPTION */
- copy->flags = report->flags;
-
-#undef JS_CHARS_SIZE
return copy;
}
+JSErrorNotes::Note*
+js::CopyErrorNote(JSContext* cx, JSErrorNotes::Note* note)
+{
+ return CopyErrorHelper(cx, note);
+}
+
+JSErrorReport*
+js::CopyErrorReport(JSContext* cx, JSErrorReport* report)
+{
+ return CopyErrorHelper(cx, report);
+}
+
struct SuppressErrorsGuard
{
JSContext* cx;
@@ -322,7 +378,7 @@ exn_finalize(FreeOp* fop, JSObject* obj)
{
MOZ_ASSERT(fop->maybeOffMainThread());
if (JSErrorReport* report = obj->as<ErrorObject>().getErrorReport())
- fop->free_(report);
+ fop->delete_(report);
}
JSErrorReport*