Bug 944164 - Move a bunch of file-related stuff onto an os.file object, creating aliases from the old names, r=jorendorff

This commit is contained in:
Steve Fink
2015-05-13 15:16:26 -07:00
parent 0c81a173e9
commit 6d1314c800
4 changed files with 363 additions and 284 deletions

View File

@@ -11,6 +11,7 @@
#include <errno.h>
#include <stdlib.h>
#ifdef XP_WIN
#include <direct.h>
#include <process.h>
#include <string.h>
#else
@@ -18,13 +19,262 @@
#include <unistd.h>
#endif
#include "jsapi.h"
// For JSFunctionSpecWithHelp
#include "jsfriendapi.h"
#include "jsobj.h"
#ifdef XP_WIN
# include "jswin.h"
#endif
#include "jswrapper.h"
#include "js/Conversions.h"
#include "shell/jsshell.h"
#include "vm/TypedArrayObject.h"
#include "jsobjinlines.h"
#ifdef XP_WIN
# define PATH_MAX (MAX_PATH > _MAX_DIR ? MAX_PATH : _MAX_DIR)
# define getcwd _getcwd
#else
# include <libgen.h>
#endif
using namespace JS;
namespace js {
namespace shell {
/*
* Resolve a (possibly) relative filename to an absolute path. If
* |scriptRelative| is true, then the result will be relative to the directory
* containing the currently-running script, or the current working directory if
* the currently-running script is "-e" (namely, you're using it from the
* command line.) Otherwise, it will be relative to the current working
* directory.
*/
JSString*
ResolvePath(JSContext* cx, HandleString filenameStr, PathResolutionMode resolveMode)
{
JSAutoByteString filename(cx, filenameStr);
if (!filename)
return nullptr;
const char* pathname = filename.ptr();
if (pathname[0] == '/')
return filenameStr;
#ifdef XP_WIN
// Various forms of absolute paths per http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx
// "\..."
if (pathname[0] == '\\')
return filenameStr;
// "C:\..."
if (strlen(pathname) > 3 && isalpha(pathname[0]) && pathname[1] == ':' && pathname[2] == '\\')
return filenameStr;
// "\\..."
if (strlen(pathname) > 2 && pathname[1] == '\\' && pathname[2] == '\\')
return filenameStr;
#endif
/* Get the currently executing script's name. */
JS::AutoFilename scriptFilename;
if (!DescribeScriptedCaller(cx, &scriptFilename))
return nullptr;
if (!scriptFilename.get())
return nullptr;
if (strcmp(scriptFilename.get(), "-e") == 0 || strcmp(scriptFilename.get(), "typein") == 0)
resolveMode = RootRelative;
static char buffer[PATH_MAX+1];
if (resolveMode == ScriptRelative) {
#ifdef XP_WIN
// The docs say it can return EINVAL, but the compiler says it's void
_splitpath(scriptFilename.get(), nullptr, buffer, nullptr, nullptr);
#else
strncpy(buffer, scriptFilename.get(), PATH_MAX+1);
if (buffer[PATH_MAX] != '\0')
return nullptr;
// dirname(buffer) might return buffer, or it might return a
// statically-allocated string
memmove(buffer, dirname(buffer), strlen(buffer) + 1);
#endif
} else {
const char* cwd = getcwd(buffer, PATH_MAX);
if (!cwd)
return nullptr;
}
size_t len = strlen(buffer);
buffer[len] = '/';
strncpy(buffer + len + 1, pathname, sizeof(buffer) - (len+1));
if (buffer[PATH_MAX] != '\0')
return nullptr;
return JS_NewStringCopyZ(cx, buffer);
}
static JSObject*
FileAsTypedArray(JSContext* cx, const char* pathname)
{
FILE* file = fopen(pathname, "rb");
if (!file) {
JS_ReportError(cx, "can't open %s: %s", pathname, strerror(errno));
return nullptr;
}
AutoCloseInputFile autoClose(file);
RootedObject obj(cx);
if (fseek(file, 0, SEEK_END) != 0) {
JS_ReportError(cx, "can't seek end of %s", pathname);
} else {
size_t len = ftell(file);
if (fseek(file, 0, SEEK_SET) != 0) {
JS_ReportError(cx, "can't seek start of %s", pathname);
} else {
obj = JS_NewUint8Array(cx, len);
if (!obj)
return nullptr;
char* buf = (char*) obj->as<js::TypedArrayObject>().viewData();
size_t cc = fread(buf, 1, len, file);
if (cc != len) {
JS_ReportError(cx, "can't read %s: %s", pathname,
(ptrdiff_t(cc) < 0) ? strerror(errno) : "short read");
obj = nullptr;
}
}
}
return obj;
}
static bool
ReadFile(JSContext* cx, unsigned argc, jsval* vp, bool scriptRelative)
{
CallArgs args = CallArgsFromVp(argc, vp);
if (args.length() < 1 || args.length() > 2) {
JS_ReportErrorNumber(cx, js::shell::my_GetErrorMessage, nullptr,
args.length() < 1 ? JSSMSG_NOT_ENOUGH_ARGS : JSSMSG_TOO_MANY_ARGS,
"snarf");
return false;
}
if (!args[0].isString() || (args.length() == 2 && !args[1].isString())) {
JS_ReportErrorNumber(cx, js::shell::my_GetErrorMessage, nullptr, JSSMSG_INVALID_ARGS, "snarf");
return false;
}
RootedString givenPath(cx, args[0].toString());
RootedString str(cx, js::shell::ResolvePath(cx, givenPath, scriptRelative ? ScriptRelative : RootRelative));
if (!str)
return false;
JSAutoByteString filename(cx, str);
if (!filename)
return false;
if (args.length() > 1) {
JSString* opt = JS::ToString(cx, args[1]);
if (!opt)
return false;
bool match;
if (!JS_StringEqualsAscii(cx, opt, "binary", &match))
return false;
if (match) {
JSObject* obj;
if (!(obj = FileAsTypedArray(cx, filename.ptr())))
return false;
args.rval().setObject(*obj);
return true;
}
}
if (!(str = FileAsString(cx, filename.ptr())))
return false;
args.rval().setString(str);
return true;
}
static bool
osfile_readFile(JSContext* cx, unsigned argc, jsval* vp)
{
return ReadFile(cx, argc, vp, false);
}
static bool
osfile_readRelativeToScript(JSContext* cx, unsigned argc, jsval* vp)
{
return ReadFile(cx, argc, vp, true);
}
static bool
Redirect(JSContext* cx, FILE* fp, HandleString relFilename)
{
RootedString filename(cx, ResolvePath(cx, relFilename, RootRelative));
if (!filename)
return false;
JSAutoByteString filenameABS(cx, filename);
if (!filenameABS)
return false;
if (freopen(filenameABS.ptr(), "wb", fp) == nullptr) {
JS_ReportError(cx, "cannot redirect to %s: %s", filenameABS.ptr(), strerror(errno));
return false;
}
return true;
}
static bool
osfile_redirect(JSContext* cx, unsigned argc, jsval* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
if (args.length() < 1 || args.length() > 2) {
JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr, JSSMSG_INVALID_ARGS, "redirect");
return false;
}
if (args[0].isString()) {
RootedString stdoutPath(cx, args[0].toString());
if (!stdoutPath)
return false;
if (!Redirect(cx, stdout, stdoutPath))
return false;
}
if (args.length() > 1 && args[1].isString()) {
RootedString stderrPath(cx, args[1].toString());
if (!stderrPath)
return false;
if (!Redirect(cx, stderr, stderrPath))
return false;
}
args.rval().setUndefined();
return true;
}
static const JSFunctionSpecWithHelp osfile_functions[] = {
JS_FN_HELP("readFile", osfile_readFile, 1, 0,
"readFile(filename, [\"binary\"])",
" Read filename into returned string. Filename is relative to the current\n"
" working directory."),
JS_FN_HELP("readRelativeToScript", osfile_readRelativeToScript, 1, 0,
"readRelativeToScript(filename, [\"binary\"])",
" Read filename into returned string. Filename is relative to the directory\n"
" containing the current script."),
JS_FN_HELP("redirect", osfile_redirect, 2, 0,
"redirect(stdoutFilename[, stderrFilename])",
" Redirect stdout and/or stderr to the named file. Pass undefined to avoid\n"
" redirecting. Filenames are relative to the current working directory."),
JS_FS_HELP_END
};
static bool
os_getenv(JSContext* cx, unsigned argc, Value* vp)
{
@@ -292,14 +542,54 @@ static const JSFunctionSpecWithHelp os_functions[] = {
" The return value is an object containing a 'pid' field, if a process was waitable\n"
" and an 'exitStatus' field if a pid exited."),
#endif
JS_FS_HELP_END
};
bool
js::DefineOS(JSContext* cx, HandleObject global)
DefineOS(JSContext* cx, HandleObject global, bool fuzzingSafe)
{
RootedObject obj(cx, JS_NewPlainObject(cx));
return obj &&
JS_DefineFunctionsWithHelp(cx, obj, os_functions) &&
JS_DefineProperty(cx, global, "os", obj, 0);
if (!obj || !JS_DefineProperty(cx, global, "os", obj, 0))
return false;
if (!fuzzingSafe) {
if (!JS_DefineFunctionsWithHelp(cx, obj, os_functions))
return false;
}
RootedObject osfile(cx, JS_NewPlainObject(cx));
if (!osfile ||
!JS_DefineFunctionsWithHelp(cx, osfile, osfile_functions) ||
!JS_DefineProperty(cx, obj, "file", osfile, 0))
{
return false;
}
// For backwards compatibility, expose various os.file.* functions as
// direct methods on the global.
RootedValue val(cx);
struct {
const char* src;
const char* dst;
} osfile_exports[] = {
{ "readFile", "read" },
{ "readFile", "snarf" },
{ "readRelativeToScript", "readRelativeToScript" },
{ "redirect", "redirect" }
};
for (auto pair : osfile_exports) {
if (!JS_GetProperty(cx, osfile, pair.src, &val))
return false;
RootedObject function(cx, &val.toObject());
if (!JS_DefineProperty(cx, global, pair.dst, function, 0))
return false;
}
return true;
}
}
}

