From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- js/src/jsapi-tests/testFrontendErrors.cpp | 353 ++++++++++++++++++++++++++++++ 1 file changed, 353 insertions(+) create mode 100644 js/src/jsapi-tests/testFrontendErrors.cpp (limited to 'js/src/jsapi-tests/testFrontendErrors.cpp') diff --git a/js/src/jsapi-tests/testFrontendErrors.cpp b/js/src/jsapi-tests/testFrontendErrors.cpp new file mode 100644 index 0000000000..c9d3ee1eb5 --- /dev/null +++ b/js/src/jsapi-tests/testFrontendErrors.cpp @@ -0,0 +1,353 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/RefPtr.h" // RefPtr +#include "mozilla/Utf8.h" // mozilla::Utf8Unit + +#include // strcmp + +#include "frontend/FrontendContext.h" // js::FrontendContext +#include "js/AllocPolicy.h" // js::ReportOutOfMemory +#include "js/CompileOptions.h" // JS::PrefableCompileOptions, JS::CompileOptions +#include "js/Exception.h" // JS_IsExceptionPending, JS_IsThrowingOutOfMemory, JS_GetPendingException, JS_ClearPendingException, JS_ErrorFromException +#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 +#include "js/friend/ErrorMessages.h" // JSMSG_* +#include "js/friend/StackLimits.h" // js::ReportOverRecursed +#include "js/RootingAPI.h" // JS::Rooted +#include "js/SourceText.h" // JS::SourceText +#include "js/Stack.h" // JS::NativeStackSize +#include "js/Warnings.h" // JS::SetWarningReporter +#include "jsapi-tests/tests.h" +#include "util/NativeStack.h" // js::GetNativeStackBase +#include "vm/ErrorObject.h" // js::ErrorObject +#include "vm/JSContext.h" // JSContext +#include "vm/JSObject.h" // JSObject +#include "vm/NativeObject.h" // js::NativeObject +#include "vm/Runtime.h" // js::ReportAllocationOverflow + +using namespace JS; + +BEGIN_TEST(testFrontendErrors_error) { + JS::FrontendContext* fc = JS::NewFrontendContext(); + CHECK(fc); + + static constexpr JS::NativeStackSize stackSize = 128 * sizeof(size_t) * 1024; + + JS::SetNativeStackQuota(fc, stackSize); + + JS::PrefableCompileOptions prefableOptions; + JS::CompileOptions options(prefableOptions); + const char* filename = "testFrontendErrors_error.js"; + options.setFile(filename); + + CHECK(!JS::HadFrontendErrors(fc)); + + { + const char source[] = "syntax error"; + + JS::SourceText srcBuf; + CHECK( + srcBuf.init(fc, source, strlen(source), JS::SourceOwnership::Borrowed)); + JS::CompilationStorage compileStorage; + RefPtr stencil = + JS::CompileGlobalScriptToStencil(fc, options, srcBuf, compileStorage); + CHECK(!stencil); + } + + CHECK(JS::HadFrontendErrors(fc)); + CHECK(!JS::HadFrontendOverRecursed(fc)); + CHECK(!JS::HadFrontendOutOfMemory(fc)); + CHECK(!JS::HadFrontendAllocationOverflow(fc)); + CHECK(JS::GetFrontendWarningCount(fc) == 0); + + { + const JSErrorReport* report = JS::GetFrontendErrorReport(fc, options); + CHECK(report); + + CHECK(report->errorNumber == JSMSG_UNEXPECTED_TOKEN_NO_EXPECT); + // FrontendContext's error report borrows the filename. + CHECK(report->filename.c_str() == filename); + } + + CHECK(!JS_IsExceptionPending(cx)); + + JS::SetWarningReporter(cx, warningReporter); + + bool result = JS::ConvertFrontendErrorsToRuntimeErrors(cx, fc, options); + CHECK(result); + + CHECK(JS_IsExceptionPending(cx)); + CHECK(!warningReporterCalled); + CHECK(!JS_IsThrowingOutOfMemory(cx)); + + { + JS::Rooted exception(cx); + CHECK(JS_GetPendingException(cx, &exception)); + + CHECK(exception.isObject()); + JS::Rooted exceptionObj(cx, &exception.toObject()); + + const JSErrorReport* report = JS_ErrorFromException(cx, exceptionObj); + CHECK(report); + + CHECK(report->errorNumber == JSMSG_UNEXPECTED_TOKEN_NO_EXPECT); + // Runtime's error report doesn't borrow the filename. + CHECK(report->filename.c_str() != filename); + CHECK(strcmp(report->filename.c_str(), filename) == 0); + } + + JS_ClearPendingException(cx); + + JS::DestroyFrontendContext(fc); + + return true; +} + +static bool warningReporterCalled; + +static void warningReporter(JSContext* cx, JSErrorReport* report) { + warningReporterCalled = true; +} +END_TEST(testFrontendErrors_error) + +/* static */ bool cls_testFrontendErrors_error::warningReporterCalled = false; + +BEGIN_TEST(testFrontendErrors_warning) { + JS::FrontendContext* fc = JS::NewFrontendContext(); + CHECK(fc); + + static constexpr JS::NativeStackSize stackSize = 128 * sizeof(size_t) * 1024; + + JS::SetNativeStackQuota(fc, stackSize); + + JS::PrefableCompileOptions prefableOptions; + JS::CompileOptions options(prefableOptions); + options.setFile(filename); + + { + const char source[] = "function f() { return; f(); }"; + + JS::SourceText srcBuf; + CHECK( + srcBuf.init(fc, source, strlen(source), JS::SourceOwnership::Borrowed)); + JS::CompilationStorage compileStorage; + RefPtr stencil = + JS::CompileGlobalScriptToStencil(fc, options, srcBuf, compileStorage); + CHECK(stencil); + } + + CHECK(!JS::HadFrontendErrors(fc)); + CHECK(!JS::HadFrontendOverRecursed(fc)); + CHECK(!JS::HadFrontendOutOfMemory(fc)); + CHECK(!JS::HadFrontendAllocationOverflow(fc)); + CHECK(JS::GetFrontendWarningCount(fc) == 1); + + { + const JSErrorReport* report = JS::GetFrontendWarningAt(fc, 0, options); + CHECK(report); + + CHECK(report->errorNumber == JSMSG_STMT_AFTER_RETURN); + // FrontendContext's error report borrows the filename. + CHECK(report->filename.c_str() == filename); + } + + CHECK(!JS_IsExceptionPending(cx)); + + JS::SetWarningReporter(cx, warningReporter); + + bool result = JS::ConvertFrontendErrorsToRuntimeErrors(cx, fc, options); + CHECK(result); + + CHECK(!JS_IsExceptionPending(cx)); + CHECK(warningReporterCalled); + CHECK(!JS_IsThrowingOutOfMemory(cx)); + + CHECK(errorNumberMatches); + CHECK(filenameMatches); + + JS::DestroyFrontendContext(fc); + + return true; +} + +static const char* filename; +static bool warningReporterCalled; +static bool errorNumberMatches; +static bool filenameMatches; + +static void warningReporter(JSContext* cx, JSErrorReport* report) { + warningReporterCalled = true; + + errorNumberMatches = report->errorNumber == JSMSG_STMT_AFTER_RETURN; + filenameMatches = report->filename.c_str() == filename; +} +END_TEST(testFrontendErrors_warning) + +/* static */ const char* cls_testFrontendErrors_warning::filename = + "testFrontendErrors_warning.js"; +/* static */ bool cls_testFrontendErrors_warning::warningReporterCalled = false; +/* static */ bool cls_testFrontendErrors_warning::errorNumberMatches = false; +/* static */ bool cls_testFrontendErrors_warning::filenameMatches = false; + +BEGIN_TEST(testFrontendErrors_oom) { + JS::FrontendContext* fc = JS::NewFrontendContext(); + CHECK(fc); + + JS::PrefableCompileOptions prefableOptions; + JS::CompileOptions options(prefableOptions); + + CHECK(!JS::HadFrontendErrors(fc)); + + js::ReportOutOfMemory(fc); + + CHECK(JS::HadFrontendErrors(fc)); + CHECK(!JS::HadFrontendOverRecursed(fc)); + CHECK(JS::HadFrontendOutOfMemory(fc)); + CHECK(!JS::HadFrontendAllocationOverflow(fc)); + CHECK(JS::GetFrontendWarningCount(fc) == 0); + + CHECK(!JS_IsExceptionPending(cx)); + + JS::SetWarningReporter(cx, warningReporter); + + bool result = JS::ConvertFrontendErrorsToRuntimeErrors(cx, fc, options); + CHECK(!result); + + CHECK(JS_IsExceptionPending(cx)); + CHECK(!warningReporterCalled); + CHECK(JS_IsThrowingOutOfMemory(cx)); + + JS_ClearPendingException(cx); + + JS::DestroyFrontendContext(fc); + + return true; +} + +static bool warningReporterCalled; + +static void warningReporter(JSContext* cx, JSErrorReport* report) { + warningReporterCalled = true; +} +END_TEST(testFrontendErrors_oom) + +/* static */ bool cls_testFrontendErrors_oom::warningReporterCalled = false; + +BEGIN_TEST(testFrontendErrors_overRecursed) { + JS::FrontendContext* fc = JS::NewFrontendContext(); + CHECK(fc); + + JS::PrefableCompileOptions prefableOptions; + JS::CompileOptions options(prefableOptions); + + CHECK(!JS::HadFrontendErrors(fc)); + + js::ReportOverRecursed(fc); + + CHECK(JS::HadFrontendErrors(fc)); + CHECK(JS::HadFrontendOverRecursed(fc)); + CHECK(!JS::HadFrontendOutOfMemory(fc)); + CHECK(!JS::HadFrontendAllocationOverflow(fc)); + CHECK(JS::GetFrontendWarningCount(fc) == 0); + + CHECK(!JS_IsExceptionPending(cx)); + + JS::SetWarningReporter(cx, warningReporter); + + bool result = JS::ConvertFrontendErrorsToRuntimeErrors(cx, fc, options); + CHECK(result); + + CHECK(JS_IsExceptionPending(cx)); + CHECK(!warningReporterCalled); + CHECK(!JS_IsThrowingOutOfMemory(cx)); + + { + JS::Rooted exception(cx); + CHECK(JS_GetPendingException(cx, &exception)); + + CHECK(exception.isObject()); + JS::Rooted exceptionObj(cx, &exception.toObject()); + + const JSErrorReport* report = JS_ErrorFromException(cx, exceptionObj); + CHECK(report); + + CHECK(report->errorNumber == JSMSG_OVER_RECURSED); + } + + JS_ClearPendingException(cx); + + JS::DestroyFrontendContext(fc); + + return true; +} + +static bool warningReporterCalled; + +static void warningReporter(JSContext* cx, JSErrorReport* report) { + warningReporterCalled = true; +} +END_TEST(testFrontendErrors_overRecursed) + +/* static */ bool cls_testFrontendErrors_overRecursed::warningReporterCalled = + false; + +BEGIN_TEST(testFrontendErrors_allocationOverflow) { + JS::FrontendContext* fc = JS::NewFrontendContext(); + CHECK(fc); + + JS::PrefableCompileOptions prefableOptions; + JS::CompileOptions options(prefableOptions); + + CHECK(!JS::HadFrontendErrors(fc)); + + js::ReportAllocationOverflow(fc); + + CHECK(JS::HadFrontendErrors(fc)); + CHECK(!JS::HadFrontendOverRecursed(fc)); + CHECK(!JS::HadFrontendOutOfMemory(fc)); + CHECK(JS::HadFrontendAllocationOverflow(fc)); + CHECK(JS::GetFrontendWarningCount(fc) == 0); + + CHECK(!JS_IsExceptionPending(cx)); + + JS::SetWarningReporter(cx, warningReporter); + + bool result = JS::ConvertFrontendErrorsToRuntimeErrors(cx, fc, options); + CHECK(result); + + CHECK(JS_IsExceptionPending(cx)); + CHECK(!warningReporterCalled); + CHECK(!JS_IsThrowingOutOfMemory(cx)); + + { + JS::Rooted exception(cx); + CHECK(JS_GetPendingException(cx, &exception)); + + CHECK(exception.isObject()); + JS::Rooted exceptionObj(cx, &exception.toObject()); + + const JSErrorReport* report = JS_ErrorFromException(cx, exceptionObj); + CHECK(report); + + CHECK(report->errorNumber == JSMSG_ALLOC_OVERFLOW); + } + + JS_ClearPendingException(cx); + + JS::DestroyFrontendContext(fc); + + return true; +} + +static bool warningReporterCalled; + +static void warningReporter(JSContext* cx, JSErrorReport* report) { + warningReporterCalled = true; +} +END_TEST(testFrontendErrors_allocationOverflow) + +/* static */ bool + cls_testFrontendErrors_allocationOverflow::warningReporterCalled = false; -- cgit v1.2.3