Backed out changeset 8f976ed899d7 (bug 1847231) for causing bc failures on browser_se...
[gecko.git] / js / src / jsapi-tests / testFrontendErrors.cpp
blobc9d3ee1eb51f7ea86d8b3c818074564e1dd41ae8
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
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/. */
7 #include "mozilla/RefPtr.h" // RefPtr
8 #include "mozilla/Utf8.h" // mozilla::Utf8Unit
10 #include <string.h> // strcmp
12 #include "frontend/FrontendContext.h" // js::FrontendContext
13 #include "js/AllocPolicy.h" // js::ReportOutOfMemory
14 #include "js/CompileOptions.h" // JS::PrefableCompileOptions, JS::CompileOptions
15 #include "js/Exception.h" // JS_IsExceptionPending, JS_IsThrowingOutOfMemory, JS_GetPendingException, JS_ClearPendingException, JS_ErrorFromException
16 #include "js/experimental/CompileScript.h" // JS::NewFrontendContext, JS::DestroyFrontendContext, JS::SetNativeStackQuota, JS::CompileGlobalScriptToStencil, JS::ConvertFrontendErrorsToRuntimeErrors, JS::HadFrontendErrors, JS::HadFrontendOverRecursed, JS::HadFrontendOutOfMemory, JS::HadFrontendAllocationOverflow, JS::GetFrontendWarningCount, JS::GetFrontendWarningAt
17 #include "js/friend/ErrorMessages.h" // JSMSG_*
18 #include "js/friend/StackLimits.h" // js::ReportOverRecursed
19 #include "js/RootingAPI.h" // JS::Rooted
20 #include "js/SourceText.h" // JS::SourceText
21 #include "js/Stack.h" // JS::NativeStackSize
22 #include "js/Warnings.h" // JS::SetWarningReporter
23 #include "jsapi-tests/tests.h"
24 #include "util/NativeStack.h" // js::GetNativeStackBase
25 #include "vm/ErrorObject.h" // js::ErrorObject
26 #include "vm/JSContext.h" // JSContext
27 #include "vm/JSObject.h" // JSObject
28 #include "vm/NativeObject.h" // js::NativeObject
29 #include "vm/Runtime.h" // js::ReportAllocationOverflow
31 using namespace JS;
33 BEGIN_TEST(testFrontendErrors_error) {
34 JS::FrontendContext* fc = JS::NewFrontendContext();
35 CHECK(fc);
37 static constexpr JS::NativeStackSize stackSize = 128 * sizeof(size_t) * 1024;
39 JS::SetNativeStackQuota(fc, stackSize);
41 JS::PrefableCompileOptions prefableOptions;
42 JS::CompileOptions options(prefableOptions);
43 const char* filename = "testFrontendErrors_error.js";
44 options.setFile(filename);
46 CHECK(!JS::HadFrontendErrors(fc));
49 const char source[] = "syntax error";
51 JS::SourceText<mozilla::Utf8Unit> srcBuf;
52 CHECK(
53 srcBuf.init(fc, source, strlen(source), JS::SourceOwnership::Borrowed));
54 JS::CompilationStorage compileStorage;
55 RefPtr<JS::Stencil> stencil =
56 JS::CompileGlobalScriptToStencil(fc, options, srcBuf, compileStorage);
57 CHECK(!stencil);
60 CHECK(JS::HadFrontendErrors(fc));
61 CHECK(!JS::HadFrontendOverRecursed(fc));
62 CHECK(!JS::HadFrontendOutOfMemory(fc));
63 CHECK(!JS::HadFrontendAllocationOverflow(fc));
64 CHECK(JS::GetFrontendWarningCount(fc) == 0);
67 const JSErrorReport* report = JS::GetFrontendErrorReport(fc, options);
68 CHECK(report);
70 CHECK(report->errorNumber == JSMSG_UNEXPECTED_TOKEN_NO_EXPECT);
71 // FrontendContext's error report borrows the filename.
72 CHECK(report->filename.c_str() == filename);
75 CHECK(!JS_IsExceptionPending(cx));
77 JS::SetWarningReporter(cx, warningReporter);
79 bool result = JS::ConvertFrontendErrorsToRuntimeErrors(cx, fc, options);
80 CHECK(result);
82 CHECK(JS_IsExceptionPending(cx));
83 CHECK(!warningReporterCalled);
84 CHECK(!JS_IsThrowingOutOfMemory(cx));
87 JS::Rooted<JS::Value> exception(cx);
88 CHECK(JS_GetPendingException(cx, &exception));
90 CHECK(exception.isObject());
91 JS::Rooted<JSObject*> exceptionObj(cx, &exception.toObject());
93 const JSErrorReport* report = JS_ErrorFromException(cx, exceptionObj);
94 CHECK(report);
96 CHECK(report->errorNumber == JSMSG_UNEXPECTED_TOKEN_NO_EXPECT);
97 // Runtime's error report doesn't borrow the filename.
98 CHECK(report->filename.c_str() != filename);
99 CHECK(strcmp(report->filename.c_str(), filename) == 0);
102 JS_ClearPendingException(cx);
104 JS::DestroyFrontendContext(fc);
106 return true;
109 static bool warningReporterCalled;
111 static void warningReporter(JSContext* cx, JSErrorReport* report) {
112 warningReporterCalled = true;
114 END_TEST(testFrontendErrors_error)
116 /* static */ bool cls_testFrontendErrors_error::warningReporterCalled = false;
118 BEGIN_TEST(testFrontendErrors_warning) {
119 JS::FrontendContext* fc = JS::NewFrontendContext();
120 CHECK(fc);
122 static constexpr JS::NativeStackSize stackSize = 128 * sizeof(size_t) * 1024;
124 JS::SetNativeStackQuota(fc, stackSize);
126 JS::PrefableCompileOptions prefableOptions;
127 JS::CompileOptions options(prefableOptions);
128 options.setFile(filename);
131 const char source[] = "function f() { return; f(); }";
133 JS::SourceText<mozilla::Utf8Unit> srcBuf;
134 CHECK(
135 srcBuf.init(fc, source, strlen(source), JS::SourceOwnership::Borrowed));
136 JS::CompilationStorage compileStorage;
137 RefPtr<JS::Stencil> stencil =
138 JS::CompileGlobalScriptToStencil(fc, options, srcBuf, compileStorage);
139 CHECK(stencil);
142 CHECK(!JS::HadFrontendErrors(fc));
143 CHECK(!JS::HadFrontendOverRecursed(fc));
144 CHECK(!JS::HadFrontendOutOfMemory(fc));
145 CHECK(!JS::HadFrontendAllocationOverflow(fc));
146 CHECK(JS::GetFrontendWarningCount(fc) == 1);
149 const JSErrorReport* report = JS::GetFrontendWarningAt(fc, 0, options);
150 CHECK(report);
152 CHECK(report->errorNumber == JSMSG_STMT_AFTER_RETURN);
153 // FrontendContext's error report borrows the filename.
154 CHECK(report->filename.c_str() == filename);
157 CHECK(!JS_IsExceptionPending(cx));
159 JS::SetWarningReporter(cx, warningReporter);
161 bool result = JS::ConvertFrontendErrorsToRuntimeErrors(cx, fc, options);
162 CHECK(result);
164 CHECK(!JS_IsExceptionPending(cx));
165 CHECK(warningReporterCalled);
166 CHECK(!JS_IsThrowingOutOfMemory(cx));
168 CHECK(errorNumberMatches);
169 CHECK(filenameMatches);
171 JS::DestroyFrontendContext(fc);
173 return true;
176 static const char* filename;
177 static bool warningReporterCalled;
178 static bool errorNumberMatches;
179 static bool filenameMatches;
181 static void warningReporter(JSContext* cx, JSErrorReport* report) {
182 warningReporterCalled = true;
184 errorNumberMatches = report->errorNumber == JSMSG_STMT_AFTER_RETURN;
185 filenameMatches = report->filename.c_str() == filename;
187 END_TEST(testFrontendErrors_warning)
189 /* static */ const char* cls_testFrontendErrors_warning::filename =
190 "testFrontendErrors_warning.js";
191 /* static */ bool cls_testFrontendErrors_warning::warningReporterCalled = false;
192 /* static */ bool cls_testFrontendErrors_warning::errorNumberMatches = false;
193 /* static */ bool cls_testFrontendErrors_warning::filenameMatches = false;
195 BEGIN_TEST(testFrontendErrors_oom) {
196 JS::FrontendContext* fc = JS::NewFrontendContext();
197 CHECK(fc);
199 JS::PrefableCompileOptions prefableOptions;
200 JS::CompileOptions options(prefableOptions);
202 CHECK(!JS::HadFrontendErrors(fc));
204 js::ReportOutOfMemory(fc);
206 CHECK(JS::HadFrontendErrors(fc));
207 CHECK(!JS::HadFrontendOverRecursed(fc));
208 CHECK(JS::HadFrontendOutOfMemory(fc));
209 CHECK(!JS::HadFrontendAllocationOverflow(fc));
210 CHECK(JS::GetFrontendWarningCount(fc) == 0);
212 CHECK(!JS_IsExceptionPending(cx));
214 JS::SetWarningReporter(cx, warningReporter);
216 bool result = JS::ConvertFrontendErrorsToRuntimeErrors(cx, fc, options);
217 CHECK(!result);
219 CHECK(JS_IsExceptionPending(cx));
220 CHECK(!warningReporterCalled);
221 CHECK(JS_IsThrowingOutOfMemory(cx));
223 JS_ClearPendingException(cx);
225 JS::DestroyFrontendContext(fc);
227 return true;
230 static bool warningReporterCalled;
232 static void warningReporter(JSContext* cx, JSErrorReport* report) {
233 warningReporterCalled = true;
235 END_TEST(testFrontendErrors_oom)
237 /* static */ bool cls_testFrontendErrors_oom::warningReporterCalled = false;
239 BEGIN_TEST(testFrontendErrors_overRecursed) {
240 JS::FrontendContext* fc = JS::NewFrontendContext();
241 CHECK(fc);
243 JS::PrefableCompileOptions prefableOptions;
244 JS::CompileOptions options(prefableOptions);
246 CHECK(!JS::HadFrontendErrors(fc));
248 js::ReportOverRecursed(fc);
250 CHECK(JS::HadFrontendErrors(fc));
251 CHECK(JS::HadFrontendOverRecursed(fc));
252 CHECK(!JS::HadFrontendOutOfMemory(fc));
253 CHECK(!JS::HadFrontendAllocationOverflow(fc));
254 CHECK(JS::GetFrontendWarningCount(fc) == 0);
256 CHECK(!JS_IsExceptionPending(cx));
258 JS::SetWarningReporter(cx, warningReporter);
260 bool result = JS::ConvertFrontendErrorsToRuntimeErrors(cx, fc, options);
261 CHECK(result);
263 CHECK(JS_IsExceptionPending(cx));
264 CHECK(!warningReporterCalled);
265 CHECK(!JS_IsThrowingOutOfMemory(cx));
268 JS::Rooted<JS::Value> exception(cx);
269 CHECK(JS_GetPendingException(cx, &exception));
271 CHECK(exception.isObject());
272 JS::Rooted<JSObject*> exceptionObj(cx, &exception.toObject());
274 const JSErrorReport* report = JS_ErrorFromException(cx, exceptionObj);
275 CHECK(report);
277 CHECK(report->errorNumber == JSMSG_OVER_RECURSED);
280 JS_ClearPendingException(cx);
282 JS::DestroyFrontendContext(fc);
284 return true;
287 static bool warningReporterCalled;
289 static void warningReporter(JSContext* cx, JSErrorReport* report) {
290 warningReporterCalled = true;
292 END_TEST(testFrontendErrors_overRecursed)
294 /* static */ bool cls_testFrontendErrors_overRecursed::warningReporterCalled =
295 false;
297 BEGIN_TEST(testFrontendErrors_allocationOverflow) {
298 JS::FrontendContext* fc = JS::NewFrontendContext();
299 CHECK(fc);
301 JS::PrefableCompileOptions prefableOptions;
302 JS::CompileOptions options(prefableOptions);
304 CHECK(!JS::HadFrontendErrors(fc));
306 js::ReportAllocationOverflow(fc);
308 CHECK(JS::HadFrontendErrors(fc));
309 CHECK(!JS::HadFrontendOverRecursed(fc));
310 CHECK(!JS::HadFrontendOutOfMemory(fc));
311 CHECK(JS::HadFrontendAllocationOverflow(fc));
312 CHECK(JS::GetFrontendWarningCount(fc) == 0);
314 CHECK(!JS_IsExceptionPending(cx));
316 JS::SetWarningReporter(cx, warningReporter);
318 bool result = JS::ConvertFrontendErrorsToRuntimeErrors(cx, fc, options);
319 CHECK(result);
321 CHECK(JS_IsExceptionPending(cx));
322 CHECK(!warningReporterCalled);
323 CHECK(!JS_IsThrowingOutOfMemory(cx));
326 JS::Rooted<JS::Value> exception(cx);
327 CHECK(JS_GetPendingException(cx, &exception));
329 CHECK(exception.isObject());
330 JS::Rooted<JSObject*> exceptionObj(cx, &exception.toObject());
332 const JSErrorReport* report = JS_ErrorFromException(cx, exceptionObj);
333 CHECK(report);
335 CHECK(report->errorNumber == JSMSG_ALLOC_OVERFLOW);
338 JS_ClearPendingException(cx);
340 JS::DestroyFrontendContext(fc);
342 return true;
345 static bool warningReporterCalled;
347 static void warningReporter(JSContext* cx, JSErrorReport* report) {
348 warningReporterCalled = true;
350 END_TEST(testFrontendErrors_allocationOverflow)
352 /* static */ bool
353 cls_testFrontendErrors_allocationOverflow::warningReporterCalled = false;