Support lazy initialization of standard classes and their associated global functions/properties (46703, r=jband,rogerl).

This commit is contained in:
brendan%mozilla.org 2000-08-19 08:37:07 +00:00
Родитель b100da9c08
Коммит 9d16e66aad
22 изменённых файлов: 844 добавлений и 291 удалений

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

@ -1781,10 +1781,32 @@ Exec(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
}
#endif
#define LAZY_STANDARD_CLASSES
static JSBool
global_enumerate(JSContext *cx, JSObject *obj)
{
#ifdef LAZY_STANDARD_CLASSES
return JS_EnumerateStandardClasses(cx, obj);
#else
return JS_TRUE;
#endif
}
static JSBool
global_resolve(JSContext *cx, JSObject *obj, jsval id)
{
#ifdef LAZY_STANDARD_CLASSES
JSBool resolved;
if (!JS_ResolveStandardClass(cx, obj, id, &resolved))
return JS_FALSE;
if (resolved)
return JS_TRUE;
#endif
#if defined(SHELL_HACK) && defined(DEBUG) && defined(XP_UNIX)
{
/*
* Do this expensive hack only for unoptimized Unix builds, which are not
* used for benchmarking.
@ -1826,6 +1848,7 @@ global_resolve(JSContext *cx, JSObject *obj, jsval id)
}
JS_free(cx, path);
return ok;
}
#else
return JS_TRUE;
#endif
@ -1834,7 +1857,7 @@ global_resolve(JSContext *cx, JSObject *obj, jsval id)
static JSClass global_class = {
"global", 0,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, global_resolve, JS_ConvertStub, JS_FinalizeStub
global_enumerate, global_resolve, JS_ConvertStub, JS_FinalizeStub
};
int
@ -1917,8 +1940,10 @@ main(int argc, char **argv)
glob = JS_NewObject(cx, &global_class, NULL, NULL);
if (!glob)
return 1;
#ifndef LAZY_STANDARD_CLASSES
if (!JS_InitStandardClasses(cx, glob))
return 1;
#endif
if (!JS_DefineFunctions(cx, glob, shell_functions))
return 1;

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

@ -945,50 +945,89 @@ JS_SetGlobalObject(JSContext *cx, JSObject *obj)
cx->globalObject = obj;
}
JS_PUBLIC_API(JSBool)
JS_InitStandardClasses(JSContext *cx, JSObject *obj)
static JSObject *
InitFunctionAndObjectClasses(JSContext *cx, JSObject *obj)
{
JSDHashTable *table;
JSRuntime *rt;
JSString *idstr;
JSDHashEntryHdr *entry;
JSObject *fun_proto, *obj_proto;
CHECK_REQUEST(cx);
/* If cx has no global object, use obj so prototypes can be found. */
if (!cx->globalObject)
cx->globalObject = obj;
#if JS_HAS_UNDEFINED
/*
* Define a top-level property 'undefined' with the undefined value.
* (proposed ECMA v2, now in ECMA ed3?)
*/
if (!OBJ_DEFINE_PROPERTY(cx, obj,
(jsid)cx->runtime->atomState.typeAtoms[JSTYPE_VOID],
JSVAL_VOID, NULL, NULL, JSPROP_PERMANENT, NULL)) {
return JS_FALSE;
/* Record both Function and Object in resolving, if we are resolving. */
table = cx->resolving;
if (table) {
rt = cx->runtime;
idstr = ATOM_TO_STRING(rt->atomState.FunctionAtom);
entry = JS_DHashTableOperate(table, idstr, JS_DHASH_LOOKUP);
if (JS_DHASH_ENTRY_IS_BUSY(entry))
idstr = ATOM_TO_STRING(rt->atomState.ObjectAtom);
entry = JS_DHashTableOperate(table, idstr, JS_DHASH_ADD);
if (!entry) {
JS_ReportOutOfMemory(cx);
return NULL;
}
((JSDHashEntryStub *)entry)->key = idstr;
}
#endif
/* Initialize the function class first so constructors can be made. */
fun_proto = js_InitFunctionClass(cx, obj);
if (!fun_proto)
return JS_FALSE;
return NULL;
/* Initialize the object class next so Object.prototype works. */
obj_proto = js_InitObjectClass(cx, obj);
if (!obj_proto)
return JS_FALSE;
return NULL;
/* Function.prototype and the global object delegate to Object.prototype. */
OBJ_SET_PROTO(cx, fun_proto, obj_proto);
if (!OBJ_GET_PROTO(cx, obj))
OBJ_SET_PROTO(cx, obj, obj_proto);
/* If resolving, remove the other entry (Object or Function) from table. */
if (table)
JS_DHashTableRawRemove(table, entry);
return fun_proto;
}
JS_PUBLIC_API(JSBool)
JS_InitStandardClasses(JSContext *cx, JSObject *obj)
{
CHECK_REQUEST(cx);
#if JS_HAS_UNDEFINED
{
/* Define a top-level property 'undefined' with the undefined value. */
JSAtom *atom = cx->runtime->atomState.typeAtoms[JSTYPE_VOID];
if (!OBJ_DEFINE_PROPERTY(cx, obj, (jsid)atom, JSVAL_VOID, NULL, NULL,
JSPROP_PERMANENT, NULL)) {
return JS_FALSE;
}
}
#endif
/* Function and Object require cooperative bootstrapping magic. */
if (!InitFunctionAndObjectClasses(cx, obj))
return JS_FALSE;
/* Initialize the rest of the standard objects and functions. */
return js_InitArgsAndCallClasses(cx, obj) &&
js_InitArrayClass(cx, obj) &&
return js_InitArrayClass(cx, obj) &&
js_InitBooleanClass(cx, obj) &&
js_InitMathClass(cx, obj) &&
js_InitNumberClass(cx, obj) &&
js_InitStringClass(cx, obj) &&
#if JS_HAS_ARGS_OBJECT
js_InitArgumentsClass(cx, obj) &&
#endif
#if JS_HAS_CALL_OBJECT
js_InitCallClass(cx, obj) &&
#endif
#if JS_HAS_REGEXPS
js_InitRegExpClass(cx, obj) &&
#endif
@ -1004,6 +1043,296 @@ JS_InitStandardClasses(JSContext *cx, JSObject *obj)
js_InitDateClass(cx, obj);
}
#define ATOM_OFFSET(name) offsetof(JSAtomState, name##Atom)
#define OFFSET_TO_ATOM(rt,off) (*(JSAtom **)((char*)&(rt)->atomState + (off)))
#define TAG_ATOM_OFFSET(name) ((const char *) ATOM_OFFSET(name))
#define TAG_CHAR_STRING(name) name
#define UNTAG_ATOM_OFFSET(ptr) ((size_t) (ptr))
#define UNTAG_CHAR_STRING(ptr) ptr
#define IS_ATOM_OFFSET(ptr) ((size_t)(ptr) < sizeof(JSAtomState))
/*
* Table of class initializers and their atom offsets in rt->atomState.
* If you add a "standard" class, remember to update this table.
*/
static struct {
JSObjectOp init;
size_t atomOffset;
} standard_class_atoms[] = {
{InitFunctionAndObjectClasses, ATOM_OFFSET(Function)},
{InitFunctionAndObjectClasses, ATOM_OFFSET(Object)},
{js_InitArrayClass, ATOM_OFFSET(Array)},
{js_InitBooleanClass, ATOM_OFFSET(Boolean)},
{js_InitDateClass, ATOM_OFFSET(Date)},
{js_InitMathClass, ATOM_OFFSET(Math)},
{js_InitNumberClass, ATOM_OFFSET(Number)},
{js_InitStringClass, ATOM_OFFSET(String)},
#if JS_HAS_ARGS_OBJECT
{js_InitArgumentsClass, ATOM_OFFSET(Arguments)},
#endif
#if JS_HAS_CALL_OBJECT
{js_InitCallClass, ATOM_OFFSET(Call)},
#endif
#if JS_HAS_ERROR_EXCEPTIONS
{js_InitExceptionClasses, ATOM_OFFSET(Error)},
#endif
#if JS_HAS_REGEXPS
{js_InitRegExpClass, ATOM_OFFSET(RegExp)},
#endif
#if JS_HAS_SCRIPT_OBJECT
{js_InitScriptClass, ATOM_OFFSET(Script)},
#endif
{NULL, 0}
};
/*
* Table of top-level function and constant names and their init functions.
* If you add a "standard" global function or property, remember to update
* this table.
*/
typedef struct JSStdName {
JSObjectOp init;
const char *name; /* tagged (const char *) or atom offset */
} JSStdName;
static JSAtom *
StdNameToAtom(JSContext *cx, const char *name)
{
if (IS_ATOM_OFFSET(name))
return OFFSET_TO_ATOM(cx->runtime, UNTAG_ATOM_OFFSET(name));
name = UNTAG_CHAR_STRING(name);
return js_Atomize(cx, name, strlen(name), 0);
}
static JSStdName standard_class_names[] = {
/* ECMA requires that eval be a direct property of the global object. */
{js_InitObjectClass, TAG_ATOM_OFFSET(eval)},
/* Global properties and functions defined by the Number class. */
{js_InitNumberClass, TAG_CHAR_STRING(js_NaN_str)},
{js_InitNumberClass, TAG_CHAR_STRING(js_Infinity_str)},
{js_InitNumberClass, TAG_CHAR_STRING(js_isNaN_str)},
{js_InitNumberClass, TAG_CHAR_STRING(js_isFinite_str)},
{js_InitNumberClass, TAG_CHAR_STRING(js_parseFloat_str)},
{js_InitNumberClass, TAG_CHAR_STRING(js_parseInt_str)},
/* String global functions. */
{js_InitStringClass, TAG_CHAR_STRING(js_escape_str)},
{js_InitStringClass, TAG_CHAR_STRING(js_unescape_str)},
{js_InitStringClass, TAG_CHAR_STRING(js_decodeURI_str)},
{js_InitStringClass, TAG_CHAR_STRING(js_encodeURI_str)},
{js_InitStringClass, TAG_CHAR_STRING(js_decodeURIComponent_str)},
{js_InitStringClass, TAG_CHAR_STRING(js_encodeURIComponent_str)},
#if JS_HAS_UNEVAL
{js_InitStringClass, TAG_CHAR_STRING(js_uneval_str)},
#endif
/* Exception constructors. */
#if JS_HAS_ERROR_EXCEPTIONS
{js_InitExceptionClasses, TAG_ATOM_OFFSET(Error)},
{js_InitExceptionClasses, TAG_CHAR_STRING(js_InternalError_str)},
{js_InitExceptionClasses, TAG_CHAR_STRING(js_EvalError_str)},
{js_InitExceptionClasses, TAG_CHAR_STRING(js_RangeError_str)},
{js_InitExceptionClasses, TAG_CHAR_STRING(js_ReferenceError_str)},
{js_InitExceptionClasses, TAG_CHAR_STRING(js_SyntaxError_str)},
{js_InitExceptionClasses, TAG_CHAR_STRING(js_TypeError_str)},
{js_InitExceptionClasses, TAG_CHAR_STRING(js_URIError_str)},
#endif
{NULL, NULL}
};
static JSStdName object_prototype_names[] = {
/* Object.prototype properties (global delegates to Object.prototype). */
{js_InitObjectClass, TAG_ATOM_OFFSET(proto)},
{js_InitObjectClass, TAG_ATOM_OFFSET(parent)},
{js_InitObjectClass, TAG_ATOM_OFFSET(count)},
#if JS_HAS_TOSOURCE
{js_InitObjectClass, TAG_ATOM_OFFSET(toSource)},
#endif
{js_InitObjectClass, TAG_ATOM_OFFSET(toString)},
{js_InitObjectClass, TAG_ATOM_OFFSET(toLocaleString)},
{js_InitObjectClass, TAG_ATOM_OFFSET(valueOf)},
#if JS_HAS_OBJ_WATCHPOINT
{js_InitObjectClass, TAG_CHAR_STRING(js_watch_str)},
{js_InitObjectClass, TAG_CHAR_STRING(js_unwatch_str)},
#endif
#if JS_HAS_NEW_OBJ_METHODS
{js_InitObjectClass, TAG_CHAR_STRING(js_hasOwnProperty_str)},
{js_InitObjectClass, TAG_CHAR_STRING(js_isPrototypeOf_str)},
{js_InitObjectClass, TAG_CHAR_STRING(js_propertyIsEnumerable_str)},
#endif
#if JS_HAS_GETTER_SETTER
{js_InitObjectClass, TAG_CHAR_STRING(js_defineGetter_str)},
{js_InitObjectClass, TAG_CHAR_STRING(js_defineSetter_str)},
#endif
{NULL, NULL}
};
JS_PUBLIC_API(JSBool)
JS_ResolveStandardClass(JSContext *cx, JSObject *obj, jsval id,
JSBool *resolved)
{
JSString *idstr;
JSDHashTable *table;
JSDHashEntryHdr *entry;
JSRuntime *rt;
JSAtom *atom;
JSObjectOp init;
uintN i;
JSBool ok;
CHECK_REQUEST(cx);
*resolved = JS_FALSE;
if (!JSVAL_IS_STRING(id))
return JS_TRUE;
idstr = JSVAL_TO_STRING(id);
table = cx->resolving;
if (table) {
entry = JS_DHashTableOperate(table, idstr, JS_DHASH_LOOKUP);
if (JS_DHASH_ENTRY_IS_BUSY(entry))
return JS_TRUE;
}
rt = cx->runtime;
#if JS_HAS_UNDEFINED
/* See if we're resolving 'undefined', and define it if so. */
atom = rt->atomState.typeAtoms[JSTYPE_VOID];
if (idstr == ATOM_TO_STRING(atom)) {
*resolved = JS_TRUE;
return OBJ_DEFINE_PROPERTY(cx, obj, (jsid)atom, JSVAL_VOID, NULL, NULL,
JSPROP_PERMANENT, NULL);
}
#endif
/* Try for class constructors/prototypes named by well-known atoms. */
init = NULL;
for (i = 0; standard_class_atoms[i].init; i++) {
atom = OFFSET_TO_ATOM(rt, standard_class_atoms[i].atomOffset);
if (idstr == ATOM_TO_STRING(atom)) {
init = standard_class_atoms[i].init;
break;
}
}
if (!init) {
/* Try less frequently used top-level functions and constants. */
for (i = 0; standard_class_names[i].init; i++) {
atom = StdNameToAtom(cx, standard_class_names[i].name);
if (idstr == ATOM_TO_STRING(atom)) {
init = standard_class_names[i].init;
break;
}
}
if (!init && !OBJ_GET_PROTO(cx, obj)) {
/*
* Try even less frequently used names delegated from the global
* object to Object.prototype, but only if the Object class hasn't
* yet been initialized.
*/
for (i = 0; object_prototype_names[i].init; i++) {
atom = StdNameToAtom(cx, object_prototype_names[i].name);
if (idstr == ATOM_TO_STRING(atom)) {
init = standard_class_names[i].init;
break;
}
}
}
}
if (init) {
if (!table) {
table = JS_NewDHashTable(JS_DHashGetStubOps(),
NULL,
sizeof(JSDHashEntryStub),
JS_DHASH_MIN_SIZE);
if (!table)
goto outofmem;
cx->resolving = table;
}
entry = JS_DHashTableOperate(table, idstr, JS_DHASH_ADD);
if (!entry)
goto outofmem;
((JSDHashEntryStub *)entry)->key = idstr;
if (init(cx, obj))
ok = *resolved = JS_TRUE;
else
ok = JS_FALSE;
JS_DHashTableRawRemove(table, entry);
if (table->entryCount == 0) {
JS_DHashTableDestroy(table);
cx->resolving = NULL;
}
}
return ok;
outofmem:
JS_ReportOutOfMemory(cx);
return JS_FALSE;
}
static JSBool
HasOwnProperty(JSContext *cx, JSObject *obj, JSAtom *atom, JSBool *ownp)
{
JSObject *pobj;
JSProperty *prop;
if (!OBJ_LOOKUP_PROPERTY(cx, obj, (jsid)atom, &pobj, &prop))
return JS_FALSE;
if (prop)
OBJ_DROP_PROPERTY(cx, pobj, prop);
*ownp = (pobj == obj && prop);
return JS_TRUE;
}
JS_PUBLIC_API(JSBool)
JS_EnumerateStandardClasses(JSContext *cx, JSObject *obj)
{
JSRuntime *rt;
JSAtom *atom;
JSBool found;
uintN i;
CHECK_REQUEST(cx);
rt = cx->runtime;
#if JS_HAS_UNDEFINED
/* See if we need to bind 'undefined' and define it if so. */
atom = rt->atomState.typeAtoms[JSTYPE_VOID];
if (!HasOwnProperty(cx, obj, atom, &found))
return JS_FALSE;
if (!found &&
!OBJ_DEFINE_PROPERTY(cx, obj, (jsid)atom, JSVAL_VOID, NULL, NULL,
JSPROP_PERMANENT, NULL)) {
return JS_FALSE;
}
#endif
/* Initialize any classes that have not been resolved yet. */
for (i = 0; standard_class_atoms[i].init; i++) {
atom = OFFSET_TO_ATOM(rt, standard_class_atoms[i].atomOffset);
if (!HasOwnProperty(cx, obj, atom, &found))
return JS_FALSE;
if (!found && !standard_class_atoms[i].init(cx, obj))
return JS_FALSE;
}
return JS_TRUE;
}
#undef ATOM_OFFSET
#undef OFFSET_TO_ATOM
#undef TAG_ATOM_OFFSET
#undef TAG_CHAR_STRING
#undef UNTAG_ATOM_OFFSET
#undef UNTAG_CHAR_STRING
#undef IS_ATOM_OFFSET
JS_PUBLIC_API(JSObject *)
JS_GetScopeChain(JSContext *cx)
{

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

@ -428,10 +428,36 @@ JS_GetGlobalObject(JSContext *cx);
extern JS_PUBLIC_API(void)
JS_SetGlobalObject(JSContext *cx, JSObject *obj);
/* NB: This sets cx's global object to obj if it was null. */
/*
* Initialize standard JS class constructors, prototypes, and any top-level
* functions and constants associated with the standard classes (e.g. isNaN
* for Number).
*
* NB: This sets cx's global object to obj if it was null.
*/
extern JS_PUBLIC_API(JSBool)
JS_InitStandardClasses(JSContext *cx, JSObject *obj);
/*
* Resolve id, which must contain either a string or an int, to a standard
* class name in obj if possible, defining the class's constructor and/or
* prototype and storing true in *resolved. If id does not name a standard
* class or a top-level property induced by initializing a standard class,
* store false in *resolved and just return true. Return false on error,
* as usual for JSBool result-typed API entry points.
*
* This API can be called directly from a global object class's resolve op,
* to define standard classes lazily. The class's enumerate op should call
* JS_EnumerateStandardClasses(cx, obj), to define eagerly during for..in
* loops any classes not yet resolved lazily.
*/
extern JS_PUBLIC_API(JSBool)
JS_ResolveStandardClass(JSContext *cx, JSObject *obj, jsval id,
JSBool *resolved);
extern JS_PUBLIC_API(JSBool)
JS_EnumerateStandardClasses(JSContext *cx, JSObject *obj);
extern JS_PUBLIC_API(JSObject *)
JS_GetScopeChain(JSContext *cx);
@ -515,7 +541,7 @@ JS_SetGCCallbackRT(JSRuntime *rt, JSGCCallback cb);
* Classes, objects, and properties.
*/
struct JSClass {
char *name;
const char *name;
uint32 flags;
/* Mandatory non-null function pointer members. */

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

@ -51,11 +51,13 @@
#include "jsopcode.h"
#include "jsstr.h"
extern const char js_Error_str[]; /* trivial, from jsexn.h */
/*
* Keep this in sync with jspubtd.h -- an assertion below will insist that
* its length match the JSType enum's JSTYPE_LIMIT limit value.
*/
char *js_type_str[] = {
const char *js_type_str[] = {
"undefined",
"object",
"function",
@ -64,38 +66,46 @@ char *js_type_str[] = {
"boolean",
};
char *js_boolean_str[] = {
const char *js_boolean_str[] = {
js_false_str,
js_true_str
};
char js_Array_str[] = "Array";
char js_Math_str[] = "Math";
char js_NaN_str[] = "NaN";
char js_Object_str[] = "Object";
char js_anonymous_str[] = "anonymous";
char js_arguments_str[] = "arguments";
char js_arity_str[] = "arity";
char js_callee_str[] = "callee";
char js_caller_str[] = "caller";
char js_class_prototype_str[] = "prototype";
char js_constructor_str[] = "constructor";
char js_count_str[] = "__count__";
char js_eval_str[] = "eval";
char js_getter_str[] = "getter";
char js_get_str[] = "get";
char js_index_str[] = "index";
char js_input_str[] = "input";
char js_length_str[] = "length";
char js_name_str[] = "name";
char js_parent_str[] = "__parent__";
char js_proto_str[] = "__proto__";
char js_setter_str[] = "setter";
char js_set_str[] = "set";
char js_toSource_str[] = "toSource";
char js_toString_str[] = "toString";
char js_toLocaleString_str[] = "toLocaleString";
char js_valueOf_str[] = "valueOf";
const char js_Arguments_str[] = "Arguments";
const char js_Array_str[] = "Array";
const char js_Boolean_str[] = "Boolean";
const char js_Call_str[] = "Call";
const char js_Date_str[] = "Date";
const char js_Function_str[] = "Function";
const char js_Math_str[] = "Math";
const char js_Number_str[] = "Number";
const char js_Object_str[] = "Object";
const char js_RegExp_str[] = "RegExp";
const char js_Script_str[] = "Script";
const char js_String_str[] = "String";
const char js_anonymous_str[] = "anonymous";
const char js_arguments_str[] = "arguments";
const char js_arity_str[] = "arity";
const char js_callee_str[] = "callee";
const char js_caller_str[] = "caller";
const char js_class_prototype_str[] = "prototype";
const char js_constructor_str[] = "constructor";
const char js_count_str[] = "__count__";
const char js_eval_str[] = "eval";
const char js_getter_str[] = "getter";
const char js_get_str[] = "get";
const char js_index_str[] = "index";
const char js_input_str[] = "input";
const char js_length_str[] = "length";
const char js_name_str[] = "name";
const char js_parent_str[] = "__parent__";
const char js_proto_str[] = "__proto__";
const char js_setter_str[] = "setter";
const char js_set_str[] = "set";
const char js_toSource_str[] = "toSource";
const char js_toString_str[] = "toString";
const char js_toLocaleString_str[] = "toLocaleString";
const char js_valueOf_str[] = "valueOf";
#define HASH_OBJECT(o) ((JSHashNumber)(o) >> JSVAL_TAGBITS)
#define HASH_INT(i) ((JSHashNumber)(i))
@ -237,10 +247,19 @@ js_InitAtomState(JSContext *cx, JSAtomState *state)
FROB(booleanAtoms[1], js_true_str);
FROB(nullAtom, js_null_str);
FROB(ArgumentsAtom, js_Arguments_str);
FROB(ArrayAtom, js_Array_str);
FROB(BooleanAtom, js_Boolean_str);
FROB(CallAtom, js_Call_str);
FROB(DateAtom, js_Date_str);
FROB(ErrorAtom, js_Error_str);
FROB(FunctionAtom, js_Function_str);
FROB(MathAtom, js_Math_str);
FROB(NaNAtom, js_NaN_str);
FROB(NumberAtom, js_Number_str);
FROB(ObjectAtom, js_Object_str);
FROB(RegExpAtom, js_RegExp_str);
FROB(ScriptAtom, js_Script_str);
FROB(StringAtom, js_String_str);
FROB(anonymousAtom, js_anonymous_str);
FROB(argumentsAtom, js_arguments_str);
FROB(arityAtom, js_arity_str);
@ -249,21 +268,21 @@ js_InitAtomState(JSContext *cx, JSAtomState *state)
FROB(classPrototypeAtom, js_class_prototype_str);
FROB(constructorAtom, js_constructor_str);
FROB(countAtom, js_count_str);
FROB(getterAtom, js_getter_str);
FROB(evalAtom, js_eval_str);
FROB(getAtom, js_get_str);
FROB(getterAtom, js_getter_str);
FROB(indexAtom, js_index_str);
FROB(inputAtom, js_input_str);
FROB(lengthAtom, js_length_str);
FROB(nameAtom, js_name_str);
FROB(parentAtom, js_parent_str);
FROB(protoAtom, js_proto_str);
FROB(setterAtom, js_setter_str);
FROB(setAtom, js_set_str);
FROB(setterAtom, js_setter_str);
FROB(toSourceAtom, js_toSource_str);
FROB(toStringAtom, js_toString_str);
FROB(toLocaleStringAtom, js_toLocaleString_str);
FROB(valueOfAtom, js_valueOf_str);
FROB(evalAtom, js_eval_str);
#undef FROB

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

@ -141,10 +141,19 @@ struct JSAtomState {
JSAtom *nullAtom;
/* Various built-in or commonly-used atoms. */
JSAtom *ArgumentsAtom;
JSAtom *ArrayAtom;
JSAtom *BooleanAtom;
JSAtom *CallAtom;
JSAtom *DateAtom;
JSAtom *ErrorAtom;
JSAtom *FunctionAtom;
JSAtom *MathAtom;
JSAtom *NaNAtom;
JSAtom *NumberAtom;
JSAtom *ObjectAtom;
JSAtom *RegExpAtom;
JSAtom *ScriptAtom;
JSAtom *StringAtom;
JSAtom *anonymousAtom;
JSAtom *argumentsAtom;
JSAtom *arityAtom;
@ -153,21 +162,21 @@ struct JSAtomState {
JSAtom *classPrototypeAtom;
JSAtom *constructorAtom;
JSAtom *countAtom;
JSAtom *getterAtom;
JSAtom *evalAtom;
JSAtom *getAtom;
JSAtom *getterAtom;
JSAtom *indexAtom;
JSAtom *inputAtom;
JSAtom *lengthAtom;
JSAtom *nameAtom;
JSAtom *parentAtom;
JSAtom *protoAtom;
JSAtom *setterAtom;
JSAtom *setAtom;
JSAtom *setterAtom;
JSAtom *toLocaleStringAtom;
JSAtom *toSourceAtom;
JSAtom *toStringAtom;
JSAtom *toLocaleStringAtom;
JSAtom *valueOfAtom;
JSAtom *evalAtom;
#ifdef JS_THREADSAFE
JSThinLock lock;
@ -176,36 +185,44 @@ struct JSAtomState {
};
/* Well-known predefined strings and their atoms. */
extern char *js_type_str[];
extern char *js_boolean_str[];
extern const char *js_type_str[];
extern const char *js_boolean_str[];
extern char js_Array_str[];
extern char js_Math_str[];
extern char js_NaN_str[];
extern char js_Object_str[];
extern char js_anonymous_str[];
extern char js_arguments_str[];
extern char js_arity_str[];
extern char js_callee_str[];
extern char js_caller_str[];
extern char js_class_prototype_str[];
extern char js_constructor_str[];
extern char js_count_str[];
extern char js_eval_str[];
extern char js_getter_str[];
extern char js_get_str[];
extern char js_index_str[];
extern char js_input_str[];
extern char js_length_str[];
extern char js_name_str[];
extern char js_parent_str[];
extern char js_proto_str[];
extern char js_setter_str[];
extern char js_set_str[];
extern char js_toSource_str[];
extern char js_toString_str[];
extern char js_toLocaleString_str[];
extern char js_valueOf_str[];
extern const char js_Arguments_str[];
extern const char js_Array_str[];
extern const char js_Boolean_str[];
extern const char js_Call_str[];
extern const char js_Date_str[];
extern const char js_Function_str[];
extern const char js_Math_str[];
extern const char js_Number_str[];
extern const char js_Object_str[];
extern const char js_RegExp_str[];
extern const char js_Script_str[];
extern const char js_String_str[];
extern const char js_anonymous_str[];
extern const char js_arguments_str[];
extern const char js_arity_str[];
extern const char js_callee_str[];
extern const char js_caller_str[];
extern const char js_class_prototype_str[];
extern const char js_constructor_str[];
extern const char js_count_str[];
extern const char js_eval_str[];
extern const char js_getter_str[];
extern const char js_get_str[];
extern const char js_index_str[];
extern const char js_input_str[];
extern const char js_length_str[];
extern const char js_name_str[];
extern const char js_parent_str[];
extern const char js_proto_str[];
extern const char js_setter_str[];
extern const char js_set_str[];
extern const char js_toSource_str[];
extern const char js_toString_str[];
extern const char js_toLocaleString_str[];
extern const char js_valueOf_str[];
/*
* Initialize atom state. Return true on success, false with an out of

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

@ -51,10 +51,12 @@
#include "jsexn.h"
#include "jsgc.h"
#include "jslock.h"
#include "jsnum.h"
#include "jsobj.h"
#include "jsopcode.h"
#include "jsscan.h"
#include "jsscript.h"
#include "jsstr.h"
JSContext *
js_NewContext(JSRuntime *rt, size_t stackChunkSize)
@ -89,23 +91,13 @@ js_NewContext(JSRuntime *rt, size_t stackChunkSize)
JS_APPEND_LINK(&cx->links, &rt->contextList);
JS_UNLOCK_RUNTIME(rt);
if (first) {
/* First context on this runtime: initialize atoms and keywords. */
ok = js_InitAtomState(cx, &rt->atomState);
if (ok)
ok = js_InitScanner(cx);
JS_LOCK_RUNTIME(rt);
rt->state = JSRTS_UP;
JS_NOTIFY_ALL_CONDVAR(rt->stateChange);
JS_UNLOCK_RUNTIME(rt);
if (!ok) {
free(cx);
return NULL;
}
}
/*
* First we do the infallible, every-time per-context initializations.
* Should a later, fallible initialization (js_InitRegExpStatics, e.g.,
* or the stuff under 'if (first)' below) fail, at least the version
* and arena-pools will be valid and safe to use (say, from the last GC
* done by js_DestroyContext).
*/
cx->version = JSVERSION_DEFAULT;
cx->jsop_eq = JSOP_EQ;
cx->jsop_ne = JSOP_NE;
@ -116,7 +108,7 @@ js_NewContext(JSRuntime *rt, size_t stackChunkSize)
#if JS_HAS_REGEXPS
if (!js_InitRegExpStatics(cx, &cx->regExpStatics)) {
js_DestroyContext(cx, JS_FORCE_GC);
js_DestroyContext(cx, JS_NO_GC);
return NULL;
}
#endif
@ -124,6 +116,33 @@ js_NewContext(JSRuntime *rt, size_t stackChunkSize)
cx->throwing = JS_FALSE;
#endif
/*
* If cx is the first context on this runtime, initialize well-known atoms,
* keywords, numbers, and strings. If one of these steps should fail, the
* runtime will be left in a partially initialized state, with zeroes and
* nulls stored in the default-initialized remainder of the struct. We'll
* clean the runtime up under js_DestroyContext, because cx will be "last"
* as well as "first".
*/
if (first) {
ok = js_InitAtomState(cx, &rt->atomState);
if (ok)
ok = js_InitScanner(cx);
if (ok)
ok = js_InitRuntimeNumberState(cx);
if (ok)
ok = js_InitRuntimeStringState(cx);
if (!ok) {
js_DestroyContext(cx, JS_NO_GC);
return NULL;
}
JS_LOCK_RUNTIME(rt);
rt->state = JSRTS_UP;
JS_NOTIFY_ALL_CONDVAR(rt->stateChange);
JS_UNLOCK_RUNTIME(rt);
}
return cx;
}
@ -138,7 +157,7 @@ js_DestroyContext(JSContext *cx, JSGCMode gcmode)
/* Remove cx from context list first. */
JS_LOCK_RUNTIME(rt);
JS_ASSERT(rt->state == JSRTS_UP);
JS_ASSERT(rt->state == JSRTS_UP || rt->state == JSRTS_LAUNCHING);
JS_REMOVE_LINK(&cx->links);
last = (rt->contextList.next == (JSCList *)&rt->contextList);
if (last)
@ -149,20 +168,9 @@ js_DestroyContext(JSContext *cx, JSGCMode gcmode)
/* Unpin all pinned atoms before final GC. */
js_UnpinPinnedAtoms(&rt->atomState);
/* Unlock GC things held by runtime pointers. */
js_UnlockGCThing(cx, rt->jsNaN);
js_UnlockGCThing(cx, rt->jsNegativeInfinity);
js_UnlockGCThing(cx, rt->jsPositiveInfinity);
js_UnlockGCThing(cx, rt->emptyString);
/*
* Clear these so they get recreated if the standard classes are
* initialized again.
*/
rt->jsNaN = NULL;
rt->jsNegativeInfinity = NULL;
rt->jsPositiveInfinity = NULL;
rt->emptyString = NULL;
/* Unlock and clear GC things held by runtime pointers. */
js_FinishRuntimeNumberState(cx);
js_FinishRuntimeStringState(cx);
/* Clear debugging state to remove GC roots. */
JS_ClearAllTraps(cx);

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

@ -42,6 +42,7 @@
#include "jslong.h"
#include "jsatom.h"
#include "jsconfig.h"
#include "jsdhash.h"
#include "jsgc.h"
#include "jsinterp.h"
#include "jsobj.h"
@ -247,6 +248,8 @@ struct JSContext {
/* Locale specific callbacks for string conversion. */
JSLocaleCallbacks *localeCallbacks;
/* Non-null if init'ing standard classes lazily, to stop recursion. */
JSDHashTable *resolving;
};
/* Slightly more readable macros, also to hide bitset implementation detail. */

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

@ -428,7 +428,7 @@ MakeDay(jsdouble year, jsdouble month, jsdouble date)
#define TIMECLIP(d) ((JSDOUBLE_IS_FINITE(d) \
&& !((d < 0 ? -d : d) > HalfTimeDomain)) \
? js_DoubleToInteger(d + (+0.)) : *(cx->runtime->jsNaN))
? js_DoubleToInteger(d + (+0.)) : *cx->runtime->jsNaN)
/**
* end of ECMA 'support' functions
@ -439,7 +439,7 @@ MakeDay(jsdouble year, jsdouble month, jsdouble date)
*/
static JSClass date_class = {
"Date",
js_Date_str,
JSCLASS_HAS_PRIVATE,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
@ -1142,7 +1142,7 @@ date_makeTime(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
if (!js_ValueToNumber(cx, argv[i], &args[i]))
return JS_FALSE;
if (!JSDOUBLE_IS_FINITE(args[i])) {
*date = *(cx->runtime->jsNaN);
*date = *cx->runtime->jsNaN;
return js_NewNumberValue(cx, *date, rval);
}
args[i] = js_DoubleToInteger(args[i]);
@ -1271,7 +1271,7 @@ date_makeDate(JSContext *cx, JSObject *obj, uintN argc,
if (!js_ValueToNumber(cx, argv[i], &args[i]))
return JS_FALSE;
if (!JSDOUBLE_IS_FINITE(args[i])) {
*date = *(cx->runtime->jsNaN);
*date = *cx->runtime->jsNaN;
return js_NewNumberValue(cx, *date, rval);
}
args[i] = js_DoubleToInteger(args[i]);
@ -1378,7 +1378,7 @@ date_setYear(JSContext *cx, JSObject *obj, uintN argc,
if (!js_ValueToNumber(cx, argv[0], &year))
return JS_FALSE;
if (!JSDOUBLE_IS_FINITE(year)) {
*date = *(cx->runtime->jsNaN);
*date = *cx->runtime->jsNaN;
return js_NewNumberValue(cx, *date, rval);
}
@ -1857,7 +1857,7 @@ Date(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
return JS_FALSE;
if (!date_parseString(str->chars, date))
*date = *(cx->runtime->jsNaN);
*date = *cx->runtime->jsNaN;
*date = TIMECLIP(*date);
}
} else {
@ -1877,7 +1877,7 @@ Date(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
date = date_constructor(cx, obj);
if (!date)
return JS_FALSE;
*date = *(cx->runtime->jsNaN);
*date = *cx->runtime->jsNaN;
return JS_TRUE;
}
array[loop] = js_DoubleToInteger(double_arg);
@ -1924,7 +1924,7 @@ js_InitDateClass(JSContext *cx, JSObject *obj)
proto_date = date_constructor(cx, proto);
if (!proto_date)
return NULL;
*proto_date = *(cx->runtime->jsNaN);
*proto_date = *cx->runtime->jsNaN;
return proto;
}

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

@ -259,6 +259,7 @@ struct JSExnSpec {
* standard class sets. See jsfun.c:fun_hasInstance.
*/
#define MAKE_EXCEPTION_CTOR(name) \
const char js_##name##_str[] = #name; \
static JSBool \
name(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) \
{ \
@ -277,14 +278,14 @@ MAKE_EXCEPTION_CTOR(URIError)
#undef MAKE_EXCEPTION_CTOR
static struct JSExnSpec exceptions[] = {
{ JSEXN_NONE, "Error", Error },
{ JSEXN_ERR, "InternalError", InternalError },
{ JSEXN_ERR, "EvalError", EvalError },
{ JSEXN_ERR, "RangeError", RangeError },
{ JSEXN_ERR, "ReferenceError", ReferenceError },
{ JSEXN_ERR, "SyntaxError", SyntaxError },
{ JSEXN_ERR, "TypeError", TypeError },
{ JSEXN_ERR, "URIError", URIError },
{ JSEXN_NONE, js_Error_str, Error },
{ JSEXN_ERR, js_InternalError_str, InternalError },
{ JSEXN_ERR, js_EvalError_str, EvalError },
{ JSEXN_ERR, js_RangeError_str, RangeError },
{ JSEXN_ERR, js_ReferenceError_str, ReferenceError },
{ JSEXN_ERR, js_SyntaxError_str, SyntaxError },
{ JSEXN_ERR, js_TypeError_str, TypeError },
{ JSEXN_ERR, js_URIError_str, URIError },
{0,0,NULL}
};

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

@ -42,11 +42,23 @@
JS_BEGIN_EXTERN_C
/*
* Initialize exception object hierarchy.
* Initialize the exception constructor/prototype hierarchy.
*/
extern JSObject *
js_InitExceptionClasses(JSContext *cx, JSObject *obj);
/*
* String constants naming the exception classes.
*/
extern const char js_Error_str[];
extern const char js_InternalError_str[];
extern const char js_EvalError_str[];
extern const char js_RangeError_str[];
extern const char js_ReferenceError_str[];
extern const char js_SyntaxError_str[];
extern const char js_TypeError_str[];
extern const char js_URIError_str[];
/*
* Given a JSErrorReport, check to see if there is an exception associated with
* the error number. If there is, then create an appropriate exception object,

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

@ -254,7 +254,7 @@ args_enumerate(JSContext *cx, JSObject *obj)
}
JSClass js_ArgumentsClass = {
"Arguments",
js_Arguments_str,
JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE,
JS_PropertyStub, JS_PropertyStub,
args_getProperty, args_setProperty,
@ -578,7 +578,7 @@ call_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
}
JSClass js_CallClass = {
"Call",
js_Call_str,
JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE,
JS_PropertyStub, JS_PropertyStub,
call_getProperty, call_setProperty,
@ -1044,7 +1044,7 @@ fun_hasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
#endif /* !JS_HAS_INSTANCEOF */
JSClass js_FunctionClass = {
"Function",
js_Function_str,
JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE,
JS_PropertyStub, fun_delProperty,
fun_getProperty, JS_PropertyStub,
@ -1080,7 +1080,7 @@ fun_toString_sub(JSContext *cx, JSObject *obj, uint32 indent,
if (!JSVAL_IS_FUNCTION(cx, fval)) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_INCOMPATIBLE_PROTO,
"Function", "toString",
js_Function_str, js_toString_str,
JS_GetTypeName(cx, JS_TypeOfValue(cx, fval)));
return JS_FALSE;
}
@ -1113,7 +1113,7 @@ fun_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
}
#endif
static char js_call_str[] = "call";
static const char js_call_str[] = "call";
#if JS_HAS_CALL_FUNCTION
static JSBool
@ -1132,7 +1132,7 @@ fun_call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
if (!JSVAL_IS_FUNCTION(cx, fval)) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_INCOMPATIBLE_PROTO,
"Function", js_call_str,
js_Function_str, js_call_str,
JS_GetStringBytes(JS_ValueToString(cx, fval)));
return JS_FALSE;
}
@ -1197,7 +1197,7 @@ fun_apply(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
if (!JSVAL_IS_FUNCTION(cx, fval)) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_INCOMPATIBLE_PROTO,
"Function", "apply",
js_Function_str, "apply",
JS_GetStringBytes(JS_ValueToString(cx, fval)));
return JS_FALSE;
}
@ -1578,25 +1578,23 @@ bad:
return NULL;
}
JSBool
js_InitArgsAndCallClasses(JSContext *cx, JSObject *obj)
{
#if JS_HAS_ARGS_OBJECT
if (!JS_InitClass(cx, obj, NULL, &js_ArgumentsClass, Arguments, 0,
args_props, NULL, NULL, NULL)) {
return JS_FALSE;
}
JSObject *
js_InitArgumentsClass(JSContext *cx, JSObject *obj)
{
return JS_InitClass(cx, obj, NULL, &js_ArgumentsClass, Arguments, 0,
args_props, NULL, NULL, NULL);
}
#endif
#if JS_HAS_CALL_OBJECT
if (!JS_InitClass(cx, obj, NULL, &js_CallClass, Call, 0,
call_props, NULL, NULL, NULL)) {
return JS_FALSE;
}
#endif
return JS_TRUE;
JSObject *
js_InitCallClass(JSContext *cx, JSObject *obj)
{
return JS_InitClass(cx, obj, NULL, &js_CallClass, Call, 0,
call_props, NULL, NULL, NULL);
}
#endif
JSFunction *
js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, uintN nargs,

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

@ -75,8 +75,11 @@ js_IsIdentifier(JSString *str);
extern JSObject *
js_InitFunctionClass(JSContext *cx, JSObject *obj);
extern JSBool
js_InitArgsAndCallClasses(JSContext *cx, JSObject *obj);
extern JSObject *
js_InitArgumentsClass(JSContext *cx, JSObject *obj);
extern JSObject *
js_InitCallClass(JSContext *cx, JSObject *obj);
extern JSFunction *
js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, uintN nargs,

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

@ -715,6 +715,8 @@ have_fun:
frame.scopeChain = fp->scopeChain;
ok = native(cx, frame.thisp, argc, frame.argv, &frame.rval);
} else if (script) {
/* Use parent scope so js_GetCallObject can find the right "Call". */
frame.scopeChain = parent;
if (fun->flags & JSFUN_HEAVYWEIGHT) {
#if JS_HAS_CALL_OBJECT
/* Scope with a call object parented by the callee's parent. */
@ -726,8 +728,6 @@ have_fun:
/* Bad old code used the function as a proxy for all calls to it. */
frame.scopeChain = funobj;
#endif
} else {
frame.scopeChain = parent;
}
ok = js_Interpret(cx, &v);
} else {

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

@ -101,7 +101,7 @@ math_abs(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
jsdouble x, z;
if (!js_ValueToNumber(cx, argv[0], &x))
return JS_FALSE;
return JS_FALSE;
z = fd_fabs(x);
return js_NewNumberValue(cx, z, rval);
}
@ -112,7 +112,7 @@ math_acos(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
jsdouble x, z;
if (!js_ValueToNumber(cx, argv[0], &x))
return JS_FALSE;
return JS_FALSE;
z = fd_acos(x);
return js_NewNumberValue(cx, z, rval);
}
@ -123,7 +123,7 @@ math_asin(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
jsdouble x, z;
if (!js_ValueToNumber(cx, argv[0], &x))
return JS_FALSE;
return JS_FALSE;
#ifdef XP_MAC
if (x == 0)
return js_NewNumberValue(cx, x, rval);
@ -138,7 +138,7 @@ math_atan(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
jsdouble x, z;
if (!js_ValueToNumber(cx, argv[0], &x))
return JS_FALSE;
return JS_FALSE;
#ifdef XP_MAC
if (x == 0)
return js_NewNumberValue(cx, x, rval);
@ -166,7 +166,7 @@ math_ceil(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
jsdouble x, z;
if (!js_ValueToNumber(cx, argv[0], &x))
return JS_FALSE;
return JS_FALSE;
z = fd_ceil(x);
return js_NewNumberValue(cx, z, rval);
}
@ -177,7 +177,7 @@ math_cos(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
jsdouble x, z;
if (!js_ValueToNumber(cx, argv[0], &x))
return JS_FALSE;
return JS_FALSE;
z = fd_cos(x);
return js_NewNumberValue(cx, z, rval);
}
@ -188,7 +188,7 @@ math_exp(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
jsdouble x, z;
if (!js_ValueToNumber(cx, argv[0], &x))
return JS_FALSE;
return JS_FALSE;
#ifdef _WIN32
if (!JSDOUBLE_IS_NaN(x)) {
if (x == *cx->runtime->jsPositiveInfinity) {
@ -211,7 +211,7 @@ math_floor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
jsdouble x, z;
if (!js_ValueToNumber(cx, argv[0], &x))
return JS_FALSE;
return JS_FALSE;
z = fd_floor(x);
return js_NewNumberValue(cx, z, rval);
}
@ -222,7 +222,7 @@ math_log(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
jsdouble x, z;
if (!js_ValueToNumber(cx, argv[0], &x))
return JS_FALSE;
return JS_FALSE;
z = fd_log(x);
return js_NewNumberValue(cx, z, rval);
}
@ -383,7 +383,7 @@ math_round(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
jsdouble x, z;
if (!js_ValueToNumber(cx, argv[0], &x))
return JS_FALSE;
return JS_FALSE;
z = fd_copysign(fd_floor(x + 0.5), x);
return js_NewNumberValue(cx, z, rval);
}
@ -394,7 +394,7 @@ math_sin(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
jsdouble x, z;
if (!js_ValueToNumber(cx, argv[0], &x))
return JS_FALSE;
return JS_FALSE;
z = fd_sin(x);
return js_NewNumberValue(cx, z, rval);
}
@ -405,7 +405,7 @@ math_sqrt(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
jsdouble x, z;
if (!js_ValueToNumber(cx, argv[0], &x))
return JS_FALSE;
return JS_FALSE;
z = fd_sqrt(x);
return js_NewNumberValue(cx, z, rval);
}
@ -416,7 +416,7 @@ math_tan(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
jsdouble x, z;
if (!js_ValueToNumber(cx, argv[0], &x))
return JS_FALSE;
return JS_FALSE;
z = fd_tan(x);
return js_NewNumberValue(cx, z, rval);
}

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

@ -18,7 +18,7 @@
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License (the "GPL"), in which case the
@ -40,7 +40,7 @@
* identified per MPL Section 3.3
*
* Date Modified by Description of modification
* 05/15/2000 IBM Corp. Modified OS/2 floating point init.
* 05/15/2000 IBM Corp. Modified OS/2 floating point init.
*/
/*
@ -153,6 +153,12 @@ num_parseInt(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
return js_NewNumberValue(cx, d, rval);
}
const char js_Infinity_str[] = "Infinity";
const char js_NaN_str[] = "NaN";
const char js_isNaN_str[] = "isNaN";
const char js_isFinite_str[] = "isFinite";
const char js_parseFloat_str[] = "parseFloat";
const char js_parseInt_str[] = "parseInt";
static JSFunctionSpec number_functions[] = {
{"isNaN", num_isNaN, 1,0,0},
@ -383,7 +389,7 @@ enum nc_slot {
/*
* Some to most C compilers forbid spelling these at compile time, or barf
* if you try, so all but MAX_VALUE are set at runtime by js_InitNumberClass
* if you try, so all but MAX_VALUE are set up by js_InitRuntimeNumberState
* using union dpun.
*/
static JSConstDoubleSpec number_constants[] = {
@ -397,63 +403,84 @@ static JSConstDoubleSpec number_constants[] = {
static jsdouble NaN;
JSObject *
js_InitNumberClass(JSContext *cx, JSObject *obj)
JSBool
js_InitRuntimeNumberState(JSContext *cx)
{
JSRuntime *rt;
union dpun u;
JSObject *proto, *ctor;
rt = cx->runtime;
JS_ASSERT(!rt->jsNaN);
#ifdef XP_OS2
/*DSR071597 - I have no idea what this really does other than mucking with the floating */
/*point unit, but it does fix a "floating point underflow" exception I am getting, and there*/
/*is similar code in the Hursley java. Making sure we have the same code in Javascript */
/*where Netscape was calling control87 on Windows... */
_control87(MCW_EM+PC_53+RC_NEAR,MCW_EM+MCW_PC+MCW_RC);
#endif /* XP_OS2 */
#ifdef XP_OS2
/*DSR071597 - I have no idea what this really does other than mucking with the floating */
/*point unit, but it does fix a "floating point underflow" exception I am getting, and there*/
/*is similar code in the Hursley java. Making sure we have the same code in Javascript */
/*where Netscape was calling control87 on Windows... */
_control87(MCW_EM+PC_53+RC_NEAR,MCW_EM+MCW_PC+MCW_RC);
#endif /* XP_OS2 */
if (!rt->jsNaN) {
#ifndef __MWERKS__
#if defined (XP_PC) && !defined(XP_OS2)
#if defined (_M_IX86)
/* On Alpha platform this is handled via Compiler option */
_control87(MCW_EM, MCW_EM);
/* On Alpha platform this is handled via Compiler option */
_control87(MCW_EM, MCW_EM);
#endif
#endif /* XP_PC && !XP_OS2 */
#endif /* __MWERKS__ */
u.s.hi = JSDOUBLE_HI32_EXPMASK | JSDOUBLE_HI32_MANTMASK;
u.s.lo = 0xffffffff;
number_constants[NC_NaN].dval = NaN = u.d;
rt->jsNaN = js_NewDouble(cx, NaN);
if (!rt->jsNaN || !js_LockGCThing(cx, rt->jsNaN))
return NULL;
u.s.hi = JSDOUBLE_HI32_EXPMASK | JSDOUBLE_HI32_MANTMASK;
u.s.lo = 0xffffffff;
number_constants[NC_NaN].dval = NaN = u.d;
rt->jsNaN = js_NewDouble(cx, NaN);
if (!rt->jsNaN || !js_LockGCThing(cx, rt->jsNaN))
return JS_FALSE;
u.s.hi = JSDOUBLE_HI32_EXPMASK;
u.s.lo = 0x00000000;
number_constants[NC_POSITIVE_INFINITY].dval = u.d;
rt->jsPositiveInfinity = js_NewDouble(cx, u.d);
if (!rt->jsPositiveInfinity ||
!js_LockGCThing(cx, rt->jsPositiveInfinity)) {
return NULL;
}
u.s.hi = JSDOUBLE_HI32_SIGNBIT | JSDOUBLE_HI32_EXPMASK;
u.s.lo = 0x00000000;
number_constants[NC_NEGATIVE_INFINITY].dval = u.d;
rt->jsNegativeInfinity = js_NewDouble(cx, u.d);
if (!rt->jsNegativeInfinity ||
!js_LockGCThing(cx, rt->jsNegativeInfinity)) {
return NULL;
}
u.s.hi = 0;
u.s.lo = 1;
number_constants[NC_MIN_VALUE].dval = u.d;
u.s.hi = JSDOUBLE_HI32_EXPMASK;
u.s.lo = 0x00000000;
number_constants[NC_POSITIVE_INFINITY].dval = u.d;
rt->jsPositiveInfinity = js_NewDouble(cx, u.d);
if (!rt->jsPositiveInfinity ||
!js_LockGCThing(cx, rt->jsPositiveInfinity)) {
return JS_FALSE;
}
u.s.hi = JSDOUBLE_HI32_SIGNBIT | JSDOUBLE_HI32_EXPMASK;
u.s.lo = 0x00000000;
number_constants[NC_NEGATIVE_INFINITY].dval = u.d;
rt->jsNegativeInfinity = js_NewDouble(cx, u.d);
if (!rt->jsNegativeInfinity ||
!js_LockGCThing(cx, rt->jsNegativeInfinity)) {
return JS_FALSE;
}
u.s.hi = 0;
u.s.lo = 1;
number_constants[NC_MIN_VALUE].dval = u.d;
return JS_TRUE;
}
void
js_FinishRuntimeNumberState(JSContext *cx)
{
JSRuntime *rt = cx->runtime;
js_UnlockGCThing(cx, rt->jsNaN);
js_UnlockGCThing(cx, rt->jsNegativeInfinity);
js_UnlockGCThing(cx, rt->jsPositiveInfinity);
rt->jsNaN = NULL;
rt->jsNegativeInfinity = NULL;
rt->jsPositiveInfinity = NULL;
}
JSObject *
js_InitNumberClass(JSContext *cx, JSObject *obj)
{
JSObject *proto, *ctor;
JSRuntime *rt;
if (!JS_DefineFunctions(cx, obj, number_functions))
return NULL;
@ -466,13 +493,14 @@ js_InitNumberClass(JSContext *cx, JSObject *obj)
return NULL;
/* ECMA 15.1.1.1 */
rt = cx->runtime;
if (!JS_DefineProperty(cx, obj, js_NaN_str, DOUBLE_TO_JSVAL(rt->jsNaN),
NULL, NULL, JSPROP_PERMANENT)) {
return NULL;
}
/* ECMA 15.1.1.2 */
if (!JS_DefineProperty(cx, obj, "Infinity",
if (!JS_DefineProperty(cx, obj, js_Infinity_str,
DOUBLE_TO_JSVAL(rt->jsPositiveInfinity),
NULL, NULL, JSPROP_PERMANENT)) {
return NULL;
@ -768,7 +796,7 @@ js_strtod(JSContext *cx, const jschar *s, const jschar **ep, jsdouble *dp)
istr = cstr;
if ((negative = (*istr == '-')) != 0 || *istr == '+')
istr++;
if (!strncmp(istr, "Infinity", 8)) {
if (!strncmp(istr, js_Infinity_str, sizeof js_Infinity_str - 1)) {
d = *(negative ? cx->runtime->jsNegativeInfinity : cx->runtime->jsPositiveInfinity);
estr = istr + 8;
} else {
@ -843,22 +871,26 @@ js_strtointeger(JSContext *cx, const jschar *s, const jschar **ep, jsint base, j
if ((negative = (*s1 == '-')) != 0 || *s1 == '+')
s1++;
if (base == 0)
if (base == 0) {
/* No base supplied, or some base that evaluated to 0. */
if (*s1 == '0')
if (*s1 == '0') {
/* It's either hex or octal; only increment char if str isn't '0' */
if (s1[1] == 'X' || s1[1] == 'x') { /* Hex */
s1 += 2;
base = 16;
} else /* Octal */
} else { /* Octal */
base = 8;
else
}
} else {
base = 10; /* Default to decimal. */
else if (base == 16 && *s1 == '0' && (s1[1] == 'X' || s1[1] == 'x'))
}
} else if (base == 16 && *s1 == '0' && (s1[1] == 'X' || s1[1] == 'x')) {
/* If base is 16, ignore hex prefix. */
s1 += 2;
}
/* Done with the preliminaries; find some prefix of the string that's
/*
* Done with the preliminaries; find some prefix of the string that's
* a number in the given base.
*/
start = s1; /* Mark - if string is empty, we return NaN. */
@ -876,16 +908,17 @@ js_strtointeger(JSContext *cx, const jschar *s, const jschar **ep, jsint base, j
break;
if (digit >= (uintN)base)
break;
value = value*base + digit;
value = value * base + digit;
s1++;
}
if (value >= 9007199254740992.0) {
if (base == 10) {
/* If we're accumulating a decimal number and the number is >= 2^53, then
* the result from the repeated multiply-add above may be inaccurate. Call
* JS_strtod to get the correct answer.
*/
/*
* If we're accumulating a decimal number and the number is >=
* 2^53, then the result from the repeated multiply-add above may
* be inaccurate. Call JS_strtod to get the correct answer.
*/
size_t i;
size_t length = s1 - start;
char *cstr = (char *) malloc(length + 1);
@ -902,17 +935,17 @@ js_strtointeger(JSContext *cx, const jschar *s, const jschar **ep, jsint base, j
if (errno == ERANGE && value == HUGE_VAL)
value = *cx->runtime->jsPositiveInfinity;
free(cstr);
} else if (base == 2 || base == 4 || base == 8 || base == 16 || base == 32) {
/* The number may also be inaccurate for one of these bases. This
* happens if the addition in value*base + digit causes a round-down
* to an even least significant mantissa bit when the first dropped bit
* is a one. If any of the following digits in the number (which haven't
* been added in yet) are nonzero then the correct action would have
* been to round up instead of down. An example of this occurs when
* reading the number 0x1000000000000081, which rounds to 0x1000000000000000
* instead of 0x1000000000000100.
*/
} else if ((base & (base - 1)) == 0) {
/*
* The number may also be inaccurate for power-of-two bases. This
* happens if the addition in value * base + digit causes a round-
* down to an even least significant mantissa bit when the first
* dropped bit is a one. If any of the following digits in the
* number (which haven't been added in yet) are nonzero, then the
* correct action would have been to round up instead of down. An
* example occurs when reading the number 0x1000000000000081, which
* rounds to 0x1000000000000000 instead of 0x1000000000000100.
*/
struct BinaryDigitReader bdr;
intN bit, bit2;
intN j;

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

@ -79,13 +79,31 @@ JS_BEGIN_EXTERN_C
* safe) leaves i as (jsint)d. This also avoid anomalous NaN floating point
* comparisons under MSVC.
*/
#define JSDOUBLE_IS_INT(d, i) (JSDOUBLE_IS_FINITE(d) && !JSDOUBLE_IS_NEGZERO(d) \
#define JSDOUBLE_IS_INT(d, i) (JSDOUBLE_IS_FINITE(d) \
&& !JSDOUBLE_IS_NEGZERO(d) \
&& ((d) == (i = (jsint)(d))))
/* Initialize number constants and runtime state for the first context. */
extern JSBool
js_InitRuntimeNumberState(JSContext *cx);
extern void
js_FinishRuntimeNumberState(JSContext *cx);
/* Initialize the Number class, returning its prototype object. */
extern JSObject *
js_InitNumberClass(JSContext *cx, JSObject *obj);
/*
* String constants for global function names, used in jsapi.c and jsnum.c.
*/
extern const char js_Infinity_str[];
extern const char js_NaN_str[];
extern const char js_isNaN_str[];
extern const char js_isFinite_str[];
extern const char js_parseFloat_str[];
extern const char js_parseInt_str[];
/* GC-allocate a new JS number. */
extern jsdouble *
js_NewDouble(JSContext *cx, jsdouble d);

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

@ -775,7 +775,7 @@ js_obj_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
{
jschar *chars;
size_t nchars;
char *clazz, *prefix;
const char *clazz, *prefix;
JSString *str;
#if JS_HAS_INITIALIZERS
@ -1094,27 +1094,40 @@ obj_defineSetter(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
}
#endif /* JS_HAS_GETTER_SETTER */
#if JS_HAS_OBJ_WATCHPOINT
const char js_watch_str[] = "watch";
const char js_unwatch_str[] = "unwatch";
#endif
#if JS_HAS_NEW_OBJ_METHODS
const char js_hasOwnProperty_str[] = "hasOwnProperty";
const char js_isPrototypeOf_str[] = "isPrototypeOf";
const char js_propertyIsEnumerable_str[] = "propertyIsEnumerable";
#endif
#if JS_HAS_GETTER_SETTER
const char js_defineGetter_str[] = "__defineGetter__";
const char js_defineSetter_str[] = "__defineSetter__";
#endif
static JSFunctionSpec object_methods[] = {
#if JS_HAS_TOSOURCE
{js_toSource_str, js_obj_toSource, 0, 0, OBJ_TOSTRING_EXTRA},
{js_toSource_str, js_obj_toSource, 0, 0, OBJ_TOSTRING_EXTRA},
#endif
{js_toString_str, js_obj_toString, 0, 0, OBJ_TOSTRING_EXTRA},
{js_toLocaleString_str, js_obj_toString, 0, 0, OBJ_TOSTRING_EXTRA},
{js_valueOf_str, obj_valueOf, 0,0,0},
{js_eval_str, obj_eval, 1,0,0},
{js_toString_str, js_obj_toString, 0, 0, OBJ_TOSTRING_EXTRA},
{js_toLocaleString_str, js_obj_toString, 0, 0, OBJ_TOSTRING_EXTRA},
{js_valueOf_str, obj_valueOf, 0,0,0},
{js_eval_str, obj_eval, 1,0,0},
#if JS_HAS_OBJ_WATCHPOINT
{"watch", obj_watch, 2,0,0},
{"unwatch", obj_unwatch, 1,0,0},
{js_watch_str, obj_watch, 2,0,0},
{js_unwatch_str, obj_unwatch, 1,0,0},
#endif
#if JS_HAS_NEW_OBJ_METHODS
{"hasOwnProperty", obj_hasOwnProperty, 1,0,0},
{"isPrototypeOf", obj_isPrototypeOf, 1,0,0},
{"propertyIsEnumerable", obj_propertyIsEnumerable, 1,0,0},
{js_hasOwnProperty_str, obj_hasOwnProperty, 1,0,0},
{js_isPrototypeOf_str, obj_isPrototypeOf, 1,0,0},
{js_propertyIsEnumerable_str, obj_propertyIsEnumerable, 1,0,0},
#endif
#if JS_HAS_GETTER_SETTER
{"__defineGetter__", obj_defineGetter, 2,0,0},
{"__defineSetter__", obj_defineSetter, 2,0,0},
{js_defineGetter_str, obj_defineGetter, 2,0,0},
{js_defineSetter_str, obj_defineSetter, 2,0,0},
#endif
{0,0,0,0,0}
};
@ -1318,7 +1331,7 @@ JSObject *
js_InitObjectClass(JSContext *cx, JSObject *obj)
{
JSObject *proto;
jsval fval;
jsval eval;
#if JS_HAS_SHARP_VARS
JS_ASSERT(sizeof(jsatomid) * JS_BITS_PER_BYTE >= ATOM_INDEX_LIMIT_LOG2 + 1);
@ -1335,11 +1348,11 @@ js_InitObjectClass(JSContext *cx, JSObject *obj)
/* ECMA (15.1.2.1) says 'eval' is also a property of the global object. */
if (!OBJ_GET_PROPERTY(cx, proto, (jsid)cx->runtime->atomState.evalAtom,
&fval)) {
&eval)) {
return NULL;
}
if (!OBJ_DEFINE_PROPERTY(cx, obj, (jsid)cx->runtime->atomState.evalAtom,
fval, NULL, NULL, 0, NULL)) {
eval, NULL, NULL, 0, NULL)) {
return NULL;
}
@ -2930,7 +2943,7 @@ js_XDRObject(JSXDRState *xdr, JSObject **objp)
{
JSContext *cx;
JSClass *clasp;
char *className;
const char *className;
uint32 classId, classDef;
JSBool ok;
JSObject *proto;
@ -2952,7 +2965,7 @@ js_XDRObject(JSXDRState *xdr, JSObject **objp)
/* XDR a flag word followed (if true) by the class name. */
if (!JS_XDRUint32(xdr, &classDef))
return JS_FALSE;
if (classDef && !JS_XDRCString(xdr, &className))
if (classDef && !JS_XDRCString(xdr, (char **) &className))
return JS_FALSE;
/* From here on, return through out: to free className if it was set. */
@ -2991,7 +3004,7 @@ js_XDRObject(JSXDRState *xdr, JSObject **objp)
}
out:
if (xdr->mode != JSXDR_ENCODE && className)
JS_free(cx, className);
JS_free(cx, (void *)className);
return ok;
}

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

@ -196,6 +196,15 @@ js_obj_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
extern JSObject *
js_InitObjectClass(JSContext *cx, JSObject *obj);
/* Select Object.prototype method names shared between jsapi.c and jsobj.c. */
extern const char js_watch_str[];
extern const char js_unwatch_str[];
extern const char js_hasOwnProperty_str[];
extern const char js_isPrototypeOf_str[];
extern const char js_propertyIsEnumerable_str[];
extern const char js_defineGetter_str[];
extern const char js_defineSetter_str[];
extern void
js_InitObjectMap(JSObjectMap *map, jsrefcount nrefs, JSObjectOps *ops,
JSClass *clasp);

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

@ -2483,7 +2483,7 @@ regexp_xdrObject(JSXDRState *xdr, JSObject **objp)
#endif /* !JS_HAS_XDR */
JSClass js_RegExpClass = {
"RegExp",
js_RegExp_str,
JSCLASS_HAS_PRIVATE,
JS_PropertyStub, JS_PropertyStub, regexp_getProperty, regexp_setProperty,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, regexp_finalize,

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

@ -623,7 +623,7 @@ script_call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
}
JS_FRIEND_DATA(JSClass) js_ScriptClass = {
"Script",
js_Script_str,
JSCLASS_HAS_PRIVATE,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, script_finalize,

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

@ -268,16 +268,26 @@ str_uneval(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
}
#endif
static JSFunctionSpec string_functions[] = {
{"escape", str_escape, 1,0,0},
{"unescape", str_unescape, 1,0,0},
const char js_escape_str[] = "escape";
const char js_unescape_str[] = "unescape";
#if JS_HAS_UNEVAL
{"uneval", str_uneval, 1,0,0},
const char js_uneval_str[] = "uneval";
#endif
{"decodeURI", str_decodeURI, 1,0,0},
{"encodeURI", str_encodeURI, 1,0,0},
{"decodeURIComponent", str_decodeURI_Component, 1,0,0},
{"encodeURIComponent", str_encodeURI_Component, 1,0,0},
const char js_decodeURI_str[] = "decodeURI";
const char js_encodeURI_str[] = "encodeURI";
const char js_decodeURIComponent_str[] = "decodeURIComponent";
const char js_encodeURIComponent_str[] = "encodeURIComponent";
static JSFunctionSpec string_functions[] = {
{js_escape_str, str_escape, 1,0,0},
{js_unescape_str, str_unescape, 1,0,0},
#if JS_HAS_UNEVAL
{js_uneval_str, str_uneval, 1,0,0},
#endif
{js_decodeURI_str, str_decodeURI, 1,0,0},
{js_encodeURI_str, str_encodeURI, 1,0,0},
{js_decodeURIComponent_str, str_decodeURI_Component, 1,0,0},
{js_encodeURIComponent_str, str_encodeURI_Component, 1,0,0},
{0,0,0,0,0}
};
@ -373,7 +383,7 @@ str_resolve(JSContext *cx, JSObject *obj, jsval id)
}
static JSClass string_class = {
"String",
js_String_str,
JSCLASS_HAS_PRIVATE,
JS_PropertyStub, str_delProperty, str_getProperty, JS_PropertyStub,
str_enumerate, str_resolve, JS_ConvertStub, JS_FinalizeStub,
@ -911,9 +921,9 @@ match_or_replace(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
reobj = JSVAL_TO_OBJECT(argv[0]);
re = (JSRegExp *) JS_GetPrivate(cx, reobj);
} else {
if (JSVAL_IS_VOID(argv[0]))
if (JSVAL_IS_VOID(argv[0])) {
re = js_NewRegExp(cx, NULL, cx->runtime->emptyString, 0, JS_FALSE);
else {
} else {
src = js_ValueToString(cx, argv[0]);
if (!src)
return JS_FALSE;
@ -2213,22 +2223,36 @@ js_FreeStringGlobals()
#endif
}
JSObject *
js_InitStringClass(JSContext *cx, JSObject *obj)
JSBool
js_InitRuntimeStringState(JSContext *cx)
{
JSRuntime *rt;
JSString *empty;
JSObject *proto;
rt = cx->runtime;
empty = rt->emptyString;
if (!empty) {
/* Make a permanently locked empty string. */
empty = js_NewStringCopyN(cx, js_empty_ucstr, 0, GCF_LOCK);
if (!empty)
return NULL;
rt->emptyString = empty;
}
JS_ASSERT(!rt->emptyString);
/* Make a permanently locked empty string. */
empty = js_NewStringCopyN(cx, js_empty_ucstr, 0, GCF_LOCK);
if (!empty)
return JS_FALSE;
rt->emptyString = empty;
return JS_TRUE;
}
void
js_FinishRuntimeStringState(JSContext *cx)
{
JSRuntime *rt = cx->runtime;
js_UnlockGCThing(cx, rt->emptyString);
rt->emptyString = NULL;
}
JSObject *
js_InitStringClass(JSContext *cx, JSObject *obj)
{
JSObject *proto;
/* Define the escape, unescape functions in the global object. */
if (!JS_DefineFunctions(cx, obj, string_functions))
@ -2239,7 +2263,8 @@ js_InitStringClass(JSContext *cx, JSObject *obj)
NULL, string_static_methods);
if (!proto)
return NULL;
OBJ_SET_SLOT(cx, proto, JSSLOT_PRIVATE, STRING_TO_JSVAL(empty));
OBJ_SET_SLOT(cx, proto, JSSLOT_PRIVATE,
STRING_TO_JSVAL(cx->runtime->emptyString));
return proto;
}

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

@ -184,10 +184,25 @@ js_InitStringGlobals(void);
extern void
js_FreeStringGlobals(void);
/* Initialize per-runtime string state for the first context in the runtime. */
extern JSBool
js_InitRuntimeStringState(JSContext *cx);
extern void
js_FinishRuntimeStringState(JSContext *cx);
/* Initialize the String class, returning its prototype object. */
extern JSObject *
js_InitStringClass(JSContext *cx, JSObject *obj);
extern const char js_escape_str[];
extern const char js_unescape_str[];
extern const char js_uneval_str[];
extern const char js_decodeURI_str[];
extern const char js_encodeURI_str[];
extern const char js_decodeURIComponent_str[];
extern const char js_encodeURIComponent_str[];
/* GC-allocate a string descriptor for the given malloc-allocated chars. */
extern JSString *
js_NewString(JSContext *cx, jschar *chars, size_t length, uintN gcflag);
@ -251,8 +266,8 @@ js_CompareStrings(const JSString *str1, const JSString *str2);
extern jsint
js_BoyerMooreHorspool(const jschar *text, jsint textlen,
const jschar *pat, jsint patlen,
jsint start);
const jschar *pat, jsint patlen,
jsint start);
extern size_t
js_strlen(const jschar *s);
@ -303,11 +318,10 @@ js_GetStringBytes(JSString *str);
/*
* Returns an escaped version of character string str.
* */
*/
char*
js_escape(JSContext *cx, JSObject *obj, char *str);
JSBool
str_escape(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);