View File

@@ -12,11 +12,21 @@
#include "jsapi.h"
namespace js {
namespace shell {
/* Define an os object on the given global object. */
bool
DefineOS(JSContext* cx, JS::HandleObject global);
DefineOS(JSContext* cx, JS::HandleObject global, bool fuzzingSafe);
enum PathResolutionMode {
RootRelative,
ScriptRelative
};
JSString*
ResolvePath(JSContext* cx, JS::HandleString filenameStr, PathResolutionMode resolveMode);
}
}
#endif /* shell_OSObject_h */

View File

@@ -86,14 +86,9 @@
#include "vm/Interpreter-inl.h"
#include "vm/Stack-inl.h"
#ifdef XP_WIN
# define PATH_MAX (MAX_PATH > _MAX_DIR ? MAX_PATH : _MAX_DIR)
#else
# include <libgen.h>
#endif
using namespace js;
using namespace js::cli;
using namespace js::shell;
using mozilla::ArrayLength;
using mozilla::MakeUnique;
@@ -110,11 +105,6 @@ enum JSShellExitCode {
EXITCODE_TIMEOUT = 6
};
enum PathResolutionMode {
RootRelative,
ScriptRelative
};
static size_t gStackChunkSize = 8192;
/*
@@ -195,14 +185,6 @@ static bool dumpEntrainedVariables = false;
static bool OOM_printAllocationCount = false;
#endif
enum JSShellErrNum {
#define MSG_DEF(name, count, exception, format) \
name,
#include "jsshell.msg"
#undef MSG_DEF
JSShellErr_Limit
};
static JSContext*
NewContext(JSRuntime* rt);
@@ -213,12 +195,6 @@ static JSObject*
NewGlobalObject(JSContext* cx, JS::CompartmentOptions& options,
JSPrincipals* principals);
static const JSErrorFormatString*
my_GetErrorMessage(void* userRef, const unsigned errorNumber);
static void
my_ErrorReporter(JSContext* cx, const char* message, JSErrorReport* report);
/*
* A toy principals type for the shell.
*
@@ -565,18 +541,6 @@ ReadEvalPrintLoop(JSContext* cx, FILE* in, FILE* out, bool compileOnly)
fprintf(out, "\n");
}
class AutoCloseInputFile
{
private:
FILE* f_;
public:
explicit AutoCloseInputFile(FILE* f) : f_(f) {}
~AutoCloseInputFile() {
if (f_ && f_ != stdin)
fclose(f_);
}
};
static void
Process(JSContext* cx, const char* filename, bool forceTTY)
{
@@ -631,77 +595,6 @@ Version(JSContext* cx, unsigned argc, jsval* vp)
return true;
}
/*
* Resolve a (possibly) relative filename to an absolute path. If
* |scriptRelative| is true, then the result will be relative to the directory
* containing the currently-running script, or the current working directory if
* the currently-running script is "-e" (namely, you're using it from the
* command line.) Otherwise, it will be relative to the current working
* directory.
*/
static JSString*
ResolvePath(JSContext* cx, HandleString filenameStr, PathResolutionMode resolveMode)
{
JSAutoByteString filename(cx, filenameStr);
if (!filename)
return nullptr;
const char* pathname = filename.ptr();
if (pathname[0] == '/')
return filenameStr;
#ifdef XP_WIN
// Various forms of absolute paths per http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx
// "\..."
if (pathname[0] == '\\')
return filenameStr;
// "C:\..."
if (strlen(pathname) > 3 && isalpha(pathname[0]) && pathname[1] == ':' && pathname[2] == '\\')
return filenameStr;
// "\\..."
if (strlen(pathname) > 2 && pathname[1] == '\\' && pathname[2] == '\\')
return filenameStr;
#endif
/* Get the currently executing script's name. */
JS::AutoFilename scriptFilename;
if (!DescribeScriptedCaller(cx, &scriptFilename))
return nullptr;
if (!scriptFilename.get())
return nullptr;
if (strcmp(scriptFilename.get(), "-e") == 0 || strcmp(scriptFilename.get(), "typein") == 0)
resolveMode = RootRelative;
static char buffer[PATH_MAX+1];
if (resolveMode == ScriptRelative) {
#ifdef XP_WIN
// The docs say it can return EINVAL, but the compiler says it's void
_splitpath(scriptFilename.get(), nullptr, buffer, nullptr, nullptr);
#else
strncpy(buffer, scriptFilename.get(), PATH_MAX+1);
if (buffer[PATH_MAX] != '\0')
return nullptr;
// dirname(buffer) might return buffer, or it might return a
// statically-allocated string
memmove(buffer, dirname(buffer), strlen(buffer) + 1);
#endif
} else {
const char* cwd = getcwd(buffer, PATH_MAX);
if (!cwd)
return nullptr;
}
size_t len = strlen(buffer);
buffer[len] = '/';
strncpy(buffer + len + 1, pathname, sizeof(buffer) - (len+1));
if (buffer[PATH_MAX] != '\0')
return nullptr;
return JS_NewStringCopyZ(cx, buffer);
}
static bool
CreateMappedArrayBuffer(JSContext* cx, unsigned argc, Value* vp)
{
@@ -1366,8 +1259,8 @@ Evaluate(JSContext* cx, unsigned argc, jsval* vp)
return JS_WrapValue(cx, args.rval());
}
static JSString*
FileAsString(JSContext* cx, const char* pathname)
JSString*
js::shell::FileAsString(JSContext* cx, const char* pathname)
{
FILE* file;
RootedString str(cx);
@@ -1412,39 +1305,6 @@ FileAsString(JSContext* cx, const char* pathname)
return str;
}
static JSObject*
FileAsTypedArray(JSContext* cx, const char* pathname)
{
FILE* file = fopen(pathname, "rb");
if (!file) {
JS_ReportError(cx, "can't open %s: %s", pathname, strerror(errno));
return nullptr;
}
AutoCloseInputFile autoClose(file);
RootedObject obj(cx);
if (fseek(file, 0, SEEK_END) != 0) {
JS_ReportError(cx, "can't seek end of %s", pathname);
} else {
size_t len = ftell(file);
if (fseek(file, 0, SEEK_SET) != 0) {
JS_ReportError(cx, "can't seek start of %s", pathname);
} else {
obj = JS_NewUint8Array(cx, len);
if (!obj)
return nullptr;
char* buf = (char*) obj->as<TypedArrayObject>().viewData();
size_t cc = fread(buf, 1, len, file);
if (cc != len) {
JS_ReportError(cx, "can't read %s: %s", pathname,
(ptrdiff_t(cc) < 0) ? strerror(errno) : "short read");
obj = nullptr;
}
}
}
return obj;
}
/*
* Function to run scripts and return compilation + execution time. Semantics
* are closely modelled after the equivalent function in WebKit, as this is used
@@ -3592,112 +3452,6 @@ struct FreeOnReturn
}
};
static bool
ReadFile(JSContext* cx, unsigned argc, jsval* vp, bool scriptRelative)
{
CallArgs args = CallArgsFromVp(argc, vp);
if (args.length() < 1 || args.length() > 2) {
JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr,
args.length() < 1 ? JSSMSG_NOT_ENOUGH_ARGS : JSSMSG_TOO_MANY_ARGS,
"snarf");
return false;
}
if (!args[0].isString() || (args.length() == 2 && !args[1].isString())) {
JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr, JSSMSG_INVALID_ARGS, "snarf");
return false;
}
RootedString givenPath(cx, args[0].toString());
RootedString str(cx, ResolvePath(cx, givenPath, scriptRelative ? ScriptRelative : RootRelative));
if (!str)
return false;
JSAutoByteString filename(cx, str);
if (!filename)
return false;
if (args.length() > 1) {
JSString* opt = JS::ToString(cx, args[1]);
if (!opt)
return false;
bool match;
if (!JS_StringEqualsAscii(cx, opt, "binary", &match))
return false;
if (match) {
JSObject* obj;
if (!(obj = FileAsTypedArray(cx, filename.ptr())))
return false;
args.rval().setObject(*obj);
return true;
}
}
if (!(str = FileAsString(cx, filename.ptr())))
return false;
args.rval().setString(str);
return true;
}
static bool
Snarf(JSContext* cx, unsigned argc, jsval* vp)
{
return ReadFile(cx, argc, vp, false);
}
static bool
ReadRelativeToScript(JSContext* cx, unsigned argc, jsval* vp)
{
return ReadFile(cx, argc, vp, true);
}
static bool
redirect(JSContext* cx, FILE* fp, HandleString relFilename)
{
RootedString filename(cx, ResolvePath(cx, relFilename, RootRelative));
if (!filename)
return false;
JSAutoByteString filenameABS(cx, filename);
if (!filenameABS)
return false;
if (freopen(filenameABS.ptr(), "wb", fp) == nullptr) {
JS_ReportError(cx, "cannot redirect to %s: %s", filenameABS.ptr(), strerror(errno));
return false;
}
return true;
}
static bool
RedirectOutput(JSContext* cx, unsigned argc, jsval* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
if (args.length() < 1 || args.length() > 2) {
JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr, JSSMSG_INVALID_ARGS, "redirect");
return false;
}
if (args[0].isString()) {
RootedString stdoutPath(cx, args[0].toString());
if (!stdoutPath)
return false;
if (!redirect(cx, stdout, stdoutPath))
return false;
}
if (args.length() > 1 && args[1].isString()) {
RootedString stderrPath(cx, args[1].toString());
if (!stderrPath)
return false;
if (!redirect(cx, stderr, stderrPath))
return false;
}
args.rval().setUndefined();
return true;
}
static int sArgc;
static char** sArgv;
@@ -4512,6 +4266,7 @@ ReflectTrackedOptimizations(JSContext* cx, unsigned argc, Value* vp)
return true;
}
namespace js {
namespace shell {
class ShellAutoEntryMonitor : JS::dbg::AutoEntryMonitor {
@@ -4583,6 +4338,7 @@ class ShellAutoEntryMonitor : JS::dbg::AutoEntryMonitor {
};
} // namespace shell
} // namespace js
static bool
EntryPoints(JSContext* cx, unsigned argc, Value* vp)
@@ -4605,7 +4361,7 @@ EntryPoints(JSContext* cx, unsigned argc, Value* vp)
if (!JS_GetProperty(cx, opts, "function", &fun))
return false;
if (!fun.isUndefined()) {
shell::ShellAutoEntryMonitor sarep(cx);
js::shell::ShellAutoEntryMonitor sarep(cx);
if (!Call(cx, UndefinedHandleValue, fun, JS::HandleValueArray::empty(), &dummy))
return false;
return sarep.buildResult(cx, args.rval());
@@ -4635,7 +4391,7 @@ EntryPoints(JSContext* cx, unsigned argc, Value* vp)
if (!JS_GetProperty(cx, opts, "value", &valuev))
return false;
shell::ShellAutoEntryMonitor sarep(cx);
js::shell::ShellAutoEntryMonitor sarep(cx);
if (!valuev.isUndefined()) {
if (!JS_SetPropertyById(cx, object, id, valuev))
@@ -4656,7 +4412,7 @@ EntryPoints(JSContext* cx, unsigned argc, Value* vp)
if (!JS_GetProperty(cx, opts, "ToString", &v))
return false;
if (!v.isUndefined()) {
shell::ShellAutoEntryMonitor sarep(cx);
js::shell::ShellAutoEntryMonitor sarep(cx);
if (!JS::ToString(cx, v))
return false;
return sarep.buildResult(cx, args.rval());
@@ -4671,7 +4427,7 @@ EntryPoints(JSContext* cx, unsigned argc, Value* vp)
if (!JS_GetProperty(cx, opts, "ToNumber", &v))
return false;
if (!v.isUndefined()) {
shell::ShellAutoEntryMonitor sarep(cx);
js::shell::ShellAutoEntryMonitor sarep(cx);
if (!JS::ToNumber(cx, v, &dummy))
return false;
return sarep.buildResult(cx, args.rval());
@@ -4699,7 +4455,7 @@ EntryPoints(JSContext* cx, unsigned argc, Value* vp)
options.setIntroductionType("entryPoint eval")
.setFileAndLine("entryPoint eval", 1);
shell::ShellAutoEntryMonitor sarep(cx);
js::shell::ShellAutoEntryMonitor sarep(cx);
if (!JS::Evaluate(cx, options, chars, length, &dummy))
return false;
return sarep.buildResult(cx, args.rval());
@@ -4905,20 +4661,6 @@ static const JSFunctionSpecWithHelp shell_functions[] = {
"sleep(dt)",
" Sleep for dt seconds."),
JS_FN_HELP("snarf", Snarf, 1, 0,
"snarf(filename, [\"binary\"])",
" Read filename into returned string. Filename is relative to the current\n"
" working directory."),
JS_FN_HELP("read", Snarf, 1, 0,
"read(filename, [\"binary\"])",
" Synonym for snarf."),
JS_FN_HELP("readRelativeToScript", ReadRelativeToScript, 1, 0,
"readRelativeToScript(filename, [\"binary\"])",
" Read filename into returned string. Filename is relative to the directory\n"
" containing the current script."),
JS_FN_HELP("compile", Compile, 1, 0,
"compile(code)",
" Compiles a string to bytecode, potentially throwing."),
@@ -5111,11 +4853,6 @@ static const JSFunctionSpecWithHelp fuzzing_unsafe_functions[] = {
"pc2line(fun[, pc])",
" Map PC to line number."),
JS_FN_HELP("redirect", RedirectOutput, 2, 0,
"redirect(stdoutFilename[, stderrFilename])",
" Redirect stdout and/or stderr to the named file. Pass undefined to avoid\n"
" redirecting. Filenames are relative to the current working directory."),
JS_FN_HELP("nestedShell", NestedShell, 0, 0,
"nestedShell(shellArgs...)",
" Execute the given code in a new JS shell process, passing this nested shell\n"
@@ -5294,8 +5031,8 @@ static const JSErrorFormatString jsShell_ErrorFormatString[JSShellErr_Limit] = {
#undef MSG_DEF
};
static const JSErrorFormatString*
my_GetErrorMessage(void* userRef, const unsigned errorNumber)
const JSErrorFormatString*
js::shell::my_GetErrorMessage(void* userRef, const unsigned errorNumber)
{
if (errorNumber == 0 || errorNumber >= JSShellErr_Limit)
return nullptr;
@@ -5303,8 +5040,8 @@ my_GetErrorMessage(void* userRef, const unsigned errorNumber)
return &jsShell_ErrorFormatString[errorNumber];
}
static void
my_ErrorReporter(JSContext* cx, const char* message, JSErrorReport* report)
void
js::shell::my_ErrorReporter(JSContext* cx, const char* message, JSErrorReport* report)
{
gGotError = PrintError(cx, gErrFile, message, report, reportWarnings);
if (report->exnType != JSEXN_NONE && !JSREPORT_IS_WARNING(report->flags)) {
@@ -5889,12 +5626,13 @@ NewGlobalObject(JSContext* cx, JS::CompartmentOptions& options,
if (!fuzzingSafe) {
if (!JS_DefineFunctionsWithHelp(cx, glob, fuzzing_unsafe_functions))
return nullptr;
if (!js::DefineOS(cx, glob))
return nullptr;
if (!DefineConsole(cx, glob))
return nullptr;
}
if (!DefineOS(cx, glob, fuzzingSafe))
return nullptr;
RootedObject performanceObj(cx, JS_NewObject(cx, nullptr));
if (!performanceObj)
return nullptr;

41
js/src/shell/jsshell.h Normal file
View File

@@ -0,0 +1,41 @@
#ifndef jsshell_js_h
#define jsshell_js_h
#include "jsapi.h"
namespace js {
namespace shell {
enum JSShellErrNum {
#define MSG_DEF(name, count, exception, format) \
name,
#include "jsshell.msg"
#undef MSG_DEF
JSShellErr_Limit
};
const JSErrorFormatString*
my_GetErrorMessage(void* userRef, const unsigned errorNumber);
static void
my_ErrorReporter(JSContext* cx, const char* message, JSErrorReport* report);
JSString*
FileAsString(JSContext* cx, const char* pathname);
class AutoCloseInputFile
{
private:
FILE* f_;
public:
explicit AutoCloseInputFile(FILE* f) : f_(f) {}
~AutoCloseInputFile() {
if (f_ && f_ != stdin)
fclose(f_);
}
};
} /* namespace shell */
} /* namespace js */
#endif