Bug 1852740: add tests for the `fetchpriority` attribute in Link headers. r=necko...
[gecko.git] / js / src / jsapi-tests / testEmptyWindowIsOmitted.cpp
blobc03a8106c05b532a6deda0802bb6d747ddd34eec
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/. */
5 #include "mozilla/TextUtils.h"
6 #include "mozilla/Utf8.h"
8 #include <cstring>
10 #include "js/CharacterEncoding.h"
11 #include "js/CompilationAndEvaluation.h" // JS::Compile
12 #include "js/Exception.h"
13 #include "js/friend/ErrorMessages.h" // JSMSG_*
14 #include "js/SourceText.h"
15 #include "jsapi-tests/tests.h"
16 #include "util/Text.h"
17 #include "vm/ErrorReporting.h"
19 using mozilla::IsAsciiHexDigit;
20 using mozilla::Utf8Unit;
22 BEGIN_TEST(testEmptyWindow) { return testUtf8() && testUtf16(); }
24 bool testUtf8() {
25 // Bad unit with nothing before it.
26 static const char badLeadingUnit[] = "\x80";
27 CHECK(testOmittedWindow(badLeadingUnit, JSMSG_BAD_LEADING_UTF8_UNIT, "0x80"));
29 // Bad unit at start of a fresh line.
30 static const char badStartingFreshLine[] = "var x = 5;\n\x98";
31 CHECK(testOmittedWindow(badStartingFreshLine, JSMSG_BAD_LEADING_UTF8_UNIT,
32 "0x98"));
34 // Bad trailing unit in initial code point.
35 static const char badTrailingUnit[] = "\xD8\x20";
36 CHECK(testOmittedWindow(badTrailingUnit, JSMSG_BAD_TRAILING_UTF8_UNIT,
37 "0xD8 0x20"));
39 // Bad trailing unit at start of a fresh line.
40 static const char badTrailingUnitFreshLine[] = "var x = 5;\n\xD8\x20";
41 CHECK(testOmittedWindow(badTrailingUnitFreshLine,
42 JSMSG_BAD_TRAILING_UTF8_UNIT, "0xD8 0x20"));
44 // Overlong in initial code point.
45 static const char overlongInitial[] = "\xC0\x80";
46 CHECK(testOmittedWindow(overlongInitial, JSMSG_FORBIDDEN_UTF8_CODE_POINT,
47 "0xC0 0x80"));
49 // Overlong at start of a fresh line.
50 static const char overlongFreshLine[] = "var x = 5;\n\xC0\x81";
51 CHECK(testOmittedWindow(overlongFreshLine, JSMSG_FORBIDDEN_UTF8_CODE_POINT,
52 "0xC0 0x81"));
54 // Not-enough in initial code point.
55 static const char notEnoughInitial[] = "\xF0";
56 CHECK(
57 testOmittedWindow(notEnoughInitial, JSMSG_NOT_ENOUGH_CODE_UNITS, "0xF0"));
59 // Not-enough at start of a fresh line.
60 static const char notEnoughFreshLine[] = "var x = 5;\n\xF0";
61 CHECK(testOmittedWindow(notEnoughFreshLine, JSMSG_NOT_ENOUGH_CODE_UNITS,
62 "0xF0"));
64 return true;
67 bool testUtf16() {
68 // Bad unit with nothing before it.
69 static const char16_t badLeadingUnit[] = u"\xDFFF";
70 CHECK(testOmittedWindow(badLeadingUnit, JSMSG_ILLEGAL_CHARACTER));
72 // Bad unit at start of a fresh line.
73 static const char16_t badStartingFreshLine[] = u"var x = 5;\n\xDFFF";
74 CHECK(testOmittedWindow(badStartingFreshLine, JSMSG_ILLEGAL_CHARACTER));
76 return true;
79 static bool startsWith(const char* str, const char* prefix) {
80 return std::strncmp(prefix, str, strlen(prefix)) == 0;
83 static bool equals(const char* str, const char* expected) {
84 return std::strcmp(str, expected) == 0;
87 JSScript* compile(const char16_t* chars, size_t len) {
88 JS::SourceText<char16_t> source;
89 MOZ_RELEASE_ASSERT(
90 source.init(cx, chars, len, JS::SourceOwnership::Borrowed));
92 JS::CompileOptions options(cx);
93 return JS::Compile(cx, options, source);
96 JSScript* compile(const char* chars, size_t len) {
97 JS::SourceText<Utf8Unit> source;
98 MOZ_RELEASE_ASSERT(
99 source.init(cx, chars, len, JS::SourceOwnership::Borrowed));
101 JS::CompileOptions options(cx);
102 return JS::Compile(cx, options, source);
105 template <typename CharT, size_t N>
106 bool testOmittedWindow(const CharT (&chars)[N], unsigned expectedErrorNumber,
107 const char* badCodeUnits = nullptr) {
108 JS::Rooted<JSScript*> script(cx, compile(chars, N - 1));
109 CHECK(!script);
111 JS::ExceptionStack exnStack(cx);
112 CHECK(JS::StealPendingExceptionStack(cx, &exnStack));
114 JS::ErrorReportBuilder report(cx);
115 CHECK(report.init(cx, exnStack, JS::ErrorReportBuilder::WithSideEffects));
117 const auto* errorReport = report.report();
119 CHECK(errorReport->errorNumber == expectedErrorNumber);
121 if (const auto& notes = errorReport->notes) {
122 CHECK(sizeof(CharT) == 1);
123 CHECK(badCodeUnits != nullptr);
125 auto iter = notes->begin();
126 CHECK(iter != notes->end());
128 const char* noteMessage = (*iter)->message().c_str();
130 // The prefix ought always be the same.
131 static constexpr char expectedPrefix[] =
132 "the code units comprising this invalid code point were: ";
133 constexpr size_t expectedPrefixLen = js_strlen(expectedPrefix);
135 CHECK(startsWith(noteMessage, expectedPrefix));
137 // The end of the prefix is the bad code units.
138 CHECK(equals(noteMessage + expectedPrefixLen, badCodeUnits));
140 ++iter;
141 CHECK(iter == notes->end());
142 } else {
143 CHECK(sizeof(CharT) == 2);
145 // UTF-16 encoding "errors" are not categorical errors, so the errors
146 // are just of the invalid-character sort, without an accompanying note
147 // spelling out a series of invalid code units.
148 CHECK(!badCodeUnits);
151 CHECK(!errorReport->linebuf());
153 return true;
155 END_TEST(testEmptyWindow)