зеркало из https://github.com/mozilla/pjs.git
Support lazy initialization of standard classes and their associated global functions/properties (46703, r=jband,rogerl).
This commit is contained in:
Родитель
b100da9c08
Коммит
9d16e66aad
27
js/src/js.c
27
js/src/js.c
|
@ -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;
|
||||
|
||||
|
|
363
js/src/jsapi.c
363
js/src/jsapi.c
|
@ -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);
|
||||
}
|
||||
|
|
167
js/src/jsnum.c
167
js/src/jsnum.c
|
@ -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);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче