jsshell.cpp (3509B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 // jsshell.cpp - Utilities for the JS shell 8 9 #include "shell/jsshell.h" 10 11 #include "mozilla/Sprintf.h" 12 13 #include "jsfriendapi.h" 14 15 #include "js/GlobalObject.h" 16 #include "js/PropertyAndElement.h" // JS_DefineProperty, JS_GetProperty, JS_GetPropertyById 17 #include "util/StringBuilder.h" 18 19 using namespace JS; 20 21 namespace js { 22 namespace shell { 23 24 // Generate 'usage' and 'help' properties for the given object. 25 // JS_DefineFunctionsWithHelp will define individual function objects with both 26 // of those properties (eg getpid.usage = "getpid()" and getpid.help = "return 27 // the process id"). This function will generate strings for an "interface 28 // object", eg os.file, which contains some number of functions. 29 // 30 // .usage will be set to "<name> - interface object". 31 // 32 // .help will be set to a newline-separated list of functions that have either 33 // 'help' or 'usage' properties. Functions are described with their usage 34 // strings, if they have them, else with just their names. 35 // 36 bool GenerateInterfaceHelp(JSContext* cx, HandleObject obj, const char* name) { 37 RootedIdVector idv(cx); 38 if (!GetPropertyKeys(cx, obj, JSITER_OWNONLY | JSITER_HIDDEN, &idv)) { 39 return false; 40 } 41 42 JSStringBuilder buf(cx); 43 int numEntries = 0; 44 for (size_t i = 0; i < idv.length(); i++) { 45 RootedId id(cx, idv[i]); 46 RootedValue v(cx); 47 if (!JS_GetPropertyById(cx, obj, id, &v)) { 48 return false; 49 } 50 if (!v.isObject()) { 51 continue; 52 } 53 RootedObject prop(cx, &v.toObject()); 54 55 RootedValue usage(cx); 56 RootedValue help(cx); 57 if (!JS_GetProperty(cx, prop, "usage", &usage)) { 58 return false; 59 } 60 if (!JS_GetProperty(cx, prop, "help", &help)) { 61 return false; 62 } 63 if (!usage.isString() && !help.isString()) { 64 continue; 65 } 66 67 if (numEntries && !buf.append("\n")) { 68 return false; 69 } 70 numEntries++; 71 72 if (!buf.append(" ")) { 73 return false; 74 } 75 76 if (!buf.append(usage.isString() ? usage.toString() : id.toString())) { 77 return false; 78 } 79 } 80 81 RootedString s(cx, buf.finishString()); 82 if (!s || !JS_DefineProperty(cx, obj, "help", s, 0)) { 83 return false; 84 } 85 86 buf.clear(); 87 if (!buf.append(name, strlen(name)) || 88 !buf.append(" - interface object with ")) { 89 return false; 90 } 91 char cbuf[100]; 92 SprintfLiteral(cbuf, "%d %s", numEntries, 93 numEntries == 1 ? "entry" : "entries"); 94 if (!buf.append(cbuf, strlen(cbuf))) { 95 return false; 96 } 97 s = buf.finishString(); 98 if (!s || !JS_DefineProperty(cx, obj, "usage", s, 0)) { 99 return false; 100 } 101 102 return true; 103 } 104 105 bool CreateAlias(JSContext* cx, const char* dstName, 106 JS::HandleObject namespaceObj, const char* srcName) { 107 RootedObject global(cx, JS::GetNonCCWObjectGlobal(namespaceObj)); 108 109 RootedValue val(cx); 110 if (!JS_GetProperty(cx, namespaceObj, srcName, &val)) { 111 return false; 112 } 113 114 if (!val.isObject()) { 115 JS_ReportErrorASCII(cx, "attempted to alias nonexistent function"); 116 return false; 117 } 118 119 RootedObject function(cx, &val.toObject()); 120 if (!JS_DefineProperty(cx, global, dstName, function, 0)) { 121 return false; 122 } 123 124 return true; 125 } 126 127 } // namespace shell 128 } // namespace js