Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sts=4 et sw=4 tw=99:
3 : * This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #include "vm/ErrorReporting.h"
8 :
9 : #include "mozilla/Move.h"
10 :
11 : #include <stdarg.h>
12 :
13 : #include "jscntxt.h"
14 : #include "jsexn.h"
15 : #include "jsfriendapi.h"
16 :
17 : #include "jscntxtinlines.h"
18 :
19 : using mozilla::Move;
20 :
21 : using JS::HandleObject;
22 : using JS::HandleValue;
23 : using JS::UniqueTwoByteChars;
24 :
25 : void
26 0 : js::CallWarningReporter(JSContext* cx, JSErrorReport* reportp)
27 : {
28 0 : MOZ_ASSERT(reportp);
29 0 : MOZ_ASSERT(JSREPORT_IS_WARNING(reportp->flags));
30 :
31 0 : if (JS::WarningReporter warningReporter = cx->runtime()->warningReporter)
32 0 : warningReporter(cx, reportp);
33 0 : }
34 :
35 : void
36 0 : js::CompileError::throwError(JSContext* cx)
37 : {
38 0 : if (JSREPORT_IS_WARNING(flags)) {
39 0 : CallWarningReporter(cx, this);
40 0 : return;
41 : }
42 :
43 : // If there's a runtime exception type associated with this error
44 : // number, set that as the pending exception. For errors occuring at
45 : // compile time, this is very likely to be a JSEXN_SYNTAXERR.
46 : //
47 : // If an exception is thrown but not caught, the JSREPORT_EXCEPTION
48 : // flag will be set in report.flags. Proper behavior for an error
49 : // reporter is to ignore a report with this flag for all but top-level
50 : // compilation errors. The exception will remain pending, and so long
51 : // as the non-top-level "load", "eval", or "compile" native function
52 : // returns false, the top-level reporter will eventually receive the
53 : // uncaught exception report.
54 0 : ErrorToException(cx, this, nullptr, nullptr);
55 : }
56 :
57 : bool
58 0 : js::ReportCompileWarning(JSContext* cx, ErrorMetadata&& metadata, UniquePtr<JSErrorNotes> notes,
59 : unsigned flags, unsigned errorNumber, va_list args)
60 : {
61 : // On the active thread, report the error immediately. When compiling off
62 : // thread, save the error so that the thread finishing the parse can report
63 : // it later.
64 0 : CompileError tempErr;
65 0 : CompileError* err = &tempErr;
66 0 : if (cx->helperThread() && !cx->addPendingCompileError(&err))
67 0 : return false;
68 :
69 0 : err->notes = Move(notes);
70 0 : err->flags = flags;
71 0 : err->errorNumber = errorNumber;
72 :
73 0 : err->filename = metadata.filename;
74 0 : err->lineno = metadata.lineNumber;
75 0 : err->column = metadata.columnNumber;
76 0 : err->isMuted = metadata.isMuted;
77 :
78 0 : if (UniqueTwoByteChars lineOfContext = Move(metadata.lineOfContext))
79 0 : err->initOwnedLinebuf(lineOfContext.release(), metadata.lineLength, metadata.tokenOffset);
80 :
81 0 : if (!ExpandErrorArgumentsVA(cx, GetErrorMessage, nullptr, errorNumber,
82 : nullptr, ArgumentsAreLatin1, err, args))
83 : {
84 0 : return false;
85 : }
86 :
87 0 : if (!cx->helperThread())
88 0 : err->throwError(cx);
89 :
90 0 : return true;
91 : }
92 :
93 : void
94 0 : js::ReportCompileError(JSContext* cx, ErrorMetadata&& metadata, UniquePtr<JSErrorNotes> notes,
95 : unsigned flags, unsigned errorNumber, va_list args)
96 : {
97 : // On the active thread, report the error immediately. When compiling off
98 : // thread, save the error so that the thread finishing the parse can report
99 : // it later.
100 0 : CompileError tempErr;
101 0 : CompileError* err = &tempErr;
102 0 : if (cx->helperThread() && !cx->addPendingCompileError(&err))
103 0 : return;
104 :
105 0 : err->notes = Move(notes);
106 0 : err->flags = flags;
107 0 : err->errorNumber = errorNumber;
108 :
109 0 : err->filename = metadata.filename;
110 0 : err->lineno = metadata.lineNumber;
111 0 : err->column = metadata.columnNumber;
112 0 : err->isMuted = metadata.isMuted;
113 :
114 0 : if (UniqueTwoByteChars lineOfContext = Move(metadata.lineOfContext))
115 0 : err->initOwnedLinebuf(lineOfContext.release(), metadata.lineLength, metadata.tokenOffset);
116 :
117 0 : if (!ExpandErrorArgumentsVA(cx, GetErrorMessage, nullptr, errorNumber,
118 : nullptr, ArgumentsAreLatin1, err, args))
119 : {
120 0 : return;
121 : }
122 :
123 0 : if (!cx->helperThread())
124 0 : err->throwError(cx);
125 : }
126 :
127 : namespace {
128 :
129 : class MOZ_STACK_CLASS ReportExceptionClosure
130 : : public js::ScriptEnvironmentPreparer::Closure
131 : {
132 : public:
133 0 : explicit ReportExceptionClosure(HandleValue& exn)
134 0 : : exn_(exn)
135 : {
136 0 : }
137 :
138 0 : bool operator()(JSContext* cx) override
139 : {
140 0 : cx->setPendingException(exn_);
141 0 : return false;
142 : }
143 :
144 : private:
145 : HandleValue& exn_;
146 : };
147 :
148 : } // anonymous namespace
149 :
150 : void
151 0 : js::ReportErrorToGlobal(JSContext* cx, HandleObject global, HandleValue error)
152 : {
153 0 : MOZ_ASSERT(!cx->isExceptionPending());
154 : #ifdef DEBUG
155 : // No assertSameCompartment version that doesn't take JSContext...
156 0 : if (error.isObject()) {
157 0 : AssertSameCompartment(global, &error.toObject());
158 : }
159 : #endif // DEBUG
160 0 : ReportExceptionClosure report(error);
161 0 : PrepareScriptEnvironmentAndInvoke(cx, global, report);
162 0 : }
|