зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 9 changesets (bug 1492090
) for causing multiple xpcshell failures.
Backed out changeset 1e0705e94f79 (bug1492090
) Backed out changeset aeee4b4981b4 (bug1492090
) Backed out changeset ed83091dfdb5 (bug1492090
) Backed out changeset d2604a65c523 (bug1492090
) Backed out changeset e4aad0fb85b9 (bug1492090
) Backed out changeset 4e7c4724e994 (bug1492090
) Backed out changeset bc39eac4ecca (bug1492090
) Backed out changeset 8e3b95812c39 (bug1492090
) Backed out changeset ddb2eb1a1c62 (bug1492090
)
This commit is contained in:
Родитель
83a76a1352
Коммит
d73773412a
|
@ -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");
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче