diff --git a/mozilla/js/js2/icodegenerator.cpp b/mozilla/js/js2/icodegenerator.cpp index 3180a263270..46835ac5392 100644 --- a/mozilla/js/js2/icodegenerator.cpp +++ b/mozilla/js/js2/icodegenerator.cpp @@ -861,7 +861,7 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I { ASSERT(b->getKind() == ExprNode::dot); - LValueKind lValueKind; + LValueKind lValueKind = Property; if (b->op2->getKind() != ExprNode::identifier) { NOT_REACHED("Implement me"); // turns into a getProperty (but not via any overloaded [] ) @@ -876,7 +876,6 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I const StringAtom &baseName = (static_cast(b->op1))->name; resolveIdentifier(baseName, base, slotIndex); - lValueKind = Property; // // handle . // diff --git a/mozilla/js/js2/interpreter.cpp b/mozilla/js/js2/interpreter.cpp index 9a648aacbba..5c3ba00af13 100644 --- a/mozilla/js/js2/interpreter.cpp +++ b/mozilla/js/js2/interpreter.cpp @@ -34,6 +34,7 @@ #include "interpreter.h" #include "jsclasses.h" #include "world.h" +#include "jsmath.h" #include @@ -58,6 +59,7 @@ namespace Interpreter { using namespace ICG; using namespace JSTypes; using namespace JSClasses; +using namespace JSMathClass; // These classes are private to the JS interpreter. @@ -495,6 +497,22 @@ void Context::initContext() for (int i = 0; i < sizeof(PDTs) / sizeof(struct PDT); i++) mGlobal->defineVariable(widenCString(PDTs[i].name), &Type_Type, JSValue(PDTs[i].type)); + // set up the correct [[Class]] for the global object (matching SpiderMonkey) + mGlobal->setClass(new JSString("global")); + + // add (XXX some) of the global object properties + mGlobal->setProperty(widenCString("NaN"), kNaNValue); + mGlobal->setProperty(widenCString("undefined"), kUndefinedValue); + + // 'Object', 'Date', 'RegExp', 'Array' etc are all (constructor) properties of the global object + + mGlobal->setProperty(widenCString("Math"), JSValue(new JSMath())); + + + // This initializes the state of the binary operator overload mechanism. + // One could argue that it is unneccessary to do this until the 'Operators' + // package is loaded and that all (un-typed) binary operators should use a + // form of icode that performed the inline operation instead. JSBinaryOperator::JSBinaryCode defaultFunction[] = { add_Default, subtract_Default, @@ -548,8 +566,12 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args) JSValue rv; + // when invoked with empty args, make sure that 'this' is + // going to be the global object. + mActivation = new Activation(iCode, args); JSValues* registers = &mActivation->mRegisters; + if (args.size() == 0) (*registers)[0] = mGlobal; mPC = mActivation->mICode->its_iCode->begin(); InstructionIterator endPC = mActivation->mICode->its_iCode->end(); @@ -689,6 +711,7 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args) case NEW_OBJECT: { NewObject* no = static_cast(instruction); + JSObject *obj = new JSObject(); (*registers)[dst(no).first] = new JSObject(); } break; diff --git a/mozilla/js/js2/js2.cpp b/mozilla/js/js2/js2.cpp index dd4e49a006f..7162d3bcd27 100644 --- a/mozilla/js/js2/js2.cpp +++ b/mozilla/js/js2/js2.cpp @@ -89,7 +89,6 @@ static bool promptLine(LineReader &inReader, string &s, const char *prompt) } World world; -JSScope global; /* "filename" of the console */ const String ConsoleName = widenCString(""); @@ -184,6 +183,7 @@ static JSValue time(Context *cx, const JSValues &argv) static void readEvalPrint(FILE *in, World &world) { + JSScope global; Context cx(world, &global); #ifdef DEBUGGER_FOO jsd.attachToContext (&cx); diff --git a/mozilla/js/js2/jsmath.cpp b/mozilla/js/js2/jsmath.cpp new file mode 100644 index 00000000000..ec9c5ec9b95 --- /dev/null +++ b/mozilla/js/js2/jsmath.cpp @@ -0,0 +1,203 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the JavaScript 2 Prototype. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * 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 + * provisions of the GPL are applicable instead of those above. + * If you wish to allow use of your version of this file only + * under the terms of the GPL and not to allow others to use your + * version of this file under the NPL, indicate your decision by + * deleting the provisions above and replace them with the notice + * and other provisions required by the GPL. If you do not delete + * the provisions above, a recipient may use your version of this + * file under either the NPL or the GPL. + */ + +#include +#include "jsmath.h" + +namespace JavaScript { +namespace JSMathClass { + +using namespace JSTypes; + +#ifndef M_E +#define M_E 2.7182818284590452354 +#endif +#ifndef M_LOG2E +#define M_LOG2E 1.4426950408889634074 +#endif +#ifndef M_LOG10E +#define M_LOG10E 0.43429448190325182765 +#endif +#ifndef M_LN2 +#define M_LN2 0.69314718055994530942 +#endif +#ifndef M_LN10 +#define M_LN10 2.30258509299404568402 +#endif +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_SQRT2 +#define M_SQRT2 1.41421356237309504880 +#endif +#ifndef M_SQRT1_2 +#define M_SQRT1_2 0.70710678118654752440 +#endif + + +/* + Concept copied from SpiderMonkey - + fd_XXX needs to be defined either as a call to the fdlibm routine + or the native C library routine depending on the platform +*/ + +#define JS_USE_FDLIBM_MATH 0 + + +#if !JS_USE_FDLIBM_MATH +/* + * Use system provided math routines. + */ + + +#define fd_acos acos +#define fd_asin asin +#define fd_atan atan +#define fd_atan2 atan2 +#define fd_ceil ceil +#define fd_copysign copysign +#define fd_cos cos +#define fd_exp exp +#define fd_fabs fabs +#define fd_floor floor +#define fd_fmod fmod +#define fd_log log +#define fd_pow pow +#define fd_sin sin +#define fd_sqrt sqrt +#define fd_tan tan + +#endif + +JSValue math_abs(Context *cx, const JSValues& argv) +{ + if (argv.size() > 0) { + JSValue num = argv[1].toNumber(); + if (num.isNaN()) return num; + if (num.isNegativeZero()) return kPositiveZero; + if (num.isNegativeInfinity()) return kPositiveInfinity; + if (num.f64 < 0) return JSValue(-num.f64); + return num; + } + return kUndefinedValue; +} + +JSValue math_acos(Context *cx, const JSValues& argv) +{ + if (argv.size() > 0) { + JSValue num = argv[1].toNumber(); + return JSValue(fd_acos(num.f64)); + } + return kUndefinedValue; +} + +JSValue math_asin(Context *cx, const JSValues& argv) +{ + if (argv.size() > 0) { + JSValue num = argv[1].toNumber(); + return JSValue(fd_asin(num.f64)); + } + return kUndefinedValue; +} + +JSValue math_atan(Context *cx, const JSValues& argv) +{ + if (argv.size() > 0) { + JSValue num = argv[1].toNumber(); + return JSValue(fd_atan(num.f64)); + } + return kUndefinedValue; +} + +JSValue math_atan2(Context *cx, const JSValues& argv) +{ + if (argv.size() > 1) { + JSValue num1 = argv[1].toNumber(); + JSValue num2 = argv[1].toNumber(); + return JSValue(fd_atan2(num1.f64, num2.f64)); + } + return kUndefinedValue; +} + +JSValue math_ceil(Context *cx, const JSValues& argv) +{ + if (argv.size() > 0) { + JSValue num = argv[1].toNumber(); + return JSValue(fd_ceil(num.f64)); + } + return kUndefinedValue; +} + +struct MathFunctionEntry { + char *name; + JSNativeFunction::JSCode fn; +} MathFunctions[] = { + { "abs", math_abs }, + { "acos", math_acos }, + { "asin", math_asin }, + { "atan", math_atan }, + { "atan2", math_atan2 }, + { "ceil", math_acos }, + { "acos", math_acos }, + { "acos", math_acos } +}; + +struct MathConstantEntry { + char *name; + double value; +} MathConstants[] = { + { "E", M_E }, + { "LOG2E", M_LOG2E }, + { "LOG10E", M_LOG10E }, + { "LN2", M_LN2 }, + { "LN10", M_LN10 }, + { "PI", M_PI }, + { "SQRT2", M_SQRT2 }, + { "SQRT1_2", M_SQRT1_2 } +}; + +JSMath::JSMath() +{ + setClass(new JSString("Math")); + + for (int i = 0; i < sizeof(MathFunctions) / sizeof(MathFunctionEntry); i++) + setProperty(widenCString(MathFunctions[i].name), JSValue(new JSNativeFunction(MathFunctions[i].fn) ) ); + + for (i = 0; i < sizeof(MathConstants) / sizeof(MathConstantEntry); i++) + setProperty(widenCString(MathConstants[i].name), JSValue(MathConstants[i].value) ); + +} + + +} /* JSMathClass */ +} /* JavaScript */ \ No newline at end of file diff --git a/mozilla/js/js2/jsmath.h b/mozilla/js/js2/jsmath.h new file mode 100644 index 00000000000..605227ebe59 --- /dev/null +++ b/mozilla/js/js2/jsmath.h @@ -0,0 +1,56 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the JavaScript 2 Prototype. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * 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 + * provisions of the GPL are applicable instead of those above. + * If you wish to allow use of your version of this file only + * under the terms of the GPL and not to allow others to use your + * version of this file under the NPL, indicate your decision by + * deleting the provisions above and replace them with the notice + * and other provisions required by the GPL. If you do not delete + * the provisions above, a recipient may use your version of this + * file under either the NPL or the GPL. + */ + +#ifndef jsmath_h +#define jsmath_h + +#include "jstypes.h" + +namespace JavaScript { +namespace JSMathClass { + + using JSTypes::JSObject; + using JSTypes::JSString; + + class JSMath : public JSObject { + public: + JSMath(); + + }; + + +} /* JSMathClass */ +} /* JavaScript */ + + +#endif jsmath_h \ No newline at end of file diff --git a/mozilla/js/js2/jstypes.cpp b/mozilla/js/js2/jstypes.cpp index 3800d910ee3..1cf1f5335b7 100644 --- a/mozilla/js/js2/jstypes.cpp +++ b/mozilla/js/js2/jstypes.cpp @@ -41,14 +41,33 @@ namespace JSTypes { using namespace JSClasses; -// using JavaScript::StringAtom; -// the canonical undefined value, etc. -const JSValue kUndefinedValue; -const JSValue kNaNValue = JSValue(nan); -const JSValue kTrueValue = JSValue(true); -const JSValue kFalseValue = JSValue(false); -const JSValue kNullValue = JSValue((JSObject*)NULL); +JSValue object_toString(Context *cx, const JSValues& argv) +{ + if (argv.size() > 0) { + JSString *s = new JSString("[object "); + JSValue theThis = argv[0]; + ASSERT(theThis.isObject()); + s->append(theThis.object->getClass()); + s->append("]"); + return JSValue(s); + } + return kUndefinedValue; +} + + +JSObject *JSObject::objectPrototypeObject = JSObject::initJSObject(); +JSString *JSObject::ObjectString = new JSString("Object"); + +JSObject *JSObject::initJSObject() +{ + JSObject *result = new JSObject(); + result->setProperty(widenCString("toString"), JSValue(new JSNativeFunction(object_toString) ) ); + return result; +} + + + JSType Any_Type = JSType(widenCString("any"), NULL); JSType Integer_Type = JSType(widenCString("Integer"), &Any_Type); @@ -91,6 +110,18 @@ JSType None_Type = JSType(widenCString("none"), &Any_Type); JSDOUBLE_LO32(d) == 0) +// the canonical undefined value, etc. +const JSValue kUndefinedValue; +const JSValue kNaNValue = JSValue(nan); +const JSValue kTrueValue = JSValue(true); +const JSValue kFalseValue = JSValue(false); +const JSValue kNullValue = JSValue((JSObject*)NULL); +const JSValue kNegativeZero = JSValue(-0.0); +const JSValue kPositiveZero = JSValue(0.0); +const JSValue kNegativeInfinity = JSValue(negativeInfinity); +const JSValue kPositiveInfinity = JSValue(positiveInfinity); + + const JSType *JSValue::getType() const { switch (tag) { @@ -147,6 +178,71 @@ bool JSValue::isNaN() const } } +bool JSValue::isNegativeInfinity() const +{ + ASSERT(isNumber()); + switch (tag) { + case i32_tag: + case u32_tag: + return false; + case integer_tag: + case f64_tag: + return (f64 < 0) && JSDOUBLE_IS_INFINITE(f64); + default: + NOT_REACHED("Broken compiler?"); + return true; + } +} + +bool JSValue::isPositiveInfinity() const +{ + ASSERT(isNumber()); + switch (tag) { + case i32_tag: + case u32_tag: + return false; + case integer_tag: + case f64_tag: + return (f64 > 0) && JSDOUBLE_IS_INFINITE(f64); + default: + NOT_REACHED("Broken compiler?"); + return true; + } +} + +bool JSValue::isNegativeZero() const +{ + ASSERT(isNumber()); + switch (tag) { + case i32_tag: + case u32_tag: + return false; + case integer_tag: + case f64_tag: + return JSDOUBLE_IS_NEGZERO(f64); + default: + NOT_REACHED("Broken compiler?"); + return true; + } +} + +bool JSValue::isPositiveZero() const +{ + ASSERT(isNumber()); + switch (tag) { + case i32_tag: + return (i32 == 0); + case u32_tag: + return (u32 == 0); + case integer_tag: + case f64_tag: + return (f64 == 0.0) && !JSDOUBLE_IS_NEGZERO(f64); + default: + NOT_REACHED("Broken compiler?"); + return true; + } +} + int JSValue::operator==(const JSValue& value) const { if (this->tag == value.tag) { @@ -522,6 +618,21 @@ JSString::JSString(const char* str) std::transform(str, str + n, begin(), JavaScript::widen); } +void JSString::append(const char* str) +{ + size_t n = ::strlen(str); + size_t oldSize = size(); + resize(oldSize + n); + std::transform(str, str + n, begin() + oldSize, JavaScript::widen); +} + +void JSString::append(const JSStringBase* str) +{ + size_t n = str->size(); + size_t oldSize = size(); + resize(oldSize + n); + traits_type::copy(begin() + oldSize, str->begin(), n); +} JSString::operator String() { diff --git a/mozilla/js/js2/jstypes.h b/mozilla/js/js2/jstypes.h index 2503218d0a9..01d8f68b177 100644 --- a/mozilla/js/js2/jstypes.h +++ b/mozilla/js/js2/jstypes.h @@ -138,6 +138,10 @@ namespace JSTypes { bool isUndefined() const { return (tag == undefined_tag); } bool isNull() const { return ((tag == object_tag) && (this->object == NULL)); } bool isNaN() const; + bool isNegativeInfinity() const; + bool isPositiveInfinity() const; + bool isNegativeZero() const; + bool isPositiveZero() const; bool isType() const { return (tag == type_tag); } JSValue toString() const { return (isString() ? *this : valueToString(*this)); } @@ -189,6 +193,10 @@ namespace JSTypes { extern const JSValue kTrueValue; extern const JSValue kFalseValue; extern const JSValue kNullValue; + extern const JSValue kNegativeZero; + extern const JSValue kPositiveZero; + extern const JSValue kNegativeInfinity; + extern const JSValue kPositiveInfinity; extern JSType Any_Type; extern JSType Integer_Type; @@ -214,9 +222,15 @@ namespace JSTypes { JSProperties mProperties; JSObject* mPrototype; JSType* mType; + JSString* mClass; // this is the internal [[Class]] property + public: - JSObject() : mPrototype(0), mType(&Any_Type) {} + JSObject() : mPrototype(objectPrototypeObject), mType(&Any_Type), mClass(ObjectString) {} + static JSObject *objectPrototypeObject; + static JSObject *initJSObject(); + static JSString *ObjectString; + bool hasProperty(const String& name) { return (mProperties.count(name) != 0); @@ -278,6 +292,16 @@ namespace JSTypes { return mType; } + JSString* getClass() + { + return mClass; + } + + void setClass(JSString* s) + { + mClass = s; + } + virtual void printProperties(Formatter& f); }; @@ -394,6 +418,9 @@ namespace JSTypes { explicit JSString(const char* str); operator String(); + + void append(const char* str); + void append(const JSStringBase* str); }; class JSException : public gc_base { diff --git a/mozilla/js/js2/winbuild/js2.dsp b/mozilla/js/js2/winbuild/js2.dsp index da1371d3f10..31b00713674 100644 --- a/mozilla/js/js2/winbuild/js2.dsp +++ b/mozilla/js/js2/winbuild/js2.dsp @@ -135,6 +135,10 @@ SOURCE=..\js2.cpp # End Source File # Begin Source File +SOURCE=..\jsmath.cpp +# End Source File +# Begin Source File + SOURCE=..\jstypes.cpp # End Source File # Begin Source File diff --git a/mozilla/js2/src/icodegenerator.cpp b/mozilla/js2/src/icodegenerator.cpp index 3180a263270..46835ac5392 100644 --- a/mozilla/js2/src/icodegenerator.cpp +++ b/mozilla/js2/src/icodegenerator.cpp @@ -861,7 +861,7 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I { ASSERT(b->getKind() == ExprNode::dot); - LValueKind lValueKind; + LValueKind lValueKind = Property; if (b->op2->getKind() != ExprNode::identifier) { NOT_REACHED("Implement me"); // turns into a getProperty (but not via any overloaded [] ) @@ -876,7 +876,6 @@ TypedRegister ICodeGenerator::handleDot(BinaryExprNode *b, ExprNode::Kind use, I const StringAtom &baseName = (static_cast(b->op1))->name; resolveIdentifier(baseName, base, slotIndex); - lValueKind = Property; // // handle . // diff --git a/mozilla/js2/src/interpreter.cpp b/mozilla/js2/src/interpreter.cpp index 9a648aacbba..5c3ba00af13 100644 --- a/mozilla/js2/src/interpreter.cpp +++ b/mozilla/js2/src/interpreter.cpp @@ -34,6 +34,7 @@ #include "interpreter.h" #include "jsclasses.h" #include "world.h" +#include "jsmath.h" #include @@ -58,6 +59,7 @@ namespace Interpreter { using namespace ICG; using namespace JSTypes; using namespace JSClasses; +using namespace JSMathClass; // These classes are private to the JS interpreter. @@ -495,6 +497,22 @@ void Context::initContext() for (int i = 0; i < sizeof(PDTs) / sizeof(struct PDT); i++) mGlobal->defineVariable(widenCString(PDTs[i].name), &Type_Type, JSValue(PDTs[i].type)); + // set up the correct [[Class]] for the global object (matching SpiderMonkey) + mGlobal->setClass(new JSString("global")); + + // add (XXX some) of the global object properties + mGlobal->setProperty(widenCString("NaN"), kNaNValue); + mGlobal->setProperty(widenCString("undefined"), kUndefinedValue); + + // 'Object', 'Date', 'RegExp', 'Array' etc are all (constructor) properties of the global object + + mGlobal->setProperty(widenCString("Math"), JSValue(new JSMath())); + + + // This initializes the state of the binary operator overload mechanism. + // One could argue that it is unneccessary to do this until the 'Operators' + // package is loaded and that all (un-typed) binary operators should use a + // form of icode that performed the inline operation instead. JSBinaryOperator::JSBinaryCode defaultFunction[] = { add_Default, subtract_Default, @@ -548,8 +566,12 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args) JSValue rv; + // when invoked with empty args, make sure that 'this' is + // going to be the global object. + mActivation = new Activation(iCode, args); JSValues* registers = &mActivation->mRegisters; + if (args.size() == 0) (*registers)[0] = mGlobal; mPC = mActivation->mICode->its_iCode->begin(); InstructionIterator endPC = mActivation->mICode->its_iCode->end(); @@ -689,6 +711,7 @@ JSValue Context::interpret(ICodeModule* iCode, const JSValues& args) case NEW_OBJECT: { NewObject* no = static_cast(instruction); + JSObject *obj = new JSObject(); (*registers)[dst(no).first] = new JSObject(); } break; diff --git a/mozilla/js2/src/jsmath.cpp b/mozilla/js2/src/jsmath.cpp new file mode 100644 index 00000000000..ec9c5ec9b95 --- /dev/null +++ b/mozilla/js2/src/jsmath.cpp @@ -0,0 +1,203 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the JavaScript 2 Prototype. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * 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 + * provisions of the GPL are applicable instead of those above. + * If you wish to allow use of your version of this file only + * under the terms of the GPL and not to allow others to use your + * version of this file under the NPL, indicate your decision by + * deleting the provisions above and replace them with the notice + * and other provisions required by the GPL. If you do not delete + * the provisions above, a recipient may use your version of this + * file under either the NPL or the GPL. + */ + +#include +#include "jsmath.h" + +namespace JavaScript { +namespace JSMathClass { + +using namespace JSTypes; + +#ifndef M_E +#define M_E 2.7182818284590452354 +#endif +#ifndef M_LOG2E +#define M_LOG2E 1.4426950408889634074 +#endif +#ifndef M_LOG10E +#define M_LOG10E 0.43429448190325182765 +#endif +#ifndef M_LN2 +#define M_LN2 0.69314718055994530942 +#endif +#ifndef M_LN10 +#define M_LN10 2.30258509299404568402 +#endif +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#ifndef M_SQRT2 +#define M_SQRT2 1.41421356237309504880 +#endif +#ifndef M_SQRT1_2 +#define M_SQRT1_2 0.70710678118654752440 +#endif + + +/* + Concept copied from SpiderMonkey - + fd_XXX needs to be defined either as a call to the fdlibm routine + or the native C library routine depending on the platform +*/ + +#define JS_USE_FDLIBM_MATH 0 + + +#if !JS_USE_FDLIBM_MATH +/* + * Use system provided math routines. + */ + + +#define fd_acos acos +#define fd_asin asin +#define fd_atan atan +#define fd_atan2 atan2 +#define fd_ceil ceil +#define fd_copysign copysign +#define fd_cos cos +#define fd_exp exp +#define fd_fabs fabs +#define fd_floor floor +#define fd_fmod fmod +#define fd_log log +#define fd_pow pow +#define fd_sin sin +#define fd_sqrt sqrt +#define fd_tan tan + +#endif + +JSValue math_abs(Context *cx, const JSValues& argv) +{ + if (argv.size() > 0) { + JSValue num = argv[1].toNumber(); + if (num.isNaN()) return num; + if (num.isNegativeZero()) return kPositiveZero; + if (num.isNegativeInfinity()) return kPositiveInfinity; + if (num.f64 < 0) return JSValue(-num.f64); + return num; + } + return kUndefinedValue; +} + +JSValue math_acos(Context *cx, const JSValues& argv) +{ + if (argv.size() > 0) { + JSValue num = argv[1].toNumber(); + return JSValue(fd_acos(num.f64)); + } + return kUndefinedValue; +} + +JSValue math_asin(Context *cx, const JSValues& argv) +{ + if (argv.size() > 0) { + JSValue num = argv[1].toNumber(); + return JSValue(fd_asin(num.f64)); + } + return kUndefinedValue; +} + +JSValue math_atan(Context *cx, const JSValues& argv) +{ + if (argv.size() > 0) { + JSValue num = argv[1].toNumber(); + return JSValue(fd_atan(num.f64)); + } + return kUndefinedValue; +} + +JSValue math_atan2(Context *cx, const JSValues& argv) +{ + if (argv.size() > 1) { + JSValue num1 = argv[1].toNumber(); + JSValue num2 = argv[1].toNumber(); + return JSValue(fd_atan2(num1.f64, num2.f64)); + } + return kUndefinedValue; +} + +JSValue math_ceil(Context *cx, const JSValues& argv) +{ + if (argv.size() > 0) { + JSValue num = argv[1].toNumber(); + return JSValue(fd_ceil(num.f64)); + } + return kUndefinedValue; +} + +struct MathFunctionEntry { + char *name; + JSNativeFunction::JSCode fn; +} MathFunctions[] = { + { "abs", math_abs }, + { "acos", math_acos }, + { "asin", math_asin }, + { "atan", math_atan }, + { "atan2", math_atan2 }, + { "ceil", math_acos }, + { "acos", math_acos }, + { "acos", math_acos } +}; + +struct MathConstantEntry { + char *name; + double value; +} MathConstants[] = { + { "E", M_E }, + { "LOG2E", M_LOG2E }, + { "LOG10E", M_LOG10E }, + { "LN2", M_LN2 }, + { "LN10", M_LN10 }, + { "PI", M_PI }, + { "SQRT2", M_SQRT2 }, + { "SQRT1_2", M_SQRT1_2 } +}; + +JSMath::JSMath() +{ + setClass(new JSString("Math")); + + for (int i = 0; i < sizeof(MathFunctions) / sizeof(MathFunctionEntry); i++) + setProperty(widenCString(MathFunctions[i].name), JSValue(new JSNativeFunction(MathFunctions[i].fn) ) ); + + for (i = 0; i < sizeof(MathConstants) / sizeof(MathConstantEntry); i++) + setProperty(widenCString(MathConstants[i].name), JSValue(MathConstants[i].value) ); + +} + + +} /* JSMathClass */ +} /* JavaScript */ \ No newline at end of file diff --git a/mozilla/js2/src/jsmath.h b/mozilla/js2/src/jsmath.h new file mode 100644 index 00000000000..605227ebe59 --- /dev/null +++ b/mozilla/js2/src/jsmath.h @@ -0,0 +1,56 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is the JavaScript 2 Prototype. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * 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 + * provisions of the GPL are applicable instead of those above. + * If you wish to allow use of your version of this file only + * under the terms of the GPL and not to allow others to use your + * version of this file under the NPL, indicate your decision by + * deleting the provisions above and replace them with the notice + * and other provisions required by the GPL. If you do not delete + * the provisions above, a recipient may use your version of this + * file under either the NPL or the GPL. + */ + +#ifndef jsmath_h +#define jsmath_h + +#include "jstypes.h" + +namespace JavaScript { +namespace JSMathClass { + + using JSTypes::JSObject; + using JSTypes::JSString; + + class JSMath : public JSObject { + public: + JSMath(); + + }; + + +} /* JSMathClass */ +} /* JavaScript */ + + +#endif jsmath_h \ No newline at end of file diff --git a/mozilla/js2/src/jstypes.cpp b/mozilla/js2/src/jstypes.cpp index 3800d910ee3..1cf1f5335b7 100644 --- a/mozilla/js2/src/jstypes.cpp +++ b/mozilla/js2/src/jstypes.cpp @@ -41,14 +41,33 @@ namespace JSTypes { using namespace JSClasses; -// using JavaScript::StringAtom; -// the canonical undefined value, etc. -const JSValue kUndefinedValue; -const JSValue kNaNValue = JSValue(nan); -const JSValue kTrueValue = JSValue(true); -const JSValue kFalseValue = JSValue(false); -const JSValue kNullValue = JSValue((JSObject*)NULL); +JSValue object_toString(Context *cx, const JSValues& argv) +{ + if (argv.size() > 0) { + JSString *s = new JSString("[object "); + JSValue theThis = argv[0]; + ASSERT(theThis.isObject()); + s->append(theThis.object->getClass()); + s->append("]"); + return JSValue(s); + } + return kUndefinedValue; +} + + +JSObject *JSObject::objectPrototypeObject = JSObject::initJSObject(); +JSString *JSObject::ObjectString = new JSString("Object"); + +JSObject *JSObject::initJSObject() +{ + JSObject *result = new JSObject(); + result->setProperty(widenCString("toString"), JSValue(new JSNativeFunction(object_toString) ) ); + return result; +} + + + JSType Any_Type = JSType(widenCString("any"), NULL); JSType Integer_Type = JSType(widenCString("Integer"), &Any_Type); @@ -91,6 +110,18 @@ JSType None_Type = JSType(widenCString("none"), &Any_Type); JSDOUBLE_LO32(d) == 0) +// the canonical undefined value, etc. +const JSValue kUndefinedValue; +const JSValue kNaNValue = JSValue(nan); +const JSValue kTrueValue = JSValue(true); +const JSValue kFalseValue = JSValue(false); +const JSValue kNullValue = JSValue((JSObject*)NULL); +const JSValue kNegativeZero = JSValue(-0.0); +const JSValue kPositiveZero = JSValue(0.0); +const JSValue kNegativeInfinity = JSValue(negativeInfinity); +const JSValue kPositiveInfinity = JSValue(positiveInfinity); + + const JSType *JSValue::getType() const { switch (tag) { @@ -147,6 +178,71 @@ bool JSValue::isNaN() const } } +bool JSValue::isNegativeInfinity() const +{ + ASSERT(isNumber()); + switch (tag) { + case i32_tag: + case u32_tag: + return false; + case integer_tag: + case f64_tag: + return (f64 < 0) && JSDOUBLE_IS_INFINITE(f64); + default: + NOT_REACHED("Broken compiler?"); + return true; + } +} + +bool JSValue::isPositiveInfinity() const +{ + ASSERT(isNumber()); + switch (tag) { + case i32_tag: + case u32_tag: + return false; + case integer_tag: + case f64_tag: + return (f64 > 0) && JSDOUBLE_IS_INFINITE(f64); + default: + NOT_REACHED("Broken compiler?"); + return true; + } +} + +bool JSValue::isNegativeZero() const +{ + ASSERT(isNumber()); + switch (tag) { + case i32_tag: + case u32_tag: + return false; + case integer_tag: + case f64_tag: + return JSDOUBLE_IS_NEGZERO(f64); + default: + NOT_REACHED("Broken compiler?"); + return true; + } +} + +bool JSValue::isPositiveZero() const +{ + ASSERT(isNumber()); + switch (tag) { + case i32_tag: + return (i32 == 0); + case u32_tag: + return (u32 == 0); + case integer_tag: + case f64_tag: + return (f64 == 0.0) && !JSDOUBLE_IS_NEGZERO(f64); + default: + NOT_REACHED("Broken compiler?"); + return true; + } +} + int JSValue::operator==(const JSValue& value) const { if (this->tag == value.tag) { @@ -522,6 +618,21 @@ JSString::JSString(const char* str) std::transform(str, str + n, begin(), JavaScript::widen); } +void JSString::append(const char* str) +{ + size_t n = ::strlen(str); + size_t oldSize = size(); + resize(oldSize + n); + std::transform(str, str + n, begin() + oldSize, JavaScript::widen); +} + +void JSString::append(const JSStringBase* str) +{ + size_t n = str->size(); + size_t oldSize = size(); + resize(oldSize + n); + traits_type::copy(begin() + oldSize, str->begin(), n); +} JSString::operator String() { diff --git a/mozilla/js2/src/jstypes.h b/mozilla/js2/src/jstypes.h index 2503218d0a9..01d8f68b177 100644 --- a/mozilla/js2/src/jstypes.h +++ b/mozilla/js2/src/jstypes.h @@ -138,6 +138,10 @@ namespace JSTypes { bool isUndefined() const { return (tag == undefined_tag); } bool isNull() const { return ((tag == object_tag) && (this->object == NULL)); } bool isNaN() const; + bool isNegativeInfinity() const; + bool isPositiveInfinity() const; + bool isNegativeZero() const; + bool isPositiveZero() const; bool isType() const { return (tag == type_tag); } JSValue toString() const { return (isString() ? *this : valueToString(*this)); } @@ -189,6 +193,10 @@ namespace JSTypes { extern const JSValue kTrueValue; extern const JSValue kFalseValue; extern const JSValue kNullValue; + extern const JSValue kNegativeZero; + extern const JSValue kPositiveZero; + extern const JSValue kNegativeInfinity; + extern const JSValue kPositiveInfinity; extern JSType Any_Type; extern JSType Integer_Type; @@ -214,9 +222,15 @@ namespace JSTypes { JSProperties mProperties; JSObject* mPrototype; JSType* mType; + JSString* mClass; // this is the internal [[Class]] property + public: - JSObject() : mPrototype(0), mType(&Any_Type) {} + JSObject() : mPrototype(objectPrototypeObject), mType(&Any_Type), mClass(ObjectString) {} + static JSObject *objectPrototypeObject; + static JSObject *initJSObject(); + static JSString *ObjectString; + bool hasProperty(const String& name) { return (mProperties.count(name) != 0); @@ -278,6 +292,16 @@ namespace JSTypes { return mType; } + JSString* getClass() + { + return mClass; + } + + void setClass(JSString* s) + { + mClass = s; + } + virtual void printProperties(Formatter& f); }; @@ -394,6 +418,9 @@ namespace JSTypes { explicit JSString(const char* str); operator String(); + + void append(const char* str); + void append(const JSStringBase* str); }; class JSException : public gc_base { diff --git a/mozilla/js2/src/winbuild/js2.dsp b/mozilla/js2/src/winbuild/js2.dsp index da1371d3f10..31b00713674 100644 --- a/mozilla/js2/src/winbuild/js2.dsp +++ b/mozilla/js2/src/winbuild/js2.dsp @@ -135,6 +135,10 @@ SOURCE=..\js2.cpp # End Source File # Begin Source File +SOURCE=..\jsmath.cpp +# End Source File +# Begin Source File + SOURCE=..\jstypes.cpp # End Source File # Begin Source File diff --git a/mozilla/js2/tests/cpp/js2_shell.cpp b/mozilla/js2/tests/cpp/js2_shell.cpp index dd4e49a006f..7162d3bcd27 100644 --- a/mozilla/js2/tests/cpp/js2_shell.cpp +++ b/mozilla/js2/tests/cpp/js2_shell.cpp @@ -89,7 +89,6 @@ static bool promptLine(LineReader &inReader, string &s, const char *prompt) } World world; -JSScope global; /* "filename" of the console */ const String ConsoleName = widenCString(""); @@ -184,6 +183,7 @@ static JSValue time(Context *cx, const JSValues &argv) static void readEvalPrint(FILE *in, World &world) { + JSScope global; Context cx(world, &global); #ifdef DEBUGGER_FOO jsd.attachToContext (&cx);