source: webkit/trunk/JavaScriptCore/kjs/RegExpObject.cpp@ 34757

Last change on this file since 34757 was 34754, checked in by Darin Adler, 17 years ago

JavaScriptCore:

2008-06-23 Darin Adler <Darin Adler>

Reviewed by Geoff.

More preparation toward making functions work on primitive types without
creating wrapper objects. No speedup this time, but prepares for a future
speedup without slowing things down.

SunSpider reports no change.

  • Eliminated the implementsCall, callAsFunction and construct virtual functions from JSObject. Instead, the CallData and ConstructData for a native function includes a function pointer that the caller can use directly. Changed all call sites to use CallData and ConstructData.
  • Changed the "this" argument to native functions to be a JSValue rather than a JSObject. This prepares us for passing primitives into these functions. The conversion to an object now must be done inside the function. Critically, if it's a function that can be called on a DOM window object, then we have to be sure to call toThisObject on the argument before we use it for anything even if it's already an object.
  • Eliminated the practice of using constructor objects in the global object to make objects of the various basic types. Since these constructors can't be replaced by script, there's no reason to involve a constructor object at all. Added functions to do the construction directly.
  • Made some more class members private and protected, including virtual function overrides. This can catch code using unnecessarily slow virtual function code paths when the type of an object is known statically. If we later find a new reason use the members outside the class it's easy to make them public again.
  • Moved the declarations of the native implementations for functions out of header files. These can have internal linkage and be declared inside the source file.
  • Changed PrototypeFunction to take function pointers with the right arguments to be put directly into CallData. This eliminates the need to have a separate PrototypeReflexiveFunction, and reveals that the real purpose of that class included something else specific to eval -- storage of a cached global object. So renamed PrototypeReflexiveFunction to GlobalEvalFunction.
  • API/JSCallbackConstructor.cpp: (KJS::constructJSCallback): (KJS::JSCallbackConstructor::getConstructData):
  • API/JSCallbackConstructor.h:
  • API/JSCallbackFunction.cpp: (KJS::JSCallbackFunction::implementsHasInstance): (KJS::JSCallbackFunction::call): (KJS::JSCallbackFunction::getCallData):
  • API/JSCallbackFunction.h: (KJS::JSCallbackFunction::classInfo):
  • API/JSCallbackObject.h: (KJS::JSCallbackObject::classRef): (KJS::JSCallbackObject::classInfo):
  • API/JSCallbackObjectFunctions.h: (KJS::::getConstructData): (KJS::::construct): (KJS::::getCallData): (KJS::::call):
  • API/JSObjectRef.cpp: (JSObjectMakeFunction): (JSObjectIsFunction): (JSObjectCallAsFunction): (JSObjectCallAsConstructor):
  • JavaScriptCore.exp:
  • VM/Machine.cpp: (KJS::jsTypeStringForValue): (KJS::Machine::privateExecute):
  • kjs/ArrayPrototype.cpp: (KJS::arrayProtoFuncToString): (KJS::arrayProtoFuncToLocaleString): (KJS::arrayProtoFuncJoin): (KJS::arrayProtoFuncConcat): (KJS::arrayProtoFuncPop): (KJS::arrayProtoFuncPush): (KJS::arrayProtoFuncReverse): (KJS::arrayProtoFuncShift): (KJS::arrayProtoFuncSlice): (KJS::arrayProtoFuncSort): (KJS::arrayProtoFuncSplice): (KJS::arrayProtoFuncUnShift): (KJS::arrayProtoFuncFilter): (KJS::arrayProtoFuncMap): (KJS::arrayProtoFuncEvery): (KJS::arrayProtoFuncForEach): (KJS::arrayProtoFuncSome): (KJS::arrayProtoFuncIndexOf): (KJS::arrayProtoFuncLastIndexOf): (KJS::ArrayConstructor::ArrayConstructor): (KJS::constructArrayWithSizeQuirk): (KJS::constructWithArrayConstructor): (KJS::ArrayConstructor::getConstructData): (KJS::callArrayConstructor): (KJS::ArrayConstructor::getCallData):
  • kjs/ArrayPrototype.h:
  • kjs/BooleanObject.cpp: (KJS::booleanProtoFuncToString): (KJS::booleanProtoFuncValueOf): (KJS::constructBoolean): (KJS::constructWithBooleanConstructor): (KJS::BooleanConstructor::getConstructData): (KJS::callBooleanConstructor): (KJS::BooleanConstructor::getCallData): (KJS::constructBooleanFromImmediateBoolean):
  • kjs/BooleanObject.h:
  • kjs/CallData.h: (KJS::):
  • kjs/ConstructData.h: (KJS::):
  • kjs/FunctionPrototype.cpp: (KJS::callFunctionPrototype): (KJS::FunctionPrototype::getCallData): (KJS::functionProtoFuncToString): (KJS::functionProtoFuncApply): (KJS::functionProtoFuncCall): (KJS::constructWithFunctionConstructor): (KJS::FunctionConstructor::getConstructData): (KJS::callFunctionConstructor): (KJS::FunctionConstructor::getCallData): (KJS::constructFunction):
  • kjs/FunctionPrototype.h:
  • kjs/JSArray.cpp: (KJS::AVLTreeAbstractorForArrayCompare::compare_key_key): (KJS::JSArray::sort): (KJS::constructEmptyArray): (KJS::constructArray):
  • kjs/JSArray.h: (KJS::JSArray::classInfo):
  • kjs/JSFunction.cpp: (KJS::JSFunction::call): (KJS::globalFuncEval): (KJS::globalFuncParseInt): (KJS::globalFuncParseFloat): (KJS::globalFuncIsNaN): (KJS::globalFuncIsFinite): (KJS::globalFuncDecodeURI): (KJS::globalFuncDecodeURIComponent): (KJS::globalFuncEncodeURI): (KJS::globalFuncEncodeURIComponent): (KJS::globalFuncEscape): (KJS::globalFuncUnescape): (KJS::globalFuncKJSPrint): (KJS::PrototypeFunction::PrototypeFunction): (KJS::PrototypeFunction::getCallData): (KJS::GlobalEvalFunction::GlobalEvalFunction): (KJS::GlobalEvalFunction::mark):
  • kjs/JSFunction.h: (KJS::InternalFunction::classInfo): (KJS::InternalFunction::functionName): (KJS::JSFunction::classInfo): (KJS::GlobalEvalFunction::cachedGlobalObject):
  • kjs/JSGlobalObject.cpp: (KJS::JSGlobalObject::reset): (KJS::JSGlobalObject::mark):
  • kjs/JSGlobalObject.h: (KJS::JSGlobalObject::JSGlobalObject): (KJS::JSGlobalObject::evalFunction):
  • kjs/JSImmediate.cpp: (KJS::JSImmediate::toObject):
  • kjs/JSNotAnObject.cpp:
  • kjs/JSNotAnObject.h:
  • kjs/JSObject.cpp: (KJS::JSObject::put): (KJS::callDefaultValueFunction): (KJS::JSObject::defaultValue): (KJS::JSObject::lookupGetter): (KJS::JSObject::lookupSetter): (KJS::JSObject::hasInstance): (KJS::JSObject::fillGetterPropertySlot): (KJS::Error::create): (KJS::constructEmptyObject):
  • kjs/JSObject.h: (KJS::GetterSetter::GetterSetter): (KJS::GetterSetter::getter): (KJS::GetterSetter::setGetter): (KJS::GetterSetter::setter): (KJS::GetterSetter::setSetter):
  • kjs/JSValue.cpp: (KJS::JSCell::deleteProperty): (KJS::call): (KJS::construct):
  • kjs/JSValue.h:
  • kjs/MathObject.cpp: (KJS::mathProtoFuncAbs): (KJS::mathProtoFuncACos): (KJS::mathProtoFuncASin): (KJS::mathProtoFuncATan): (KJS::mathProtoFuncATan2): (KJS::mathProtoFuncCeil): (KJS::mathProtoFuncCos): (KJS::mathProtoFuncExp): (KJS::mathProtoFuncFloor): (KJS::mathProtoFuncLog): (KJS::mathProtoFuncMax): (KJS::mathProtoFuncMin): (KJS::mathProtoFuncPow): (KJS::mathProtoFuncRandom): (KJS::mathProtoFuncRound): (KJS::mathProtoFuncSin): (KJS::mathProtoFuncSqrt): (KJS::mathProtoFuncTan):
  • kjs/MathObject.h:
  • kjs/NumberObject.cpp: (KJS::numberProtoFuncToString): (KJS::numberProtoFuncToLocaleString): (KJS::numberProtoFuncValueOf): (KJS::numberProtoFuncToFixed): (KJS::numberProtoFuncToExponential): (KJS::numberProtoFuncToPrecision): (KJS::NumberConstructor::NumberConstructor): (KJS::constructWithNumberConstructor): (KJS::NumberConstructor::getConstructData): (KJS::callNumberConstructor): (KJS::NumberConstructor::getCallData): (KJS::constructNumber): (KJS::constructNumberFromImmediateNumber):
  • kjs/NumberObject.h: (KJS::NumberObject::classInfo): (KJS::NumberConstructor::classInfo):
  • kjs/PropertySlot.cpp: (KJS::PropertySlot::functionGetter):
  • kjs/RegExpObject.cpp: (KJS::regExpProtoFuncTest): (KJS::regExpProtoFuncExec): (KJS::regExpProtoFuncCompile): (KJS::regExpProtoFuncToString): (KJS::callRegExpObject): (KJS::RegExpObject::getCallData): (KJS::constructRegExp): (KJS::constructWithRegExpConstructor): (KJS::RegExpConstructor::getConstructData): (KJS::callRegExpConstructor): (KJS::RegExpConstructor::getCallData):
  • kjs/RegExpObject.h: (KJS::RegExpConstructor::classInfo):
  • kjs/Shell.cpp: (GlobalObject::GlobalObject): (functionPrint): (functionDebug): (functionGC): (functionVersion): (functionRun): (functionLoad): (functionReadline): (functionQuit):
  • kjs/date_object.cpp: (KJS::gmtoffset): (KJS::formatLocaleDate): (KJS::fillStructuresUsingDateArgs): (KJS::DateInstance::getTime): (KJS::DateInstance::getUTCTime): (KJS::DateConstructor::DateConstructor): (KJS::constructDate): (KJS::DateConstructor::getConstructData): (KJS::callDate): (KJS::DateConstructor::getCallData): (KJS::dateParse): (KJS::dateNow): (KJS::dateUTC): (KJS::dateProtoFuncToString): (KJS::dateProtoFuncToUTCString): (KJS::dateProtoFuncToDateString): (KJS::dateProtoFuncToTimeString): (KJS::dateProtoFuncToLocaleString): (KJS::dateProtoFuncToLocaleDateString): (KJS::dateProtoFuncToLocaleTimeString): (KJS::dateProtoFuncValueOf): (KJS::dateProtoFuncGetTime): (KJS::dateProtoFuncGetFullYear): (KJS::dateProtoFuncGetUTCFullYear): (KJS::dateProtoFuncToGMTString): (KJS::dateProtoFuncGetMonth): (KJS::dateProtoFuncGetUTCMonth): (KJS::dateProtoFuncGetDate): (KJS::dateProtoFuncGetUTCDate): (KJS::dateProtoFuncGetDay): (KJS::dateProtoFuncGetUTCDay): (KJS::dateProtoFuncGetHours): (KJS::dateProtoFuncGetUTCHours): (KJS::dateProtoFuncGetMinutes): (KJS::dateProtoFuncGetUTCMinutes): (KJS::dateProtoFuncGetSeconds): (KJS::dateProtoFuncGetUTCSeconds): (KJS::dateProtoFuncGetMilliSeconds): (KJS::dateProtoFuncGetUTCMilliseconds): (KJS::dateProtoFuncGetTimezoneOffset): (KJS::dateProtoFuncSetTime): (KJS::setNewValueFromTimeArgs): (KJS::setNewValueFromDateArgs): (KJS::dateProtoFuncSetMilliSeconds): (KJS::dateProtoFuncSetUTCMilliseconds): (KJS::dateProtoFuncSetSeconds): (KJS::dateProtoFuncSetUTCSeconds): (KJS::dateProtoFuncSetMinutes): (KJS::dateProtoFuncSetUTCMinutes): (KJS::dateProtoFuncSetHours): (KJS::dateProtoFuncSetUTCHours): (KJS::dateProtoFuncSetDate): (KJS::dateProtoFuncSetUTCDate): (KJS::dateProtoFuncSetMonth): (KJS::dateProtoFuncSetUTCMonth): (KJS::dateProtoFuncSetFullYear): (KJS::dateProtoFuncSetUTCFullYear): (KJS::dateProtoFuncSetYear): (KJS::dateProtoFuncGetYear):
  • kjs/date_object.h: (KJS::DateInstance::internalNumber): (KJS::DateInstance::classInfo):
  • kjs/error_object.cpp: (KJS::errorProtoFuncToString): (KJS::constructError): (KJS::constructWithErrorConstructor): (KJS::ErrorConstructor::getConstructData): (KJS::callErrorConstructor): (KJS::ErrorConstructor::getCallData): (KJS::NativeErrorConstructor::construct): (KJS::constructWithNativeErrorConstructor): (KJS::NativeErrorConstructor::getConstructData): (KJS::callNativeErrorConstructor): (KJS::NativeErrorConstructor::getCallData):
  • kjs/error_object.h: (KJS::NativeErrorConstructor::classInfo):
  • kjs/internal.cpp: (KJS::JSNumberCell::toObject): (KJS::JSNumberCell::toThisObject): (KJS::GetterSetter::mark): (KJS::GetterSetter::toPrimitive): (KJS::GetterSetter::toBoolean): (KJS::GetterSetter::toNumber): (KJS::GetterSetter::toString): (KJS::GetterSetter::toObject): (KJS::InternalFunction::InternalFunction): (KJS::InternalFunction::implementsHasInstance):
  • kjs/lookup.h: (KJS::HashEntry::):
  • kjs/nodes.cpp: (KJS::FuncDeclNode::makeFunction): (KJS::FuncExprNode::makeFunction):
  • kjs/object_object.cpp: (KJS::objectProtoFuncValueOf): (KJS::objectProtoFuncHasOwnProperty): (KJS::objectProtoFuncIsPrototypeOf): (KJS::objectProtoFuncDefineGetter): (KJS::objectProtoFuncDefineSetter): (KJS::objectProtoFuncLookupGetter): (KJS::objectProtoFuncLookupSetter): (KJS::objectProtoFuncPropertyIsEnumerable): (KJS::objectProtoFuncToLocaleString): (KJS::objectProtoFuncToString): (KJS::ObjectConstructor::ObjectConstructor): (KJS::constructObject): (KJS::constructWithObjectConstructor): (KJS::ObjectConstructor::getConstructData): (KJS::callObjectConstructor): (KJS::ObjectConstructor::getCallData):
  • kjs/object_object.h:
  • kjs/string_object.cpp: (KJS::replace): (KJS::stringProtoFuncToString): (KJS::stringProtoFuncValueOf): (KJS::stringProtoFuncCharAt): (KJS::stringProtoFuncCharCodeAt): (KJS::stringProtoFuncConcat): (KJS::stringProtoFuncIndexOf): (KJS::stringProtoFuncLastIndexOf): (KJS::stringProtoFuncMatch): (KJS::stringProtoFuncSearch): (KJS::stringProtoFuncReplace): (KJS::stringProtoFuncSlice): (KJS::stringProtoFuncSplit): (KJS::stringProtoFuncSubstr): (KJS::stringProtoFuncSubstring): (KJS::stringProtoFuncToLowerCase): (KJS::stringProtoFuncToUpperCase): (KJS::stringProtoFuncToLocaleLowerCase): (KJS::stringProtoFuncToLocaleUpperCase): (KJS::stringProtoFuncLocaleCompare): (KJS::stringProtoFuncBig): (KJS::stringProtoFuncSmall): (KJS::stringProtoFuncBlink): (KJS::stringProtoFuncBold): (KJS::stringProtoFuncFixed): (KJS::stringProtoFuncItalics): (KJS::stringProtoFuncStrike): (KJS::stringProtoFuncSub): (KJS::stringProtoFuncSup): (KJS::stringProtoFuncFontcolor): (KJS::stringProtoFuncFontsize): (KJS::stringProtoFuncAnchor): (KJS::stringProtoFuncLink): (KJS::stringFromCharCode): (KJS::StringConstructor::StringConstructor): (KJS::constructWithStringConstructor): (KJS::StringConstructor::getConstructData): (KJS::callStringConstructor): (KJS::StringConstructor::getCallData):
  • kjs/string_object.h:

JavaScriptGlue:

2008-06-23 Darin Adler <Darin Adler>

Reviewed by Geoff.

  • JSValueWrapper.cpp: (JSValueWrapper::JSObjectCallFunction): Updated to use getCallData and call instead of the old callAsFunction.

WebCore:

2008-06-23 Darin Adler <Darin Adler>

Reviewed by Geoff.

Update for JavaScript changes.

  • Use CallData and ConstructData instead of the obsolete implementsCall, callAsFunction, and construct functions.
  • Updated native function arguments, specifically to allow a JSValue rather than a JSObject for the this argument, and to call toThisObject as needed when treating it as an object.
  • Made some more class members private and protected, including virtual function overrides.
  • Eliminated the use of getCallData in the JavaScript bridging code as a way to check if an instance supports invokeDefaultMethod.
  • Eliminated unnecessary polymorphism in the NodeIterator and TreeWalker classes. They were using virtual functions simply to share an instance of the RefCounted template, which was not helpful.
  • bindings/js/JSAudioConstructor.cpp: (WebCore::constructAudio): (WebCore::JSAudioConstructor::getConstructData):
  • bindings/js/JSAudioConstructor.h: (WebCore::JSAudioConstructor::document): (WebCore::JSAudioConstructor::classInfo):
  • bindings/js/JSClipboardCustom.cpp: (WebCore::JSClipboard::types):
  • bindings/js/JSCustomSQLStatementCallback.cpp: (WebCore::JSCustomSQLStatementCallback::handleEvent):
  • bindings/js/JSCustomSQLStatementErrorCallback.cpp: (WebCore::JSCustomSQLStatementErrorCallback::handleEvent):
  • bindings/js/JSCustomSQLTransactionCallback.cpp: (WebCore::JSCustomSQLTransactionCallback::handleEvent):
  • bindings/js/JSCustomSQLTransactionErrorCallback.cpp: (WebCore::JSCustomSQLTransactionErrorCallback::handleEvent):
  • bindings/js/JSCustomVoidCallback.cpp: (WebCore::JSCustomVoidCallback::handleEvent):
  • bindings/js/JSCustomXPathNSResolver.cpp: (WebCore::JSCustomXPathNSResolver::lookupNamespaceURI):
  • bindings/js/JSDOMBinding.h: (WebCore::DOMObject::DOMObject):
  • bindings/js/JSDOMWindowBase.cpp: (WebCore::windowProtoFuncAToB): (WebCore::windowProtoFuncBToA): (WebCore::windowProtoFuncOpen): (WebCore::windowProtoFuncSetTimeout): (WebCore::windowProtoFuncClearTimeout): (WebCore::windowProtoFuncSetInterval): (WebCore::windowProtoFuncAddEventListener): (WebCore::windowProtoFuncRemoveEventListener): (WebCore::windowProtoFuncShowModalDialog): (WebCore::windowProtoFuncNotImplemented): (WebCore::toJSDOMWindow):
  • bindings/js/JSDOMWindowBase.h:
  • bindings/js/JSDOMWindowShell.h: (WebCore::JSDOMWindowShell::classInfo):
  • bindings/js/JSEventListener.cpp: (WebCore::JSAbstractEventListener::handleEvent): (WebCore::JSLazyEventListener::parseCode):
  • bindings/js/JSEventTargetBase.cpp: (WebCore::retrieveEventTargetAndCorrespondingNode): (WebCore::jsEventTargetAddEventListener): (WebCore::jsEventTargetRemoveEventListener): (WebCore::jsEventTargetDispatchEvent):
  • bindings/js/JSEventTargetBase.h:
  • bindings/js/JSHTMLAppletElementCustom.cpp: (WebCore::JSHTMLAppletElement::customGetOwnPropertySlot): (WebCore::JSHTMLAppletElement::customPut): (WebCore::JSHTMLAppletElement::getCallData):
  • bindings/js/JSHTMLCollectionCustom.cpp: (WebCore::callHTMLCollection): (WebCore::JSHTMLCollection::getCallData):
  • bindings/js/JSHTMLDocumentCustom.cpp: (WebCore::JSHTMLDocument::open):
  • bindings/js/JSHTMLEmbedElementCustom.cpp: (WebCore::JSHTMLEmbedElement::customGetOwnPropertySlot): (WebCore::JSHTMLEmbedElement::customPut): (WebCore::JSHTMLEmbedElement::getCallData):
  • bindings/js/JSHTMLInputElementBase.cpp: (WebCore::jsHTMLInputElementBaseFunctionSetSelectionRange):
  • bindings/js/JSHTMLInputElementBase.h:
  • bindings/js/JSHTMLObjectElementCustom.cpp: (WebCore::JSHTMLObjectElement::customGetOwnPropertySlot): (WebCore::JSHTMLObjectElement::customPut): (WebCore::JSHTMLObjectElement::getCallData):
  • bindings/js/JSHTMLOptionElementConstructor.cpp: (WebCore::constructHTMLOptionElement): (WebCore::JSHTMLOptionElementConstructor::getConstructData):
  • bindings/js/JSHTMLOptionElementConstructor.h: (WebCore::JSHTMLOptionElementConstructor::document): (WebCore::JSHTMLOptionElementConstructor::classInfo):
  • bindings/js/JSImageConstructor.cpp: (WebCore::constructImage): (WebCore::JSImageConstructor::getConstructData):
  • bindings/js/JSImageConstructor.h: (WebCore::JSImageConstructor::document): (WebCore::JSImageConstructor::classInfo):
  • bindings/js/JSInspectedObjectWrapper.h: (WebCore::JSInspectedObjectWrapper::classInfo):
  • bindings/js/JSInspectorCallbackWrapper.cpp: (WebCore::JSInspectorCallbackWrapper::prepareIncomingValue):
  • bindings/js/JSJavaScriptCallFrameCustom.cpp: (WebCore::JSJavaScriptCallFrame::scopeChain):
  • bindings/js/JSNodeFilterCondition.cpp: (WebCore::JSNodeFilterCondition::JSNodeFilterCondition): (WebCore::JSNodeFilterCondition::mark): (WebCore::JSNodeFilterCondition::acceptNode):
  • bindings/js/JSNodeFilterCondition.h: (WebCore::JSNodeFilterCondition::create):
  • bindings/js/JSNodeFilterCustom.cpp: (WebCore::toNodeFilter):
  • bindings/js/JSNodeListCustom.cpp: (WebCore::callNodeList): (WebCore::JSNodeList::getCallData): (WebCore::JSNodeList::canGetItemsForName): (WebCore::JSNodeList::nameGetter):
  • bindings/js/JSPluginElementFunctions.cpp: (WebCore::runtimeObjectGetter): (WebCore::runtimeObjectPropertyGetter): (WebCore::runtimeObjectCustomGetOwnPropertySlot): (WebCore::runtimeObjectCustomPut): (WebCore::runtimeObjectGetCallData): (WebCore::pluginInstance): (WebCore::getRuntimeObject): (WebCore::callPlugin):
  • bindings/js/JSPluginElementFunctions.h:
  • bindings/js/JSQuarantinedObjectWrapper.cpp: (WebCore::JSQuarantinedObjectWrapper::put): (WebCore::JSQuarantinedObjectWrapper::construct): (WebCore::JSQuarantinedObjectWrapper::getConstructData): (WebCore::JSQuarantinedObjectWrapper::hasInstance): (WebCore::JSQuarantinedObjectWrapper::call): (WebCore::JSQuarantinedObjectWrapper::getCallData):
  • bindings/js/JSQuarantinedObjectWrapper.h: (WebCore::JSQuarantinedObjectWrapper::className):
  • bindings/js/JSRGBColor.cpp:
  • bindings/js/JSXMLHttpRequestConstructor.cpp: (WebCore::constructXMLHttpRequest): (WebCore::JSXMLHttpRequestConstructor::getConstructData):
  • bindings/js/JSXMLHttpRequestConstructor.h: (WebCore::JSXMLHttpRequestConstructor::document): (WebCore::JSXMLHttpRequestConstructor::classInfo):
  • bindings/js/JSXSLTProcessorConstructor.cpp: (WebCore::constructXSLTProcessor): (WebCore::JSXSLTProcessorConstructor::getConstructData):
  • bindings/js/JSXSLTProcessorConstructor.h: (WebCore::JSXSLTProcessorConstructor::classInfo):
  • bindings/js/ScheduledAction.cpp: (WebCore::ScheduledAction::ScheduledAction): (WebCore::ScheduledAction::execute):
  • bindings/js/ScheduledAction.h:
  • bindings/objc/WebScriptObject.mm: (-[WebScriptObject callWebScriptMethod:withArguments:]):
  • bindings/scripts/CodeGeneratorJS.pm:
  • bridge/NP_jsobject.cpp: (_NPN_InvokeDefault): (_NPN_Invoke):
  • bridge/c/c_instance.cpp: (KJS::Bindings::CInstance::supportsInvokeDefaultMethod):
  • bridge/c/c_instance.h:
  • bridge/jni/jni_jsobject.mm: (JavaJSObject::call):
  • bridge/objc/objc_instance.h:
  • bridge/objc/objc_instance.mm: (ObjcInstance::supportsInvokeDefaultMethod):
  • bridge/objc/objc_runtime.h: (KJS::Bindings::ObjcFallbackObjectImp::propertyName): (KJS::Bindings::ObjcFallbackObjectImp::classInfo):
  • bridge/objc/objc_runtime.mm: (Bindings::webScriptObjectClass): (Bindings::webUndefinedClass): (ObjcFallbackObjectImp::ObjcFallbackObjectImp): (callObjCFallbackObject): (ObjcFallbackObjectImp::getCallData):
  • bridge/qt/qt_instance.h:
  • bridge/runtime.cpp: (KJS::Bindings::Instance::createRuntimeObject): (KJS::Bindings::Instance::getInstance):
  • bridge/runtime.h: (KJS::Bindings::Field::~Field): (KJS::Bindings::Method::~Method): (KJS::Bindings::Class::~Class): (KJS::Bindings::Instance::supportsInvokeDefaultMethod):
  • bridge/runtime_method.cpp: (KJS::callRuntimeMethod): (KJS::RuntimeMethod::getCallData):
  • bridge/runtime_method.h: (KJS::RuntimeMethod::methods):
  • bridge/runtime_object.cpp: (RuntimeObjectImp::defaultValue): (callRuntimeObject): (RuntimeObjectImp::getCallData):
  • bridge/runtime_object.h: (KJS::RuntimeObjectImp::getInternalInstance): (KJS::RuntimeObjectImp::classInfo):
  • dom/NodeIterator.h:
  • dom/Traversal.cpp:
  • dom/Traversal.h:
  • dom/TreeWalker.h:
  • Property svn:eol-style set to native
