зеркало из https://github.com/mozilla/gecko-dev.git
- "varargs" counterpart to JS_ConvertArguments, JS_ConvertArgumentsVA.
- JS_PushArguments{,VA} and JS_PopArguments to convert a list of C/C++ values passed as actual arguments into an 'jsval *argv' on the JS stack. - Clean up and robustify ConvertArgs test command in the js shell.
This commit is contained in:
Родитель
4d8ab97905
Коммит
85b69beb44
60
js/src/js.c
60
js/src/js.c
|
@ -158,7 +158,7 @@ GetLine(JSContext *cx, char *bufp, FILE *fh, const char *prompt) {
|
||||||
if (fgets(line, 256, fh) == NULL)
|
if (fgets(line, 256, fh) == NULL)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
strcpy(bufp, line);
|
strcpy(bufp, line);
|
||||||
}
|
}
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,7 +186,7 @@ Process(JSContext *cx, JSObject *obj, char *filename)
|
||||||
} else {
|
} else {
|
||||||
fh = stdin;
|
fh = stdin;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isatty(fileno(fh))) {
|
if (!isatty(fileno(fh))) {
|
||||||
/*
|
/*
|
||||||
* It's not interactive - just execute it.
|
* It's not interactive - just execute it.
|
||||||
|
@ -244,19 +244,19 @@ Process(JSContext *cx, JSObject *obj, char *filename)
|
||||||
startline);
|
startline);
|
||||||
if (script) {
|
if (script) {
|
||||||
JSErrorReporter older;
|
JSErrorReporter older;
|
||||||
|
|
||||||
ok = JS_ExecuteScript(cx, obj, script, &result);
|
ok = JS_ExecuteScript(cx, obj, script, &result);
|
||||||
if (ok && result != JSVAL_VOID) {
|
if (ok && result != JSVAL_VOID) {
|
||||||
/* Suppress error reports from JS_ValueToString(). */
|
/* Suppress error reports from JS_ValueToString(). */
|
||||||
older = JS_SetErrorReporter(cx, NULL);
|
older = JS_SetErrorReporter(cx, NULL);
|
||||||
str = JS_ValueToString(cx, result);
|
str = JS_ValueToString(cx, result);
|
||||||
JS_SetErrorReporter(cx, older);
|
JS_SetErrorReporter(cx, older);
|
||||||
|
|
||||||
if (str)
|
if (str)
|
||||||
fprintf(gOutFile, "%s\n", JS_GetStringBytes(str));
|
fprintf(gOutFile, "%s\n", JS_GetStringBytes(str));
|
||||||
else
|
else
|
||||||
ok = JS_FALSE;
|
ok = JS_FALSE;
|
||||||
}
|
}
|
||||||
#if 0
|
#if 0
|
||||||
#if JS_HAS_ERROR_EXCEPTIONS
|
#if JS_HAS_ERROR_EXCEPTIONS
|
||||||
/*
|
/*
|
||||||
|
@ -264,7 +264,7 @@ Process(JSContext *cx, JSObject *obj, char *filename)
|
||||||
* been set.
|
* been set.
|
||||||
*/
|
*/
|
||||||
JS_ASSERT(ok || JS_IsExceptionPending(cx));
|
JS_ASSERT(ok || JS_IsExceptionPending(cx));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Also that any time an exception has been set, we've
|
* Also that any time an exception has been set, we've
|
||||||
* returned failure.
|
* returned failure.
|
||||||
|
@ -324,7 +324,7 @@ ProcessArgs(JSContext *cx, JSObject *obj, char **argv, int argc)
|
||||||
filename = NULL;
|
filename = NULL;
|
||||||
/* XXX: js -f foo.js should interpret foo.js and then
|
/* XXX: js -f foo.js should interpret foo.js and then
|
||||||
* drop into interactive mode, but that breaks test
|
* drop into interactive mode, but that breaks test
|
||||||
* harness. Just execute foo.js for now.
|
* harness. Just execute foo.js for now.
|
||||||
*/
|
*/
|
||||||
isInteractive = JS_FALSE;
|
isInteractive = JS_FALSE;
|
||||||
i++;
|
i++;
|
||||||
|
@ -1000,6 +1000,8 @@ EscapeWideString(jschar *w)
|
||||||
unsigned char b, c;
|
unsigned char b, c;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
|
if (!w)
|
||||||
|
return "";
|
||||||
for (i = j = 0; i < sizeof enuf - 1; i++, j++) {
|
for (i = j = 0; i < sizeof enuf - 1; i++, j++) {
|
||||||
u = w[j];
|
u = w[j];
|
||||||
if (u == 0)
|
if (u == 0)
|
||||||
|
@ -1033,17 +1035,17 @@ EscapeWideString(jschar *w)
|
||||||
static JSBool
|
static JSBool
|
||||||
ConvertArgs(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
ConvertArgs(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||||
{
|
{
|
||||||
JSBool b;
|
JSBool b = JS_FALSE;
|
||||||
jschar c;
|
jschar c = 0;
|
||||||
int32 i, j;
|
int32 i = 0, j = 0;
|
||||||
uint32 u;
|
uint32 u = 0;
|
||||||
jsdouble d, I;
|
jsdouble d = 0, I = 0;
|
||||||
char *s;
|
char *s = NULL;
|
||||||
JSString *str;
|
JSString *str = NULL;
|
||||||
jschar *w;
|
jschar *w = NULL;
|
||||||
JSObject *obj;
|
JSObject *obj = NULL;
|
||||||
JSFunction *fun;
|
JSFunction *fun = NULL;
|
||||||
jsval v;
|
jsval v = JSVAL_VOID;
|
||||||
|
|
||||||
if (!JS_ConvertArguments(cx, argc, argv, "b/ciujdIsSWofv*",
|
if (!JS_ConvertArguments(cx, argc, argv, "b/ciujdIsSWofv*",
|
||||||
&b, &c, &i, &u, &j, &d, &I, &s, &str, &w, &obj,
|
&b, &c, &i, &u, &j, &d, &I, &s, &str, &w, &obj,
|
||||||
|
@ -1055,9 +1057,9 @@ ConvertArgs(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||||
b, c, (char)c, i, u, j);
|
b, c, (char)c, i, u, j);
|
||||||
fprintf(gOutFile,
|
fprintf(gOutFile,
|
||||||
"d %g, I %g, s %s, S %s, W %s, obj %s, fun %s, v %s\n",
|
"d %g, I %g, s %s, S %s, W %s, obj %s, fun %s, v %s\n",
|
||||||
d, I, s, JS_GetStringBytes(str), EscapeWideString(w),
|
d, I, s, str ? JS_GetStringBytes(str) : "", EscapeWideString(w),
|
||||||
JS_GetStringBytes(JS_ValueToString(cx, OBJECT_TO_JSVAL(obj))),
|
JS_GetStringBytes(JS_ValueToString(cx, OBJECT_TO_JSVAL(obj))),
|
||||||
JS_GetStringBytes(JS_DecompileFunction(cx, fun, 4)),
|
fun ? JS_GetStringBytes(JS_DecompileFunction(cx, fun, 4)) : "",
|
||||||
JS_GetStringBytes(JS_ValueToString(cx, v)));
|
JS_GetStringBytes(JS_ValueToString(cx, v)));
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
@ -1214,16 +1216,16 @@ static JSPropertySpec its_props[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef JSD_LOWLEVEL_SOURCE
|
#ifdef JSD_LOWLEVEL_SOURCE
|
||||||
/*
|
/*
|
||||||
* This facilitates sending source to JSD (the debugger system) in the shell
|
* This facilitates sending source to JSD (the debugger system) in the shell
|
||||||
* where the source is loaded using the JSFILE hack in jsscan. The function
|
* where the source is loaded using the JSFILE hack in jsscan. The function
|
||||||
* below is used as a callback for the jsdbgapi JS_SetSourceHandler hook.
|
* below is used as a callback for the jsdbgapi JS_SetSourceHandler hook.
|
||||||
* A more normal embedding (e.g. mozilla) loads source itself and can send
|
* A more normal embedding (e.g. mozilla) loads source itself and can send
|
||||||
* source directly to JSD without using this hook scheme.
|
* source directly to JSD without using this hook scheme.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
SendSourceToJSDebugger(const char *filename, uintN lineno,
|
SendSourceToJSDebugger(const char *filename, uintN lineno,
|
||||||
jschar *str, size_t length,
|
jschar *str, size_t length,
|
||||||
void **listenerTSData, JSDContext* jsdc)
|
void **listenerTSData, JSDContext* jsdc)
|
||||||
{
|
{
|
||||||
JSDSourceText *jsdsrc = (JSDSourceText *) *listenerTSData;
|
JSDSourceText *jsdsrc = (JSDSourceText *) *listenerTSData;
|
||||||
|
@ -1242,7 +1244,7 @@ SendSourceToJSDebugger(const char *filename, uintN lineno,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (jsdsrc) {
|
if (jsdsrc) {
|
||||||
jsdsrc = JSD_AppendUCSourceText(jsdc,jsdsrc, str, length,
|
jsdsrc = JSD_AppendUCSourceText(jsdc,jsdsrc, str, length,
|
||||||
JSD_SOURCE_PARTIAL);
|
JSD_SOURCE_PARTIAL);
|
||||||
}
|
}
|
||||||
*listenerTSData = jsdsrc;
|
*listenerTSData = jsdsrc;
|
||||||
|
@ -1587,7 +1589,7 @@ main(int argc, char **argv)
|
||||||
if (f != NULL) {
|
if (f != NULL) {
|
||||||
int maxArgs = 32; /* arbitrary max !!! */
|
int maxArgs = 32; /* arbitrary max !!! */
|
||||||
argc = 1;
|
argc = 1;
|
||||||
argv = malloc(sizeof(char *) * maxArgs);
|
argv = malloc(sizeof(char *) * maxArgs);
|
||||||
argv[0] = NULL;
|
argv[0] = NULL;
|
||||||
while (fgets(argText, 255, f) != NULL) {
|
while (fgets(argText, 255, f) != NULL) {
|
||||||
/* argText includes '\n' */
|
/* argText includes '\n' */
|
||||||
|
@ -1599,7 +1601,7 @@ main(int argc, char **argv)
|
||||||
if (argc >= maxArgs) break;
|
if (argc >= maxArgs) break;
|
||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
}
|
}
|
||||||
gTestResultFile = fopen("results.txt", "w");
|
gTestResultFile = fopen("results.txt", "w");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
135
js/src/jsapi.c
135
js/src/jsapi.c
|
@ -96,9 +96,20 @@ JS_ConvertArguments(JSContext *cx, uintN argc, jsval *argv, const char *format,
|
||||||
...)
|
...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
JSBool ok;
|
||||||
|
|
||||||
|
va_start(ap, format);
|
||||||
|
ok = JS_ConvertArgumentsVA(cx, argc, argv, format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_PUBLIC_API(JSBool)
|
||||||
|
JS_ConvertArgumentsVA(JSContext *cx, uintN argc, jsval *argv,
|
||||||
|
const char *format, va_list ap)
|
||||||
|
{
|
||||||
uintN i;
|
uintN i;
|
||||||
JSBool required;
|
JSBool required;
|
||||||
const char *cp;
|
|
||||||
char c;
|
char c;
|
||||||
JSFunction *fun;
|
JSFunction *fun;
|
||||||
jsdouble d;
|
jsdouble d;
|
||||||
|
@ -106,13 +117,12 @@ JS_ConvertArguments(JSContext *cx, uintN argc, jsval *argv, const char *format,
|
||||||
JSObject *obj;
|
JSObject *obj;
|
||||||
|
|
||||||
CHECK_REQUEST(cx);
|
CHECK_REQUEST(cx);
|
||||||
va_start(ap, format);
|
|
||||||
i = 0;
|
i = 0;
|
||||||
required = JS_TRUE;
|
required = JS_TRUE;
|
||||||
for (cp = format; *cp != '\0'; cp++) {
|
while ((c = *format++) != '\0') {
|
||||||
if (isspace(*cp))
|
if (isspace(c))
|
||||||
continue;
|
continue;
|
||||||
if (*cp == '/') {
|
if (c == '/') {
|
||||||
required = JS_FALSE;
|
required = JS_FALSE;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -131,7 +141,7 @@ JS_ConvertArguments(JSContext *cx, uintN argc, jsval *argv, const char *format,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
switch ((c = *cp)) {
|
switch (c) {
|
||||||
case 'b':
|
case 'b':
|
||||||
if (!js_ValueToBoolean(cx, argv[i], va_arg(ap, JSBool *)))
|
if (!js_ValueToBoolean(cx, argv[i], va_arg(ap, JSBool *)))
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
|
@ -195,18 +205,125 @@ JS_ConvertArguments(JSContext *cx, uintN argc, jsval *argv, const char *format,
|
||||||
break;
|
break;
|
||||||
default: {
|
default: {
|
||||||
char charBuf[2] = " ";
|
char charBuf[2] = " ";
|
||||||
charBuf[0] = *cp;
|
charBuf[0] = c;
|
||||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_CHAR,
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_CHAR,
|
||||||
charBuf);
|
charBuf);
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
va_end(ap);
|
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JS_PUBLIC_API(jsval *)
|
||||||
|
JS_PushArguments(JSContext *cx, void **markp, const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
jsval *argv;
|
||||||
|
|
||||||
|
va_start(ap, format);
|
||||||
|
argv = JS_PushArgumentsVA(cx, markp, format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return argv;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_PUBLIC_API(jsval *)
|
||||||
|
JS_PushArgumentsVA(JSContext *cx, void **markp, const char *format, va_list ap)
|
||||||
|
{
|
||||||
|
uintN argc;
|
||||||
|
jsval *argv, *sp;
|
||||||
|
char c;
|
||||||
|
const char *cp;
|
||||||
|
JSString *str;
|
||||||
|
JSFunction *fun;
|
||||||
|
|
||||||
|
CHECK_REQUEST(cx);
|
||||||
|
*markp = NULL;
|
||||||
|
argc = 0;
|
||||||
|
for (cp = format; (c = *cp) != '\0'; cp++) {
|
||||||
|
if (isspace(c) || c == '*')
|
||||||
|
continue;
|
||||||
|
argc++;
|
||||||
|
}
|
||||||
|
sp = js_AllocStack(cx, argc, markp);
|
||||||
|
if (!sp)
|
||||||
|
return NULL;
|
||||||
|
argv = sp;
|
||||||
|
while ((c = *format++) != '\0') {
|
||||||
|
if (isspace(c) || c == '*')
|
||||||
|
continue;
|
||||||
|
switch (c) {
|
||||||
|
case 'b':
|
||||||
|
*sp = BOOLEAN_TO_JSVAL(va_arg(ap, JSBool));
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
*sp = INT_TO_JSVAL(va_arg(ap, uint16));
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
case 'j':
|
||||||
|
if (!js_NewNumberValue(cx, (jsdouble) va_arg(ap, int32), sp))
|
||||||
|
goto bad;
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
if (!js_NewNumberValue(cx, (jsdouble) va_arg(ap, uint32), sp))
|
||||||
|
goto bad;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
case 'I':
|
||||||
|
if (!js_NewDoubleValue(cx, va_arg(ap, jsdouble), sp))
|
||||||
|
goto bad;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
str = JS_NewStringCopyZ(cx, va_arg(ap, char *));
|
||||||
|
if (!str)
|
||||||
|
goto bad;
|
||||||
|
*sp = STRING_TO_JSVAL(str);
|
||||||
|
break;
|
||||||
|
case 'W':
|
||||||
|
str = JS_NewUCStringCopyZ(cx, va_arg(ap, jschar *));
|
||||||
|
if (!str)
|
||||||
|
goto bad;
|
||||||
|
*sp = STRING_TO_JSVAL(str);
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
str = va_arg(ap, JSString *);
|
||||||
|
*sp = STRING_TO_JSVAL(str);
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
*sp = OBJECT_TO_JSVAL(va_arg(ap, JSObject *));
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
fun = va_arg(ap, JSFunction *);
|
||||||
|
*sp = fun ? OBJECT_TO_JSVAL(fun->object) : JSVAL_NULL;
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
*sp = va_arg(ap, jsval);
|
||||||
|
break;
|
||||||
|
default: {
|
||||||
|
char charBuf[2] = " ";
|
||||||
|
charBuf[0] = c;
|
||||||
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_CHAR,
|
||||||
|
charBuf);
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sp++;
|
||||||
|
}
|
||||||
|
return argv;
|
||||||
|
|
||||||
|
bad:
|
||||||
|
js_FreeStack(cx, *markp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_PUBLIC_API(void)
|
||||||
|
JS_PopArguments(JSContext *cx, void *mark)
|
||||||
|
{
|
||||||
|
CHECK_REQUEST(cx);
|
||||||
|
js_FreeStack(cx, mark);
|
||||||
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(JSBool)
|
JS_PUBLIC_API(JSBool)
|
||||||
JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp)
|
JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp)
|
||||||
{
|
{
|
||||||
|
|
|
@ -165,6 +165,33 @@ extern JS_PUBLIC_API(JSBool)
|
||||||
JS_ConvertArguments(JSContext *cx, uintN argc, jsval *argv, const char *format,
|
JS_ConvertArguments(JSContext *cx, uintN argc, jsval *argv, const char *format,
|
||||||
...);
|
...);
|
||||||
|
|
||||||
|
#ifdef va_start
|
||||||
|
JS_PUBLIC_API(JSBool)
|
||||||
|
JS_ConvertArgumentsVA(JSContext *cx, uintN argc, jsval *argv,
|
||||||
|
const char *format, va_list ap);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Inverse of JS_ConvertArguments: scan format and convert trailing arguments
|
||||||
|
* into jsvals, GC-rooted if necessary by the JS stack. Return null on error,
|
||||||
|
* and a pointer to the new argument vector on success. Also return a stack
|
||||||
|
* mark on success via *markp, in which case the caller must eventually clean
|
||||||
|
* up by calling JS_PopArguments.
|
||||||
|
*
|
||||||
|
* Note that the number of actual arguments supplied is specified exclusively
|
||||||
|
* by format, so there is no argc parameter.
|
||||||
|
*/
|
||||||
|
extern JS_PUBLIC_API(jsval *)
|
||||||
|
JS_PushArguments(JSContext *cx, void **markp, const char *format, ...);
|
||||||
|
|
||||||
|
#ifdef va_start
|
||||||
|
extern JS_PUBLIC_API(jsval *)
|
||||||
|
JS_PushArgumentsVA(JSContext *cx, void **markp, const char *format, va_list ap);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern JS_PUBLIC_API(void)
|
||||||
|
JS_PopArguments(JSContext *cx, void *mark);
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSBool)
|
extern JS_PUBLIC_API(JSBool)
|
||||||
JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp);
|
JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp);
|
||||||
|
|
||||||
|
@ -1045,18 +1072,17 @@ JS_SetPendingException(JSContext *cx, jsval v);
|
||||||
extern JS_PUBLIC_API(void)
|
extern JS_PUBLIC_API(void)
|
||||||
JS_ClearPendingException(JSContext *cx);
|
JS_ClearPendingException(JSContext *cx);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Save the current exception state. This takes a snapshot of the current
|
* Save the current exception state. This takes a snapshot of the current
|
||||||
* exception state without making any change to that state.
|
* exception state without making any change to that state.
|
||||||
*
|
*
|
||||||
* The returned object MUST be later passed to either JS_RestoreExceptionState
|
* The returned object MUST be later passed to either JS_RestoreExceptionState
|
||||||
* (to restore that saved state) or JS_DropExceptionState (to cleanup the state
|
* (to restore that saved state) or JS_DropExceptionState (to cleanup the state
|
||||||
* object in case it is not desireable to restore to that state). Both
|
* object in case it is not desireable to restore to that state). Both
|
||||||
* JS_RestoreExceptionState and JS_DropExceptionState will destroy the
|
* JS_RestoreExceptionState and JS_DropExceptionState will destroy the
|
||||||
* JSExceptionState object -- so that object can not be referenced again
|
* JSExceptionState object -- so that object can not be referenced again
|
||||||
* after making either of those calls.
|
* after making either of those calls.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern JS_PUBLIC_API(JSExceptionState *)
|
extern JS_PUBLIC_API(JSExceptionState *)
|
||||||
JS_SaveExceptionState(JSContext *cx);
|
JS_SaveExceptionState(JSContext *cx);
|
||||||
|
|
||||||
|
@ -1093,7 +1119,7 @@ JS_ClearContextThread(JSContext *cx);
|
||||||
* Returns true if a script is executing and its current bytecode is a set
|
* Returns true if a script is executing and its current bytecode is a set
|
||||||
* (assignment) operation.
|
* (assignment) operation.
|
||||||
*
|
*
|
||||||
* NOTE: Previously conditional on NETSCAPE_INTERNAL. This function may
|
* NOTE: Previously conditional on NETSCAPE_INTERNAL. This function may
|
||||||
* be removed in the future.
|
* be removed in the future.
|
||||||
*/
|
*/
|
||||||
extern JS_FRIEND_API(JSBool)
|
extern JS_FRIEND_API(JSBool)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче