Bug 944121: Abstract JS shell's compilation options parsing out into its own function. r=bhackett

This commit is contained in:
Jim Blandy 2014-01-22 16:41:16 -08:00
Родитель bcdbbde4dc
Коммит f044b1e28b
3 изменённых файлов: 106 добавлений и 86 удалений

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

@ -4339,7 +4339,7 @@ JS::OwningCompileOptions::copy(JSContext *cx, const ReadOnlyCompileOptions &rhs)
}
bool
JS::OwningCompileOptions::setFileAndLine(JSContext *cx, const char *f, unsigned l)
JS::OwningCompileOptions::setFile(JSContext *cx, const char *f)
{
char *copy = nullptr;
if (f) {
@ -4352,6 +4352,15 @@ JS::OwningCompileOptions::setFileAndLine(JSContext *cx, const char *f, unsigned
js_free(const_cast<char *>(filename_));
filename_ = copy;
return true;
}
bool
JS::OwningCompileOptions::setFileAndLine(JSContext *cx, const char *f, unsigned l)
{
if (!setFile(cx, f))
return false;
lineno = l;
return true;
}

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

@ -3549,10 +3549,12 @@ class JS_FRIEND_API(OwningCompileOptions) : public ReadOnlyCompileOptions
bool copy(JSContext *cx, const ReadOnlyCompileOptions &rhs);
/* These setters make copies of their string arguments, and are fallible. */
bool setFile(JSContext *cx, const char *f);
bool setFileAndLine(JSContext *cx, const char *f, unsigned l);
bool setSourceMapURL(JSContext *cx, const jschar *s);
/* These setters are infallible, and can be chained. */
OwningCompileOptions &setLine(unsigned l) { lineno = l; return *this; }
OwningCompileOptions &setElement(JSObject *e) { elementRoot = e; return *this; }
OwningCompileOptions &setElementProperty(JSString *p) { elementPropertyRoot = p; return *this; }
OwningCompileOptions &setPrincipals(JSPrincipals *p) {
@ -3614,6 +3616,8 @@ class MOZ_STACK_CLASS JS_FRIEND_API(CompileOptions) : public ReadOnlyCompileOpti
JSObject *element() const MOZ_OVERRIDE { return elementRoot; }
JSString *elementProperty() const MOZ_OVERRIDE { return elementPropertyRoot; }
CompileOptions &setFile(const char *f) { filename_ = f; return *this; }
CompileOptions &setLine(unsigned l) { lineno = l; return *this; }
CompileOptions &setFileAndLine(const char *f, unsigned l) {
filename_ = f; lineno = l; return *this;
}

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

@ -765,6 +765,87 @@ LoadScriptRelativeToScript(JSContext *cx, unsigned argc, jsval *vp)
return LoadScript(cx, argc, vp, true);
}
// Populate |options| with the options given by |opts|'s properties. If we
// need to convert a filename to a C string, let fileNameBytes own the
// bytes.
static bool
ParseCompileOptions(JSContext *cx, CompileOptions &options, HandleObject opts,
JSAutoByteString &fileNameBytes)
{
RootedValue v(cx);
RootedString s(cx);
if (!JS_GetProperty(cx, opts, "compileAndGo", &v))
return false;
if (!v.isUndefined())
options.setCompileAndGo(ToBoolean(v));
if (!JS_GetProperty(cx, opts, "noScriptRval", &v))
return false;
if (!v.isUndefined())
options.setNoScriptRval(ToBoolean(v));
if (!JS_GetProperty(cx, opts, "fileName", &v))
return false;
if (v.isNull()) {
options.setFile(nullptr);
} else if (!v.isUndefined()) {
s = ToString(cx, v);
if (!s)
return false;
char *fileName = fileNameBytes.encodeLatin1(cx, s);
if (!fileName)
return false;
options.setFile(fileName);
}
if (!JS_GetProperty(cx, opts, "element", &v))
return false;
if (v.isObject())
options.setElement(&v.toObject());
if (!JS_GetProperty(cx, opts, "elementProperty", &v))
return false;
if (!v.isUndefined()) {
s = ToString(cx, v);
if (!s)
return false;
options.setElementProperty(s);
}
if (!JS_GetProperty(cx, opts, "lineNumber", &v))
return false;
if (!v.isUndefined()) {
uint32_t u;
if (!ToUint32(cx, v, &u))
return false;
options.setLine(u);
}
if (!JS_GetProperty(cx, opts, "sourcePolicy", &v))
return false;
if (!v.isUndefined()) {
JSString *s = ToString(cx, v);
if (!s)
return false;
char *policy = JS_EncodeStringToUTF8(cx, s);
if (!policy)
return false;
if (strcmp(policy, "NO_SOURCE") == 0) {
options.setSourcePolicy(CompileOptions::NO_SOURCE);
} else if (strcmp(policy, "LAZY_SOURCE") == 0) {
options.setSourcePolicy(CompileOptions::LAZY_SOURCE);
} else if (strcmp(policy, "SAVE_SOURCE") == 0) {
options.setSourcePolicy(CompileOptions::SAVE_SOURCE);
} else {
JS_ReportError(cx, "bad 'sourcePolicy' option: '%s'", policy);
return false;
}
}
return true;
}
class AutoNewContext
{
private:
@ -849,21 +930,17 @@ Evaluate(JSContext *cx, unsigned argc, jsval *vp)
return false;
}
bool newContext = false;
bool compileAndGo = true;
bool noScriptRval = false;
const char *fileName = "@evaluate";
RootedObject element(cx);
RootedString elementProperty(cx);
CompileOptions options(cx);
JSAutoByteString fileNameBytes;
bool newContext = false;
RootedString displayURL(cx);
RootedString sourceMapURL(cx);
unsigned lineNumber = 1;
RootedObject global(cx, nullptr);
bool catchTermination = false;
bool saveFrameChain = false;
RootedObject callerGlobal(cx, cx->global());
CompileOptions::SourcePolicy sourcePolicy = CompileOptions::SAVE_SOURCE;
options.setFileAndLine("@evaluate", 1);
global = JS_GetGlobalForObject(cx, &args.callee());
if (!global)
@ -873,47 +950,14 @@ Evaluate(JSContext *cx, unsigned argc, jsval *vp)
RootedObject opts(cx, &args[1].toObject());
RootedValue v(cx);
if (!ParseCompileOptions(cx, options, opts, fileNameBytes))
return false;
if (!JS_GetProperty(cx, opts, "newContext", &v))
return false;
if (!v.isUndefined())
newContext = ToBoolean(v);
if (!JS_GetProperty(cx, opts, "compileAndGo", &v))
return false;
if (!v.isUndefined())
compileAndGo = ToBoolean(v);
if (!JS_GetProperty(cx, opts, "noScriptRval", &v))
return false;
if (!v.isUndefined())
noScriptRval = ToBoolean(v);
if (!JS_GetProperty(cx, opts, "fileName", &v))
return false;
if (v.isNull()) {
fileName = nullptr;
} else if (!v.isUndefined()) {
JSString *s = ToString(cx, v);
if (!s)
return false;
fileName = fileNameBytes.encodeLatin1(cx, s);
if (!fileName)
return false;
}
if (!JS_GetProperty(cx, opts, "element", &v))
return false;
if (v.isObject())
element = &v.toObject();
if (!JS_GetProperty(cx, opts, "elementProperty", &v))
return false;
if (!v.isUndefined()) {
elementProperty = ToString(cx, v);
if (!elementProperty)
return false;
}
if (!JS_GetProperty(cx, opts, "displayURL", &v))
return false;
if (!v.isUndefined()) {
@ -930,15 +974,6 @@ Evaluate(JSContext *cx, unsigned argc, jsval *vp)
return false;
}
if (!JS_GetProperty(cx, opts, "lineNumber", &v))
return false;
if (!v.isUndefined()) {
uint32_t u;
if (!ToUint32(cx, v, &u))
return false;
lineNumber = u;
}
if (!JS_GetProperty(cx, opts, "global", &v))
return false;
if (!v.isUndefined()) {
@ -963,28 +998,6 @@ Evaluate(JSContext *cx, unsigned argc, jsval *vp)
return false;
if (!v.isUndefined())
saveFrameChain = ToBoolean(v);
if (!JS_GetProperty(cx, opts, "sourcePolicy", &v))
return false;
if (!v.isUndefined()) {
JSString *s = ToString(cx, v);
if (!s)
return false;
char *policy = JS_EncodeStringToUTF8(cx, s);
if (!policy)
return false;
if (strcmp(policy, "NO_SOURCE") == 0) {
sourcePolicy = CompileOptions::NO_SOURCE;
} else if (strcmp(policy, "LAZY_SOURCE") == 0) {
sourcePolicy = CompileOptions::LAZY_SOURCE;
} else if (strcmp(policy, "SAVE_SOURCE") == 0) {
sourcePolicy = CompileOptions::SAVE_SOURCE;
} else {
JS_ReportError(cx, "bad 'sourcePolicy' option passed to 'evaluate': '%s'",
policy);
return false;
}
}
}
RootedString code(cx, args[0].toString());
@ -1009,19 +1022,13 @@ Evaluate(JSContext *cx, unsigned argc, jsval *vp)
JSAutoCompartment ac(cx, global);
RootedScript script(cx);
{
JS::AutoSaveContextOptions asco(cx);
JS::ContextOptionsRef(cx).setNoScriptRval(noScriptRval);
CompileOptions options(cx);
options.setFileAndLine(fileName, lineNumber)
.setElement(element)
.setElementProperty(elementProperty)
.setSourcePolicy(sourcePolicy)
.setCompileAndGo(compileAndGo);
if (!options.wrap(cx, cx->compartment()))
return false;
{
JS::AutoSaveContextOptions asco(cx);
JS::ContextOptionsRef(cx).setNoScriptRval(options.noScriptRval);
script = JS::Compile(cx, global, options, codeChars, codeLength);
if (!script)
return false;