source: webkit/trunk/JavaScriptCore/kjs/JSObject.cpp@ 34754

Last change on this file since 34754 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: 16.5 KB
Line 
1// -*- c-basic-offset: 2 -*-
2/*
3 * Copyright (C) 1999-2001 Harri Porten ([email protected])
4 * Copyright (C) 2001 Peter Kelly ([email protected])
5 * Copyright (C) 2003, 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.
6 * Copyright (C) 2007 Eric Seidel ([email protected])
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 *
23 */
24
25#include "config.h"
26#include "JSObject.h"
27
28#include "date_object.h"
29#include "error_object.h"
30#include "nodes.h"
31#include "operations.h"
32#include "PropertyNameArray.h"
33#include <math.h>
34#include <profiler/Profiler.h>
35#include <wtf/Assertions.h>
36
37#define JAVASCRIPT_MARK_TRACING 0
38
39namespace KJS {
40
41// ------------------------------ JSObject ------------------------------------
42
43void JSObject::mark()
44{
45 JSCell::mark();
46
47#if JAVASCRIPT_MARK_TRACING
48 static int markStackDepth = 0;
49 markStackDepth++;
50 for (int i = 0; i < markStackDepth; i++)
51 putchar('-');
52
53 printf("%s (%p)\n", className().UTF8String().c_str(), this);
54#endif
55
56 JSValue *proto = _proto;
57 if (!proto->marked())
58 proto->mark();
59
60 _prop.mark();
61
62#if JAVASCRIPT_MARK_TRACING
63 markStackDepth--;
64#endif
65}
66
67JSType JSObject::type() const
68{
69 return ObjectType;
70}
71
72UString JSObject::className() const
73{
74 const ClassInfo *ci = classInfo();
75 if ( ci )
76 return ci->className;
77 return "Object";
78}
79
80bool JSObject::getOwnPropertySlot(ExecState *exec, unsigned propertyName, PropertySlot& slot)
81{
82 return getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot);
83}
84
85static void throwSetterError(ExecState *exec)
86{
87 throwError(exec, TypeError, "setting a property that has only a getter");
88}
89
90// ECMA 8.6.2.2
91void JSObject::put(ExecState* exec, const Identifier& propertyName, JSValue* value)
92{
93 ASSERT(value);
94 ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
95
96 if (propertyName == exec->propertyNames().underscoreProto) {
97 JSObject* proto = value->getObject();
98
99 // Setting __proto__ to a non-object, non-null value is silently ignored to match Mozilla.
100 if (!proto && value != jsNull())
101 return;
102
103 while (proto) {
104 if (proto == this) {
105 throwError(exec, GeneralError, "cyclic __proto__ value");
106 return;
107 }
108 proto = proto->prototype() ? proto->prototype()->getObject() : 0;
109 }
110
111 setPrototype(value);
112 return;
113 }
114
115 // Check if there are any setters or getters in the prototype chain
116 JSObject* obj;
117 JSValue* prototype;
118 for (obj = this; !obj->_prop.hasGetterSetterProperties(); obj = static_cast<JSObject*>(prototype)) {
119 prototype = obj->_proto;
120 if (prototype == jsNull()) {
121 _prop.put(propertyName, value, 0, true);
122 return;
123 }
124 }
125
126 unsigned attributes;
127 if (_prop.get(propertyName, attributes) && attributes & ReadOnly)
128 return;
129
130 for (; ; obj = static_cast<JSObject*>(prototype)) {
131 if (JSValue* gs = obj->_prop.get(propertyName, attributes)) {
132 if (attributes & IsGetterSetter) {
133 JSObject* setterFunc = static_cast<GetterSetter*>(gs)->setter();
134 if (!setterFunc) {
135 throwSetterError(exec);
136 return;
137 }
138
139 CallData callData;
140 CallType callType = setterFunc->getCallData(callData);
141 ArgList args;
142 args.append(value);
143 call(exec, setterFunc, callType, callData, this, args);
144 return;
145 }
146
147 // If there's an existing property on the object or one of its
148 // prototypes it should be replaced, so break here.
149 break;
150 }
151
152 prototype = obj->_proto;
153 if (prototype == jsNull())
154 break;
155 }
156
157 _prop.put(propertyName, value, 0, true);
158}
159
160void JSObject::put(ExecState* exec, unsigned propertyName, JSValue* value)
161{
162 put(exec, Identifier::from(exec, propertyName), value);
163}
164
165void JSObject::putWithAttributes(ExecState*, const Identifier& propertyName, JSValue* value, unsigned attributes)
166{
167 putDirect(propertyName, value, attributes);
168}
169
170void JSObject::putWithAttributes(ExecState* exec, unsigned propertyName, JSValue* value, unsigned attributes)
171{
172 putWithAttributes(exec, Identifier::from(exec, propertyName), value, attributes);
173}
174
175bool JSObject::hasProperty(ExecState *exec, const Identifier &propertyName) const
176{
177 PropertySlot slot;
178 return const_cast<JSObject *>(this)->getPropertySlot(exec, propertyName, slot);
179}
180
181bool JSObject::hasProperty(ExecState *exec, unsigned propertyName) const
182{
183 PropertySlot slot;
184 return const_cast<JSObject *>(this)->getPropertySlot(exec, propertyName, slot);
185}
186
187// ECMA 8.6.2.5
188bool JSObject::deleteProperty(ExecState* exec, const Identifier &propertyName)
189{
190 unsigned attributes;
191 JSValue *v = _prop.get(propertyName, attributes);
192 if (v) {
193 if ((attributes & DontDelete))
194 return false;
195 _prop.remove(propertyName);
196 if (attributes & IsGetterSetter)
197 _prop.setHasGetterSetterProperties(_prop.containsGettersOrSetters());
198 return true;
199 }
200
201 // Look in the static hashtable of properties
202 const HashEntry* entry = findPropertyHashEntry(exec, propertyName);
203 if (entry && entry->attributes & DontDelete)
204 return false; // this builtin property can't be deleted
205 // FIXME: Should the code here actually do some deletion?
206 return true;
207}
208
209bool JSObject::hasOwnProperty(ExecState* exec, const Identifier& propertyName) const
210{
211 PropertySlot slot;
212 return const_cast<JSObject*>(this)->getOwnPropertySlot(exec, propertyName, slot);
213}
214
215bool JSObject::deleteProperty(ExecState *exec, unsigned propertyName)
216{
217 return deleteProperty(exec, Identifier::from(exec, propertyName));
218}
219
220static ALWAYS_INLINE JSValue* callDefaultValueFunction(ExecState* exec, const JSObject* object, const Identifier& propertyName)
221{
222 JSValue* function = object->get(exec, propertyName);
223 CallData callData;
224 CallType callType = function->getCallData(callData);
225 if (callType == CallTypeNone)
226 return 0;
227 JSValue* result = call(exec, function, callType, callData, const_cast<JSObject*>(object), exec->emptyList());
228 ASSERT(result->type() != GetterSetterType);
229 if (exec->hadException())
230 return exec->exception();
231 if (result->isObject())
232 return 0;
233 return result;
234}
235
236bool JSObject::getPrimitiveNumber(ExecState* exec, double& number, JSValue*& result)
237{
238 result = defaultValue(exec, NumberType);
239 number = result->toNumber(exec);
240 return !result->isString();
241}
242
243// ECMA 8.6.2.6
244JSValue* JSObject::defaultValue(ExecState* exec, JSType hint) const
245{
246 // We need this check to guard against the case where this object is rhs of
247 // a binary expression where lhs threw an exception in its conversion to
248 // primitive.
249 if (exec->hadException())
250 return exec->exception();
251
252 // Must call toString first for Date objects.
253 if ((hint == StringType) || (hint != NumberType && _proto == exec->lexicalGlobalObject()->datePrototype())) {
254 if (JSValue* value = callDefaultValueFunction(exec, this, exec->propertyNames().toString))
255 return value;
256 if (JSValue* value = callDefaultValueFunction(exec, this, exec->propertyNames().valueOf))
257 return value;
258 } else {
259 if (JSValue* value = callDefaultValueFunction(exec, this, exec->propertyNames().valueOf))
260 return value;
261 if (JSValue* value = callDefaultValueFunction(exec, this, exec->propertyNames().toString))
262 return value;
263 }
264
265 ASSERT(!exec->hadException());
266
267 return throwError(exec, TypeError, "No default value");
268}
269
270const HashEntry* JSObject::findPropertyHashEntry(ExecState* exec, const Identifier& propertyName) const
271{
272 for (const ClassInfo* info = classInfo(); info; info = info->parentClass) {
273 if (const HashTable* propHashTable = info->propHashTable(exec)) {
274 if (const HashEntry* e = propHashTable->entry(exec, propertyName))
275 return e;
276 }
277 }
278 return 0;
279}
280
281void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunc)
282{
283 JSValue *o = getDirect(propertyName);
284 GetterSetter *gs;
285
286 if (o && o->type() == GetterSetterType) {
287 gs = static_cast<GetterSetter *>(o);
288 } else {
289 gs = new (exec) GetterSetter;
290 putDirect(propertyName, gs, IsGetterSetter);
291 }
292
293 _prop.setHasGetterSetterProperties(true);
294 gs->setGetter(getterFunc);
295}
296
297void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunc)
298{
299 JSValue *o = getDirect(propertyName);
300 GetterSetter *gs;
301
302 if (o && o->type() == GetterSetterType) {
303 gs = static_cast<GetterSetter *>(o);
304 } else {
305 gs = new (exec) GetterSetter;
306 putDirect(propertyName, gs, IsGetterSetter);
307 }
308
309 _prop.setHasGetterSetterProperties(true);
310 gs->setSetter(setterFunc);
311}
312
313JSValue* JSObject::lookupGetter(ExecState*, const Identifier& propertyName)
314{
315 JSObject* obj = this;
316 while (true) {
317 JSValue* v = obj->getDirect(propertyName);
318 if (v) {
319 if (v->type() != GetterSetterType)
320 return jsUndefined();
321 JSObject* funcObj = static_cast<GetterSetter*>(v)->getter();
322 if (!funcObj)
323 return jsUndefined();
324 return funcObj;
325 }
326
327 if (!obj->prototype() || !obj->prototype()->isObject())
328 return jsUndefined();
329 obj = static_cast<JSObject*>(obj->prototype());
330 }
331}
332
333JSValue* JSObject::lookupSetter(ExecState*, const Identifier& propertyName)
334{
335 JSObject* obj = this;
336 while (true) {
337 JSValue* v = obj->getDirect(propertyName);
338 if (v) {
339 if (v->type() != GetterSetterType)
340 return jsUndefined();
341 JSObject* funcObj = static_cast<GetterSetter*>(v)->setter();
342 if (!funcObj)
343 return jsUndefined();
344 return funcObj;
345 }
346
347 if (!obj->prototype() || !obj->prototype()->isObject())
348 return jsUndefined();
349 obj = static_cast<JSObject*>(obj->prototype());
350 }
351}
352
353bool JSObject::implementsHasInstance() const
354{
355 return false;
356}
357
358bool JSObject::hasInstance(ExecState* exec, JSValue* value)
359{
360 JSValue* proto = get(exec, exec->propertyNames().prototype);
361 if (!proto->isObject()) {
362 throwError(exec, TypeError, "instanceof called on an object with an invalid prototype property.");
363 return false;
364 }
365
366 if (!value->isObject())
367 return false;
368
369 JSObject* o = static_cast<JSObject*>(value);
370 while ((o = o->prototype()->getObject())) {
371 if (o == proto)
372 return true;
373 }
374 return false;
375}
376
377bool JSObject::propertyIsEnumerable(ExecState* exec, const Identifier& propertyName) const
378{
379 unsigned attributes;
380
381 if (!getPropertyAttributes(exec, propertyName, attributes))
382 return false;
383 else
384 return !(attributes & DontEnum);
385}
386
387bool JSObject::getPropertyAttributes(ExecState* exec, const Identifier& propertyName, unsigned& attributes) const
388{
389 if (_prop.get(propertyName, attributes))
390 return true;
391
392 // Look in the static hashtable of properties
393 const HashEntry* e = findPropertyHashEntry(exec, propertyName);
394 if (e) {
395 attributes = e->attributes;
396 return true;
397 }
398
399 return false;
400}
401
402void JSObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
403{
404 _prop.getEnumerablePropertyNames(propertyNames);
405
406 // Add properties from the static hashtables of properties
407 for (const ClassInfo* info = classInfo(); info; info = info->parentClass) {
408 const HashTable* table = info->propHashTable(exec);
409 if (!table)
410 continue;
411 table->initializeIfNeeded(exec);
412 ASSERT(table->table);
413 int hashSizeMask = table->hashSizeMask;
414 const HashEntry* e = table->table;
415 for (int i = 0; i <= hashSizeMask; ++i, ++e) {
416 if (e->key && !(e->attributes & DontEnum))
417 propertyNames.add(e->key);
418 }
419 }
420
421 if (_proto->isObject())
422 static_cast<JSObject*>(_proto)->getPropertyNames(exec, propertyNames);
423}
424
425bool JSObject::toBoolean(ExecState*) const
426{
427 return true;
428}
429
430double JSObject::toNumber(ExecState *exec) const
431{
432 JSValue *prim = toPrimitive(exec,NumberType);
433 if (exec->hadException()) // should be picked up soon in nodes.cpp
434 return 0.0;
435 return prim->toNumber(exec);
436}
437
438UString JSObject::toString(ExecState *exec) const
439{
440 JSValue *prim = toPrimitive(exec,StringType);
441 if (exec->hadException()) // should be picked up soon in nodes.cpp
442 return "";
443 return prim->toString(exec);
444}
445
446JSObject *JSObject::toObject(ExecState*) const
447{
448 return const_cast<JSObject*>(this);
449}
450
451JSObject* JSObject::toThisObject(ExecState*) const
452{
453 return const_cast<JSObject*>(this);
454}
455
456JSGlobalObject* JSObject::toGlobalObject(ExecState*) const
457{
458 return 0;
459}
460
461void JSObject::removeDirect(const Identifier &propertyName)
462{
463 _prop.remove(propertyName);
464}
465
466void JSObject::putDirectFunction(InternalFunction* func, int attr)
467{
468 putDirect(func->functionName(), func, attr);
469}
470
471void JSObject::fillGetterPropertySlot(PropertySlot& slot, JSValue** location)
472{
473 if (JSObject* getterFunc = static_cast<GetterSetter*>(*location)->getter())
474 slot.setGetterSlot(getterFunc);
475 else
476 slot.setUndefined();
477}
478
479// ------------------------------ Error ----------------------------------------
480
481JSObject* Error::create(ExecState* exec, ErrorType errtype, const UString& message,
482 int lineno, int sourceId, const UString& sourceURL)
483{
484 JSObject* cons;
485 const char* name;
486 switch (errtype) {
487 case EvalError:
488 cons = exec->lexicalGlobalObject()->evalErrorConstructor();
489 name = "Evaluation error";
490 break;
491 case RangeError:
492 cons = exec->lexicalGlobalObject()->rangeErrorConstructor();
493 name = "Range error";
494 break;
495 case ReferenceError:
496 cons = exec->lexicalGlobalObject()->referenceErrorConstructor();
497 name = "Reference error";
498 break;
499 case SyntaxError:
500 cons = exec->lexicalGlobalObject()->syntaxErrorConstructor();
501 name = "Syntax error";
502 break;
503 case TypeError:
504 cons = exec->lexicalGlobalObject()->typeErrorConstructor();
505 name = "Type error";
506 break;
507 case URIError:
508 cons = exec->lexicalGlobalObject()->URIErrorConstructor();
509 name = "URI error";
510 break;
511 default:
512 cons = exec->lexicalGlobalObject()->errorConstructor();
513 name = "Error";
514 break;
515 }
516
517 ArgList args;
518 if (message.isEmpty())
519 args.append(jsString(exec, name));
520 else
521 args.append(jsString(exec, message));
522 ConstructData constructData;
523 ConstructType constructType = cons->getConstructData(constructData);
524 JSObject* err = construct(exec, cons, constructType, constructData, args);
525
526 if (lineno != -1)
527 err->put(exec, Identifier(exec, "line"), jsNumber(exec, lineno));
528 if (sourceId != -1)
529 err->put(exec, Identifier(exec, "sourceId"), jsNumber(exec, sourceId));
530
531 if(!sourceURL.isNull())
532 err->put(exec, Identifier(exec, "sourceURL"), jsString(exec, sourceURL));
533
534 return err;
535}
536
537JSObject *Error::create(ExecState *exec, ErrorType type, const char *message)
538{
539 return create(exec, type, message, -1, -1, NULL);
540}
541
542JSObject *throwError(ExecState *exec, ErrorType type)
543{
544 JSObject *error = Error::create(exec, type, UString(), -1, -1, NULL);
545 exec->setException(error);
546 return error;
547}
548
549JSObject *throwError(ExecState *exec, ErrorType type, const UString &message)
550{
551 JSObject *error = Error::create(exec, type, message, -1, -1, NULL);
552 exec->setException(error);
553 return error;
554}
555
556JSObject *throwError(ExecState *exec, ErrorType type, const char *message)
557{
558 JSObject *error = Error::create(exec, type, message, -1, -1, NULL);
559 exec->setException(error);
560 return error;
561}
562
563JSObject *throwError(ExecState *exec, ErrorType type, const UString &message, int line, int sourceId, const UString &sourceURL)
564{
565 JSObject *error = Error::create(exec, type, message, line, sourceId, sourceURL);
566 exec->setException(error);
567 return error;
568}
569
570JSObject* constructEmptyObject(ExecState* exec)
571{
572 return new (exec) JSObject(exec->lexicalGlobalObject()->objectPrototype());
573}
574
575} // namespace KJS
Note: See TracBrowser for help on using the repository browser.