Bug 507448. Expose the names of the function arguments on jsdIScript. r=timeless,brendan

--HG--
rename : content/base/test/Makefile.in => js/jsd/test/Makefile.in
This commit is contained in:
Boris Zbarsky 2009-10-26 09:30:40 -04:00
parent 523bfdfd54
commit 3aef7b8edb
7 changed files with 198 additions and 3 deletions

View File

@ -94,6 +94,10 @@ EXPORT_LIBRARY = 1
endif
endif
ifdef ENABLE_TESTS
TOOL_DIRS += test
endif
include $(topsrcdir)/config/rules.mk
DEFINES += -DEXPORT_JSD_API

View File

@ -866,7 +866,7 @@ interface jsdIStackFrame : jsdIEphemeral
* Script object. In JavaScript engine terms, there's a single script for each
* function, and one for the top level script.
*/
[scriptable, uuid(b1b7f95d-85f9-431e-afb0-936f91c27244)]
[scriptable, uuid(18e09893-f461-4b4b-94d3-776fb0069c6f)]
interface jsdIScript : jsdIEphemeral
{
/** Internal use only. */
@ -923,6 +923,12 @@ interface jsdIScript : jsdIEphemeral
* invalidated.
*/
readonly attribute AUTF8String functionName;
/**
* The names of the arguments for this function; empty if this is
* not a function.
*/
void getParameterNames([optional] out unsigned long count,
[array, size_is(count), retval] out wstring paramNames);
/**
* Fetch the function object as a jsdIValue.
*/

View File

@ -1219,6 +1219,67 @@ jsdScript::GetFunctionName(nsACString &_rval)
return NS_OK;
}
NS_IMETHODIMP
jsdScript::GetParameterNames(PRUint32* count, PRUnichar*** paramNames)
{
ASSERT_VALID_EPHEMERAL;
JSContext *cx = JSD_GetDefaultJSContext (mCx);
if (!cx) {
NS_WARNING("No default context !?");
return NS_ERROR_FAILURE;
}
JSFunction *fun = JSD_GetJSFunction (mCx, mScript);
JSAutoRequest ar(cx);
if (!fun || !fun->hasLocalNames() || fun->nargs == 0) {
*count = 0;
*paramNames = nsnull;
return NS_OK;
}
PRUnichar **ret =
static_cast<PRUnichar**>(NS_Alloc(fun->nargs * sizeof(PRUnichar*)));
if (!ret)
return NS_ERROR_OUT_OF_MEMORY;
void *mark = JS_ARENA_MARK(&cx->tempPool);
jsuword *names = js_GetLocalNameArray(cx, fun, &cx->tempPool);
if (!names) {
NS_Free(ret);
return NS_ERROR_OUT_OF_MEMORY;
}
nsresult rv = NS_OK;
for (uintN i = 0; i < fun->nargs; ++i) {
JSAtom *atom = JS_LOCAL_NAME_TO_ATOM(names[i]);
if (!atom) {
ret[i] = 0;
} else {
jsval atomVal = ATOM_KEY(atom);
if (!JSVAL_IS_STRING(atomVal)) {
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(i, ret);
rv = NS_ERROR_UNEXPECTED;
break;
}
JSString *str = JSVAL_TO_STRING(atomVal);
ret[i] = NS_strndup(reinterpret_cast<PRUnichar*>(JS_GetStringChars(str)),
JS_GetStringLength(str));
if (!ret[i]) {
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(i, ret);
rv = NS_ERROR_OUT_OF_MEMORY;
break;
}
}
}
JS_ARENA_RELEASE(&cx->tempPool, mark);
if (NS_FAILED(rv))
return rv;
*count = fun->nargs;
*paramNames = ret;
return NS_OK;
}
NS_IMETHODIMP
jsdScript::GetFunctionObject(jsdIValue **_rval)
{

54
js/jsd/test/Makefile.in Normal file
View File

@ -0,0 +1,54 @@
#
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is
# Mozilla Foundation.
# Portions created by the Initial Developer are Copyright (C) 2007
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#
# Alternatively, the contents of this file may be used under the terms of
# either of the GNU General Public License Version 2 or later (the "GPL"),
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = js/jsd/test
include $(DEPTH)/config/autoconf.mk
MODULE = jsdebug
include $(topsrcdir)/config/rules.mk
_TEST_FILES = test_bug507448.html \
$(NULL)
libs:: $(_TEST_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)

View File

@ -0,0 +1,70 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=507448
-->
<head>
<title>Test for Bug 507448</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=507448">Mozilla Bug 507448</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 507448 **/
function assertArraysEqual(arr1, arr2) {
is(arr1.length, arr2.length, "Lengths not equal");
for (var i = 0 ; i < arr1.length; ++i) {
is(arr1[i], arr2[i], "Element " + i + " not equal");
}
}
// This is somewhat unfortunate: jsd only deals with scripts that have a
// nonzero line number, so we can't just createElement a script here.
// So break the test up into three <script>s, of which the middle one has our test functions.
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var jsdIDebuggerService = Components.interfaces.jsdIDebuggerService;
var jsd = Components.classes['@mozilla.org/js/jsd/debugger-service;1']
.getService(jsdIDebuggerService);
var jsdOn = jsd.isOn;
if (!jsdOn) {
jsd.on();
ok(jsd.isOn, "JSD should be running.");
}
</script>
<script>
function f() {}
function g(a,b) {}
function h(me, too, here) { var x = 1; }
function annoying(a, b, a, b, b, a) {}
function manyLocals(a, b, c, d, e, f, g, h, i, j, k, l, m) {
var n, o, p, q, r, s, t, u, v, w, x, y, z;
}
</script>
<script>
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
assertArraysEqual(jsd.wrapValue(f).script.getParameterNames(), []);
assertArraysEqual(jsd.wrapValue(g).script.getParameterNames(), ["a", "b"]);
assertArraysEqual(jsd.wrapValue(h).script.getParameterNames(), ["me", "too", "here"]);
assertArraysEqual(jsd.wrapValue(annoying).script.getParameterNames(),
["a", "b", "a", "b", "b", "a"]);
dump('aa');
assertArraysEqual(jsd.wrapValue(manyLocals).script.getParameterNames(),
"abcdefghijklm".split(""));
if (!jsdOn) {
jsd.off();
ok(!jsd.isOn, "JSD shouldn't be running anymore.");
}
</script>
</pre>
</body>
</html>

View File

@ -2936,7 +2936,7 @@ get_local_names_enumerator(JSDHashTable *table, JSDHashEntryHdr *hdr,
return JS_DHASH_NEXT;
}
jsuword *
JS_FRIEND_API(jsuword *)
js_GetLocalNameArray(JSContext *cx, JSFunction *fun, JSArenaPool *pool)
{
uintN n;

View File

@ -424,7 +424,7 @@ js_LookupLocal(JSContext *cx, JSFunction *fun, JSAtom *atom, uintN *indexp);
* If nameWord does not name a formal parameter, use JS_LOCAL_NAME_IS_CONST to
* check if nameWord corresponds to the const declaration.
*/
extern jsuword *
extern JS_FRIEND_API(jsuword *)
js_GetLocalNameArray(JSContext *cx, JSFunction *fun, struct JSArenaPool *pool);
#define JS_LOCAL_NAME_TO_ATOM(nameWord) \