Backed out 9 changesets (bug 1492090) for causing multiple xpcshell failures.

Backed out changeset 1e0705e94f79 (bug 1492090)
Backed out changeset aeee4b4981b4 (bug 1492090)
Backed out changeset ed83091dfdb5 (bug 1492090)
Backed out changeset d2604a65c523 (bug 1492090)
Backed out changeset e4aad0fb85b9 (bug 1492090)
Backed out changeset 4e7c4724e994 (bug 1492090)
Backed out changeset bc39eac4ecca (bug 1492090)
Backed out changeset 8e3b95812c39 (bug 1492090)
Backed out changeset ddb2eb1a1c62 (bug 1492090)
This commit is contained in:
Stanca Serban 2023-05-12 15:15:55 +03:00
Родитель 83a76a1352
Коммит d73773412a
48 изменённых файлов: 551 добавлений и 1192 удалений

Просмотреть файл

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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
@ -113,20 +113,24 @@ static bool Load(JSContext* cx, unsigned argc, JS::Value* vp) {
for (unsigned i = 0; i < args.length(); i++) {
JS::Rooted<JSString*> str(cx, JS::ToString(cx, args[i]));
if (!str) {
return false;
}
JS::UniqueChars filename = JS_EncodeStringToUTF8(cx, str);
if (!filename) {
if (!str) return false;
JS::UniqueChars filename = JS_EncodeStringToLatin1(cx, str);
if (!filename) return false;
FILE* file = fopen(filename.get(), "r");
if (!file) {
filename = JS_EncodeStringToUTF8(cx, str);
if (!filename) return false;
JS_ReportErrorUTF8(cx, "cannot open file '%s' for reading",
filename.get());
return false;
}
JS::CompileOptions options(cx);
JS::Rooted<JSScript*> script(
cx, JS::CompileUtf8Path(cx, options, filename.get()));
if (!script) {
return false;
}
options.setFileAndLine(filename.get(), 1);
JS::Rooted<JSScript*> script(cx, JS::CompileUtf8File(cx, options, file));
fclose(file);
if (!script) return false;
if (!JS_ExecuteScript(cx, script)) {
return false;
@ -255,7 +259,9 @@ void XPCShellEnvironment::ProcessFile(JSContext* cx, const char* filename,
* It's not interactive - just execute it.
*
* Support the UNIX #! shell hack; gobble the first line if it starts
* with '#'.
* with '#'. TODO - this isn't quite compatible with sharp variables,
* as a legal js program (using sharp variables) might start with '#'.
* But that would require multi-character lookahead.
*/
int ch = fgetc(file);
if (ch == '#') {

Просмотреть файл

@ -341,40 +341,6 @@ extern JS_PUBLIC_API bool StringIsASCII(const char* s);
*/
extern JS_PUBLIC_API bool StringIsASCII(mozilla::Span<const char> s);
/**
* Encode a narrow multibyte character string to a UTF-8 string.
*
* NOTE: Should only be used when interacting with POSIX/OS functions and not
* for encoding ASCII/Latin-1/etc. strings to UTF-8.
*/
extern JS_PUBLIC_API JS::UniqueChars EncodeNarrowToUtf8(JSContext* cx,
const char* chars);
/**
* Encode a wide string to a UTF-8 string.
*
* NOTE: Should only be used when interacting with Windows API functions.
*/
extern JS_PUBLIC_API JS::UniqueChars EncodeWideToUtf8(JSContext* cx,
const wchar_t* chars);
/**
* Encode a UTF-8 string to a narrow multibyte character string.
*
* NOTE: Should only be used when interacting with POSIX/OS functions and not
* for encoding UTF-8 to ASCII/Latin-1/etc. strings.
*/
extern JS_PUBLIC_API JS::UniqueChars EncodeUtf8ToNarrow(JSContext* cx,
const char* chars);
/**
* Encode a UTF-8 string to a wide string.
*
* NOTE: Should only be used when interacting with Windows API functions.
*/
extern JS_PUBLIC_API JS::UniqueWideChars EncodeUtf8ToWide(JSContext* cx,
const char* chars);
} // namespace JS
inline void JS_free(JS::Latin1CharsZ& ptr) { js_free((void*)ptr.get()); }

Просмотреть файл

@ -125,8 +125,9 @@ extern JS_PUBLIC_API bool Evaluate(JSContext* cx,
/**
* Evaluate the UTF-8 contents of the file at the given path, and return the
* completion value in |rval|. (The path itself is UTF-8 encoded, too.) If
* the contents contain any malformed UTF-8, an error is reported.
* completion value in |rval|. (The path itself is in the system encoding, not
* [necessarily] UTF-8.) If the contents contain any malformed UTF-8, an error
* is reported.
*/
extern JS_PUBLIC_API bool EvaluateUtf8Path(
JSContext* cx, const ReadOnlyCompileOptions& options, const char* filename,

Просмотреть файл

@ -123,12 +123,8 @@ class JS_PUBLIC_API TransitiveCompileOptions {
protected:
// non-POD options:
// UTF-8 encoded file name.
const char* filename_ = nullptr;
// UTF-8 encoded introducer file name.
const char* introducerFilename_ = nullptr;
const char16_t* sourceMapURL_ = nullptr;
// POD options:
@ -237,8 +233,8 @@ class JS_PUBLIC_API TransitiveCompileOptions {
bool deoptimizeModuleGlobalVars = false;
/**
* |introductionType| is a statically allocated C string. See JSScript.h
* for more information.
* |introductionType| is a statically allocated C string: one of "eval",
* "Function", or "GeneratorFunction".
*/
const char* introductionType = nullptr;

Просмотреть файл

@ -111,7 +111,7 @@ class JSErrorBase {
JS::ConstUTF8CharsZ message_;
public:
// The UTF-8 encoded source file name, URL, etc., or null.
// Source file name, URL, etc., or null.
const char* filename;
// Unique identifier for the script source.

Просмотреть файл

@ -632,10 +632,9 @@ struct FreePolicy {
void operator()(const void* ptr) { js_free(const_cast<void*>(ptr)); }
};
using UniqueChars = mozilla::UniquePtr<char[], JS::FreePolicy>;
using UniqueTwoByteChars = mozilla::UniquePtr<char16_t[], JS::FreePolicy>;
using UniqueLatin1Chars = mozilla::UniquePtr<JS::Latin1Char[], JS::FreePolicy>;
using UniqueWideChars = mozilla::UniquePtr<wchar_t[], JS::FreePolicy>;
typedef mozilla::UniquePtr<char[], JS::FreePolicy> UniqueChars;
typedef mozilla::UniquePtr<char16_t[], JS::FreePolicy> UniqueTwoByteChars;
typedef mozilla::UniquePtr<JS::Latin1Char[], JS::FreePolicy> UniqueLatin1Chars;
} // namespace JS

Просмотреть файл

@ -400,12 +400,6 @@ MSG_DEF(JSMSG_BAD_TRAILING_UTF8_UNIT, 1, JSEXN_SYNTAXERR, "bad trailing UTF-8 b
MSG_DEF(JSMSG_FORBIDDEN_UTF8_CODE_POINT,2,JSEXN_SYNTAXERR, "{0} isn't a valid code point because {1}")
MSG_DEF(JSMSG_BAD_CODE_UNITS, 1, JSEXN_NOTE, "the code units comprising this invalid code point were: {0}")
// System encoding errors
MSG_DEF(JSMSG_CANT_CONVERT_TO_NARROW, 0, JSEXN_NOTE, "can't convert to narrow string")
MSG_DEF(JSMSG_CANT_CONVERT_TO_WIDE, 0, JSEXN_NOTE, "can't convert to wide string")
MSG_DEF(JSMSG_CANT_CONVERT_WIDE_TO_UTF8, 0, JSEXN_NOTE, "can't convert wide string to UTF-8")
MSG_DEF(JSMSG_CANT_CONVERT_UTF8_TO_WIDE, 0, JSEXN_NOTE, "can't convert UTF-8 to wide string")
// SmooshMonkey
MSG_DEF(JSMSG_SMOOSH_COMPILE_ERROR, 1, JSEXN_SYNTAXERR, "{0}")
MSG_DEF(JSMSG_SMOOSH_UNIMPLEMENTED, 1, JSEXN_INTERNALERR, "{0}")

Просмотреть файл

@ -65,7 +65,6 @@ using JS::Latin1Char;
using JS::UniqueChars;
using JS::UniqueLatin1Chars;
using JS::UniqueTwoByteChars;
using JS::UniqueWideChars;
using JS::Ok;
using JS::OOM;

Просмотреть файл

@ -267,7 +267,7 @@ class NodeBuilder {
FrontendContext* fc;
frontend::Parser<frontend::FullParseHandler, char16_t>* parser;
bool saveLoc; /* save source location information? */
char const* src; /* UTF-8 encoded source filename or null */
char const* src; /* source filename or null */
RootedValue srcval; /* source filename JS value or null */
public:
@ -276,7 +276,7 @@ class NodeBuilder {
[[nodiscard]] bool init() {
if (src) {
if (!atomValueUtf8(src, &srcval)) {
if (!atomValue(src, &srcval)) {
return false;
}
} else {
@ -292,8 +292,6 @@ class NodeBuilder {
private:
[[nodiscard]] bool atomValue(const char* s, MutableHandleValue dst) {
MOZ_ASSERT(JS::StringIsASCII(s));
/*
* Bug 575416: instead of Atomize, lookup constant atoms in tbl file
*/
@ -306,16 +304,6 @@ class NodeBuilder {
return true;
}
[[nodiscard]] bool atomValueUtf8(const char* s, MutableHandleValue dst) {
Rooted<JSAtom*> atom(cx, AtomizeUTF8Chars(cx, s, strlen(s)));
if (!atom) {
return false;
}
dst.setString(atom);
return true;
}
[[nodiscard]] bool newObject(MutableHandleObject dst) {
Rooted<PlainObject*> nobj(cx, NewPlainObject(cx));
if (!nobj) {
@ -3654,7 +3642,7 @@ static bool reflect_parse(JSContext* cx, uint32_t argc, Value* vp) {
return false;
}
filename = StringToNewUTF8CharsZ(cx, *str);
filename = EncodeLatin1(cx, str);
if (!filename) {
return false;
}

Просмотреть файл

@ -3727,7 +3727,7 @@ bool IterativeFailureTest::testThread(unsigned thread) {
fprintf(stderr, " error while trying to print exception, giving up\n");
return false;
}
UniqueChars bytes(JS_EncodeStringToUTF8(cx, str));
UniqueChars bytes(JS_EncodeStringToLatin1(cx, str));
if (!bytes) {
return false;
}
@ -4173,11 +4173,6 @@ static bool DumpHeap(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
FILE* dumpFile = stdout;
auto closeFile = mozilla::MakeScopeExit([&dumpFile] {
if (dumpFile != stdout) {
fclose(dumpFile);
}
});
if (args.length() > 1) {
RootedObject callee(cx, &args.callee());
@ -4191,27 +4186,17 @@ static bool DumpHeap(JSContext* cx, unsigned argc, Value* vp) {
return false;
}
if (!fuzzingSafe) {
UniqueChars fileNameBytes = JS_EncodeStringToUTF8(cx, str);
UniqueChars fileNameBytes = JS_EncodeStringToLatin1(cx, str);
if (!fileNameBytes) {
return false;
}
#ifdef XP_WIN
UniqueWideChars wideFileNameBytes =
JS::EncodeUtf8ToWide(cx, fileNameBytes.get());
if (!wideFileNameBytes) {
return false;
}
dumpFile = _wfopen(wideFileNameBytes.get(), L"w");
#else
UniqueChars narrowFileNameBytes =
JS::EncodeUtf8ToNarrow(cx, fileNameBytes.get());
if (!narrowFileNameBytes) {
return false;
}
dumpFile = fopen(narrowFileNameBytes.get(), "w");
#endif
dumpFile = fopen(fileNameBytes.get(), "w");
if (!dumpFile) {
JS_ReportErrorUTF8(cx, "can't open %s", fileNameBytes.get());
fileNameBytes = JS_EncodeStringToLatin1(cx, str);
if (!fileNameBytes) {
return false;
}
JS_ReportErrorLatin1(cx, "can't open %s", fileNameBytes.get());
return false;
}
}
@ -4219,6 +4204,10 @@ static bool DumpHeap(JSContext* cx, unsigned argc, Value* vp) {
js::DumpHeap(cx, dumpFile, js::IgnoreNurseryObjects);
if (dumpFile != stdout) {
fclose(dumpFile);
}
args.rval().setUndefined();
return true;
}
@ -4402,8 +4391,7 @@ static bool ReadGeckoInterpProfilingStack(JSContext* cx, unsigned argc,
}
// Skip fake JS frame pushed for js::RunScript by GeckoProfilerEntryMarker.
const char* dynamicStr = frame.dynamicString();
if (!dynamicStr) {
if (!frame.dynamicString()) {
continue;
}
@ -4413,8 +4401,7 @@ static bool ReadGeckoInterpProfilingStack(JSContext* cx, unsigned argc,
}
Rooted<JSString*> dynamicString(
cx, JS_NewStringCopyUTF8Z(
cx, JS::ConstUTF8CharsZ(dynamicStr, strlen(dynamicStr))));
cx, JS_NewStringCopyZ(cx, frame.dynamicString()));
if (!dynamicString) {
return false;
}
@ -7532,8 +7519,7 @@ static bool GetLcovInfo(JSContext* cx, unsigned argc, Value* vp) {
return false;
}
JSString* str =
JS_NewStringCopyUTF8N(cx, JS::UTF8Chars(content.get(), length));
JSString* str = JS_NewStringCopyN(cx, content.get(), length);
if (!str) {
return false;
}

Просмотреть файл

@ -9,7 +9,7 @@
#include <stdint.h> // uint32_t
#include "jsapi.h" // JS_NewPlainObject, JS_WrapValue
#include "js/CharacterEncoding.h" // JS_EncodeStringToUTF8
#include "js/CharacterEncoding.h" // JS_EncodeStringToLatin1
#include "js/CompileOptions.h" // JS::CompileOptions
#include "js/Conversions.h" // JS::ToBoolean, JS::ToString, JS::ToUint32, JS::ToInt32
#include "js/PropertyAndElement.h" // JS_GetProperty, JS_DefineProperty
@ -50,7 +50,7 @@ bool js::ParseCompileOptions(JSContext* cx, JS::CompileOptions& options,
return false;
}
if (fileNameBytes) {
*fileNameBytes = JS_EncodeStringToUTF8(cx, s);
*fileNameBytes = JS_EncodeStringToLatin1(cx, s);
if (!*fileNameBytes) {
return false;
}

Просмотреть файл

@ -177,17 +177,24 @@ JSObject* Library::Create(JSContext* cx, HandleValue path,
PRLibrary* library = PR_LoadLibraryWithFlags(libSpec, PR_LD_NOW);
if (!library) {
constexpr size_t MaxErrorLength = 1024;
char error[MaxErrorLength] = "Cannot get error from NSPR.";
#define MAX_ERROR_LEN 1024
char error[MAX_ERROR_LEN] = "Cannot get error from NSPR.";
uint32_t errorLen = PR_GetErrorTextLength();
if (errorLen && errorLen < MaxErrorLength) {
if (errorLen && errorLen < MAX_ERROR_LEN) {
PR_GetErrorText(error);
}
#undef MAX_ERROR_LEN
if (JS::UniqueChars errorUtf8 = JS::EncodeNarrowToUtf8(cx, error)) {
if (JS::UniqueChars pathChars = JS_EncodeStringToUTF8(cx, pathStr)) {
JS_ReportErrorUTF8(cx, "couldn't open library %s: %s", pathChars.get(),
errorUtf8.get());
if (JS::StringIsASCII(error)) {
if (JS::UniqueChars pathCharsUTF8 = JS_EncodeStringToUTF8(cx, pathStr)) {
JS_ReportErrorUTF8(cx, "couldn't open library %s: %s",
pathCharsUTF8.get(), error);
}
} else {
if (JS::UniqueChars pathCharsLatin1 =
JS_EncodeStringToLatin1(cx, pathStr)) {
JS_ReportErrorLatin1(cx, "couldn't open library %s: %s",
pathCharsLatin1.get(), error);
}
}
return nullptr;

Просмотреть файл

@ -370,7 +370,7 @@ bool js::ParseEvalOptions(JSContext* cx, HandleValue value,
if (!url_str) {
return false;
}
UniqueChars url_bytes = JS_EncodeStringToUTF8(cx, url_str);
UniqueChars url_bytes = JS_EncodeStringToLatin1(cx, url_str);
if (!url_bytes) {
return false;
}
@ -2439,8 +2439,7 @@ static bool RememberSourceURL(JSContext* cx, HandleScript script) {
return true;
}
RootedString filenameString(cx,
AtomizeUTF8Chars(cx, filename, strlen(filename)));
RootedString filenameString(cx, JS_AtomizeString(cx, filename));
if (!filenameString) {
return false;
}
@ -5423,8 +5422,7 @@ class MOZ_STACK_CLASS Debugger::ScriptQuery : public Debugger::QueryBase {
// Compute urlCString and displayURLChars, if a url or displayURL was
// given respectively.
if (url.isString()) {
Rooted<JSString*> str(cx, url.toString());
urlCString = JS_EncodeStringToUTF8(cx, str);
urlCString = JS_EncodeStringToLatin1(cx, url.toString());
if (!urlCString) {
return false;
}

Просмотреть файл

@ -18,7 +18,7 @@
#include "vm/JSContext.h" // for ProtectedDataContextArg, JSContext
#include "vm/JSScript.h" // for JSScript
#include "vm/Realm.h" // for AutoRealm, Realm
#include "vm/Warnings.h" // for WarnNumberUTF8
#include "vm/Warnings.h" // for WarnNumberLatin1
#include "gc/StableCellHasher-inl.h"
#include "vm/Realm-inl.h" // for AutoRealm::AutoRealm
@ -76,13 +76,14 @@ bool EnterDebuggeeNoExecute::reportIfFoundInStack(JSContext* cx,
const char* filename = script->filename() ? script->filename() : "(none)";
char linenoStr[15];
SprintfLiteral(linenoStr, "%u", script->lineno());
// FIXME: filename should be UTF-8 (bug 987069).
if (warning) {
return WarnNumberUTF8(cx, JSMSG_DEBUGGEE_WOULD_RUN, filename,
linenoStr);
return WarnNumberLatin1(cx, JSMSG_DEBUGGEE_WOULD_RUN, filename,
linenoStr);
}
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr,
JSMSG_DEBUGGEE_WOULD_RUN, filename, linenoStr);
JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr,
JSMSG_DEBUGGEE_WOULD_RUN, filename, linenoStr);
return false;
}
}

Просмотреть файл

@ -347,12 +347,11 @@ bool DebuggerScript::CallData::getUrl() {
if (script->filename()) {
JSString* str;
if (const char* introducer = script->scriptSource()->introducerFilename()) {
str =
NewStringCopyUTF8N(cx, JS::UTF8Chars(introducer, strlen(introducer)));
if (script->scriptSource()->introducerFilename()) {
str = NewStringCopyZ<CanGC>(cx,
script->scriptSource()->introducerFilename());
} else {
const char* filename = script->filename();
str = NewStringCopyUTF8N(cx, JS::UTF8Chars(filename, strlen(filename)));
str = NewStringCopyZ<CanGC>(cx, script->filename());
}
if (!str) {
return false;

Просмотреть файл

@ -301,9 +301,8 @@ class DebuggerSourceGetURLMatcher {
ReturnType match(Handle<ScriptSourceObject*> sourceObject) {
ScriptSource* ss = sourceObject->source();
MOZ_ASSERT(ss);
if (const char* filename = ss->filename()) {
JS::UTF8Chars utf8chars(filename, strlen(filename));
JSString* str = NewStringCopyUTF8N(cx_, utf8chars);
if (ss->filename()) {
JSString* str = NewStringCopyZ<CanGC>(cx_, ss->filename());
return Some(str);
}
return Nothing();

Просмотреть файл

@ -1,3 +1,3 @@
// |jit-test| error:unsafe filename:
// |jit-test| error:unsafe filename: (invalid UTF-8 filename)
setTestFilenameValidationCallback();
evaluate("throw 2", {fileName: "\uDEFF"});

Просмотреть файл

@ -2,9 +2,10 @@ if (typeof disassemble !== "function") {
quit();
}
// Invalid UTF-8 should be replaced with U+FFFD.
const out = evaluate(`
disassemble();
`, {
fileName: String.fromCharCode(3823486100),
});
assertEq(out.includes(`"file": "\uC494",`), true);
assertEq(out.includes(`"file": "\uFFFD",`), true);

Просмотреть файл

@ -1,5 +1,13 @@
// |jit-test| skip-if: isLcovEnabled()
// Skip this test on Lcov because the invalid filename breaks the test harness.
// Some filename handling code still uses latin1, and some characters are
// replaced with REPLACEMENT CHARACTER (U+FFFD).
//
// FIXME: bug 1492090
const backtrace = evaluate(`
this.getBacktrace(this);
`, { fileName: "\u86D9" });
assertEq(backtrace.includes(`["\u86D9":2:5]`), true);
assertEq(backtrace.includes(`["\uFFFD":2:5]`), true);

Просмотреть файл

@ -22,10 +22,5 @@ testUrl(null, "debugger eval code");
testUrl({ url: undefined }, "debugger eval code");
testUrl({ url: null }, "null");
testUrl({ url: 5 }, "5");
testUrl({ url: "" }, "");
testUrl({ url: "test" }, "test");
testUrl({ url: "Ðëßþ" }, "Ðëßþ");
testUrl({ url: "тест" }, "тест");
testUrl({ url: "テスト" }, "テスト");
testUrl({ url: "\u{1F9EA}" }, "\u{1F9EA}");
assertEq(count, 0);

Просмотреть файл

@ -22,10 +22,5 @@ testUrl(null, "debugger eval code");
testUrl({ url: undefined }, "debugger eval code");
testUrl({ url: null }, "null");
testUrl({ url: 5 }, "5");
testUrl({ url: "" }, "");
testUrl({ url: "test" }, "test");
testUrl({ url: "Ðëßþ" }, "Ðëßþ");
testUrl({ url: "тест" }, "тест");
testUrl({ url: "テスト" }, "テスト");
testUrl({ url: "\u{1F9EA}" }, "\u{1F9EA}");
assertEq(count, 0);

Просмотреть файл

@ -20,10 +20,5 @@ testUrl(null, "debugger eval code");
testUrl({ url: undefined }, "debugger eval code");
testUrl({ url: null }, "null");
testUrl({ url: 5 }, "5");
testUrl({ url: "" }, "");
testUrl({ url: "test" }, "test");
testUrl({ url: "Ðëßþ" }, "Ðëßþ");
testUrl({ url: "тест" }, "тест");
testUrl({ url: "テスト" }, "テスト");
testUrl({ url: "\u{1F9EA}" }, "\u{1F9EA}");
assertEq(count, 0);

Просмотреть файл

@ -1,29 +0,0 @@
// executeInGlobalWithBindings correctly handles optional custom url option
var g = newGlobal({newCompartment: true});
var dbg = new Debugger(g);
var debuggee = dbg.getDebuggees()[0];
var count = 0;
function testUrl (options, expected) {
count++;
dbg.onNewScript = function(script){
dbg.onNewScript = undefined;
assertEq(script.url, expected);
count--;
};
debuggee.executeInGlobalWithBindings("", {}, options);
}
testUrl(undefined, "debugger eval code");
testUrl(null, "debugger eval code");
testUrl({ url: undefined }, "debugger eval code");
testUrl({ url: null }, "null");
testUrl({ url: 5 }, "5");
testUrl({ url: "" }, "");
testUrl({ url: "test" }, "test");
testUrl({ url: "Ðëßþ" }, "Ðëßþ");
testUrl({ url: "тест" }, "тест");
testUrl({ url: "テスト" }, "テスト");
testUrl({ url: "\u{1F9EA}" }, "\u{1F9EA}");
assertEq(count, 0);

Просмотреть файл

@ -168,9 +168,8 @@ class JSAPIRuntimeTest : public JSAPITest {
JS::MutableHandleValue vp);
JSAPITestString jsvalToSource(JS::HandleValue v) {
JS::Rooted<JSString*> str(cx, JS_ValueToSource(cx, v));
if (str) {
if (JS::UniqueChars bytes = JS_EncodeStringToUTF8(cx, str)) {
if (JSString* str = JS_ValueToSource(cx, v)) {
if (JS::UniqueChars bytes = JS_EncodeStringToLatin1(cx, str)) {
return JSAPITestString(bytes.get());
}
}
@ -329,7 +328,7 @@ class JSAPIRuntimeTest : public JSAPITest {
JS::RootedValue v(cx);
JS_GetPendingException(cx, &v);
JS_ClearPendingException(cx);
JS::Rooted<JSString*> s(cx, JS::ToString(cx, v));
JSString* s = JS::ToString(cx, v);
if (s) {
if (JS::UniqueChars bytes = JS_EncodeStringToLatin1(cx, s)) {
message += bytes.get();
@ -348,13 +347,12 @@ class JSAPIRuntimeTest : public JSAPITest {
static bool print(JSContext* cx, unsigned argc, JS::Value* vp) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
JS::Rooted<JSString*> str(cx);
for (unsigned i = 0; i < args.length(); i++) {
str = JS::ToString(cx, args[i]);
JSString* str = JS::ToString(cx, args[i]);
if (!str) {
return false;
}
JS::UniqueChars bytes = JS_EncodeStringToUTF8(cx, str);
JS::UniqueChars bytes = JS_EncodeStringToLatin1(cx, str);
if (!bytes) {
return false;
}

Просмотреть файл

@ -323,15 +323,9 @@ void js::ErrorToException(JSContext* cx, JSErrorReport* reportp,
return;
}
Rooted<JSString*> fileName(cx);
if (const char* filename = reportp->filename) {
fileName =
JS_NewStringCopyUTF8N(cx, JS::UTF8Chars(filename, strlen(filename)));
if (!fileName) {
return;
}
} else {
fileName = cx->emptyString();
RootedString fileName(cx, JS_NewStringCopyZ(cx, reportp->filename));
if (!fileName) {
return;
}
uint32_t sourceId = reportp->sourceId;

Просмотреть файл

@ -10,7 +10,6 @@
MSG_DEF(JSSMSG_NOT_AN_ERROR, 0, JSEXN_ERR, "<Error #0 is reserved>")
MSG_DEF(JSSMSG_CANT_OPEN, 2, JSEXN_ERR, "can't open {0}: {1}")
MSG_DEF(JSSMSG_CANT_READ, 2, JSEXN_ERR, "can't read {0}: {1}")
MSG_DEF(JSSMSG_LINE2PC_USAGE, 0, JSEXN_ERR, "usage: line2pc [fun] line")
MSG_DEF(JSSMSG_FILE_SCRIPTS_ONLY, 0, JSEXN_ERR, "only works on JS scripts read from files")
MSG_DEF(JSSMSG_UNEXPECTED_EOF, 1, JSEXN_ERR, "unexpected EOF in {0}")

Просмотреть файл

@ -459,7 +459,7 @@ JSObject* ModuleLoader::loadAndParse(JSContext* cx, HandleString pathArg) {
return module;
}
UniqueChars filename = JS_EncodeStringToUTF8(cx, path);
UniqueChars filename = JS_EncodeStringToLatin1(cx, path);
if (!filename) {
return nullptr;
}

Просмотреть файл

@ -8,7 +8,6 @@
#include "shell/OSObject.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/ScopeExit.h"
#include "mozilla/TextUtils.h"
@ -18,7 +17,6 @@
# include <direct.h>
# include <process.h>
# include <string.h>
# include <wchar.h>
# include <windows.h>
#elif __wasi__
# include <dirent.h>
@ -95,67 +93,6 @@ bool IsAbsolutePath(JSLinearString* filename) {
return length > 0 && CharAt(filename, 0) == PathSeparator;
}
static UniqueChars DirectoryName(JSContext* cx, const char* path) {
#ifdef XP_WIN
UniqueWideChars widePath = JS::EncodeUtf8ToWide(cx, path);
if (!widePath) {
return nullptr;
}
wchar_t dirName[PATH_MAX + 1];
wchar_t* drive = nullptr;
wchar_t* fileName = nullptr;
wchar_t* fileExt = nullptr;
// The docs say it can return EINVAL, but the compiler says it's void
_wsplitpath(widePath.get(), drive, dirName, fileName, fileExt);
return JS::EncodeWideToUtf8(cx, dirName);
#else
UniqueChars narrowPath = JS::EncodeUtf8ToNarrow(cx, path);
if (!narrowPath) {
return nullptr;
}
char dirName[PATH_MAX + 1];
strncpy(dirName, narrowPath.get(), PATH_MAX);
if (dirName[PATH_MAX - 1] != '\0') {
return nullptr;
}
# ifdef __wasi__
// dirname() seems not to behave properly with wasi-libc; so we do our own
// simple thing here.
char* p = dirName + strlen(dirName);
bool found = false;
while (p > dirName) {
if (*p == '/') {
found = true;
*p = '\0';
break;
}
p--;
}
if (!found) {
// There's no '/'. Possible cases are the following:
// * "."
// * ".."
// * filename only
//
// dirname() returns "." for all cases.
dirName[0] = '.';
dirName[1] = '\0';
}
# else
// dirname(dirName) might return dirName, or it might return a
// statically-allocated string
memmove(dirName, dirname(dirName), strlen(dirName) + 1);
# endif
return JS::EncodeNarrowToUtf8(cx, dirName);
#endif
}
/*
* Resolve a (possibly) relative filename to an absolute path. If
* |scriptRelative| is true, then the result will be relative to the directory
@ -186,7 +123,7 @@ JSString* ResolvePath(JSContext* cx, HandleString filenameStr,
return str;
}
UniqueChars filename = JS_EncodeStringToUTF8(cx, str);
UniqueChars filename = JS_EncodeStringToLatin1(cx, str);
if (!filename) {
return nullptr;
}
@ -208,176 +145,151 @@ JSString* ResolvePath(JSContext* cx, HandleString filenameStr,
}
}
UniqueChars path;
char buffer[PATH_MAX + 1];
if (resolveMode == ScriptRelative) {
path = DirectoryName(cx, scriptFilename.get());
} else {
path = GetCWD(cx);
}
if (!path) {
return nullptr;
}
size_t pathLen = strlen(path.get());
size_t filenameLen = strlen(filename.get());
size_t resultLen = pathLen + 1 + filenameLen;
UniqueChars result = cx->make_pod_array<char>(resultLen + 1);
if (!result) {
return nullptr;
}
memcpy(result.get(), path.get(), pathLen);
result[pathLen] = '/';
memcpy(result.get() + pathLen + 1, filename.get(), filenameLen);
result[pathLen + 1 + filenameLen] = '\0';
return JS_NewStringCopyUTF8N(cx, JS::UTF8Chars(result.get(), resultLen));
}
FILE* OpenFile(JSContext* cx, const char* filename, const char* mode) {
#ifdef XP_WIN
// Maximum valid mode string is "w+xb". Longer strings or strings
// containing invalid input lead to undefined behavior.
constexpr size_t MaxValidModeLength = 4;
wchar_t wideMode[MaxValidModeLength + 1] = {0};
for (size_t i = 0; i < MaxValidModeLength && mode[i] != '\0'; i++) {
wideMode[i] = mode[i] & 0x7f;
}
UniqueWideChars wideFilename = JS::EncodeUtf8ToWide(cx, filename);
if (!wideFilename) {
return nullptr;
}
FILE* file = _wfopen(wideFilename.get(), wideMode);
// The docs say it can return EINVAL, but the compiler says it's void
_splitpath(scriptFilename.get(), nullptr, buffer, nullptr, nullptr);
#else
UniqueChars narrowFilename = JS::EncodeUtf8ToNarrow(cx, filename);
if (!narrowFilename) {
return nullptr;
}
FILE* file = fopen(narrowFilename.get(), mode);
#endif
if (!file) {
if (UniqueChars error = SystemErrorMessage(cx, errno)) {
JS_ReportErrorNumberUTF8(cx, my_GetErrorMessage, nullptr,
JSSMSG_CANT_OPEN, filename, error.get());
strncpy(buffer, scriptFilename.get(), PATH_MAX);
if (buffer[PATH_MAX - 1] != '\0') {
return nullptr;
}
return nullptr;
}
return file;
}
bool ReadFile(JSContext* cx, const char* filename, FILE* file, char* buffer,
size_t length) {
size_t cc = fread(buffer, sizeof(char), length, file);
if (cc != length) {
if (ptrdiff_t(cc) < 0) {
if (UniqueChars error = SystemErrorMessage(cx, errno)) {
JS_ReportErrorNumberUTF8(cx, my_GetErrorMessage, nullptr,
JSSMSG_CANT_READ, filename, error.get());
# ifdef __wasi__
// dirname() seems not to behave properly with wasi-libc; so we do our own
// simple thing here.
char* p = buffer + strlen(buffer);
while (p > buffer) {
if (*p == '/') {
*p = '\0';
break;
}
} else {
JS_ReportErrorUTF8(cx, "can't read %s: short read", filename);
p--;
}
# else
// dirname(buffer) might return buffer, or it might return a
// statically-allocated string
memmove(buffer, dirname(buffer), strlen(buffer) + 1);
# endif
#endif
} else {
const char* cwd = getcwd(buffer, PATH_MAX);
if (!cwd) {
return nullptr;
}
return false;
}
return true;
}
bool FileSize(JSContext* cx, const char* filename, FILE* file, size_t* size) {
if (fseek(file, 0, SEEK_END) != 0) {
JS_ReportErrorUTF8(cx, "can't seek end of %s", filename);
return false;
}
size_t len = ftell(file);
if (fseek(file, 0, SEEK_SET) != 0) {
JS_ReportErrorUTF8(cx, "can't seek start of %s", filename);
return false;
size_t len = strlen(buffer);
buffer[len] = '/';
strncpy(buffer + len + 1, filename.get(), sizeof(buffer) - (len + 1));
if (buffer[PATH_MAX] != '\0') {
return nullptr;
}
*size = len;
return true;
return JS_NewStringCopyZ(cx, buffer);
}
JSObject* FileAsTypedArray(JSContext* cx, JS::HandleString pathnameStr) {
UniqueChars pathname = JS_EncodeStringToUTF8(cx, pathnameStr);
UniqueChars pathname = JS_EncodeStringToLatin1(cx, pathnameStr);
if (!pathname) {
return nullptr;
}
FILE* file = OpenFile(cx, pathname.get(), "rb");
FILE* file = fopen(pathname.get(), "rb");
if (!file) {
/*
* Use Latin1 variant here because the encoding of the return value of
* strerror function can be non-UTF-8.
*/
JS_ReportErrorLatin1(cx, "can't open %s: %s", pathname.get(),
strerror(errno));
return nullptr;
}
AutoCloseFile autoClose(file);
size_t len;
if (!FileSize(cx, pathname.get(), file, &len)) {
return nullptr;
RootedObject obj(cx);
if (fseek(file, 0, SEEK_END) != 0) {
pathname = JS_EncodeStringToUTF8(cx, pathnameStr);
if (!pathname) {
return nullptr;
}
JS_ReportErrorUTF8(cx, "can't seek end of %s", pathname.get());
} else {
size_t len = ftell(file);
if (fseek(file, 0, SEEK_SET) != 0) {
pathname = JS_EncodeStringToUTF8(cx, pathnameStr);
if (!pathname) {
return nullptr;
}
JS_ReportErrorUTF8(cx, "can't seek start of %s", pathname.get());
} else {
if (len > ArrayBufferObject::MaxByteLength) {
JS_ReportErrorUTF8(cx, "file %s is too large for a Uint8Array",
pathname.get());
return nullptr;
}
obj = JS_NewUint8Array(cx, len);
if (!obj) {
return nullptr;
}
js::TypedArrayObject& ta = obj->as<js::TypedArrayObject>();
if (ta.isSharedMemory()) {
// Must opt in to use shared memory. For now, don't.
//
// (It is incorrect to read into the buffer without
// synchronization since that can create a race. A
// lock here won't fix it - both sides must
// participate. So what one must do is to create a
// temporary buffer, read into that, and use a
// race-safe primitive to copy memory into the
// buffer.)
pathname = JS_EncodeStringToUTF8(cx, pathnameStr);
if (!pathname) {
return nullptr;
}
JS_ReportErrorUTF8(cx, "can't read %s: shared memory buffer",
pathname.get());
return nullptr;
}
char* buf = static_cast<char*>(ta.dataPointerUnshared());
size_t cc = fread(buf, 1, len, file);
if (cc != len) {
if (ptrdiff_t(cc) < 0) {
/*
* Use Latin1 variant here because the encoding of the return
* value of strerror function can be non-UTF-8.
*/
JS_ReportErrorLatin1(cx, "can't read %s: %s", pathname.get(),
strerror(errno));
} else {
pathname = JS_EncodeStringToUTF8(cx, pathnameStr);
if (!pathname) {
return nullptr;
}
JS_ReportErrorUTF8(cx, "can't read %s: short read", pathname.get());
}
obj = nullptr;
}
}
}
if (len > ArrayBufferObject::MaxByteLength) {
JS_ReportErrorUTF8(cx, "file %s is too large for a Uint8Array",
pathname.get());
return nullptr;
}
JS::Rooted<JSObject*> obj(cx, JS_NewUint8Array(cx, len));
if (!obj) {
return nullptr;
}
js::TypedArrayObject& ta = obj->as<js::TypedArrayObject>();
if (ta.isSharedMemory()) {
// Must opt in to use shared memory. For now, don't.
//
// (It is incorrect to read into the buffer without
// synchronization since that can create a race. A
// lock here won't fix it - both sides must
// participate. So what one must do is to create a
// temporary buffer, read into that, and use a
// race-safe primitive to copy memory into the
// buffer.)
JS_ReportErrorUTF8(cx, "can't read %s: shared memory buffer",
pathname.get());
return nullptr;
}
char* buf = static_cast<char*>(ta.dataPointerUnshared());
if (!ReadFile(cx, pathname.get(), file, buf, len)) {
return nullptr;
}
return obj;
}
/**
* Return the current working directory or |null| on failure.
*/
UniqueChars GetCWD(JSContext* cx) {
#ifdef XP_WIN
wchar_t buffer[PATH_MAX + 1];
const wchar_t* cwd = _wgetcwd(buffer, PATH_MAX);
if (!cwd) {
return nullptr;
}
return JS::EncodeWideToUtf8(cx, buffer);
#else
UniqueChars GetCWD() {
char buffer[PATH_MAX + 1];
const char* cwd = getcwd(buffer, PATH_MAX);
if (!cwd) {
return nullptr;
return UniqueChars();
}
return JS::EncodeNarrowToUtf8(cx, buffer);
#endif
return js::DuplicateString(buffer);
}
static bool ReadFile(JSContext* cx, unsigned argc, Value* vp,
PathResolutionMode resolveMode) {
bool scriptRelative) {
CallArgs args = CallArgsFromVp(argc, vp);
if (args.length() < 1 || args.length() > 2) {
@ -394,9 +306,10 @@ static bool ReadFile(JSContext* cx, unsigned argc, Value* vp,
return false;
}
JS::Rooted<JSString*> givenPath(cx, args[0].toString());
JS::Rooted<JSString*> str(cx,
js::shell::ResolvePath(cx, givenPath, resolveMode));
RootedString givenPath(cx, args[0].toString());
RootedString str(
cx, js::shell::ResolvePath(
cx, givenPath, scriptRelative ? ScriptRelative : RootRelative));
if (!str) {
return false;
}
@ -428,12 +341,12 @@ static bool ReadFile(JSContext* cx, unsigned argc, Value* vp,
}
static bool osfile_readFile(JSContext* cx, unsigned argc, Value* vp) {
return ReadFile(cx, argc, vp, RootRelative);
return ReadFile(cx, argc, vp, false);
}
static bool osfile_readRelativeToScript(JSContext* cx, unsigned argc,
Value* vp) {
return ReadFile(cx, argc, vp, ScriptRelative);
return ReadFile(cx, argc, vp, true);
}
static bool ListDir(JSContext* cx, unsigned argc, Value* vp,
@ -457,7 +370,7 @@ static bool ListDir(JSContext* cx, unsigned argc, Value* vp,
return false;
}
UniqueChars pathname = JS_EncodeStringToUTF8(cx, str);
UniqueChars pathname = JS_EncodeStringToLatin1(cx, str);
if (!pathname) {
JS_ReportErrorASCII(cx, "os.file.listDir cannot convert path to Latin1");
return false;
@ -556,13 +469,19 @@ static bool osfile_writeTypedArrayToFile(JSContext* cx, unsigned argc,
return false;
}
UniqueChars filename = JS_EncodeStringToUTF8(cx, str);
UniqueChars filename = JS_EncodeStringToLatin1(cx, str);
if (!filename) {
return false;
}
FILE* file = OpenFile(cx, filename.get(), "wb");
FILE* file = fopen(filename.get(), "wb");
if (!file) {
/*
* Use Latin1 variant here because the encoding of the return value of
* strerror function can be non-UTF-8.
*/
JS_ReportErrorLatin1(cx, "can't open %s: %s", filename.get(),
strerror(errno));
return false;
}
AutoCloseFile autoClose(file);
@ -573,6 +492,10 @@ static bool osfile_writeTypedArrayToFile(JSContext* cx, unsigned argc,
// Must opt in to use shared memory. For now, don't.
//
// See further comments in FileAsTypedArray, above.
filename = JS_EncodeStringToUTF8(cx, str);
if (!filename) {
return false;
}
JS_ReportErrorUTF8(cx, "can't write %s: shared memory buffer",
filename.get());
return false;
@ -581,6 +504,10 @@ static bool osfile_writeTypedArrayToFile(JSContext* cx, unsigned argc,
size_t length = obj->length();
if (fwrite(buf, obj->bytesPerElement(), length, file) != length ||
!autoClose.release()) {
filename = JS_EncodeStringToUTF8(cx, str);
if (!filename) {
return false;
}
JS_ReportErrorUTF8(cx, "can't write %s", filename.get());
return false;
}
@ -591,7 +518,7 @@ static bool osfile_writeTypedArrayToFile(JSContext* cx, unsigned argc,
/* static */
RCFile* RCFile::create(JSContext* cx, const char* filename, const char* mode) {
FILE* fp = OpenFile(cx, filename, mode);
FILE* fp = fopen(filename, mode);
if (!fp) {
return nullptr;
}
@ -689,12 +616,18 @@ static FileObject* redirect(JSContext* cx, HandleString relFilename,
if (!filename) {
return nullptr;
}
UniqueChars filenameABS = JS_EncodeStringToUTF8(cx, filename);
UniqueChars filenameABS = JS_EncodeStringToLatin1(cx, filename);
if (!filenameABS) {
return nullptr;
}
RCFile* file = RCFile::create(cx, filenameABS.get(), "wb");
if (!file) {
/*
* Use Latin1 variant here because the encoding of the return value of
* strerror function can be non-UTF-8.
*/
JS_ReportErrorLatin1(cx, "cannot redirect to %s: %s", filenameABS.get(),
strerror(errno));
return nullptr;
}
@ -884,7 +817,6 @@ static bool ospath_join(JSContext* cx, unsigned argc, Value* vp) {
// e.g. the drive letter is always reset when an absolute path is appended.
JSStringBuilder buffer(cx);
Rooted<JSLinearString*> str(cx);
for (unsigned i = 0; i < args.length(); i++) {
if (!args[i].isString()) {
@ -892,7 +824,8 @@ static bool ospath_join(JSContext* cx, unsigned argc, Value* vp) {
return false;
}
str = JS_EnsureLinearString(cx, args[i].toString());
Rooted<JSLinearString*> str(cx,
JS_EnsureLinearString(cx, args[i].toString()));
if (!str) {
return false;
}
@ -900,7 +833,7 @@ static bool ospath_join(JSContext* cx, unsigned argc, Value* vp) {
if (IsAbsolutePath(str)) {
MOZ_ALWAYS_TRUE(buffer.resize(0));
} else if (i != 0) {
UniqueChars path = JS_EncodeStringToUTF8(cx, str);
UniqueChars path = JS_EncodeStringToLatin1(cx, str);
if (!path) {
return false;
}
@ -975,7 +908,8 @@ static bool os_getpid(JSContext* cx, unsigned argc, Value* vp) {
return true;
}
#if !defined(XP_WIN)
#ifndef __wasi__
# if !defined(XP_WIN)
// There are two possible definitions of strerror_r floating around. The GNU
// one returns a char* which may or may not be the buffer you passed in. The
@ -988,34 +922,28 @@ inline char* strerror_message(int result, char* buffer) {
inline char* strerror_message(char* result, char* buffer) { return result; }
#endif
# endif
UniqueChars SystemErrorMessage(JSContext* cx, int errnum) {
#if defined(XP_WIN)
wchar_t buffer[200];
const wchar_t* errstr = buffer;
if (_wcserror_s(buffer, mozilla::ArrayLength(buffer), errnum) != 0) {
errstr = L"unknown error";
}
return JS::EncodeWideToUtf8(cx, errstr);
#else
static void ReportSysError(JSContext* cx, const char* prefix) {
char buffer[200];
const char* errstr = strerror_message(
strerror_r(errno, buffer, mozilla::ArrayLength(buffer)), buffer);
# if defined(XP_WIN)
strerror_s(buffer, sizeof(buffer), errno);
const char* errstr = buffer;
# else
const char* errstr =
strerror_message(strerror_r(errno, buffer, sizeof(buffer)), buffer);
# endif
if (!errstr) {
errstr = "unknown error";
}
return JS::EncodeNarrowToUtf8(cx, errstr);
#endif
}
#ifndef __wasi__
static void ReportSysError(JSContext* cx, const char* prefix) {
MOZ_ASSERT(JS::StringIsASCII(prefix));
if (UniqueChars error = SystemErrorMessage(cx, errno)) {
JS_ReportErrorUTF8(cx, "%s: %s", prefix, error.get());
}
/*
* Use Latin1 variant here because the encoding of the return value of
* strerror_s and strerror_r function can be non-UTF-8.
*/
JS_ReportErrorLatin1(cx, "%s: %s", prefix, errstr);
}
static bool os_system(JSContext* cx, unsigned argc, Value* vp) {
@ -1026,35 +954,17 @@ static bool os_system(JSContext* cx, unsigned argc, Value* vp) {
return false;
}
Rooted<JSString*> str(cx, JS::ToString(cx, args[0]));
JSString* str = JS::ToString(cx, args[0]);
if (!str) {
return false;
}
UniqueChars command = JS_EncodeStringToUTF8(cx, str);
UniqueChars command = JS_EncodeStringToLatin1(cx, str);
if (!command) {
return false;
}
# ifdef XP_WIN
UniqueWideChars wideCommand = JS::EncodeUtf8ToWide(cx, command.get());
if (!wideCommand) {
return false;
}
// Existing streams must be explicitly flushed or closed before calling
// the system() function on Windows.
_flushall();
int result = _wsystem(wideCommand.get());
# else
UniqueChars narrowCommand = JS::EncodeUtf8ToNarrow(cx, command.get());
if (!narrowCommand) {
return false;
}
int result = system(narrowCommand.get());
# endif
int result = system(command.get());
if (result == -1) {
ReportSysError(cx, "system call failed");
return false;
@ -1073,19 +983,15 @@ static bool os_spawn(JSContext* cx, unsigned argc, Value* vp) {
return false;
}
Rooted<JSString*> str(cx, JS::ToString(cx, args[0]));
JSString* str = JS::ToString(cx, args[0]);
if (!str) {
return false;
}
UniqueChars command = JS_EncodeStringToUTF8(cx, str);
UniqueChars command = JS_EncodeStringToLatin1(cx, str);
if (!command) {
return false;
}
UniqueChars narrowCommand = JS::EncodeUtf8ToNarrow(cx, command.get());
if (!narrowCommand) {
return false;
}
int32_t childPid = fork();
if (childPid == -1) {
@ -1101,7 +1007,7 @@ static bool os_spawn(JSContext* cx, unsigned argc, Value* vp) {
// We are in the child
const char* cmd[] = {"sh", "-c", nullptr, nullptr};
cmd[2] = narrowCommand.get();
cmd[2] = command.get();
execvp("sh", (char* const*)cmd);
exit(1);
@ -1187,8 +1093,8 @@ static bool os_waitpid(JSContext* cx, unsigned argc, Value* vp) {
args.rval().setObject(*info);
return true;
}
# endif
#endif // !__wasi__
# endif // !__wasi__
#endif
// clang-format off
static const JSFunctionSpecWithHelp os_functions[] = {

Просмотреть файл

@ -9,8 +9,6 @@
#ifndef shell_OSObject_h
#define shell_OSObject_h
#include <stdio.h>
#include "js/TypeDecls.h"
#include "js/Utility.h"
@ -40,58 +38,7 @@ JSString* ResolvePath(JSContext* cx, JS::HandleString filenameStr,
JSObject* FileAsTypedArray(JSContext* cx, JS::HandleString pathnameStr);
/**
* Return the current working directory as a UTF-8 encoded string.
*
* @param cx current js-context
* @return the working directory name or {@code nullptr} on error
*/
JS::UniqueChars GetCWD(JSContext* cx);
/**
* Open the requested file.
*
* @param cx current js-context
* @param filename file name encoded in UTF-8
* @param mode file mode specifier, see {@code fopen} for valid values
* @return a FILE pointer or {@code nullptr} on failure
*/
FILE* OpenFile(JSContext* cx, const char* filename, const char* mode);
/**
* Read {@code length} bytes in the given buffer.
*
* @param cx current js-context
* @param filename file name encoded in UTF-8, only used for error reporting
* @param file file pointer to read from
* @param buffer destination buffer to copy read bytes into
* @param length number of bytes to read
* @return returns false and reports an error if not exactly {@code length}
* bytes could be read from the input file
*/
bool ReadFile(JSContext* cx, const char* filename, FILE* file, char* buffer,
size_t length);
/**
* Compute the file size in bytes.
*
* @param cx current js-context
* @param filename file name encoded in UTF-8, only used for error reporting
* @param file file object to inspect
* @param size output parameter to store the file size into
* @return returns false and reports an error if an I/O error occurred
*/
bool FileSize(JSContext* cx, const char* filename, FILE* file, size_t* size);
/**
* Return the system error message for the given error number. The error
* message is UTF-8 encoded.
*
* @param cx current js-context
* @param errnum error number
* @return error message or {@code nullptr} on error
*/
JS::UniqueChars SystemErrorMessage(JSContext* cx, int errnum);
JS::UniqueChars GetCWD();
} // namespace shell
} // namespace js

Просмотреть файл

@ -826,10 +826,6 @@ static bool TraceGrayRoots(JSTracer* trc, SliceBudget& budget, void* data) {
return true;
}
static inline JSString* NewStringCopyUTF8(JSContext* cx, const char* chars) {
return JS_NewStringCopyUTF8N(cx, JS::UTF8Chars(chars, strlen(chars)));
}
static mozilla::UniqueFreePtr<char[]> GetLine(FILE* file, const char* prompt) {
#ifdef EDITLINE
/*
@ -1015,7 +1011,7 @@ static bool RegisterScriptPathWithModuleLoader(JSContext* cx,
// script's filename so that the module loader can use it to resolve
// relative imports.
RootedString path(cx, NewStringCopyUTF8(cx, filename));
RootedString path(cx, JS_NewStringCopyZ(cx, filename));
if (!path) {
return false;
}
@ -1116,7 +1112,7 @@ enum class CompileUtf8 {
bool compileOnly) {
ShellContext* sc = GetShellContext(cx);
RootedString path(cx, NewStringCopyUTF8(cx, filename));
RootedString path(cx, JS_NewStringCopyZ(cx, filename));
if (!path) {
return false;
}
@ -1591,9 +1587,11 @@ static bool AddIntlExtras(JSContext* cx, unsigned argc, Value* vp) {
GetLine(in, startline == lineno ? "js> " : "");
if (!line) {
if (errno) {
if (UniqueChars error = SystemErrorMessage(cx, errno)) {
JS_ReportErrorUTF8(cx, "%s", error.get());
}
/*
* Use Latin1 variant here because strerror(errno)'s
* encoding depends on the user's C locale.
*/
JS_ReportErrorLatin1(cx, "%s", strerror(errno));
return false;
}
hitEOF = true;
@ -1656,14 +1654,31 @@ enum FileKind {
FileModule,
};
static void ReportCantOpenErrorUnknownEncoding(JSContext* cx,
const char* filename) {
/*
* Filenames are in some random system encoding. *Probably* it's UTF-8,
* but no guarantees.
*
* strerror(errno)'s encoding, in contrast, depends on the user's C locale.
*
* Latin-1 is possibly wrong for both of these -- but at least if it's
* wrong it'll produce mojibake *safely*. Run with Latin-1 til someone
* complains.
*/
JS_ReportErrorNumberLatin1(cx, my_GetErrorMessage, nullptr, JSSMSG_CANT_OPEN,
filename, strerror(errno));
}
[[nodiscard]] static bool Process(JSContext* cx, const char* filename,
bool forceTTY, FileKind kind) {
FILE* file;
if (forceTTY || !filename || strcmp(filename, "-") == 0) {
file = stdin;
} else {
file = OpenFile(cx, filename, "rb");
file = fopen(filename, "rb");
if (!file) {
ReportCantOpenErrorUnknownEncoding(cx, filename);
return false;
}
}
@ -1780,12 +1795,11 @@ static bool CreateMappedArrayBuffer(JSContext* cx, unsigned argc, Value* vp) {
// I need a file at a known location, and the only good way I know of to do
// that right now is to include it in the repo alongside the test script.
// Bug 944164 would introduce an alternative.
Rooted<JSString*> filenameStr(
cx, ResolvePath(cx, rawFilenameStr, ScriptRelative));
JSString* filenameStr = ResolvePath(cx, rawFilenameStr, ScriptRelative);
if (!filenameStr) {
return false;
}
UniqueChars filename = JS_EncodeStringToUTF8(cx, filenameStr);
UniqueChars filename = JS_EncodeStringToLatin1(cx, filenameStr);
if (!filename) {
return false;
}
@ -1811,8 +1825,9 @@ static bool CreateMappedArrayBuffer(JSContext* cx, unsigned argc, Value* vp) {
}
}
FILE* file = OpenFile(cx, filename.get(), "rb");
FILE* file = fopen(filename.get(), "rb");
if (!file) {
ReportCantOpenErrorUnknownEncoding(cx, filename.get());
return false;
}
AutoCloseFile autoClose(file);
@ -1988,7 +2003,7 @@ static bool LoadScript(JSContext* cx, unsigned argc, Value* vp,
return false;
}
UniqueChars filename = JS_EncodeStringToUTF8(cx, str);
UniqueChars filename = JS_EncodeStringToLatin1(cx, str);
if (!filename) {
return false;
}
@ -2552,13 +2567,16 @@ static bool Evaluate(JSContext* cx, unsigned argc, Value* vp) {
}
JSString* js::shell::FileAsString(JSContext* cx, JS::HandleString pathnameStr) {
UniqueChars pathname = JS_EncodeStringToUTF8(cx, pathnameStr);
UniqueChars pathname = JS_EncodeStringToLatin1(cx, pathnameStr);
if (!pathname) {
return nullptr;
}
FILE* file = OpenFile(cx, pathname.get(), "rb");
FILE* file;
file = fopen(pathname.get(), "rb");
if (!file) {
ReportCantOpenErrorUnknownEncoding(cx, pathname.get());
return nullptr;
}
@ -2575,8 +2593,28 @@ JSString* js::shell::FileAsString(JSContext* cx, JS::HandleString pathnameStr) {
return nullptr;
}
size_t len;
if (!FileSize(cx, pathname.get(), file, &len)) {
if (fseek(file, 0, SEEK_END) != 0) {
pathname = JS_EncodeStringToUTF8(cx, pathnameStr);
if (!pathname) {
return nullptr;
}
JS_ReportErrorUTF8(cx, "can't seek end of %s", pathname.get());
return nullptr;
}
long endPos = ftell(file);
if (endPos < 0) {
JS_ReportErrorUTF8(cx, "can't read length of %s", pathname.get());
return nullptr;
}
size_t len = endPos;
if (fseek(file, 0, SEEK_SET) != 0) {
pathname = JS_EncodeStringToUTF8(cx, pathnameStr);
if (!pathname) {
return nullptr;
}
JS_ReportErrorUTF8(cx, "can't seek start of %s", pathname.get());
return nullptr;
}
@ -2586,7 +2624,17 @@ JSString* js::shell::FileAsString(JSContext* cx, JS::HandleString pathnameStr) {
return nullptr;
}
if (!ReadFile(cx, pathname.get(), file, buf.get(), len)) {
size_t cc = fread(buf.get(), 1, len, file);
if (cc != len) {
if (ptrdiff_t(cc) < 0) {
ReportCantOpenErrorUnknownEncoding(cx, pathname.get());
} else {
pathname = JS_EncodeStringToUTF8(cx, pathnameStr);
if (!pathname) {
return nullptr;
}
JS_ReportErrorUTF8(cx, "can't read %s: short read", pathname.get());
}
return nullptr;
}
@ -2595,6 +2643,10 @@ JSString* js::shell::FileAsString(JSContext* cx, JS::HandleString pathnameStr) {
&len, js::MallocArena)
.get());
if (!ucbuf) {
pathname = JS_EncodeStringToUTF8(cx, pathnameStr);
if (!pathname) {
return nullptr;
}
JS_ReportErrorUTF8(cx, "Invalid UTF-8 in file '%s'", pathname.get());
return nullptr;
}
@ -2639,7 +2691,8 @@ static bool Run(JSContext* cx, unsigned argc, Value* vp) {
RootedScript script(cx);
int64_t startClock = PRMJ_Now();
{
UniqueChars filename = JS_EncodeStringToUTF8(cx, str);
/* FIXME: This should use UTF-8 (bug 987069). */
UniqueChars filename = JS_EncodeStringToLatin1(cx, str);
if (!filename) {
return false;
}
@ -3319,12 +3372,11 @@ static bool DisassFile(JSContext* cx, unsigned argc, Value* vp) {
}
// We should change DisassembleOptionParser to store CallArgs.
Rooted<JSString*> str(
cx, JS::ToString(cx, HandleValue::fromMarkedLocation(&p.argv[0])));
JSString* str = JS::ToString(cx, HandleValue::fromMarkedLocation(&p.argv[0]));
if (!str) {
return false;
}
UniqueChars filename = JS_EncodeStringToUTF8(cx, str);
UniqueChars filename = JS_EncodeStringToLatin1(cx, str);
if (!filename) {
return false;
}
@ -3384,8 +3436,10 @@ static bool DisassWithSrc(JSContext* cx, unsigned argc, Value* vp) {
return false;
}
FILE* file = OpenFile(cx, script->filename(), "rb");
FILE* file = fopen(script->filename(), "rb");
if (!file) {
/* FIXME: script->filename() should become UTF-8 (bug 987069). */
ReportCantOpenErrorUnknownEncoding(cx, script->filename());
return false;
}
auto closeFile = MakeScopeExit([file] { fclose(file); });
@ -3403,7 +3457,8 @@ static bool DisassWithSrc(JSContext* cx, unsigned argc, Value* vp) {
for (line1 = 0; line1 < line2 - 1; line1++) {
char* tmp = fgets(linebuf, lineBufLen, file);
if (!tmp) {
JS_ReportErrorUTF8(cx, "failed to read %s fully", script->filename());
/* FIXME: This should use UTF-8 (bug 987069). */
JS_ReportErrorLatin1(cx, "failed to read %s fully", script->filename());
return false;
}
}
@ -3428,8 +3483,13 @@ static bool DisassWithSrc(JSContext* cx, unsigned argc, Value* vp) {
bupline = 0;
while (line1 < line2) {
if (!fgets(linebuf, lineBufLen, file)) {
JS_ReportErrorNumberUTF8(cx, my_GetErrorMessage, nullptr,
JSSMSG_UNEXPECTED_EOF, script->filename());
/*
* FIXME: script->filename() should become UTF-8
* (bug 987069).
*/
JS_ReportErrorNumberLatin1(cx, my_GetErrorMessage, nullptr,
JSSMSG_UNEXPECTED_EOF,
script->filename());
return false;
}
line1++;
@ -4879,7 +4939,7 @@ static bool ParseModule(JSContext* cx, unsigned argc, Value* vp) {
}
RootedString str(cx, args[1].toString());
filename = JS_EncodeStringToUTF8(cx, str);
filename = JS_EncodeStringToLatin1(cx, str);
if (!filename) {
return false;
}
@ -6490,7 +6550,7 @@ static bool ThisFilename(JSContext* cx, unsigned argc, Value* vp) {
return true;
}
JSString* str = NewStringCopyUTF8(cx, filename.get());
JSString* str = JS_NewStringCopyZ(cx, filename.get());
if (!str) {
return false;
}
@ -6847,14 +6907,9 @@ class ShellSourceHook : public SourceHook {
MOZ_ASSERT((twoByteSource != nullptr) != (utf8Source != nullptr),
"must be called requesting only one of UTF-8 or UTF-16 source");
RootedString str(cx);
if (filename) {
str = NewStringCopyUTF8(cx, filename);
if (!str) {
return false;
}
} else {
str = JS_GetEmptyString(cx);
RootedString str(cx, JS_NewStringCopyZ(cx, filename));
if (!str) {
return false;
}
RootedValue filenameValue(cx, StringValue(str));
@ -7656,6 +7711,24 @@ done:
}
}
static bool EnsureLatin1CharsLinearString(JSContext* cx, HandleValue value,
UniqueChars* result) {
if (!value.isString()) {
result->reset(nullptr);
return true;
}
RootedString str(cx, value.toString());
if (!str->isLinear() || !str->hasLatin1Chars()) {
JS_ReportErrorASCII(cx,
"only latin1 chars and linear strings are expected");
return false;
}
// Use JS_EncodeStringToLatin1 to null-terminate.
*result = JS_EncodeStringToLatin1(cx, str);
return !!*result;
}
static bool ConsumeBufferSource(JSContext* cx, JS::HandleObject obj,
JS::MimeType, JS::StreamConsumer* consumer) {
{
@ -7664,12 +7737,8 @@ static bool ConsumeBufferSource(JSContext* cx, JS::HandleObject obj,
return false;
}
UniqueChars urlChars;
if (url.isString()) {
Rooted<JSString*> str(cx, url.toString());
urlChars = JS_EncodeStringToUTF8(cx, str);
if (!urlChars) {
return false;
}
if (!EnsureLatin1CharsLinearString(cx, url, &urlChars)) {
return false;
}
RootedValue mapUrl(cx);
@ -7677,12 +7746,8 @@ static bool ConsumeBufferSource(JSContext* cx, JS::HandleObject obj,
return false;
}
UniqueChars mapUrlChars;
if (mapUrl.isString()) {
Rooted<JSString*> str(cx, mapUrl.toString());
mapUrlChars = JS_EncodeStringToUTF8(cx, str);
if (!mapUrlChars) {
return false;
}
if (!EnsureLatin1CharsLinearString(cx, mapUrl, &mapUrlChars)) {
return false;
}
consumer->noteResponseURLs(urlChars.get(), mapUrlChars.get());
@ -8065,7 +8130,7 @@ class ShellAutoEntryMonitor : JS::dbg::AutoEntryMonitor {
for (size_t i = 0; i < log.length(); i++) {
char* name = log[i].get();
RootedString string(cx, AtomizeUTF8Chars(cx, name, strlen(name)));
RootedString string(cx, Atomize(cx, name, strlen(name)));
if (!string) {
return false;
}
@ -10402,24 +10467,16 @@ static bool BindScriptArgs(JSContext* cx, OptionParser* op) {
for (size_t i = 0; !msr.empty(); msr.popFront(), ++i) {
const char* scriptArg = msr.front();
UniqueChars scriptArgUtf8 = JS::EncodeNarrowToUtf8(cx, scriptArg);
if (!scriptArgUtf8) {
return false;
}
RootedString str(cx, NewStringCopyUTF8(cx, scriptArgUtf8.get()));
JS::RootedString str(cx, JS_NewStringCopyZ(cx, scriptArg));
if (!str || !JS_DefineElement(cx, scriptArgs, i, str, JSPROP_ENUMERATE)) {
return false;
}
}
const char* scriptPath = op->getStringArg("script");
RootedValue scriptPathValue(cx);
if (const char* scriptPath = op->getStringArg("script")) {
UniqueChars scriptPathUtf8 = JS::EncodeNarrowToUtf8(cx, scriptPath);
if (!scriptPathUtf8) {
return false;
}
RootedString scriptPathString(cx,
NewStringCopyUTF8(cx, scriptPathUtf8.get()));
if (scriptPath) {
RootedString scriptPathString(cx, JS_NewStringCopyZ(cx, scriptPath));
if (!scriptPathString) {
return false;
}
@ -10493,11 +10550,8 @@ auto minVal(T a, Ts... args) {
size_t minArgno = minVal(ppArgno, fpArgno, ufpArgno, ccArgno, mpArgno);
if (ppArgno == minArgno) {
UniqueChars path = JS::EncodeNarrowToUtf8(cx, preludePaths.front());
if (!path) {
return false;
}
if (!Process(cx, path.get(), false, PreludeScript)) {
char* path = preludePaths.front();
if (!Process(cx, path, false, PreludeScript)) {
return false;
}
@ -10506,11 +10560,8 @@ auto minVal(T a, Ts... args) {
}
if (fpArgno == minArgno) {
UniqueChars path = JS::EncodeNarrowToUtf8(cx, filePaths.front());
if (!path) {
return false;
}
if (!Process(cx, path.get(), false, FileScript)) {
char* path = filePaths.front();
if (!Process(cx, path, false, FileScript)) {
return false;
}
@ -10519,11 +10570,8 @@ auto minVal(T a, Ts... args) {
}
if (ufpArgno == minArgno) {
UniqueChars path = JS::EncodeNarrowToUtf8(cx, utf16FilePaths.front());
if (!path) {
return false;
}
if (!Process(cx, path.get(), false, FileScriptUtf16)) {
char* path = utf16FilePaths.front();
if (!Process(cx, path, false, FileScriptUtf16)) {
return false;
}
@ -10532,10 +10580,7 @@ auto minVal(T a, Ts... args) {
}
if (ccArgno == minArgno) {
UniqueChars code = JS::EncodeNarrowToUtf8(cx, codeChunks.front());
if (!code) {
return false;
}
const char* code = codeChunks.front();
// Command line scripts are always parsed with full-parse to evaluate
// conditions which might filter code coverage conditions.
@ -10543,8 +10588,7 @@ auto minVal(T a, Ts... args) {
opts.setFileAndLine("-e", 1).setForceFullParse();
JS::SourceText<Utf8Unit> srcBuf;
if (!srcBuf.init(cx, code.get(), strlen(code.get()),
JS::SourceOwnership::Borrowed)) {
if (!srcBuf.init(cx, code, strlen(code), JS::SourceOwnership::Borrowed)) {
return false;
}
@ -10563,11 +10607,8 @@ auto minVal(T a, Ts... args) {
MOZ_ASSERT(mpArgno == minArgno);
UniqueChars path = JS::EncodeNarrowToUtf8(cx, modulePaths.front());
if (!path) {
return false;
}
if (!Process(cx, path.get(), false, FileModule)) {
char* path = modulePaths.front();
if (!Process(cx, path, false, FileModule)) {
return false;
}
@ -10580,11 +10621,7 @@ auto minVal(T a, Ts... args) {
/* The |script| argument is processed after all options. */
if (const char* path = op->getStringArg("script")) {
UniqueChars pathUtf8 = JS::EncodeNarrowToUtf8(cx, path);
if (!pathUtf8) {
return false;
}
if (!Process(cx, pathUtf8.get(), false, FileScript)) {
if (!Process(cx, path, false, FileScript)) {
return false;
}
}
@ -12572,32 +12609,25 @@ bool SetContextGCOptions(JSContext* cx, const OptionParser& op) {
bool InitModuleLoader(JSContext* cx, const OptionParser& op) {
RootedString moduleLoadPath(cx);
if (const char* option = op.getStringOption("module-load-path")) {
UniqueChars pathUtf8 = JS::EncodeNarrowToUtf8(cx, option);
if (!pathUtf8) {
return false;
}
Rooted<JSString*> jspath(cx, NewStringCopyUTF8(cx, pathUtf8.get()));
RootedString jspath(cx, JS_NewStringCopyZ(cx, option));
if (!jspath) {
return false;
}
moduleLoadPath = js::shell::ResolvePath(cx, jspath, RootRelative);
processWideModuleLoadPath = JS_EncodeStringToUTF8(cx, moduleLoadPath);
if (!processWideModuleLoadPath) {
return false;
}
} else {
processWideModuleLoadPath = js::shell::GetCWD(cx);
if (!processWideModuleLoadPath) {
return false;
}
UniqueChars cwd = js::shell::GetCWD();
moduleLoadPath = JS_NewStringCopyZ(cx, cwd.get());
}
moduleLoadPath = NewStringCopyUTF8(cx, processWideModuleLoadPath.get());
if (!moduleLoadPath) {
return false;
}
if (!moduleLoadPath) {
return false;
}
processWideModuleLoadPath = JS_EncodeStringToUTF8(cx, moduleLoadPath);
if (!processWideModuleLoadPath) {
MOZ_ASSERT(cx->isExceptionPending());
return false;
}
ShellContext* sc = GetShellContext(cx);

Просмотреть файл

@ -1,235 +0,0 @@
// |reftest| skip-if(!xulRuntime.shell)
// Retrieve the script file name through various functions and ensure it's
// always correctly decoded from UTF-8.
// Special value when filename cannot be retrieved.
const NOT_SUPPORTED = "*not supported*";
// Return the file name from the Error#fileName property.
function errorFileName(fileName) {
return evaluate("new Error().fileName", {fileName});
}
// Return the file name from the Parser by a SyntaxError.
function errorFileNameParser(fileName) {
try {
evaluate("###", {fileName});
} catch (e) {
return e.fileName;
}
}
// Retrieve the file name through DescriptedCaller (1).
function descriptedCallerViaThisFileName(fileName) {
return evaluate("thisFilename()", {fileName});
}
// Retrieve the file name through DescriptedCaller (2).
function descriptedCallerViaEvalInContext(fileName) {
return evaluate("evalcx('new Error().fileName')", {fileName});
}
// Retrieve the file name through DescriptedCaller (3).
function descriptedCallerViaEval(fileName) {
var pattern = / line 1 > eval$/;
return evaluate("eval('new Error().fileName')", {fileName}).replace(pattern, "");
}
// Retrieve the file name through DescriptedCaller (4).
function descriptedCallerViaFunction(fileName) {
var pattern = / line 1 > Function$/;
return evaluate("Function('return new Error().fileName')()", {fileName}).replace(pattern, "");
}
// Retrieve the file name through DescriptedCaller (5).
function descriptedCallerViaEvalReturningScope(fileName) {
return evaluate("evalReturningScope('var a = new Error().fileName')", {fileName}).a;
}
// Retrieve the file name through DescriptedCaller (7).
var wasmModuleConstructorTemp;
function descriptedCallerViaWasm(fileName) {
if (!wasmIsSupported()) {
return fileName;
}
wasmModuleConstructorTemp = null;
evaluate(`
function wasmEvalText(str, imports) {
let binary = wasmTextToBinary(str);
assertEq(WebAssembly.validate(binary), true);
let m = new WebAssembly.Module(binary);
return new WebAssembly.Instance(m, imports);
}
wasmEvalText('(module (import "" "a" (func)) (func (call 0)) (export "bar" (func 1)))',
{
"": {
a() {
wasmModuleConstructorTemp = new Error().stack;
return 0;
}
}
}).exports.bar();
`, {fileName});
var pattern = /^@(.*) line \d+ >.*$/;
var index = 1; // Direct caller is the wasm function.
return wasmModuleConstructorTemp.split("\n")[index].replace(pattern, "$1");
}
// Return the file name from Reflect.parse().
function reflectParseSource(fileName) {
return Reflect.parse("", {source: fileName}).loc.source;
}
// Return the file name using the Error#stack property.
function fromErrorStack(fileName) {
var pattern = /^@(.*):\d+:\d+$/;
return evaluate("new Error().stack", {fileName}).split("\n")[0].replace(pattern, "$1");
}
// Return the file name using the Error#stack property from an asm.js function.
function fromErrorStackAsmJS(fileName) {
var asm = evaluate(`(function asm(stdlib, foreign) {
"use asm";
var f = foreign.f;
function g() {
return f() | 0;
}
return {g: g};
})`, {fileName});
var stackFileName;
var foreign = {
f() {
var pattern = /^g@(.*):\d+:\d+$/;
var index = 1; // Direct caller is the asm.js function.
var stack = new Error().stack;
stackFileName = stack.split("\n")[index].replace(pattern, "$1");
return 0;
}
};
asm(this, foreign).g();
return stackFileName;
}
// Return the file name using the Error#stacl property when a streaming compiled WASM function.
function fromErrorStackStreamingWasm(fileName) {
if (!wasmIsSupported() || helperThreadCount() == 0) {
return fileName;
}
var source = new Uint8Array(wasmTextToBinary(`
(module (import "" "a" (func)) (func (call 0)) (export "bar" (func 1)))
`));
source.url = fileName;
var stackFileName;
var imports = {
"": {
a() {
var pattern = /^@(.*):wasm-function.*$/;
var index = 1; // Direct caller is the asm.js function.
var stack = new Error().stack;
stackFileName = stack.split("\n")[index].replace(pattern, "$1");
return 0;
}
}
};
var result;
WebAssembly.instantiateStreaming(source, imports).then(r => result = r);
drainJobQueue();
result.instance.exports.bar();
return stackFileName;
}
// Return the file name using the embedded info in getBacktrace().
function getBacktraceScriptName(fileName) {
var pattern = /^\d+ <TOP LEVEL> \["(.*)":\d+:\d\]$/;
return evaluate("getBacktrace()", {fileName}).split("\n")[0].replace(pattern, "$1");
}
// Return the file name from the coverage report.
function getLcovInfoScriptName(fileName) {
var g = newGlobal();
var scriptFiles = g.evaluate("getLcovInfo()", {fileName})
.split("\n")
.filter(x => x.startsWith("SF:"));
assertEq(scriptFiles.length, 1);
return scriptFiles[0].substring(3);
}
// Return the file name from the error during module import.
function moduleResolutionError(fileName) {
const a = parseModule(`import { x } from "b";`, fileName);
const ma = registerModule("a", a);
const b = parseModule(`export var y = 10;`);
const mb = registerModule("b", b);
try {
moduleLink(ma);
} catch (e) {
return e.fileName;
}
}
// Return the file name from the profiler stack.
function geckoInterpProfilingStack(fileName) {
enableGeckoProfilingWithSlowAssertions();
const stack = evaluate(`readGeckoInterpProfilingStack();`, { fileName });
if (stack.length === 0) {
return NOT_SUPPORTED;
}
const result = stack[0].dynamicString;
disableGeckoProfiling();
return result;
}
const testFunctions = [
errorFileName,
errorFileNameParser,
descriptedCallerViaThisFileName,
descriptedCallerViaEvalInContext,
descriptedCallerViaEval,
descriptedCallerViaFunction,
descriptedCallerViaEvalReturningScope,
descriptedCallerViaWasm,
reflectParseSource,
fromErrorStack,
fromErrorStackAsmJS,
fromErrorStackStreamingWasm,
getBacktraceScriptName,
moduleResolutionError,
];
if (isLcovEnabled()) {
testFunctions.push(getLcovInfoScriptName);
}
const fileNames = [
"",
"test",
"Ðëßþ",
"тест",
"テスト",
"\u{1F9EA}",
];
for (const fn of testFunctions) {
for (const fileName of fileNames) {
const result = fn(fileName);
if (result === NOT_SUPPORTED) {
continue;
}
assertEq(result, fileName, `Caller '${fn.name}'`);
}
}
if (typeof reportCompare === "function")
reportCompare(true, true);

Просмотреть файл

@ -14,8 +14,7 @@
# include "js/Vector.h"
#endif // __wasi__
#include "js/CharacterEncoding.h" // EncodeUtf8ToWide, EncodeUtf8ToNarrow
#include "js/ErrorReport.h" // JS_ReportErrorNumberUTF8
#include "js/ErrorReport.h" // JS_ReportErrorNumberLatin1
#include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_CANT_OPEN
bool js::ReadCompleteFile(JSContext* cx, FILE* fp, FileContents& buffer) {
@ -104,22 +103,6 @@ static bool NormalizeWASIPath(const char* filename,
}
#endif
static FILE* OpenFile(JSContext* cx, const char* filename) {
#ifdef XP_WIN
JS::UniqueWideChars wideFilename = JS::EncodeUtf8ToWide(cx, filename);
if (!wideFilename) {
return nullptr;
}
return _wfopen(wideFilename.get(), L"r");
#else
JS::UniqueChars narrowFilename = JS::EncodeUtf8ToNarrow(cx, filename);
if (!narrowFilename) {
return nullptr;
}
return fopen(narrowFilename.get(), "r");
#endif
}
/*
* Open a source file for reading. Supports "-" and nullptr to mean stdin. The
* return value must be fclosed unless it is stdin.
@ -133,13 +116,17 @@ bool js::AutoFile::open(JSContext* cx, const char* filename) {
if (!NormalizeWASIPath(filename, &normalized, cx)) {
return false;
}
fp_ = OpenFile(cx, normalized.begin());
fp_ = fopen(normalized.begin(), "r");
#else
fp_ = OpenFile(cx, filename);
fp_ = fopen(filename, "r");
#endif
if (!fp_) {
JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_CANT_OPEN,
filename, "No such file or directory");
/*
* Use Latin1 variant here because the encoding of filename is
* platform dependent.
*/
JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr, JSMSG_CANT_OPEN,
filename, "No such file or directory");
return false;
}
}

Просмотреть файл

@ -2735,17 +2735,11 @@ JSString* JS::GetPCCountScriptSummary(JSContext* cx, size_t index) {
json.beginObject();
Rooted<JSString*> filenameStr(cx);
if (const char* filename = script->filename()) {
filenameStr =
JS_NewStringCopyUTF8N(cx, JS::UTF8Chars(filename, strlen(filename)));
} else {
filenameStr = JS_GetEmptyString(cx);
}
if (!filenameStr) {
RootedString filename(cx, NewStringCopyZ<CanGC>(cx, script->filename()));
if (!filename) {
return nullptr;
}
if (!JSONStringProperty(sp, json, "file", filenameStr)) {
if (!JSONStringProperty(sp, json, "file", filename)) {
return nullptr;
}
json.property("line", script->lineno());

Просмотреть файл

@ -6,23 +6,14 @@
#include "js/CharacterEncoding.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/Latin1.h"
#include "mozilla/Maybe.h"
#include "mozilla/Range.h"
#include "mozilla/Span.h"
#include "mozilla/Sprintf.h"
#include "mozilla/TextUtils.h"
#include "mozilla/Utf8.h"
#ifndef XP_LINUX
// We still support libstd++ versions without codecvt support on Linux.
# include <codecvt>
#endif
#include <cwchar>
#include <limits>
#include <locale>
#include <type_traits>
#include "frontend/FrontendContext.h"
@ -596,224 +587,6 @@ bool JS::StringIsASCII(const char* s) {
bool JS::StringIsASCII(Span<const char> s) { return IsAscii(s); }
JS_PUBLIC_API JS::UniqueChars JS::EncodeNarrowToUtf8(JSContext* cx,
const char* chars) {
// Convert the narrow multibyte character string to a wide string and then
// use EncodeWideToUtf8() to convert the wide string to a UTF-8 string.
std::mbstate_t mb{};
size_t wideLen = std::mbsrtowcs(nullptr, &chars, 0, &mb);
if (wideLen == size_t(-1)) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
JSMSG_CANT_CONVERT_TO_WIDE);
return nullptr;
}
MOZ_ASSERT(std::mbsinit(&mb),
"multi-byte state is in its initial state when no conversion "
"error occured");
size_t bufLen = wideLen + 1;
auto wideChars = cx->make_pod_array<wchar_t>(bufLen);
if (!wideChars) {
return nullptr;
}
mozilla::DebugOnly<size_t> actualLen =
std::mbsrtowcs(wideChars.get(), &chars, bufLen, &mb);
MOZ_ASSERT(wideLen == actualLen);
MOZ_ASSERT(wideChars[actualLen] == '\0');
return EncodeWideToUtf8(cx, wideChars.get());
}
JS_PUBLIC_API JS::UniqueChars JS::EncodeWideToUtf8(JSContext* cx,
const wchar_t* chars) {
using CheckedSizeT = mozilla::CheckedInt<size_t>;
#ifndef XP_LINUX
// Use the standard codecvt facet to convert a wide string to UTF-8.
std::codecvt_utf8<wchar_t> cv;
size_t len = std::wcslen(chars);
CheckedSizeT utf8MaxLen = CheckedSizeT(len) * cv.max_length();
CheckedSizeT utf8BufLen = utf8MaxLen + 1;
if (!utf8BufLen.isValid()) {
JS_ReportAllocationOverflow(cx);
return nullptr;
}
auto utf8 = cx->make_pod_array<char>(utf8BufLen.value());
if (!utf8) {
return nullptr;
}
// STL returns |codecvt_base::partial| for empty strings.
if (len == 0) {
return utf8;
}
std::mbstate_t mb{};
const wchar_t* fromNext;
char* toNext;
std::codecvt_base::result result =
cv.out(mb, chars, chars + len, fromNext, utf8.get(),
utf8.get() + utf8MaxLen.value(), toNext);
if (result != std::codecvt_base::ok) {
MOZ_ASSERT(result == std::codecvt_base::error);
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
JSMSG_CANT_CONVERT_WIDE_TO_UTF8);
return nullptr;
}
*toNext = '\0'; // Explicit null-termination required.
// codecvt_utf8 doesn't validate its output and may produce WTF-8 instead
// of UTF-8 on some platforms when the input contains unpaired surrogate
// characters. We don't allow this.
if (!mozilla::IsUtf8(
mozilla::Span(utf8.get(), size_t(toNext - utf8.get())))) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
JSMSG_CANT_CONVERT_WIDE_TO_UTF8);
return nullptr;
}
return utf8;
#else
static_assert(sizeof(wchar_t) == 4,
"Assume wchar_t is UTF-32 on Linux systems");
constexpr size_t MaxUtf8CharLength = 4;
size_t len = std::wcslen(chars);
CheckedSizeT utf8MaxLen = CheckedSizeT(len) * MaxUtf8CharLength;
CheckedSizeT utf8BufLen = utf8MaxLen + 1;
if (!utf8BufLen.isValid()) {
JS_ReportAllocationOverflow(cx);
return nullptr;
}
auto utf8 = cx->make_pod_array<char>(utf8BufLen.value());
if (!utf8) {
return nullptr;
}
char* dst = utf8.get();
for (size_t i = 0; i < len; i++) {
uint8_t utf8buf[MaxUtf8CharLength];
uint32_t utf8Len = OneUcs4ToUtf8Char(utf8buf, chars[i]);
for (size_t j = 0; j < utf8Len; j++) {
*dst++ = char(utf8buf[j]);
}
}
*dst = '\0';
return utf8;
#endif
}
JS_PUBLIC_API JS::UniqueChars JS::EncodeUtf8ToNarrow(JSContext* cx,
const char* chars) {
// Convert the UTF-8 string to a wide string via EncodeUtf8ToWide() and
// then convert the resulting wide string to a narrow multibyte character
// string.
auto wideChars = EncodeUtf8ToWide(cx, chars);
if (!wideChars) {
return nullptr;
}
const wchar_t* cWideChars = wideChars.get();
std::mbstate_t mb{};
size_t narrowLen = std::wcsrtombs(nullptr, &cWideChars, 0, &mb);
if (narrowLen == size_t(-1)) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
JSMSG_CANT_CONVERT_TO_NARROW);
return nullptr;
}
MOZ_ASSERT(std::mbsinit(&mb),
"multi-byte state is in its initial state when no conversion "
"error occured");
size_t bufLen = narrowLen + 1;
auto narrow = cx->make_pod_array<char>(bufLen);
if (!narrow) {
return nullptr;
}
mozilla::DebugOnly<size_t> actualLen =
std::wcsrtombs(narrow.get(), &cWideChars, bufLen, &mb);
MOZ_ASSERT(narrowLen == actualLen);
MOZ_ASSERT(narrow[actualLen] == '\0');
return narrow;
}
JS_PUBLIC_API JS::UniqueWideChars JS::EncodeUtf8ToWide(JSContext* cx,
const char* chars) {
// Only valid UTF-8 strings should be passed to this function.
MOZ_ASSERT(mozilla::IsUtf8(mozilla::Span(chars, strlen(chars))));
#ifndef XP_LINUX
// Use the standard codecvt facet to convert from UTF-8 to a wide string.
std::codecvt_utf8<wchar_t> cv;
size_t len = strlen(chars);
auto wideChars = cx->make_pod_array<wchar_t>(len + 1);
if (!wideChars) {
return nullptr;
}
// STL returns |codecvt_base::partial| for empty strings.
if (len == 0) {
return wideChars;
}
std::mbstate_t mb{};
const char* fromNext;
wchar_t* toNext;
std::codecvt_base::result result =
cv.in(mb, chars, chars + len, fromNext, wideChars.get(),
wideChars.get() + len, toNext);
if (result != std::codecvt_base::ok) {
MOZ_ASSERT(result == std::codecvt_base::error);
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
JSMSG_CANT_CONVERT_UTF8_TO_WIDE);
return nullptr;
}
*toNext = '\0'; // Explicit null-termination required.
return wideChars;
#else
static_assert(sizeof(wchar_t) == 4,
"Assume wchar_t is UTF-32 on Linux systems");
size_t len = strlen(chars);
auto wideChars = cx->make_pod_array<wchar_t>(len + 1);
if (!wideChars) {
return nullptr;
}
const auto* s = reinterpret_cast<const unsigned char*>(chars);
const auto* const limit = s + len;
wchar_t* dst = wideChars.get();
while (s < limit) {
unsigned char c = *s++;
if (mozilla::IsAscii(c)) {
*dst++ = wchar_t(c);
continue;
}
mozilla::Utf8Unit utf8(c);
mozilla::Maybe<char32_t> codePoint =
mozilla::DecodeOneUtf8CodePoint(utf8, &s, limit);
MOZ_ASSERT(codePoint.isSome());
*dst++ = wchar_t(*codePoint);
}
*dst++ = '\0';
return wideChars;
#endif
}
bool StringBuffer::append(const Utf8Unit* units, size_t len) {
MOZ_ASSERT(maybeCx_);

Просмотреть файл

@ -61,7 +61,7 @@ using namespace js;
#define IMPLEMENT_ERROR_PROTO_CLASS(name) \
{ \
#name ".prototype", JSCLASS_HAS_CACHED_PROTO(JSProto_##name), \
# name ".prototype", JSCLASS_HAS_CACHED_PROTO(JSProto_##name), \
JS_NULL_CLASS_OPS, \
&ErrorObject::classSpecs[JSProto_##name - JSProto_Error] \
}
@ -150,7 +150,7 @@ const ClassSpec ErrorObject::classSpecs[JSEXN_ERROR_LIMIT] = {
#define IMPLEMENT_ERROR_CLASS_CORE(name, reserved_slots) \
{ \
#name, \
# name, \
JSCLASS_HAS_CACHED_PROTO(JSProto_##name) | \
JSCLASS_HAS_RESERVED_SLOTS(reserved_slots) | \
JSCLASS_BACKGROUND_FINALIZE, \
@ -247,8 +247,7 @@ static ErrorObject* CreateErrorObject(JSContext* cx, const CallArgs& args,
fileName = cx->runtime()->emptyString;
if (!iter.done()) {
if (const char* cfilename = iter.filename()) {
fileName = JS_NewStringCopyUTF8Z(
cx, JS::ConstUTF8CharsZ(cfilename, strlen(cfilename)));
fileName = JS_NewStringCopyZ(cx, cfilename);
}
if (iter.hasScript()) {
sourceId = iter.script()->scriptSource()->id();
@ -572,8 +571,7 @@ JSErrorReport* js::ErrorObject::getOrCreateErrorReport(JSContext* cx) {
report.exnType = type_;
// Filename.
RootedString filename(cx, fileName(cx));
UniqueChars filenameStr = JS_EncodeStringToUTF8(cx, filename);
UniqueChars filenameStr = JS_EncodeStringToLatin1(cx, fileName(cx));
if (!filenameStr) {
return nullptr;
}

Просмотреть файл

@ -696,9 +696,8 @@ JSObject* js::CreateErrorNotesArray(JSContext* cx, JSErrorReport* report) {
}
RootedValue filenameVal(cx);
if (const char* filename = note->filename) {
JS::UTF8Chars utf8chars(filename, strlen(filename));
Rooted<JSString*> filenameStr(cx, NewStringCopyUTF8N(cx, utf8chars));
if (note->filename) {
RootedString filenameStr(cx, NewStringCopyZ<CanGC>(cx, note->filename));
if (!filenameStr) {
return nullptr;
}

Просмотреть файл

@ -76,6 +76,7 @@
#include "vm/StringType.h" // JSString, JSAtom
#include "vm/Time.h" // AutoIncrementalTimer
#include "vm/ToSource.h" // JS::ValueToSource
#include "vm/Warnings.h" // js::WarnNumberLatin1
#ifdef MOZ_VTUNE
# include "vtune/VTuneWrapper.h"
#endif

Просмотреть файл

@ -554,7 +554,7 @@ class ScriptSource {
};
ExclusiveData<ReaderInstances> readers_;
// The UTF-8 encoded filename of this script.
// The filename of this script.
SharedImmutableString filename_;
// Hash of the script filename;
@ -569,7 +569,7 @@ class ScriptSource {
// raw filename of "foo.js".
//
// In the case described above, this field will be set to to the original raw
// UTF-8 encoded filename from above, otherwise it will be mozilla::Nothing.
// filename from above, otherwise it will be mozilla::Nothing.
SharedImmutableString introducerFilename_;
SharedImmutableTwoByteString displayURL_;
@ -583,8 +583,6 @@ class ScriptSource {
// A string indicating how this source code was introduced into the system.
// This is a constant, statically allocated C string, so does not need memory
// management.
//
// TODO: Document the various additional introduction type constants.
const char* introductionType_ = nullptr;
// Bytecode offset in caller script that generated this code. This is

Просмотреть файл

@ -885,12 +885,7 @@ static void ThrowResolutionError(JSContext* cx, Handle<ModuleObject*> module,
}
RootedString filename(cx);
if (const char* chars = module->script()->filename()) {
filename =
JS_NewStringCopyUTF8Z(cx, JS::ConstUTF8CharsZ(chars, strlen(chars)));
} else {
filename = cx->names().empty;
}
filename = JS_NewStringCopyZ(cx, module->script()->filename());
if (!filename) {
return;
}

Просмотреть файл

@ -36,8 +36,6 @@ static const char* FunctionName(JSContext* cx, JSFunction* fun,
if (!fun->displayAtom()) {
return probes::anonymousName;
}
// TODO: Should be JS_EncodeStringToUTF8, but that'd introduce a rooting
// hazard, because JS_EncodeStringToUTF8 can GC.
*bytes = JS_EncodeStringToLatin1(cx, fun->displayAtom());
return *bytes ? bytes->get() : probes::nullName;
}

Просмотреть файл

@ -1835,7 +1835,7 @@ bool SavedStacks::getLocation(JSContext* cx, const FrameIter& iter,
locationp.setSource(AtomizeChars(cx, displayURL, js_strlen(displayURL)));
} else {
const char* filename = iter.filename() ? iter.filename() : "";
locationp.setSource(AtomizeUTF8Chars(cx, filename, strlen(filename)));
locationp.setSource(Atomize(cx, filename, strlen(filename)));
}
if (!locationp.source()) {
return false;
@ -1851,7 +1851,8 @@ bool SavedStacks::getLocation(JSContext* cx, const FrameIter& iter,
RootedScript script(cx, iter.script());
jsbytecode* pc = iter.pc();
PCLocationMap::AddPtr p = pcLocationMap.lookupForAdd(PCKey(script, pc));
PCKey key(script, pc);
PCLocationMap::AddPtr p = pcLocationMap.lookupForAdd(key);
if (!p) {
Rooted<JSAtom*> source(cx);
@ -1859,7 +1860,7 @@ bool SavedStacks::getLocation(JSContext* cx, const FrameIter& iter,
source = AtomizeChars(cx, displayURL, js_strlen(displayURL));
} else {
const char* filename = script->filename() ? script->filename() : "";
source = AtomizeUTF8Chars(cx, filename, strlen(filename));
source = Atomize(cx, filename, strlen(filename));
}
if (!source) {
return false;
@ -1870,7 +1871,6 @@ bool SavedStacks::getLocation(JSContext* cx, const FrameIter& iter,
uint32_t line = PCToLineNumber(script, pc, &column);
// Make the column 1-based. See comment above.
PCKey key(script, pc);
LocationValue value(source, sourceId, line, column + 1);
if (!pcLocationMap.add(p, key, value)) {
ReportOutOfMemory(cx);

Просмотреть файл

@ -340,7 +340,7 @@ using CStringCountMap = HashMap<const char*, CountBasePtr,
// `Map` must be a `HashMap` from some key type to a `CountBasePtr`.
//
// `GetName` must be a callable type which takes `const Map::Key&` and returns
// `JSAtom*`.
// `const char*`.
template <class Map, class GetName>
static PlainObject* countMapToObject(JSContext* cx, Map& map, GetName getName) {
// Build a vector of pointers to entries; sort by total; and then use
@ -374,7 +374,59 @@ static PlainObject* countMapToObject(JSContext* cx, Map& map, GetName getName) {
return nullptr;
}
JSAtom* atom = getName(entry->key());
const char* name = getName(entry->key());
MOZ_ASSERT(name);
JSAtom* atom = Atomize(cx, name, strlen(name));
if (!atom) {
return nullptr;
}
RootedId entryId(cx, AtomToId(atom));
if (!DefineDataProperty(cx, obj, entryId, thenReport)) {
return nullptr;
}
}
return obj;
}
template <class Map, class GetName>
static PlainObject* countMap16ToObject(JSContext* cx, Map& map,
GetName getName) {
// Build a vector of pointers to entries; sort by total; and then use
// that to build the result object. This makes the ordering of entries
// more interesting, and a little less non-deterministic.
JS::ubi::Vector<typename Map::Entry*> entries;
if (!entries.reserve(map.count())) {
ReportOutOfMemory(cx);
return nullptr;
}
for (auto r = map.all(); !r.empty(); r.popFront()) {
entries.infallibleAppend(&r.front());
}
if (entries.length()) {
qsort(entries.begin(), entries.length(), sizeof(*entries.begin()),
compareEntries<typename Map::Entry>);
}
Rooted<PlainObject*> obj(cx, NewPlainObject(cx));
if (!obj) {
return nullptr;
}
for (auto& entry : entries) {
CountBasePtr& thenCount = entry->value();
RootedValue thenReport(cx);
if (!thenCount->report(cx, &thenReport)) {
return nullptr;
}
const char16_t* name = getName(entry->key());
MOZ_ASSERT(name);
JSAtom* atom = AtomizeChars(cx, name, js_strlen(name));
if (!atom) {
return nullptr;
}
@ -476,10 +528,8 @@ bool ByObjectClass::report(JSContext* cx, CountBase& countBase,
Count& count = static_cast<Count&>(countBase);
Rooted<PlainObject*> obj(
cx, countMapToObject(cx, count.table, [cx](const char* key) {
MOZ_ASSERT(key);
return Atomize(cx, key, strlen(key));
}));
cx,
countMapToObject(cx, count.table, [](const char* key) { return key; }));
if (!obj) {
return false;
}
@ -586,10 +636,8 @@ bool ByDomObjectClass::report(JSContext* cx, CountBase& countBase,
Count& count = static_cast<Count&>(countBase);
Rooted<PlainObject*> obj(
cx, countMapToObject(cx, count.table, [cx](const UniqueC16String& key) {
const char16_t* chars = key.get();
MOZ_ASSERT(chars);
return AtomizeChars(cx, chars, js_strlen(chars));
cx, countMap16ToObject(cx, count.table, [](const UniqueC16String& key) {
return key.get();
}));
if (!obj) {
return false;
@ -1016,10 +1064,8 @@ bool ByFilename::report(JSContext* cx, CountBase& countBase,
Count& count = static_cast<Count&>(countBase);
Rooted<PlainObject*> obj(
cx, countMapToObject(cx, count.table, [cx](const UniqueCString& key) {
const char* utf8chars = key.get();
return AtomizeUTF8Chars(cx, utf8chars, strlen(utf8chars));
}));
cx, countMapToObject(cx, count.table,
[](const UniqueCString& key) { return key.get(); }));
if (!obj) {
return false;
}

Просмотреть файл

@ -109,7 +109,7 @@ struct FeatureArgs {
// Describes the JS scripted caller of a request to compile a wasm module.
struct ScriptedCaller {
UniqueChars filename; // UTF-8 encoded
UniqueChars filename;
bool filenameIsURL;
unsigned line;

Просмотреть файл

@ -2606,8 +2606,7 @@ JSString* Instance::createDisplayURL(JSContext* cx) {
// fetched Response.
if (metadata().filenameIsURL) {
const char* filename = metadata().filename.get();
return NewStringCopyUTF8N(cx, JS::UTF8Chars(filename, strlen(filename)));
return NewStringCopyZ<CanGC>(cx, metadata().filename.get());
}
// Otherwise, build wasm module URL from following parts:

Просмотреть файл

@ -4455,14 +4455,9 @@ static bool Reject(JSContext* cx, const CompileArgs& args,
}
RootedObject stack(cx, promise->allocationSite());
RootedString fileName(cx);
if (const char* filename = args.scriptedCaller.filename.get()) {
fileName =
JS_NewStringCopyUTF8N(cx, JS::UTF8Chars(filename, strlen(filename)));
} else {
fileName = JS_GetEmptyString(cx);
}
if (!fileName) {
RootedString filename(
cx, JS_NewStringCopyZ(cx, args.scriptedCaller.filename.get()));
if (!filename) {
return false;
}
@ -4486,7 +4481,7 @@ static bool Reject(JSContext* cx, const CompileArgs& args,
auto cause = JS::NothingHandleValue;
RootedObject errorObj(
cx, ErrorObject::create(cx, JSEXN_WASMCOMPILEERROR, stack, fileName, 0,
cx, ErrorObject::create(cx, JSEXN_WASMCOMPILEERROR, stack, filename, 0,
line, 0, nullptr, message, cause));
if (!errorObj) {
return false;

Просмотреть файл

@ -1159,7 +1159,7 @@ static nsresult JSErrorToXPCException(JSContext* cx, const char* toStringResult,
data = new nsScriptError();
data->nsIScriptError::InitWithWindowID(
bestMessage, NS_ConvertUTF8toUTF16(report->filename),
bestMessage, NS_ConvertASCIItoUTF16(report->filename),
linebuf ? nsDependentString(linebuf, report->linebufLength())
: EmptyString(),
report->lineno, report->tokenOffset(), flags, "XPConnect JavaScript"_ns,

Просмотреть файл

@ -164,7 +164,32 @@ static bool GetLocationProperty(JSContext* cx, unsigned argc, Value* vp) {
#else
JS::AutoFilename filename;
if (JS::DescribeScriptedCaller(cx, &filename) && filename.get()) {
# if defined(XP_WIN)
// convert from the system codepage to UTF-16
int bufferSize =
MultiByteToWideChar(CP_ACP, 0, filename.get(), -1, nullptr, 0);
nsAutoString filenameString;
filenameString.SetLength(bufferSize);
MultiByteToWideChar(CP_ACP, 0, filename.get(), -1,
(LPWSTR)filenameString.BeginWriting(),
filenameString.Length());
// remove the null terminator
filenameString.SetLength(bufferSize - 1);
// replace forward slashes with backslashes,
// since nsLocalFileWin chokes on them
char16_t* start = filenameString.BeginWriting();
char16_t* end = filenameString.EndWriting();
while (start != end) {
if (*start == L'/') {
*start = L'\\';
}
start++;
}
# elif defined(XP_UNIX)
NS_ConvertUTF8toUTF16 filenameString(filename.get());
# endif
nsCOMPtr<nsIFile> location;
nsresult rv =
@ -350,14 +375,28 @@ static bool Load(JSContext* cx, unsigned argc, Value* vp) {
if (!str) {
return false;
}
JS::UniqueChars filename = JS_EncodeStringToUTF8(cx, str);
JS::UniqueChars filename = JS_EncodeStringToLatin1(cx, str);
if (!filename) {
return false;
}
FILE* file = fopen(filename.get(), "r");
if (!file) {
filename = JS_EncodeStringToUTF8(cx, str);
if (!filename) {
return false;
}
JS_ReportErrorUTF8(cx, "cannot open file '%s' for reading",
filename.get());
return false;
}
JS::CompileOptions options(cx);
options.setIsRunOnce(true).setSkipFilenameValidation(true);
JS::Rooted<JSScript*> script(
cx, JS::CompileUtf8Path(cx, options, filename.get()));
options.setFileAndLine(filename.get(), 1)
.setIsRunOnce(true)
.setSkipFilenameValidation(true);
JS::Rooted<JSScript*> script(cx);
JS::Rooted<JSObject*> global(cx, JS::CurrentGlobalOrNull(cx));
script = JS::CompileUtf8File(cx, options, file);
fclose(file);
if (!script) {
return false;
}
@ -754,7 +793,9 @@ static bool ProcessFile(AutoJSAPI& jsapi, const char* filename, FILE* file,
* It's not interactive - just execute it.
*
* Support the UNIX #! shell hack; gobble the first line if it starts
* with '#'.
* with '#'. TODO - this isn't quite compatible with sharp variables,
* as a legal js program (using sharp variables) might start with '#'.
* But that would require multi-character lookahead.
*/
int ch = fgetc(file);
if (ch == '#') {
@ -766,15 +807,10 @@ static bool ProcessFile(AutoJSAPI& jsapi, const char* filename, FILE* file,
}
ungetc(ch, file);
JS::UniqueChars filenameUtf8 = JS::EncodeNarrowToUtf8(jsapi.cx(), filename);
if (!filenameUtf8) {
return false;
}
JS::RootedScript script(cx);
JS::RootedValue unused(cx);
JS::CompileOptions options(cx);
options.setFileAndLine(filenameUtf8.get(), 1)
options.setFileAndLine(filename, 1)
.setIsRunOnce(true)
.setNoScriptRval(true)
.setSkipFilenameValidation(true);

Просмотреть файл

@ -14,10 +14,7 @@ function run_test() {
load("file_that_does_not_exist.js");
subscriptLoaded = true;
} catch (ex) {
Assert.ok(
ex.message.startsWith("can't open "),
`Unexpected message: ${ex.message}`
);
Assert.equal(ex.message.substring(0, 16), "cannot open file");
}
Assert.ok(!subscriptLoaded, "load() should throw an error");
}