зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1337465 - Create proper help strings for JS shell namespace objects, r=jonco
MozReview-Commit-ID: Ha6gkvgUIgZ --HG-- extra : rebase_source : 9272fd8f06280b19a25250fa43d970cfa72389a6
This commit is contained in:
Родитель
cce5817930
Коммит
3c066c06e6
|
@ -1001,25 +1001,30 @@ DefineOS(JSContext* cx, HandleObject global,
|
||||||
|
|
||||||
// For backwards compatibility, expose various os.file.* functions as
|
// For backwards compatibility, expose various os.file.* functions as
|
||||||
// direct methods on the global.
|
// direct methods on the global.
|
||||||
RootedValue val(cx);
|
struct Export {
|
||||||
|
|
||||||
struct {
|
|
||||||
const char* src;
|
const char* src;
|
||||||
const char* dst;
|
const char* dst;
|
||||||
} osfile_exports[] = {
|
};
|
||||||
|
|
||||||
|
const Export osfile_exports[] = {
|
||||||
{ "readFile", "read" },
|
{ "readFile", "read" },
|
||||||
{ "readFile", "snarf" },
|
{ "readFile", "snarf" },
|
||||||
{ "readRelativeToScript", "readRelativeToScript" },
|
{ "readRelativeToScript", "readRelativeToScript" },
|
||||||
{ "redirect", "redirect" },
|
|
||||||
{ "redirectErr", "redirectErr" }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
for (auto pair : osfile_exports) {
|
for (auto pair : osfile_exports) {
|
||||||
if (!JS_GetProperty(cx, osfile, pair.src, &val))
|
if (!CreateAlias(cx, pair.dst, osfile, pair.src))
|
||||||
return false;
|
return false;
|
||||||
if (val.isObject()) {
|
}
|
||||||
RootedObject function(cx, &val.toObject());
|
|
||||||
if (!JS_DefineProperty(cx, global, pair.dst, function, 0))
|
if (!fuzzingSafe) {
|
||||||
|
const Export unsafe_osfile_exports[] = {
|
||||||
|
{ "redirect", "redirect" },
|
||||||
|
{ "redirectErr", "redirectErr" }
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto pair : unsafe_osfile_exports) {
|
||||||
|
if (!CreateAlias(cx, pair.dst, osfile, pair.src))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,18 @@ using namespace JS;
|
||||||
namespace js {
|
namespace js {
|
||||||
namespace shell {
|
namespace shell {
|
||||||
|
|
||||||
|
// Generate 'usage' and 'help' properties for the given object.
|
||||||
|
// JS_DefineFunctionsWithHelp will define individual function objects with both
|
||||||
|
// of those properties (eg getpid.usage = "getpid()" and getpid.help = "return
|
||||||
|
// the process id"). This function will generate strings for an "interface
|
||||||
|
// object", eg os.file, which contains some number of functions.
|
||||||
|
//
|
||||||
|
// .usage will be set to "<name> - interface object".
|
||||||
|
//
|
||||||
|
// .help will be set to a newline-separated list of functions that have either
|
||||||
|
// 'help' or 'usage' properties. Functions are described with their usage
|
||||||
|
// strings, if they have them, else with just their names.
|
||||||
|
//
|
||||||
bool
|
bool
|
||||||
GenerateInterfaceHelp(JSContext* cx, HandleObject obj, const char* name)
|
GenerateInterfaceHelp(JSContext* cx, HandleObject obj, const char* name)
|
||||||
{
|
{
|
||||||
|
@ -26,45 +38,68 @@ GenerateInterfaceHelp(JSContext* cx, HandleObject obj, const char* name)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
StringBuffer buf(cx);
|
StringBuffer buf(cx);
|
||||||
if (!buf.append(' '))
|
if (!buf.append(name, strlen(name)) || !buf.append(" - interface object", 19))
|
||||||
return false;
|
return false;
|
||||||
|
RootedString s(cx, buf.finishString());
|
||||||
|
if (!s || !JS_DefineProperty(cx, obj, "usage", s, 0))
|
||||||
|
return false;
|
||||||
|
buf.clear();
|
||||||
|
|
||||||
|
bool first = true;
|
||||||
for (size_t i = 0; i < idv.length(); i++) {
|
for (size_t i = 0; i < idv.length(); i++) {
|
||||||
RootedValue v(cx);
|
|
||||||
RootedId id(cx, idv[i]);
|
RootedId id(cx, idv[i]);
|
||||||
|
RootedValue v(cx);
|
||||||
if (!JS_GetPropertyById(cx, obj, id, &v))
|
if (!JS_GetPropertyById(cx, obj, id, &v))
|
||||||
return false;
|
return false;
|
||||||
if (!v.isObject())
|
if (!v.isObject())
|
||||||
continue;
|
continue;
|
||||||
bool hasHelp = false;
|
|
||||||
RootedObject prop(cx, &v.toObject());
|
RootedObject prop(cx, &v.toObject());
|
||||||
if (!JS_GetProperty(cx, prop, "usage", &v))
|
|
||||||
|
RootedValue usage(cx);
|
||||||
|
RootedValue help(cx);
|
||||||
|
if (!JS_GetProperty(cx, prop, "usage", &usage))
|
||||||
return false;
|
return false;
|
||||||
if (v.isString())
|
if (!JS_GetProperty(cx, prop, "help", &help))
|
||||||
hasHelp = true;
|
return false;
|
||||||
if (!JS_GetProperty(cx, prop, "help", &v))
|
if (!usage.isString() && !help.isString())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!first && !buf.append("\n"))
|
||||||
|
return false;
|
||||||
|
first = false;
|
||||||
|
|
||||||
|
if (!buf.append(" ", 2))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!buf.append(usage.isString() ? usage.toString() : JSID_TO_FLAT_STRING(id)))
|
||||||
return false;
|
return false;
|
||||||
if (v.isString())
|
|
||||||
hasHelp = true;
|
|
||||||
if (hasHelp) {
|
|
||||||
if (!buf.append(' ') ||
|
|
||||||
!buf.append(name, strlen(name)) ||
|
|
||||||
!buf.append('.') ||
|
|
||||||
!buf.append(JSID_TO_FLAT_STRING(id)))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RootedString s(cx, buf.finishString());
|
s = buf.finishString();
|
||||||
if (!s || !JS_DefineProperty(cx, obj, "help", s, 0))
|
if (!s || !JS_DefineProperty(cx, obj, "help", s, 0))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!buf.append(name, strlen(name)) || !buf.append(" - interface object", 20))
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CreateAlias(JSContext* cx, const char* dstName, JS::HandleObject namespaceObj, const char* srcName)
|
||||||
|
{
|
||||||
|
RootedObject global(cx, JS_GetGlobalForObject(cx, namespaceObj));
|
||||||
|
if (!global)
|
||||||
return false;
|
return false;
|
||||||
s = buf.finishString();
|
|
||||||
if (!s || !JS_DefineProperty(cx, obj, "usage", s, 0))
|
RootedValue val(cx);
|
||||||
|
if (!JS_GetProperty(cx, namespaceObj, srcName, &val))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!val.isObject()) {
|
||||||
|
JS_ReportErrorASCII(cx, "attempted to alias nonexistent function");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
RootedObject function(cx, &val.toObject());
|
||||||
|
if (!JS_DefineProperty(cx, global, dstName, function, 0))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -78,6 +78,18 @@ struct RCFile {
|
||||||
bool release();
|
bool release();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Alias the global dstName to namespaceObj.srcName. For example, if dstName is
|
||||||
|
// "snarf", namespaceObj represents "os.file", and srcName is "readFile", then
|
||||||
|
// this is equivalent to the JS code:
|
||||||
|
//
|
||||||
|
// snarf = os.file.readFile;
|
||||||
|
//
|
||||||
|
// This provides a mechanism for namespacing the various JS shell helper
|
||||||
|
// functions without breaking backwards compatibility with things that use the
|
||||||
|
// global names.
|
||||||
|
bool
|
||||||
|
CreateAlias(JSContext* cx, const char* dstName, JS::HandleObject namespaceObj, const char* srcName);
|
||||||
|
|
||||||
} /* namespace shell */
|
} /* namespace shell */
|
||||||
} /* namespace js */
|
} /* namespace js */
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче