testErrorLineOfContext.cpp (2586B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #include "js/CompilationAndEvaluation.h" 6 #include "js/Exception.h" 7 #include "js/GlobalObject.h" 8 #include "js/SourceText.h" 9 #include "jsapi-tests/tests.h" 10 #include "vm/ErrorReporting.h" 11 12 BEGIN_TEST(testErrorLineOfContext) { 13 static const char16_t fullLineR[] = u"\n var x = @; \r "; 14 CHECK(testLineOfContextHasNoLineTerminator(fullLineR, ' ')); 15 16 static const char16_t fullLineN[] = u"\n var x = @; !\n "; 17 CHECK(testLineOfContextHasNoLineTerminator(fullLineN, '!')); 18 19 static const char16_t fullLineLS[] = u"\n var x = @; +\u2028 "; 20 CHECK(testLineOfContextHasNoLineTerminator(fullLineLS, '+')); 21 22 static const char16_t fullLinePS[] = u"\n var x = @; #\u2029 "; 23 CHECK(testLineOfContextHasNoLineTerminator(fullLinePS, '#')); 24 25 static_assert(js::ErrorMetadata::lineOfContextRadius == 60, 26 "current max count past offset is 60, hits 'X' below"); 27 28 static const char16_t truncatedLine[] = 29 u"@ + 4567890123456789012345678901234567890123456789012345678XYZW\n"; 30 CHECK(testLineOfContextHasNoLineTerminator(truncatedLine, 'X')); 31 32 return true; 33 } 34 35 bool eval(const char16_t* chars, size_t len, JS::MutableHandleValue rval) { 36 JS::RealmOptions globalOptions; 37 JS::RootedObject global( 38 cx, JS_NewGlobalObject(cx, getGlobalClass(), nullptr, 39 JS::FireOnNewGlobalHook, globalOptions)); 40 CHECK(global); 41 42 JSAutoRealm ar(cx, global); 43 44 JS::SourceText<char16_t> srcBuf; 45 CHECK(srcBuf.init(cx, chars, len, JS::SourceOwnership::Borrowed)); 46 47 JS::CompileOptions options(cx); 48 return JS::Evaluate(cx, options, srcBuf, rval); 49 } 50 51 template <size_t N> 52 bool testLineOfContextHasNoLineTerminator(const char16_t (&chars)[N], 53 char16_t expectedLast) { 54 JS::RootedValue rval(cx); 55 CHECK(!eval(chars, N - 1, &rval)); 56 57 JS::ExceptionStack exnStack(cx); 58 CHECK(JS::StealPendingExceptionStack(cx, &exnStack)); 59 60 JS::ErrorReportBuilder report(cx); 61 CHECK(report.init(cx, exnStack, JS::ErrorReportBuilder::WithSideEffects)); 62 63 const auto* errorReport = report.report(); 64 65 const char16_t* lineOfContext = errorReport->linebuf(); 66 size_t lineOfContextLength = errorReport->linebufLength(); 67 68 CHECK(lineOfContext[lineOfContextLength] == '\0'); 69 char16_t last = lineOfContext[lineOfContextLength - 1]; 70 CHECK(last == expectedLast); 71 72 return true; 73 } 74 END_TEST(testErrorLineOfContext)