File size: 19.0 KB
Line 
1/*
2 * Copyright (C) 1999-2000 Harri Porten ([email protected])
3 * Copyright (C) 2003, 2007, 2008 Apple Inc. All Rights Reserved.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 */
20
21#include "config.h"
22#include "RegExpObject.h"
23#include "RegExpObject.lut.h"
24
25#include "JSArray.h"
26#include "ArrayPrototype.h"
27#include "error_object.h"
28#include "JSString.h"
29#include "JSObject.h"
30#include "operations.h"
31#include "regexp.h"
32#include "JSValue.h"
33#include "UnusedParam.h"
34
35#include <stdio.h>
36
37namespace KJS {
38
39// ------------------------------ RegExpPrototype ---------------------------
40
41static JSValue* regExpProtoFuncTest(ExecState*, JSObject*, JSValue*, const ArgList&);
42static JSValue* regExpProtoFuncExec(ExecState*, JSObject*, JSValue*, const ArgList&);
43static JSValue* regExpProtoFuncCompile(ExecState*, JSObject*, JSValue*, const ArgList&);
44static JSValue* regExpProtoFuncToString(ExecState*, JSObject*, JSValue*, const ArgList&);
45
46// ECMA 15.10.5
47
48const ClassInfo RegExpPrototype::info = { "RegExpPrototype", 0, 0, 0 };
49
50RegExpPrototype::RegExpPrototype(ExecState* exec, ObjectPrototype* objectPrototype, FunctionPrototype* functionPrototype)
51 : JSObject(objectPrototype)
52{
53 putDirectFunction(new (exec) PrototypeFunction(exec, functionPrototype, 0, exec->propertyNames().compile, regExpProtoFuncCompile), DontEnum);
54 putDirectFunction(new (exec) PrototypeFunction(exec, functionPrototype, 0, exec->propertyNames().exec, regExpProtoFuncExec), DontEnum);
55 putDirectFunction(new (exec) PrototypeFunction(exec, functionPrototype, 0, exec->propertyNames().test, regExpProtoFuncTest), DontEnum);
56 putDirectFunction(new (exec) PrototypeFunction(exec, functionPrototype, 0, exec->propertyNames().toString, regExpProtoFuncToString), DontEnum);
57}
58
59// ------------------------------ Functions ---------------------------
60
61JSValue* regExpProtoFuncTest(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
62{
63 if (!thisValue->isObject(&RegExpObject::info))
64 return throwError(exec, TypeError);
65 return static_cast<RegExpObject*>(thisValue)->test(exec, args);
66}
67
68JSValue* regExpProtoFuncExec(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
69{
70 if (!thisValue->isObject(&RegExpObject::info))
71 return throwError(exec, TypeError);
72 return static_cast<RegExpObject*>(thisValue)->exec(exec, args);
73}
74
75JSValue* regExpProtoFuncCompile(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
76{
77 if (!thisValue->isObject(&RegExpObject::info))
78 return throwError(exec, TypeError);
79
80 RefPtr<RegExp> regExp;
81 JSValue* arg0 = args[0];
82 JSValue* arg1 = args[1];
83
84 if (arg0->isObject(&RegExpObject::info)) {
85 if (!arg1->isUndefined())
86 return throwError(exec, TypeError, "Cannot supply flags when constructing one RegExp from another.");
87 regExp = static_cast<RegExpObject*>(arg0)->regExp();
88 } else {
89 UString pattern = args.isEmpty() ? UString("") : arg0->toString(exec);
90 UString flags = arg1->isUndefined() ? UString("") : arg1->toString(exec);
91 regExp = RegExp::create(pattern, flags);
92 }
93
94 if (!regExp->isValid())
95 return throwError(exec, SyntaxError, UString("Invalid regular expression: ").append(regExp->errorMessage()));
96
97 static_cast<RegExpObject*>(thisValue)->setRegExp(regExp.release());
98 static_cast<RegExpObject*>(thisValue)->setLastIndex(0);
99 return jsUndefined();
100}
101
102JSValue* regExpProtoFuncToString(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList&)
103{
104 if (!thisValue->isObject(&RegExpObject::info)) {
105 if (thisValue->isObject(&RegExpPrototype::info))
106 return jsString(exec, "//");
107 return throwError(exec, TypeError);
108 }
109
110 UString result = "/" + static_cast<RegExpObject*>(thisValue)->get(exec, exec->propertyNames().source)->toString(exec) + "/";
111 if (static_cast<RegExpObject*>(thisValue)->get(exec, exec->propertyNames().global)->toBoolean(exec))
112 result += "g";
113 if (static_cast<RegExpObject*>(thisValue)->get(exec, exec->propertyNames().ignoreCase)->toBoolean(exec))
114 result += "i";
115 if (static_cast<RegExpObject*>(thisValue)->get(exec, exec->propertyNames().multiline)->toBoolean(exec))
116 result += "m";
117 return jsString(exec, result);
118}
119
120// ------------------------------ RegExpObject ------------------------------------
121
122const ClassInfo RegExpObject::info = { "RegExp", 0, 0, ExecState::regExpTable };
123
124/* Source for RegExpObject.lut.h
125@begin regExpTable
126 global RegExpObject::Global DontDelete|ReadOnly|DontEnum
127 ignoreCase RegExpObject::IgnoreCase DontDelete|ReadOnly|DontEnum
128 multiline RegExpObject::Multiline DontDelete|ReadOnly|DontEnum
129 source RegExpObject::Source DontDelete|ReadOnly|DontEnum
130 lastIndex RegExpObject::LastIndex DontDelete|DontEnum
131@end
132*/
133
134RegExpObject::RegExpObject(RegExpPrototype* regexpProto, PassRefPtr<RegExp> regExp)
135 : JSObject(regexpProto)
136 , m_regExp(regExp)
137 , m_lastIndex(0)
138{
139}
140
141RegExpObject::~RegExpObject()
142{
143}
144
145bool RegExpObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
146{
147 return getStaticValueSlot<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), this, propertyName, slot);
148}
149
150JSValue* RegExpObject::getValueProperty(ExecState* exec, int token) const
151{
152 switch (token) {
153 case Global:
154 return jsBoolean(m_regExp->global());
155 case IgnoreCase:
156 return jsBoolean(m_regExp->ignoreCase());
157 case Multiline:
158 return jsBoolean(m_regExp->multiline());
159 case Source:
160 return jsString(exec, m_regExp->pattern());
161 case LastIndex:
162 return jsNumber(exec, m_lastIndex);
163 }
164
165 ASSERT_NOT_REACHED();
166 return 0;
167}
168
169void RegExpObject::put(ExecState* exec, const Identifier& propertyName, JSValue* value)
170{
171 lookupPut<RegExpObject, JSObject>(exec, propertyName, value, ExecState::regExpTable(exec), this);
172}
173
174void RegExpObject::putValueProperty(ExecState* exec, int token, JSValue* value)
175{
176 UNUSED_PARAM(token);
177 ASSERT(token == LastIndex);
178 m_lastIndex = value->toInteger(exec);
179}
180
181bool RegExpObject::match(ExecState* exec, const ArgList& args)
182{
183 RegExpConstructor* regExpObj = exec->lexicalGlobalObject()->regExpConstructor();
184
185 UString input;
186 if (!args.isEmpty())
187 input = args[0]->toString(exec);
188 else {
189 input = regExpObj->input();
190 if (input.isNull()) {
191 throwError(exec, GeneralError, "No input.");
192 return false;
193 }
194 }
195
196 bool global = get(exec, exec->propertyNames().global)->toBoolean(exec);
197 int lastIndex = 0;
198 if (global) {
199 if (m_lastIndex < 0 || m_lastIndex > input.size()) {
200 m_lastIndex = 0;
201 return false;
202 }
203 lastIndex = static_cast<int>(m_lastIndex);
204 }
205
206 int foundIndex;
207 int foundLength;
208 regExpObj->performMatch(m_regExp.get(), input, lastIndex, foundIndex, foundLength);
209
210 if (global) {
211 lastIndex = foundIndex < 0 ? 0 : foundIndex + foundLength;
212 m_lastIndex = lastIndex;
213 }
214
215 return foundIndex >= 0;
216}
217
218JSValue* RegExpObject::test(ExecState* exec, const ArgList& args)
219{
220 return jsBoolean(match(exec, args));
221}
222
223JSValue* RegExpObject::exec(ExecState* exec, const ArgList& args)
224{
225 return match(exec, args)
226 ? exec->lexicalGlobalObject()->regExpConstructor()->arrayOfMatches(exec)
227 : jsNull();
228}
229
230static JSValue* callRegExpObject(ExecState* exec, JSObject* function, JSValue*, const ArgList& args)
231{
232 return static_cast<RegExpObject*>(function)->exec(exec, args);
233}
234
235CallType RegExpObject::getCallData(CallData& callData)
236{
237 callData.native.function = callRegExpObject;
238 return CallTypeNative;
239}
240
241// ------------------------------ RegExpConstructor ------------------------------
242
243const ClassInfo RegExpConstructor::info = { "Function", &InternalFunction::info, 0, ExecState::regExpConstructorTable };
244
245/* Source for RegExpObject.lut.h
246@begin regExpConstructorTable
247 input RegExpConstructor::Input None
248 $_ RegExpConstructor::Input DontEnum
249 multiline RegExpConstructor::Multiline None
250 $* RegExpConstructor::Multiline DontEnum
251 lastMatch RegExpConstructor::LastMatch DontDelete|ReadOnly
252 $& RegExpConstructor::LastMatch DontDelete|ReadOnly|DontEnum
253 lastParen RegExpConstructor::LastParen DontDelete|ReadOnly
254 $+ RegExpConstructor::LastParen DontDelete|ReadOnly|DontEnum
255 leftContext RegExpConstructor::LeftContext DontDelete|ReadOnly
256 $` RegExpConstructor::LeftContext DontDelete|ReadOnly|DontEnum
257 rightContext RegExpConstructor::RightContext DontDelete|ReadOnly
258 $' RegExpConstructor::RightContext DontDelete|ReadOnly|DontEnum
259 $1 RegExpConstructor::Dollar1 DontDelete|ReadOnly
260 $2 RegExpConstructor::Dollar2 DontDelete|ReadOnly
261 $3 RegExpConstructor::Dollar3 DontDelete|ReadOnly
262 $4 RegExpConstructor::Dollar4 DontDelete|ReadOnly
263 $5 RegExpConstructor::Dollar5 DontDelete|ReadOnly
264 $6 RegExpConstructor::Dollar6 DontDelete|ReadOnly
265 $7 RegExpConstructor::Dollar7 DontDelete|ReadOnly
266 $8 RegExpConstructor::Dollar8 DontDelete|ReadOnly
267 $9 RegExpConstructor::Dollar9 DontDelete|ReadOnly
268@end
269*/
270
271struct RegExpConstructorPrivate {
272 // Global search cache / settings
273 RegExpConstructorPrivate() : lastNumSubPatterns(0), multiline(false) { }
274 UString lastInput;
275 OwnArrayPtr<int> lastOvector;
276 unsigned lastNumSubPatterns : 31;
277 bool multiline : 1;
278};
279
280RegExpConstructor::RegExpConstructor(ExecState* exec, FunctionPrototype* funcProto, RegExpPrototype* regProto)
281 : InternalFunction(funcProto, Identifier(exec, "RegExp"))
282 , d(new RegExpConstructorPrivate)
283{
284 // ECMA 15.10.5.1 RegExp.prototype
285 putDirect(exec->propertyNames().prototype, regProto, DontEnum | DontDelete | ReadOnly);
286
287 // no. of arguments for constructor
288 putDirect(exec->propertyNames().length, jsNumber(exec, 2), ReadOnly | DontDelete | DontEnum);
289}
290
291/*
292 To facilitate result caching, exec(), test(), match(), search(), and replace() dipatch regular
293 expression matching through the performMatch function. We use cached results to calculate,
294 e.g., RegExp.lastMatch and RegExp.leftParen.
295*/
296void RegExpConstructor::performMatch(RegExp* r, const UString& s, int startOffset, int& position, int& length, int** ovector)
297{
298 OwnArrayPtr<int> tmpOvector;
299 position = r->match(s, startOffset, &tmpOvector);
300
301 if (ovector)
302 *ovector = tmpOvector.get();
303
304 if (position != -1) {
305 ASSERT(tmpOvector);
306
307 length = tmpOvector[1] - tmpOvector[0];
308
309 d->lastInput = s;
310 d->lastOvector.set(tmpOvector.release());
311 d->lastNumSubPatterns = r->numSubpatterns();
312 }
313}
314
315class RegExpMatchesArray : public JSArray {
316public:
317 RegExpMatchesArray(ExecState*, RegExpConstructorPrivate*);
318 virtual ~RegExpMatchesArray();
319
320private:
321 virtual bool getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { if (lazyCreationData()) fillArrayInstance(exec); return JSArray::getOwnPropertySlot(exec, propertyName, slot); }
322 virtual bool getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot) { if (lazyCreationData()) fillArrayInstance(exec); return JSArray::getOwnPropertySlot(exec, propertyName, slot); }
323 virtual void put(ExecState* exec, const Identifier& propertyName, JSValue* v) { if (lazyCreationData()) fillArrayInstance(exec); JSArray::put(exec, propertyName, v); }
324 virtual void put(ExecState* exec, unsigned propertyName, JSValue* v) { if (lazyCreationData()) fillArrayInstance(exec); JSArray::put(exec, propertyName, v); }
325 virtual bool deleteProperty(ExecState* exec, const Identifier& propertyName) { if (lazyCreationData()) fillArrayInstance(exec); return JSArray::deleteProperty(exec, propertyName); }
326 virtual bool deleteProperty(ExecState* exec, unsigned propertyName) { if (lazyCreationData()) fillArrayInstance(exec); return JSArray::deleteProperty(exec, propertyName); }
327 virtual void getPropertyNames(ExecState* exec, PropertyNameArray& arr) { if (lazyCreationData()) fillArrayInstance(exec); JSArray::getPropertyNames(exec, arr); }
328
329 void fillArrayInstance(ExecState*);
330};
331
332RegExpMatchesArray::RegExpMatchesArray(ExecState* exec, RegExpConstructorPrivate* data)
333 : JSArray(exec->lexicalGlobalObject()->arrayPrototype(), data->lastNumSubPatterns + 1)
334{
335 RegExpConstructorPrivate* d = new RegExpConstructorPrivate;
336 d->lastInput = data->lastInput;
337 d->lastNumSubPatterns = data->lastNumSubPatterns;
338 unsigned offsetVectorSize = (data->lastNumSubPatterns + 1) * 2; // only copying the result part of the vector
339 d->lastOvector.set(new int[offsetVectorSize]);
340 memcpy(d->lastOvector.get(), data->lastOvector.get(), offsetVectorSize * sizeof(int));
341 // d->multiline is not needed, and remains uninitialized
342
343 setLazyCreationData(d);
344}
345
346RegExpMatchesArray::~RegExpMatchesArray()
347{
348 delete static_cast<RegExpConstructorPrivate*>(lazyCreationData());
349}
350
351void RegExpMatchesArray::fillArrayInstance(ExecState* exec)
352{
353 RegExpConstructorPrivate* d = static_cast<RegExpConstructorPrivate*>(lazyCreationData());
354 ASSERT(d);
355
356 unsigned lastNumSubpatterns = d->lastNumSubPatterns;
357
358 for (unsigned i = 0; i <= lastNumSubpatterns; ++i) {
359 int start = d->lastOvector[2 * i];
360 if (start >= 0)
361 JSArray::put(exec, i, jsString(exec, d->lastInput.substr(start, d->lastOvector[2 * i + 1] - start)));
362 }
363 JSArray::put(exec, exec->propertyNames().index, jsNumber(exec, d->lastOvector[0]));
364 JSArray::put(exec, exec->propertyNames().input, jsString(exec, d->lastInput));
365
366 delete d;
367 setLazyCreationData(0);
368}
369
370JSObject* RegExpConstructor::arrayOfMatches(ExecState* exec) const
371{
372 return new (exec) RegExpMatchesArray(exec, d.get());
373}
374
375JSValue* RegExpConstructor::getBackref(ExecState* exec, unsigned i) const
376{
377 if (d->lastOvector && i <= d->lastNumSubPatterns)
378 return jsString(exec, d->lastInput.substr(d->lastOvector[2 * i], d->lastOvector[2 * i + 1] - d->lastOvector[2 * i]));
379 return jsString(exec, "");
380}
381
382JSValue* RegExpConstructor::getLastParen(ExecState* exec) const
383{
384 unsigned i = d->lastNumSubPatterns;
385 if (i > 0) {
386 ASSERT(d->lastOvector);
387 return jsString(exec, d->lastInput.substr(d->lastOvector[2 * i], d->lastOvector[2 * i + 1] - d->lastOvector[2 * i]));
388 }
389 return jsString(exec, "");
390}
391
392JSValue* RegExpConstructor::getLeftContext(ExecState* exec) const
393{
394 if (d->lastOvector)
395 return jsString(exec, d->lastInput.substr(0, d->lastOvector[0]));
396 return jsString(exec, "");
397}
398
399JSValue* RegExpConstructor::getRightContext(ExecState* exec) const
400{
401 if (d->lastOvector) {
402 UString s = d->lastInput;
403 return jsString(exec, s.substr(d->lastOvector[1], s.size() - d->lastOvector[1]));
404 }
405 return jsString(exec, "");
406}
407
408bool RegExpConstructor::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
409{
410 return getStaticValueSlot<RegExpConstructor, InternalFunction>(exec, ExecState::regExpConstructorTable(exec), this, propertyName, slot);
411}
412
413JSValue *RegExpConstructor::getValueProperty(ExecState* exec, int token) const
414{
415 switch (token) {
416 case Dollar1:
417 return getBackref(exec, 1);
418 case Dollar2:
419 return getBackref(exec, 2);
420 case Dollar3:
421 return getBackref(exec, 3);
422 case Dollar4:
423 return getBackref(exec, 4);
424 case Dollar5:
425 return getBackref(exec, 5);
426 case Dollar6:
427 return getBackref(exec, 6);
428 case Dollar7:
429 return getBackref(exec, 7);
430 case Dollar8:
431 return getBackref(exec, 8);
432 case Dollar9:
433 return getBackref(exec, 9);
434 case Input:
435 return jsString(exec, d->lastInput);
436 case Multiline:
437 return jsBoolean(d->multiline);
438 case LastMatch:
439 return getBackref(exec, 0);
440 case LastParen:
441 return getLastParen(exec);
442 case LeftContext:
443 return getLeftContext(exec);
444 case RightContext:
445 return getRightContext(exec);
446 default:
447 ASSERT_NOT_REACHED();
448 }
449
450 return jsString(exec, "");
451}
452
453void RegExpConstructor::put(ExecState *exec, const Identifier &propertyName, JSValue *value)
454{
455 lookupPut<RegExpConstructor, InternalFunction>(exec, propertyName, value, ExecState::regExpConstructorTable(exec), this);
456}
457
458void RegExpConstructor::putValueProperty(ExecState *exec, int token, JSValue *value)
459{
460 switch (token) {
461 case Input:
462 d->lastInput = value->toString(exec);
463 break;
464 case Multiline:
465 d->multiline = value->toBoolean(exec);
466 break;
467 default:
468 ASSERT(0);
469 }
470}
471
472// ECMA 15.10.4
473static JSObject* constructRegExp(ExecState* exec, const ArgList& args)
474{
475 JSValue* arg0 = args[0];
476 JSValue* arg1 = args[1];
477
478 if (arg0->isObject(&RegExpObject::info)) {
479 if (!arg1->isUndefined())
480 return throwError(exec, TypeError, "Cannot supply flags when constructing one RegExp from another.");
481 return static_cast<JSObject*>(arg0);
482 }
483
484 UString pattern = arg0->isUndefined() ? UString("") : arg0->toString(exec);
485 UString flags = arg1->isUndefined() ? UString("") : arg1->toString(exec);
486
487 RefPtr<RegExp> regExp = RegExp::create(pattern, flags);
488 return regExp->isValid()
489 ? new (exec) RegExpObject(exec->lexicalGlobalObject()->regExpPrototype(), regExp.release())
490 : throwError(exec, SyntaxError, UString("Invalid regular expression: ").append(regExp->errorMessage()));
491}
492
493static JSObject* constructWithRegExpConstructor(ExecState* exec, JSObject*, const ArgList& args)
494{
495 return constructRegExp(exec, args);
496}
497
498ConstructType RegExpConstructor::getConstructData(ConstructData& constructData)
499{
500 constructData.native.function = constructWithRegExpConstructor;
501 return ConstructTypeNative;
502}
503
504// ECMA 15.10.3
505static JSValue* callRegExpConstructor(ExecState* exec, JSObject*, JSValue*, const ArgList& args)
506{
507 return constructRegExp(exec, args);
508}
509
510CallType RegExpConstructor::getCallData(CallData& callData)
511{
512 callData.native.function = callRegExpConstructor;
513 return CallTypeNative;
514}
515
516const UString& RegExpConstructor::input() const
517{
518 // Can detect a distinct initial state that is invisible to JavaScript, by checking for null
519 // state (since jsString turns null strings to empty strings).
520 return d->lastInput;
521}
522
523}
Note: See TracBrowser for help on using the repository browser.