view release on metacpan or search on metacpan
JS/js/ChangeLog view on Meta::CPAN
- Fixed standard class bootstrapping bug that left an extra Object instance
in the middle of the prototype chain for Date, RegExp, etc. (all but Object
and Function) instances.
- String.prototype.split ECMAv1 conformance restoration (split-by-empty-string
was stupidly broken last time).
Tag JSREF_RELEASE_19980219 (2/16/98):
- Fixed very recent i++ (for undefined i) crash-bug (also prior, longstanding
bug where i++ for undefined i resulted in NaN).
- ECMA conformance for [[DefaultValue]] (8.6.2.6), ToBoolean (9.2), and null
(default) this-parameter handling (10.2.3).
- New bytecodes paving the way for ECMA-conformant for/in loops and unqualified
name assignment.
- JS1.2 String.prototype.replace did not emulate Perl4's expansion of $` to be
the global left context (not from last local match). Essentially the same
bug bit replace for the empty-string global match case, which "bumps along"
JS/js/ChangeLog view on Meta::CPAN
- bitwise logical and shift operators use the correct ECMA type conversions,
intermediate types, and boundary behavior.
- Array.prototype.push emulates Perl5 for JS versions other than 1.2; there
it emulated Perl4, except when no arguments were passed (it would return
the array object bound to this in that case; fixed to return undefined).
- All generic Array methods now update a length property, in case no such
property existed in the object that delegates to Array.prototype, or that
refers to the particular method.
- Except for JS1.2, Array.prototype.splice always returns an array, even when
given no arguments or a zero-length slice. JS1.2 compatibility continues.
- NaN Date fixes.
- JSFunctionSpec's nargs member now species the "best arity" of the function,
which ECMA specifies as the value of the function's length property. So to
allocate local GC roots, use the new extra member of JSFunctionSpec and let
nargs count only the minimum or optimum number of desired arguments.
- Relational and equality operator fixes too gnarly and subtle to describe
here, affecting mainly the hint argument (or lack of it) to valueOf.
- A new JS_IsConstructing API and underlying support, so ECMA [[Call]] and
[[Construct]] can be distinguished.
- A JS_InitClass extension to tolerate NULL for the constructor native C
function argument -- this causes a class like Math to be created, where
JS/js/ChangeLog view on Meta::CPAN
In a future release, the final JS1.3 version will return object and array
initializer strings from {Object,Array}.prototype.toSource methods, rather
than toString, for ECMA and backward compatibility.
- More ECMA conformance fixes, apart from Unicode:
- New ECMA-conformant jsdate.c by Mike McCabe (mccabe@netscape.com).
- Improved equality and relational operator implementations.
- Correct division operator result sign.
- The unary-plus operator.
- NaN and Infinity top-level properties.
- Setting a read-only property fails silently, rather than stopping the
script with an error report.
- Deleting a permanent property fails with a false return from the delete
operator. If the property is not in the object addressed in the delete
expression, or it is successfully deleted, the expression results in true.
- The beginnings of finer-grained, non-nesting/low-level locking in jslock.h,
used in jsstr.c for the deflated_string_cache_lock. For this version, you
need to provide a PRLock typedef and PR_NewLock, PR_DestroyLock, PR_Lock,
and PR_Unlock functions that implement a binary semaphore.
JS/js/ChangeLog view on Meta::CPAN
release; it precludes too many alternative GC implementations.
- ECMA conformant Date API, including get/setFullYear and the UTC variants
to all the get/set methods.
- ECMA conformant Number.MIN_VALUE, which is the smallest denorm now, not
the smallest normal as in all past JS versions.
- ECMA comformant isFinite() function.
- ECMA signed 0 and NaN number to string conversions.
- Watcom (__WATCOMC__) support for PC builds.
Quick update (4/27/97):
- Prototypes are no longer constructed in JS_InitClass. If you want a class
prototype to be constructed by the native 'constructor' function passed to
JS_InitClass, you can save JS_InitClass's return value and do it yourself:
proto = JS_InitClass(...);
ok = JS_CallFunctionName(cx, proto, "constructor", argc, argc, &rval);
JS/js/README view on Meta::CPAN
- prprintf.c, prprintf.h
Portable, buffer-overrun-resistant sprintf and friends.
For no good reason save lack of time, the %e, %f, and %g formats cause your
system's native sprintf, rather than PR_dtoa, to be used. This bug doesn't
affect JSRef, because it uses its own PR_dtoa call in jsnum.c to convert
from double to string, but it's a bug that we'll fix later, and one you
should be aware of if you intend to use a PR_*printf function with your own
floating type arguments -- various vendor sprintf's mishandle NaN, +/-Inf,
and some even print normal floating values inaccurately.
- prtime.c, prtime.h
Time functions. These interfaces are named in a way that makes local vs.
universal time confusion likely. Caveat emptor, and we're working on it.
To make matters worse, Java (and therefore JavaScript) uses "local" time
numbers (offsets from the epoch) in its Date class.
JS/js/jsapi.c view on Meta::CPAN
#include "jsscript.h"
#include "jsstr.h"
#if defined(JS_PARANOID_REQUEST) && defined(JS_THREADSAFE)
#define CHECK_REQUEST(cx) PR_ASSERT(cx->requestDepth)
#else
#define CHECK_REQUEST(cx) ((void)0)
#endif
JS_PUBLIC_API(jsval)
JS_GetNaNValue(JSContext *cx)
{
CHECK_REQUEST(cx);
return DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
}
JS_PUBLIC_API(jsval)
JS_GetNegativeInfinityValue(JSContext *cx)
{
CHECK_REQUEST(cx);
return DOUBLE_TO_JSVAL(cx->runtime->jsNegativeInfinity);
}
JS_PUBLIC_API(jsval)
JS/js/jsapi.h view on Meta::CPAN
*/
#define JSVAL_VOID INT_TO_JSVAL(0 - JSVAL_INT_POW2(30))
#define JSVAL_NULL OBJECT_TO_JSVAL(0)
#define JSVAL_ZERO INT_TO_JSVAL(0)
#define JSVAL_ONE INT_TO_JSVAL(1)
#define JSVAL_FALSE BOOLEAN_TO_JSVAL(JS_FALSE)
#define JSVAL_TRUE BOOLEAN_TO_JSVAL(JS_TRUE)
/* Don't want to export data, so provide accessors for non-inline jsvals. */
extern JS_PUBLIC_API(jsval)
JS_GetNaNValue(JSContext *cx);
extern JS_PUBLIC_API(jsval)
JS_GetNegativeInfinityValue(JSContext *cx);
extern JS_PUBLIC_API(jsval)
JS_GetPositiveInfinityValue(JSContext *cx);
extern JS_PUBLIC_API(jsval)
JS_GetEmptyStringValue(JSContext *cx);
JS/js/jsbool.c view on Meta::CPAN
}
}
if (JSVAL_IS_STRING(v)) {
b = JSVAL_TO_STRING(v)->length ? JS_TRUE : JS_FALSE;
}
if (JSVAL_IS_INT(v)) {
b = JSVAL_TO_INT(v) ? JS_TRUE : JS_FALSE;
}
if (JSVAL_IS_DOUBLE(v)) {
d = *JSVAL_TO_DOUBLE(v);
b = (!JSDOUBLE_IS_NaN(d) && d != 0) ? JS_TRUE : JS_FALSE;
}
if (JSVAL_IS_BOOLEAN(v)) {
b = JSVAL_TO_BOOLEAN(v);
}
*bp = b;
return JS_TRUE;
}
JS/js/jscntxt.c view on Meta::CPAN
if (js_InterpreterHooks && js_InterpreterHooks->destroyContext) {
/* This is a stub, but in case it removes roots, call it now. */
js_InterpreterHooks->destroyContext(cx);
}
if (rtempty) {
/* 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;
/* Clear debugging state to remove GC roots. */
JS_ClearAllTraps(cx);
JS_ClearAllWatchPoints(cx);
}
/* Remove more GC roots in regExpStatics, then collect garbage. */
JS/js/jscntxt.h view on Meta::CPAN
/* Random number generator state, used by jsmath.c. */
JSBool rngInitialized;
int64 rngMultiplier;
int64 rngAddend;
int64 rngMask;
int64 rngSeed;
jsdouble rngDscale;
/* Well-known numbers held for use by this runtime's contexts. */
jsdouble *jsNaN;
jsdouble *jsNegativeInfinity;
jsdouble *jsPositiveInfinity;
/* Empty string held for use by this runtime's contexts. */
JSString *emptyString;
/* List of active contexts sharing this runtime. */
PRCList contextList;
/* These are used for debugging -- see jsprvtd.h and jsdbgapi.h. */
JS/js/jsdate.c view on Meta::CPAN
static jsdouble LocalTZA;
static jsdouble
DaylightSavingTA(jsdouble t)
{
int64 PR_t;
int64 ms2us;
int64 offset;
jsdouble result;
/* abort if NaN */
if (JSDOUBLE_IS_NaN(t))
return t;
/* put our t in an LL, and map it to usec for prtime */
LL_D2L(PR_t, t);
LL_I2L(ms2us, PR_USEC_PER_MSEC);
LL_MUL(PR_t, PR_t, ms2us);
offset = PR_DSTOffset(PR_t);
LL_DIV(offset, offset, ms2us);
JS/js/jsdate.c view on Meta::CPAN
result = yearday
+ monthday
+ date - 1;
return result;
}
#define MakeDate(day, time) (day * msPerDay + time)
#define TIMECLIP(d) ((JSDOUBLE_IS_FINITE(d) \
&& !((d < 0 ? -d : d) > HalfTimeDomain)) \
? js_DoubleToInteger(d + (+0.)) : *(cx->runtime->jsNaN))
/**
* end of ECMA 'support' functions
*/
/*
* Other Support routines and definitions
*/
static JSClass date_class = {
JS/js/jsdate.c view on Meta::CPAN
date_UTC(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
jsdouble array[MAXARGS];
uintN loop;
jsdouble d;
for (loop = 0; loop < MAXARGS; loop++) {
if (loop < argc) {
if (!js_ValueToNumber(cx, argv[loop], &d))
return JS_FALSE;
/* return NaN if any arg is NaN */
if (!JSDOUBLE_IS_FINITE(d)) {
return js_NewNumberValue(cx, d, rval);
}
array[loop] = floor(d);
} else {
array[loop] = 0;
}
}
/* adjust 2-digit years into the 20th century */
JS/js/jsdate.c view on Meta::CPAN
static JSBool
date_parse(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
JSString *str;
jsdouble result;
str = js_ValueToString(cx, argv[0]);
if (!str)
return JS_FALSE;
if (!date_parseString(str->chars, &result)) {
*rval = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
return JS_TRUE;
}
result = TIMECLIP(result);
return js_NewNumberValue(cx, result, rval);
}
/*
* Check that obj is an object of class Date, and get the date value.
* Return NULL on failure.
JS/js/jsdate.c view on Meta::CPAN
jsdouble time;
jsdouble result;
jsdouble *date = date_getProlog(cx, obj, argv);
if (!date)
return JS_FALSE;
result = *date;
/* just return NaN if the date is already NaN */
if (!JSDOUBLE_IS_FINITE(result))
return js_NewNumberValue(cx, result, rval);
/* Satisfy the ECMA rule that if a function is called with
* fewer arguments than the specified formal arguments, the
* remaining arguments are set to undefined. Seems like all
* the Date.setWhatever functions in ECMA are only varargs
* beyond the first argument; this should be set to undefined
* if it's not given. This means that "d = new Date();
* d.setMilliseconds()" returns NaN. Blech.
*/
if (argc == 0)
argc = 1; /* should be safe, because length of all settors is 1 */
else if (argc > maxargs)
argc = maxargs; /* clamp argc */
for (i = 0; i < argc; i++) {
if (!js_ValueToNumber(cx, argv[i], &args[i]))
return JS_FALSE;
if (!JSDOUBLE_IS_FINITE(args[i])) {
*date = *(cx->runtime->jsNaN);
return js_NewNumberValue(cx, *date, rval);
}
args[i] = js_DoubleToInteger(args[i]);
}
if (local)
lorutime = LocalTime(result);
else
lorutime = result;
JS/js/jsdate.c view on Meta::CPAN
/* see complaint about ECMA in date_MakeTime */
if (argc == 0)
argc = 1; /* should be safe, because length of all settors is 1 */
else if (argc > maxargs)
argc = maxargs; /* clamp argc */
for (i = 0; i < argc; i++) {
if (!js_ValueToNumber(cx, argv[i], &args[i]))
return JS_FALSE;
if (!JSDOUBLE_IS_FINITE(args[i])) {
*date = *(cx->runtime->jsNaN);
return js_NewNumberValue(cx, *date, rval);
}
args[i] = js_DoubleToInteger(args[i]);
}
/* return NaN if date is NaN and we're not setting the year,
* If we are, use 0 as the time. */
if (!(JSDOUBLE_IS_FINITE(result))) {
if (argc < 3)
return js_NewNumberValue(cx, result, rval);
else
lorutime = +0.;
} else {
if (local)
lorutime = LocalTime(result);
else
JS/js/jsdate.c view on Meta::CPAN
jsdouble *date = date_getProlog(cx, obj, argv);
if (!date)
return JS_FALSE;
result = *date;
if (!js_ValueToNumber(cx, argv[0], &year))
return JS_FALSE;
if (!JSDOUBLE_IS_FINITE(year)) {
*date = *(cx->runtime->jsNaN);
return js_NewNumberValue(cx, *date, rval);
}
year = js_DoubleToInteger(year);
if (!JSDOUBLE_IS_FINITE(result)) {
t = +0.0;
} else {
t = LocalTime(result);
}
JS/js/jsdate.c view on Meta::CPAN
day = MakeDay(year, MonthFromTime(t), DateFromTime(t));
result = MakeDate(day, TimeWithinDay(t));
result = UTC(result);
*date = TIMECLIP(result);
return js_NewNumberValue(cx, *date, rval);
}
/* constants for toString, toUTCString */
static char js_NaN_date_str[] = "Invalid Date";
static const char* days[] =
{
"Sun","Mon","Tue","Wed","Thu","Fri","Sat"
};
static const char* months[] =
{
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
static JSBool
date_toGMTString(JSContext *cx, JSObject *obj, uintN argc,
jsval *argv, jsval *rval)
{
char buf[100];
JSString *str;
jsdouble *date = date_getProlog(cx, obj, argv);
if (!date)
return JS_FALSE;
if (!JSDOUBLE_IS_FINITE(*date)) {
PR_snprintf(buf, sizeof buf, js_NaN_date_str);
} else {
jsdouble temp = *date;
/* Avoid dependence on PR_FormatTimeUSEnglish, because it
* requires a PRTime... which only has 16-bit years. Sub-ECMA.
*/
PR_snprintf(buf, sizeof buf, "%s, %.2d %s %.4d %.2d:%.2d:%.2d GMT",
days[WeekDay(temp)],
DateFromTime(temp),
months[MonthFromTime(temp)],
JS/js/jsdate.c view on Meta::CPAN
jsval *argv, jsval *rval)
{
char buf[100];
JSString *str;
PRTime split;
jsdouble *date = date_getProlog(cx, obj, argv);
if (!date)
return JS_FALSE;
if (!JSDOUBLE_IS_FINITE(*date)) {
PR_snprintf(buf, sizeof buf, js_NaN_date_str);
} else {
jsdouble local = LocalTime(*date);
new_explode(local, &split);
/* let PRTime format it. Use '%#c' for windows, because '%c' is
* backward-compatible and non-y2k with msvc; '%#c' requests that a
* full year be used in the result string.
*/
PR_FormatTime(buf, sizeof buf,
#ifdef _WIN32
JS/js/jsdate.c view on Meta::CPAN
/* helper function */
static JSBool
date_format(JSContext *cx, jsdouble date, jsval *rval)
{
char buf[100];
JSString *str;
char tzbuf[100];
PRTime split;
if (!JSDOUBLE_IS_FINITE(date)) {
PR_snprintf(buf, sizeof buf, js_NaN_date_str);
} else {
jsdouble local = LocalTime(date);
/* offset from GMT in minutes. The offset includes daylight savings,
if it applies. */
jsint minutes = (jsint) floor((LocalTZA + DaylightSavingTA(date))
/ msPerMinute);
/* map 510 minutes to 0830 hours */
intN offset = (minutes / 60) * 100 + minutes % 60;
JS/js/jsdate.c view on Meta::CPAN
/* the argument is a string; parse it. */
date = date_constructor(cx, obj);
if (!date)
return JS_FALSE;
str = js_ValueToString(cx, argv[0]);
if (!str)
return JS_FALSE;
if (!date_parseString(str->chars, date))
*date = *(cx->runtime->jsNaN);
*date = TIMECLIP(*date);
}
} else {
jsdouble array[MAXARGS];
uintN loop;
jsdouble d;
jsdouble day;
jsdouble time;
for (loop = 0; loop < MAXARGS; loop++) {
if (loop < argc) {
if (!js_ValueToNumber(cx, argv[loop], &d))
return JS_FALSE;
/* if any arg is NaN, make a NaN date object
and return */
if (!JSDOUBLE_IS_FINITE(d)) {
date = date_constructor(cx, obj);
if (!date)
return JS_FALSE;
*date = *(cx->runtime->jsNaN);
return JS_TRUE;
}
array[loop] = js_DoubleToInteger(d);
} else {
array[loop] = 0;
}
}
date = date_constructor(cx, obj);
if (!date)
JS/js/jsdate.c view on Meta::CPAN
JSObject *proto;
jsdouble *proto_date;
/* set static LocalTZA */
LocalTZA = -(PR_LocalGMTDifference() * msPerSecond);
proto = JS_InitClass(cx, obj, NULL, &date_class, Date, MAXARGS,
NULL, date_methods, NULL, date_static_methods);
if (!proto)
return NULL;
/* Set the value of the Date.prototype date to NaN */
proto_date = date_constructor(cx, proto);
if (!proto_date)
return NULL;
*proto_date = *(cx->runtime->jsNaN);
return proto;
}
JS_FRIEND_API(JSObject *)
js_NewDateObject(JSContext* cx, int year, int mon, int mday,
int hour, int min, int sec)
{
JSObject *obj;
jsdouble *date;
JS/js/jsdate.c view on Meta::CPAN
}
extern JS_FRIEND_API(void)
js_DateSetYear(JSContext *cx, JSObject *obj, int year)
{
jsdouble local;
jsdouble *date = date_getProlog(cx, obj, NULL);
if (!date)
return;
local = LocalTime(*date);
/* reset date if it was NaN */
if (JSDOUBLE_IS_NaN(local))
local = 0;
local = date_msecFromDate(year,
MonthFromTime(local),
DateFromTime(local),
HourFromTime(local),
MinFromTime(local),
SecFromTime(local),
msFromTime(local));
*date = UTC(local);
}
extern JS_FRIEND_API(void)
js_DateSetMonth(JSContext *cx, JSObject *obj, int month)
{
jsdouble local;
jsdouble *date = date_getProlog(cx, obj, NULL);
if (!date)
return;
local = LocalTime(*date);
/* bail if date was NaN */
if (JSDOUBLE_IS_NaN(local))
return;
local = date_msecFromDate(YearFromTime(local),
month,
DateFromTime(local),
HourFromTime(local),
MinFromTime(local),
SecFromTime(local),
msFromTime(local));
*date = UTC(local);
}
extern JS_FRIEND_API(void)
js_DateSetDate(JSContext *cx, JSObject *obj, int date)
{
jsdouble local;
jsdouble *datep = date_getProlog(cx, obj, NULL);
if (!datep)
return;
local = LocalTime(*datep);
if (JSDOUBLE_IS_NaN(local))
return;
local = date_msecFromDate(YearFromTime(local),
MonthFromTime(local),
date,
HourFromTime(local),
MinFromTime(local),
SecFromTime(local),
msFromTime(local));
*datep = UTC(local);
}
extern JS_FRIEND_API(void)
js_DateSetHours(JSContext *cx, JSObject *obj, int hours)
{
jsdouble local;
jsdouble *date = date_getProlog(cx, obj, NULL);
if (!date)
return;
local = LocalTime(*date);
if (JSDOUBLE_IS_NaN(local))
return;
local = date_msecFromDate(YearFromTime(local),
MonthFromTime(local),
DateFromTime(local),
hours,
MinFromTime(local),
SecFromTime(local),
msFromTime(local));
*date = UTC(local);
}
extern JS_FRIEND_API(void)
js_DateSetMinutes(JSContext *cx, JSObject *obj, int minutes)
{
jsdouble local;
jsdouble *date = date_getProlog(cx, obj, NULL);
if (!date)
return;
local = LocalTime(*date);
if (JSDOUBLE_IS_NaN(local))
return;
local = date_msecFromDate(YearFromTime(local),
MonthFromTime(local),
DateFromTime(local),
HourFromTime(local),
minutes,
SecFromTime(local),
msFromTime(local));
*date = UTC(local);
}
extern JS_FRIEND_API(void)
js_DateSetSeconds(JSContext *cx, JSObject *obj, int seconds)
{
jsdouble local;
jsdouble *date = date_getProlog(cx, obj, NULL);
if (!date)
return;
local = LocalTime(*date);
if (JSDOUBLE_IS_NaN(local))
return;
local = date_msecFromDate(YearFromTime(local),
MonthFromTime(local),
DateFromTime(local),
HourFromTime(local),
MinFromTime(local),
seconds,
msFromTime(local));
*date = UTC(local);
}
JS/js/jsinterp.c view on Meta::CPAN
case JSOP_BITXOR:
BITWISE_OP(^);
break;
case JSOP_BITAND:
BITWISE_OP(&);
break;
#ifdef XP_PC
#define COMPARE_DOUBLES(LVAL, OP, RVAL, IFNAN) \
((JSDOUBLE_IS_NaN(LVAL) || JSDOUBLE_IS_NaN(RVAL)) \
? (IFNAN) \
: (LVAL) OP (RVAL))
#else
#define COMPARE_DOUBLES(LVAL, OP, RVAL, IFNAN) ((LVAL) OP (RVAL))
#endif
#define RELATIONAL_OP(OP) { \
rval = POP(); \
lval = POP(); \
/* Optimize for two int-tagged operands (typical loop control). */ \
if ((lval & rval) & JSVAL_INT) { \
ltmp = lval ^ JSVAL_VOID; \
rtmp = rval ^ JSVAL_VOID; \
if (ltmp && rtmp) { \
cond = JSVAL_TO_INT(lval) OP JSVAL_TO_INT(rval); \
} else { \
d = ltmp ? JSVAL_TO_INT(lval) : *rt->jsNaN; \
d2 = rtmp ? JSVAL_TO_INT(rval) : *rt->jsNaN; \
cond = COMPARE_DOUBLES(d, OP, d2, JS_FALSE); \
} \
} else { \
VALUE_TO_PRIMITIVE(cx, lval, JSTYPE_NUMBER, &lval); \
/* Need lval for strcmp or ToNumber later, so root it via sp[0]. */ \
sp[0] = lval; \
VALUE_TO_PRIMITIVE(cx, rval, JSTYPE_NUMBER, &rval); \
if (JSVAL_IS_STRING(lval) && JSVAL_IS_STRING(rval)) { \
str = JSVAL_TO_STRING(lval); \
str2 = JSVAL_TO_STRING(rval); \
JS/js/jsinterp.c view on Meta::CPAN
if (ltmp == rtmp) { \
if (ltmp == JSVAL_STRING) { \
str = JSVAL_TO_STRING(lval); \
str2 = JSVAL_TO_STRING(rval); \
cond = js_CompareStrings(str, str2) OP 0; \
} else if (ltmp == JSVAL_DOUBLE) { \
d = *JSVAL_TO_DOUBLE(lval); \
d2 = *JSVAL_TO_DOUBLE(rval); \
cond = COMPARE_DOUBLES(d, OP, d2, IFNAN); \
} else { \
/* Handle all undefined (=>NaN) and int combinations. */ \
cond = lval OP rval; \
} \
} else { \
if (JSVAL_IS_NULL(lval) || JSVAL_IS_VOID(lval)) { \
cond = (JSVAL_IS_NULL(rval) || JSVAL_IS_VOID(rval)) OP 1; \
} else if (JSVAL_IS_NULL(rval) || JSVAL_IS_VOID(rval)) { \
cond = 1 OP 0; \
} else { \
if (ltmp == JSVAL_OBJECT) { \
VALUE_TO_PRIMITIVE(cx, lval, JSTYPE_VOID, &lval); \
JS/js/jsinterp.c view on Meta::CPAN
case JSOP_MUL:
BINARY_OP(*);
break;
case JSOP_DIV:
POP_NUMBER(cx, d2);
POP_NUMBER(cx, d);
if (d2 == 0) {
#ifdef XP_PC
/* XXX MSVC miscompiles such that (NaN == 0) */
if (JSDOUBLE_IS_NaN(d2))
rval = DOUBLE_TO_JSVAL(rt->jsNaN);
else
#endif
if (d == 0 || JSDOUBLE_IS_NaN(d))
rval = DOUBLE_TO_JSVAL(rt->jsNaN);
else if ((JSDOUBLE_HI32(d) ^ JSDOUBLE_HI32(d2)) >> 31)
rval = DOUBLE_TO_JSVAL(rt->jsNegativeInfinity);
else
rval = DOUBLE_TO_JSVAL(rt->jsPositiveInfinity);
PUSH_OPND(rval);
} else {
d /= d2;
PUSH_NUMBER(cx, d);
}
break;
case JSOP_MOD:
POP_NUMBER(cx, d2);
POP_NUMBER(cx, d);
if (d2 == 0) {
PUSH_OPND(DOUBLE_TO_JSVAL(rt->jsNaN));
} else {
#ifdef XP_PC
/* Workaround MS fmod bug where 42 % (1/0) => NaN, not 42. */
if (!(JSDOUBLE_IS_FINITE(d) && JSDOUBLE_IS_INFINITE(d2)))
#endif
d = fmod(d, d2);
PUSH_NUMBER(cx, d);
}
break;
case JSOP_NOT:
POP_BOOLEAN(cx, rval, cond);
PUSH_OPND(BOOLEAN_TO_JSVAL(!cond));
JS/js/jsnum.c view on Meta::CPAN
#ifdef IS_LITTLE_ENDIAN
uint32 lo, hi;
#else
uint32 hi, lo;
#endif
} s;
jsdouble d;
};
static JSBool
num_isNaN(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
jsdouble x;
if (!js_ValueToNumber(cx, argv[0], &x))
return JS_FALSE;
*rval = BOOLEAN_TO_JSVAL(JSDOUBLE_IS_NaN(x));
return JS_TRUE;
}
static JSBool
num_isFinite(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
jsdouble x;
if (!js_ValueToNumber(cx, argv[0], &x))
return JS_FALSE;
JS/js/jsnum.c view on Meta::CPAN
jsval *rval)
{
JSString *str;
jsdouble d, *dp;
jschar *ep;
str = js_ValueToString(cx, argv[0]);
if (!str)
return JS_FALSE;
if (!js_strtod(str->chars, &ep, &d) || ep == str->chars) {
*rval = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
} else {
dp = js_NewDouble(cx, d);
if (!dp)
return JS_FALSE;
*rval = DOUBLE_TO_JSVAL(dp);
}
return JS_TRUE;
}
static JSBool
JS/js/jsnum.c view on Meta::CPAN
str = js_ValueToString(cx, argv[0]);
if (!str)
return JS_FALSE;
if (argc > 1) {
if (!js_ValueToECMAInt32(cx, argv[1], &base))
return JS_FALSE;
} else {
base = 0;
}
if (!js_strtol(str->chars, &ep, base, &d)) {
*rval = DOUBLE_TO_JSVAL(cx->runtime->jsNaN);
} else {
if (!js_NewNumberValue(cx, d, rval))
return JS_FALSE;
}
return JS_TRUE;
}
static JSFunctionSpec number_functions[] = {
{"isNaN", num_isNaN, 1},
{"isFinite", num_isFinite, 1},
{"parseFloat", num_parseFloat, 1},
{"parseInt", num_parseInt, 2},
{0}
};
static JSClass number_class = {
"Number",
JSCLASS_HAS_PRIVATE,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS/js/jsnum.c view on Meta::CPAN
#if JS_HAS_TOSOURCE
{js_toSource_str, num_toSource, 0},
#endif
{js_toString_str, num_toString, 0},
{js_valueOf_str, num_valueOf, 0},
{0}
};
/* NB: Keep this in synch with number_constants[]. */
enum nc_slot {
NC_NaN,
NC_POSITIVE_INFINITY,
NC_NEGATIVE_INFINITY,
NC_MAX_VALUE,
NC_MIN_VALUE,
NC_LIMIT
};
/*
* 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
* using union dpun.
*/
static JSConstDoubleSpec number_constants[] = {
{0, "NaN"},
{0, "POSITIVE_INFINITY"},
{0, "NEGATIVE_INFINITY"},
{1.7976931348623157E+308, "MAX_VALUE"},
{0, "MIN_VALUE"},
{0}
};
static jsdouble NaN;
JSObject *
js_InitNumberClass(JSContext *cx, JSObject *obj)
{
JSRuntime *rt;
union dpun u;
JSObject *proto, *ctor;
rt = cx->runtime;
if (!rt->jsNaN) {
#ifdef XP_PC
#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);
#else
_control87(MCW_EM, MCW_EM);
#endif
#endif
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;
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;
}
JS/js/jsnum.c view on Meta::CPAN
proto = JS_InitClass(cx, obj, NULL, &number_class, Number, 1,
NULL, number_methods, NULL, NULL);
if (!proto || !(ctor = JS_GetConstructor(cx, proto)))
return NULL;
OBJ_SET_SLOT(cx, proto, JSSLOT_PRIVATE, JSVAL_ZERO);
if (!JS_DefineConstDoubles(cx, ctor, number_constants))
return NULL;
/* ECMA 15.1.1.1 */
if (!JS_DefineProperty(cx, obj, "NaN", DOUBLE_TO_JSVAL(rt->jsNaN),
NULL, NULL, 0)) {
return NULL;
}
/* ECMA 15.1.1.2 */
if (!JS_DefineProperty(cx, obj, "Infinity",
DOUBLE_TO_JSVAL(rt->jsPositiveInfinity),
NULL, NULL, 0)) {
return NULL;
}
JS/js/jsnum.c view on Meta::CPAN
dp = js_AllocGCThing(cx, GCX_DOUBLE);
if (!dp)
return NULL;
*dp = d;
return dp;
}
void
js_FinalizeDouble(JSContext *cx, jsdouble *dp)
{
*dp = NaN;
}
JSBool
js_NewDoubleValue(JSContext *cx, jsdouble d, jsval *rval)
{
jsdouble *dp;
dp = js_NewDouble(cx, d);
if (!dp)
return JS_FALSE;
JS/js/jsnum.c view on Meta::CPAN
#if JS_BUG_FALLIBLE_TONUM
str = js_DecompileValueGenerator(cx, v, NULL);
badstr:
if (str) {
JS_ReportError(cx, "%s is not a number",
JS_GetStringBytes(str));
}
return JS_FALSE;
#else
badstr:
*dp = *cx->runtime->jsNaN;
#endif
}
return JS_TRUE;
}
JSBool
js_ValueToECMAInt32(JSContext *cx, jsval v, int32 *ip)
{
jsdouble d;
JS/js/jsnum.c view on Meta::CPAN
}
JSBool
js_ValueToInt32(JSContext *cx, jsval v, int32 *ip)
{
jsdouble d;
JSString *str;
if (!js_ValueToNumber(cx, v, &d))
return JS_FALSE;
if (JSDOUBLE_IS_NaN(d) || d <= -2147483649.0 || 2147483648.0 <= d) {
str = js_DecompileValueGenerator(cx, v, NULL);
if (str) {
JS_ReportError(cx, "can't convert %s to an integer",
JS_GetStringBytes(str));
}
return JS_FALSE;
}
*ip = (int32)floor(d + 0.5); /* Round to nearest */
return JS_TRUE;
}
JS/js/jsnum.c view on Meta::CPAN
}
jsdouble
js_DoubleToInteger(jsdouble d)
{
JSBool neg;
if (d == 0)
return d;
if (!JSDOUBLE_IS_FINITE(d)) {
if (JSDOUBLE_IS_NaN(d))
return 0;
return d;
}
neg = (d < 0);
d = floor(neg ? -d : d);
return neg ? -d : d;
}
/* XXXbe rewrite me! */
JSBool
JS/js/jsnum.h view on Meta::CPAN
#define JSDOUBLE_HI32(x) (((uint32 *)&(x))[1])
#define JSDOUBLE_LO32(x) (((uint32 *)&(x))[0])
#else
#define JSDOUBLE_HI32(x) (((uint32 *)&(x))[0])
#define JSDOUBLE_LO32(x) (((uint32 *)&(x))[1])
#endif
#define JSDOUBLE_HI32_SIGNBIT 0x80000000
#define JSDOUBLE_HI32_EXPMASK 0x7ff00000
#define JSDOUBLE_HI32_MANTMASK 0x000fffff
#define JSDOUBLE_IS_NaN(x) \
((JSDOUBLE_HI32(x) & JSDOUBLE_HI32_EXPMASK) == JSDOUBLE_HI32_EXPMASK && \
(JSDOUBLE_LO32(x) || (JSDOUBLE_HI32(x) & JSDOUBLE_HI32_MANTMASK)))
#define JSDOUBLE_IS_INFINITE(x) \
((JSDOUBLE_HI32(x) & ~JSDOUBLE_HI32_SIGNBIT) == JSDOUBLE_HI32_EXPMASK && \
!JSDOUBLE_LO32(x))
#define JSDOUBLE_IS_FINITE(x) \
((JSDOUBLE_HI32(x) & JSDOUBLE_HI32_EXPMASK) != JSDOUBLE_HI32_EXPMASK)
#define JSDOUBLE_IS_NEGZERO(d) (JSDOUBLE_HI32(d) == JSDOUBLE_HI32_SIGNBIT && \
JSDOUBLE_LO32(d) == 0)
#define JSDOUBLE_IS_INT_2(d, i) (!JSDOUBLE_IS_NEGZERO(d) && (jsdouble)i == d)
#ifdef XP_PC
/* XXX MSVC miscompiles NaN floating point comparisons for ==, !=, <, and <= */
#define JSDOUBLE_IS_INT(d, i) (!JSDOUBLE_IS_NaN(d) && JSDOUBLE_IS_INT_2(d, i))
#else
#define JSDOUBLE_IS_INT(d, i) JSDOUBLE_IS_INT_2(d, i)
#endif
/* Initialize the Number class, returning its prototype object. */
extern JSObject *
js_InitNumberClass(JSContext *cx, JSObject *obj);
/* GC-allocate a new JS number. */
extern jsdouble *
JS/js/jsnum.h view on Meta::CPAN
/*
* Convert a value to a number, then to a uint16 according to the ECMA rules
* for ToUint16.
*/
extern JSBool
js_ValueToUint16(JSContext *cx, jsval v, uint16 *ip);
/*
* Convert a jsdouble to an integral number, stored in a jsdouble.
* If d is NaN, return 0. If d is an infinity, return it without conversion.
*/
extern jsdouble
js_DoubleToInteger(jsdouble d);
extern JSBool
js_strtod(const jschar *s, jschar **ep, jsdouble *dp);
extern JSBool
js_strtol(const jschar *s, jschar **ep, jsint radix, jsdouble *dp);
JS/js/jsparse.c view on Meta::CPAN
d -= d2;
break;
case JSOP_MUL:
d *= d2;
break;
case JSOP_DIV:
if (d2 == 0) {
#ifdef XP_PC
/* XXX MSVC miscompiles such that (NaN == 0) */
if (JSDOUBLE_IS_NaN(d2))
d = *cx->runtime->jsNaN;
else
#endif
if (d == 0 || JSDOUBLE_IS_NaN(d))
d = *cx->runtime->jsNaN;
else if ((JSDOUBLE_HI32(d) ^ JSDOUBLE_HI32(d2)) >> 31)
d = *cx->runtime->jsNegativeInfinity;
else
d = *cx->runtime->jsPositiveInfinity;
} else {
d /= d2;
}
break;
case JSOP_MOD:
if (d2 == 0) {
d = *cx->runtime->jsNaN;
} else {
#ifdef XP_PC
/* Workaround MS fmod bug where 42 % (1/0) => NaN, not 42. */
if (!(JSDOUBLE_IS_FINITE(d) && JSDOUBLE_IS_INFINITE(d2)))
#endif
d = fmod(d, d2);
}
break;
default:;
}
pn->pn_type = TOK_NUMBER;
pn->pn_op = JSOP_NUMBER;
JS/js/jsstr.c view on Meta::CPAN
str = js_ValueToString(cx, OBJECT_TO_JSVAL(obj));
if (!str)
return JS_FALSE;
argv[-1] = STRING_TO_JSVAL(str);
if (!js_ValueToNumber(cx, argv[0], &d))
return JS_FALSE;
d = js_DoubleToInteger(d);
if (d < 0 || str->length <= d) {
*rval = JS_GetNaNValue(cx);
} else {
index = (size_t)d;
*rval = INT_TO_JSVAL((jsint)str->chars[index]);
}
return JS_TRUE;
}
jsint
js_BoyerMooreHorspool(const jschar *text, jsint textlen,
const jschar *pat, jsint patlen,
JS/js/jsstr.c view on Meta::CPAN
str2 = js_ValueToString(cx, argv[0]);
if (!str2)
return JS_FALSE;
argv[0] = STRING_TO_JSVAL(str2);
pat = str2->chars;
patlen = (jsint)str2->length;
if (argc > 1) {
if (!js_ValueToNumber(cx, argv[1], &d))
return JS_FALSE;
if (JSDOUBLE_IS_NaN(d)) {
i = textlen;
} else {
d = js_DoubleToInteger(d);
if (d < 0)
i = 0;
else if (d > textlen - patlen)
i = textlen - patlen;
else
i = (jsint)d;
}
JS/js/prdtoa.c view on Meta::CPAN
* calculation.
*/
static PRBool
PR_dtoa(double d, int mode, int ndigits,
int *decpt, int *sign, char **rve, char *buf, size_t bufsize)
{
/* Arguments ndigits, decpt, sign are similar to those
of ecvt and fcvt; trailing zeros are suppressed from
the returned string. If not null, *rve is set to point
to the end of the return value. If d is +-Infinity or NaN,
then *decpt is set to 9999.
mode:
0 ==> shortest string that yields d when read in
and rounded to nearest.
1 ==> like 0, but with Steele & White stopping rule;
e.g. with IEEE P754 arithmetic , mode 0 gives
1e23 whereas mode 1 gives 9.999999999999999e22.
2 ==> max(1,ndigits) significant digits. This gives a
return value similar to that of ecvt, except
JS/js/prdtoa.c view on Meta::CPAN
Bigint *result = 0;
static int32 result_k;
PRBool retval;
size_t strsize;
#ifdef JS_THREADSAFE
if (!initialized) InitDtoa();
#endif
if (word0(d) & Sign_bit) {
/* set sign for everything, including 0's and NaNs */
*sign = 1;
word0(d) &= ~Sign_bit; /* clear sign bit */
}
else
*sign = 0;
#if defined(IEEE_Arith) + defined(VAX)
#ifdef IEEE_Arith
if ((word0(d) & Exp_mask) == Exp_mask)
#else
if (word0(d) == 0x8000)
#endif
{
/* Infinity or NaN */
*decpt = 9999;
s =
#ifdef IEEE_Arith
!word1(d) && !(word0(d) & 0xfffff) ? "Infinity" :
#endif
"NaN";
if ((s[0] == 'I' && bufsize < 9) || (s[0] == 'N' && bufsize < 4)) {
PR_ASSERT(PR_FALSE);
/* PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0); */
return PR_FALSE;
}
strcpy(buf, s);
if (rve) {
*rve =
#ifdef IEEE_Arith
buf[3] ? buf + 8 :
JS/js/prdtoa.c view on Meta::CPAN
}
/* XXX Why use mode 1? */
if (PR_dtoa(fval,1,prcsn,&decpt,&sign,&endnum,num,bufsz)
== PR_FALSE) {
buf[0] = '\0';
goto done;
}
numdigits = endnum - num;
nump = num;
/* If negative and not signed zero and not a NaN, print leading "-". */
if (sign &&
!(word0(fval) == Sign_bit && word1(fval) == 0) &&
!((word0(fval) & Exp_mask) == Exp_mask &&
(word1(fval) || (word0(fval) & 0xfffff)))) {
*bufp++ = '-';
}
if(decpt == 9999){
while((*bufp++ = *nump++) != 0) ;
goto done;