Value ObjectProtoFuncImp::call(ExecState *exec, Object &thisObj, const List &args) { switch(id) { case ToString: // fall through case ToLocaleString: return String("[object " + thisObj.className() + "]"); case ValueOf: return thisObj; case HasOwnProperty: { // Same as hasProperty() but without checking the prototype Identifier propertyName(args[0].toString(exec)); Value tempProto(thisObj.imp()->prototype()); thisObj.imp()->setPrototype(Value()); bool exists = thisObj.hasProperty(exec, propertyName); thisObj.imp()->setPrototype(tempProto); return Value(exists ? BooleanImp::staticTrue : BooleanImp::staticFalse); } case IsPrototypeOf: { Value v = args[0]; for(; v.isValid() && v.isA(ObjectType); v = Object::dynamicCast(v).prototype()) { if(v.imp() == thisObj.imp()) return Value(BooleanImp::staticTrue); } return Value(BooleanImp::staticFalse); } case PropertyIsEnumerable: { Identifier propertyName(args[0].toString(exec)); ObjectImp *obj = static_cast< ObjectImp * >(thisObj.imp()); int attributes; ValueImp *v = obj->_prop.get(propertyName, attributes); if(v) return Value((attributes & DontEnum) ? BooleanImp::staticFalse : BooleanImp::staticTrue); if(propertyName == specialPrototypePropertyName) return Value(BooleanImp::staticFalse); const HashEntry *entry = obj->findPropertyHashEntry(propertyName); return Value((entry && !(entry->attr & DontEnum)) ? BooleanImp::staticTrue : BooleanImp::staticFalse); } } return Undefined(); }
Value DOMCSSStyleSheetProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args) { KJS_CHECK_THIS( KJS::DOMCSSStyleSheet, thisObj ); DOM::CSSStyleSheet styleSheet = static_cast<DOMCSSStyleSheet *>(thisObj.imp())->toCSSStyleSheet(); switch (id) { case DOMCSSStyleSheet::InsertRule: return Number(styleSheet.insertRule(args[0].toString(exec).string(),(long unsigned int)args[1].toInteger(exec))); case DOMCSSStyleSheet::DeleteRule: styleSheet.deleteRule(args[0].toInteger(exec)); return Undefined(); // IE extensions case DOMCSSStyleSheet::AddRule: { //Unpassed/-1 means append. Since insertRule is picky (throws exceptions) //we adjust it to the desired length unsigned long index = args[2].toInteger(exec); unsigned long length = styleSheet.cssRules().length(); if (args[2].type() == UndefinedType) index = length; if (index > length) index = length; DOM::DOMString str = args[0].toString(exec).string() + " { " + args[1].toString(exec).string() + " } "; return Number(styleSheet.insertRule(str,index)); } case DOMCSSStyleSheet::RemoveRule: { int index = args.size() > 0 ? args[0].toInteger(exec) : 0 /*first one*/; styleSheet.deleteRule(index); return Undefined(); } default: return Undefined(); } }
Value NavigatorFunc::tryCall(ExecState *exec, Object &thisObj, const List &) { KJS_CHECK_THIS(KJS::Navigator, thisObj); Navigator *nav = static_cast< Navigator * >(thisObj.imp()); // javaEnabled() return Boolean(nav->part()->javaEnabled()); }
Value MozillaSidebarExtensionFunc::tryCall(ExecState *exec, Object &thisObj, const List &args) { KJS_CHECK_THIS(KJS::MozillaSidebarExtension, thisObj); MozillaSidebarExtension *mse = static_cast< MozillaSidebarExtension * >(thisObj.imp()); KHTMLPart *part = mse->part(); if(!part) return Undefined(); // addPanel() id == 0 KParts::BrowserExtension *ext = part->browserExtension(); if(ext) { QString url, name; if(args.size() == 1) { // I've seen this, don't know if it's legal. name = QString::null; url = args[0].toString(exec).qstring(); } else if(args.size() == 2 || args.size() == 3) { name = args[0].toString(exec).qstring(); url = args[1].toString(exec).qstring(); // 2 is the "CURL" which I don't understand and don't think we need. } else { return Boolean(false); } emit ext->addWebSideBar(KURL(url), name); return Boolean(true); } return Undefined(); }
Value DOMParserProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args) { if (!thisObj.inherits(&DOMParser::info)) { Object err = Error::create(exec,TypeError); exec->setException(err); return err; } DOMParser *parser = static_cast<DOMParser *>(thisObj.imp()); switch (id) { case DOMParser::ParseFromString: { if (args.size() != 2) { return Undefined(); } TQString str = args[0].toString(exec).qstring(); TQString contentType = args[1].toString(exec).qstring().stripWhiteSpace(); if (contentType == "text/xml" || contentType == "application/xml" || contentType == "application/xhtml+xml") { DocumentImpl *docImpl = parser->doc->implementation()->createDocument(); docImpl->open(); docImpl->write(str); docImpl->finishParsing(); docImpl->close(); return getDOMNode(exec, docImpl); } } } return Undefined(); }
Value DOMCSSPrimitiveValueProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args) { KJS_CHECK_THIS(KJS::DOMCSSPrimitiveValue, thisObj); DOM::CSSPrimitiveValue val = static_cast< DOMCSSPrimitiveValue * >(thisObj.imp())->toCSSPrimitiveValue(); switch(id) { case DOMCSSPrimitiveValue::SetFloatValue: val.setFloatValue(args[0].toInteger(exec), args[1].toNumber(exec)); return Undefined(); case DOMCSSPrimitiveValue::GetFloatValue: return Number(val.getFloatValue(args[0].toInteger(exec))); case DOMCSSPrimitiveValue::SetStringValue: val.setStringValue(args[0].toInteger(exec), args[1].toString(exec).string()); return Undefined(); case DOMCSSPrimitiveValue::GetStringValue: return String(val.getStringValue()); case DOMCSSPrimitiveValue::GetCounterValue: return getDOMCounter(exec, val.getCounterValue()); case DOMCSSPrimitiveValue::GetRectValue: return getDOMRect(exec, val.getRectValue()); case DOMCSSPrimitiveValue::GetRGBColorValue: return getDOMRGBColor(exec, val.getRGBColorValue()); default: return Undefined(); } }
Value MimeTypesFunc::tryCall(ExecState *exec, Object &thisObj, const List &args) { KJS_CHECK_THIS(KJS::MimeTypes, thisObj); KJS::MimeTypes *base = static_cast< KJS::MimeTypes * >(thisObj.imp()); if(!base->pluginsEnabled()) { if(id == MimeTypes_Item || id == MimeTypes_NamedItem) return Undefined(); } else { switch(id) { case MimeTypes_Item: { bool ok; unsigned int i = args[0].toString(exec).toArrayIndex(&ok); if(ok && i < base->mimes->count()) return Value(new MimeType(exec, base->mimes->at(i))); return Undefined(); } case MimeTypes_NamedItem: UString s = args[0].toString(exec); return base->mimeTypeByName(exec, s.qstring()); } } kdDebug(6070) << "WARNING: Unhandled token in MimeTypesFunc::tryCall : " << id << endl; return Undefined(); }
Value DOMCSSStyleDeclarationProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args) { KJS_CHECK_THIS(KJS::DOMCSSStyleDeclaration, thisObj); DOM::CSSStyleDeclaration styleDecl = static_cast< DOMCSSStyleDeclaration * >(thisObj.imp())->toStyleDecl(); String str = args[0].toString(exec); DOM::DOMString s = str.value().string(); switch(id) { case DOMCSSStyleDeclaration::GetPropertyValue: return String(styleDecl.getPropertyValue(s)); case DOMCSSStyleDeclaration::GetPropertyCSSValue: return getDOMCSSValue(exec, styleDecl.getPropertyCSSValue(s)); case DOMCSSStyleDeclaration::RemoveProperty: return String(styleDecl.removeProperty(s)); case DOMCSSStyleDeclaration::GetPropertyPriority: return String(styleDecl.getPropertyPriority(s)); case DOMCSSStyleDeclaration::SetProperty: styleDecl.setProperty(args[0].toString(exec).string(), args[1].toString(exec).string(), args[2].toString(exec).string()); return Undefined(); case DOMCSSStyleDeclaration::Item: return String(styleDecl.item(args[0].toInteger(exec))); default: return Undefined(); } }
Value DOMStyleSheetListFunc::tryCall(ExecState *exec, Object &thisObj, const List &args) { KJS_CHECK_THIS(KJS::DOMStyleSheetList, thisObj); DOM::StyleSheetList styleSheetList = static_cast< DOMStyleSheetList * >(thisObj.imp())->toStyleSheetList(); if(id == DOMStyleSheetList::Item) return getDOMStyleSheet(exec, styleSheetList.item(args[0].toInteger(exec))); return Undefined(); }
void ArrayInstanceImp::sort(ExecState *exec, Object &compareFunction) { int lengthNotIncludingUndefined = pushUndefinedObjectsToEnd(exec); CompareWithCompareFunctionArguments args(exec, compareFunction.imp()); compareWithCompareFunctionArguments = &args; qsort(storage, lengthNotIncludingUndefined, sizeof(ValueImp *), compareWithCompareFunctionForQSort); compareWithCompareFunctionArguments = 0; }
DOM::CSSRule toCSSRule(const Value &val) { Object obj = Object::dynamicCast(val); if(!obj.isValid() || !obj.inherits(&DOMCSSRule::info)) return DOM::CSSRule(); const DOMCSSRule *dobj = static_cast< const DOMCSSRule * >(obj.imp()); return dobj->toCSSRule(); }
DOM::Node KJS::toNode(const Value& val) { Object obj = Object::dynamicCast(val); if (obj.isNull() || !obj.inherits(&DOMNode::info)) return DOM::Node(); const DOMNode *dobj = static_cast<const DOMNode*>(obj.imp()); return dobj->toNode(); }
NativeErrorImp::NativeErrorImp(ExecState *exec, FunctionPrototypeImp *funcProto, const Object &prot) : InternalFunctionImp(funcProto), proto(0) { Value protect(this); proto = static_cast<ObjectImp*>(prot.imp()); putDirect(lengthPropertyName, NumberImp::one(), DontDelete|ReadOnly|DontEnum); // ECMA 15.11.7.5 putDirect(prototypePropertyName, proto, 0); }
Value DOMCSSRuleListFunc::tryCall(ExecState *exec, Object &thisObj, const List &args) { KJS_CHECK_THIS( KJS::DOMCSSRuleList, thisObj ); DOM::CSSRuleList cssRuleList = static_cast<DOMCSSRuleList *>(thisObj.imp())->toCSSRuleList(); switch (id) { case DOMCSSRuleList::Item: return getDOMCSSRule(exec,cssRuleList.item(args[0].toInteger(exec))); default: return Undefined(); } }
Value DOMCSSRuleFunc::tryCall(ExecState *exec, Object &thisObj, const List &args) { KJS_CHECK_THIS( KJS::DOMCSSRule, thisObj ); DOM::CSSRule cssRule = static_cast<DOMCSSRule *>(thisObj.imp())->toCSSRule(); if (cssRule.type() == DOM::CSSRule::MEDIA_RULE) { DOM::CSSMediaRule rule = static_cast<DOM::CSSMediaRule>(cssRule); if (id == DOMCSSRule::Media_InsertRule) return Number(rule.insertRule(args[0].toString(exec).string(),args[1].toInteger(exec))); else if (id == DOMCSSRule::Media_DeleteRule) rule.deleteRule(args[0].toInteger(exec)); } return Undefined(); }
Value KJS::DOMMediaListProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args) { KJS_CHECK_THIS( KJS::DOMMediaList, thisObj ); DOM::MediaList mediaList = static_cast<DOMMediaList *>(thisObj.imp())->toMediaList(); switch (id) { case DOMMediaList::Item: return String(mediaList.item(args[0].toInteger(exec))); case DOMMediaList::DeleteMedium: mediaList.deleteMedium(args[0].toString(exec).string()); return Undefined(); case DOMMediaList::AppendMedium: mediaList.appendMedium(args[0].toString(exec).string()); return Undefined(); default: return Undefined(); } }
Boolean DOMObject::hasInstance(ExecState *exec, const Value &value) { if(value.type() != ObjectType) return Boolean(false); Value prot = get(exec, prototypePropertyName); if(prot.type() != ObjectType && prot.type() != NullType) { Object err = Error::create(exec, TypeError, "Invalid prototype encountered " "in instanceof operation."); exec->setException(err); return Boolean(false); } Object v = Object(static_cast< ObjectImp * >(value.imp())); while((v = Object::dynamicCast(v.prototype())).imp()) { if(v.imp() == prot.imp()) return Boolean(true); } return Boolean(false); }
Value PluginFunc::tryCall(ExecState *exec, Object &thisObj, const List &args) { KJS_CHECK_THIS(KJS::Plugin, thisObj); KJS::Plugin *plugin = static_cast< KJS::Plugin * >(thisObj.imp()); switch(id) { case Plugin_Item: { bool ok; unsigned int i = args[0].toString(exec).toArrayIndex(&ok); if(ok && i < plugin->pluginInfo()->mimes.count()) return Value(new MimeType(exec, plugin->pluginInfo()->mimes.at(i))); return Undefined(); } case Plugin_NamedItem: { UString s = args[0].toString(exec); return plugin->mimeByName(exec, s.qstring()); } default: kdDebug(6070) << "WARNING: Unhandled token in PluginFunc::tryCall : " << id << endl; return Undefined(); } }
// ECMA 15.4.4 Value ArrayProtoFuncImp::call(ExecState *exec, Object &thisObj, const List &args) { unsigned int length = thisObj.get(exec, lengthPropertyName).toUInt32(exec); Value result; switch(id) { case ToLocaleString: case ToString: if(!thisObj.inherits(&ArrayInstanceImp::info)) { Object err = Error::create(exec, TypeError); exec->setException(err); return err; } // fall through case Join: { UString separator = ","; UString str = ""; if(id == Join && args.size() > 0 && !args[0].isA(UndefinedType)) separator = args[0].toString(exec); for(unsigned int k = 0; k < length; k++) { if(k >= 1) str += separator; Value element = thisObj.get(exec, k); if(element.type() == UndefinedType || element.type() == NullType) continue; bool fallback = false; if(id == ToLocaleString) { Object o = element.toObject(exec); Object conversionFunction = Object::dynamicCast(o.get(exec, toLocaleStringPropertyName)); if(conversionFunction.isValid() && conversionFunction.implementsCall()) { str += conversionFunction.call(exec, o, List()).toString(exec); } else { // try toString() fallback fallback = true; } } if(id == ToString || id == Join || fallback) { if(element.type() == ObjectType) { Object o = Object::dynamicCast(element); Object conversionFunction = Object::dynamicCast(o.get(exec, toStringPropertyName)); if(conversionFunction.isValid() && conversionFunction.implementsCall()) { str += conversionFunction.call(exec, o, List()).toString(exec); } else { UString msg = "Can't convert " + o.className() + " object to string"; Object error = Error::create(exec, RangeError, msg.cstring().c_str()); exec->setException(error); return error; } } else { str += element.toString(exec); } } if(exec->hadException()) break; } result = String(str); break; } case Concat: { Object arr = Object::dynamicCast(exec->lexicalInterpreter()->builtinArray().construct(exec, List::empty())); int n = 0; Value curArg = thisObj; Object curObj = Object::dynamicCast(thisObj); ListIterator it = args.begin(); for(;;) { if(curArg.type() == ObjectType && curObj.inherits(&ArrayInstanceImp::info)) { unsigned int k = 0; // Older versions tried to optimize out getting the length of thisObj // by checking for n != 0, but that doesn't work if thisObj is an empty array. length = curObj.get(exec, lengthPropertyName).toUInt32(exec); while(k < length) { if(curObj.hasProperty(exec, k)) arr.put(exec, n, curObj.get(exec, k)); n++; k++; } } else { arr.put(exec, n, curArg); n++; } if(it == args.end()) break; curArg = *it; curObj = Object::dynamicCast(it++); // may be 0 } arr.put(exec, lengthPropertyName, Number(n), DontEnum | DontDelete); result = arr; break; } case Pop: { if(length == 0) { thisObj.put(exec, lengthPropertyName, Number(length), DontEnum | DontDelete); result = Undefined(); } else { result = thisObj.get(exec, length - 1); thisObj.put(exec, lengthPropertyName, Number(length - 1), DontEnum | DontDelete); } break; } case Push: { for(int n = 0; n < args.size(); n++) thisObj.put(exec, length + n, args[n]); length += args.size(); thisObj.put(exec, lengthPropertyName, Number(length), DontEnum | DontDelete); result = Number(length); break; } case Reverse: { unsigned int middle = length / 2; for(unsigned int k = 0; k < middle; k++) { unsigned lk1 = length - k - 1; Value obj = thisObj.get(exec, k); Value obj2 = thisObj.get(exec, lk1); if(thisObj.hasProperty(exec, lk1)) { if(thisObj.hasProperty(exec, k)) { thisObj.put(exec, k, obj2); thisObj.put(exec, lk1, obj); } else { thisObj.put(exec, k, obj2); thisObj.deleteProperty(exec, lk1); } } else { if(thisObj.hasProperty(exec, k)) { thisObj.deleteProperty(exec, k); thisObj.put(exec, lk1, obj); } else { // why delete something that's not there ? Strange. thisObj.deleteProperty(exec, k); thisObj.deleteProperty(exec, lk1); } } } result = thisObj; break; } case Shift: { if(length == 0) { thisObj.put(exec, lengthPropertyName, Number(length), DontEnum | DontDelete); result = Undefined(); } else { result = thisObj.get(exec, 0); for(unsigned int k = 1; k < length; k++) { if(thisObj.hasProperty(exec, k)) { Value obj = thisObj.get(exec, k); thisObj.put(exec, k - 1, obj); } else thisObj.deleteProperty(exec, k - 1); } thisObj.deleteProperty(exec, length - 1); thisObj.put(exec, lengthPropertyName, Number(length - 1), DontEnum | DontDelete); } break; } case Slice: { // http://developer.netscape.com/docs/manuals/js/client/jsref/array.htm#1193713 or 15.4.4.10 // We return a new array Object resObj = Object::dynamicCast(exec->lexicalInterpreter()->builtinArray().construct(exec, List::empty())); result = resObj; int begin = 0; if(args[0].type() != UndefinedType) { begin = args[0].toInteger(exec); if(begin < 0) begin = maxInt(begin + length, 0); else begin = minInt(begin, length); } int end = length; if(args[1].type() != UndefinedType) { end = args[1].toInteger(exec); if(end < 0) end = maxInt(end + length, 0); else end = minInt(end, length); } // printf( "Slicing from %d to %d \n", begin, end ); int n = 0; for(int k = begin; k < end; k++, n++) { if(thisObj.hasProperty(exec, k)) { Value obj = thisObj.get(exec, k); resObj.put(exec, n, obj); } } resObj.put(exec, lengthPropertyName, Number(n), DontEnum | DontDelete); break; } case Sort: { #if 0 printf("KJS Array::Sort length=%d\n", length); for ( unsigned int i = 0 ; i<length ; ++i ) printf("KJS Array::Sort: %d: %s\n", i, thisObj.get(exec, i).toString(exec).ascii() ); #endif Object sortFunction; bool useSortFunction = (args[0].type() != UndefinedType); if(useSortFunction) { sortFunction = args[0].toObject(exec); if(!sortFunction.implementsCall()) useSortFunction = false; } if(thisObj.imp()->classInfo() == &ArrayInstanceImp::info) { if(useSortFunction) ((ArrayInstanceImp *)thisObj.imp())->sort(exec, sortFunction); else ((ArrayInstanceImp *)thisObj.imp())->sort(exec); result = thisObj; break; } if(length == 0) { thisObj.put(exec, lengthPropertyName, Number(0), DontEnum | DontDelete); result = thisObj; break; } // "Min" sort. Not the fastest, but definitely less code than heapsort // or quicksort, and much less swapping than bubblesort/insertionsort. for(unsigned int i = 0; i < length - 1; ++i) { Value iObj = thisObj.get(exec, i); unsigned int themin = i; Value minObj = iObj; for(unsigned int j = i + 1; j < length; ++j) { Value jObj = thisObj.get(exec, j); double cmp; if(jObj.type() == UndefinedType) { cmp = 1; // don't check minObj because there's no need to differentiate == (0) from > (1) } else if(minObj.type() == UndefinedType) { cmp = -1; } else if(useSortFunction) { List l; l.append(jObj); l.append(minObj); cmp = sortFunction.call(exec, exec->dynamicInterpreter()->globalObject(), l).toNumber(exec); } else { cmp = (jObj.toString(exec) < minObj.toString(exec)) ? -1 : 1; } if(cmp < 0) { themin = j; minObj = jObj; } } // Swap themin and i if(themin > i) { // printf("KJS Array::Sort: swapping %d and %d\n", i, themin ); thisObj.put(exec, i, minObj); thisObj.put(exec, themin, iObj); } } #if 0 printf("KJS Array::Sort -- Resulting array:\n"); for ( unsigned int i = 0 ; i<length ; ++i ) printf("KJS Array::Sort: %d: %s\n", i, thisObj.get(exec, i).toString(exec).ascii() ); #endif result = thisObj; break; } case Splice: { // 15.4.4.12 - oh boy this is huge Object resObj = Object::dynamicCast(exec->lexicalInterpreter()->builtinArray().construct(exec, List::empty())); result = resObj; int begin = args[0].toUInt32(exec); if(begin < 0) begin = maxInt(begin + length, 0); else begin = minInt(begin, length); unsigned int deleteCount = minInt(maxInt(args[1].toUInt32(exec), 0), length - begin); // printf( "Splicing from %d, deleteCount=%d \n", begin, deleteCount ); for(unsigned int k = 0; k < deleteCount; k++) { if(thisObj.hasProperty(exec, k + begin)) { Value obj = thisObj.get(exec, k + begin); resObj.put(exec, k, obj); } } resObj.put(exec, lengthPropertyName, Number(deleteCount), DontEnum | DontDelete); unsigned int additionalArgs = maxInt(args.size() - 2, 0); if(additionalArgs != deleteCount) { if(additionalArgs < deleteCount) { for(unsigned int k = begin; k < length - deleteCount; ++k) { if(thisObj.hasProperty(exec, k + deleteCount)) { Value obj = thisObj.get(exec, k + deleteCount); thisObj.put(exec, k + additionalArgs, obj); } else thisObj.deleteProperty(exec, k + additionalArgs); } for(unsigned int k = length; k > length - deleteCount + additionalArgs; --k) thisObj.deleteProperty(exec, k - 1); } else { for(unsigned int k = length - deleteCount; (int)k > begin; --k) { if(thisObj.hasProperty(exec, k + deleteCount - 1)) { Value obj = thisObj.get(exec, k + deleteCount - 1); thisObj.put(exec, k + additionalArgs - 1, obj); } else thisObj.deleteProperty(exec, k + additionalArgs - 1); } } } for(unsigned int k = 0; k < additionalArgs; ++k) { thisObj.put(exec, k + begin, args[k + 2]); } thisObj.put(exec, lengthPropertyName, Number(length - deleteCount + additionalArgs), DontEnum | DontDelete); break; } case UnShift: { // 15.4.4.13 unsigned int nrArgs = args.size(); for(unsigned int k = length; k > 0; --k) { if(thisObj.hasProperty(exec, k - 1)) { Value obj = thisObj.get(exec, k - 1); thisObj.put(exec, k + nrArgs - 1, obj); } else { thisObj.deleteProperty(exec, k + nrArgs - 1); } } for(unsigned int k = 0; k < nrArgs; ++k) thisObj.put(exec, k, args[k]); result = Number(length + nrArgs); thisObj.put(exec, lengthPropertyName, result, DontEnum | DontDelete); break; } default: assert(0); break; } return result; }
Value RegExpProtoFuncImp::call(ExecState *exec, Object &thisObj, const List &args) { if (!thisObj.inherits(&RegExpImp::info)) { Object err = Error::create(exec,TypeError); exec->setException(err); return err; } RegExpImp *reimp = static_cast<RegExpImp*>(thisObj.imp()); RegExp *re = reimp->regExp(); String s; UString str; switch (id) { case Exec: // 15.10.6.2 case Test: { s = args[0].toString(exec); int length = s.value().size(); Value lastIndex = thisObj.get(exec,"lastIndex"); int i = lastIndex.isNull() ? 0 : lastIndex.toInt32(exec); bool globalFlag = thisObj.get(exec,"global").toBoolean(exec); if (!globalFlag) i = 0; if (i < 0 || i > length) { thisObj.put(exec,"lastIndex", Number(0), DontDelete | DontEnum); if (id == Test) return Boolean(false); else Null(); } RegExpObjectImp* regExpObj = static_cast<RegExpObjectImp*>(exec->interpreter()->builtinRegExp().imp()); int **ovector = regExpObj->registerRegexp( re, s.value() ); str = re->match(s.value(), i, 0L, ovector); regExpObj->setSubPatterns(re->subPatterns()); if (id == Test) return Boolean(!str.isNull()); if (str.isNull()) // no match { if (globalFlag) thisObj.put(exec,"lastIndex",Number(0), DontDelete | DontEnum); return Null(); } else // success { if (globalFlag) thisObj.put(exec,"lastIndex",Number( (*ovector)[1] ), DontDelete | DontEnum); return regExpObj->arrayOfMatches(exec,str); } } break; case ToString: s = thisObj.get(exec,"source").toString(exec); str = "/"; str += s.value(); str += "/"; // TODO append the flags return String(str); } return Undefined(); }
bool KJSDebugWin::exception(ExecState *exec, const Value &value, bool inTryCatch) { assert(value.isValid()); // Ignore exceptions that will be caught by the script if(inTryCatch) return true; KParts::ReadOnlyPart *part = static_cast< ScriptInterpreter * >(exec->interpreter())->part(); KHTMLPart *khtmlpart = ::qt_cast< KHTMLPart * >(part); if(khtmlpart && !khtmlpart->settings()->isJavaScriptErrorReportingEnabled()) return true; QWidget *dlgParent = (m_evalDepth == 0) ? (QWidget *)part->widget() : (QWidget *)this; QString exceptionMsg = value.toString(exec).qstring(); // Syntax errors are a special case. For these we want to display the url & lineno, // which isn't included in the exception messeage. So we work it out from the values // passed to sourceParsed() Object valueObj = Object::dynamicCast(value); Object syntaxError = exec->interpreter()->builtinSyntaxError(); if(valueObj.isValid() && valueObj.get(exec, "constructor").imp() == syntaxError.imp()) { Value sidValue = valueObj.get(exec, "sid"); if(sidValue.isA(NumberType)) { // sid is not set for Function() constructor int sourceId = (int)sidValue.toNumber(exec); assert(m_sourceFragments[sourceId]); exceptionMsg = i18n("Parse error at %1 line %2") .arg(m_sourceFragments[sourceId]->sourceFile->url) .arg(m_sourceFragments[sourceId]->baseLine + m_sourceFragments[sourceId]->errorLine - 1); } } bool dontShowAgain = false; if(m_execsCount == 0) { // An exception occurred and we're not currently executing any code... this can // happen in some cases e.g. a parse error, or native code accessing funcitons like // Object::put() QString msg = i18n("An error occurred while attempting to run a script on this page.\n\n%1").arg(exceptionMsg); KJSErrorDialog dlg(dlgParent, msg, false); dlg.exec(); dontShowAgain = dlg.dontShowAgain(); } else { Context ctx = m_execs[m_execsCount - 1]->context(); SourceFragment *sourceFragment = m_sourceFragments[ctx.sourceId()]; QString msg = i18n("An error occurred while attempting to run a script on this page.\n\n%1 line %2:\n%3") .arg(KStringHandler::rsqueeze(sourceFragment->sourceFile->url, 80), QString::number(sourceFragment->baseLine + ctx.curStmtFirstLine() - 1), exceptionMsg); KJSErrorDialog dlg(dlgParent, msg, true); dlg.exec(); dontShowAgain = dlg.dontShowAgain(); if(dlg.debugSelected()) { m_mode = Next; m_steppingDepth = m_execsCount - 1; enterSession(exec); } } if(dontShowAgain) { KConfig *config = kapp->config(); KConfigGroupSaver saver(config, QString::fromLatin1("Java/JavaScript Settings")); config->writeEntry("ReportJavaScriptErrors", QVariant(false, 0)); config->sync(); QByteArray data; kapp->dcopClient()->send("konqueror*", "KonquerorIface", "reparseConfiguration()", data); } return (m_mode != Stop); }
// ECMA 15.9.3 Object DateObjectImp::construct(ExecState *exec, const List &args) { int numArgs = args.size(); #ifdef KJS_VERBOSE fprintf(stderr,"DateObjectImp::construct - %d args\n", numArgs); #endif double value; if (numArgs == 0) { // new Date() ECMA 15.9.3.3 #ifdef HAVE_SYS_TIMEB_H # if defined(__BORLANDC__) struct timeb timebuffer; ftime(&timebuffer); # else struct _timeb timebuffer; _ftime(&timebuffer); # endif double utc = floor((double)timebuffer.time * 1000.0 + (double)timebuffer.millitm); #else struct timeval tv; gettimeofday(&tv, 0L); double utc = floor((double)tv.tv_sec * 1000.0 + (double)tv.tv_usec / 1000.0); #endif value = utc; } else if (numArgs == 1) { Value prim = args[0].toPrimitive(exec); if (prim.isA(StringType)) value = parseDate(prim.toString(exec)); else value = prim.toNumber(exec); } else { if (isNaN(args[0].toNumber(exec)) || isNaN(args[1].toNumber(exec)) || (numArgs >= 3 && isNaN(args[2].toNumber(exec))) || (numArgs >= 4 && isNaN(args[3].toNumber(exec))) || (numArgs >= 5 && isNaN(args[4].toNumber(exec))) || (numArgs >= 6 && isNaN(args[5].toNumber(exec))) || (numArgs >= 7 && isNaN(args[6].toNumber(exec)))) { value = NaN; } else { struct tm t; memset(&t, 0, sizeof(t)); int year = args[0].toInt32(exec); t.tm_year = (year >= 0 && year <= 99) ? year : year - 1900; t.tm_mon = args[1].toInt32(exec); t.tm_mday = (numArgs >= 3) ? args[2].toInt32(exec) : 1; t.tm_hour = (numArgs >= 4) ? args[3].toInt32(exec) : 0; t.tm_min = (numArgs >= 5) ? args[4].toInt32(exec) : 0; t.tm_sec = (numArgs >= 6) ? args[5].toInt32(exec) : 0; t.tm_isdst = -1; int ms = (numArgs >= 7) ? args[6].toInt32(exec) : 0; value = makeTime(&t, ms, false); } } Object proto = exec->lexicalInterpreter()->builtinDatePrototype(); Object ret(new DateInstanceImp(proto.imp())); ret.setInternalValue(Number(timeClip(value))); return ret; }
Value RegExpProtoFuncImp::call(ExecState *exec, Object &thisObj, const List &args) { if (!thisObj.inherits(&RegExpImp::info)) { if (thisObj.inherits(&RegExpPrototypeImp::info)) { switch (id) { case ToString: return String("//"); // FireFox returns /(?:)/ } } Object err = Error::create(exec,TypeError); exec->setException(err); return err; } RegExpImp *reimp = static_cast<RegExpImp*>(thisObj.imp()); RegExp *re = reimp->regExp(); String s; UString str; switch (id) { case Exec: // 15.10.6.2 case Test: { s = args[0].toString(exec); int length = s.value().size(); // Get values from the last time (in case of /g) Value lastIndex = thisObj.get(exec,"lastIndex"); int i = lastIndex.isValid() ? lastIndex.toInt32(exec) : 0; bool globalFlag = thisObj.get(exec,"global").toBoolean(exec); if (!globalFlag) i = 0; if (i < 0 || i > length) { thisObj.put(exec,"lastIndex", Number(0), DontDelete | DontEnum); if (id == Test) return Boolean(false); else return Null(); } RegExpObjectImp* regExpObj = static_cast<RegExpObjectImp*>(exec->lexicalInterpreter()->builtinRegExp().imp()); int **ovector = regExpObj->registerRegexp( re, s.value() ); re->prepareMatch(s.value()); str = re->match(s.value(), i, 0L, ovector); re->doneMatch(); regExpObj->setSubPatterns(re->subPatterns()); if (id == Test) return Boolean(!str.isNull()); if (str.isNull()) // no match { if (globalFlag) thisObj.put(exec,"lastIndex",Number(0), DontDelete | DontEnum); return Null(); } else // success { if (globalFlag) thisObj.put(exec,"lastIndex",Number( (*ovector)[1] ), DontDelete | DontEnum); return regExpObj->arrayOfMatches(exec,str); } } break; case ToString: s = thisObj.get(exec,"source").toString(exec); str = "/"; str += s.value(); str += "/"; if (thisObj.get(exec,"global").toBoolean(exec)) { str += "g"; } if (thisObj.get(exec,"ignoreCase").toBoolean(exec)) { str += "i"; } if (thisObj.get(exec,"multiline").toBoolean(exec)) { str += "m"; } return String(str); case Compile: { RegExp* newEngine = RegExpObjectImp::makeEngine(exec, args[0].toString(exec), args[1]); if (!newEngine) return exec->exception(); reimp->setRegExp(newEngine); return Value(reimp); } } return Undefined(); }