summaryrefslogtreecommitdiffstats
path: root/WebCore/bindings
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/bindings')
-rw-r--r--WebCore/bindings/js/DOMObjectWithSVGContext.h2
-rw-r--r--WebCore/bindings/js/JSAbstractWorkerCustom.cpp31
-rw-r--r--WebCore/bindings/js/JSAttrCustom.cpp17
-rw-r--r--WebCore/bindings/js/JSAudioConstructor.cpp1
-rw-r--r--WebCore/bindings/js/JSCSSRuleListCustom.cpp47
-rw-r--r--WebCore/bindings/js/JSCSSStyleDeclarationCustom.cpp19
-rw-r--r--WebCore/bindings/js/JSCallbackData.cpp77
-rw-r--r--WebCore/bindings/js/JSCallbackData.h70
-rw-r--r--WebCore/bindings/js/JSCanvasArrayBufferConstructor.cpp70
-rw-r--r--WebCore/bindings/js/JSCanvasArrayBufferConstructor.h97
-rw-r--r--WebCore/bindings/js/JSCanvasArrayCustom.cpp56
-rw-r--r--WebCore/bindings/js/JSCanvasByteArrayConstructor.cpp67
-rw-r--r--WebCore/bindings/js/JSCanvasByteArrayConstructor.h (renamed from WebCore/bindings/js/JSNamedNodesCollection.h)40
-rw-r--r--WebCore/bindings/js/JSCanvasByteArrayCustom.cpp50
-rw-r--r--WebCore/bindings/js/JSCanvasFloatArrayConstructor.cpp67
-rw-r--r--WebCore/bindings/js/JSCanvasFloatArrayConstructor.h46
-rw-r--r--WebCore/bindings/js/JSCanvasFloatArrayCustom.cpp50
-rw-r--r--WebCore/bindings/js/JSCanvasIntArrayConstructor.cpp67
-rw-r--r--WebCore/bindings/js/JSCanvasIntArrayConstructor.h46
-rw-r--r--WebCore/bindings/js/JSCanvasIntArrayCustom.cpp50
-rw-r--r--WebCore/bindings/js/JSCanvasNumberArrayCustom.cpp46
-rw-r--r--WebCore/bindings/js/JSCanvasRenderingContext2DCustom.cpp32
-rw-r--r--WebCore/bindings/js/JSCanvasRenderingContext3DCustom.cpp443
-rw-r--r--WebCore/bindings/js/JSCanvasRenderingContextCustom.cpp53
-rw-r--r--WebCore/bindings/js/JSCanvasShortArrayConstructor.cpp68
-rw-r--r--WebCore/bindings/js/JSCanvasShortArrayConstructor.h46
-rw-r--r--WebCore/bindings/js/JSCanvasShortArrayCustom.cpp50
-rw-r--r--WebCore/bindings/js/JSCanvasUnsignedByteArrayConstructor.cpp67
-rw-r--r--WebCore/bindings/js/JSCanvasUnsignedByteArrayConstructor.h46
-rw-r--r--WebCore/bindings/js/JSCanvasUnsignedByteArrayCustom.cpp50
-rw-r--r--WebCore/bindings/js/JSCanvasUnsignedIntArrayConstructor.cpp67
-rw-r--r--WebCore/bindings/js/JSCanvasUnsignedIntArrayConstructor.h46
-rw-r--r--WebCore/bindings/js/JSCanvasUnsignedIntArrayCustom.cpp50
-rw-r--r--WebCore/bindings/js/JSCanvasUnsignedShortArrayConstructor.cpp67
-rw-r--r--WebCore/bindings/js/JSCanvasUnsignedShortArrayConstructor.h46
-rw-r--r--WebCore/bindings/js/JSCanvasUnsignedShortArrayCustom.cpp50
-rw-r--r--WebCore/bindings/js/JSCustomPositionCallback.cpp42
-rw-r--r--WebCore/bindings/js/JSCustomPositionCallback.h23
-rw-r--r--WebCore/bindings/js/JSCustomPositionErrorCallback.cpp40
-rw-r--r--WebCore/bindings/js/JSCustomPositionErrorCallback.h23
-rw-r--r--WebCore/bindings/js/JSCustomSQLStatementCallback.cpp53
-rw-r--r--WebCore/bindings/js/JSCustomSQLStatementCallback.h21
-rw-r--r--WebCore/bindings/js/JSCustomSQLStatementErrorCallback.cpp66
-rw-r--r--WebCore/bindings/js/JSCustomSQLStatementErrorCallback.h25
-rw-r--r--WebCore/bindings/js/JSCustomSQLTransactionCallback.cpp75
-rw-r--r--WebCore/bindings/js/JSCustomSQLTransactionCallback.h15
-rw-r--r--WebCore/bindings/js/JSCustomSQLTransactionErrorCallback.cpp55
-rw-r--r--WebCore/bindings/js/JSCustomSQLTransactionErrorCallback.h21
-rw-r--r--WebCore/bindings/js/JSCustomVoidCallback.cpp66
-rw-r--r--WebCore/bindings/js/JSCustomVoidCallback.h38
-rw-r--r--WebCore/bindings/js/JSCustomXPathNSResolver.cpp22
-rw-r--r--WebCore/bindings/js/JSCustomXPathNSResolver.h8
-rw-r--r--WebCore/bindings/js/JSDOMApplicationCacheCustom.cpp38
-rw-r--r--WebCore/bindings/js/JSDOMBinding.cpp82
-rw-r--r--WebCore/bindings/js/JSDOMBinding.h27
-rw-r--r--WebCore/bindings/js/JSDOMGlobalObject.cpp47
-rw-r--r--WebCore/bindings/js/JSDOMGlobalObject.h33
-rw-r--r--WebCore/bindings/js/JSDOMWindowBase.cpp18
-rw-r--r--WebCore/bindings/js/JSDOMWindowBase.h11
-rw-r--r--WebCore/bindings/js/JSDOMWindowCustom.cpp332
-rw-r--r--WebCore/bindings/js/JSDOMWindowShell.cpp23
-rw-r--r--WebCore/bindings/js/JSDOMWindowShell.h7
-rw-r--r--WebCore/bindings/js/JSDatabaseCustom.cpp46
-rw-r--r--WebCore/bindings/js/JSDedicatedWorkerContextCustom.cpp9
-rw-r--r--WebCore/bindings/js/JSDesktopNotificationsCustom.cpp95
-rw-r--r--WebCore/bindings/js/JSDocumentCustom.cpp18
-rw-r--r--WebCore/bindings/js/JSElementCustom.cpp20
-rw-r--r--WebCore/bindings/js/JSEventCustom.cpp4
-rw-r--r--WebCore/bindings/js/JSEventListener.cpp77
-rw-r--r--WebCore/bindings/js/JSEventListener.h24
-rw-r--r--WebCore/bindings/js/JSEventSourceConstructor.cpp91
-rw-r--r--WebCore/bindings/js/JSEventSourceConstructor.h55
-rw-r--r--WebCore/bindings/js/JSEventSourceCustom.cpp76
-rw-r--r--WebCore/bindings/js/JSEventTarget.cpp54
-rw-r--r--WebCore/bindings/js/JSGeolocationCustom.cpp33
-rw-r--r--WebCore/bindings/js/JSHTMLAllCollection.h2
-rw-r--r--WebCore/bindings/js/JSHTMLAppletElementCustom.cpp5
-rw-r--r--WebCore/bindings/js/JSHTMLCanvasElementCustom.cpp50
-rw-r--r--WebCore/bindings/js/JSHTMLCollectionCustom.cpp11
-rw-r--r--WebCore/bindings/js/JSHTMLEmbedElementCustom.cpp5
-rw-r--r--WebCore/bindings/js/JSHTMLFormElementCustom.cpp13
-rw-r--r--WebCore/bindings/js/JSHTMLFrameElementCustom.cpp10
-rw-r--r--WebCore/bindings/js/JSHTMLIFrameElementCustom.cpp8
-rw-r--r--WebCore/bindings/js/JSHTMLInputElementCustom.cpp1
-rw-r--r--WebCore/bindings/js/JSHTMLObjectElementCustom.cpp5
-rw-r--r--WebCore/bindings/js/JSHistoryCustom.cpp51
-rw-r--r--WebCore/bindings/js/JSImageConstructor.cpp1
-rw-r--r--WebCore/bindings/js/JSInspectedObjectWrapper.cpp6
-rw-r--r--WebCore/bindings/js/JSInspectedObjectWrapper.h2
-rw-r--r--WebCore/bindings/js/JSInspectorBackendCustom.cpp130
-rw-r--r--WebCore/bindings/js/JSInspectorCallbackWrapper.cpp8
-rw-r--r--WebCore/bindings/js/JSInspectorCallbackWrapper.h2
-rw-r--r--WebCore/bindings/js/JSLazyEventListener.cpp50
-rw-r--r--WebCore/bindings/js/JSLazyEventListener.h11
-rw-r--r--WebCore/bindings/js/JSLocationCustom.cpp80
-rw-r--r--WebCore/bindings/js/JSMessageChannelConstructor.cpp1
-rw-r--r--WebCore/bindings/js/JSMessageEventCustom.cpp79
-rw-r--r--WebCore/bindings/js/JSMessagePortCustom.cpp70
-rw-r--r--WebCore/bindings/js/JSMessagePortCustom.h65
-rw-r--r--WebCore/bindings/js/JSNamedNodeMapCustom.cpp19
-rw-r--r--WebCore/bindings/js/JSNamedNodesCollection.cpp92
-rw-r--r--WebCore/bindings/js/JSNodeCustom.cpp30
-rw-r--r--WebCore/bindings/js/JSNodeFilterCustom.cpp2
-rw-r--r--WebCore/bindings/js/JSOptionConstructor.cpp1
-rw-r--r--WebCore/bindings/js/JSPluginElementFunctions.cpp16
-rw-r--r--WebCore/bindings/js/JSPluginElementFunctions.h1
-rw-r--r--WebCore/bindings/js/JSQuarantinedObjectWrapper.cpp59
-rw-r--r--WebCore/bindings/js/JSQuarantinedObjectWrapper.h7
-rw-r--r--WebCore/bindings/js/JSSQLTransactionCustom.cpp6
-rw-r--r--WebCore/bindings/js/JSSVGElementInstanceCustom.cpp12
-rw-r--r--WebCore/bindings/js/JSSharedWorkerConstructor.cpp8
-rw-r--r--WebCore/bindings/js/JSStorageCustom.cpp4
-rw-r--r--WebCore/bindings/js/JSStyleSheetCustom.cpp9
-rw-r--r--WebCore/bindings/js/JSStyleSheetListCustom.cpp14
-rw-r--r--WebCore/bindings/js/JSWebSocketConstructor.cpp1
-rw-r--r--WebCore/bindings/js/JSWebSocketCustom.cpp9
-rw-r--r--WebCore/bindings/js/JSWorkerConstructor.cpp1
-rw-r--r--WebCore/bindings/js/JSWorkerContextBase.cpp2
-rw-r--r--WebCore/bindings/js/JSWorkerContextBase.h2
-rw-r--r--WebCore/bindings/js/JSWorkerContextCustom.cpp43
-rw-r--r--WebCore/bindings/js/JSWorkerCustom.cpp9
-rw-r--r--WebCore/bindings/js/JSXMLHttpRequestConstructor.cpp1
-rw-r--r--WebCore/bindings/js/JSXMLHttpRequestCustom.cpp35
-rw-r--r--WebCore/bindings/js/JSXMLHttpRequestUploadCustom.cpp30
-rw-r--r--WebCore/bindings/js/JSXSLTProcessorCustom.cpp6
-rw-r--r--WebCore/bindings/js/ScriptCachedFrameData.cpp2
-rw-r--r--WebCore/bindings/js/ScriptCallFrame.cpp2
-rw-r--r--WebCore/bindings/js/ScriptController.cpp22
-rw-r--r--WebCore/bindings/js/ScriptController.h5
-rw-r--r--WebCore/bindings/js/ScriptControllerHaiku.cpp2
-rw-r--r--WebCore/bindings/js/ScriptEventListener.cpp57
-rw-r--r--WebCore/bindings/js/ScriptEventListener.h3
-rw-r--r--WebCore/bindings/js/ScriptObject.cpp10
-rw-r--r--WebCore/bindings/js/ScriptObject.h3
-rw-r--r--WebCore/bindings/js/ScriptObjectQuarantine.cpp10
-rw-r--r--WebCore/bindings/js/ScriptObjectQuarantine.h3
-rw-r--r--WebCore/bindings/js/ScriptValue.cpp7
-rw-r--r--WebCore/bindings/js/ScriptValue.h1
-rw-r--r--WebCore/bindings/js/SerializedScriptValue.cpp839
-rw-r--r--WebCore/bindings/js/SerializedScriptValue.h199
-rw-r--r--WebCore/bindings/objc/DOM.mm40
-rw-r--r--WebCore/bindings/objc/DOMCSS.mm3
-rw-r--r--WebCore/bindings/objc/DOMInternal.h1
-rw-r--r--WebCore/bindings/objc/DOMInternal.mm12
-rw-r--r--WebCore/bindings/objc/DOMSVG.h1
-rw-r--r--WebCore/bindings/objc/ObjCEventListener.h11
-rw-r--r--WebCore/bindings/objc/ObjCEventListener.mm12
-rw-r--r--WebCore/bindings/scripts/CodeGenerator.pm268
-rw-r--r--WebCore/bindings/scripts/CodeGeneratorCOM.pm3
-rw-r--r--WebCore/bindings/scripts/CodeGeneratorJS.pm288
-rw-r--r--WebCore/bindings/scripts/CodeGeneratorObjC.pm43
-rw-r--r--WebCore/bindings/scripts/CodeGeneratorV8.pm297
-rw-r--r--WebCore/bindings/scripts/IDLParser.pm6
-rwxr-xr-xWebCore/bindings/scripts/generate-bindings.pl6
-rw-r--r--WebCore/bindings/v8/ChildThreadDOMData.h2
-rw-r--r--WebCore/bindings/v8/DOMData.h2
-rw-r--r--WebCore/bindings/v8/DOMObjectsInclude.h72
-rw-r--r--WebCore/bindings/v8/DateExtension.cpp123
-rw-r--r--WebCore/bindings/v8/DateExtension.h55
-rw-r--r--WebCore/bindings/v8/DerivedSourcesAllInOne.cpp74
-rw-r--r--WebCore/bindings/v8/NPV8Object.cpp8
-rw-r--r--WebCore/bindings/v8/OwnHandle.h6
-rw-r--r--WebCore/bindings/v8/ScheduledAction.cpp9
-rw-r--r--WebCore/bindings/v8/ScheduledAction.h10
-rw-r--r--WebCore/bindings/v8/ScriptCallFrame.cpp2
-rw-r--r--WebCore/bindings/v8/ScriptController.cpp29
-rw-r--r--WebCore/bindings/v8/ScriptController.h29
-rw-r--r--WebCore/bindings/v8/ScriptEventListener.cpp18
-rw-r--r--WebCore/bindings/v8/ScriptEventListener.h3
-rw-r--r--WebCore/bindings/v8/ScriptFunctionCall.cpp10
-rw-r--r--WebCore/bindings/v8/ScriptObject.cpp7
-rw-r--r--WebCore/bindings/v8/ScriptObject.h1
-rw-r--r--WebCore/bindings/v8/ScriptObjectQuarantine.cpp16
-rw-r--r--WebCore/bindings/v8/ScriptObjectQuarantine.h3
-rw-r--r--WebCore/bindings/v8/ScriptScope.cpp3
-rw-r--r--WebCore/bindings/v8/ScriptSourceCode.h2
-rw-r--r--WebCore/bindings/v8/ScriptState.cpp17
-rw-r--r--WebCore/bindings/v8/ScriptState.h10
-rw-r--r--WebCore/bindings/v8/ScriptValue.h9
-rw-r--r--WebCore/bindings/v8/SerializedScriptValue.h77
-rw-r--r--WebCore/bindings/v8/SharedPersistent.h75
-rw-r--r--WebCore/bindings/v8/V8AbstractEventListener.cpp155
-rw-r--r--WebCore/bindings/v8/V8AbstractEventListener.h103
-rw-r--r--WebCore/bindings/v8/V8Binding.cpp103
-rw-r--r--WebCore/bindings/v8/V8Binding.h53
-rw-r--r--WebCore/bindings/v8/V8DOMWrapper.cpp240
-rw-r--r--WebCore/bindings/v8/V8DOMWrapper.h71
-rw-r--r--WebCore/bindings/v8/V8EventListenerList.cpp159
-rw-r--r--WebCore/bindings/v8/V8EventListenerList.h108
-rw-r--r--WebCore/bindings/v8/V8HiddenPropertyName.cpp21
-rw-r--r--WebCore/bindings/v8/V8HiddenPropertyName.h13
-rw-r--r--WebCore/bindings/v8/V8Index.cpp85
-rw-r--r--WebCore/bindings/v8/V8Index.h122
-rw-r--r--WebCore/bindings/v8/V8IsolatedWorld.cpp53
-rw-r--r--WebCore/bindings/v8/V8IsolatedWorld.h42
-rw-r--r--WebCore/bindings/v8/V8LazyEventListener.cpp248
-rw-r--r--WebCore/bindings/v8/V8LazyEventListener.h21
-rw-r--r--WebCore/bindings/v8/V8ObjectEventListener.cpp92
-rw-r--r--WebCore/bindings/v8/V8Proxy.cpp294
-rw-r--r--WebCore/bindings/v8/V8Proxy.h118
-rw-r--r--WebCore/bindings/v8/V8Utilities.cpp52
-rw-r--r--WebCore/bindings/v8/V8Utilities.h13
-rw-r--r--WebCore/bindings/v8/V8WorkerContextEventListener.cpp33
-rw-r--r--WebCore/bindings/v8/V8WorkerContextEventListener.h16
-rw-r--r--WebCore/bindings/v8/WorkerContextExecutionProxy.cpp58
-rw-r--r--WebCore/bindings/v8/WorkerContextExecutionProxy.h6
-rw-r--r--WebCore/bindings/v8/custom/V8AbstractWorkerCustom.cpp61
-rw-r--r--WebCore/bindings/v8/custom/V8CanvasArrayBufferCustom.cpp71
-rw-r--r--WebCore/bindings/v8/custom/V8CanvasArrayCustom.h136
-rw-r--r--WebCore/bindings/v8/custom/V8CanvasByteArrayCustom.cpp83
-rw-r--r--WebCore/bindings/v8/custom/V8CanvasFloatArrayCustom.cpp80
-rw-r--r--WebCore/bindings/v8/custom/V8CanvasIntArrayCustom.cpp83
-rw-r--r--WebCore/bindings/v8/custom/V8CanvasRenderingContext3DCustom.cpp597
-rw-r--r--WebCore/bindings/v8/custom/V8CanvasShortArrayCustom.cpp83
-rw-r--r--WebCore/bindings/v8/custom/V8CanvasUnsignedByteArrayCustom.cpp83
-rw-r--r--WebCore/bindings/v8/custom/V8CanvasUnsignedIntArrayCustom.cpp83
-rw-r--r--WebCore/bindings/v8/custom/V8CanvasUnsignedShortArrayCustom.cpp83
-rw-r--r--WebCore/bindings/v8/custom/V8CustomBinding.h126
-rw-r--r--WebCore/bindings/v8/custom/V8CustomEventListener.cpp38
-rw-r--r--WebCore/bindings/v8/custom/V8CustomEventListener.h16
-rw-r--r--WebCore/bindings/v8/custom/V8DOMApplicationCacheCustom.cpp62
-rw-r--r--WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp309
-rw-r--r--WebCore/bindings/v8/custom/V8DatabaseCustom.cpp61
-rw-r--r--WebCore/bindings/v8/custom/V8DedicatedWorkerContextCustom.cpp48
-rw-r--r--WebCore/bindings/v8/custom/V8DocumentCustom.cpp23
-rw-r--r--WebCore/bindings/v8/custom/V8FileListCustom.cpp (renamed from WebCore/bindings/v8/V8WorkerContextObjectEventListener.cpp)31
-rw-r--r--WebCore/bindings/v8/custom/V8GeolocationCustom.cpp10
-rw-r--r--WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.cpp21
-rwxr-xr-x[-rw-r--r--]WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.h (renamed from WebCore/bindings/js/JSSharedWorkerContextCustom.cpp)23
-rw-r--r--WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp15
-rw-r--r--WebCore/bindings/v8/custom/V8HTMLFrameElementCustom.cpp5
-rw-r--r--WebCore/bindings/v8/custom/V8HTMLIFrameElementCustom.cpp5
-rw-r--r--WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.cpp21
-rwxr-xr-x[-rw-r--r--]WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.h (renamed from WebCore/bindings/v8/V8WorkerContextObjectEventListener.h)28
-rw-r--r--WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.cpp21
-rwxr-xr-xWebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.h47
-rw-r--r--WebCore/bindings/v8/custom/V8InspectorBackendCustom.cpp108
-rw-r--r--WebCore/bindings/v8/custom/V8LocationCustom.cpp20
-rw-r--r--WebCore/bindings/v8/custom/V8MessageChannelConstructor.cpp14
-rw-r--r--WebCore/bindings/v8/custom/V8MessageEventCustom.cpp81
-rw-r--r--WebCore/bindings/v8/custom/V8MessagePortCustom.cpp114
-rw-r--r--WebCore/bindings/v8/custom/V8MessagePortCustom.h (renamed from WebCore/bindings/v8/V8ObjectEventListener.h)33
-rw-r--r--WebCore/bindings/v8/custom/V8NodeCustom.cpp64
-rw-r--r--WebCore/bindings/v8/custom/V8NotificationCenterCustom.cpp143
-rw-r--r--WebCore/bindings/v8/custom/V8SVGElementInstanceCustom.cpp14
-rw-r--r--WebCore/bindings/v8/custom/V8SharedWorkerCustom.cpp22
-rwxr-xr-xWebCore/bindings/v8/custom/V8WebKitPointConstructor.cpp23
-rw-r--r--WebCore/bindings/v8/custom/V8WebSocketCustom.cpp131
-rwxr-xr-xWebCore/bindings/v8/custom/V8WorkerContextCustom.cpp52
-rwxr-xr-xWebCore/bindings/v8/custom/V8WorkerCustom.cpp79
-rw-r--r--WebCore/bindings/v8/custom/V8XMLHttpRequestConstructor.cpp19
-rw-r--r--WebCore/bindings/v8/custom/V8XMLHttpRequestCustom.cpp254
-rw-r--r--WebCore/bindings/v8/custom/V8XMLHttpRequestUploadCustom.cpp207
-rw-r--r--WebCore/bindings/v8/npruntime.cpp16
254 files changed, 10185 insertions, 3764 deletions
diff --git a/WebCore/bindings/js/DOMObjectWithSVGContext.h b/WebCore/bindings/js/DOMObjectWithSVGContext.h
index 570548d..3d435cb 100644
--- a/WebCore/bindings/js/DOMObjectWithSVGContext.h
+++ b/WebCore/bindings/js/DOMObjectWithSVGContext.h
@@ -40,7 +40,7 @@ namespace WebCore {
SVGElement* context() const { return m_context.get(); }
protected:
- DOMObjectWithSVGContext(PassRefPtr<JSC::Structure> structure, JSDOMGlobalObject*, SVGElement* context)
+ DOMObjectWithSVGContext(NonNullPassRefPtr<JSC::Structure> structure, JSDOMGlobalObject*, SVGElement* context)
: DOMObject(structure)
, m_context(context)
{
diff --git a/WebCore/bindings/js/JSAbstractWorkerCustom.cpp b/WebCore/bindings/js/JSAbstractWorkerCustom.cpp
index 003f544..9411ad8 100644
--- a/WebCore/bindings/js/JSAbstractWorkerCustom.cpp
+++ b/WebCore/bindings/js/JSAbstractWorkerCustom.cpp
@@ -44,30 +44,17 @@ using namespace JSC;
namespace WebCore {
-void JSAbstractWorker::markChildren(MarkStack& markStack)
-{
- Base::markChildren(markStack);
-
- markIfNotNull(markStack, m_impl->onerror());
-
- typedef AbstractWorker::EventListenersMap EventListenersMap;
- typedef AbstractWorker::ListenerVector ListenerVector;
- EventListenersMap& eventListeners = m_impl->eventListeners();
- for (EventListenersMap::iterator mapIter = eventListeners.begin(); mapIter != eventListeners.end(); ++mapIter) {
- for (ListenerVector::iterator vecIter = mapIter->second.begin(); vecIter != mapIter->second.end(); ++vecIter)
- (*vecIter)->markJSFunction(markStack);
- }
-}
-
JSValue JSAbstractWorker::addEventListener(ExecState* exec, const ArgList& args)
{
JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->scriptExecutionContext());
if (!globalObject)
return jsUndefined();
- RefPtr<JSEventListener> listener = globalObject->findOrCreateJSEventListener(args.at(1));
- if (!listener)
+
+ JSValue listener = args.at(1);
+ if (!listener.isObject())
return jsUndefined();
- impl()->addEventListener(args.at(0).toString(exec), listener.release(), args.at(2).toBoolean(exec));
+
+ impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false), args.at(2).toBoolean(exec));
return jsUndefined();
}
@@ -76,10 +63,12 @@ JSValue JSAbstractWorker::removeEventListener(ExecState* exec, const ArgList& ar
JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->scriptExecutionContext());
if (!globalObject)
return jsUndefined();
- JSEventListener* listener = globalObject->findJSEventListener(args.at(1));
- if (!listener)
+
+ JSValue listener = args.at(1);
+ if (!listener.isObject())
return jsUndefined();
- impl()->removeEventListener(args.at(0).toString(exec), listener, args.at(2).toBoolean(exec));
+
+ impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false).get(), args.at(2).toBoolean(exec));
return jsUndefined();
}
diff --git a/WebCore/bindings/js/JSAttrCustom.cpp b/WebCore/bindings/js/JSAttrCustom.cpp
index abd5ad5..14457c4 100644
--- a/WebCore/bindings/js/JSAttrCustom.cpp
+++ b/WebCore/bindings/js/JSAttrCustom.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -48,7 +48,8 @@ void JSAttr::setValue(ExecState* exec, JSValue value)
Element* ownerElement = imp->ownerElement();
if (ownerElement && (ownerElement->hasTagName(iframeTag) || ownerElement->hasTagName(frameTag))) {
if (equalIgnoringCase(imp->name(), "src") && protocolIsJavaScript(deprecatedParseURL(attrValue))) {
- if (!checkNodeSecurity(exec, static_cast<HTMLFrameElementBase*>(ownerElement)->contentDocument()))
+ Document* contentDocument = static_cast<HTMLFrameElementBase*>(ownerElement)->contentDocument();
+ if (contentDocument && !checkNodeSecurity(exec, contentDocument))
return;
}
}
@@ -58,4 +59,16 @@ void JSAttr::setValue(ExecState* exec, JSValue value)
setDOMException(exec, ec);
}
+void JSAttr::markChildren(MarkStack& markStack)
+{
+ Base::markChildren(markStack);
+
+ // Mark the element so that this will work to access the attribute even if the last
+ // other reference goes away.
+ if (Element* element = impl()->ownerElement()) {
+ if (JSNode* wrapper = getCachedDOMNodeWrapper(element->document(), element))
+ markStack.append(wrapper);
+ }
+}
+
} // namespace WebCore
diff --git a/WebCore/bindings/js/JSAudioConstructor.cpp b/WebCore/bindings/js/JSAudioConstructor.cpp
index 87a3880..174cc11 100644
--- a/WebCore/bindings/js/JSAudioConstructor.cpp
+++ b/WebCore/bindings/js/JSAudioConstructor.cpp
@@ -34,6 +34,7 @@
#include "JSHTMLAudioElement.h"
#include "ScriptExecutionContext.h"
#include "Text.h"
+#include <runtime/Error.h>
using namespace JSC;
diff --git a/WebCore/bindings/js/JSCSSRuleListCustom.cpp b/WebCore/bindings/js/JSCSSRuleListCustom.cpp
new file mode 100644
index 0000000..be3a9a2
--- /dev/null
+++ b/WebCore/bindings/js/JSCSSRuleListCustom.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All right reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSCSSRuleList.h"
+
+#include "CSSRuleList.h"
+
+using namespace JSC;
+
+namespace WebCore {
+
+void JSCSSRuleList::markChildren(MarkStack& markStack)
+{
+ Base::markChildren(markStack);
+
+ CSSRuleList* list = impl();
+ JSGlobalData& globalData = *Heap::heap(this)->globalData();
+
+ unsigned length = list->length();
+ for (unsigned i = 0; i < length; ++i)
+ markDOMObjectWrapper(markStack, globalData, list->item(i));
+}
+
+}
diff --git a/WebCore/bindings/js/JSCSSStyleDeclarationCustom.cpp b/WebCore/bindings/js/JSCSSStyleDeclarationCustom.cpp
index 280ec93..4a137d3 100644
--- a/WebCore/bindings/js/JSCSSStyleDeclarationCustom.cpp
+++ b/WebCore/bindings/js/JSCSSStyleDeclarationCustom.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -27,8 +27,8 @@
#include "JSCSSStyleDeclarationCustom.h"
#include "AtomicString.h"
+#include "CSSMutableStyleDeclaration.h"
#include "CSSPrimitiveValue.h"
-#include "CSSStyleDeclaration.h"
#include "CSSValue.h"
#include "PlatformString.h"
#include <runtime/StringObjectThatMasqueradesAsUndefined.h>
@@ -40,6 +40,21 @@ using namespace WTF;
namespace WebCore {
+void JSCSSStyleDeclaration::markChildren(MarkStack& markStack)
+{
+ Base::markChildren(markStack);
+
+ CSSStyleDeclaration* declaration = impl();
+ JSGlobalData& globalData = *Heap::heap(this)->globalData();
+
+ if (declaration->isMutableStyleDeclaration()) {
+ CSSMutableStyleDeclaration* mutableDeclaration = static_cast<CSSMutableStyleDeclaration*>(declaration);
+ CSSMutableStyleDeclaration::const_iterator end = mutableDeclaration->end();
+ for (CSSMutableStyleDeclaration::const_iterator it = mutableDeclaration->begin(); it != end; ++it)
+ markDOMObjectWrapper(markStack, globalData, it->value());
+ }
+}
+
// Check for a CSS prefix.
// Passed prefix is all lowercase.
// First character of the prefix within the property name may be upper or lowercase.
diff --git a/WebCore/bindings/js/JSCallbackData.cpp b/WebCore/bindings/js/JSCallbackData.cpp
new file mode 100644
index 0000000..d08f760
--- /dev/null
+++ b/WebCore/bindings/js/JSCallbackData.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSCallbackData.h"
+
+#include "Document.h"
+#include "JSDOMBinding.h"
+
+using namespace JSC;
+
+namespace WebCore {
+
+void JSCallbackData::deleteData(void* context)
+{
+ delete static_cast<JSCallbackData*>(context);
+}
+
+JSValue JSCallbackData::invokeCallback(MarkedArgumentBuffer& args, bool* raisedException)
+{
+ ASSERT(callback());
+ ASSERT(globalObject());
+
+ ExecState* exec = globalObject()->globalExec();
+
+ JSValue function = callback()->get(exec, Identifier(exec, "handleEvent"));
+ CallData callData;
+ CallType callType = function.getCallData(callData);
+ if (callType == CallTypeNone) {
+ callType = callback()->getCallData(callData);
+ if (callType == CallTypeNone)
+ return JSValue();
+ function = callback();
+ }
+
+ globalObject()->globalData()->timeoutChecker.start();
+ JSValue result = call(exec, function, callType, callData, callback(), args);
+ globalObject()->globalData()->timeoutChecker.stop();
+
+ Document::updateStyleForAllDocuments();
+
+ if (exec->hadException()) {
+ reportCurrentException(exec);
+ if (raisedException)
+ *raisedException = true;
+ return result;
+ }
+
+ return result;
+}
+
+} // namespace WebCore
diff --git a/WebCore/bindings/js/JSCallbackData.h b/WebCore/bindings/js/JSCallbackData.h
new file mode 100644
index 0000000..4fc9f84
--- /dev/null
+++ b/WebCore/bindings/js/JSCallbackData.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JSCallbackData_h
+#define JSCallbackData_h
+
+#include "JSDOMGlobalObject.h"
+#include <runtime/JSObject.h>
+#include <runtime/Protect.h>
+#include <wtf/Threading.h>
+
+namespace WebCore {
+
+// We have to clean up this data on the main thread because unprotecting a
+// JSObject on a non-main thread without synchronization would corrupt the heap
+// (and synchronization would be slow).
+
+class JSCallbackData {
+public:
+ static void deleteData(void*);
+
+ JSCallbackData(JSC::JSObject* callback, JSDOMGlobalObject* globalObject)
+ : m_callback(callback)
+ , m_globalObject(globalObject)
+ {
+ }
+
+ ~JSCallbackData()
+ {
+ ASSERT(isMainThread());
+ }
+
+ JSC::JSObject* callback() { return m_callback.get(); }
+ JSDOMGlobalObject* globalObject() { return m_globalObject.get(); }
+
+ JSC::JSValue invokeCallback(JSC::MarkedArgumentBuffer&, bool* raisedException = 0);
+
+private:
+ JSC::ProtectedPtr<JSC::JSObject> m_callback;
+ JSC::ProtectedPtr<JSDOMGlobalObject> m_globalObject;
+};
+
+} // namespace WebCore
+
+#endif // JSCallbackData_h
diff --git a/WebCore/bindings/js/JSCanvasArrayBufferConstructor.cpp b/WebCore/bindings/js/JSCanvasArrayBufferConstructor.cpp
new file mode 100644
index 0000000..93d53ca
--- /dev/null
+++ b/WebCore/bindings/js/JSCanvasArrayBufferConstructor.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(3D_CANVAS)
+
+#include "JSCanvasArrayBufferConstructor.h"
+
+#include "Document.h"
+#include "CanvasArrayBuffer.h"
+#include "JSCanvasArrayBuffer.h"
+
+namespace WebCore {
+
+using namespace JSC;
+
+const ClassInfo JSCanvasArrayBufferConstructor::s_info = { "CanvasArrayBufferConstructor", 0, 0, 0 };
+
+JSCanvasArrayBufferConstructor::JSCanvasArrayBufferConstructor(ExecState* exec, JSDOMGlobalObject* globalObject)
+ : DOMConstructorObject(JSCanvasArrayBufferConstructor::createStructure(globalObject->objectPrototype()), globalObject)
+{
+ putDirect(exec->propertyNames().prototype, JSCanvasArrayBufferPrototype::self(exec, globalObject), None);
+ putDirect(exec->propertyNames().length, jsNumber(exec, 2), ReadOnly|DontDelete|DontEnum);
+}
+
+static JSObject* constructCanvasArrayBuffer(ExecState* exec, JSObject* constructor, const ArgList& args)
+{
+ JSCanvasArrayBufferConstructor* jsConstructor = static_cast<JSCanvasArrayBufferConstructor*>(constructor);
+
+ unsigned int size = 0;
+ if (args.size() == 1) {
+ size = (unsigned int)args.at(0).toInt32(exec);
+ if (isnan(size))
+ size = 0;
+ }
+ return asObject(toJS(exec, jsConstructor->globalObject(), CanvasArrayBuffer::create(size)));
+}
+
+JSC::ConstructType JSCanvasArrayBufferConstructor::getConstructData(JSC::ConstructData& constructData)
+{
+ constructData.native.function = constructCanvasArrayBuffer;
+ return ConstructTypeHost;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/bindings/js/JSCanvasArrayBufferConstructor.h b/WebCore/bindings/js/JSCanvasArrayBufferConstructor.h
new file mode 100644
index 0000000..5f1254e
--- /dev/null
+++ b/WebCore/bindings/js/JSCanvasArrayBufferConstructor.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JSCanvasArrayBufferConstructor_h
+#define JSCanvasArrayBufferConstructor_h
+
+#include "JSDOMBinding.h"
+#include "JSDocument.h"
+#include "JSCanvasArrayBuffer.h"
+#include <runtime/Error.h>
+
+namespace WebCore {
+
+ class CanvasArray;
+
+ // Template function used by CanvasXXXArrayConstructors
+ template<class C, typename T>
+ PassRefPtr<CanvasArray> construct(JSC::ExecState* exec, const JSC::ArgList& args)
+ {
+ // There are 3 constructors:
+ //
+ // 1) (in int size)
+ // 2) (in CanvasArrayBuffer buffer, [Optional] in int offset, [Optional] in unsigned int length)
+ // 3) (in sequence<T>) - This ends up being a JS "array-like" object
+ //
+ RefPtr<C> arrayObject;
+
+ // For the 0 args case, just create an object without a buffer
+ if (args.size() < 1)
+ return C::create(0, 0, 0);
+
+ if (args.at(0).isObject()) {
+ RefPtr<CanvasArrayBuffer> buffer = toCanvasArrayBuffer(args.at(0));
+ if (buffer) {
+ int offset = (args.size() > 1) ? args.at(1).toInt32(exec) : 0;
+ unsigned int length = (args.size() > 2) ? static_cast<unsigned int>(args.at(2).toInt32(exec)) : 0;
+ return C::create(buffer, offset, length);
+ }
+
+ JSC::JSObject* array = asObject(args.at(0));
+ int length = array->get(exec, JSC::Identifier(exec, "length")).toInt32(exec);
+ void* tempValues;
+ if (!tryFastMalloc(length * sizeof(T)).getValue(tempValues)) {
+ throwError(exec, JSC::GeneralError);
+ return 0;
+ }
+
+ OwnFastMallocPtr<T> values(static_cast<T*>(tempValues));
+ for (int i = 0; i < length; ++i) {
+ JSC::JSValue v = array->get(exec, i);
+ if (exec->hadException())
+ return 0;
+ values.get()[i] = static_cast<T>(v.toNumber(exec));
+ }
+
+ return C::create(values.get(), length);
+ }
+
+ unsigned size = static_cast<unsigned>(args.at(0).toInt32(exec));
+ return C::create(size);
+ }
+
+ class JSCanvasArrayBufferConstructor : public DOMConstructorObject {
+ public:
+ JSCanvasArrayBufferConstructor(JSC::ExecState*, JSDOMGlobalObject*);
+ static const JSC::ClassInfo s_info;
+
+ private:
+ virtual JSC::ConstructType getConstructData(JSC::ConstructData&);
+ virtual const JSC::ClassInfo* classInfo() const { return &s_info; }
+ };
+
+}
+
+#endif // JSCanvasArrayBufferConstructor_h
diff --git a/WebCore/bindings/js/JSCanvasArrayCustom.cpp b/WebCore/bindings/js/JSCanvasArrayCustom.cpp
new file mode 100644
index 0000000..4aa1547
--- /dev/null
+++ b/WebCore/bindings/js/JSCanvasArrayCustom.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(3D_CANVAS)
+
+#include "config.h"
+#include "JSCanvasArray.h"
+
+#include "CanvasArray.h"
+
+using namespace JSC;
+
+namespace WebCore {
+
+JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, CanvasArray* object)
+{
+ if (!object)
+ return jsUndefined();
+
+
+
+#if ENABLE(3D_CANVAS)
+ if (object->is3d())
+ return getDOMObjectWrapper<JSCanvasRenderingContext3D>(exec, globalObject, static_cast<CanvasRenderingContext3D*>(object));
+#endif
+ ASSERT(object->is2d());
+ return getDOMObjectWrapper<JSCanvasRenderingContext2D>(exec, globalObject, static_cast<CanvasRenderingContext2D*>(object));
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/bindings/js/JSCanvasByteArrayConstructor.cpp b/WebCore/bindings/js/JSCanvasByteArrayConstructor.cpp
new file mode 100644
index 0000000..ec1d66d
--- /dev/null
+++ b/WebCore/bindings/js/JSCanvasByteArrayConstructor.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(3D_CANVAS)
+
+#include "JSCanvasByteArrayConstructor.h"
+
+#include "Document.h"
+#include "CanvasByteArray.h"
+#include "JSCanvasArrayBuffer.h"
+#include "JSCanvasArrayBufferConstructor.h"
+#include "JSCanvasByteArray.h"
+#include <runtime/Error.h>
+
+namespace WebCore {
+
+using namespace JSC;
+
+const ClassInfo JSCanvasByteArrayConstructor::s_info = { "CanvasByteArrayConstructor", &JSCanvasArray::s_info, 0, 0 };
+
+JSCanvasByteArrayConstructor::JSCanvasByteArrayConstructor(ExecState* exec, JSDOMGlobalObject* globalObject)
+ : DOMConstructorObject(JSCanvasByteArrayConstructor::createStructure(globalObject->objectPrototype()), globalObject)
+{
+ putDirect(exec->propertyNames().prototype, JSCanvasByteArrayPrototype::self(exec, globalObject), None);
+ putDirect(exec->propertyNames().length, jsNumber(exec, 2), ReadOnly|DontDelete|DontEnum);
+}
+
+static JSObject* constructCanvasByteArray(ExecState* exec, JSObject* constructor, const ArgList& args)
+{
+ JSCanvasByteArrayConstructor* jsConstructor = static_cast<JSCanvasByteArrayConstructor*>(constructor);
+ RefPtr<CanvasByteArray> array = static_cast<CanvasByteArray*>(construct<CanvasByteArray, signed char>(exec, args).get());
+ return asObject(toJS(exec, jsConstructor->globalObject(), array.get()));
+}
+
+JSC::ConstructType JSCanvasByteArrayConstructor::getConstructData(JSC::ConstructData& constructData)
+{
+ constructData.native.function = constructCanvasByteArray;
+ return ConstructTypeHost;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/bindings/js/JSNamedNodesCollection.h b/WebCore/bindings/js/JSCanvasByteArrayConstructor.h
index cd6c2cb..4d5dc11 100644
--- a/WebCore/bindings/js/JSNamedNodesCollection.h
+++ b/WebCore/bindings/js/JSCanvasByteArrayConstructor.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -23,44 +23,24 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef JSNamedNodesCollection_h
-#define JSNamedNodesCollection_h
+#ifndef JSCanvasByteArrayConstructor_h
+#define JSCanvasByteArrayConstructor_h
#include "JSDOMBinding.h"
-#include <wtf/Vector.h>
+#include "JSDocument.h"
namespace WebCore {
- class Node;
-
- // Internal class, used for the collection return by e.g. document.forms.myinput
- // when multiple nodes have the same name.
- class JSNamedNodesCollection : public DOMObjectWithGlobalPointer {
+ class JSCanvasByteArrayConstructor : public DOMConstructorObject {
public:
- JSNamedNodesCollection(JSC::ExecState*, JSDOMGlobalObject*, const Vector<RefPtr<Node> >&);
-
- virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);
-
- virtual const JSC::ClassInfo* classInfo() const { return &s_info; }
+ JSCanvasByteArrayConstructor(JSC::ExecState*, JSDOMGlobalObject*);
static const JSC::ClassInfo s_info;
- static JSC::ObjectPrototype* createPrototype(JSC::ExecState*, JSC::JSGlobalObject* globalObject)
- {
- return globalObject->objectPrototype();
- }
-
- static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype)
- {
- return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType));
- }
-
private:
- static JSC::JSValue lengthGetter(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&);
- static JSC::JSValue indexGetter(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&);
-
- OwnPtr<Vector<RefPtr<Node> > > m_nodes;
+ virtual JSC::ConstructType getConstructData(JSC::ConstructData&);
+ virtual const JSC::ClassInfo* classInfo() const { return &s_info; }
};
-} // namespace WebCore
+}
-#endif // JSNamedNodesCollection_h
+#endif // JSCanvasByteArrayConstructor_h
diff --git a/WebCore/bindings/js/JSCanvasByteArrayCustom.cpp b/WebCore/bindings/js/JSCanvasByteArrayCustom.cpp
new file mode 100644
index 0000000..04697ce
--- /dev/null
+++ b/WebCore/bindings/js/JSCanvasByteArrayCustom.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(3D_CANVAS)
+
+#include "JSCanvasByteArray.h"
+
+#include "CanvasByteArray.h"
+
+using namespace JSC;
+
+namespace WebCore {
+
+void JSCanvasByteArray::indexSetter(JSC::ExecState* exec, unsigned index, JSC::JSValue value)
+{
+ impl()->set(index, static_cast<signed char>(value.toInt32(exec)));
+}
+
+JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, CanvasByteArray* object)
+{
+ return getDOMObjectWrapper<JSCanvasByteArray>(exec, globalObject, object);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/bindings/js/JSCanvasFloatArrayConstructor.cpp b/WebCore/bindings/js/JSCanvasFloatArrayConstructor.cpp
new file mode 100644
index 0000000..15e39c2
--- /dev/null
+++ b/WebCore/bindings/js/JSCanvasFloatArrayConstructor.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(3D_CANVAS)
+
+#include "JSCanvasFloatArrayConstructor.h"
+
+#include "Document.h"
+#include "CanvasFloatArray.h"
+#include "JSCanvasArrayBuffer.h"
+#include "JSCanvasArrayBufferConstructor.h"
+#include "JSCanvasFloatArray.h"
+#include <runtime/Error.h>
+
+namespace WebCore {
+
+using namespace JSC;
+
+const ClassInfo JSCanvasFloatArrayConstructor::s_info = { "CanvasFloatArrayConstructor", &JSCanvasArray::s_info, 0, 0 };
+
+JSCanvasFloatArrayConstructor::JSCanvasFloatArrayConstructor(ExecState* exec, JSDOMGlobalObject* globalObject)
+ : DOMConstructorObject(JSCanvasFloatArrayConstructor::createStructure(globalObject->objectPrototype()), globalObject)
+{
+ putDirect(exec->propertyNames().prototype, JSCanvasFloatArrayPrototype::self(exec, globalObject), None);
+ putDirect(exec->propertyNames().length, jsNumber(exec, 2), ReadOnly|DontDelete|DontEnum);
+}
+
+static JSObject* constructCanvasFloatArray(ExecState* exec, JSObject* constructor, const ArgList& args)
+{
+ JSCanvasFloatArrayConstructor* jsConstructor = static_cast<JSCanvasFloatArrayConstructor*>(constructor);
+ RefPtr<CanvasFloatArray> array = static_cast<CanvasFloatArray*>(construct<CanvasFloatArray, float>(exec, args).get());
+ return asObject(toJS(exec, jsConstructor->globalObject(), array.get()));
+}
+
+JSC::ConstructType JSCanvasFloatArrayConstructor::getConstructData(JSC::ConstructData& constructData)
+{
+ constructData.native.function = constructCanvasFloatArray;
+ return ConstructTypeHost;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/bindings/js/JSCanvasFloatArrayConstructor.h b/WebCore/bindings/js/JSCanvasFloatArrayConstructor.h
new file mode 100644
index 0000000..efea250
--- /dev/null
+++ b/WebCore/bindings/js/JSCanvasFloatArrayConstructor.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JSCanvasFloatArrayConstructor_h
+#define JSCanvasFloatArrayConstructor_h
+
+#include "JSDOMBinding.h"
+#include "JSDocument.h"
+
+namespace WebCore {
+
+ class JSCanvasFloatArrayConstructor : public DOMConstructorObject {
+ public:
+ JSCanvasFloatArrayConstructor(JSC::ExecState*, JSDOMGlobalObject*);
+ static const JSC::ClassInfo s_info;
+
+ private:
+ virtual JSC::ConstructType getConstructData(JSC::ConstructData&);
+ virtual const JSC::ClassInfo* classInfo() const { return &s_info; }
+ };
+
+}
+
+#endif // JSCanvasFloatArrayConstructor_h
diff --git a/WebCore/bindings/js/JSCanvasFloatArrayCustom.cpp b/WebCore/bindings/js/JSCanvasFloatArrayCustom.cpp
new file mode 100644
index 0000000..20cd805
--- /dev/null
+++ b/WebCore/bindings/js/JSCanvasFloatArrayCustom.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(3D_CANVAS)
+
+#include "JSCanvasFloatArray.h"
+
+#include "CanvasFloatArray.h"
+
+using namespace JSC;
+
+namespace WebCore {
+
+void JSCanvasFloatArray::indexSetter(JSC::ExecState* exec, unsigned index, JSC::JSValue value)
+{
+ impl()->set(index, static_cast<float>(value.toInt32(exec)));
+}
+
+JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, CanvasFloatArray* object)
+{
+ return getDOMObjectWrapper<JSCanvasFloatArray>(exec, globalObject, object);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/bindings/js/JSCanvasIntArrayConstructor.cpp b/WebCore/bindings/js/JSCanvasIntArrayConstructor.cpp
new file mode 100644
index 0000000..6d57912
--- /dev/null
+++ b/WebCore/bindings/js/JSCanvasIntArrayConstructor.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(3D_CANVAS)
+
+#include "JSCanvasIntArrayConstructor.h"
+
+#include "Document.h"
+#include "CanvasIntArray.h"
+#include "JSCanvasArrayBuffer.h"
+#include "JSCanvasArrayBufferConstructor.h"
+#include "JSCanvasIntArray.h"
+#include <runtime/Error.h>
+
+namespace WebCore {
+
+using namespace JSC;
+
+const ClassInfo JSCanvasIntArrayConstructor::s_info = { "CanvasIntArrayConstructor", &JSCanvasArray::s_info, 0, 0 };
+
+JSCanvasIntArrayConstructor::JSCanvasIntArrayConstructor(ExecState* exec, JSDOMGlobalObject* globalObject)
+ : DOMConstructorObject(JSCanvasIntArrayConstructor::createStructure(globalObject->objectPrototype()), globalObject)
+{
+ putDirect(exec->propertyNames().prototype, JSCanvasIntArrayPrototype::self(exec, globalObject), None);
+ putDirect(exec->propertyNames().length, jsNumber(exec, 2), ReadOnly|DontDelete|DontEnum);
+}
+
+static JSObject* constructCanvasIntArray(ExecState* exec, JSObject* constructor, const ArgList& args)
+{
+ JSCanvasIntArrayConstructor* jsConstructor = static_cast<JSCanvasIntArrayConstructor*>(constructor);
+ RefPtr<CanvasIntArray> array = static_cast<CanvasIntArray*>(construct<CanvasIntArray, int>(exec, args).get());
+ return asObject(toJS(exec, jsConstructor->globalObject(), array.get()));
+}
+
+JSC::ConstructType JSCanvasIntArrayConstructor::getConstructData(JSC::ConstructData& constructData)
+{
+ constructData.native.function = constructCanvasIntArray;
+ return ConstructTypeHost;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/bindings/js/JSCanvasIntArrayConstructor.h b/WebCore/bindings/js/JSCanvasIntArrayConstructor.h
new file mode 100644
index 0000000..5e19652
--- /dev/null
+++ b/WebCore/bindings/js/JSCanvasIntArrayConstructor.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JSCanvasIntArrayConstructor_h
+#define JSCanvasIntArrayConstructor_h
+
+#include "JSDOMBinding.h"
+#include "JSDocument.h"
+
+namespace WebCore {
+
+ class JSCanvasIntArrayConstructor : public DOMConstructorObject {
+ public:
+ JSCanvasIntArrayConstructor(JSC::ExecState*, JSDOMGlobalObject*);
+ static const JSC::ClassInfo s_info;
+
+ private:
+ virtual JSC::ConstructType getConstructData(JSC::ConstructData&);
+ virtual const JSC::ClassInfo* classInfo() const { return &s_info; }
+ };
+
+}
+
+#endif // JSCanvasIntArrayConstructor_h
diff --git a/WebCore/bindings/js/JSCanvasIntArrayCustom.cpp b/WebCore/bindings/js/JSCanvasIntArrayCustom.cpp
new file mode 100644
index 0000000..8442b87
--- /dev/null
+++ b/WebCore/bindings/js/JSCanvasIntArrayCustom.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(3D_CANVAS)
+
+#include "JSCanvasIntArray.h"
+
+#include "CanvasIntArray.h"
+
+using namespace JSC;
+
+namespace WebCore {
+
+void JSCanvasIntArray::indexSetter(JSC::ExecState* exec, unsigned index, JSC::JSValue value)
+{
+ impl()->set(index, static_cast<signed int>(value.toInt32(exec)));
+}
+
+JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, CanvasIntArray* object)
+{
+ return getDOMObjectWrapper<JSCanvasIntArray>(exec, globalObject, object);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/bindings/js/JSCanvasNumberArrayCustom.cpp b/WebCore/bindings/js/JSCanvasNumberArrayCustom.cpp
new file mode 100644
index 0000000..be10ac0
--- /dev/null
+++ b/WebCore/bindings/js/JSCanvasNumberArrayCustom.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(3D_CANVAS)
+
+#include "JSCanvasNumberArray.h"
+
+#include "CanvasNumberArray.h"
+
+using namespace JSC;
+
+namespace WebCore {
+
+JSValue JSCanvasNumberArray::getByIndex(JSC::ExecState* exec, unsigned int index)
+{
+ JSC::JSValue result = jsNumber(exec, impl()->item(index));
+ return result;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/bindings/js/JSCanvasRenderingContext2DCustom.cpp b/WebCore/bindings/js/JSCanvasRenderingContext2DCustom.cpp
index 398a6799..bb3500b 100644
--- a/WebCore/bindings/js/JSCanvasRenderingContext2DCustom.cpp
+++ b/WebCore/bindings/js/JSCanvasRenderingContext2DCustom.cpp
@@ -67,27 +67,31 @@ static PassRefPtr<CanvasStyle> toHTMLCanvasStyle(ExecState*, JSValue value)
JSValue JSCanvasRenderingContext2D::strokeStyle(ExecState* exec) const
{
- return toJS(exec, impl()->strokeStyle());
+ CanvasRenderingContext2D* context = static_cast<CanvasRenderingContext2D*>(impl());
+ return toJS(exec, context->strokeStyle());
}
void JSCanvasRenderingContext2D::setStrokeStyle(ExecState* exec, JSValue value)
{
- impl()->setStrokeStyle(toHTMLCanvasStyle(exec, value));
+ CanvasRenderingContext2D* context = static_cast<CanvasRenderingContext2D*>(impl());
+ context->setStrokeStyle(toHTMLCanvasStyle(exec, value));
}
JSValue JSCanvasRenderingContext2D::fillStyle(ExecState* exec) const
{
- return toJS(exec, impl()->fillStyle());
+ CanvasRenderingContext2D* context = static_cast<CanvasRenderingContext2D*>(impl());
+ return toJS(exec, context->fillStyle());
}
void JSCanvasRenderingContext2D::setFillStyle(ExecState* exec, JSValue value)
{
- impl()->setFillStyle(toHTMLCanvasStyle(exec, value));
+ CanvasRenderingContext2D* context = static_cast<CanvasRenderingContext2D*>(impl());
+ context->setFillStyle(toHTMLCanvasStyle(exec, value));
}
JSValue JSCanvasRenderingContext2D::setFillColor(ExecState* exec, const ArgList& args)
{
- CanvasRenderingContext2D* context = impl();
+ CanvasRenderingContext2D* context = static_cast<CanvasRenderingContext2D*>(impl());
// string arg = named color
// number arg = gray color
@@ -124,7 +128,7 @@ JSValue JSCanvasRenderingContext2D::setFillColor(ExecState* exec, const ArgList&
JSValue JSCanvasRenderingContext2D::setStrokeColor(ExecState* exec, const ArgList& args)
{
- CanvasRenderingContext2D* context = impl();
+ CanvasRenderingContext2D* context = static_cast<CanvasRenderingContext2D*>(impl());
// string arg = named color
// number arg = gray color
@@ -162,7 +166,7 @@ JSValue JSCanvasRenderingContext2D::setStrokeColor(ExecState* exec, const ArgLis
JSValue JSCanvasRenderingContext2D::strokeRect(ExecState* exec, const ArgList& args)
{
- CanvasRenderingContext2D* context = impl();
+ CanvasRenderingContext2D* context = static_cast<CanvasRenderingContext2D*>(impl());
if (args.size() <= 4)
context->strokeRect(args.at(0).toFloat(exec), args.at(1).toFloat(exec),
@@ -176,7 +180,7 @@ JSValue JSCanvasRenderingContext2D::strokeRect(ExecState* exec, const ArgList& a
JSValue JSCanvasRenderingContext2D::drawImage(ExecState* exec, const ArgList& args)
{
- CanvasRenderingContext2D* context = impl();
+ CanvasRenderingContext2D* context = static_cast<CanvasRenderingContext2D*>(impl());
// DrawImage has three variants:
// drawImage(img, dx, dy)
@@ -264,7 +268,7 @@ JSValue JSCanvasRenderingContext2D::drawImage(ExecState* exec, const ArgList& ar
JSValue JSCanvasRenderingContext2D::drawImageFromRect(ExecState* exec, const ArgList& args)
{
- CanvasRenderingContext2D* context = impl();
+ CanvasRenderingContext2D* context = static_cast<CanvasRenderingContext2D*>(impl());
JSValue value = args.at(0);
if (!value.isObject())
@@ -284,7 +288,7 @@ JSValue JSCanvasRenderingContext2D::drawImageFromRect(ExecState* exec, const Arg
JSValue JSCanvasRenderingContext2D::setShadow(ExecState* exec, const ArgList& args)
{
- CanvasRenderingContext2D* context = impl();
+ CanvasRenderingContext2D* context = static_cast<CanvasRenderingContext2D*>(impl());
switch (args.size()) {
case 3:
@@ -330,7 +334,7 @@ JSValue JSCanvasRenderingContext2D::setShadow(ExecState* exec, const ArgList& ar
JSValue JSCanvasRenderingContext2D::createPattern(ExecState* exec, const ArgList& args)
{
- CanvasRenderingContext2D* context = impl();
+ CanvasRenderingContext2D* context = static_cast<CanvasRenderingContext2D*>(impl());
JSValue value = args.at(0);
if (!value.isObject())
@@ -362,7 +366,7 @@ JSValue JSCanvasRenderingContext2D::putImageData(ExecState* exec, const ArgList&
// putImageData has two variants
// putImageData(ImageData, x, y)
// putImageData(ImageData, x, y, dirtyX, dirtyY, dirtyWidth, dirtyHeight)
- CanvasRenderingContext2D* context = impl();
+ CanvasRenderingContext2D* context = static_cast<CanvasRenderingContext2D*>(impl());
ExceptionCode ec = 0;
if (args.size() >= 7)
@@ -377,7 +381,7 @@ JSValue JSCanvasRenderingContext2D::putImageData(ExecState* exec, const ArgList&
JSValue JSCanvasRenderingContext2D::fillText(ExecState* exec, const ArgList& args)
{
- CanvasRenderingContext2D* context = impl();
+ CanvasRenderingContext2D* context = static_cast<CanvasRenderingContext2D*>(impl());
// string arg = text to draw
// number arg = x
@@ -395,7 +399,7 @@ JSValue JSCanvasRenderingContext2D::fillText(ExecState* exec, const ArgList& arg
JSValue JSCanvasRenderingContext2D::strokeText(ExecState* exec, const ArgList& args)
{
- CanvasRenderingContext2D* context = impl();
+ CanvasRenderingContext2D* context = static_cast<CanvasRenderingContext2D*>(impl());
// string arg = text to draw
// number arg = x
diff --git a/WebCore/bindings/js/JSCanvasRenderingContext3DCustom.cpp b/WebCore/bindings/js/JSCanvasRenderingContext3DCustom.cpp
new file mode 100644
index 0000000..3938ba1
--- /dev/null
+++ b/WebCore/bindings/js/JSCanvasRenderingContext3DCustom.cpp
@@ -0,0 +1,443 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(3D_CANVAS)
+
+#include "JSCanvasRenderingContext3D.h"
+
+#include "CanvasRenderingContext3D.h"
+#include "ExceptionCode.h"
+#include "HTMLCanvasElement.h"
+#include "HTMLImageElement.h"
+#include "JSCanvasFloatArray.h"
+#include "JSCanvasIntArray.h"
+#include "JSHTMLCanvasElement.h"
+#include "JSHTMLImageElement.h"
+#include "JSWebKitCSSMatrix.h"
+#include <runtime/Error.h>
+#include <wtf/FastMalloc.h>
+#include <wtf/OwnFastMallocPtr.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+JSValue JSCanvasRenderingContext3D::bufferData(JSC::ExecState* exec, JSC::ArgList const& args)
+{
+ if (args.size() != 3)
+ return throwError(exec, SyntaxError);
+
+ unsigned target = args.at(0).toInt32(exec);
+ unsigned usage = args.at(2).toInt32(exec);
+
+ // If argument 1 is a number, we are initializing this buffer to that size
+ if (!args.at(1).isObject()) {
+ unsigned int count = args.at(1).toInt32(exec);
+ static_cast<CanvasRenderingContext3D*>(impl())->bufferData(target, count, usage);
+ return jsUndefined();
+ }
+
+ CanvasArray* array = toCanvasArray(args.at(1));
+
+ static_cast<CanvasRenderingContext3D*>(impl())->bufferData(target, array, usage);
+ return jsUndefined();
+}
+
+JSValue JSCanvasRenderingContext3D::bufferSubData(JSC::ExecState* exec, JSC::ArgList const& args)
+{
+ if (args.size() != 3)
+ return throwError(exec, SyntaxError);
+
+ unsigned target = args.at(0).toInt32(exec);
+ unsigned offset = args.at(1).toInt32(exec);
+
+ CanvasArray* array = toCanvasArray(args.at(2));
+
+ static_cast<CanvasRenderingContext3D*>(impl())->bufferSubData(target, offset, array);
+ return jsUndefined();
+}
+
+// void texImage2DHTML(in unsigned long target, in unsigned long level, in HTMLImageElement image);
+JSValue JSCanvasRenderingContext3D::texImage2D(ExecState* exec, const ArgList& args)
+{
+ if (args.size() < 3)
+ return throwError(exec, SyntaxError);
+
+ ExceptionCode ec = 0;
+ CanvasRenderingContext3D* context = static_cast<CanvasRenderingContext3D*>(impl());
+ unsigned target = args.at(0).toInt32(exec);
+ if (exec->hadException())
+ return jsUndefined();
+
+ unsigned level = args.at(1).toInt32(exec);
+ if (exec->hadException())
+ return jsUndefined();
+
+ if (args.size() > 5) {
+ // This must be the bare array case.
+ if (args.size() != 9)
+ return throwError(exec, SyntaxError);
+
+ unsigned internalformat = args.at(2).toInt32(exec);
+ if (exec->hadException())
+ return jsUndefined();
+
+ unsigned width = args.at(3).toInt32(exec);
+ if (exec->hadException())
+ return jsUndefined();
+
+ unsigned height = args.at(4).toInt32(exec);
+ if (exec->hadException())
+ return jsUndefined();
+
+ unsigned border = args.at(5).toInt32(exec);
+ if (exec->hadException())
+ return jsUndefined();
+
+ unsigned format = args.at(6).toInt32(exec);
+ if (exec->hadException())
+ return jsUndefined();
+
+ unsigned type = args.at(7).toInt32(exec);
+ if (exec->hadException())
+ return jsUndefined();
+
+ CanvasArray* array = toCanvasArray(args.at(8));
+ if (exec->hadException())
+ return jsUndefined();
+
+ if (!array)
+ return throwError(exec, TypeError);
+
+ // FIXME: Need to check to make sure CanvasArray is a CanvasByteArray or CanvasShortArray,
+ // depending on the passed type parameter.
+
+ context->texImage2D(target, level, internalformat, width, height, border, format, type, array, ec);
+ return jsUndefined();
+ }
+
+ // The image parameter can be a <img> or <canvas> element.
+ JSValue value = args.at(2);
+ if (!value.isObject())
+ return throwError(exec, TypeError);
+ JSObject* o = asObject(value);
+
+ bool flipY = (args.size() > 3) ? args.at(3).toBoolean(exec) : false;
+ bool premultiplyAlpha = (args.size() > 4) ? args.at(3).toBoolean(exec) : false;
+
+ if (o->inherits(&JSHTMLImageElement::s_info)) {
+ HTMLImageElement* imgElt = static_cast<HTMLImageElement*>(static_cast<JSHTMLElement*>(o)->impl());
+ context->texImage2D(target, level, imgElt, flipY, premultiplyAlpha, ec);
+ } else if (o->inherits(&JSHTMLCanvasElement::s_info)) {
+ HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(static_cast<JSHTMLElement*>(o)->impl());
+ context->texImage2D(target, level, canvas, flipY, premultiplyAlpha, ec);
+ } else {
+ setDOMException(exec, TYPE_MISMATCH_ERR);
+ }
+
+ return jsUndefined();
+}
+
+// void texSubImage2DHTML(in unsigned long target, in unsigned long level, in unsigned long xoff, in unsigned long yoff, in unsigned long width, in unsigned long height, in HTMLImageElement image);
+JSValue JSCanvasRenderingContext3D::texSubImage2D(ExecState* exec, const ArgList& args)
+{
+ if (args.size() < 7 || args.size() > 9)
+ return throwError(exec, SyntaxError);
+
+ CanvasRenderingContext3D* context = static_cast<CanvasRenderingContext3D*>(impl());
+ unsigned target = args.at(0).toInt32(exec);
+ unsigned level = args.at(1).toInt32(exec);
+ unsigned xoff = args.at(2).toInt32(exec);
+ unsigned yoff = args.at(3).toInt32(exec);
+ unsigned width = args.at(4).toInt32(exec);
+ unsigned height = args.at(5).toInt32(exec);
+
+ // The image parameter can be a <img> or <canvas> element.
+ JSValue value = args.at(6);
+ if (!value.isObject())
+ return throwError(exec, TypeError);
+ JSObject* o = asObject(value);
+
+ bool flipY = (args.size() > 3) ? args.at(3).toBoolean(exec) : false;
+ bool premultiplyAlpha = (args.size() > 4) ? args.at(3).toBoolean(exec) : false;
+
+ ExceptionCode ec = 0;
+ if (o->inherits(&JSHTMLImageElement::s_info)) {
+ HTMLImageElement* imgElt = static_cast<HTMLImageElement*>(static_cast<JSHTMLElement*>(o)->impl());
+ context->texSubImage2D(target, level, xoff, yoff, width, height, imgElt, flipY, premultiplyAlpha, ec);
+ } else if (o->inherits(&JSHTMLCanvasElement::s_info)) {
+ HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(static_cast<JSHTMLElement*>(o)->impl());
+ context->texSubImage2D(target, level, xoff, yoff, width, height, canvas, flipY, premultiplyAlpha, ec);
+ } else {
+ setDOMException(exec, TYPE_MISMATCH_ERR);
+ }
+
+ return jsUndefined();
+}
+
+template<typename T>
+void toArray(JSC::ExecState* exec, JSC::JSValue value, T*& array, int& size)
+{
+ array = 0;
+
+ if (!value.isObject())
+ return;
+
+ JSC::JSObject* object = asObject(value);
+ int length = object->get(exec, JSC::Identifier(exec, "length")).toInt32(exec);
+ void* tempValues;
+ if (!tryFastMalloc(length * sizeof(T)).getValue(tempValues))
+ return;
+
+ T* values = static_cast<T*>(tempValues);
+ for (int i = 0; i < length; ++i) {
+ JSC::JSValue v = object->get(exec, i);
+ if (exec->hadException())
+ return;
+ values[i] = static_cast<T>(v.toNumber(exec));
+ }
+
+ array = values;
+ size = length;
+}
+
+enum DataFunctionToCall {
+ f_uniform1v, f_uniform2v, f_uniform3v, f_uniform4v,
+ f_vertexAttrib1v, f_vertexAttrib2v, f_vertexAttrib3v, f_vertexAttrib4v
+};
+
+enum DataFunctionMatrixToCall {
+ f_uniformMatrix2fv, f_uniformMatrix3fv, f_uniformMatrix4fv
+};
+
+static JSC::JSValue dataFunctionf(DataFunctionToCall f, JSC::ExecState* exec, const JSC::ArgList& args, CanvasRenderingContext3D* context)
+{
+ if (args.size() != 2)
+ return throwError(exec, SyntaxError);
+
+ long location = args.at(0).toInt32(exec);
+ if (exec->hadException())
+ return jsUndefined();
+
+ RefPtr<CanvasFloatArray> canvasArray = toCanvasFloatArray(args.at(1));
+ if (exec->hadException())
+ return jsUndefined();
+
+ if (canvasArray) {
+ switch(f) {
+ case f_uniform1v: context->uniform1fv(location, canvasArray.get()); break;
+ case f_uniform2v: context->uniform2fv(location, canvasArray.get()); break;
+ case f_uniform3v: context->uniform3fv(location, canvasArray.get()); break;
+ case f_uniform4v: context->uniform4fv(location, canvasArray.get()); break;
+ case f_vertexAttrib1v: context->vertexAttrib1fv(location, canvasArray.get()); break;
+ case f_vertexAttrib2v: context->vertexAttrib2fv(location, canvasArray.get()); break;
+ case f_vertexAttrib3v: context->vertexAttrib3fv(location, canvasArray.get()); break;
+ case f_vertexAttrib4v: context->vertexAttrib4fv(location, canvasArray.get()); break;
+ }
+ return jsUndefined();
+ }
+
+ float* array;
+ int size;
+ toArray<float>(exec, args.at(1), array, size);
+
+ if (!array)
+ return throwError(exec, TypeError);
+
+ switch(f) {
+ case f_uniform1v: context->uniform1fv(location, array, size); break;
+ case f_uniform2v: context->uniform2fv(location, array, size); break;
+ case f_uniform3v: context->uniform3fv(location, array, size); break;
+ case f_uniform4v: context->uniform4fv(location, array, size); break;
+ case f_vertexAttrib1v: context->vertexAttrib1fv(location, array, size); break;
+ case f_vertexAttrib2v: context->vertexAttrib2fv(location, array, size); break;
+ case f_vertexAttrib3v: context->vertexAttrib3fv(location, array, size); break;
+ case f_vertexAttrib4v: context->vertexAttrib4fv(location, array, size); break;
+ }
+ return jsUndefined();
+}
+
+static JSC::JSValue dataFunctioni(DataFunctionToCall f, JSC::ExecState* exec, const JSC::ArgList& args, CanvasRenderingContext3D* context)
+{
+ if (args.size() != 2)
+ return throwError(exec, SyntaxError);
+
+ long location = args.at(0).toInt32(exec);
+ if (exec->hadException())
+ return jsUndefined();
+
+ RefPtr<CanvasIntArray> canvasArray = toCanvasIntArray(args.at(1));
+ if (exec->hadException())
+ return jsUndefined();
+
+ if (canvasArray) {
+ switch(f) {
+ case f_uniform1v: context->uniform1iv(location, canvasArray.get()); break;
+ case f_uniform2v: context->uniform2iv(location, canvasArray.get()); break;
+ case f_uniform3v: context->uniform3iv(location, canvasArray.get()); break;
+ case f_uniform4v: context->uniform4iv(location, canvasArray.get()); break;
+ default: break;
+ }
+ return jsUndefined();
+ }
+
+ int* array;
+ int size;
+ toArray<int>(exec, args.at(1), array, size);
+
+ if (!array)
+ return throwError(exec, TypeError);
+
+ switch(f) {
+ case f_uniform1v: context->uniform1iv(location, array, size); break;
+ case f_uniform2v: context->uniform2iv(location, array, size); break;
+ case f_uniform3v: context->uniform3iv(location, array, size); break;
+ case f_uniform4v: context->uniform4iv(location, array, size); break;
+ default: break;
+ }
+ return jsUndefined();
+}
+
+static JSC::JSValue dataFunctionMatrix(DataFunctionMatrixToCall f, JSC::ExecState* exec, const JSC::ArgList& args, CanvasRenderingContext3D* context)
+{
+ if (args.size() != 3)
+ return throwError(exec, SyntaxError);
+
+ long location = args.at(0).toInt32(exec);
+ if (exec->hadException())
+ return jsUndefined();
+
+ bool transpose = args.at(1).toBoolean(exec);
+ if (exec->hadException())
+ return jsUndefined();
+
+ RefPtr<CanvasFloatArray> canvasArray = toCanvasFloatArray(args.at(2));
+ if (exec->hadException())
+ return jsUndefined();
+
+ if (canvasArray) {
+ switch(f) {
+ case f_uniformMatrix2fv: context->uniformMatrix2fv(location, transpose, canvasArray.get()); break;
+ case f_uniformMatrix3fv: context->uniformMatrix3fv(location, transpose, canvasArray.get()); break;
+ case f_uniformMatrix4fv: context->uniformMatrix4fv(location, transpose, canvasArray.get()); break;
+ }
+ return jsUndefined();
+ }
+
+ float* array;
+ int size;
+ toArray<float>(exec, args.at(2), array, size);
+
+ if (!array)
+ return throwError(exec, TypeError);
+
+ switch(f) {
+ case f_uniformMatrix2fv: context->uniformMatrix2fv(location, transpose, array, size); break;
+ case f_uniformMatrix3fv: context->uniformMatrix3fv(location, transpose, array, size); break;
+ case f_uniformMatrix4fv: context->uniformMatrix4fv(location, transpose, array, size); break;
+ }
+ return jsUndefined();
+}
+
+JSC::JSValue JSCanvasRenderingContext3D::uniform1fv(JSC::ExecState* exec, const JSC::ArgList& args)
+{
+ return dataFunctionf(f_uniform1v, exec, args, static_cast<CanvasRenderingContext3D*>(impl()));
+}
+
+JSC::JSValue JSCanvasRenderingContext3D::uniform1iv(JSC::ExecState* exec, const JSC::ArgList& args)
+{
+ return dataFunctioni(f_uniform1v, exec, args, static_cast<CanvasRenderingContext3D*>(impl()));
+}
+
+JSC::JSValue JSCanvasRenderingContext3D::uniform2fv(JSC::ExecState* exec, const JSC::ArgList& args)
+{
+ return dataFunctionf(f_uniform2v, exec, args, static_cast<CanvasRenderingContext3D*>(impl()));
+}
+
+JSC::JSValue JSCanvasRenderingContext3D::uniform2iv(JSC::ExecState* exec, const JSC::ArgList& args)
+{
+ return dataFunctioni(f_uniform2v, exec, args, static_cast<CanvasRenderingContext3D*>(impl()));
+}
+
+JSC::JSValue JSCanvasRenderingContext3D::uniform3fv(JSC::ExecState* exec, const JSC::ArgList& args)
+{
+ return dataFunctionf(f_uniform3v, exec, args, static_cast<CanvasRenderingContext3D*>(impl()));
+}
+
+JSC::JSValue JSCanvasRenderingContext3D::uniform3iv(JSC::ExecState* exec, const JSC::ArgList& args)
+{
+ return dataFunctioni(f_uniform3v, exec, args, static_cast<CanvasRenderingContext3D*>(impl()));
+}
+
+JSC::JSValue JSCanvasRenderingContext3D::uniform4fv(JSC::ExecState* exec, const JSC::ArgList& args)
+{
+ return dataFunctionf(f_uniform4v, exec, args, static_cast<CanvasRenderingContext3D*>(impl()));
+}
+
+JSC::JSValue JSCanvasRenderingContext3D::uniform4iv(JSC::ExecState* exec, const JSC::ArgList& args)
+{
+ return dataFunctioni(f_uniform4v, exec, args, static_cast<CanvasRenderingContext3D*>(impl()));
+}
+
+JSC::JSValue JSCanvasRenderingContext3D::uniformMatrix2fv(JSC::ExecState* exec, const JSC::ArgList& args)
+{
+ return dataFunctionMatrix(f_uniformMatrix2fv, exec, args, static_cast<CanvasRenderingContext3D*>(impl()));
+}
+
+JSC::JSValue JSCanvasRenderingContext3D::uniformMatrix3fv(JSC::ExecState* exec, const JSC::ArgList& args)
+{
+ return dataFunctionMatrix(f_uniformMatrix3fv, exec, args, static_cast<CanvasRenderingContext3D*>(impl()));
+}
+
+JSC::JSValue JSCanvasRenderingContext3D::uniformMatrix4fv(JSC::ExecState* exec, const JSC::ArgList& args)
+{
+ return dataFunctionMatrix(f_uniformMatrix4fv, exec, args, static_cast<CanvasRenderingContext3D*>(impl()));
+}
+
+JSC::JSValue JSCanvasRenderingContext3D::vertexAttrib1fv(JSC::ExecState* exec, const JSC::ArgList& args)
+{
+ return dataFunctionf(f_vertexAttrib1v, exec, args, static_cast<CanvasRenderingContext3D*>(impl()));
+}
+
+JSC::JSValue JSCanvasRenderingContext3D::vertexAttrib2fv(JSC::ExecState* exec, const JSC::ArgList& args)
+{
+ return dataFunctionf(f_vertexAttrib2v, exec, args, static_cast<CanvasRenderingContext3D*>(impl()));
+}
+
+JSC::JSValue JSCanvasRenderingContext3D::vertexAttrib3fv(JSC::ExecState* exec, const JSC::ArgList& args)
+{
+ return dataFunctionf(f_vertexAttrib3v, exec, args, static_cast<CanvasRenderingContext3D*>(impl()));
+}
+
+JSC::JSValue JSCanvasRenderingContext3D::vertexAttrib4fv(JSC::ExecState* exec, const JSC::ArgList& args)
+{
+ return dataFunctionf(f_vertexAttrib4v, exec, args, static_cast<CanvasRenderingContext3D*>(impl()));
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/bindings/js/JSCanvasRenderingContextCustom.cpp b/WebCore/bindings/js/JSCanvasRenderingContextCustom.cpp
new file mode 100644
index 0000000..0cd2aa3
--- /dev/null
+++ b/WebCore/bindings/js/JSCanvasRenderingContextCustom.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSCanvasRenderingContext.h"
+
+#include "CanvasRenderingContext2D.h"
+#include "JSCanvasRenderingContext2D.h"
+#if ENABLE(3D_CANVAS)
+#include "CanvasRenderingContext3D.h"
+#include "JSCanvasRenderingContext3D.h"
+#endif
+
+using namespace JSC;
+
+namespace WebCore {
+
+JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, CanvasRenderingContext* object)
+{
+ if (!object)
+ return jsUndefined();
+
+#if ENABLE(3D_CANVAS)
+ if (object->is3d())
+ return getDOMObjectWrapper<JSCanvasRenderingContext3D>(exec, globalObject, static_cast<CanvasRenderingContext3D*>(object));
+#endif
+ ASSERT(object->is2d());
+ return getDOMObjectWrapper<JSCanvasRenderingContext2D>(exec, globalObject, static_cast<CanvasRenderingContext2D*>(object));
+}
+
+} // namespace WebCore
diff --git a/WebCore/bindings/js/JSCanvasShortArrayConstructor.cpp b/WebCore/bindings/js/JSCanvasShortArrayConstructor.cpp
new file mode 100644
index 0000000..a885b7b
--- /dev/null
+++ b/WebCore/bindings/js/JSCanvasShortArrayConstructor.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(3D_CANVAS)
+
+#include "JSCanvasShortArrayConstructor.h"
+
+#include "Document.h"
+#include "CanvasShortArray.h"
+#include "JSCanvasArray.h"
+#include "JSCanvasArrayBuffer.h"
+#include "JSCanvasArrayBufferConstructor.h"
+#include "JSCanvasShortArray.h"
+#include <runtime/Error.h>
+
+namespace WebCore {
+
+using namespace JSC;
+
+const ClassInfo JSCanvasShortArrayConstructor::s_info = { "CanvasShortArrayConstructor", &JSCanvasArray::s_info, 0, 0 };
+
+JSCanvasShortArrayConstructor::JSCanvasShortArrayConstructor(ExecState* exec, JSDOMGlobalObject* globalObject)
+ : DOMConstructorObject(JSCanvasShortArrayConstructor::createStructure(globalObject->objectPrototype()), globalObject)
+{
+ putDirect(exec->propertyNames().prototype, JSCanvasShortArrayPrototype::self(exec, globalObject), None);
+ putDirect(exec->propertyNames().length, jsNumber(exec, 2), ReadOnly|DontDelete|DontEnum);
+}
+
+static JSObject* constructCanvasShortArray(ExecState* exec, JSObject* constructor, const ArgList& args)
+{
+ JSCanvasShortArrayConstructor* jsConstructor = static_cast<JSCanvasShortArrayConstructor*>(constructor);
+ RefPtr<CanvasShortArray> array = static_cast<CanvasShortArray*>(construct<CanvasShortArray, short>(exec, args).get());
+ return asObject(toJS(exec, jsConstructor->globalObject(), array.get()));
+}
+
+JSC::ConstructType JSCanvasShortArrayConstructor::getConstructData(JSC::ConstructData& constructData)
+{
+ constructData.native.function = constructCanvasShortArray;
+ return ConstructTypeHost;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/bindings/js/JSCanvasShortArrayConstructor.h b/WebCore/bindings/js/JSCanvasShortArrayConstructor.h
new file mode 100644
index 0000000..df21825
--- /dev/null
+++ b/WebCore/bindings/js/JSCanvasShortArrayConstructor.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JSCanvasShortArrayConstructor_h
+#define JSCanvasShortArrayConstructor_h
+
+#include "JSDOMBinding.h"
+#include "JSDocument.h"
+
+namespace WebCore {
+
+ class JSCanvasShortArrayConstructor : public DOMConstructorObject {
+ public:
+ JSCanvasShortArrayConstructor(JSC::ExecState*, JSDOMGlobalObject*);
+ static const JSC::ClassInfo s_info;
+
+ private:
+ virtual JSC::ConstructType getConstructData(JSC::ConstructData&);
+ virtual const JSC::ClassInfo* classInfo() const { return &s_info; }
+ };
+
+}
+
+#endif // JSCanvasShortArrayConstructor_h
diff --git a/WebCore/bindings/js/JSCanvasShortArrayCustom.cpp b/WebCore/bindings/js/JSCanvasShortArrayCustom.cpp
new file mode 100644
index 0000000..21af0a6
--- /dev/null
+++ b/WebCore/bindings/js/JSCanvasShortArrayCustom.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(3D_CANVAS)
+
+#include "JSCanvasShortArray.h"
+
+#include "CanvasShortArray.h"
+
+using namespace JSC;
+
+namespace WebCore {
+
+void JSCanvasShortArray::indexSetter(JSC::ExecState* exec, unsigned index, JSC::JSValue value)
+{
+ impl()->set(index, static_cast<signed short>(value.toInt32(exec)));
+}
+
+JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, CanvasShortArray* object)
+{
+ return getDOMObjectWrapper<JSCanvasShortArray>(exec, globalObject, object);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/bindings/js/JSCanvasUnsignedByteArrayConstructor.cpp b/WebCore/bindings/js/JSCanvasUnsignedByteArrayConstructor.cpp
new file mode 100644
index 0000000..5d0800e
--- /dev/null
+++ b/WebCore/bindings/js/JSCanvasUnsignedByteArrayConstructor.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(3D_CANVAS)
+
+#include "JSCanvasUnsignedByteArrayConstructor.h"
+
+#include "Document.h"
+#include "CanvasUnsignedByteArray.h"
+#include "JSCanvasArrayBuffer.h"
+#include "JSCanvasArrayBufferConstructor.h"
+#include "JSCanvasUnsignedByteArray.h"
+#include <runtime/Error.h>
+
+namespace WebCore {
+
+using namespace JSC;
+
+const ClassInfo JSCanvasUnsignedByteArrayConstructor::s_info = { "CanvasUnsignedByteArrayConstructor", &JSCanvasArray::s_info, 0, 0 };
+
+JSCanvasUnsignedByteArrayConstructor::JSCanvasUnsignedByteArrayConstructor(ExecState* exec, JSDOMGlobalObject* globalObject)
+ : DOMConstructorObject(JSCanvasUnsignedByteArrayConstructor::createStructure(globalObject->objectPrototype()), globalObject)
+{
+ putDirect(exec->propertyNames().prototype, JSCanvasUnsignedByteArrayPrototype::self(exec, globalObject), None);
+ putDirect(exec->propertyNames().length, jsNumber(exec, 2), ReadOnly|DontDelete|DontEnum);
+}
+
+static JSObject* constructCanvasUnsignedByteArray(ExecState* exec, JSObject* constructor, const ArgList& args)
+{
+ JSCanvasUnsignedByteArrayConstructor* jsConstructor = static_cast<JSCanvasUnsignedByteArrayConstructor*>(constructor);
+ RefPtr<CanvasUnsignedByteArray> array = static_cast<CanvasUnsignedByteArray*>(construct<CanvasUnsignedByteArray, unsigned char>(exec, args).get());
+ return asObject(toJS(exec, jsConstructor->globalObject(), array.get()));
+}
+
+JSC::ConstructType JSCanvasUnsignedByteArrayConstructor::getConstructData(JSC::ConstructData& constructData)
+{
+ constructData.native.function = constructCanvasUnsignedByteArray;
+ return ConstructTypeHost;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/bindings/js/JSCanvasUnsignedByteArrayConstructor.h b/WebCore/bindings/js/JSCanvasUnsignedByteArrayConstructor.h
new file mode 100644
index 0000000..9cfb721
--- /dev/null
+++ b/WebCore/bindings/js/JSCanvasUnsignedByteArrayConstructor.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JSCanvasUnsignedByteArrayConstructor_h
+#define JSCanvasUnsignedByteArrayConstructor_h
+
+#include "JSDOMBinding.h"
+#include "JSDocument.h"
+
+namespace WebCore {
+
+ class JSCanvasUnsignedByteArrayConstructor : public DOMConstructorObject {
+ public:
+ JSCanvasUnsignedByteArrayConstructor(JSC::ExecState*, JSDOMGlobalObject*);
+ static const JSC::ClassInfo s_info;
+
+ private:
+ virtual JSC::ConstructType getConstructData(JSC::ConstructData&);
+ virtual const JSC::ClassInfo* classInfo() const { return &s_info; }
+ };
+
+}
+
+#endif // JSCanvasUnsignedByteArrayConstructor_h
diff --git a/WebCore/bindings/js/JSCanvasUnsignedByteArrayCustom.cpp b/WebCore/bindings/js/JSCanvasUnsignedByteArrayCustom.cpp
new file mode 100644
index 0000000..f2b0c74
--- /dev/null
+++ b/WebCore/bindings/js/JSCanvasUnsignedByteArrayCustom.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(3D_CANVAS)
+
+#include "JSCanvasUnsignedByteArray.h"
+
+#include "CanvasUnsignedByteArray.h"
+
+using namespace JSC;
+
+namespace WebCore {
+
+void JSCanvasUnsignedByteArray::indexSetter(JSC::ExecState* exec, unsigned index, JSC::JSValue value)
+{
+ impl()->set(index, static_cast<unsigned char>(value.toInt32(exec)));
+}
+
+JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, CanvasUnsignedByteArray* object)
+{
+ return getDOMObjectWrapper<JSCanvasUnsignedByteArray>(exec, globalObject, object);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/bindings/js/JSCanvasUnsignedIntArrayConstructor.cpp b/WebCore/bindings/js/JSCanvasUnsignedIntArrayConstructor.cpp
new file mode 100644
index 0000000..5f145a7
--- /dev/null
+++ b/WebCore/bindings/js/JSCanvasUnsignedIntArrayConstructor.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(3D_CANVAS)
+
+#include "JSCanvasUnsignedIntArrayConstructor.h"
+
+#include "Document.h"
+#include "CanvasUnsignedIntArray.h"
+#include "JSCanvasArrayBuffer.h"
+#include "JSCanvasArrayBufferConstructor.h"
+#include "JSCanvasUnsignedIntArray.h"
+#include <runtime/Error.h>
+
+namespace WebCore {
+
+using namespace JSC;
+
+const ClassInfo JSCanvasUnsignedIntArrayConstructor::s_info = { "CanvasUnsignedIntArrayConstructor", &JSCanvasArray::s_info, 0, 0 };
+
+JSCanvasUnsignedIntArrayConstructor::JSCanvasUnsignedIntArrayConstructor(ExecState* exec, JSDOMGlobalObject* globalObject)
+ : DOMConstructorObject(JSCanvasUnsignedIntArrayConstructor::createStructure(globalObject->objectPrototype()), globalObject)
+{
+ putDirect(exec->propertyNames().prototype, JSCanvasUnsignedIntArrayPrototype::self(exec, globalObject), None);
+ putDirect(exec->propertyNames().length, jsNumber(exec, 2), ReadOnly|DontDelete|DontEnum);
+}
+
+static JSObject* constructCanvasUnsignedIntArray(ExecState* exec, JSObject* constructor, const ArgList& args)
+{
+ JSCanvasUnsignedIntArrayConstructor* jsConstructor = static_cast<JSCanvasUnsignedIntArrayConstructor*>(constructor);
+ RefPtr<CanvasUnsignedIntArray> array = static_cast<CanvasUnsignedIntArray*>(construct<CanvasUnsignedIntArray, unsigned int>(exec, args).get());
+ return asObject(toJS(exec, jsConstructor->globalObject(), array.get()));
+}
+
+JSC::ConstructType JSCanvasUnsignedIntArrayConstructor::getConstructData(JSC::ConstructData& constructData)
+{
+ constructData.native.function = constructCanvasUnsignedIntArray;
+ return ConstructTypeHost;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/bindings/js/JSCanvasUnsignedIntArrayConstructor.h b/WebCore/bindings/js/JSCanvasUnsignedIntArrayConstructor.h
new file mode 100644
index 0000000..6016159
--- /dev/null
+++ b/WebCore/bindings/js/JSCanvasUnsignedIntArrayConstructor.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JSCanvasUnsignedIntArrayConstructor_h
+#define JSCanvasUnsignedIntArrayConstructor_h
+
+#include "JSDOMBinding.h"
+#include "JSDocument.h"
+
+namespace WebCore {
+
+ class JSCanvasUnsignedIntArrayConstructor : public DOMConstructorObject {
+ public:
+ JSCanvasUnsignedIntArrayConstructor(JSC::ExecState*, JSDOMGlobalObject*);
+ static const JSC::ClassInfo s_info;
+
+ private:
+ virtual JSC::ConstructType getConstructData(JSC::ConstructData&);
+ virtual const JSC::ClassInfo* classInfo() const { return &s_info; }
+ };
+
+}
+
+#endif // JSCanvasUnsignedIntArrayConstructor_h
diff --git a/WebCore/bindings/js/JSCanvasUnsignedIntArrayCustom.cpp b/WebCore/bindings/js/JSCanvasUnsignedIntArrayCustom.cpp
new file mode 100644
index 0000000..95a80a7
--- /dev/null
+++ b/WebCore/bindings/js/JSCanvasUnsignedIntArrayCustom.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(3D_CANVAS)
+
+#include "JSCanvasUnsignedIntArray.h"
+
+#include "CanvasUnsignedIntArray.h"
+
+using namespace JSC;
+
+namespace WebCore {
+
+void JSCanvasUnsignedIntArray::indexSetter(JSC::ExecState* exec, unsigned index, JSC::JSValue value)
+{
+ impl()->set(index, static_cast<unsigned int>(value.toInt32(exec)));
+}
+
+JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, CanvasUnsignedIntArray* object)
+{
+ return getDOMObjectWrapper<JSCanvasUnsignedIntArray>(exec, globalObject, object);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/bindings/js/JSCanvasUnsignedShortArrayConstructor.cpp b/WebCore/bindings/js/JSCanvasUnsignedShortArrayConstructor.cpp
new file mode 100644
index 0000000..9735693
--- /dev/null
+++ b/WebCore/bindings/js/JSCanvasUnsignedShortArrayConstructor.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(3D_CANVAS)
+
+#include "JSCanvasUnsignedShortArrayConstructor.h"
+
+#include "Document.h"
+#include "CanvasUnsignedShortArray.h"
+#include "JSCanvasArrayBuffer.h"
+#include "JSCanvasArrayBufferConstructor.h"
+#include "JSCanvasUnsignedShortArray.h"
+#include <runtime/Error.h>
+
+namespace WebCore {
+
+using namespace JSC;
+
+const ClassInfo JSCanvasUnsignedShortArrayConstructor::s_info = { "CanvasUnsignedShortArrayConstructor", &JSCanvasArray::s_info, 0, 0 };
+
+JSCanvasUnsignedShortArrayConstructor::JSCanvasUnsignedShortArrayConstructor(ExecState* exec, JSDOMGlobalObject* globalObject)
+ : DOMConstructorObject(JSCanvasUnsignedShortArrayConstructor::createStructure(globalObject->objectPrototype()), globalObject)
+{
+ putDirect(exec->propertyNames().prototype, JSCanvasUnsignedShortArrayPrototype::self(exec, globalObject), None);
+ putDirect(exec->propertyNames().length, jsNumber(exec, 2), ReadOnly|DontDelete|DontEnum);
+}
+
+static JSObject* constructCanvasUnsignedShortArray(ExecState* exec, JSObject* constructor, const ArgList& args)
+{
+ JSCanvasUnsignedShortArrayConstructor* jsConstructor = static_cast<JSCanvasUnsignedShortArrayConstructor*>(constructor);
+ RefPtr<CanvasUnsignedShortArray> array = static_cast<CanvasUnsignedShortArray*>(construct<CanvasUnsignedShortArray, unsigned short>(exec, args).get());
+ return asObject(toJS(exec, jsConstructor->globalObject(), array.get()));
+}
+
+JSC::ConstructType JSCanvasUnsignedShortArrayConstructor::getConstructData(JSC::ConstructData& constructData)
+{
+ constructData.native.function = constructCanvasUnsignedShortArray;
+ return ConstructTypeHost;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/bindings/js/JSCanvasUnsignedShortArrayConstructor.h b/WebCore/bindings/js/JSCanvasUnsignedShortArrayConstructor.h
new file mode 100644
index 0000000..23c197f
--- /dev/null
+++ b/WebCore/bindings/js/JSCanvasUnsignedShortArrayConstructor.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JSCanvasUnsignedShortArrayConstructor_h
+#define JSCanvasUnsignedShortArrayConstructor_h
+
+#include "JSDOMBinding.h"
+#include "JSDocument.h"
+
+namespace WebCore {
+
+ class JSCanvasUnsignedShortArrayConstructor : public DOMConstructorObject {
+ public:
+ JSCanvasUnsignedShortArrayConstructor(JSC::ExecState*, JSDOMGlobalObject*);
+ static const JSC::ClassInfo s_info;
+
+ private:
+ virtual JSC::ConstructType getConstructData(JSC::ConstructData&);
+ virtual const JSC::ClassInfo* classInfo() const { return &s_info; }
+ };
+
+}
+
+#endif // JSCanvasUnsignedShortArrayConstructor_h
diff --git a/WebCore/bindings/js/JSCanvasUnsignedShortArrayCustom.cpp b/WebCore/bindings/js/JSCanvasUnsignedShortArrayCustom.cpp
new file mode 100644
index 0000000..290cd4b
--- /dev/null
+++ b/WebCore/bindings/js/JSCanvasUnsignedShortArrayCustom.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(3D_CANVAS)
+
+#include "JSCanvasUnsignedShortArray.h"
+
+#include "CanvasUnsignedShortArray.h"
+
+using namespace JSC;
+
+namespace WebCore {
+
+void JSCanvasUnsignedShortArray::indexSetter(JSC::ExecState* exec, unsigned index, JSC::JSValue value)
+{
+ impl()->set(index, static_cast<unsigned short>(value.toInt32(exec)));
+}
+
+JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, CanvasUnsignedShortArray* object)
+{
+ return getDOMObjectWrapper<JSCanvasUnsignedShortArray>(exec, globalObject, object);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/bindings/js/JSCustomPositionCallback.cpp b/WebCore/bindings/js/JSCustomPositionCallback.cpp
index ec2d8e3..e5f83aa 100644
--- a/WebCore/bindings/js/JSCustomPositionCallback.cpp
+++ b/WebCore/bindings/js/JSCustomPositionCallback.cpp
@@ -35,52 +35,20 @@ namespace WebCore {
using namespace JSC;
-JSCustomPositionCallback::JSCustomPositionCallback(JSObject* callback, Frame* frame)
- : m_callback(callback)
- , m_frame(frame)
+JSCustomPositionCallback::JSCustomPositionCallback(JSObject* callback, JSDOMGlobalObject* globalObject)
+ : m_data(callback, globalObject)
{
}
void JSCustomPositionCallback::handleEvent(Geoposition* geoposition)
{
- ASSERT(m_callback);
- ASSERT(m_frame);
-
- if (!m_frame->script()->isEnabled())
- return;
-
- // FIXME: This is likely the wrong globalObject (for prototype chains at least)
- JSGlobalObject* globalObject = m_frame->script()->globalObject();
- ExecState* exec = globalObject->globalExec();
-
- JSC::JSLock lock(SilenceAssertionsOnly);
-
- JSValue function = m_callback->get(exec, Identifier(exec, "handleEvent"));
- CallData callData;
- CallType callType = function.getCallData(callData);
- if (callType == CallTypeNone) {
- callType = m_callback->getCallData(callData);
- if (callType == CallTypeNone) {
- // FIXME: Should an exception be thrown here?
- return;
- }
- function = m_callback;
- }
-
RefPtr<JSCustomPositionCallback> protect(this);
+ JSC::JSLock lock(SilenceAssertionsOnly);
+ ExecState* exec = m_data.globalObject()->globalExec();
MarkedArgumentBuffer args;
args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), geoposition));
-
- globalObject->globalData()->timeoutChecker.start();
- call(exec, function, callType, callData, m_callback, args);
- globalObject->globalData()->timeoutChecker.stop();
-
- if (exec->hadException()) {
- reportCurrentException(exec);
- }
-
- Document::updateStyleForAllDocuments();
+ m_data.invokeCallback(args);
}
} // namespace WebCore
diff --git a/WebCore/bindings/js/JSCustomPositionCallback.h b/WebCore/bindings/js/JSCustomPositionCallback.h
index 9c8fe86..ad5528d 100644
--- a/WebCore/bindings/js/JSCustomPositionCallback.h
+++ b/WebCore/bindings/js/JSCustomPositionCallback.h
@@ -26,31 +26,28 @@
#ifndef JSCustomPositionCallback_h
#define JSCustomPositionCallback_h
+#include "JSCallbackData.h"
#include "PositionCallback.h"
-#include <runtime/JSObject.h>
-#include <runtime/Protect.h>
#include <wtf/Forward.h>
-namespace JSC {
- class JSObject;
-}
-
namespace WebCore {
-class Frame;
class Geoposition;
+class JSDOMGlobalObject;
class JSCustomPositionCallback : public PositionCallback {
public:
- static PassRefPtr<JSCustomPositionCallback> create(JSC::JSObject* callback, Frame* frame) { return adoptRef(new JSCustomPositionCallback(callback, frame)); }
+ static PassRefPtr<JSCustomPositionCallback> create(JSC::JSObject* callback, JSDOMGlobalObject* globalObject)
+ {
+ return adoptRef(new JSCustomPositionCallback(callback, globalObject));
+ }
- virtual void handleEvent(Geoposition*);
-
private:
- JSCustomPositionCallback(JSC::JSObject* callback, Frame*);
+ JSCustomPositionCallback(JSC::JSObject* callback, JSDOMGlobalObject*);
- JSC::ProtectedPtr<JSC::JSObject> m_callback;
- RefPtr<Frame> m_frame;
+ virtual void handleEvent(Geoposition*);
+
+ JSCallbackData m_data;
};
} // namespace WebCore
diff --git a/WebCore/bindings/js/JSCustomPositionErrorCallback.cpp b/WebCore/bindings/js/JSCustomPositionErrorCallback.cpp
index cda5738..bd64deb 100644
--- a/WebCore/bindings/js/JSCustomPositionErrorCallback.cpp
+++ b/WebCore/bindings/js/JSCustomPositionErrorCallback.cpp
@@ -35,51 +35,21 @@ namespace WebCore {
using namespace JSC;
-JSCustomPositionErrorCallback::JSCustomPositionErrorCallback(JSObject* callback, Frame* frame)
- : m_callback(callback)
- , m_frame(frame)
+JSCustomPositionErrorCallback::JSCustomPositionErrorCallback(JSObject* callback, JSDOMGlobalObject* globalObject)
+ : m_data(callback, globalObject)
{
}
void JSCustomPositionErrorCallback::handleEvent(PositionError* positionError)
{
- ASSERT(m_callback);
- ASSERT(m_frame);
-
- if (!m_frame->script()->isEnabled())
- return;
+ RefPtr<JSCustomPositionErrorCallback> protect(this);
- // FIXME: This is likely the wrong globalObject (for prototype chains at least)
- JSGlobalObject* globalObject = m_frame->script()->globalObject();
- ExecState* exec = globalObject->globalExec();
-
JSC::JSLock lock(SilenceAssertionsOnly);
-
- JSValue function = m_callback->get(exec, Identifier(exec, "handleEvent"));
- CallData callData;
- CallType callType = function.getCallData(callData);
- if (callType == CallTypeNone) {
- callType = m_callback->getCallData(callData);
- if (callType == CallTypeNone) {
- // FIXME: Should an exception be thrown here?
- return;
- }
- function = m_callback;
- }
-
- RefPtr<JSCustomPositionErrorCallback> protect(this);
-
+ ExecState* exec = m_data.globalObject()->globalExec();
MarkedArgumentBuffer args;
args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), positionError));
- globalObject->globalData()->timeoutChecker.start();
- call(exec, function, callType, callData, m_callback, args);
- globalObject->globalData()->timeoutChecker.stop();
-
- if (exec->hadException())
- reportCurrentException(exec);
-
- Document::updateStyleForAllDocuments();
+ m_data.invokeCallback(args);
}
} // namespace WebCore
diff --git a/WebCore/bindings/js/JSCustomPositionErrorCallback.h b/WebCore/bindings/js/JSCustomPositionErrorCallback.h
index 9f143a2..59328ca 100644
--- a/WebCore/bindings/js/JSCustomPositionErrorCallback.h
+++ b/WebCore/bindings/js/JSCustomPositionErrorCallback.h
@@ -26,31 +26,26 @@
#ifndef JSCustomPositionErrorCallback_h
#define JSCustomPositionErrorCallback_h
+#include "JSCallbackData.h"
#include "PositionErrorCallback.h"
-#include <runtime/JSObject.h>
-#include <runtime/Protect.h>
#include <wtf/Forward.h>
-namespace JSC {
- class JSObject;
-}
-
namespace WebCore {
-class Frame;
class PositionError;
class JSCustomPositionErrorCallback : public PositionErrorCallback {
public:
- static PassRefPtr<JSCustomPositionErrorCallback> create(JSC::JSObject* callback, Frame* frame) { return adoptRef(new JSCustomPositionErrorCallback(callback, frame)); }
+ static PassRefPtr<JSCustomPositionErrorCallback> create(JSC::JSObject* callback, JSDOMGlobalObject* globalObject)
+ {
+ return adoptRef(new JSCustomPositionErrorCallback(callback, globalObject));
+ }
- virtual void handleEvent(PositionError*);
-
private:
- JSCustomPositionErrorCallback(JSC::JSObject* callback, Frame*);
-
- JSC::ProtectedPtr<JSC::JSObject> m_callback;
- RefPtr<Frame> m_frame;
+ JSCustomPositionErrorCallback(JSC::JSObject* callback, JSDOMGlobalObject* globalObject);
+ virtual void handleEvent(PositionError*);
+
+ JSCallbackData m_data;
};
} // namespace WebCore
diff --git a/WebCore/bindings/js/JSCustomSQLStatementCallback.cpp b/WebCore/bindings/js/JSCustomSQLStatementCallback.cpp
index d0943de..1f6bd95 100644
--- a/WebCore/bindings/js/JSCustomSQLStatementCallback.cpp
+++ b/WebCore/bindings/js/JSCustomSQLStatementCallback.cpp
@@ -28,6 +28,7 @@
#include "config.h"
#include "JSCustomSQLStatementCallback.h"
+
#if ENABLE(DATABASE)
#include "Frame.h"
@@ -35,60 +36,38 @@
#include "JSSQLResultSet.h"
#include "JSSQLTransaction.h"
#include <runtime/JSLock.h>
+#include <wtf/MainThread.h>
namespace WebCore {
using namespace JSC;
-JSCustomSQLStatementCallback::JSCustomSQLStatementCallback(JSObject* callback, Frame* frame)
- : m_callback(callback)
- , m_frame(frame)
+JSCustomSQLStatementCallback::JSCustomSQLStatementCallback(JSObject* callback, JSDOMGlobalObject* globalObject)
+ : m_data(new JSCallbackData(callback, globalObject))
{
}
-void JSCustomSQLStatementCallback::handleEvent(SQLTransaction* transaction, SQLResultSet* resultSet, bool& raisedException)
+JSCustomSQLStatementCallback::~JSCustomSQLStatementCallback()
{
- ASSERT(m_callback);
- ASSERT(m_frame);
-
- if (!m_frame->script()->isEnabled())
- return;
-
- // FIXME: This is likely the wrong globalObject (for prototype chains at least)
- JSGlobalObject* globalObject = m_frame->script()->globalObject();
- ExecState* exec = globalObject->globalExec();
-
- JSC::JSLock lock(SilenceAssertionsOnly);
+ callOnMainThread(JSCallbackData::deleteData, m_data);
+#ifndef NDEBUG
+ m_data = 0;
+#endif
+}
- JSValue function = m_callback->get(exec, Identifier(exec, "handleEvent"));
- CallData callData;
- CallType callType = function.getCallData(callData);
- if (callType == CallTypeNone) {
- callType = m_callback->getCallData(callData);
- if (callType == CallTypeNone) {
- // FIXME: Should an exception be thrown here?
- return;
- }
- function = m_callback;
- }
+void JSCustomSQLStatementCallback::handleEvent(SQLTransaction* transaction, SQLResultSet* resultSet, bool& raisedException)
+{
+ ASSERT(m_data);
RefPtr<JSCustomSQLStatementCallback> protect(this);
+ JSC::JSLock lock(SilenceAssertionsOnly);
+ ExecState* exec = m_data->globalObject()->globalExec();
MarkedArgumentBuffer args;
args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), transaction));
args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), resultSet));
-
- globalObject->globalData()->timeoutChecker.start();
- call(exec, function, callType, callData, m_callback, args);
- globalObject->globalData()->timeoutChecker.stop();
-
- if (exec->hadException()) {
- reportCurrentException(exec);
-
- raisedException = true;
- }
- Document::updateStyleForAllDocuments();
+ m_data->invokeCallback(args, &raisedException);
}
}
diff --git a/WebCore/bindings/js/JSCustomSQLStatementCallback.h b/WebCore/bindings/js/JSCustomSQLStatementCallback.h
index c380670..259aecf 100644
--- a/WebCore/bindings/js/JSCustomSQLStatementCallback.h
+++ b/WebCore/bindings/js/JSCustomSQLStatementCallback.h
@@ -31,32 +31,29 @@
#if ENABLE(DATABASE)
+#include "JSCallbackData.h"
#include "SQLStatementCallback.h"
-
-#include <runtime/JSObject.h>
-#include <runtime/Protect.h>
#include <wtf/Forward.h>
-namespace JSC {
- class JSObject;
-}
-
namespace WebCore {
-class Frame;
class SQLResultSet;
class JSCustomSQLStatementCallback : public SQLStatementCallback {
public:
- static PassRefPtr<JSCustomSQLStatementCallback> create(JSC::JSObject* callback, Frame* frame) { return adoptRef(new JSCustomSQLStatementCallback(callback, frame)); }
+ static PassRefPtr<JSCustomSQLStatementCallback> create(JSC::JSObject* callback, JSDOMGlobalObject* globalObject)
+ {
+ return adoptRef(new JSCustomSQLStatementCallback(callback, globalObject));
+ }
+
+ virtual ~JSCustomSQLStatementCallback();
virtual void handleEvent(SQLTransaction*, SQLResultSet*, bool& raisedException);
private:
- JSCustomSQLStatementCallback(JSC::JSObject* callback, Frame*);
+ JSCustomSQLStatementCallback(JSC::JSObject* callback, JSDOMGlobalObject*);
- JSC::ProtectedPtr<JSC::JSObject> m_callback;
- RefPtr<Frame> m_frame;
+ JSCallbackData* m_data;
};
}
diff --git a/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.cpp b/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.cpp
index 6c831ac..6178509 100644
--- a/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.cpp
+++ b/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.cpp
@@ -32,75 +32,51 @@
#if ENABLE(DATABASE)
#include "Frame.h"
-#include "ScriptController.h"
+#include "JSCallbackData.h"
#include "JSSQLError.h"
#include "JSSQLTransaction.h"
+#include "ScriptController.h"
#include <runtime/JSLock.h>
+#include <wtf/MainThread.h>
namespace WebCore {
using namespace JSC;
-JSCustomSQLStatementErrorCallback::JSCustomSQLStatementErrorCallback(JSObject* callback, Frame* frame)
- : m_callback(callback)
- , m_frame(frame)
+JSCustomSQLStatementErrorCallback::JSCustomSQLStatementErrorCallback(JSObject* callback, JSDOMGlobalObject* globalObject)
+ : m_data(new JSCallbackData(callback, globalObject))
{
}
-
-bool JSCustomSQLStatementErrorCallback::handleEvent(SQLTransaction* transaction, SQLError* error)
-{
- ASSERT(m_callback);
- ASSERT(m_frame);
-
- if (!m_frame->script()->isEnabled())
- return true;
- // FIXME: This is likely the wrong globalObject (for prototype chains at least)
- JSGlobalObject* globalObject = m_frame->script()->globalObject();
- ExecState* exec = globalObject->globalExec();
-
- JSC::JSLock lock(SilenceAssertionsOnly);
-
- JSValue handleEventFunction = m_callback->get(exec, Identifier(exec, "handleEvent"));
- CallData handleEventCallData;
- CallType handleEventCallType = handleEventFunction.getCallData(handleEventCallData);
- CallData callbackCallData;
- CallType callbackCallType = CallTypeNone;
+JSCustomSQLStatementErrorCallback::~JSCustomSQLStatementErrorCallback()
+{
+ callOnMainThread(JSCallbackData::deleteData, m_data);
+#ifndef NDEBUG
+ m_data = 0;
+#endif
+}
- if (handleEventCallType == CallTypeNone) {
- callbackCallType = m_callback->getCallData(callbackCallData);
- if (callbackCallType == CallTypeNone) {
- // FIXME: Should an exception be thrown here?
- return true;
- }
- }
+bool JSCustomSQLStatementErrorCallback::handleEvent(SQLTransaction* transaction, SQLError* error)
+{
+ ASSERT(m_data);
RefPtr<JSCustomSQLStatementErrorCallback> protect(this);
+ JSC::JSLock lock(SilenceAssertionsOnly);
+ ExecState* exec = m_data->globalObject()->globalExec();
MarkedArgumentBuffer args;
args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), transaction));
args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), error));
-
- JSValue result;
- globalObject->globalData()->timeoutChecker.start();
- if (handleEventCallType != CallTypeNone)
- result = call(exec, handleEventFunction, handleEventCallType, handleEventCallData, m_callback, args);
- else
- result = call(exec, m_callback, callbackCallType, callbackCallData, m_callback, args);
- globalObject->globalData()->timeoutChecker.stop();
-
- if (exec->hadException()) {
- reportCurrentException(exec);
-
+
+ bool raisedException = false;
+ JSValue result = m_data->invokeCallback(args, &raisedException);
+ if (raisedException) {
// The spec says:
// "If the error callback returns false, then move on to the next statement..."
// "Otherwise, the error callback did not return false, or there was no error callback"
// Therefore an exception and returning true are the same thing - so, return true on an exception
return true;
}
-
- Document::updateStyleForAllDocuments();
-
return result.toBoolean(exec);
}
diff --git a/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.h b/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.h
index e563393..ac4e45f 100644
--- a/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.h
+++ b/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.h
@@ -31,32 +31,31 @@
#if ENABLE(DATABASE)
+#include "JSDOMGlobalObject.h"
#include "SQLStatementErrorCallback.h"
-
-#include <runtime/JSObject.h>
#include <runtime/Protect.h>
#include <wtf/Forward.h>
-namespace JSC {
- class JSObject;
-}
-
namespace WebCore {
-
-class Frame;
+
+class JSCallbackData;
class SQLError;
class JSCustomSQLStatementErrorCallback : public SQLStatementErrorCallback {
public:
- static PassRefPtr<JSCustomSQLStatementErrorCallback> create(JSC::JSObject* callback, Frame* frame) { return adoptRef(new JSCustomSQLStatementErrorCallback(callback, frame)); }
-
+ static PassRefPtr<JSCustomSQLStatementErrorCallback> create(JSC::JSObject* callback, JSDOMGlobalObject* globalObject)
+ {
+ return adoptRef(new JSCustomSQLStatementErrorCallback(callback, globalObject));
+ }
+
+ virtual ~JSCustomSQLStatementErrorCallback();
+
virtual bool handleEvent(SQLTransaction*, SQLError*);
private:
- JSCustomSQLStatementErrorCallback(JSC::JSObject* callback, Frame*);
+ JSCustomSQLStatementErrorCallback(JSC::JSObject* callback, JSDOMGlobalObject*);
- JSC::ProtectedPtr<JSC::JSObject> m_callback;
- RefPtr<Frame> m_frame;
+ JSCallbackData* m_data;
};
}
diff --git a/WebCore/bindings/js/JSCustomSQLTransactionCallback.cpp b/WebCore/bindings/js/JSCustomSQLTransactionCallback.cpp
index 3d42f81..456022f 100644
--- a/WebCore/bindings/js/JSCustomSQLTransactionCallback.cpp
+++ b/WebCore/bindings/js/JSCustomSQLTransactionCallback.cpp
@@ -32,9 +32,11 @@
#if ENABLE(DATABASE)
#include "Frame.h"
-#include "ScriptController.h"
+#include "JSCallbackData.h"
+#include "JSDOMGlobalObject.h"
#include "JSSQLTransaction.h"
#include "Page.h"
+#include "ScriptController.h"
#include <runtime/JSLock.h>
#include <wtf/MainThread.h>
#include <wtf/RefCountedLeakCounter.h>
@@ -47,39 +49,17 @@ using namespace JSC;
static WTF::RefCountedLeakCounter counter("JSCustomSQLTransactionCallback");
#endif
-// We have to clean up the data on the main thread for two reasons:
-//
-// 1) Can't deref a Frame on a non-main thread.
-// 2) Unprotecting the JSObject on a non-main thread would register that thread
-// for JavaScript garbage collection, which could unnecessarily slow things down.
-
-class JSCustomSQLTransactionCallback::Data {
-public:
- Data(JSObject* callback, Frame* frame) : m_callback(callback), m_frame(frame) { }
- JSObject* callback() { return m_callback; }
- Frame* frame() { return m_frame.get(); }
-
-private:
- ProtectedPtr<JSObject> m_callback;
- RefPtr<Frame> m_frame;
-};
-
-JSCustomSQLTransactionCallback::JSCustomSQLTransactionCallback(JSObject* callback, Frame* frame)
- : m_data(new Data(callback, frame))
+JSCustomSQLTransactionCallback::JSCustomSQLTransactionCallback(JSObject* callback, JSDOMGlobalObject* globalObject)
+ : m_data(new JSCallbackData(callback, globalObject))
{
#ifndef NDEBUG
counter.increment();
#endif
}
-void JSCustomSQLTransactionCallback::deleteData(void* context)
-{
- delete static_cast<Data*>(context);
-}
-
JSCustomSQLTransactionCallback::~JSCustomSQLTransactionCallback()
{
- callOnMainThread(deleteData, m_data);
+ callOnMainThread(JSCallbackData::deleteData, m_data);
#ifndef NDEBUG
m_data = 0;
counter.decrement();
@@ -89,51 +69,14 @@ JSCustomSQLTransactionCallback::~JSCustomSQLTransactionCallback()
void JSCustomSQLTransactionCallback::handleEvent(SQLTransaction* transaction, bool& raisedException)
{
ASSERT(m_data);
- ASSERT(m_data->callback());
- ASSERT(m_data->frame());
- if (!m_data->frame()->script()->isEnabled())
- return;
-
- // FIXME: This is likely the wrong globalObject (for prototype chains at least)
- JSGlobalObject* globalObject = m_data->frame()->script()->globalObject();
- ExecState* exec = globalObject->globalExec();
-
- JSC::JSLock lock(SilenceAssertionsOnly);
-
- JSValue handleEventFunction = m_data->callback()->get(exec, Identifier(exec, "handleEvent"));
- CallData handleEventCallData;
- CallType handleEventCallType = handleEventFunction.getCallData(handleEventCallData);
- CallData callbackCallData;
- CallType callbackCallType = CallTypeNone;
-
- if (handleEventCallType == CallTypeNone) {
- callbackCallType = m_data->callback()->getCallData(callbackCallData);
- if (callbackCallType == CallTypeNone) {
- // FIXME: Should an exception be thrown here?
- return;
- }
- }
-
RefPtr<JSCustomSQLTransactionCallback> protect(this);
+ JSC::JSLock lock(SilenceAssertionsOnly);
+ ExecState* exec = m_data->globalObject()->globalExec();
MarkedArgumentBuffer args;
args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), transaction));
-
- globalObject->globalData()->timeoutChecker.start();
- if (handleEventCallType != CallTypeNone)
- call(exec, handleEventFunction, handleEventCallType, handleEventCallData, m_data->callback(), args);
- else
- call(exec, m_data->callback(), callbackCallType, callbackCallData, m_data->callback(), args);
- globalObject->globalData()->timeoutChecker.stop();
-
- if (exec->hadException()) {
- reportCurrentException(exec);
-
- raisedException = true;
- }
-
- Document::updateStyleForAllDocuments();
+ m_data->invokeCallback(args, &raisedException);
}
}
diff --git a/WebCore/bindings/js/JSCustomSQLTransactionCallback.h b/WebCore/bindings/js/JSCustomSQLTransactionCallback.h
index 22c367c..f142e59 100644
--- a/WebCore/bindings/js/JSCustomSQLTransactionCallback.h
+++ b/WebCore/bindings/js/JSCustomSQLTransactionCallback.h
@@ -32,7 +32,6 @@
#if ENABLE(DATABASE)
#include "SQLTransactionCallback.h"
-
#include <wtf/PassRefPtr.h>
namespace JSC {
@@ -42,22 +41,24 @@ namespace JSC {
namespace WebCore {
class Frame;
+class JSCallbackData;
+class JSDOMGlobalObject;
class JSCustomSQLTransactionCallback : public SQLTransactionCallback {
public:
- static PassRefPtr<JSCustomSQLTransactionCallback> create(JSC::JSObject* callback, Frame* frame) { return adoptRef(new JSCustomSQLTransactionCallback(callback, frame)); }
+ static PassRefPtr<JSCustomSQLTransactionCallback> create(JSC::JSObject* callback, JSDOMGlobalObject* globalObject)
+ {
+ return adoptRef(new JSCustomSQLTransactionCallback(callback, globalObject));
+ }
virtual ~JSCustomSQLTransactionCallback();
virtual void handleEvent(SQLTransaction*, bool& raisedException);
private:
- JSCustomSQLTransactionCallback(JSC::JSObject* callback, Frame*);
-
- static void deleteData(void*);
+ JSCustomSQLTransactionCallback(JSC::JSObject* callback, JSDOMGlobalObject*);
- class Data;
- Data* m_data;
+ JSCallbackData* m_data;
};
}
diff --git a/WebCore/bindings/js/JSCustomSQLTransactionErrorCallback.cpp b/WebCore/bindings/js/JSCustomSQLTransactionErrorCallback.cpp
index 2d41bb8..331e014 100644
--- a/WebCore/bindings/js/JSCustomSQLTransactionErrorCallback.cpp
+++ b/WebCore/bindings/js/JSCustomSQLTransactionErrorCallback.cpp
@@ -32,59 +32,40 @@
#if ENABLE(DATABASE)
#include "Frame.h"
-#include "ScriptController.h"
+#include "JSCallbackData.h"
#include "JSSQLError.h"
+#include "ScriptController.h"
#include <runtime/JSLock.h>
+#include <wtf/MainThread.h>
namespace WebCore {
using namespace JSC;
-JSCustomSQLTransactionErrorCallback::JSCustomSQLTransactionErrorCallback(JSObject* callback, Frame* frame)
- : m_callback(callback)
- , m_frame(frame)
+JSCustomSQLTransactionErrorCallback::JSCustomSQLTransactionErrorCallback(JSObject* callback, JSDOMGlobalObject* globalObject)
+ : m_data(new JSCallbackData(callback, globalObject))
{
}
-
-void JSCustomSQLTransactionErrorCallback::handleEvent(SQLError* error)
-{
- ASSERT(m_callback);
- ASSERT(m_frame);
-
- if (!m_frame->script()->isEnabled())
- return;
- // FIXME: This is likely the wrong globalObject (for prototype chains at least)
- JSGlobalObject* globalObject = m_frame->script()->globalObject();
- ExecState* exec = globalObject->globalExec();
-
- JSC::JSLock lock(SilenceAssertionsOnly);
+JSCustomSQLTransactionErrorCallback::~JSCustomSQLTransactionErrorCallback()
+{
+ callOnMainThread(JSCallbackData::deleteData, m_data);
+#ifndef NDEBUG
+ m_data = 0;
+#endif
+}
- JSValue function = m_callback->get(exec, Identifier(exec, "handleEvent"));
- CallData callData;
- CallType callType = function.getCallData(callData);
- if (callType == CallTypeNone) {
- callType = m_callback->getCallData(callData);
- if (callType == CallTypeNone) {
- // FIXME: Should an exception be thrown here?
- return;
- }
- function = m_callback;
- }
+void JSCustomSQLTransactionErrorCallback::handleEvent(SQLError* error)
+{
+ ASSERT(m_data);
RefPtr<JSCustomSQLTransactionErrorCallback> protect(this);
+ JSC::JSLock lock(SilenceAssertionsOnly);
+ ExecState* exec = m_data->globalObject()->globalExec();
MarkedArgumentBuffer args;
args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), error));
-
- globalObject->globalData()->timeoutChecker.start();
- call(exec, function, callType, callData, m_callback, args);
- globalObject->globalData()->timeoutChecker.stop();
-
- if (exec->hadException())
- reportCurrentException(exec);
-
- Document::updateStyleForAllDocuments();
+ m_data->invokeCallback(args);
}
}
diff --git a/WebCore/bindings/js/JSCustomSQLTransactionErrorCallback.h b/WebCore/bindings/js/JSCustomSQLTransactionErrorCallback.h
index be3df29..54bf33b 100644
--- a/WebCore/bindings/js/JSCustomSQLTransactionErrorCallback.h
+++ b/WebCore/bindings/js/JSCustomSQLTransactionErrorCallback.h
@@ -32,31 +32,30 @@
#if ENABLE(DATABASE)
#include "SQLTransactionErrorCallback.h"
-
-#include <runtime/JSObject.h>
+#include "JSDOMGlobalObject.h"
#include <runtime/Protect.h>
#include <wtf/Forward.h>
-namespace JSC {
- class JSObject;
-}
-
namespace WebCore {
-class Frame;
+class JSCallbackData;
class SQLError;
class JSCustomSQLTransactionErrorCallback : public SQLTransactionErrorCallback {
public:
- static PassRefPtr<JSCustomSQLTransactionErrorCallback> create(JSC::JSObject* callback, Frame* frame) { return adoptRef(new JSCustomSQLTransactionErrorCallback(callback, frame)); }
+ static PassRefPtr<JSCustomSQLTransactionErrorCallback> create(JSC::JSObject* callback, JSDOMGlobalObject* globalObject)
+ {
+ return adoptRef(new JSCustomSQLTransactionErrorCallback(callback, globalObject));
+ }
+
+ virtual ~JSCustomSQLTransactionErrorCallback();
virtual void handleEvent(SQLError*);
private:
- JSCustomSQLTransactionErrorCallback(JSC::JSObject* callback, Frame*);
+ JSCustomSQLTransactionErrorCallback(JSC::JSObject* callback, JSDOMGlobalObject* globalObject);
- JSC::ProtectedPtr<JSC::JSObject> m_callback;
- RefPtr<Frame> m_frame;
+ JSCallbackData* m_data;
};
}
diff --git a/WebCore/bindings/js/JSCustomVoidCallback.cpp b/WebCore/bindings/js/JSCustomVoidCallback.cpp
index b4e525b..0edd66f 100644
--- a/WebCore/bindings/js/JSCustomVoidCallback.cpp
+++ b/WebCore/bindings/js/JSCustomVoidCallback.cpp
@@ -30,70 +30,38 @@
#include "JSCustomVoidCallback.h"
#include "Frame.h"
+#include "JSCallbackData.h"
#include "JSDOMWindowCustom.h"
#include "ScriptController.h"
#include <runtime/JSLock.h>
+#include <wtf/MainThread.h>
namespace WebCore {
using namespace JSC;
-JSCustomVoidCallback::JSCustomVoidCallback(JSObject* callback, Frame* frame)
- : m_callback(callback)
- , m_frame(frame)
+JSCustomVoidCallback::JSCustomVoidCallback(JSObject* callback, JSDOMGlobalObject* globalObject)
+ : m_data(new JSCallbackData(callback, globalObject))
{
}
+
+JSCustomVoidCallback::~JSCustomVoidCallback()
+{
+ callOnMainThread(JSCallbackData::deleteData, m_data);
+#ifndef NDEBUG
+ m_data = 0;
+#endif
+}
void JSCustomVoidCallback::handleEvent()
{
- ASSERT(m_callback);
- ASSERT(m_frame);
-
- if (!m_frame->script()->isEnabled())
- return;
-
- JSGlobalObject* globalObject = m_frame->script()->globalObject();
- ExecState* exec = globalObject->globalExec();
-
- JSC::JSLock lock(SilenceAssertionsOnly);
-
- JSValue function = m_callback->get(exec, Identifier(exec, "handleEvent"));
- CallData callData;
- CallType callType = function.getCallData(callData);
- if (callType == CallTypeNone) {
- callType = m_callback->getCallData(callData);
- if (callType == CallTypeNone) {
- // FIXME: Should an exception be thrown here?
- return;
- }
- function = m_callback;
- }
-
+ ASSERT(m_data);
+
RefPtr<JSCustomVoidCallback> protect(this);
+ JSC::JSLock lock(SilenceAssertionsOnly);
MarkedArgumentBuffer args;
-
- globalObject->globalData()->timeoutChecker.start();
- call(exec, function, callType, callData, m_callback, args);
- globalObject->globalData()->timeoutChecker.stop();
-
- if (exec->hadException())
- reportCurrentException(exec);
-
- Document::updateStyleForAllDocuments();
-}
-
-PassRefPtr<VoidCallback> toVoidCallback(ExecState* exec, JSValue value)
-{
- JSObject* object = value.getObject();
- if (!object)
- return 0;
-
- Frame* frame = asJSDOMWindow(exec->dynamicGlobalObject())->impl()->frame();
- if (!frame)
- return 0;
-
- return JSCustomVoidCallback::create(object, frame);
+ m_data->invokeCallback(args);
}
-}
+} // namespace WebCore
diff --git a/WebCore/bindings/js/JSCustomVoidCallback.h b/WebCore/bindings/js/JSCustomVoidCallback.h
index 9cd7c34..4b8d7ea 100644
--- a/WebCore/bindings/js/JSCustomVoidCallback.h
+++ b/WebCore/bindings/js/JSCustomVoidCallback.h
@@ -29,33 +29,31 @@
#ifndef JSCustomVoidCallback_h
#define JSCustomVoidCallback_h
+#include "JSDOMGlobalObject.h"
#include "VoidCallback.h"
-
-#include <runtime/JSObject.h>
#include <runtime/Protect.h>
#include <wtf/Forward.h>
namespace WebCore {
+
+class JSCallbackData;
+
+class JSCustomVoidCallback : public VoidCallback {
+public:
+ static PassRefPtr<JSCustomVoidCallback> create(JSC::JSObject* callback, JSDOMGlobalObject* globalObject)
+ {
+ return adoptRef(new JSCustomVoidCallback(callback, globalObject));
+ }
- class Frame;
+ virtual ~JSCustomVoidCallback();
- class JSCustomVoidCallback : public VoidCallback {
- public:
- static PassRefPtr<JSCustomVoidCallback> create(JSC::JSObject* callback, Frame* frame)
- {
- return adoptRef(new JSCustomVoidCallback(callback, frame));
- }
-
- virtual void handleEvent();
-
- private:
- JSCustomVoidCallback(JSC::JSObject* callback, Frame*);
-
- JSC::ProtectedPtr<JSC::JSObject> m_callback;
- RefPtr<Frame> m_frame;
- };
-
- PassRefPtr<VoidCallback> toVoidCallback(JSC::ExecState*, JSC::JSValue);
+ virtual void handleEvent();
+
+private:
+ JSCustomVoidCallback(JSC::JSObject* callback, JSDOMGlobalObject*);
+
+ JSCallbackData* m_data;
+};
} // namespace WebCore
diff --git a/WebCore/bindings/js/JSCustomXPathNSResolver.cpp b/WebCore/bindings/js/JSCustomXPathNSResolver.cpp
index 4476be5..da4a53a 100644
--- a/WebCore/bindings/js/JSCustomXPathNSResolver.cpp
+++ b/WebCore/bindings/js/JSCustomXPathNSResolver.cpp
@@ -49,13 +49,13 @@ PassRefPtr<JSCustomXPathNSResolver> JSCustomXPathNSResolver::create(JSC::ExecSta
setDOMException(exec, TYPE_MISMATCH_ERR);
return 0;
}
-
- return adoptRef(new JSCustomXPathNSResolver(resolverObject, asJSDOMWindow(exec->dynamicGlobalObject())->impl()->frame()));
+
+ return adoptRef(new JSCustomXPathNSResolver(resolverObject, asJSDOMWindow(exec->dynamicGlobalObject())));
}
-JSCustomXPathNSResolver::JSCustomXPathNSResolver(JSObject* customResolver, Frame* frame)
+JSCustomXPathNSResolver::JSCustomXPathNSResolver(JSObject* customResolver, JSDOMWindow* globalObject)
: m_customResolver(customResolver)
- , m_frame(frame)
+ , m_globalObject(globalObject)
{
}
@@ -67,15 +67,9 @@ String JSCustomXPathNSResolver::lookupNamespaceURI(const String& prefix)
{
ASSERT(m_customResolver);
- if (!m_frame)
- return String();
- if (!m_frame->script()->isEnabled())
- return String();
-
JSLock lock(SilenceAssertionsOnly);
- JSGlobalObject* globalObject = m_frame->script()->globalObject();
- ExecState* exec = globalObject->globalExec();
+ ExecState* exec = m_globalObject->globalExec();
JSValue function = m_customResolver->get(exec, Identifier(exec, "lookupNamespaceURI"));
CallData callData;
@@ -84,7 +78,7 @@ String JSCustomXPathNSResolver::lookupNamespaceURI(const String& prefix)
callType = m_customResolver->getCallData(callData);
if (callType == CallTypeNone) {
// FIXME: Pass actual line number and source URL.
- m_frame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, "XPathNSResolver does not have a lookupNamespaceURI method.", 0, String());
+ m_globalObject->impl()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, "XPathNSResolver does not have a lookupNamespaceURI method.", 0, String());
return String();
}
function = m_customResolver;
@@ -95,9 +89,9 @@ String JSCustomXPathNSResolver::lookupNamespaceURI(const String& prefix)
MarkedArgumentBuffer args;
args.append(jsString(exec, prefix));
- globalObject->globalData()->timeoutChecker.start();
+ m_globalObject->globalData()->timeoutChecker.start();
JSValue retval = call(exec, function, callType, callData, m_customResolver, args);
- globalObject->globalData()->timeoutChecker.stop();
+ m_globalObject->globalData()->timeoutChecker.stop();
String result;
if (exec->hadException())
diff --git a/WebCore/bindings/js/JSCustomXPathNSResolver.h b/WebCore/bindings/js/JSCustomXPathNSResolver.h
index 44c44f9..7d66494 100644
--- a/WebCore/bindings/js/JSCustomXPathNSResolver.h
+++ b/WebCore/bindings/js/JSCustomXPathNSResolver.h
@@ -41,6 +41,7 @@ namespace JSC {
namespace WebCore {
class Frame;
+ class JSDOMWindow;
class JSCustomXPathNSResolver : public XPathNSResolver {
public:
@@ -51,10 +52,11 @@ namespace WebCore {
virtual String lookupNamespaceURI(const String& prefix);
private:
- JSCustomXPathNSResolver(JSC::JSObject*, Frame*);
+ JSCustomXPathNSResolver(JSC::JSObject*, JSDOMWindow*);
- JSC::JSObject* m_customResolver; // JSCustomXPathNSResolvers are always temporary, thus no need to GC protect the object.
- RefPtr<Frame> m_frame;
+ // JSCustomXPathNSResolvers are always temporary, thus no need to GC protect the objects.
+ JSC::JSObject* m_customResolver;
+ JSDOMWindow* m_globalObject;
};
} // namespace WebCore
diff --git a/WebCore/bindings/js/JSDOMApplicationCacheCustom.cpp b/WebCore/bindings/js/JSDOMApplicationCacheCustom.cpp
index 109308c..49ef5e3 100644
--- a/WebCore/bindings/js/JSDOMApplicationCacheCustom.cpp
+++ b/WebCore/bindings/js/JSDOMApplicationCacheCustom.cpp
@@ -42,28 +42,6 @@ using namespace JSC;
namespace WebCore {
-void JSDOMApplicationCache::markChildren(MarkStack& markStack)
-{
- Base::markChildren(markStack);
-
- markIfNotNull(markStack, m_impl->onchecking());
- markIfNotNull(markStack, m_impl->onerror());
- markIfNotNull(markStack, m_impl->onnoupdate());
- markIfNotNull(markStack, m_impl->ondownloading());
- markIfNotNull(markStack, m_impl->onprogress());
- markIfNotNull(markStack, m_impl->onupdateready());
- markIfNotNull(markStack, m_impl->oncached());
- markIfNotNull(markStack, m_impl->onobsolete());
-
- typedef DOMApplicationCache::EventListenersMap EventListenersMap;
- typedef DOMApplicationCache::ListenerVector ListenerVector;
- EventListenersMap& eventListeners = m_impl->eventListeners();
- for (EventListenersMap::iterator mapIter = eventListeners.begin(); mapIter != eventListeners.end(); ++mapIter) {
- for (ListenerVector::iterator vecIter = mapIter->second.begin(); vecIter != mapIter->second.end(); ++vecIter)
- (*vecIter)->markJSFunction(markStack);
- }
-}
-
#if ENABLE(APPLICATION_CACHE_DYNAMIC_ENTRIES)
JSValue JSDOMApplicationCache::hasItem(ExecState* exec, const ArgList& args)
@@ -112,10 +90,12 @@ JSValue JSDOMApplicationCache::addEventListener(ExecState* exec, const ArgList&
JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->scriptExecutionContext());
if (!globalObject)
return jsUndefined();
- RefPtr<JSEventListener> listener = globalObject->findOrCreateJSEventListener(args.at(1));
- if (!listener)
+
+ JSValue listener = args.at(1);
+ if (!listener.isObject())
return jsUndefined();
- impl()->addEventListener(args.at(0).toString(exec), listener.release(), args.at(2).toBoolean(exec));
+
+ impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false), args.at(2).toBoolean(exec));
return jsUndefined();
}
@@ -124,10 +104,12 @@ JSValue JSDOMApplicationCache::removeEventListener(ExecState* exec, const ArgLis
JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->scriptExecutionContext());
if (!globalObject)
return jsUndefined();
- JSEventListener* listener = globalObject->findJSEventListener(args.at(1));
- if (!listener)
+
+ JSValue listener = args.at(1);
+ if (!listener.isObject())
return jsUndefined();
- impl()->removeEventListener(args.at(0).toString(exec), listener, args.at(2).toBoolean(exec));
+
+ impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false).get(), args.at(2).toBoolean(exec));
return jsUndefined();
}
diff --git a/WebCore/bindings/js/JSDOMBinding.cpp b/WebCore/bindings/js/JSDOMBinding.cpp
index 566b986..515c088 100644
--- a/WebCore/bindings/js/JSDOMBinding.cpp
+++ b/WebCore/bindings/js/JSDOMBinding.cpp
@@ -28,6 +28,7 @@
#include "ExceptionCode.h"
#include "Frame.h"
#include "HTMLAudioElement.h"
+#include "HTMLCanvasElement.h"
#include "HTMLImageElement.h"
#include "HTMLScriptElement.h"
#include "HTMLNames.h"
@@ -42,6 +43,8 @@
#include "RangeException.h"
#include "ScriptController.h"
#include "XMLHttpRequestException.h"
+#include <runtime/Error.h>
+#include <runtime/JSFunction.h>
#include <runtime/PrototypeFunction.h>
#include <wtf/StdLibExtras.h>
@@ -264,18 +267,48 @@ static inline bool isObservableThroughDOM(JSNode* jsNode)
Node* node = jsNode->impl();
if (node->inDocument()) {
- // 1. If a node is in the document, and its wrapper has custom properties,
+ // If a node is in the document, and its wrapper has custom properties,
// the wrapper is observable because future access to the node through the
// DOM must reflect those properties.
if (jsNode->hasCustomProperties())
return true;
- // 2. If a node is in the document, and has event listeners, its wrapper is
+ // If a node is in the document, and has event listeners, its wrapper is
// observable because its wrapper is responsible for marking those event listeners.
- if (node->eventListeners().size())
+ if (node->hasEventListeners())
return true; // Technically, we may overzealously mark a wrapper for a node that has only non-JS event listeners. Oh well.
+
+ // If a node owns another object with a wrapper with custom properties,
+ // the wrapper must be treated as observable, because future access to
+ // those objects through the DOM must reflect those properties.
+ // FIXME: It would be better if this logic could be in the node next to
+ // the custom markChildren functions rather than here.
+ if (node->isElementNode()) {
+ if (NamedNodeMap* attributes = static_cast<Element*>(node)->attributeMap()) {
+ if (DOMObject* wrapper = getCachedDOMObjectWrapper(*jsNode->globalObject()->globalData(), attributes)) {
+ if (wrapper->hasCustomProperties())
+ return true;
+ }
+ }
+ if (node->isStyledElement()) {
+ if (CSSMutableStyleDeclaration* style = static_cast<StyledElement*>(node)->inlineStyleDecl()) {
+ if (DOMObject* wrapper = getCachedDOMObjectWrapper(*jsNode->globalObject()->globalData(), style)) {
+ if (wrapper->hasCustomProperties())
+ return true;
+ }
+ }
+ }
+ if (static_cast<Element*>(node)->hasTagName(canvasTag)) {
+ if (CanvasRenderingContext* context = static_cast<HTMLCanvasElement*>(node)->renderingContext()) {
+ if (DOMObject* wrapper = getCachedDOMObjectWrapper(*jsNode->globalObject()->globalData(), context)) {
+ if (wrapper->hasCustomProperties())
+ return true;
+ }
+ }
+ }
+ }
} else {
- // 3. If a wrapper is the last reference to an image or script element
+ // If a wrapper is the last reference to an image or script element
// that is loading but not in the document, the wrapper is observable
// because it is the only thing keeping the image element alive, and if
// the image element is destroyed, its load event will not fire.
@@ -290,6 +323,11 @@ static inline bool isObservableThroughDOM(JSNode* jsNode)
#endif
}
+ // If a node is firing event listeners, its wrapper is observable because
+ // its wrapper is responsible for marking those event listeners.
+ if (node->isFiringEventListeners())
+ return true;
+
return false;
}
@@ -348,6 +386,9 @@ void updateDOMNodeDocument(Node* node, Document* oldDocument, Document* newDocum
void markDOMObjectWrapper(MarkStack& markStack, JSGlobalData& globalData, void* object)
{
+ // FIXME: This could be changed to only mark wrappers that are "observable"
+ // as markDOMNodesForDocument does, allowing us to collect more wrappers,
+ // but doing this correctly would be challenging.
if (!object)
return;
DOMObject* wrapper = getCachedDOMObjectWrapper(globalData, object);
@@ -559,7 +600,7 @@ Structure* getCachedDOMStructure(JSDOMGlobalObject* globalObject, const ClassInf
return structures.get(classInfo).get();
}
-Structure* cacheDOMStructure(JSDOMGlobalObject* globalObject, PassRefPtr<Structure> structure, const ClassInfo* classInfo)
+Structure* cacheDOMStructure(JSDOMGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, const ClassInfo* classInfo)
{
JSDOMStructureMap& structures = globalObject->structures();
ASSERT(!structures.contains(classInfo));
@@ -571,7 +612,7 @@ Structure* getCachedDOMStructure(ExecState* exec, const ClassInfo* classInfo)
return getCachedDOMStructure(static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), classInfo);
}
-Structure* cacheDOMStructure(ExecState* exec, PassRefPtr<Structure> structure, const ClassInfo* classInfo)
+Structure* cacheDOMStructure(ExecState* exec, NonNullPassRefPtr<Structure> structure, const ClassInfo* classInfo)
{
return cacheDOMStructure(static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), structure, classInfo);
}
@@ -589,4 +630,33 @@ void cacheDOMConstructor(ExecState* exec, const ClassInfo* classInfo, JSObject*
constructors.set(classInfo, constructor);
}
+JSC::JSObject* toJSSequence(ExecState* exec, JSValue value, unsigned& length)
+{
+ JSObject* object = value.getObject();
+ if (!object) {
+ throwError(exec, TypeError);
+ return 0;
+ }
+ JSValue lengthValue = object->get(exec, exec->propertyNames().length);
+ if (exec->hadException())
+ return 0;
+
+ if (lengthValue.isUndefinedOrNull()) {
+ throwError(exec, TypeError);
+ return 0;
+ }
+
+ length = lengthValue.toUInt32(exec);
+ if (exec->hadException())
+ return 0;
+
+ return object;
+}
+
+bool DOMObject::defineOwnProperty(ExecState* exec, const Identifier&, PropertyDescriptor&, bool)
+{
+ throwError(exec, TypeError, "defineProperty is not supported on DOM Objects");
+ return false;
+}
+
} // namespace WebCore
diff --git a/WebCore/bindings/js/JSDOMBinding.h b/WebCore/bindings/js/JSDOMBinding.h
index 64cfc3a..9c0ad7e 100644
--- a/WebCore/bindings/js/JSDOMBinding.h
+++ b/WebCore/bindings/js/JSDOMBinding.h
@@ -26,7 +26,6 @@
#include "Document.h" // For DOMConstructorWithDocument
#include <runtime/Completion.h>
#include <runtime/Lookup.h>
-#include <runtime/JSFunction.h>
#include <wtf/Noncopyable.h>
namespace JSC {
@@ -51,17 +50,19 @@ namespace WebCore {
// Base class for all objects in this binding except Window.
class DOMObject : public JSC::JSObject {
protected:
- explicit DOMObject(PassRefPtr<JSC::Structure> structure)
+ explicit DOMObject(NonNullPassRefPtr<JSC::Structure> structure)
: JSObject(structure)
{
}
+ virtual bool defineOwnProperty(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&, bool);
+
#ifndef NDEBUG
virtual ~DOMObject();
#endif
};
- // FIXME: This class should colapse into DOMObject once all DOMObjects are
+ // FIXME: This class should collapse into DOMObject once all DOMObjects are
// updated to store a globalObject pointer.
class DOMObjectWithGlobalPointer : public DOMObject {
public:
@@ -73,8 +74,13 @@ namespace WebCore {
return m_globalObject->scriptExecutionContext();
}
+ static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype)
+ {
+ return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, JSC::HasStandardGetOwnPropertySlot));
+ }
+
protected:
- DOMObjectWithGlobalPointer(PassRefPtr<JSC::Structure> structure, JSDOMGlobalObject* globalObject)
+ DOMObjectWithGlobalPointer(NonNullPassRefPtr<JSC::Structure> structure, JSDOMGlobalObject* globalObject)
: DOMObject(structure)
, m_globalObject(globalObject)
{
@@ -83,7 +89,7 @@ namespace WebCore {
// needing to reach through the frame to get to the Document*. See bug 27640.
// ASSERT(globalObject->scriptExecutionContext());
}
- virtual ~DOMObjectWithGlobalPointer() {}
+ virtual ~DOMObjectWithGlobalPointer() { }
void markChildren(JSC::MarkStack& markStack)
{
@@ -104,7 +110,7 @@ namespace WebCore {
}
protected:
- DOMConstructorObject(PassRefPtr<JSC::Structure> structure, JSDOMGlobalObject* globalObject)
+ DOMConstructorObject(NonNullPassRefPtr<JSC::Structure> structure, JSDOMGlobalObject* globalObject)
: DOMObjectWithGlobalPointer(structure, globalObject)
{
}
@@ -120,7 +126,7 @@ namespace WebCore {
}
protected:
- DOMConstructorWithDocument(PassRefPtr<JSC::Structure> structure, JSDOMGlobalObject* globalObject)
+ DOMConstructorWithDocument(NonNullPassRefPtr<JSC::Structure> structure, JSDOMGlobalObject* globalObject)
: DOMConstructorObject(structure, globalObject)
{
ASSERT(globalObject->scriptExecutionContext()->isDocument());
@@ -141,9 +147,9 @@ namespace WebCore {
void markDOMObjectWrapper(JSC::MarkStack&, JSC::JSGlobalData& globalData, void* object);
JSC::Structure* getCachedDOMStructure(JSDOMGlobalObject*, const JSC::ClassInfo*);
- JSC::Structure* cacheDOMStructure(JSDOMGlobalObject*, PassRefPtr<JSC::Structure>, const JSC::ClassInfo*);
+ JSC::Structure* cacheDOMStructure(JSDOMGlobalObject*, NonNullPassRefPtr<JSC::Structure>, const JSC::ClassInfo*);
JSC::Structure* getCachedDOMStructure(JSC::ExecState*, const JSC::ClassInfo*);
- JSC::Structure* cacheDOMStructure(JSC::ExecState*, PassRefPtr<JSC::Structure>, const JSC::ClassInfo*);
+ JSC::Structure* cacheDOMStructure(JSC::ExecState*, NonNullPassRefPtr<JSC::Structure>, const JSC::ClassInfo*);
JSC::JSObject* getCachedDOMConstructor(JSC::ExecState*, const JSC::ClassInfo*);
void cacheDOMConstructor(JSC::ExecState*, const JSC::ClassInfo*, JSC::JSObject* constructor);
@@ -277,6 +283,9 @@ namespace WebCore {
return toJS(exec, globalObject, ptr.get());
}
+ // Validates that the passed object is a sequence type per section 4.1.13 of the WebIDL spec.
+ JSC::JSObject* toJSSequence(JSC::ExecState*, JSC::JSValue, unsigned&);
+
bool checkNodeSecurity(JSC::ExecState*, Node*);
// Helpers for Window, History, and Location classes to implement cross-domain policy.
diff --git a/WebCore/bindings/js/JSDOMGlobalObject.cpp b/WebCore/bindings/js/JSDOMGlobalObject.cpp
index 68a1db9..372684c 100644
--- a/WebCore/bindings/js/JSDOMGlobalObject.cpp
+++ b/WebCore/bindings/js/JSDOMGlobalObject.cpp
@@ -40,24 +40,11 @@ using namespace JSC;
namespace WebCore {
-JSDOMGlobalObject::JSDOMGlobalObjectData::JSDOMGlobalObjectData()
- : evt(0)
-{
-}
-
-JSDOMGlobalObject::JSDOMGlobalObject(PassRefPtr<Structure> structure, JSDOMGlobalObject::JSDOMGlobalObjectData* data, JSObject* thisValue)
+JSDOMGlobalObject::JSDOMGlobalObject(NonNullPassRefPtr<Structure> structure, JSDOMGlobalObject::JSDOMGlobalObjectData* data, JSObject* thisValue)
: JSGlobalObject(structure, data, thisValue)
{
}
-JSDOMGlobalObject::~JSDOMGlobalObject()
-{
- JSListenersMap::iterator it = d()->jsEventListeners.begin();
- JSListenersMap::iterator end = d()->jsEventListeners.end();
- for (; it != end; ++it)
- it->second->clearGlobalObject();
-}
-
void JSDOMGlobalObject::markChildren(MarkStack& markStack)
{
Base::markChildren(markStack);
@@ -71,37 +58,12 @@ void JSDOMGlobalObject::markChildren(MarkStack& markStack)
markStack.append(it2->second);
}
-JSEventListener* JSDOMGlobalObject::findJSEventListener(JSValue val)
-{
- if (!val.isObject())
- return 0;
-
- return d()->jsEventListeners.get(asObject(val));
-}
-
-PassRefPtr<JSEventListener> JSDOMGlobalObject::findOrCreateJSEventListener(JSValue val)
-{
- if (JSEventListener* listener = findJSEventListener(val))
- return listener;
-
- if (!val.isObject())
- return 0;
-
- // The JSEventListener constructor adds it to our jsEventListeners map.
- return JSEventListener::create(asObject(val), this, false).get();
-}
-
PassRefPtr<JSEventListener> JSDOMGlobalObject::createJSAttributeEventListener(JSValue val)
{
if (!val.isObject())
return 0;
- return JSEventListener::create(asObject(val), this, true).get();
-}
-
-JSDOMGlobalObject::JSListenersMap& JSDOMGlobalObject::jsEventListeners()
-{
- return d()->jsEventListeners;
+ return JSEventListener::create(asObject(val), true).get();
}
void JSDOMGlobalObject::setCurrentEvent(Event* evt)
@@ -114,6 +76,11 @@ Event* JSDOMGlobalObject::currentEvent() const
return d()->evt;
}
+void JSDOMGlobalObject::destroyJSDOMGlobalObjectData(void* jsDOMGlobalObjectData)
+{
+ delete static_cast<JSDOMGlobalObjectData*>(jsDOMGlobalObjectData);
+}
+
JSDOMGlobalObject* toJSDOMGlobalObject(Document* document)
{
return toJSDOMWindow(document->frame());
diff --git a/WebCore/bindings/js/JSDOMGlobalObject.h b/WebCore/bindings/js/JSDOMGlobalObject.h
index 855691c..ce26857 100644
--- a/WebCore/bindings/js/JSDOMGlobalObject.h
+++ b/WebCore/bindings/js/JSDOMGlobalObject.h
@@ -45,8 +45,7 @@ namespace WebCore {
protected:
struct JSDOMGlobalObjectData;
- JSDOMGlobalObject(PassRefPtr<JSC::Structure>, JSDOMGlobalObjectData*, JSC::JSObject* thisValue);
- virtual ~JSDOMGlobalObject();
+ JSDOMGlobalObject(NonNullPassRefPtr<JSC::Structure>, JSDOMGlobalObjectData*, JSC::JSObject* thisValue);
public:
JSDOMStructureMap& structures() { return d()->structures; }
@@ -54,20 +53,10 @@ namespace WebCore {
virtual ScriptExecutionContext* scriptExecutionContext() const = 0;
- // Finds a wrapper of a GC-unprotected JS EventListener, returns 0 if no existing one.
- JSEventListener* findJSEventListener(JSC::JSValue);
-
- // Finds or creates a wrapper of a JS EventListener. JS EventListener object is *NOT* GC-protected.
- PassRefPtr<JSEventListener> findOrCreateJSEventListener(JSC::JSValue);
-
- // Creates a GC-protected JS EventListener for an "onXXX" event attribute.
- // These listeners cannot be removed through the removeEventListener API.
+ // Creates a JS EventListener for an "onXXX" event attribute. These
+ // listeners cannot be removed through the removeEventListener API.
PassRefPtr<JSEventListener> createJSAttributeEventListener(JSC::JSValue);
- typedef HashMap<JSC::JSObject*, JSEventListener*> JSListenersMap;
-
- JSListenersMap& jsEventListeners();
-
// Make binding code generation easier.
JSDOMGlobalObject* globalObject() { return this; }
@@ -78,17 +67,27 @@ namespace WebCore {
protected:
struct JSDOMGlobalObjectData : public JSC::JSGlobalObject::JSGlobalObjectData {
- JSDOMGlobalObjectData();
+ JSDOMGlobalObjectData()
+ : JSGlobalObjectData(destroyJSDOMGlobalObjectData)
+ , evt(0)
+ {
+ }
+
+ JSDOMGlobalObjectData(Destructor destructor)
+ : JSGlobalObjectData(destructor)
+ , evt(0)
+ {
+ }
JSDOMStructureMap structures;
JSDOMConstructorMap constructors;
- JSDOMGlobalObject::JSListenersMap jsEventListeners;
-
Event* evt;
};
private:
+ static void destroyJSDOMGlobalObjectData(void*);
+
JSDOMGlobalObjectData* d() const { return static_cast<JSDOMGlobalObjectData*>(JSC::JSVariableObject::d); }
};
diff --git a/WebCore/bindings/js/JSDOMWindowBase.cpp b/WebCore/bindings/js/JSDOMWindowBase.cpp
index df6068a..a04ef89 100644
--- a/WebCore/bindings/js/JSDOMWindowBase.cpp
+++ b/WebCore/bindings/js/JSDOMWindowBase.cpp
@@ -42,13 +42,7 @@ namespace WebCore {
const ClassInfo JSDOMWindowBase::s_info = { "Window", 0, 0, 0 };
-JSDOMWindowBase::JSDOMWindowBaseData::JSDOMWindowBaseData(PassRefPtr<DOMWindow> window, JSDOMWindowShell* shell)
- : impl(window)
- , shell(shell)
-{
-}
-
-JSDOMWindowBase::JSDOMWindowBase(PassRefPtr<Structure> structure, PassRefPtr<DOMWindow> window, JSDOMWindowShell* shell)
+JSDOMWindowBase::JSDOMWindowBase(NonNullPassRefPtr<Structure> structure, PassRefPtr<DOMWindow> window, JSDOMWindowShell* shell)
: JSDOMGlobalObject(structure, new JSDOMWindowBaseData(window, shell), shell)
{
GlobalPropertyInfo staticGlobals[] = {
@@ -113,7 +107,7 @@ ExecState* JSDOMWindowBase::globalExec()
bool JSDOMWindowBase::supportsProfiling() const
{
-#if !ENABLE(JAVASCRIPT_DEBUGGER)
+#if !ENABLE(JAVASCRIPT_DEBUGGER) || !ENABLE(INSPECTOR)
return false;
#else
Frame* frame = impl()->frame();
@@ -167,11 +161,19 @@ JSGlobalData* JSDOMWindowBase::commonJSGlobalData()
if (!globalData) {
globalData = JSGlobalData::createLeaked().releaseRef();
globalData->timeoutChecker.setTimeoutInterval(10000); // 10 seconds
+#ifndef NDEBUG
+ globalData->mainThreadOnly = true;
+#endif
}
return globalData;
}
+void JSDOMWindowBase::destroyJSDOMWindowBaseData(void* jsDOMWindowBaseData)
+{
+ delete static_cast<JSDOMWindowBaseData*>(jsDOMWindowBaseData);
+}
+
// JSDOMGlobalObject* is ignored, accesing a window in any context will
// use that DOMWindow's prototype chain.
JSValue toJS(ExecState* exec, JSDOMGlobalObject*, DOMWindow* domWindow)
diff --git a/WebCore/bindings/js/JSDOMWindowBase.h b/WebCore/bindings/js/JSDOMWindowBase.h
index 84cc81f..52c3c1d 100644
--- a/WebCore/bindings/js/JSDOMWindowBase.h
+++ b/WebCore/bindings/js/JSDOMWindowBase.h
@@ -43,7 +43,7 @@ namespace WebCore {
class JSDOMWindowBase : public JSDOMGlobalObject {
typedef JSDOMGlobalObject Base;
protected:
- JSDOMWindowBase(PassRefPtr<JSC::Structure>, PassRefPtr<DOMWindow>, JSDOMWindowShell*);
+ JSDOMWindowBase(NonNullPassRefPtr<JSC::Structure>, PassRefPtr<DOMWindow>, JSDOMWindowShell*);
public:
void updateDocument();
@@ -76,7 +76,12 @@ namespace WebCore {
private:
struct JSDOMWindowBaseData : public JSDOMGlobalObjectData {
- JSDOMWindowBaseData(PassRefPtr<DOMWindow>, JSDOMWindowShell*);
+ JSDOMWindowBaseData(PassRefPtr<DOMWindow> window, JSDOMWindowShell* shell)
+ : JSDOMGlobalObjectData(destroyJSDOMWindowBaseData)
+ , impl(window)
+ , shell(shell)
+ {
+ }
RefPtr<DOMWindow> impl;
JSDOMWindowShell* shell;
@@ -85,6 +90,8 @@ namespace WebCore {
bool allowsAccessFromPrivate(const JSC::JSGlobalObject*) const;
String crossDomainAccessErrorMessage(const JSC::JSGlobalObject*) const;
+ static void destroyJSDOMWindowBaseData(void*);
+
JSDOMWindowBaseData* d() const { return static_cast<JSDOMWindowBaseData*>(JSC::JSVariableObject::d); }
};
diff --git a/WebCore/bindings/js/JSDOMWindowCustom.cpp b/WebCore/bindings/js/JSDOMWindowCustom.cpp
index 9798972..47339d4 100644
--- a/WebCore/bindings/js/JSDOMWindowCustom.cpp
+++ b/WebCore/bindings/js/JSDOMWindowCustom.cpp
@@ -38,29 +38,53 @@
#include "JSDOMWindowShell.h"
#include "JSEvent.h"
#include "JSEventListener.h"
+#include "JSEventSourceConstructor.h"
#include "JSHTMLCollection.h"
#include "JSHistory.h"
#include "JSImageConstructor.h"
#include "JSLocation.h"
#include "JSMessageChannelConstructor.h"
#include "JSMessagePort.h"
+#include "JSMessagePortCustom.h"
#include "JSOptionConstructor.h"
+
+#if ENABLE(SHARED_WORKERS)
#include "JSSharedWorkerConstructor.h"
+#endif
+
+#if ENABLE(3D_CANVAS)
+#include "JSCanvasArrayBufferConstructor.h"
+#include "JSCanvasByteArrayConstructor.h"
+#include "JSCanvasUnsignedByteArrayConstructor.h"
+#include "JSCanvasIntArrayConstructor.h"
+#include "JSCanvasUnsignedIntArrayConstructor.h"
+#include "JSCanvasShortArrayConstructor.h"
+#include "JSCanvasUnsignedShortArrayConstructor.h"
+#include "JSCanvasFloatArrayConstructor.h"
+#endif
#include "JSWebKitCSSMatrixConstructor.h"
#include "JSWebKitPointConstructor.h"
+#if ENABLE(WEB_SOCKETS)
+#include "JSWebSocketConstructor.h"
+#endif
#include "JSWorkerConstructor.h"
#include "JSXMLHttpRequestConstructor.h"
#include "JSXSLTProcessorConstructor.h"
#include "Location.h"
#include "MediaPlayer.h"
#include "MessagePort.h"
+#include "NotificationCenter.h"
#include "Page.h"
#include "PlatformScreen.h"
#include "RegisteredEventListener.h"
#include "ScheduledAction.h"
#include "ScriptController.h"
+#include "SerializedScriptValue.h"
#include "Settings.h"
+#include "SharedWorkerRepository.h"
#include "WindowFeatures.h"
+#include <runtime/Error.h>
+#include <runtime/JSFunction.h>
#include <runtime/JSObject.h>
#include <runtime/PrototypeFunction.h>
@@ -72,7 +96,7 @@ void JSDOMWindow::markChildren(MarkStack& markStack)
{
Base::markChildren(markStack);
- markEventListeners(markStack, impl()->eventListeners());
+ impl()->markEventListeners(markStack);
JSGlobalData& globalData = *Heap::heap(this)->globalData();
@@ -271,6 +295,150 @@ bool JSDOMWindow::getOwnPropertySlot(ExecState* exec, const Identifier& property
return Base::getOwnPropertySlot(exec, propertyName, slot);
}
+bool JSDOMWindow::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+ // When accessing a Window cross-domain, functions are always the native built-in ones, and they
+ // are not affected by properties changed on the Window or anything in its prototype chain.
+ // This is consistent with the behavior of Firefox.
+
+ const HashEntry* entry;
+
+ // We don't want any properties other than "close" and "closed" on a closed window.
+ if (!impl()->frame()) {
+ // The following code is safe for cross-domain and same domain use.
+ // It ignores any custom properties that might be set on the DOMWindow (including a custom prototype).
+ entry = s_info.propHashTable(exec)->entry(exec, propertyName);
+ if (entry && !(entry->attributes() & Function) && entry->propertyGetter() == jsDOMWindowClosed) {
+ descriptor.setDescriptor(jsBoolean(true), ReadOnly | DontDelete | DontEnum);
+ return true;
+ }
+ entry = JSDOMWindowPrototype::s_info.propHashTable(exec)->entry(exec, propertyName);
+ if (entry && (entry->attributes() & Function) && entry->function() == jsDOMWindowPrototypeFunctionClose) {
+ PropertySlot slot;
+ slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionClose, 0>);
+ descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
+ return true;
+ }
+ descriptor.setUndefined();
+ return true;
+ }
+
+ String errorMessage;
+ bool allowsAccess = allowsAccessFrom(exec, errorMessage);
+ if (allowsAccess && JSGlobalObject::getOwnPropertyDescriptor(exec, propertyName, descriptor))
+ return true;
+
+ // We need this code here because otherwise JSDOMWindowBase will stop the search before we even get to the
+ // prototype due to the blanket same origin (allowsAccessFrom) check at the end of getOwnPropertySlot.
+ // Also, it's important to get the implementation straight out of the DOMWindow prototype regardless of
+ // what prototype is actually set on this object.
+ entry = JSDOMWindowPrototype::s_info.propHashTable(exec)->entry(exec, propertyName);
+ if (entry) {
+ if (entry->attributes() & Function) {
+ if (entry->function() == jsDOMWindowPrototypeFunctionBlur) {
+ if (!allowsAccess) {
+ PropertySlot slot;
+ slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionBlur, 0>);
+ descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
+ return true;
+ }
+ } else if (entry->function() == jsDOMWindowPrototypeFunctionClose) {
+ if (!allowsAccess) {
+ PropertySlot slot;
+ slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionClose, 0>);
+ descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
+ return true;
+ }
+ } else if (entry->function() == jsDOMWindowPrototypeFunctionFocus) {
+ if (!allowsAccess) {
+ PropertySlot slot;
+ slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionFocus, 0>);
+ descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
+ return true;
+ }
+ } else if (entry->function() == jsDOMWindowPrototypeFunctionPostMessage) {
+ if (!allowsAccess) {
+ PropertySlot slot;
+ slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionPostMessage, 2>);
+ descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
+ return true;
+ }
+ } else if (entry->function() == jsDOMWindowPrototypeFunctionShowModalDialog) {
+ if (!DOMWindow::canShowModalDialog(impl()->frame())) {
+ descriptor.setUndefined();
+ return true;
+ }
+ }
+ }
+ } else {
+ // Allow access to toString() cross-domain, but always Object.prototype.toString.
+ if (propertyName == exec->propertyNames().toString) {
+ if (!allowsAccess) {
+ PropertySlot slot;
+ slot.setCustom(this, objectToStringFunctionGetter);
+ descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
+ return true;
+ }
+ }
+ }
+
+ entry = JSDOMWindow::s_info.propHashTable(exec)->entry(exec, propertyName);
+ if (entry) {
+ PropertySlot slot;
+ slot.setCustom(this, entry->propertyGetter());
+ descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
+ return true;
+ }
+
+ // Check for child frames by name before built-in properties to
+ // match Mozilla. This does not match IE, but some sites end up
+ // naming frames things that conflict with window properties that
+ // are in Moz but not IE. Since we have some of these, we have to do
+ // it the Moz way.
+ if (impl()->frame()->tree()->child(propertyName)) {
+ PropertySlot slot;
+ slot.setCustom(this, childFrameGetter);
+ descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
+ return true;
+ }
+
+ // Do prototype lookup early so that functions and attributes in the prototype can have
+ // precedence over the index and name getters.
+ JSValue proto = prototype();
+ if (proto.isObject()) {
+ if (asObject(proto)->getPropertyDescriptor(exec, propertyName, descriptor)) {
+ if (!allowsAccess) {
+ printErrorMessage(errorMessage);
+ descriptor.setUndefined();
+ }
+ return true;
+ }
+ }
+
+ bool ok;
+ unsigned i = propertyName.toArrayIndex(&ok);
+ if (ok && i < impl()->frame()->tree()->childCount()) {
+ PropertySlot slot;
+ slot.setCustomIndex(this, i, indexGetter);
+ descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
+ return true;
+ }
+
+ // Allow shortcuts like 'Image1' instead of document.images.Image1
+ Document* document = impl()->frame()->document();
+ if (document->isHTMLDocument()) {
+ AtomicStringImpl* atomicPropertyName = AtomicString::find(propertyName);
+ if (atomicPropertyName && (static_cast<HTMLDocument*>(document)->hasNamedItem(atomicPropertyName) || document->hasElementWithId(atomicPropertyName))) {
+ PropertySlot slot;
+ slot.setCustom(this, namedItemGetter);
+ descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
+ return true;
+ }
+ }
+
+ return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
+}
+
void JSDOMWindow::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
{
if (!impl()->frame())
@@ -306,6 +474,14 @@ void JSDOMWindow::getPropertyNames(ExecState* exec, PropertyNameArray& propertyN
Base::getPropertyNames(exec, propertyNames);
}
+void JSDOMWindow::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
+{
+ // Only allow the window to enumerated by frames in the same origin.
+ if (!allowsAccessFrom(exec))
+ return;
+ Base::getOwnPropertyNames(exec, propertyNames);
+}
+
bool JSDOMWindow::getPropertyAttributes(ExecState* exec, const Identifier& propertyName, unsigned& attributes) const
{
// Only allow getting property attributes properties by frames in the same origin.
@@ -314,7 +490,7 @@ bool JSDOMWindow::getPropertyAttributes(ExecState* exec, const Identifier& prope
return Base::getPropertyAttributes(exec, propertyName, attributes);
}
-void JSDOMWindow::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction)
+void JSDOMWindow::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes)
{
// Only allow defining getters by frames in the same origin.
if (!allowsAccessFrom(exec))
@@ -324,15 +500,23 @@ void JSDOMWindow::defineGetter(ExecState* exec, const Identifier& propertyName,
if (propertyName == "location")
return;
- Base::defineGetter(exec, propertyName, getterFunction);
+ Base::defineGetter(exec, propertyName, getterFunction, attributes);
}
-void JSDOMWindow::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction)
+void JSDOMWindow::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes)
{
// Only allow defining setters by frames in the same origin.
if (!allowsAccessFrom(exec))
return;
- Base::defineSetter(exec, propertyName, setterFunction);
+ Base::defineSetter(exec, propertyName, setterFunction, attributes);
+}
+
+bool JSDOMWindow::defineOwnProperty(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::PropertyDescriptor& descriptor, bool shouldThrow)
+{
+ // Only allow defining properties in this way by frames in the same origin, as it allows setters to be introduced.
+ if (!allowsAccessFrom(exec))
+ return false;
+ return Base::defineOwnProperty(exec, propertyName, descriptor, shouldThrow);
}
JSValue JSDOMWindow::lookupGetter(ExecState* exec, const Identifier& propertyName)
@@ -398,16 +582,16 @@ void JSDOMWindow::setLocation(ExecState* exec, JSValue value)
Frame* frame = impl()->frame();
ASSERT(frame);
- if (!shouldAllowNavigation(exec, frame))
- return;
-
KURL url = completeURL(exec, value.toString(exec));
if (url.isNull())
return;
+ if (!shouldAllowNavigation(exec, frame))
+ return;
+
if (!protocolIsJavaScript(url) || allowsAccessFrom(exec)) {
// We want a new history item if this JS was called via a user gesture
- frame->loader()->scheduleLocationChange(url, lexicalFrame->loader()->outgoingReferrer(), !lexicalFrame->script()->anyPageIsProcessingUserGesture(), false, processingUserGesture(exec));
+ frame->redirectScheduler()->scheduleLocationChange(url, lexicalFrame->loader()->outgoingReferrer(), !lexicalFrame->script()->anyPageIsProcessingUserGesture(), false, processingUserGesture(exec));
}
}
@@ -424,6 +608,13 @@ JSValue JSDOMWindow::event(ExecState* exec) const
return toJS(exec, event);
}
+#if ENABLE(EVENTSOURCE)
+JSValue JSDOMWindow::eventSource(ExecState* exec) const
+{
+ return getDOMConstructor<JSEventSourceConstructor>(exec, this);
+}
+#endif
+
JSValue JSDOMWindow::image(ExecState* exec) const
{
return getDOMConstructor<JSImageConstructor>(exec, this);
@@ -453,6 +644,48 @@ JSValue JSDOMWindow::webKitCSSMatrix(ExecState* exec) const
return getDOMConstructor<JSWebKitCSSMatrixConstructor>(exec, this);
}
+#if ENABLE(3D_CANVAS)
+JSValue JSDOMWindow::canvasArrayBuffer(ExecState* exec) const
+{
+ return getDOMConstructor<JSCanvasArrayBufferConstructor>(exec, this);
+}
+
+JSValue JSDOMWindow::canvasByteArray(ExecState* exec) const
+{
+ return getDOMConstructor<JSCanvasByteArrayConstructor>(exec, this);
+}
+
+JSValue JSDOMWindow::canvasUnsignedByteArray(ExecState* exec) const
+{
+ return getDOMConstructor<JSCanvasUnsignedByteArrayConstructor>(exec, this);
+}
+
+JSValue JSDOMWindow::canvasIntArray(ExecState* exec) const
+{
+ return getDOMConstructor<JSCanvasIntArrayConstructor>(exec, this);
+}
+
+JSValue JSDOMWindow::canvasUnsignedIntArray(ExecState* exec) const
+{
+ return getDOMConstructor<JSCanvasUnsignedIntArrayConstructor>(exec, this);
+}
+
+JSValue JSDOMWindow::canvasShortArray(ExecState* exec) const
+{
+ return getDOMConstructor<JSCanvasShortArrayConstructor>(exec, this);
+}
+
+JSValue JSDOMWindow::canvasUnsignedShortArray(ExecState* exec) const
+{
+ return getDOMConstructor<JSCanvasUnsignedShortArrayConstructor>(exec, this);
+}
+
+JSValue JSDOMWindow::canvasFloatArray(ExecState* exec) const
+{
+ return getDOMConstructor<JSCanvasFloatArrayConstructor>(exec, this);
+}
+#endif
+
JSValue JSDOMWindow::xmlHttpRequest(ExecState* exec) const
{
return getDOMConstructor<JSXMLHttpRequestConstructor>(exec, this);
@@ -482,7 +715,24 @@ JSValue JSDOMWindow::worker(ExecState* exec) const
#if ENABLE(SHARED_WORKERS)
JSValue JSDOMWindow::sharedWorker(ExecState* exec) const
{
- return getDOMConstructor<JSSharedWorkerConstructor>(exec, this);
+ if (SharedWorkerRepository::isAvailable())
+ return getDOMConstructor<JSSharedWorkerConstructor>(exec, this);
+ return jsUndefined();
+}
+#endif
+
+#if ENABLE(WEB_SOCKETS)
+JSValue JSDOMWindow::webSocket(ExecState* exec) const
+{
+ Frame* frame = impl()->frame();
+ if (!frame)
+ return jsUndefined();
+ Settings* settings = frame->settings();
+ if (!settings)
+ return jsUndefined();
+ if (!settings->experimentalWebSocketsEnabled())
+ return jsUndefined();
+ return getDOMConstructor<JSWebSocketConstructor>(exec, this);
}
#endif
@@ -521,7 +771,7 @@ static Frame* createWindow(ExecState* exec, Frame* lexicalFrame, Frame* dynamicF
return 0;
newFrame->loader()->setOpener(openerFrame);
- newFrame->loader()->setOpenedByDOM();
+ newFrame->page()->setOpenedByDOM();
JSDOMWindow* newWindow = toJSDOMWindow(newFrame);
@@ -529,13 +779,13 @@ static Frame* createWindow(ExecState* exec, Frame* lexicalFrame, Frame* dynamicF
newWindow->putDirect(Identifier(exec, "dialogArguments"), dialogArgs);
if (!protocolIsJavaScript(url) || newWindow->allowsAccessFrom(exec)) {
- KURL completedURL = url.isEmpty() ? KURL("") : completeURL(exec, url);
+ KURL completedURL = url.isEmpty() ? KURL(ParsedURLString, "") : completeURL(exec, url);
bool userGesture = processingUserGesture(exec);
if (created)
newFrame->loader()->changeLocation(completedURL, referrer, false, false, userGesture);
else if (!url.isEmpty())
- newFrame->loader()->scheduleLocationChange(completedURL.string(), referrer, !lexicalFrame->script()->anyPageIsProcessingUserGesture(), false, userGesture);
+ newFrame->redirectScheduler()->scheduleLocationChange(completedURL.string(), referrer, !lexicalFrame->script()->anyPageIsProcessingUserGesture(), false, userGesture);
}
return newFrame;
@@ -543,6 +793,10 @@ static Frame* createWindow(ExecState* exec, Frame* lexicalFrame, Frame* dynamicF
JSValue JSDOMWindow::open(ExecState* exec, const ArgList& args)
{
+ String urlString = valueToStringWithUndefinedOrNullCheck(exec, args.at(0));
+ AtomicString frameName = args.at(1).isUndefinedOrNull() ? "_blank" : AtomicString(args.at(1).toString(exec));
+ WindowFeatures windowFeatures(valueToStringWithUndefinedOrNullCheck(exec, args.at(2)));
+
Frame* frame = impl()->frame();
if (!frame)
return jsUndefined();
@@ -555,9 +809,6 @@ JSValue JSDOMWindow::open(ExecState* exec, const ArgList& args)
Page* page = frame->page();
- String urlString = valueToStringWithUndefinedOrNullCheck(exec, args.at(0));
- AtomicString frameName = args.at(1).isUndefinedOrNull() ? "_blank" : AtomicString(args.at(1).toString(exec));
-
// Because FrameTree::find() returns true for empty strings, we must check for empty framenames.
// Otherwise, illegitimate window.open() calls with no name will pass right through the popup blocker.
if (!DOMWindow::allowPopUp(dynamicFrame) && (frameName.isEmpty() || !frame->tree()->find(frameName)))
@@ -575,13 +826,13 @@ JSValue JSDOMWindow::open(ExecState* exec, const ArgList& args)
topOrParent = true;
}
if (topOrParent) {
- if (!shouldAllowNavigation(exec, frame))
- return jsUndefined();
-
String completedURL;
if (!urlString.isEmpty())
completedURL = completeURL(exec, urlString).string();
+ if (!shouldAllowNavigation(exec, frame))
+ return jsUndefined();
+
const JSDOMWindow* targetedWindow = toJSDOMWindow(frame);
if (!completedURL.isEmpty() && (!protocolIsJavaScript(completedURL) || (targetedWindow && targetedWindow->allowsAccessFrom(exec)))) {
bool userGesture = processingUserGesture(exec);
@@ -591,13 +842,12 @@ JSValue JSDOMWindow::open(ExecState* exec, const ArgList& args)
// here.
String referrer = dynamicFrame->loader()->outgoingReferrer();
- frame->loader()->scheduleLocationChange(completedURL, referrer, !lexicalFrame->script()->anyPageIsProcessingUserGesture(), false, userGesture);
+ frame->redirectScheduler()->scheduleLocationChange(completedURL, referrer, !lexicalFrame->script()->anyPageIsProcessingUserGesture(), false, userGesture);
}
return toJS(exec, frame->domWindow());
}
// In the case of a named frame or a new window, we'll use the createWindow() helper
- WindowFeatures windowFeatures(valueToStringWithUndefinedOrNullCheck(exec, args.at(2)));
FloatRect windowRect(windowFeatures.xSet ? windowFeatures.x : 0, windowFeatures.ySet ? windowFeatures.y : 0,
windowFeatures.widthSet ? windowFeatures.width : 0, windowFeatures.heightSet ? windowFeatures.height : 0);
DOMWindow::adjustWindowRect(screenAvailableRect(page ? page->mainFrame()->view() : 0), windowRect, windowRect);
@@ -617,6 +867,10 @@ JSValue JSDOMWindow::open(ExecState* exec, const ArgList& args)
JSValue JSDOMWindow::showModalDialog(ExecState* exec, const ArgList& args)
{
+ String url = valueToStringWithUndefinedOrNullCheck(exec, args.at(0));
+ JSValue dialogArgs = args.at(1);
+ String featureArgs = valueToStringWithUndefinedOrNullCheck(exec, args.at(2));
+
Frame* frame = impl()->frame();
if (!frame)
return jsUndefined();
@@ -630,10 +884,6 @@ JSValue JSDOMWindow::showModalDialog(ExecState* exec, const ArgList& args)
if (!DOMWindow::canShowModalDialogNow(frame) || !DOMWindow::allowPopUp(dynamicFrame))
return jsUndefined();
- String url = valueToStringWithUndefinedOrNullCheck(exec, args.at(0));
- JSValue dialogArgs = args.at(1);
- String featureArgs = valueToStringWithUndefinedOrNullCheck(exec, args.at(2));
-
HashMap<String, String> features;
DOMWindow::parseModalDialogFeatures(featureArgs, features);
@@ -687,7 +937,15 @@ JSValue JSDOMWindow::showModalDialog(ExecState* exec, const ArgList& args)
JSDOMWindow* dialogWindow = toJSDOMWindow(dialogFrame);
dialogFrame->page()->chrome()->runModal();
- return dialogWindow->getDirect(Identifier(exec, "returnValue"));
+ Identifier returnValue(exec, "returnValue");
+ if (dialogWindow->allowsAccessFromNoErrorMessage(exec)) {
+ PropertySlot slot;
+ // This is safe, we have already performed the origin security check and we are
+ // not interested in any of the DOM properties of the window.
+ if (dialogWindow->JSGlobalObject::getOwnPropertySlot(exec, returnValue, slot))
+ return slot.getValue(exec, returnValue);
+ }
+ return jsUndefined();
}
JSValue JSDOMWindow::postMessage(ExecState* exec, const ArgList& args)
@@ -695,19 +953,23 @@ JSValue JSDOMWindow::postMessage(ExecState* exec, const ArgList& args)
DOMWindow* window = impl();
DOMWindow* source = asJSDOMWindow(exec->lexicalGlobalObject())->impl();
- String message = args.at(0).toString(exec);
+ PassRefPtr<SerializedScriptValue> message = SerializedScriptValue::create(exec, args.at(0));
if (exec->hadException())
return jsUndefined();
- MessagePort* messagePort = (args.size() == 2) ? 0 : toMessagePort(args.at(1));
+ MessagePortArray messagePorts;
+ if (args.size() > 2)
+ fillMessagePortArray(exec, args.at(1), messagePorts);
+ if (exec->hadException())
+ return jsUndefined();
String targetOrigin = valueToStringWithUndefinedOrNullCheck(exec, args.at((args.size() == 2) ? 1 : 2));
if (exec->hadException())
return jsUndefined();
ExceptionCode ec = 0;
- window->postMessage(message, messagePort, targetOrigin, source, ec);
+ window->postMessage(message, &messagePorts, targetOrigin, source, ec);
setDOMException(exec, ec);
return jsUndefined();
@@ -788,9 +1050,11 @@ JSValue JSDOMWindow::addEventListener(ExecState* exec, const ArgList& args)
if (!frame)
return jsUndefined();
- if (RefPtr<JSEventListener> listener = findOrCreateJSEventListener(args.at(1)))
- impl()->addEventListener(AtomicString(args.at(0).toString(exec)), listener.release(), args.at(2).toBoolean(exec));
+ JSValue listener = args.at(1);
+ if (!listener.isObject())
+ return jsUndefined();
+ impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false), args.at(2).toBoolean(exec));
return jsUndefined();
}
@@ -800,9 +1064,11 @@ JSValue JSDOMWindow::removeEventListener(ExecState* exec, const ArgList& args)
if (!frame)
return jsUndefined();
- if (JSEventListener* listener = findJSEventListener(args.at(1)))
- impl()->removeEventListener(AtomicString(args.at(0).toString(exec)), listener, args.at(2).toBoolean(exec));
+ JSValue listener = args.at(1);
+ if (!listener.isObject())
+ return jsUndefined();
+ impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false).get(), args.at(2).toBoolean(exec));
return jsUndefined();
}
diff --git a/WebCore/bindings/js/JSDOMWindowShell.cpp b/WebCore/bindings/js/JSDOMWindowShell.cpp
index efffd42..3c3ff4c 100644
--- a/WebCore/bindings/js/JSDOMWindowShell.cpp
+++ b/WebCore/bindings/js/JSDOMWindowShell.cpp
@@ -88,6 +88,11 @@ bool JSDOMWindowShell::getOwnPropertySlot(ExecState* exec, const Identifier& pro
return m_window->getOwnPropertySlot(exec, propertyName, slot);
}
+bool JSDOMWindowShell::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+ return m_window->getOwnPropertyDescriptor(exec, propertyName, descriptor);
+}
+
void JSDOMWindowShell::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
{
m_window->put(exec, propertyName, value, slot);
@@ -98,6 +103,11 @@ void JSDOMWindowShell::putWithAttributes(ExecState* exec, const Identifier& prop
m_window->putWithAttributes(exec, propertyName, value, attributes);
}
+bool JSDOMWindowShell::defineOwnProperty(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::PropertyDescriptor& descriptor, bool shouldThrow)
+{
+ return m_window->defineOwnProperty(exec, propertyName, descriptor, shouldThrow);
+}
+
bool JSDOMWindowShell::deleteProperty(ExecState* exec, const Identifier& propertyName)
{
return m_window->deleteProperty(exec, propertyName);
@@ -108,19 +118,24 @@ void JSDOMWindowShell::getPropertyNames(ExecState* exec, PropertyNameArray& prop
m_window->getPropertyNames(exec, propertyNames);
}
+void JSDOMWindowShell::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
+{
+ m_window->getOwnPropertyNames(exec, propertyNames);
+}
+
bool JSDOMWindowShell::getPropertyAttributes(JSC::ExecState* exec, const Identifier& propertyName, unsigned& attributes) const
{
return m_window->getPropertyAttributes(exec, propertyName, attributes);
}
-void JSDOMWindowShell::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction)
+void JSDOMWindowShell::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes)
{
- m_window->defineGetter(exec, propertyName, getterFunction);
+ m_window->defineGetter(exec, propertyName, getterFunction, attributes);
}
-void JSDOMWindowShell::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction)
+void JSDOMWindowShell::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes)
{
- m_window->defineSetter(exec, propertyName, setterFunction);
+ m_window->defineSetter(exec, propertyName, setterFunction, attributes);
}
JSValue JSDOMWindowShell::lookupGetter(ExecState* exec, const Identifier& propertyName)
diff --git a/WebCore/bindings/js/JSDOMWindowShell.h b/WebCore/bindings/js/JSDOMWindowShell.h
index 0506283..23af340 100644
--- a/WebCore/bindings/js/JSDOMWindowShell.h
+++ b/WebCore/bindings/js/JSDOMWindowShell.h
@@ -67,13 +67,16 @@ namespace WebCore {
virtual void markChildren(JSC::MarkStack&);
virtual JSC::UString className() const;
virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&);
+ virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&);
virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&);
virtual void putWithAttributes(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, unsigned attributes);
virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier& propertyName);
virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&);
+ virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&);
virtual bool getPropertyAttributes(JSC::ExecState*, const JSC::Identifier& propertyName, unsigned& attributes) const;
- virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction);
- virtual void defineSetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction);
+ virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction, unsigned attributes);
+ virtual void defineSetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction, unsigned attributes);
+ virtual bool defineOwnProperty(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&, bool shouldThrow);
virtual JSC::JSValue lookupGetter(JSC::ExecState*, const JSC::Identifier& propertyName);
virtual JSC::JSValue lookupSetter(JSC::ExecState*, const JSC::Identifier& propertyName);
virtual JSC::JSObject* unwrappedObject();
diff --git a/WebCore/bindings/js/JSDatabaseCustom.cpp b/WebCore/bindings/js/JSDatabaseCustom.cpp
index af3b066..0932cca 100644
--- a/WebCore/bindings/js/JSDatabaseCustom.cpp
+++ b/WebCore/bindings/js/JSDatabaseCustom.cpp
@@ -52,17 +52,13 @@ JSValue JSDatabase::changeVersion(ExecState* exec, const ArgList& args)
String oldVersion = args.at(0).toString(exec);
String newVersion = args.at(1).toString(exec);
- Frame* frame = asJSDOMWindow(exec->dynamicGlobalObject())->impl()->frame();
- if (!frame)
- return jsUndefined();
-
JSObject* object;
if (!(object = args.at(2).getObject())) {
setDOMException(exec, TYPE_MISMATCH_ERR);
return jsUndefined();
}
- RefPtr<SQLTransactionCallback> callback(JSCustomSQLTransactionCallback::create(object, frame));
+ RefPtr<SQLTransactionCallback> callback(JSCustomSQLTransactionCallback::create(object, static_cast<JSDOMGlobalObject*>(exec->dynamicGlobalObject())));
RefPtr<SQLTransactionErrorCallback> errorCallback;
if (!args.at(3).isNull()) {
@@ -71,24 +67,25 @@ JSValue JSDatabase::changeVersion(ExecState* exec, const ArgList& args)
return jsUndefined();
}
- errorCallback = JSCustomSQLTransactionErrorCallback::create(object, frame);
+ errorCallback = JSCustomSQLTransactionErrorCallback::create(object, static_cast<JSDOMGlobalObject*>(exec->dynamicGlobalObject()));
}
RefPtr<VoidCallback> successCallback;
if (!args.at(4).isNull()) {
- successCallback = toVoidCallback(exec, args.at(4));
- if (!successCallback) {
+ if (!(object = args.at(4).getObject())) {
setDOMException(exec, TYPE_MISMATCH_ERR);
return jsUndefined();
}
+
+ successCallback = JSCustomVoidCallback::create(object, static_cast<JSDOMGlobalObject*>(exec->dynamicGlobalObject()));
}
-
+
m_impl->changeVersion(oldVersion, newVersion, callback.release(), errorCallback.release(), successCallback.release());
return jsUndefined();
}
-JSValue JSDatabase::transaction(ExecState* exec, const ArgList& args)
+static JSValue createTransaction(ExecState* exec, const ArgList& args, Database* database, JSDOMGlobalObject* globalObject, bool readOnly)
{
JSObject* object;
@@ -96,12 +93,8 @@ JSValue JSDatabase::transaction(ExecState* exec, const ArgList& args)
setDOMException(exec, TYPE_MISMATCH_ERR);
return jsUndefined();
}
-
- Frame* frame = asJSDOMWindow(exec->dynamicGlobalObject())->impl()->frame();
- if (!frame)
- return jsUndefined();
-
- RefPtr<SQLTransactionCallback> callback(JSCustomSQLTransactionCallback::create(object, frame));
+
+ RefPtr<SQLTransactionCallback> callback(JSCustomSQLTransactionCallback::create(object, globalObject));
RefPtr<SQLTransactionErrorCallback> errorCallback;
if (args.size() > 1 && !args.at(1).isNull()) {
@@ -110,22 +103,33 @@ JSValue JSDatabase::transaction(ExecState* exec, const ArgList& args)
return jsUndefined();
}
- errorCallback = JSCustomSQLTransactionErrorCallback::create(object, frame);
+ errorCallback = JSCustomSQLTransactionErrorCallback::create(object, globalObject);
}
RefPtr<VoidCallback> successCallback;
if (args.size() > 2 && !args.at(2).isNull()) {
- successCallback = toVoidCallback(exec, args.at(2));
- if (!successCallback) {
+ if (!(object = args.at(2).getObject())) {
setDOMException(exec, TYPE_MISMATCH_ERR);
return jsUndefined();
}
+
+ successCallback = JSCustomVoidCallback::create(object, globalObject);
}
- m_impl->transaction(callback.release(), errorCallback.release(), successCallback.release());
-
+ database->transaction(callback.release(), errorCallback.release(), successCallback.release(), readOnly);
return jsUndefined();
}
+
+JSValue JSDatabase::transaction(ExecState* exec, const ArgList& args)
+{
+ return createTransaction(exec, args, m_impl.get(), static_cast<JSDOMGlobalObject*>(exec->dynamicGlobalObject()), false);
+}
+JSValue JSDatabase::readTransaction(ExecState* exec, const ArgList& args)
+{
+ return createTransaction(exec, args, m_impl.get(), static_cast<JSDOMGlobalObject*>(exec->dynamicGlobalObject()), true);
+}
+
}
+
#endif // ENABLE(DATABASE)
diff --git a/WebCore/bindings/js/JSDedicatedWorkerContextCustom.cpp b/WebCore/bindings/js/JSDedicatedWorkerContextCustom.cpp
index 657f9b3..fbee5ef 100644
--- a/WebCore/bindings/js/JSDedicatedWorkerContextCustom.cpp
+++ b/WebCore/bindings/js/JSDedicatedWorkerContextCustom.cpp
@@ -35,15 +35,16 @@
#include "JSDedicatedWorkerContext.h"
+#include "JSDOMBinding.h"
+#include "JSMessagePortCustom.h"
+
using namespace JSC;
namespace WebCore {
-void JSDedicatedWorkerContext::markChildren(MarkStack& markStack)
+JSC::JSValue JSDedicatedWorkerContext::postMessage(JSC::ExecState* exec, const JSC::ArgList& args)
{
- Base::markChildren(markStack);
-
- markIfNotNull(markStack, impl()->onmessage());
+ return handlePostMessage(exec, args, impl());
}
} // namespace WebCore
diff --git a/WebCore/bindings/js/JSDesktopNotificationsCustom.cpp b/WebCore/bindings/js/JSDesktopNotificationsCustom.cpp
new file mode 100644
index 0000000..493d7bd
--- /dev/null
+++ b/WebCore/bindings/js/JSDesktopNotificationsCustom.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(NOTIFICATIONS)
+
+#include "Document.h"
+#include "JSCustomVoidCallback.h"
+#include "JSEventListener.h"
+#include "JSNotification.h"
+#include "JSNotificationCenter.h"
+#include "Notification.h"
+#include "NotificationCenter.h"
+#include <runtime/Error.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+JSValue JSNotificationCenter::requestPermission(ExecState* exec, const ArgList& args)
+{
+ // Permission request is only valid from page context.
+ ScriptExecutionContext* context = impl()->context();
+ if (context->isWorkerContext())
+ return throwError(exec, SyntaxError);
+
+ if (!args.at(0).isObject())
+ return throwError(exec, TypeError);
+
+ PassRefPtr<JSCustomVoidCallback> callback = JSCustomVoidCallback::create(args.at(0).getObject(), static_cast<Document*>(context)->frame());
+
+ impl()->requestPermission(callback);
+ return jsUndefined();
+}
+
+JSValue JSNotification::addEventListener(ExecState* exec, const ArgList& args)
+{
+ JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->scriptExecutionContext());
+ if (!globalObject)
+ return jsUndefined();
+
+ JSValue listener = args.at(1);
+ if (!listener.isObject())
+ return jsUndefined();
+
+ impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener)), globalObject, false), args.at(2).toBoolean(exec));
+ return jsUndefined();
+}
+
+JSValue JSNotification::removeEventListener(ExecState* exec, const ArgList& args)
+{
+ JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->scriptExecutionContext());
+ if (!globalObject)
+ return jsUndefined();
+
+ JSValue listener = args.at(1);
+ if (!listener.isObject())
+ return jsUndefined();
+
+ impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), globalObject, false).get(), args.at(2).toBoolean(exec));
+ return jsUndefined();
+}
+
+
+} // namespace
+
+#endif // ENABLE(NOTIFICATIONS)
diff --git a/WebCore/bindings/js/JSDocumentCustom.cpp b/WebCore/bindings/js/JSDocumentCustom.cpp
index 39a1fc5..d7f8725 100644
--- a/WebCore/bindings/js/JSDocumentCustom.cpp
+++ b/WebCore/bindings/js/JSDocumentCustom.cpp
@@ -24,6 +24,10 @@
#include "Frame.h"
#include "FrameLoader.h"
#include "HTMLDocument.h"
+#include "JSCanvasRenderingContext2D.h"
+#if ENABLE(3D_CANVAS)
+#include "JSCanvasRenderingContext3D.h"
+#endif
#include "JSDOMWindowCustom.h"
#include "JSHTMLDocument.h"
#include "JSLocation.h"
@@ -35,6 +39,8 @@
#include "SVGDocument.h"
#endif
+#include <wtf/GetPtr.h>
+
using namespace JSC;
namespace WebCore {
@@ -42,8 +48,14 @@ namespace WebCore {
void JSDocument::markChildren(MarkStack& markStack)
{
JSNode::markChildren(markStack);
- markDOMNodesForDocument(markStack, impl());
- markActiveObjectsForContext(markStack, *Heap::heap(this)->globalData(), impl());
+
+ Document* document = impl();
+ JSGlobalData& globalData = *Heap::heap(this)->globalData();
+
+ markDOMNodesForDocument(markStack, document);
+ markActiveObjectsForContext(markStack, globalData, document);
+ markDOMObjectWrapper(markStack, globalData, document->implementation());
+ markDOMObjectWrapper(markStack, globalData, document->styleSheets());
}
JSValue JSDocument::location(ExecState* exec) const
@@ -76,7 +88,7 @@ void JSDocument::setLocation(ExecState* exec, JSValue value)
str = activeFrame->document()->completeURL(str).string();
bool userGesture = activeFrame->script()->processingUserGesture();
- frame->loader()->scheduleLocationChange(str, activeFrame->loader()->outgoingReferrer(), !activeFrame->script()->anyPageIsProcessingUserGesture(), false, userGesture);
+ frame->redirectScheduler()->scheduleLocationChange(str, activeFrame->loader()->outgoingReferrer(), !activeFrame->script()->anyPageIsProcessingUserGesture(), false, userGesture);
}
JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, Document* document)
diff --git a/WebCore/bindings/js/JSElementCustom.cpp b/WebCore/bindings/js/JSElementCustom.cpp
index 47793d0..fb64ff2 100644
--- a/WebCore/bindings/js/JSElementCustom.cpp
+++ b/WebCore/bindings/js/JSElementCustom.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -51,15 +51,27 @@ namespace WebCore {
using namespace HTMLNames;
+void JSElement::markChildren(MarkStack& markStack)
+{
+ Base::markChildren(markStack);
+
+ Element* element = impl();
+ JSGlobalData& globalData = *Heap::heap(this)->globalData();
+
+ markDOMObjectWrapper(markStack, globalData, element->attributeMap());
+ if (element->isStyledElement())
+ markDOMObjectWrapper(markStack, globalData, static_cast<StyledElement*>(element)->inlineStyleDecl());
+}
+
static inline bool allowSettingSrcToJavascriptURL(ExecState* exec, Element* element, const String& name, const String& value)
{
if ((element->hasTagName(iframeTag) || element->hasTagName(frameTag)) && equalIgnoringCase(name, "src") && protocolIsJavaScript(deprecatedParseURL(value))) {
- HTMLFrameElementBase* frame = static_cast<HTMLFrameElementBase*>(element);
- if (!checkNodeSecurity(exec, frame->contentDocument()))
+ Document* contentDocument = static_cast<HTMLFrameElementBase*>(element)->contentDocument();
+ if (contentDocument && !checkNodeSecurity(exec, contentDocument))
return false;
}
return true;
-}
+}
JSValue JSElement::setAttribute(ExecState* exec, const ArgList& args)
{
diff --git a/WebCore/bindings/js/JSEventCustom.cpp b/WebCore/bindings/js/JSEventCustom.cpp
index 804c529..c64ddc9 100644
--- a/WebCore/bindings/js/JSEventCustom.cpp
+++ b/WebCore/bindings/js/JSEventCustom.cpp
@@ -38,6 +38,7 @@
#include "JSMouseEvent.h"
#include "JSMutationEvent.h"
#include "JSOverflowEvent.h"
+#include "JSPageTransitionEvent.h"
#include "JSProgressEvent.h"
#include "JSTextEvent.h"
#include "JSUIEvent.h"
@@ -51,6 +52,7 @@
#include "MouseEvent.h"
#include "MutationEvent.h"
#include "OverflowEvent.h"
+#include "PageTransitionEvent.h"
#include "ProgressEvent.h"
#include "TextEvent.h"
#include "UIEvent.h"
@@ -120,6 +122,8 @@ JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, Event* event)
wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, OverflowEvent, event);
else if (event->isMessageEvent())
wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, MessageEvent, event);
+ else if (event->isPageTransitionEvent())
+ wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, PageTransitionEvent, event);
else if (event->isProgressEvent()) {
if (event->isXMLHttpRequestProgressEvent())
wrapper = CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, XMLHttpRequestProgressEvent, event);
diff --git a/WebCore/bindings/js/JSEventListener.cpp b/WebCore/bindings/js/JSEventListener.cpp
index 42e0281..4f273fe 100644
--- a/WebCore/bindings/js/JSEventListener.cpp
+++ b/WebCore/bindings/js/JSEventListener.cpp
@@ -31,22 +31,18 @@ using namespace JSC;
namespace WebCore {
-JSEventListener::JSEventListener(JSObject* function, JSDOMGlobalObject* globalObject, bool isAttribute)
- : m_jsFunction(function)
- , m_globalObject(globalObject)
+JSEventListener::JSEventListener(JSObject* function, bool isAttribute)
+ : EventListener(JSEventListenerType)
+ , m_jsFunction(function)
, m_isAttribute(isAttribute)
{
- if (!m_isAttribute && m_jsFunction)
- globalObject->jsEventListeners().set(m_jsFunction, this);
}
JSEventListener::~JSEventListener()
{
- if (!m_isAttribute && m_jsFunction && m_globalObject)
- m_globalObject->jsEventListeners().remove(m_jsFunction);
}
-JSObject* JSEventListener::jsFunction() const
+JSObject* JSEventListener::jsFunction(ScriptExecutionContext*) const
{
return m_jsFunction;
}
@@ -55,30 +51,24 @@ void JSEventListener::markJSFunction(MarkStack& markStack)
{
if (m_jsFunction)
markStack.append(m_jsFunction);
- if (m_globalObject)
- markStack.append(m_globalObject);
}
-void JSEventListener::handleEvent(Event* event, bool isWindowEvent)
+void JSEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext, Event* event)
{
+ ASSERT(scriptExecutionContext);
+ if (!scriptExecutionContext)
+ return;
+
JSLock lock(SilenceAssertionsOnly);
- JSObject* jsFunction = this->jsFunction();
+ JSObject* jsFunction = this->jsFunction(scriptExecutionContext);
if (!jsFunction)
return;
- JSDOMGlobalObject* globalObject = m_globalObject;
- // Null check as clearGlobalObject() can clear this and we still get called back by
- // xmlhttprequest objects. See http://bugs.webkit.org/show_bug.cgi?id=13275
- // FIXME: Is this check still necessary? Requests are supposed to be stopped before clearGlobalObject() is called.
- ASSERT(globalObject);
+ JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(scriptExecutionContext);
if (!globalObject)
return;
- ScriptExecutionContext* scriptExecutionContext = globalObject->scriptExecutionContext();
- if (!scriptExecutionContext)
- return;
-
if (scriptExecutionContext->isDocument()) {
JSDOMWindow* window = static_cast<JSDOMWindow*>(globalObject);
Frame* frame = window->impl()->frame();
@@ -113,26 +103,14 @@ void JSEventListener::handleEvent(Event* event, bool isWindowEvent)
Event* savedEvent = globalObject->currentEvent();
globalObject->setCurrentEvent(event);
- // If this event handler is the first JavaScript to execute, then the
- // dynamic global object should be set to the global object of the
- // window in which the event occurred.
JSGlobalData* globalData = globalObject->globalData();
DynamicGlobalObjectScope globalObjectScope(exec, globalData->dynamicGlobalObject ? globalData->dynamicGlobalObject : globalObject);
- JSValue retval;
- if (handleEventFunction) {
- globalObject->globalData()->timeoutChecker.start();
- retval = call(exec, handleEventFunction, callType, callData, jsFunction, args);
- } else {
- JSValue thisValue;
- if (isWindowEvent)
- thisValue = globalObject->toThisObject(exec);
- else
- thisValue = toJS(exec, globalObject, event->currentTarget());
- globalObject->globalData()->timeoutChecker.start();
- retval = call(exec, jsFunction, callType, callData, thisValue, args);
- }
- globalObject->globalData()->timeoutChecker.stop();
+ globalData->timeoutChecker.start();
+ JSValue retval = handleEventFunction
+ ? call(exec, handleEventFunction, callType, callData, jsFunction, args)
+ : call(exec, jsFunction, callType, callData, toJS(exec, globalObject, event->currentTarget()), args);
+ globalData->timeoutChecker.stop();
globalObject->setCurrentEvent(savedEvent);
@@ -154,18 +132,15 @@ void JSEventListener::handleEvent(Event* event, bool isWindowEvent)
}
}
-bool JSEventListener::reportError(const String& message, const String& url, int lineNumber)
+bool JSEventListener::reportError(ScriptExecutionContext* context, const String& message, const String& url, int lineNumber)
{
JSLock lock(SilenceAssertionsOnly);
- JSObject* jsFunction = this->jsFunction();
+ JSObject* jsFunction = this->jsFunction(context);
if (!jsFunction)
return false;
- JSDOMGlobalObject* globalObject = m_globalObject;
- if (!globalObject)
- return false;
-
+ JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(context);
ExecState* exec = globalObject->globalExec();
CallData callData;
@@ -179,17 +154,14 @@ bool JSEventListener::reportError(const String& message, const String& url, int
args.append(jsString(exec, url));
args.append(jsNumber(exec, lineNumber));
- // If this event handler is the first JavaScript to execute, then the
- // dynamic global object should be set to the global object of the
- // window in which the event occurred.
JSGlobalData* globalData = globalObject->globalData();
DynamicGlobalObjectScope globalObjectScope(exec, globalData->dynamicGlobalObject ? globalData->dynamicGlobalObject : globalObject);
JSValue thisValue = globalObject->toThisObject(exec);
- globalObject->globalData()->timeoutChecker.start();
+ globalData->timeoutChecker.start();
JSValue returnValue = call(exec, jsFunction, callType, callData, thisValue, args);
- globalObject->globalData()->timeoutChecker.stop();
+ globalData->timeoutChecker.stop();
// If an error occurs while handling the script error, it should be bubbled up.
if (exec->hadException()) {
@@ -206,4 +178,11 @@ bool JSEventListener::virtualisAttribute() const
return m_isAttribute;
}
+bool JSEventListener::operator==(const EventListener& listener)
+{
+ if (const JSEventListener* jsEventListener = JSEventListener::cast(&listener))
+ return m_jsFunction == jsEventListener->m_jsFunction && m_isAttribute == jsEventListener->m_isAttribute;
+ return false;
+}
+
} // namespace WebCore
diff --git a/WebCore/bindings/js/JSEventListener.h b/WebCore/bindings/js/JSEventListener.h
index 7929169..285a9c4 100644
--- a/WebCore/bindings/js/JSEventListener.h
+++ b/WebCore/bindings/js/JSEventListener.h
@@ -30,30 +30,38 @@ namespace WebCore {
class JSEventListener : public EventListener {
public:
- static PassRefPtr<JSEventListener> create(JSC::JSObject* listener, JSDOMGlobalObject* globalObject, bool isAttribute)
+ static PassRefPtr<JSEventListener> create(JSC::JSObject* listener, bool isAttribute)
{
- return adoptRef(new JSEventListener(listener, globalObject, isAttribute));
+ return adoptRef(new JSEventListener(listener, isAttribute));
}
+
+ static const JSEventListener* cast(const EventListener* listener)
+ {
+ return listener->type() == JSEventListenerType
+ ? static_cast<const JSEventListener*>(listener)
+ : 0;
+ }
+
virtual ~JSEventListener();
- void clearGlobalObject() { m_globalObject = 0; }
+
+ virtual bool operator==(const EventListener& other);
// Returns true if this event listener was created for an event handler attribute, like "onload" or "onclick".
bool isAttribute() const { return m_isAttribute; }
- virtual JSC::JSObject* jsFunction() const;
+ virtual JSC::JSObject* jsFunction(ScriptExecutionContext*) const;
private:
virtual void markJSFunction(JSC::MarkStack&);
- virtual void handleEvent(Event*, bool isWindowEvent);
- virtual bool reportError(const String& message, const String& url, int lineNumber);
+ virtual void handleEvent(ScriptExecutionContext*, Event*);
+ virtual bool reportError(ScriptExecutionContext*, const String& message, const String& url, int lineNumber);
virtual bool virtualisAttribute() const;
void clearJSFunctionInline();
protected:
- JSEventListener(JSC::JSObject* function, JSDOMGlobalObject*, bool isAttribute);
+ JSEventListener(JSC::JSObject* function, bool isAttribute);
mutable JSC::JSObject* m_jsFunction;
- JSDOMGlobalObject* m_globalObject;
bool m_isAttribute;
};
diff --git a/WebCore/bindings/js/JSEventSourceConstructor.cpp b/WebCore/bindings/js/JSEventSourceConstructor.cpp
new file mode 100644
index 0000000..c6e4825
--- /dev/null
+++ b/WebCore/bindings/js/JSEventSourceConstructor.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2009 Ericsson AB
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Ericsson nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(EVENTSOURCE)
+
+#include "JSEventSourceConstructor.h"
+
+#include "EventSource.h"
+#include "ExceptionCode.h"
+#include "JSEventSource.h"
+#include "ScriptExecutionContext.h"
+#include <runtime/Error.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+ASSERT_CLASS_FITS_IN_CELL(JSEventSourceConstructor);
+
+const ClassInfo JSEventSourceConstructor::s_info = { "EventSourceContructor", 0, 0, 0 };
+
+JSEventSourceConstructor::JSEventSourceConstructor(ExecState* exec, JSDOMGlobalObject* globalObject)
+ : DOMConstructorObject(JSEventSourceConstructor::createStructure(globalObject->objectPrototype()), globalObject)
+{
+ putDirect(exec->propertyNames().prototype, JSEventSourcePrototype::self(exec, globalObject), None);
+ putDirect(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly|DontDelete|DontEnum);
+}
+
+static JSObject* constructEventSource(ExecState* exec, JSObject* constructor, const ArgList& args)
+{
+ if (args.size() < 1)
+ return throwError(exec, SyntaxError, "Not enough arguments");
+
+ UString url = args.at(0).toString(exec);
+ if (exec->hadException())
+ return 0;
+
+ JSEventSourceConstructor* jsConstructor = static_cast<JSEventSourceConstructor*>(constructor);
+ ScriptExecutionContext* context = jsConstructor->scriptExecutionContext();
+ if (!context)
+ return throwError(exec, ReferenceError, "EventSource constructor associated document is unavailable");
+
+ ExceptionCode ec = 0;
+ RefPtr<EventSource> eventSource = EventSource::create(url, context, ec);
+ if (ec) {
+ setDOMException(exec, ec);
+ return 0;
+ }
+
+ return asObject(toJS(exec, jsConstructor->globalObject(), eventSource.release()));
+}
+
+ConstructType JSEventSourceConstructor::getConstructData(ConstructData& constructData)
+{
+ constructData.native.function = constructEventSource;
+ return ConstructTypeHost;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(EVENTSOURCE)
diff --git a/WebCore/bindings/js/JSEventSourceConstructor.h b/WebCore/bindings/js/JSEventSourceConstructor.h
new file mode 100644
index 0000000..b2f3cb5
--- /dev/null
+++ b/WebCore/bindings/js/JSEventSourceConstructor.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2009 Ericsson AB
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Ericsson nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JSEventSourceConstructor_h
+#define JSEventSourceConstructor_h
+
+#if ENABLE(EVENTSOURCE)
+
+#include "JSDOMBinding.h"
+
+namespace WebCore {
+
+ class JSEventSourceConstructor : public DOMConstructorObject {
+ public:
+ JSEventSourceConstructor(JSC::ExecState*, JSDOMGlobalObject*);
+ static const JSC::ClassInfo s_info;
+
+ private:
+ virtual JSC::ConstructType getConstructData(JSC::ConstructData&);
+ virtual const JSC::ClassInfo* classInfo() const { return &s_info; }
+ };
+
+} // namespace WebCore
+
+#endif // ENABLE(EVENTSOURCE)
+
+#endif // JSEventSourceConstructor_h
diff --git a/WebCore/bindings/js/JSEventSourceCustom.cpp b/WebCore/bindings/js/JSEventSourceCustom.cpp
new file mode 100644
index 0000000..404bf11
--- /dev/null
+++ b/WebCore/bindings/js/JSEventSourceCustom.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2009 Ericsson AB
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name of Ericsson nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(EVENTSOURCE)
+
+#include "JSEventSource.h"
+
+#include "EventSource.h"
+#include "JSDOMGlobalObject.h"
+#include "JSEventListener.h"
+
+using namespace JSC;
+
+namespace WebCore {
+
+JSValue JSEventSource::addEventListener(ExecState* exec, const ArgList& args)
+{
+ JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->scriptExecutionContext());
+ if (!globalObject)
+ return jsUndefined();
+
+ JSValue listener = args.at(1);
+ if (!listener.isObject())
+ return jsUndefined();
+
+ impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false).get(), args.at(2).toBoolean(exec));
+ return jsUndefined();
+}
+
+JSValue JSEventSource::removeEventListener(ExecState* exec, const ArgList& args)
+{
+ JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->scriptExecutionContext());
+ if (!globalObject)
+ return jsUndefined();
+
+ JSValue listener = args.at(1);
+ if (!listener.isObject())
+ return jsUndefined();
+
+ impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false).get(), args.at(2).toBoolean(exec));
+ return jsUndefined();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(EVENTSOURCE)
diff --git a/WebCore/bindings/js/JSEventTarget.cpp b/WebCore/bindings/js/JSEventTarget.cpp
index c34e10e..0421d10 100644
--- a/WebCore/bindings/js/JSEventTarget.cpp
+++ b/WebCore/bindings/js/JSEventTarget.cpp
@@ -33,16 +33,29 @@
#include "JSEventListener.h"
#include "JSMessagePort.h"
#include "JSNode.h"
+#if ENABLE(SHARED_WORKERS)
+
#include "JSSharedWorker.h"
#include "JSSharedWorkerContext.h"
+#endif
+
#include "JSXMLHttpRequest.h"
#include "JSXMLHttpRequestUpload.h"
#include "MessagePort.h"
+
+#if ENABLE(SHARED_WORKERS)
#include "SharedWorker.h"
#include "SharedWorkerContext.h"
+#endif
+
#include "XMLHttpRequest.h"
#include "XMLHttpRequestUpload.h"
+#if ENABLE(EVENTSOURCE)
+#include "EventSource.h"
+#include "JSEventSource.h"
+#endif
+
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
#include "DOMApplicationCache.h"
#include "JSDOMApplicationCache.h"
@@ -60,6 +73,16 @@
#include "Worker.h"
#endif
+#if ENABLE(NOTIFICATIONS)
+#include "JSNotification.h"
+#include "Notification.h"
+#endif
+
+#if ENABLE(WEB_SOCKETS)
+#include "JSWebSocket.h"
+#include "WebSocket.h"
+#endif
+
using namespace JSC;
namespace WebCore {
@@ -69,6 +92,11 @@ JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, EventTarget* targ
if (!target)
return jsNull();
+#if ENABLE(EVENTSOURCE)
+ if (EventSource* eventSource = target->toEventSource())
+ return toJS(exec, globalObject, eventSource);
+#endif
+
#if ENABLE(SVG)
// SVGElementInstance supports both toSVGElementInstance and toNode since so much mouse handling code depends on toNode returning a valid node.
if (SVGElementInstance* instance = target->toSVGElementInstance())
@@ -111,6 +139,16 @@ JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, EventTarget* targ
return toJSDOMGlobalObject(workerContext);
#endif
+#if ENABLE(NOTIFICATIONS)
+ if (Notification* notification = target->toNotification())
+ return toJS(exec, notification);
+#endif
+
+#if ENABLE(WEB_SOCKETS)
+ if (WebSocket* webSocket = target->toWebSocket())
+ return toJS(exec, webSocket);
+#endif
+
ASSERT_NOT_REACHED();
return jsNull();
}
@@ -118,7 +156,7 @@ JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, EventTarget* targ
EventTarget* toEventTarget(JSC::JSValue value)
{
#define CONVERT_TO_EVENT_TARGET(type) \
- if (value.isObject(&JS##type::s_info)) \
+ if (value.inherits(&JS##type::s_info)) \
return static_cast<JS##type*>(asObject(value))->impl();
CONVERT_TO_EVENT_TARGET(Node)
@@ -126,9 +164,13 @@ EventTarget* toEventTarget(JSC::JSValue value)
CONVERT_TO_EVENT_TARGET(XMLHttpRequestUpload)
CONVERT_TO_EVENT_TARGET(MessagePort)
- if (value.isObject(&JSDOMWindowShell::s_info))
+ if (value.inherits(&JSDOMWindowShell::s_info))
return static_cast<JSDOMWindowShell*>(asObject(value))->impl();
+#if ENABLE(EVENTSOURCE)
+ CONVERT_TO_EVENT_TARGET(EventSource)
+#endif
+
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
CONVERT_TO_EVENT_TARGET(DOMApplicationCache)
#endif
@@ -147,6 +189,14 @@ EventTarget* toEventTarget(JSC::JSValue value)
CONVERT_TO_EVENT_TARGET(SharedWorkerContext)
#endif
+#if ENABLE(NOTIFICATIONS)
+ CONVERT_TO_EVENT_TARGET(Notification)
+#endif
+
+#if ENABLE(WEB_SOCKETS)
+ CONVERT_TO_EVENT_TARGET(WebSocket)
+#endif
+
return 0;
}
diff --git a/WebCore/bindings/js/JSGeolocationCustom.cpp b/WebCore/bindings/js/JSGeolocationCustom.cpp
index 8ef8601..530b89b 100644
--- a/WebCore/bindings/js/JSGeolocationCustom.cpp
+++ b/WebCore/bindings/js/JSGeolocationCustom.cpp
@@ -34,40 +34,39 @@
#include "JSCustomPositionErrorCallback.h"
#include "JSDOMWindow.h"
#include "PositionOptions.h"
+#include <runtime/InternalFunction.h>
using namespace JSC;
using namespace std;
namespace WebCore {
-static PassRefPtr<PositionCallback> createPositionCallback(ExecState* exec, JSValue value)
+static PassRefPtr<PositionCallback> createPositionCallback(ExecState* exec, JSDOMGlobalObject* globalObject, JSValue value)
{
// The spec specifies 'FunctionOnly' for this object.
- if (!value.isObject(&InternalFunction::info)) {
+ if (!value.inherits(&InternalFunction::info)) {
setDOMException(exec, TYPE_MISMATCH_ERR);
return 0;
}
JSObject* object = asObject(value);
- Frame* frame = toJSDOMWindow(exec->lexicalGlobalObject())->impl()->frame();
- return JSCustomPositionCallback::create(object, frame);
+ return JSCustomPositionCallback::create(object, globalObject);
}
-static PassRefPtr<PositionErrorCallback> createPositionErrorCallback(ExecState* exec, JSValue value)
+static PassRefPtr<PositionErrorCallback> createPositionErrorCallback(ExecState* exec, JSDOMGlobalObject* globalObject, JSValue value)
{
// Argument is optional (hence undefined is allowed), and null is allowed.
if (value.isUndefinedOrNull())
return 0;
// The spec specifies 'FunctionOnly' for this object.
- if (!value.isObject(&InternalFunction::info)) {
+ if (!value.inherits(&InternalFunction::info)) {
setDOMException(exec, TYPE_MISMATCH_ERR);
return 0;
}
JSObject* object = asObject(value);
- Frame* frame = toJSDOMWindow(exec->lexicalGlobalObject())->impl()->frame();
- return JSCustomPositionErrorCallback::create(object, frame);
+ return JSCustomPositionErrorCallback::create(object, globalObject);
}
static PassRefPtr<PositionOptions> createPositionOptions(ExecState* exec, JSValue value)
@@ -91,7 +90,7 @@ static PassRefPtr<PositionOptions> createPositionOptions(ExecState* exec, JSValu
JSValue enableHighAccuracyValue = object->get(exec, Identifier(exec, "enableHighAccuracy"));
if (exec->hadException())
return 0;
- if(!enableHighAccuracyValue.isUndefined()) {
+ if (!enableHighAccuracyValue.isUndefined()) {
options->setEnableHighAccuracy(enableHighAccuracyValue.toBoolean(exec));
if (exec->hadException())
return 0;
@@ -104,8 +103,8 @@ static PassRefPtr<PositionOptions> createPositionOptions(ExecState* exec, JSValu
double timeoutNumber = timeoutValue.toNumber(exec);
if (exec->hadException())
return 0;
- // If the value is infinity, there's nothing to do.
- if (timeoutNumber != Inf) {
+ // If the value is positive infinity, there's nothing to do.
+ if (!(isinf(timeoutNumber) && (timeoutNumber > 0))) {
// Wrap to int32 and force non-negative to match behavior of window.setTimeout.
options->setTimeout(max(0, timeoutValue.toInt32(exec)));
if (exec->hadException())
@@ -120,8 +119,8 @@ static PassRefPtr<PositionOptions> createPositionOptions(ExecState* exec, JSValu
double maximumAgeNumber = maximumAgeValue.toNumber(exec);
if (exec->hadException())
return 0;
- if (maximumAgeNumber == Inf) {
- // If the value is infinity, clear maximumAge.
+ if (isinf(maximumAgeNumber) && (maximumAgeNumber > 0)) {
+ // If the value is positive infinity, clear maximumAge.
options->clearMaximumAge();
} else {
// Wrap to int32 and force non-negative to match behavior of window.setTimeout.
@@ -138,12 +137,12 @@ JSValue JSGeolocation::getCurrentPosition(ExecState* exec, const ArgList& args)
{
// Arguments: PositionCallback, (optional)PositionErrorCallback, (optional)PositionOptions
- RefPtr<PositionCallback> positionCallback = createPositionCallback(exec, args.at(0));
+ RefPtr<PositionCallback> positionCallback = createPositionCallback(exec, static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), args.at(0));
if (exec->hadException())
return jsUndefined();
ASSERT(positionCallback);
- RefPtr<PositionErrorCallback> positionErrorCallback = createPositionErrorCallback(exec, args.at(1));
+ RefPtr<PositionErrorCallback> positionErrorCallback = createPositionErrorCallback(exec, static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), args.at(1));
if (exec->hadException())
return jsUndefined();
@@ -160,12 +159,12 @@ JSValue JSGeolocation::watchPosition(ExecState* exec, const ArgList& args)
{
// Arguments: PositionCallback, (optional)PositionErrorCallback, (optional)PositionOptions
- RefPtr<PositionCallback> positionCallback = createPositionCallback(exec, args.at(0));
+ RefPtr<PositionCallback> positionCallback = createPositionCallback(exec, static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), args.at(0));
if (exec->hadException())
return jsUndefined();
ASSERT(positionCallback);
- RefPtr<PositionErrorCallback> positionErrorCallback = createPositionErrorCallback(exec, args.at(1));
+ RefPtr<PositionErrorCallback> positionErrorCallback = createPositionErrorCallback(exec, static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), args.at(1));
if (exec->hadException())
return jsUndefined();
diff --git a/WebCore/bindings/js/JSHTMLAllCollection.h b/WebCore/bindings/js/JSHTMLAllCollection.h
index 7363e5c..e6fe7f5 100644
--- a/WebCore/bindings/js/JSHTMLAllCollection.h
+++ b/WebCore/bindings/js/JSHTMLAllCollection.h
@@ -35,7 +35,7 @@ namespace WebCore {
class JSHTMLAllCollection : public JSHTMLCollection {
public:
- JSHTMLAllCollection(PassRefPtr<JSC::Structure> structure, JSDOMGlobalObject* globalObject, PassRefPtr<HTMLCollection> collection)
+ JSHTMLAllCollection(NonNullPassRefPtr<JSC::Structure> structure, JSDOMGlobalObject* globalObject, PassRefPtr<HTMLCollection> collection)
: JSHTMLCollection(structure, globalObject, collection)
{
}
diff --git a/WebCore/bindings/js/JSHTMLAppletElementCustom.cpp b/WebCore/bindings/js/JSHTMLAppletElementCustom.cpp
index 37561af..30892e0 100644
--- a/WebCore/bindings/js/JSHTMLAppletElementCustom.cpp
+++ b/WebCore/bindings/js/JSHTMLAppletElementCustom.cpp
@@ -38,6 +38,11 @@ bool JSHTMLAppletElement::getOwnPropertySlotDelegate(ExecState* exec, const Iden
return runtimeObjectCustomGetOwnPropertySlot(exec, propertyName, slot, this);
}
+bool JSHTMLAppletElement::getOwnPropertyDescriptorDelegate(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+ return runtimeObjectCustomGetOwnPropertyDescriptor(exec, propertyName, descriptor, this);
+}
+
bool JSHTMLAppletElement::putDelegate(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
{
return runtimeObjectCustomPut(exec, propertyName, value, impl(), slot);
diff --git a/WebCore/bindings/js/JSHTMLCanvasElementCustom.cpp b/WebCore/bindings/js/JSHTMLCanvasElementCustom.cpp
new file mode 100644
index 0000000..8ecd287
--- /dev/null
+++ b/WebCore/bindings/js/JSHTMLCanvasElementCustom.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2007 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSHTMLCanvasElement.h"
+
+#include "HTMLCanvasElement.h"
+#include "JSCanvasRenderingContext2D.h"
+#if ENABLE(3D_CANVAS)
+#include "JSCanvasRenderingContext3D.h"
+#endif
+#include <wtf/GetPtr.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+void JSHTMLCanvasElement::markChildren(MarkStack& markStack)
+{
+ Base::markChildren(markStack);
+
+ HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(impl());
+ JSGlobalData& globalData = *Heap::heap(this)->globalData();
+
+ markDOMObjectWrapper(markStack, globalData, canvas->renderingContext());
+}
+
+} // namespace WebCore
diff --git a/WebCore/bindings/js/JSHTMLCollectionCustom.cpp b/WebCore/bindings/js/JSHTMLCollectionCustom.cpp
index dd9af74..8ffddf7 100644
--- a/WebCore/bindings/js/JSHTMLCollectionCustom.cpp
+++ b/WebCore/bindings/js/JSHTMLCollectionCustom.cpp
@@ -23,12 +23,13 @@
#include "AtomicString.h"
#include "HTMLCollection.h"
#include "HTMLOptionsCollection.h"
+#include "JSDOMBinding.h"
#include "JSHTMLAllCollection.h"
#include "JSHTMLOptionsCollection.h"
-#include "JSNamedNodesCollection.h"
#include "JSNode.h"
+#include "JSNodeList.h"
#include "Node.h"
-#include "JSDOMBinding.h"
+#include "StaticNodeList.h"
#include <wtf/Vector.h>
using namespace JSC;
@@ -42,11 +43,13 @@ static JSValue getNamedItems(ExecState* exec, JSHTMLCollection* collection, cons
if (namedItems.isEmpty())
return jsUndefined();
-
if (namedItems.size() == 1)
return toJS(exec, collection->globalObject(), namedItems[0].get());
- return new (exec) JSNamedNodesCollection(exec, collection->globalObject(), namedItems);
+ // FIXME: HTML5 specifies that this should be a DynamicNodeList.
+ // FIXME: HTML5 specifies that non-HTMLOptionsCollection collections should return
+ // the first matching item instead of a NodeList.
+ return toJS(exec, collection->globalObject(), StaticNodeList::adopt(namedItems).get());
}
// HTMLCollections are strange objects, they support both get and call,
diff --git a/WebCore/bindings/js/JSHTMLEmbedElementCustom.cpp b/WebCore/bindings/js/JSHTMLEmbedElementCustom.cpp
index 2570bc6..bce3ffb 100644
--- a/WebCore/bindings/js/JSHTMLEmbedElementCustom.cpp
+++ b/WebCore/bindings/js/JSHTMLEmbedElementCustom.cpp
@@ -38,6 +38,11 @@ bool JSHTMLEmbedElement::getOwnPropertySlotDelegate(ExecState* exec, const Ident
return runtimeObjectCustomGetOwnPropertySlot(exec, propertyName, slot, this);
}
+bool JSHTMLEmbedElement::getOwnPropertyDescriptorDelegate(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+ return runtimeObjectCustomGetOwnPropertyDescriptor(exec, propertyName, descriptor, this);
+}
+
bool JSHTMLEmbedElement::putDelegate(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
{
return runtimeObjectCustomPut(exec, propertyName, value, impl(), slot);
diff --git a/WebCore/bindings/js/JSHTMLFormElementCustom.cpp b/WebCore/bindings/js/JSHTMLFormElementCustom.cpp
index ffa2d57..de9ec4a 100644
--- a/WebCore/bindings/js/JSHTMLFormElementCustom.cpp
+++ b/WebCore/bindings/js/JSHTMLFormElementCustom.cpp
@@ -30,7 +30,8 @@
#include "HTMLCollection.h"
#include "HTMLFormElement.h"
#include "JSDOMWindowCustom.h"
-#include "JSNamedNodesCollection.h"
+#include "JSNodeList.h"
+#include "StaticNodeList.h"
using namespace JSC;
@@ -47,15 +48,17 @@ JSValue JSHTMLFormElement::nameGetter(ExecState* exec, const Identifier& propert
{
JSHTMLElement* jsForm = static_cast<JSHTMLFormElement*>(asObject(slot.slotBase()));
HTMLFormElement* form = static_cast<HTMLFormElement*>(jsForm->impl());
-
+
Vector<RefPtr<Node> > namedItems;
form->getNamedElements(propertyName, namedItems);
+ if (namedItems.isEmpty())
+ return jsUndefined();
if (namedItems.size() == 1)
return toJS(exec, namedItems[0].get());
- if (namedItems.size() > 1)
- return new (exec) JSNamedNodesCollection(exec, jsForm->globalObject(), namedItems);
- return jsUndefined();
+
+ // FIXME: HTML5 specifies that this should be a RadioNodeList.
+ return toJS(exec, jsForm->globalObject(), StaticNodeList::adopt(namedItems).get());
}
JSValue JSHTMLFormElement::submit(ExecState* exec, const ArgList&)
diff --git a/WebCore/bindings/js/JSHTMLFrameElementCustom.cpp b/WebCore/bindings/js/JSHTMLFrameElementCustom.cpp
index c8aea9f..6e01513 100644
--- a/WebCore/bindings/js/JSHTMLFrameElementCustom.cpp
+++ b/WebCore/bindings/js/JSHTMLFrameElementCustom.cpp
@@ -32,16 +32,20 @@
#include "CSSHelper.h"
#include "Document.h"
#include "HTMLFrameElement.h"
+#include "HTMLNames.h"
#include "JSDOMBinding.h"
using namespace JSC;
namespace WebCore {
+using namespace HTMLNames;
+
static inline bool allowSettingJavascriptURL(ExecState* exec, HTMLFrameElement* imp, const String& value)
{
if (protocolIsJavaScript(deprecatedParseURL(value))) {
- if (!checkNodeSecurity(exec, imp->contentDocument()))
+ Document* contentDocument = imp->contentDocument();
+ if (contentDocument && !checkNodeSecurity(exec, contentDocument))
return false;
}
return true;
@@ -55,8 +59,7 @@ void JSHTMLFrameElement::setSrc(ExecState* exec, JSValue value)
if (!allowSettingJavascriptURL(exec, imp, srcValue))
return;
- imp->setSrc(srcValue);
- return;
+ imp->setAttribute(srcAttr, srcValue);
}
void JSHTMLFrameElement::setLocation(ExecState* exec, JSValue value)
@@ -68,7 +71,6 @@ void JSHTMLFrameElement::setLocation(ExecState* exec, JSValue value)
return;
imp->setLocation(locationValue);
- return;
}
} // namespace WebCore
diff --git a/WebCore/bindings/js/JSHTMLIFrameElementCustom.cpp b/WebCore/bindings/js/JSHTMLIFrameElementCustom.cpp
index 8e32381..60ea45e 100644
--- a/WebCore/bindings/js/JSHTMLIFrameElementCustom.cpp
+++ b/WebCore/bindings/js/JSHTMLIFrameElementCustom.cpp
@@ -32,12 +32,15 @@
#include "CSSHelper.h"
#include "Document.h"
#include "HTMLIFrameElement.h"
+#include "HTMLNames.h"
#include "JSDOMBinding.h"
using namespace JSC;
namespace WebCore {
+using namespace HTMLNames;
+
void JSHTMLIFrameElement::setSrc(ExecState* exec, JSValue value)
{
HTMLIFrameElement* imp = static_cast<HTMLIFrameElement*>(impl());
@@ -45,11 +48,12 @@ void JSHTMLIFrameElement::setSrc(ExecState* exec, JSValue value)
String srcValue = valueToStringWithNullCheck(exec, value);
if (protocolIsJavaScript(deprecatedParseURL(srcValue))) {
- if (!checkNodeSecurity(exec, imp->contentDocument()))
+ Document* contentDocument = imp->contentDocument();
+ if (contentDocument && !checkNodeSecurity(exec, contentDocument))
return;
}
- imp->setSrc(srcValue);
+ imp->setAttribute(srcAttr, srcValue);
}
} // namespace WebCore
diff --git a/WebCore/bindings/js/JSHTMLInputElementCustom.cpp b/WebCore/bindings/js/JSHTMLInputElementCustom.cpp
index 6b47622..e5166ee 100644
--- a/WebCore/bindings/js/JSHTMLInputElementCustom.cpp
+++ b/WebCore/bindings/js/JSHTMLInputElementCustom.cpp
@@ -29,6 +29,7 @@
#include "Document.h"
#include "HTMLInputElement.h"
#include "Settings.h"
+#include <runtime/Error.h>
using namespace JSC;
diff --git a/WebCore/bindings/js/JSHTMLObjectElementCustom.cpp b/WebCore/bindings/js/JSHTMLObjectElementCustom.cpp
index a99e46c..1bfb51f 100644
--- a/WebCore/bindings/js/JSHTMLObjectElementCustom.cpp
+++ b/WebCore/bindings/js/JSHTMLObjectElementCustom.cpp
@@ -38,6 +38,11 @@ bool JSHTMLObjectElement::getOwnPropertySlotDelegate(ExecState* exec, const Iden
return runtimeObjectCustomGetOwnPropertySlot(exec, propertyName, slot, this);
}
+bool JSHTMLObjectElement::getOwnPropertyDescriptorDelegate(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+ return runtimeObjectCustomGetOwnPropertyDescriptor(exec, propertyName, descriptor, this);
+}
+
bool JSHTMLObjectElement::putDelegate(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
{
return runtimeObjectCustomPut(exec, propertyName, value, impl(), slot);
diff --git a/WebCore/bindings/js/JSHistoryCustom.cpp b/WebCore/bindings/js/JSHistoryCustom.cpp
index a3b15e1..b24b1ff 100644
--- a/WebCore/bindings/js/JSHistoryCustom.cpp
+++ b/WebCore/bindings/js/JSHistoryCustom.cpp
@@ -31,6 +31,7 @@
#include "Frame.h"
#include "History.h"
+#include <runtime/JSFunction.h>
#include <runtime/PrototypeFunction.h>
using namespace JSC;
@@ -92,6 +93,52 @@ bool JSHistory::getOwnPropertySlotDelegate(ExecState* exec, const Identifier& pr
return true;
}
+bool JSHistory::getOwnPropertyDescriptorDelegate(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+ // When accessing History cross-domain, functions are always the native built-in ones.
+ // See JSDOMWindow::getOwnPropertySlotDelegate for additional details.
+
+ // Our custom code is only needed to implement the Window cross-domain scheme, so if access is
+ // allowed, return false so the normal lookup will take place.
+ String message;
+ if (allowsAccessFromFrame(exec, impl()->frame(), message))
+ return false;
+
+ // Check for the few functions that we allow, even when called cross-domain.
+ const HashEntry* entry = JSHistoryPrototype::s_info.propHashTable(exec)->entry(exec, propertyName);
+ if (entry) {
+ PropertySlot slot;
+ // Allow access to back(), forward() and go() from any frame.
+ if (entry->attributes() & Function) {
+ if (entry->function() == jsHistoryPrototypeFunctionBack) {
+ slot.setCustom(this, nonCachingStaticBackFunctionGetter);
+ descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
+ return true;
+ } else if (entry->function() == jsHistoryPrototypeFunctionForward) {
+ slot.setCustom(this, nonCachingStaticForwardFunctionGetter);
+ descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
+ return true;
+ } else if (entry->function() == jsHistoryPrototypeFunctionGo) {
+ slot.setCustom(this, nonCachingStaticGoFunctionGetter);
+ descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
+ return true;
+ }
+ }
+ } else {
+ // Allow access to toString() cross-domain, but always Object.toString.
+ if (propertyName == exec->propertyNames().toString) {
+ PropertySlot slot;
+ slot.setCustom(this, objectToStringFunctionGetter);
+ descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
+ return true;
+ }
+ }
+
+ printErrorMessageForFrame(impl()->frame(), message);
+ descriptor.setUndefined();
+ return true;
+}
+
bool JSHistory::putDelegate(ExecState* exec, const Identifier&, JSValue, PutPropertySlot&)
{
// Only allow putting by frames in the same origin.
@@ -108,12 +155,12 @@ bool JSHistory::deleteProperty(ExecState* exec, const Identifier& propertyName)
return Base::deleteProperty(exec, propertyName);
}
-void JSHistory::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
+void JSHistory::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
{
// Only allow the history object to enumerated by frames in the same origin.
if (!allowsAccessFromFrame(exec, impl()->frame()))
return;
- Base::getPropertyNames(exec, propertyNames);
+ Base::getOwnPropertyNames(exec, propertyNames);
}
} // namespace WebCore
diff --git a/WebCore/bindings/js/JSImageConstructor.cpp b/WebCore/bindings/js/JSImageConstructor.cpp
index faaaf41..0f4a991 100644
--- a/WebCore/bindings/js/JSImageConstructor.cpp
+++ b/WebCore/bindings/js/JSImageConstructor.cpp
@@ -25,6 +25,7 @@
#include "JSHTMLImageElement.h"
#include "JSNode.h"
#include "ScriptExecutionContext.h"
+#include <runtime/Error.h>
using namespace JSC;
diff --git a/WebCore/bindings/js/JSInspectedObjectWrapper.cpp b/WebCore/bindings/js/JSInspectedObjectWrapper.cpp
index fff7aee..ed79427 100644
--- a/WebCore/bindings/js/JSInspectedObjectWrapper.cpp
+++ b/WebCore/bindings/js/JSInspectedObjectWrapper.cpp
@@ -26,6 +26,8 @@
#include "config.h"
#include "JSInspectedObjectWrapper.h"
+#if ENABLE(INSPECTOR)
+
#include "JSInspectorCallbackWrapper.h"
#include <runtime/JSGlobalObject.h>
#include <wtf/StdLibExtras.h>
@@ -69,7 +71,7 @@ JSValue JSInspectedObjectWrapper::wrap(ExecState* unwrappedExec, JSValue unwrapp
return new (unwrappedExec) JSInspectedObjectWrapper(unwrappedExec, unwrappedObject, JSQuarantinedObjectWrapper::createStructure(asObject(wrap(unwrappedExec, prototype))));
}
-JSInspectedObjectWrapper::JSInspectedObjectWrapper(ExecState* unwrappedExec, JSObject* unwrappedObject, PassRefPtr<Structure> structure)
+JSInspectedObjectWrapper::JSInspectedObjectWrapper(ExecState* unwrappedExec, JSObject* unwrappedObject, NonNullPassRefPtr<Structure> structure)
: JSQuarantinedObjectWrapper(unwrappedExec, unwrappedObject, structure)
{
WrapperMap* wrapperMap = wrappers().get(unwrappedGlobalObject());
@@ -125,3 +127,5 @@ JSValue JSInspectedObjectWrapper::prepareIncomingValue(ExecState*, JSValue value
}
} // namespace WebCore
+
+#endif // ENABLE(INSPECTOR)
diff --git a/WebCore/bindings/js/JSInspectedObjectWrapper.h b/WebCore/bindings/js/JSInspectedObjectWrapper.h
index 201feb6..ad97035 100644
--- a/WebCore/bindings/js/JSInspectedObjectWrapper.h
+++ b/WebCore/bindings/js/JSInspectedObjectWrapper.h
@@ -38,7 +38,7 @@ namespace WebCore {
static const JSC::ClassInfo s_info;
private:
- JSInspectedObjectWrapper(JSC::ExecState* unwrappedExec, JSC::JSObject* unwrappedObject, PassRefPtr<JSC::Structure>);
+ JSInspectedObjectWrapper(JSC::ExecState* unwrappedExec, JSC::JSObject* unwrappedObject, NonNullPassRefPtr<JSC::Structure>);
virtual bool allowsGetProperty() const { return true; }
virtual bool allowsSetProperty() const { return true; }
diff --git a/WebCore/bindings/js/JSInspectorBackendCustom.cpp b/WebCore/bindings/js/JSInspectorBackendCustom.cpp
index b2eb2d1..73fa268 100644
--- a/WebCore/bindings/js/JSInspectorBackendCustom.cpp
+++ b/WebCore/bindings/js/JSInspectorBackendCustom.cpp
@@ -33,6 +33,8 @@
#include "config.h"
#include "JSInspectorBackend.h"
+#if ENABLE(INSPECTOR)
+
#include "Console.h"
#if ENABLE(DATABASE)
#include "Database.h"
@@ -51,6 +53,10 @@
#include "JSRange.h"
#include "Node.h"
#include "Page.h"
+#if ENABLE(DOM_STORAGE)
+#include "Storage.h"
+#include "JSStorage.h"
+#endif
#include "TextIterator.h"
#include "VisiblePosition.h"
#include <runtime/JSArray.h>
@@ -70,21 +76,12 @@ using namespace JSC;
namespace WebCore {
-JSValue JSInspectorBackend::highlightDOMNode(JSC::ExecState*, const JSC::ArgList& args)
+JSValue JSInspectorBackend::highlightDOMNode(JSC::ExecState* exec, const JSC::ArgList& args)
{
if (args.size() < 1)
return jsUndefined();
- JSQuarantinedObjectWrapper* wrapper = JSQuarantinedObjectWrapper::asWrapper(args.at(0));
- if (!wrapper)
- return jsUndefined();
-
- Node* node = toNode(wrapper->unwrappedObject());
- if (!node)
- return jsUndefined();
-
- impl()->highlight(node);
-
+ impl()->highlight(args.at(0).toInt32(exec));
return jsUndefined();
}
@@ -125,27 +122,20 @@ JSValue JSInspectorBackend::search(ExecState* exec, const ArgList& args)
}
#if ENABLE(DATABASE)
-JSValue JSInspectorBackend::databaseTableNames(ExecState* exec, const ArgList& args)
+JSValue JSInspectorBackend::databaseForId(ExecState* exec, const ArgList& args)
{
if (args.size() < 1)
return jsUndefined();
- JSQuarantinedObjectWrapper* wrapper = JSQuarantinedObjectWrapper::asWrapper(args.at(0));
- if (!wrapper)
+ InspectorController* ic = impl()->inspectorController();
+ if (!ic)
return jsUndefined();
- Database* database = toDatabase(wrapper->unwrappedObject());
+ Database* database = impl()->databaseForId(args.at(0).toInt32(exec));
if (!database)
return jsUndefined();
-
- MarkedArgumentBuffer result;
-
- Vector<String> tableNames = database->tableNames();
- unsigned length = tableNames.size();
- for (unsigned i = 0; i < length; ++i)
- result.append(jsString(exec, tableNames[i]));
-
- return constructArray(exec, result);
+ JSDOMWindow* inspectedWindow = toJSDOMWindow(ic->inspectedPage()->mainFrame());
+ return JSInspectedObjectWrapper::wrap(inspectedWindow->globalExec(), toJS(exec, database));
}
#endif
@@ -257,7 +247,7 @@ JSValue JSInspectorBackend::currentCallFrame(ExecState* exec, const ArgList&)
return jsUndefined();
// FIXME: I am not sure if this is actually needed. Can we just use exec?
- ExecState* globalExec = callFrame->scopeChain()->globalObject()->globalExec();
+ ExecState* globalExec = callFrame->scopeChain()->globalObject->globalExec();
JSLock lock(SilenceAssertionsOnly);
return JSInspectedObjectWrapper::wrap(globalExec, toJS(exec, callFrame));
@@ -280,4 +270,94 @@ JSValue JSInspectorBackend::profiles(JSC::ExecState* exec, const JSC::ArgList&)
#endif
+JSValue JSInspectorBackend::nodeForId(ExecState* exec, const ArgList& args)
+{
+ if (args.size() < 1)
+ return jsUndefined();
+
+ Node* node = impl()->nodeForId(args.at(0).toInt32(exec));
+ if (!node)
+ return jsUndefined();
+
+ InspectorController* ic = impl()->inspectorController();
+ if (!ic)
+ return jsUndefined();
+
+ JSLock lock(SilenceAssertionsOnly);
+ JSDOMWindow* inspectedWindow = toJSDOMWindow(ic->inspectedPage()->mainFrame());
+ return JSInspectedObjectWrapper::wrap(inspectedWindow->globalExec(), toJS(exec, deprecatedGlobalObjectForPrototype(inspectedWindow->globalExec()), node));
+}
+
+JSValue JSInspectorBackend::wrapObject(ExecState* exec, const ArgList& args)
+{
+ if (args.size() < 2)
+ return jsUndefined();
+
+ return impl()->wrapObject(ScriptValue(args.at(0)), args.at(1).toString(exec)).jsValue();
+}
+
+JSValue JSInspectorBackend::unwrapObject(ExecState* exec, const ArgList& args)
+{
+ if (args.size() < 1)
+ return jsUndefined();
+
+ return impl()->unwrapObject(args.at(0).toString(exec)).jsValue();
+}
+
+JSValue JSInspectorBackend::pushNodePathToFrontend(ExecState* exec, const ArgList& args)
+{
+ if (args.size() < 2)
+ return jsUndefined();
+
+ JSQuarantinedObjectWrapper* wrapper = JSQuarantinedObjectWrapper::asWrapper(args.at(0));
+ if (!wrapper)
+ return jsUndefined();
+
+ Node* node = toNode(wrapper->unwrappedObject());
+ if (!node)
+ return jsUndefined();
+
+ bool selectInUI = args.at(1).toBoolean(exec);
+ return jsNumber(exec, impl()->pushNodePathToFrontend(node, selectInUI));
+}
+
+#if ENABLE(DATABASE)
+JSValue JSInspectorBackend::selectDatabase(ExecState*, const ArgList& args)
+{
+ if (args.size() < 1)
+ return jsUndefined();
+
+ JSQuarantinedObjectWrapper* wrapper = JSQuarantinedObjectWrapper::asWrapper(args.at(0));
+ if (!wrapper)
+ return jsUndefined();
+
+ Database* database = toDatabase(wrapper->unwrappedObject());
+ if (database)
+ impl()->selectDatabase(database);
+ return jsUndefined();
+}
+#endif
+
+#if ENABLE(DOM_STORAGE)
+JSValue JSInspectorBackend::selectDOMStorage(ExecState*, const ArgList& args)
+{
+ if (args.size() < 1)
+ return jsUndefined();
+ InspectorController* ic = impl()->inspectorController();
+ if (!ic)
+ return jsUndefined();
+
+ JSQuarantinedObjectWrapper* wrapper = JSQuarantinedObjectWrapper::asWrapper(args.at(0));
+ if (!wrapper)
+ return jsUndefined();
+
+ Storage* storage = toStorage(wrapper->unwrappedObject());
+ if (storage)
+ impl()->selectDOMStorage(storage);
+ return jsUndefined();
+}
+#endif
+
} // namespace WebCore
+
+#endif // ENABLE(INSPECTOR)
diff --git a/WebCore/bindings/js/JSInspectorCallbackWrapper.cpp b/WebCore/bindings/js/JSInspectorCallbackWrapper.cpp
index 0e14109..9c4330d 100644
--- a/WebCore/bindings/js/JSInspectorCallbackWrapper.cpp
+++ b/WebCore/bindings/js/JSInspectorCallbackWrapper.cpp
@@ -26,6 +26,8 @@
#include "config.h"
#include "JSInspectorCallbackWrapper.h"
+#if ENABLE(INSPECTOR)
+
#include "JSInspectedObjectWrapper.h"
#include <wtf/StdLibExtras.h>
@@ -73,10 +75,10 @@ JSValue JSInspectorCallbackWrapper::wrap(ExecState* unwrappedExec, JSValue unwra
static Structure* structure = leakInspectorCallbackWrapperStructure();
return new (unwrappedExec) JSInspectorCallbackWrapper(unwrappedExec, unwrappedObject, structure);
}
- return new (unwrappedExec) JSInspectorCallbackWrapper(unwrappedExec, unwrappedObject, asObject(wrap(unwrappedExec, prototype))->inheritorID());
+ return new (unwrappedExec) JSInspectorCallbackWrapper(unwrappedExec, unwrappedObject, createStructure(wrap(unwrappedExec, prototype)));
}
-JSInspectorCallbackWrapper::JSInspectorCallbackWrapper(ExecState* unwrappedExec, JSObject* unwrappedObject, PassRefPtr<Structure> structure)
+JSInspectorCallbackWrapper::JSInspectorCallbackWrapper(ExecState* unwrappedExec, JSObject* unwrappedObject, NonNullPassRefPtr<Structure> structure)
: JSQuarantinedObjectWrapper(unwrappedExec, unwrappedObject, structure)
{
ASSERT(!wrappers().contains(unwrappedObject));
@@ -105,3 +107,5 @@ JSValue JSInspectorCallbackWrapper::prepareIncomingValue(ExecState* unwrappedExe
}
} // namespace WebCore
+
+#endif // ENABLE(INSPECTOR)
diff --git a/WebCore/bindings/js/JSInspectorCallbackWrapper.h b/WebCore/bindings/js/JSInspectorCallbackWrapper.h
index cfc2fb6..be28063 100644
--- a/WebCore/bindings/js/JSInspectorCallbackWrapper.h
+++ b/WebCore/bindings/js/JSInspectorCallbackWrapper.h
@@ -40,7 +40,7 @@ namespace WebCore {
static const JSC::ClassInfo s_info;
protected:
- JSInspectorCallbackWrapper(JSC::ExecState* unwrappedExec, JSC::JSObject* unwrappedObject, PassRefPtr<JSC::Structure>);
+ JSInspectorCallbackWrapper(JSC::ExecState* unwrappedExec, JSC::JSObject* unwrappedObject, NonNullPassRefPtr<JSC::Structure>);
virtual bool allowsCallAsFunction() const { return true; }
diff --git a/WebCore/bindings/js/JSLazyEventListener.cpp b/WebCore/bindings/js/JSLazyEventListener.cpp
index 7caff2b..0d6cb57 100644
--- a/WebCore/bindings/js/JSLazyEventListener.cpp
+++ b/WebCore/bindings/js/JSLazyEventListener.cpp
@@ -23,6 +23,7 @@
#include "Frame.h"
#include "JSNode.h"
#include <runtime/FunctionConstructor.h>
+#include <runtime/JSFunction.h>
#include <runtime/JSLock.h>
#include <wtf/RefCountedLeakCounter.h>
@@ -34,12 +35,13 @@ namespace WebCore {
static WTF::RefCountedLeakCounter eventListenerCounter("JSLazyEventListener");
#endif
-JSLazyEventListener::JSLazyEventListener(const String& functionName, const String& eventParameterName, const String& code, JSDOMGlobalObject* globalObject, Node* node, int lineNumber)
- : JSEventListener(0, globalObject, true)
+JSLazyEventListener::JSLazyEventListener(const String& functionName, const String& eventParameterName, const String& code, Node* node, const String& sourceURL, int lineNumber)
+ : JSEventListener(0, true)
, m_functionName(functionName)
, m_eventParameterName(eventParameterName)
, m_code(code)
, m_parsed(false)
+ , m_sourceURL(sourceURL)
, m_lineNumber(lineNumber)
, m_originalNode(node)
{
@@ -66,23 +68,43 @@ JSLazyEventListener::~JSLazyEventListener()
#endif
}
-JSObject* JSLazyEventListener::jsFunction() const
+JSObject* JSLazyEventListener::jsFunction(ScriptExecutionContext* executionContext) const
{
- parseCode();
+ parseCode(executionContext);
return m_jsFunction;
}
-void JSLazyEventListener::parseCode() const
+void JSLazyEventListener::parseCode(ScriptExecutionContext* executionContext) const
{
+ ASSERT(executionContext);
+ ASSERT(executionContext->isDocument());
+ if (!executionContext)
+ return;
+
if (m_parsed)
return;
- ScriptExecutionContext* executionContext = m_globalObject->scriptExecutionContext();
- ASSERT(executionContext);
- if (!executionContext)
+ Frame* frame = static_cast<Document*>(executionContext)->frame();
+ if (!frame)
return;
+
+ ScriptController* scriptController = frame->script();
+ if (!scriptController->isEnabled())
+ return;
+
+ JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(executionContext);
+ if (!globalObject)
+ return;
+
+ // Ensure that 'node' has a JavaScript wrapper to mark the event listener we're creating.
+ if (m_originalNode) {
+ JSLock lock(SilenceAssertionsOnly);
+ // FIXME: Should pass the global object associated with the node
+ toJS(globalObject->globalExec(), globalObject, m_originalNode);
+ }
+
if (executionContext->isDocument()) {
- JSDOMWindow* window = static_cast<JSDOMWindow*>(m_globalObject);
+ JSDOMWindow* window = static_cast<JSDOMWindow*>(globalObject);
Frame* frame = window->impl()->frame();
if (!frame)
return;
@@ -94,16 +116,13 @@ void JSLazyEventListener::parseCode() const
m_parsed = true;
- ExecState* exec = m_globalObject->globalExec();
+ ExecState* exec = globalObject->globalExec();
MarkedArgumentBuffer args;
- UString sourceURL(executionContext->url().string());
args.append(jsNontrivialString(exec, m_eventParameterName));
args.append(jsString(exec, m_code));
- // FIXME: Passing the document's URL to construct is not always correct, since this event listener might
- // have been added with setAttribute from a script, and we should pass String() in that case.
- m_jsFunction = constructFunction(exec, args, Identifier(exec, m_functionName), sourceURL, m_lineNumber); // FIXME: is globalExec ok?
+ m_jsFunction = constructFunction(exec, args, Identifier(exec, m_functionName), m_sourceURL, m_lineNumber); // FIXME: is globalExec ok?
JSFunction* listenerAsFunction = static_cast<JSFunction*>(m_jsFunction);
@@ -117,7 +136,7 @@ void JSLazyEventListener::parseCode() const
// (and the document, and the form - see JSHTMLElement::eventHandlerScope)
ScopeChain scope = listenerAsFunction->scope();
- JSValue thisObj = toJS(exec, m_globalObject, m_originalNode);
+ JSValue thisObj = toJS(exec, globalObject, m_originalNode);
if (thisObj.isObject()) {
static_cast<JSNode*>(asObject(thisObj))->pushEventHandlerScope(exec, scope);
listenerAsFunction->setScope(scope);
@@ -128,6 +147,7 @@ void JSLazyEventListener::parseCode() const
m_functionName = String();
m_code = String();
m_eventParameterName = String();
+ m_sourceURL = String();
}
} // namespace WebCore
diff --git a/WebCore/bindings/js/JSLazyEventListener.h b/WebCore/bindings/js/JSLazyEventListener.h
index a5304cf..e3137b8 100644
--- a/WebCore/bindings/js/JSLazyEventListener.h
+++ b/WebCore/bindings/js/JSLazyEventListener.h
@@ -29,24 +29,25 @@ namespace WebCore {
class JSLazyEventListener : public JSEventListener {
public:
- static PassRefPtr<JSLazyEventListener> create(const String& functionName, const String& eventParameterName, const String& code, JSDOMGlobalObject* globalObject, Node* node, int lineNumber)
+ static PassRefPtr<JSLazyEventListener> create(const String& functionName, const String& eventParameterName, const String& code, Node* node, const String& sourceURL, int lineNumber)
{
- return adoptRef(new JSLazyEventListener(functionName, eventParameterName, code, globalObject, node, lineNumber));
+ return adoptRef(new JSLazyEventListener(functionName, eventParameterName, code, node, sourceURL, lineNumber));
}
virtual ~JSLazyEventListener();
private:
- JSLazyEventListener(const String& functionName, const String& eventParameterName, const String& code, JSDOMGlobalObject*, Node*, int lineNumber);
+ JSLazyEventListener(const String& functionName, const String& eventParameterName, const String& code, Node*, const String& sourceURL, int lineNumber);
- virtual JSC::JSObject* jsFunction() const;
+ virtual JSC::JSObject* jsFunction(ScriptExecutionContext*) const;
virtual bool wasCreatedFromMarkup() const { return true; }
- void parseCode() const;
+ void parseCode(ScriptExecutionContext*) const;
mutable String m_functionName;
mutable String m_eventParameterName;
mutable String m_code;
mutable bool m_parsed;
+ mutable String m_sourceURL;
int m_lineNumber;
Node* m_originalNode;
};
diff --git a/WebCore/bindings/js/JSLocationCustom.cpp b/WebCore/bindings/js/JSLocationCustom.cpp
index d7d32f4..c76a2b1 100644
--- a/WebCore/bindings/js/JSLocationCustom.cpp
+++ b/WebCore/bindings/js/JSLocationCustom.cpp
@@ -31,6 +31,7 @@
#include "KURL.h"
#include "Location.h"
#include "ScriptController.h"
+#include <runtime/JSFunction.h>
#include <runtime/PrototypeFunction.h>
using namespace JSC;
@@ -93,6 +94,51 @@ bool JSLocation::getOwnPropertySlotDelegate(ExecState* exec, const Identifier& p
return true;
}
+bool JSLocation::getOwnPropertyDescriptorDelegate(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+ Frame* frame = impl()->frame();
+ if (!frame) {
+ descriptor.setUndefined();
+ return true;
+ }
+
+ // When accessing Location cross-domain, functions are always the native built-in ones.
+ // See JSDOMWindow::getOwnPropertySlotDelegate for additional details.
+
+ // Our custom code is only needed to implement the Window cross-domain scheme, so if access is
+ // allowed, return false so the normal lookup will take place.
+ String message;
+ if (allowsAccessFromFrame(exec, frame, message))
+ return false;
+
+ // Check for the few functions that we allow, even when called cross-domain.
+ const HashEntry* entry = JSLocationPrototype::s_info.propHashTable(exec)->entry(exec, propertyName);
+ PropertySlot slot;
+ if (entry && (entry->attributes() & Function)) {
+ if (entry->function() == jsLocationPrototypeFunctionReplace) {
+ slot.setCustom(this, nonCachingStaticReplaceFunctionGetter);
+ descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
+ return true;
+ } else if (entry->function() == jsLocationPrototypeFunctionReload) {
+ slot.setCustom(this, nonCachingStaticReloadFunctionGetter);
+ descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
+ return true;
+ } else if (entry->function() == jsLocationPrototypeFunctionAssign) {
+ slot.setCustom(this, nonCachingStaticAssignFunctionGetter);
+ descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
+ return true;
+ }
+ }
+
+ // FIXME: Other implementers of the Window cross-domain scheme (Window, History) allow toString,
+ // but for now we have decided not to, partly because it seems silly to return "[Object Location]" in
+ // such cases when normally the string form of Location would be the URL.
+
+ printErrorMessageForFrame(frame, message);
+ descriptor.setUndefined();
+ return true;
+}
+
bool JSLocation::putDelegate(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
{
Frame* frame = impl()->frame();
@@ -128,19 +174,19 @@ bool JSLocation::deleteProperty(ExecState* exec, const Identifier& propertyName)
return Base::deleteProperty(exec, propertyName);
}
-void JSLocation::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
+void JSLocation::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
{
// Only allow the location object to enumerated by frames in the same origin.
if (!allowsAccessFromFrame(exec, impl()->frame()))
return;
- Base::getPropertyNames(exec, propertyNames);
+ Base::getOwnPropertyNames(exec, propertyNames);
}
-void JSLocation::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction)
+void JSLocation::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes)
{
if (propertyName == exec->propertyNames().toString || propertyName == exec->propertyNames().valueOf)
return;
- Base::defineGetter(exec, propertyName, getterFunction);
+ Base::defineGetter(exec, propertyName, getterFunction, attributes);
}
static void navigateIfAllowed(ExecState* exec, Frame* frame, const KURL& url, bool lockHistory, bool lockBackForwardList)
@@ -150,7 +196,7 @@ static void navigateIfAllowed(ExecState* exec, Frame* frame, const KURL& url, bo
return;
if (!protocolIsJavaScript(url) || allowsAccessFromFrame(exec, frame))
- frame->loader()->scheduleLocationChange(url.string(), lexicalFrame->loader()->outgoingReferrer(), lockHistory, lockBackForwardList, processingUserGesture(exec));
+ frame->redirectScheduler()->scheduleLocationChange(url.string(), lexicalFrame->loader()->outgoingReferrer(), lockHistory, lockBackForwardList, processingUserGesture(exec));
}
void JSLocation::setHref(ExecState* exec, JSValue value)
@@ -158,13 +204,13 @@ void JSLocation::setHref(ExecState* exec, JSValue value)
Frame* frame = impl()->frame();
ASSERT(frame);
- if (!shouldAllowNavigation(exec, frame))
- return;
-
KURL url = completeURL(exec, value.toString(exec));
if (url.isNull())
return;
+ if (!shouldAllowNavigation(exec, frame))
+ return;
+
navigateIfAllowed(exec, frame, url, !frame->script()->anyPageIsProcessingUserGesture(), false);
}
@@ -262,13 +308,13 @@ JSValue JSLocation::replace(ExecState* exec, const ArgList& args)
if (!frame)
return jsUndefined();
- if (!shouldAllowNavigation(exec, frame))
- return jsUndefined();
-
KURL url = completeURL(exec, args.at(0).toString(exec));
if (url.isNull())
return jsUndefined();
+ if (!shouldAllowNavigation(exec, frame))
+ return jsUndefined();
+
navigateIfAllowed(exec, frame, url, true, true);
return jsUndefined();
}
@@ -280,7 +326,7 @@ JSValue JSLocation::reload(ExecState* exec, const ArgList&)
return jsUndefined();
if (!protocolIsJavaScript(frame->loader()->url()))
- frame->loader()->scheduleRefresh(processingUserGesture(exec));
+ frame->redirectScheduler()->scheduleRefresh(processingUserGesture(exec));
return jsUndefined();
}
@@ -290,13 +336,13 @@ JSValue JSLocation::assign(ExecState* exec, const ArgList& args)
if (!frame)
return jsUndefined();
- if (!shouldAllowNavigation(exec, frame))
- return jsUndefined();
-
KURL url = completeURL(exec, args.at(0).toString(exec));
if (url.isNull())
return jsUndefined();
+ if (!shouldAllowNavigation(exec, frame))
+ return jsUndefined();
+
// We want a new history item if this JS was called via a user gesture
navigateIfAllowed(exec, frame, url, !frame->script()->anyPageIsProcessingUserGesture(), false);
return jsUndefined();
@@ -316,11 +362,11 @@ bool JSLocationPrototype::putDelegate(ExecState* exec, const Identifier& propert
return (propertyName == exec->propertyNames().toString || propertyName == exec->propertyNames().valueOf);
}
-void JSLocationPrototype::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction)
+void JSLocationPrototype::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes)
{
if (propertyName == exec->propertyNames().toString || propertyName == exec->propertyNames().valueOf)
return;
- Base::defineGetter(exec, propertyName, getterFunction);
+ Base::defineGetter(exec, propertyName, getterFunction, attributes);
}
} // namespace WebCore
diff --git a/WebCore/bindings/js/JSMessageChannelConstructor.cpp b/WebCore/bindings/js/JSMessageChannelConstructor.cpp
index 25a5cb2..9721ba3 100644
--- a/WebCore/bindings/js/JSMessageChannelConstructor.cpp
+++ b/WebCore/bindings/js/JSMessageChannelConstructor.cpp
@@ -30,6 +30,7 @@
#include "JSDocument.h"
#include "JSMessageChannel.h"
#include "MessageChannel.h"
+#include <runtime/Error.h>
using namespace JSC;
diff --git a/WebCore/bindings/js/JSMessageEventCustom.cpp b/WebCore/bindings/js/JSMessageEventCustom.cpp
new file mode 100644
index 0000000..2e7b2d0
--- /dev/null
+++ b/WebCore/bindings/js/JSMessageEventCustom.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSMessageEvent.h"
+
+#include "JSDOMBinding.h"
+#include "JSDOMWindow.h"
+#include "JSEventTarget.h"
+#include "JSMessagePortCustom.h"
+#include "MessageEvent.h"
+#include <runtime/JSArray.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+JSValue JSMessageEvent::ports(ExecState* exec) const
+{
+ MessagePortArray* ports = static_cast<MessageEvent*>(impl())->ports();
+ if (!ports || ports->isEmpty())
+ return jsNull();
+
+ MarkedArgumentBuffer list;
+ for (size_t i = 0; i < ports->size(); i++)
+ list.append(toJS(exec, globalObject(), (*ports)[i].get()));
+ return constructArray(exec, list);
+}
+
+JSC::JSValue JSMessageEvent::initMessageEvent(JSC::ExecState* exec, const JSC::ArgList& args)
+{
+ const UString& typeArg = args.at(0).toString(exec);
+ bool canBubbleArg = args.at(1).toBoolean(exec);
+ bool cancelableArg = args.at(2).toBoolean(exec);
+ PassRefPtr<SerializedScriptValue> dataArg = SerializedScriptValue::create(exec, args.at(3));
+ const UString& originArg = args.at(4).toString(exec);
+ const UString& lastEventIdArg = args.at(5).toString(exec);
+ DOMWindow* sourceArg = toDOMWindow(args.at(6));
+ OwnPtr<MessagePortArray> messagePorts;
+ if (!args.at(7).isUndefinedOrNull()) {
+ messagePorts = new MessagePortArray();
+ fillMessagePortArray(exec, args.at(7), *messagePorts);
+ if (exec->hadException())
+ return jsUndefined();
+ }
+
+ MessageEvent* event = static_cast<MessageEvent*>(this->impl());
+ event->initMessageEvent(typeArg, canBubbleArg, cancelableArg, dataArg, originArg, lastEventIdArg, sourceArg, messagePorts.release());
+ return jsUndefined();
+}
+
+} // namespace WebCore
diff --git a/WebCore/bindings/js/JSMessagePortCustom.cpp b/WebCore/bindings/js/JSMessagePortCustom.cpp
index c3316c5..210c93e 100644
--- a/WebCore/bindings/js/JSMessagePortCustom.cpp
+++ b/WebCore/bindings/js/JSMessagePortCustom.cpp
@@ -28,11 +28,14 @@
#include "AtomicString.h"
#include "Event.h"
+#include "ExceptionCode.h"
#include "Frame.h"
#include "JSDOMGlobalObject.h"
#include "JSEvent.h"
#include "JSEventListener.h"
+#include "JSMessagePortCustom.h"
#include "MessagePort.h"
+#include <runtime/Error.h>
using namespace JSC;
@@ -42,8 +45,6 @@ void JSMessagePort::markChildren(MarkStack& markStack)
{
Base::markChildren(markStack);
- markIfNotNull(markStack, m_impl->onmessage());
-
// If we have a locally entangled port, we can directly mark it as reachable. Ports that are remotely entangled are marked in-use by markActiveObjectsForContext().
if (MessagePort* entangledPort = m_impl->locallyEntangledPort()) {
DOMObject* wrapper = getCachedDOMObjectWrapper(*Heap::heap(this)->globalData(), entangledPort);
@@ -51,13 +52,7 @@ void JSMessagePort::markChildren(MarkStack& markStack)
markStack.append(wrapper);
}
- typedef MessagePort::EventListenersMap EventListenersMap;
- typedef MessagePort::ListenerVector ListenerVector;
- EventListenersMap& eventListeners = m_impl->eventListeners();
- for (EventListenersMap::iterator mapIter = eventListeners.begin(); mapIter != eventListeners.end(); ++mapIter) {
- for (ListenerVector::iterator vecIter = mapIter->second.begin(); vecIter != mapIter->second.end(); ++vecIter)
- (*vecIter)->markJSFunction(markStack);
- }
+ m_impl->markEventListeners(markStack);
}
JSValue JSMessagePort::addEventListener(ExecState* exec, const ArgList& args)
@@ -65,10 +60,12 @@ JSValue JSMessagePort::addEventListener(ExecState* exec, const ArgList& args)
JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->scriptExecutionContext());
if (!globalObject)
return jsUndefined();
- RefPtr<JSEventListener> listener = globalObject->findOrCreateJSEventListener(args.at(1));
- if (!listener)
+
+ JSValue listener = args.at(1);
+ if (!listener.isObject())
return jsUndefined();
- impl()->addEventListener(args.at(0).toString(exec), listener.release(), args.at(2).toBoolean(exec));
+
+ impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false).get(), args.at(2).toBoolean(exec));
return jsUndefined();
}
@@ -77,11 +74,54 @@ JSValue JSMessagePort::removeEventListener(ExecState* exec, const ArgList& args)
JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->scriptExecutionContext());
if (!globalObject)
return jsUndefined();
- JSEventListener* listener = globalObject->findJSEventListener(args.at(1));
- if (!listener)
+
+ JSValue listener = args.at(1);
+ if (!listener.isObject())
return jsUndefined();
- impl()->removeEventListener(args.at(0).toString(exec), listener, args.at(2).toBoolean(exec));
+
+ impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false).get(), args.at(2).toBoolean(exec));
return jsUndefined();
}
+JSC::JSValue JSMessagePort::postMessage(JSC::ExecState* exec, const JSC::ArgList& args)
+{
+ return handlePostMessage(exec, args, impl());
+}
+
+void fillMessagePortArray(JSC::ExecState* exec, JSC::JSValue value, MessagePortArray& portArray)
+{
+ // Convert from the passed-in JS array-like object to a MessagePortArray.
+ // Also validates the elements per sections 4.1.13 and 4.1.15 of the WebIDL spec and section 8.3.3 of the HTML5 spec.
+ if (value.isUndefinedOrNull()) {
+ portArray.resize(0);
+ return;
+ }
+
+ // Validation of sequence types, per WebIDL spec 4.1.13.
+ unsigned length;
+ JSObject* object = toJSSequence(exec, value, length);
+ if (exec->hadException())
+ return;
+
+ portArray.resize(length);
+ for (unsigned i = 0 ; i < length; ++i) {
+ JSValue value = object->get(exec, i);
+ if (exec->hadException())
+ return;
+ // Validation of non-null objects, per HTML5 spec 8.3.3.
+ if (value.isUndefinedOrNull()) {
+ setDOMException(exec, INVALID_STATE_ERR);
+ return;
+ }
+
+ // Validation of Objects implementing an interface, per WebIDL spec 4.1.15.
+ RefPtr<MessagePort> port = toMessagePort(value);
+ if (!port) {
+ throwError(exec, TypeError);
+ return;
+ }
+ portArray[i] = port.release();
+ }
+}
+
} // namespace WebCore
diff --git a/WebCore/bindings/js/JSMessagePortCustom.h b/WebCore/bindings/js/JSMessagePortCustom.h
new file mode 100644
index 0000000..17b1eae
--- /dev/null
+++ b/WebCore/bindings/js/JSMessagePortCustom.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JSMessagePortCustom_h
+#define JSMessagePortCustom_h
+
+#include "MessagePort.h"
+#include <runtime/JSValue.h>
+
+namespace WebCore {
+
+ typedef int ExceptionCode;
+
+ class String;
+
+ // Helper function which pulls the values out of a JS sequence and into a MessagePortArray.
+ // Also validates the elements per sections 4.1.13 and 4.1.15 of the WebIDL spec and section 8.3.3 of the HTML5 spec.
+ // May generate an exception via the passed ExecState.
+ void fillMessagePortArray(JSC::ExecState*, JSC::JSValue, MessagePortArray&);
+
+ // Helper function to convert from JS postMessage arguments to WebCore postMessage arguments.
+ template <typename T>
+ inline JSC::JSValue handlePostMessage(JSC::ExecState* exec, const JSC::ArgList& args, T* impl)
+ {
+ PassRefPtr<SerializedScriptValue> message = SerializedScriptValue::create(exec, args.at(0));
+ MessagePortArray portArray;
+ fillMessagePortArray(exec, args.at(1), portArray);
+ if (exec->hadException())
+ return JSC::jsUndefined();
+
+ ExceptionCode ec = 0;
+ impl->postMessage(message, &portArray, ec);
+ setDOMException(exec, ec);
+ return JSC::jsUndefined();
+ }
+
+}
+#endif // JSMessagePortCustom_h
diff --git a/WebCore/bindings/js/JSNamedNodeMapCustom.cpp b/WebCore/bindings/js/JSNamedNodeMapCustom.cpp
index 7bd95b4..1974ab0 100644
--- a/WebCore/bindings/js/JSNamedNodeMapCustom.cpp
+++ b/WebCore/bindings/js/JSNamedNodeMapCustom.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -27,10 +27,9 @@
#include "JSNamedNodeMap.h"
#include "JSNode.h"
+
+#include "Element.h"
#include "NamedNodeMap.h"
-#include "Node.h"
-#include "PlatformString.h"
-#include "JSDOMBinding.h"
using namespace JSC;
@@ -47,4 +46,16 @@ JSValue JSNamedNodeMap::nameGetter(ExecState* exec, const Identifier& propertyNa
return toJS(exec, thisObj->impl()->getNamedItem(propertyName));
}
+void JSNamedNodeMap::markChildren(MarkStack& markStack)
+{
+ Base::markChildren(markStack);
+
+ // Mark the element so that this will work to access the attribute even if the last
+ // other reference goes away.
+ if (Element* element = impl()->element()) {
+ if (JSNode* wrapper = getCachedDOMNodeWrapper(element->document(), element))
+ markStack.append(wrapper);
+ }
+}
+
} // namespace WebCore
diff --git a/WebCore/bindings/js/JSNamedNodesCollection.cpp b/WebCore/bindings/js/JSNamedNodesCollection.cpp
deleted file mode 100644
index f36a7d6..0000000
--- a/WebCore/bindings/js/JSNamedNodesCollection.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "JSNamedNodesCollection.h"
-
-#include "AtomicString.h"
-#include "Element.h"
-#include "JSNode.h"
-#include "NamedNodeMap.h"
-
-namespace WebCore {
-
-using namespace JSC;
-
-ASSERT_CLASS_FITS_IN_CELL(JSNamedNodesCollection);
-
-const ClassInfo JSNamedNodesCollection::s_info = { "Collection", 0, 0, 0 };
-
-// Such a collection is usually very short-lived, it only exists
-// for constructs like document.forms.<name>[1],
-// so it shouldn't be a problem that it's storing all the nodes (with the same name). (David)
-JSNamedNodesCollection::JSNamedNodesCollection(ExecState* exec, JSDOMGlobalObject* globalObject, const Vector<RefPtr<Node> >& nodes)
- : DOMObjectWithGlobalPointer(getDOMStructure<JSNamedNodesCollection>(exec, globalObject), globalObject)
- , m_nodes(new Vector<RefPtr<Node> >(nodes))
-{
-}
-
-JSValue JSNamedNodesCollection::lengthGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
-{
- JSNamedNodesCollection* thisObj = static_cast<JSNamedNodesCollection*>(asObject(slot.slotBase()));
- return jsNumber(exec, thisObj->m_nodes->size());
-}
-
-JSValue JSNamedNodesCollection::indexGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)
-{
- JSNamedNodesCollection *thisObj = static_cast<JSNamedNodesCollection*>(asObject(slot.slotBase()));
- return toJS(exec, (*thisObj->m_nodes)[slot.index()].get());
-}
-
-bool JSNamedNodesCollection::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
-{
- if (propertyName == exec->propertyNames().length) {
- slot.setCustom(this, lengthGetter);
- return true;
- }
-
- bool ok;
- unsigned index = propertyName.toUInt32(&ok);
- if (ok && index < m_nodes->size()) {
- slot.setCustomIndex(this, index, indexGetter);
- return true;
- }
-
- // For IE compatibility, we need to be able to look up elements in a
- // document.formName.name result by id as well as be index.
-
- AtomicString atomicPropertyName = propertyName;
- for (unsigned i = 0; i < m_nodes->size(); i++) {
- Node* node = (*m_nodes)[i].get();
- if (node->hasAttributes() && node->attributes()->id() == atomicPropertyName) {
- slot.setCustomIndex(this, i, indexGetter);
- return true;
- }
- }
-
- return DOMObjectWithGlobalPointer::getOwnPropertySlot(exec, propertyName, slot);
-}
-
-} // namespace WebCore
diff --git a/WebCore/bindings/js/JSNodeCustom.cpp b/WebCore/bindings/js/JSNodeCustom.cpp
index cf884b9..52f21e7 100644
--- a/WebCore/bindings/js/JSNodeCustom.cpp
+++ b/WebCore/bindings/js/JSNodeCustom.cpp
@@ -110,25 +110,37 @@ JSValue JSNode::appendChild(ExecState* exec, const ArgList& args)
JSValue JSNode::addEventListener(ExecState* exec, const ArgList& args)
{
- JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->document());
+ Document* document = impl()->document();
+ if (!document)
+ return jsUndefined();
+
+ JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(document);
if (!globalObject)
return jsUndefined();
- if (RefPtr<JSEventListener> listener = globalObject->findOrCreateJSEventListener(args.at(1)))
- impl()->addEventListener(args.at(0).toString(exec), listener.release(), args.at(2).toBoolean(exec));
+ JSValue listener = args.at(1);
+ if (!listener.isObject())
+ return jsUndefined();
+ impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false), args.at(2).toBoolean(exec));
return jsUndefined();
}
JSValue JSNode::removeEventListener(ExecState* exec, const ArgList& args)
{
- JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->document());
+ Document* document = impl()->document();
+ if (!document)
+ return jsUndefined();
+
+ JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(document);
if (!globalObject)
return jsUndefined();
- if (JSEventListener* listener = globalObject->findJSEventListener(args.at(1)))
- impl()->removeEventListener(args.at(0).toString(exec), listener, args.at(2).toBoolean(exec));
+ JSValue listener = args.at(1);
+ if (!listener.isObject())
+ return jsUndefined();
+ impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false).get(), args.at(2).toBoolean(exec));
return jsUndefined();
}
@@ -138,10 +150,10 @@ void JSNode::pushEventHandlerScope(ExecState*, ScopeChain&) const
void JSNode::markChildren(MarkStack& markStack)
{
- Node* node = m_impl.get();
-
Base::markChildren(markStack);
- markEventListeners(markStack, node->eventListeners());
+
+ Node* node = m_impl.get();
+ node->markEventListeners(markStack);
// Nodes in the document are kept alive by JSDocument::mark, so, if we're in
// the document, we need to mark the document, but we don't need to explicitly
diff --git a/WebCore/bindings/js/JSNodeFilterCustom.cpp b/WebCore/bindings/js/JSNodeFilterCustom.cpp
index 09fd110..2a99a93 100644
--- a/WebCore/bindings/js/JSNodeFilterCustom.cpp
+++ b/WebCore/bindings/js/JSNodeFilterCustom.cpp
@@ -48,7 +48,7 @@ JSValue JSNodeFilter::acceptNode(ExecState* exec, const ArgList& args)
PassRefPtr<NodeFilter> toNodeFilter(JSValue value)
{
- if (value.isObject(&JSNodeFilter::s_info))
+ if (value.inherits(&JSNodeFilter::s_info))
return static_cast<JSNodeFilter*>(asObject(value))->impl();
return NodeFilter::create(JSNodeFilterCondition::create(value));
diff --git a/WebCore/bindings/js/JSOptionConstructor.cpp b/WebCore/bindings/js/JSOptionConstructor.cpp
index 2b8bd5d..7da0666 100644
--- a/WebCore/bindings/js/JSOptionConstructor.cpp
+++ b/WebCore/bindings/js/JSOptionConstructor.cpp
@@ -25,6 +25,7 @@
#include "JSHTMLOptionElement.h"
#include "ScriptExecutionContext.h"
#include "Text.h"
+#include <runtime/Error.h>
using namespace JSC;
diff --git a/WebCore/bindings/js/JSPluginElementFunctions.cpp b/WebCore/bindings/js/JSPluginElementFunctions.cpp
index 56b0eca..ada2a77 100644
--- a/WebCore/bindings/js/JSPluginElementFunctions.cpp
+++ b/WebCore/bindings/js/JSPluginElementFunctions.cpp
@@ -86,6 +86,22 @@ bool runtimeObjectCustomGetOwnPropertySlot(ExecState* exec, const Identifier& pr
return true;
}
+bool runtimeObjectCustomGetOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, JSHTMLElement* element)
+{
+ RuntimeObjectImp* runtimeObject = getRuntimeObject(exec, element->impl());
+ if (!runtimeObject)
+ return false;
+ if (!runtimeObject->hasProperty(exec, propertyName))
+ return false;
+ PropertySlot slot;
+ slot.setCustom(element, runtimeObjectPropertyGetter);
+ // While we don't know what the plugin allows, we do know that we prevent
+ // enumeration or deletion of properties, so we mark plugin properties
+ // as DontEnum | DontDelete
+ descriptor.setDescriptor(slot.getValue(exec, propertyName), DontEnum | DontDelete);
+ return true;
+}
+
bool runtimeObjectCustomPut(ExecState* exec, const Identifier& propertyName, JSValue value, HTMLElement* element, PutPropertySlot& slot)
{
RuntimeObjectImp* runtimeObject = getRuntimeObject(exec, element);
diff --git a/WebCore/bindings/js/JSPluginElementFunctions.h b/WebCore/bindings/js/JSPluginElementFunctions.h
index 8c9dfa7..a5a323a 100644
--- a/WebCore/bindings/js/JSPluginElementFunctions.h
+++ b/WebCore/bindings/js/JSPluginElementFunctions.h
@@ -33,6 +33,7 @@ namespace WebCore {
JSC::JSValue runtimeObjectGetter(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&);
JSC::JSValue runtimeObjectPropertyGetter(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&);
bool runtimeObjectCustomGetOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&, JSHTMLElement*);
+ bool runtimeObjectCustomGetOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&, JSHTMLElement*);
bool runtimeObjectCustomPut(JSC::ExecState*, const JSC::Identifier&, JSC::JSValue, HTMLElement*, JSC::PutPropertySlot&);
JSC::CallType runtimeObjectGetCallData(HTMLElement*, JSC::CallData&);
diff --git a/WebCore/bindings/js/JSQuarantinedObjectWrapper.cpp b/WebCore/bindings/js/JSQuarantinedObjectWrapper.cpp
index 5f4dfd4..a0551a1 100644
--- a/WebCore/bindings/js/JSQuarantinedObjectWrapper.cpp
+++ b/WebCore/bindings/js/JSQuarantinedObjectWrapper.cpp
@@ -56,7 +56,7 @@ JSValue JSQuarantinedObjectWrapper::cachedValueGetter(ExecState*, const Identifi
return v;
}
-JSQuarantinedObjectWrapper::JSQuarantinedObjectWrapper(ExecState* unwrappedExec, JSObject* unwrappedObject, PassRefPtr<Structure> structure)
+JSQuarantinedObjectWrapper::JSQuarantinedObjectWrapper(ExecState* unwrappedExec, JSObject* unwrappedObject, NonNullPassRefPtr<Structure> structure)
: JSObject(structure)
, m_unwrappedGlobalObject(unwrappedExec->lexicalGlobalObject())
, m_unwrappedObject(unwrappedObject)
@@ -138,6 +138,26 @@ bool JSQuarantinedObjectWrapper::getOwnPropertySlot(ExecState* exec, unsigned id
return result;
}
+bool JSQuarantinedObjectWrapper::getOwnPropertyDescriptor(ExecState* exec, const Identifier& identifier, PropertyDescriptor& descriptor)
+{
+ if (!allowsGetProperty()) {
+ descriptor.setUndefined();
+ return true;
+ }
+
+ PropertyDescriptor unwrappedDescriptor;
+ bool result = m_unwrappedObject->getOwnPropertyDescriptor(unwrappedExecState(), identifier, unwrappedDescriptor);
+
+ if (unwrappedDescriptor.isAccessorDescriptor()) {
+ descriptor.setAccessorDescriptor(wrapOutgoingValue(unwrappedExecState(), unwrappedDescriptor.getter()),
+ wrapOutgoingValue(unwrappedExecState(), unwrappedDescriptor.setter()),
+ unwrappedDescriptor.attributes());
+ } else
+ descriptor.setDescriptor(wrapOutgoingValue(unwrappedExecState(), unwrappedDescriptor.value()), unwrappedDescriptor.attributes());
+ transferExceptionToExecState(exec);
+ return result;
+}
+
void JSQuarantinedObjectWrapper::put(ExecState* exec, const Identifier& identifier, JSValue value, PutPropertySlot& slot)
{
if (!allowsSetProperty())
@@ -158,6 +178,33 @@ void JSQuarantinedObjectWrapper::put(ExecState* exec, unsigned identifier, JSVal
transferExceptionToExecState(exec);
}
+bool JSQuarantinedObjectWrapper::defineOwnProperty(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool shouldThrow)
+{
+ if (!allowsSetProperty())
+ return false;
+
+ PropertyDescriptor wrappedDescriptor;
+ if (descriptor.isDataDescriptor()) {
+ wrappedDescriptor.setValue(prepareIncomingValue(exec, descriptor.value()));
+ if (wrappedDescriptor.writablePresent())
+ wrappedDescriptor.setWritable(descriptor.writable());
+ } else if (descriptor.isAccessorDescriptor()) {
+ if (descriptor.getter())
+ wrappedDescriptor.setGetter(prepareIncomingValue(exec, descriptor.getter()));
+ if (descriptor.setter())
+ wrappedDescriptor.setSetter(prepareIncomingValue(exec, descriptor.setter()));
+ }
+ if (wrappedDescriptor.enumerablePresent())
+ wrappedDescriptor.setEnumerable(descriptor.enumerable());
+ if (wrappedDescriptor.configurablePresent())
+ wrappedDescriptor.setConfigurable(descriptor.configurable());
+
+ bool result = m_unwrappedObject->defineOwnProperty(unwrappedExecState(), propertyName, wrappedDescriptor, shouldThrow);
+
+ transferExceptionToExecState(exec);
+ return result;
+}
+
bool JSQuarantinedObjectWrapper::deleteProperty(ExecState* exec, const Identifier& identifier)
{
if (!allowsDeleteProperty())
@@ -270,8 +317,16 @@ void JSQuarantinedObjectWrapper::getPropertyNames(ExecState*, PropertyNameArray&
{
if (!allowsGetPropertyNames())
return;
-
+
m_unwrappedObject->getPropertyNames(unwrappedExecState(), array);
}
+void JSQuarantinedObjectWrapper::getOwnPropertyNames(ExecState*, PropertyNameArray& array)
+{
+ if (!allowsGetPropertyNames())
+ return;
+
+ m_unwrappedObject->getOwnPropertyNames(unwrappedExecState(), array);
+}
+
} // namespace WebCore
diff --git a/WebCore/bindings/js/JSQuarantinedObjectWrapper.h b/WebCore/bindings/js/JSQuarantinedObjectWrapper.h
index 08935e7..94a92bd 100644
--- a/WebCore/bindings/js/JSQuarantinedObjectWrapper.h
+++ b/WebCore/bindings/js/JSQuarantinedObjectWrapper.h
@@ -51,16 +51,18 @@ namespace WebCore {
}
protected:
- JSQuarantinedObjectWrapper(JSC::ExecState* unwrappedExec, JSC::JSObject* unwrappedObject, PassRefPtr<JSC::Structure>);
+ JSQuarantinedObjectWrapper(JSC::ExecState* unwrappedExec, JSC::JSObject* unwrappedObject, NonNullPassRefPtr<JSC::Structure>);
virtual void markChildren(JSC::MarkStack&);
private:
virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);
virtual bool getOwnPropertySlot(JSC::ExecState*, unsigned, JSC::PropertySlot&);
+ virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&);
virtual void put(JSC::ExecState*, const JSC::Identifier&, JSC::JSValue, JSC::PutPropertySlot&);
virtual void put(JSC::ExecState*, unsigned, JSC::JSValue);
+ virtual bool defineOwnProperty(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&, bool shouldThrow);
virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier&);
virtual bool deleteProperty(JSC::ExecState*, unsigned);
@@ -69,8 +71,9 @@ namespace WebCore {
virtual JSC::ConstructType getConstructData(JSC::ConstructData&);
virtual bool hasInstance(JSC::ExecState*, JSC::JSValue, JSC::JSValue proto);
-
+
virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&);
+ virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&);
virtual JSC::UString className() const { return m_unwrappedObject->className(); }
diff --git a/WebCore/bindings/js/JSSQLTransactionCustom.cpp b/WebCore/bindings/js/JSSQLTransactionCustom.cpp
index dbe8e3c..e022401 100644
--- a/WebCore/bindings/js/JSSQLTransactionCustom.cpp
+++ b/WebCore/bindings/js/JSSQLTransactionCustom.cpp
@@ -95,8 +95,7 @@ JSValue JSSQLTransaction::executeSql(ExecState* exec, const ArgList& args)
return jsUndefined();
}
- if (Frame* frame = asJSDOMWindow(exec->dynamicGlobalObject())->impl()->frame())
- callback = JSCustomSQLStatementCallback::create(object, frame);
+ callback = JSCustomSQLStatementCallback::create(object, static_cast<JSDOMGlobalObject*>(exec->dynamicGlobalObject()));
}
RefPtr<SQLStatementErrorCallback> errorCallback;
@@ -107,8 +106,7 @@ JSValue JSSQLTransaction::executeSql(ExecState* exec, const ArgList& args)
return jsUndefined();
}
- if (Frame* frame = asJSDOMWindow(exec->dynamicGlobalObject())->impl()->frame())
- errorCallback = JSCustomSQLStatementErrorCallback::create(object, frame);
+ errorCallback = JSCustomSQLStatementErrorCallback::create(object, static_cast<JSDOMGlobalObject*>(exec->dynamicGlobalObject()));
}
ExceptionCode ec = 0;
diff --git a/WebCore/bindings/js/JSSVGElementInstanceCustom.cpp b/WebCore/bindings/js/JSSVGElementInstanceCustom.cpp
index 6e77f9b..571e302 100644
--- a/WebCore/bindings/js/JSSVGElementInstanceCustom.cpp
+++ b/WebCore/bindings/js/JSSVGElementInstanceCustom.cpp
@@ -54,9 +54,11 @@ JSValue JSSVGElementInstance::addEventListener(ExecState* exec, const ArgList& a
if (!globalObject)
return jsUndefined();
- if (RefPtr<JSEventListener> listener = globalObject->findOrCreateJSEventListener(args.at(1)))
- impl()->addEventListener(args.at(0).toString(exec), listener.release(), args.at(2).toBoolean(exec));
+ JSValue listener = args.at(1);
+ if (!listener.isObject())
+ return jsUndefined();
+ impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false), args.at(2).toBoolean(exec));
return jsUndefined();
}
@@ -66,9 +68,11 @@ JSValue JSSVGElementInstance::removeEventListener(ExecState* exec, const ArgList
if (!globalObject)
return jsUndefined();
- if (JSEventListener* listener = globalObject->findJSEventListener(args.at(1)))
- impl()->removeEventListener(args.at(0).toString(exec), listener, args.at(2).toBoolean(exec));
+ JSValue listener = args.at(1);
+ if (!listener.isObject())
+ return jsUndefined();
+ impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false).get(), args.at(2).toBoolean(exec));
return jsUndefined();
}
diff --git a/WebCore/bindings/js/JSSharedWorkerConstructor.cpp b/WebCore/bindings/js/JSSharedWorkerConstructor.cpp
index e2f1136..c05b3d2 100644
--- a/WebCore/bindings/js/JSSharedWorkerConstructor.cpp
+++ b/WebCore/bindings/js/JSSharedWorkerConstructor.cpp
@@ -37,6 +37,7 @@
#include "JSDOMWindowCustom.h"
#include "JSSharedWorker.h"
#include "SharedWorker.h"
+#include <runtime/Error.h>
using namespace JSC;
@@ -56,11 +57,14 @@ static JSObject* constructSharedWorker(ExecState* exec, JSObject* constructor, c
{
JSSharedWorkerConstructor* jsConstructor = static_cast<JSSharedWorkerConstructor*>(constructor);
- if (args.size() < 2)
+ if (args.size() < 1)
return throwError(exec, SyntaxError, "Not enough arguments");
UString scriptURL = args.at(0).toString(exec);
- UString name = args.at(1).toString(exec);
+ UString name;
+ if (args.size() > 1)
+ name = args.at(1).toString(exec);
+
if (exec->hadException())
return 0;
diff --git a/WebCore/bindings/js/JSStorageCustom.cpp b/WebCore/bindings/js/JSStorageCustom.cpp
index 07cf2f8..e416d35 100644
--- a/WebCore/bindings/js/JSStorageCustom.cpp
+++ b/WebCore/bindings/js/JSStorageCustom.cpp
@@ -64,13 +64,13 @@ bool JSStorage::deleteProperty(ExecState* exec, const Identifier& propertyName)
return true;
}
-void JSStorage::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
+void JSStorage::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)
{
unsigned length = m_impl->length();
for (unsigned i = 0; i < length; ++i)
propertyNames.add(Identifier(exec, m_impl->key(i)));
- Base::getPropertyNames(exec, propertyNames);
+ Base::getOwnPropertyNames(exec, propertyNames);
}
bool JSStorage::putDelegate(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot&)
diff --git a/WebCore/bindings/js/JSStyleSheetCustom.cpp b/WebCore/bindings/js/JSStyleSheetCustom.cpp
index 43249dc..d711b6f 100644
--- a/WebCore/bindings/js/JSStyleSheetCustom.cpp
+++ b/WebCore/bindings/js/JSStyleSheetCustom.cpp
@@ -56,12 +56,19 @@ void JSStyleSheet::markChildren(MarkStack& markStack)
{
Base::markChildren(markStack);
+ StyleSheet* sheet = impl();
+ JSGlobalData& globalData = *Heap::heap(this)->globalData();
+
+ unsigned length = sheet->length();
+ for (unsigned i = 0; i < length; ++i)
+ markDOMObjectWrapper(markStack, globalData, sheet->item(i));
+
// This prevents us from having a style sheet with a dangling ownerNode pointer.
// A better solution would be to handle this on the DOM side -- if the style sheet
// is kept around, then we want the node to stay around too. One possibility would
// be to make ref/deref on the style sheet ref/deref the node instead, but there's
// a lot of disentangling of the CSS DOM objects that would need to happen first.
- if (Node* ownerNode = impl()->ownerNode()) {
+ if (Node* ownerNode = sheet->ownerNode()) {
if (JSNode* ownerNodeWrapper = getCachedDOMNodeWrapper(ownerNode->document(), ownerNode))
markStack.append(ownerNodeWrapper);
}
diff --git a/WebCore/bindings/js/JSStyleSheetListCustom.cpp b/WebCore/bindings/js/JSStyleSheetListCustom.cpp
index 1da6418..7bf9389 100644
--- a/WebCore/bindings/js/JSStyleSheetListCustom.cpp
+++ b/WebCore/bindings/js/JSStyleSheetListCustom.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -35,6 +35,18 @@ using namespace JSC;
namespace WebCore {
+void JSStyleSheetList::markChildren(MarkStack& markStack)
+{
+ Base::markChildren(markStack);
+
+ StyleSheetList* list = impl();
+ JSGlobalData& globalData = *Heap::heap(this)->globalData();
+
+ unsigned length = list->length();
+ for (unsigned i = 0; i < length; ++i)
+ markDOMObjectWrapper(markStack, globalData, list->item(i));
+}
+
bool JSStyleSheetList::canGetItemsForName(ExecState*, StyleSheetList* styleSheetList, const Identifier& propertyName)
{
return styleSheetList->getNamedItem(propertyName);
diff --git a/WebCore/bindings/js/JSWebSocketConstructor.cpp b/WebCore/bindings/js/JSWebSocketConstructor.cpp
index ca2e104..5b34765 100644
--- a/WebCore/bindings/js/JSWebSocketConstructor.cpp
+++ b/WebCore/bindings/js/JSWebSocketConstructor.cpp
@@ -37,6 +37,7 @@
#include "JSWebSocket.h"
#include "ScriptExecutionContext.h"
#include "WebSocket.h"
+#include <runtime/Error.h>
using namespace JSC;
diff --git a/WebCore/bindings/js/JSWebSocketCustom.cpp b/WebCore/bindings/js/JSWebSocketCustom.cpp
index 3aa4b8b..d305502 100644
--- a/WebCore/bindings/js/JSWebSocketCustom.cpp
+++ b/WebCore/bindings/js/JSWebSocketCustom.cpp
@@ -38,19 +38,12 @@
#include "KURL.h"
#include "WebSocket.h"
#include "NotImplemented.h"
+#include <runtime/Error.h>
using namespace JSC;
namespace WebCore {
-void JSWebSocket::markChildren(MarkStack& markStack)
-{
- Base::markChildren(markStack);
- if (m_impl->readyState() != WebSocket::CLOSED)
- markIfNotNull(markStack, m_impl->onmessage());
- // FIXME: mark if EventListeners is registered.
-}
-
// Custom functions
JSValue JSWebSocket::send(ExecState* exec, const ArgList& args)
{
diff --git a/WebCore/bindings/js/JSWorkerConstructor.cpp b/WebCore/bindings/js/JSWorkerConstructor.cpp
index 9943cfb..69c05e7 100644
--- a/WebCore/bindings/js/JSWorkerConstructor.cpp
+++ b/WebCore/bindings/js/JSWorkerConstructor.cpp
@@ -34,6 +34,7 @@
#include "JSDOMWindowCustom.h"
#include "JSWorker.h"
#include "Worker.h"
+#include <runtime/Error.h>
using namespace JSC;
diff --git a/WebCore/bindings/js/JSWorkerContextBase.cpp b/WebCore/bindings/js/JSWorkerContextBase.cpp
index 1e4df42..741a269 100644
--- a/WebCore/bindings/js/JSWorkerContextBase.cpp
+++ b/WebCore/bindings/js/JSWorkerContextBase.cpp
@@ -44,7 +44,7 @@ ASSERT_CLASS_FITS_IN_CELL(JSWorkerContextBase);
const ClassInfo JSWorkerContextBase::s_info = { "WorkerContext", 0, 0, 0 };
-JSWorkerContextBase::JSWorkerContextBase(PassRefPtr<JSC::Structure> structure, PassRefPtr<WorkerContext> impl)
+JSWorkerContextBase::JSWorkerContextBase(NonNullPassRefPtr<JSC::Structure> structure, PassRefPtr<WorkerContext> impl)
: JSDOMGlobalObject(structure, new JSDOMGlobalObjectData, this)
, m_impl(impl)
{
diff --git a/WebCore/bindings/js/JSWorkerContextBase.h b/WebCore/bindings/js/JSWorkerContextBase.h
index a9a6e63..45238f1 100644
--- a/WebCore/bindings/js/JSWorkerContextBase.h
+++ b/WebCore/bindings/js/JSWorkerContextBase.h
@@ -41,7 +41,7 @@ namespace WebCore {
class JSWorkerContextBase : public JSDOMGlobalObject {
typedef JSDOMGlobalObject Base;
public:
- JSWorkerContextBase(PassRefPtr<JSC::Structure>, PassRefPtr<WorkerContext>);
+ JSWorkerContextBase(NonNullPassRefPtr<JSC::Structure>, PassRefPtr<WorkerContext>);
virtual ~JSWorkerContextBase();
virtual const JSC::ClassInfo* classInfo() const { return &s_info; }
diff --git a/WebCore/bindings/js/JSWorkerContextCustom.cpp b/WebCore/bindings/js/JSWorkerContextCustom.cpp
index 919c81f..e1c8a8c 100644
--- a/WebCore/bindings/js/JSWorkerContextCustom.cpp
+++ b/WebCore/bindings/js/JSWorkerContextCustom.cpp
@@ -43,6 +43,10 @@
#include "WorkerNavigator.h"
#include <interpreter/Interpreter.h>
+#if ENABLE(EVENTSOURCE)
+#include "JSEventSourceConstructor.h"
+#endif
+
using namespace JSC;
namespace WebCore {
@@ -58,15 +62,7 @@ void JSWorkerContext::markChildren(MarkStack& markStack)
markDOMObjectWrapper(markStack, globalData, impl()->optionalLocation());
markDOMObjectWrapper(markStack, globalData, impl()->optionalNavigator());
- markIfNotNull(markStack, impl()->onerror());
-
- typedef WorkerContext::EventListenersMap EventListenersMap;
- typedef WorkerContext::ListenerVector ListenerVector;
- EventListenersMap& eventListeners = impl()->eventListeners();
- for (EventListenersMap::iterator mapIter = eventListeners.begin(); mapIter != eventListeners.end(); ++mapIter) {
- for (ListenerVector::iterator vecIter = mapIter->second.begin(); vecIter != mapIter->second.end(); ++vecIter)
- (*vecIter)->markJSFunction(markStack);
- }
+ impl()->markEventListeners(markStack);
}
bool JSWorkerContext::getOwnPropertySlotDelegate(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
@@ -77,6 +73,21 @@ bool JSWorkerContext::getOwnPropertySlotDelegate(ExecState* exec, const Identifi
return false;
}
+bool JSWorkerContext::getOwnPropertyDescriptorDelegate(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+ // Look for overrides before looking at any of our own properties.
+ if (JSGlobalObject::getOwnPropertyDescriptor(exec, propertyName, descriptor))
+ return true;
+ return false;
+}
+
+#if ENABLE(EVENTSOURCE)
+JSValue JSWorkerContext::eventSource(ExecState* exec) const
+{
+ return getDOMConstructor<JSEventSourceConstructor>(exec, this);
+}
+#endif
+
JSValue JSWorkerContext::xmlHttpRequest(ExecState* exec) const
{
return getDOMConstructor<JSXMLHttpRequestConstructor>(exec, this);
@@ -107,19 +118,21 @@ JSValue JSWorkerContext::importScripts(ExecState* exec, const ArgList& args)
JSValue JSWorkerContext::addEventListener(ExecState* exec, const ArgList& args)
{
- RefPtr<JSEventListener> listener = findOrCreateJSEventListener(args.at(1));
- if (!listener)
+ JSValue listener = args.at(1);
+ if (!listener.isObject())
return jsUndefined();
- impl()->addEventListener(args.at(0).toString(exec), listener.release(), args.at(2).toBoolean(exec));
+
+ impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false), args.at(2).toBoolean(exec));
return jsUndefined();
}
JSValue JSWorkerContext::removeEventListener(ExecState* exec, const ArgList& args)
{
- JSEventListener* listener = findJSEventListener(args.at(1));
- if (!listener)
+ JSValue listener = args.at(1);
+ if (!listener.isObject())
return jsUndefined();
- impl()->removeEventListener(args.at(0).toString(exec), listener, args.at(2).toBoolean(exec));
+
+ impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false).get(), args.at(2).toBoolean(exec));
return jsUndefined();
}
diff --git a/WebCore/bindings/js/JSWorkerCustom.cpp b/WebCore/bindings/js/JSWorkerCustom.cpp
index f5c394b..09b881a 100644
--- a/WebCore/bindings/js/JSWorkerCustom.cpp
+++ b/WebCore/bindings/js/JSWorkerCustom.cpp
@@ -30,17 +30,16 @@
#include "JSWorker.h"
#include "JSDOMGlobalObject.h"
+#include "JSMessagePortCustom.h"
#include "Worker.h"
using namespace JSC;
namespace WebCore {
-
-void JSWorker::markChildren(MarkStack& markStack)
-{
- Base::markChildren(markStack);
- markIfNotNull(markStack, static_cast<Worker*>(impl())->onmessage());
+JSC::JSValue JSWorker::postMessage(JSC::ExecState* exec, const JSC::ArgList& args)
+{
+ return handlePostMessage(exec, args, impl());
}
} // namespace WebCore
diff --git a/WebCore/bindings/js/JSXMLHttpRequestConstructor.cpp b/WebCore/bindings/js/JSXMLHttpRequestConstructor.cpp
index a644c9e..91fff9a 100644
--- a/WebCore/bindings/js/JSXMLHttpRequestConstructor.cpp
+++ b/WebCore/bindings/js/JSXMLHttpRequestConstructor.cpp
@@ -23,6 +23,7 @@
#include "JSXMLHttpRequest.h"
#include "ScriptExecutionContext.h"
#include "XMLHttpRequest.h"
+#include <runtime/Error.h>
using namespace JSC;
diff --git a/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp b/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp
index a591fae..4b44db2 100644
--- a/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp
+++ b/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp
@@ -59,20 +59,7 @@ void JSXMLHttpRequest::markChildren(MarkStack& markStack)
markStack.append(wrapper);
}
- markIfNotNull(markStack, m_impl->onreadystatechange());
- markIfNotNull(markStack, m_impl->onabort());
- markIfNotNull(markStack, m_impl->onerror());
- markIfNotNull(markStack, m_impl->onload());
- markIfNotNull(markStack, m_impl->onloadstart());
- markIfNotNull(markStack, m_impl->onprogress());
-
- typedef XMLHttpRequest::EventListenersMap EventListenersMap;
- typedef XMLHttpRequest::ListenerVector ListenerVector;
- EventListenersMap& eventListeners = m_impl->eventListeners();
- for (EventListenersMap::iterator mapIter = eventListeners.begin(); mapIter != eventListeners.end(); ++mapIter) {
- for (ListenerVector::iterator vecIter = mapIter->second.begin(); vecIter != mapIter->second.end(); ++vecIter)
- (*vecIter)->markJSFunction(markStack);
- }
+ m_impl->markEventListeners(markStack);
}
// Custom functions
@@ -123,9 +110,9 @@ JSValue JSXMLHttpRequest::send(ExecState* exec, const ArgList& args)
JSValue val = args.at(0);
if (val.isUndefinedOrNull())
impl()->send(ec);
- else if (val.isObject(&JSDocument::s_info))
+ else if (val.inherits(&JSDocument::s_info))
impl()->send(toDocument(val), ec);
- else if (val.isObject(&JSFile::s_info))
+ else if (val.inherits(&JSFile::s_info))
impl()->send(toFile(val), ec);
else
impl()->send(val.toString(exec), ec);
@@ -168,10 +155,12 @@ JSValue JSXMLHttpRequest::addEventListener(ExecState* exec, const ArgList& args)
JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->scriptExecutionContext());
if (!globalObject)
return jsUndefined();
- RefPtr<JSEventListener> listener = globalObject->findOrCreateJSEventListener(args.at(1));
- if (!listener)
+
+ JSValue listener = args.at(1);
+ if (!listener.isObject())
return jsUndefined();
- impl()->addEventListener(args.at(0).toString(exec), listener.release(), args.at(2).toBoolean(exec));
+
+ impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false), args.at(2).toBoolean(exec));
return jsUndefined();
}
@@ -180,10 +169,12 @@ JSValue JSXMLHttpRequest::removeEventListener(ExecState* exec, const ArgList& ar
JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->scriptExecutionContext());
if (!globalObject)
return jsUndefined();
- JSEventListener* listener = globalObject->findJSEventListener(args.at(1));
- if (!listener)
+
+ JSValue listener = args.at(1);
+ if (!listener.isObject())
return jsUndefined();
- impl()->removeEventListener(args.at(0).toString(exec), listener, args.at(2).toBoolean(exec));
+
+ impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false).get(), args.at(2).toBoolean(exec));
return jsUndefined();
}
diff --git a/WebCore/bindings/js/JSXMLHttpRequestUploadCustom.cpp b/WebCore/bindings/js/JSXMLHttpRequestUploadCustom.cpp
index cb6d5f2..dab0a3e 100644
--- a/WebCore/bindings/js/JSXMLHttpRequestUploadCustom.cpp
+++ b/WebCore/bindings/js/JSXMLHttpRequestUploadCustom.cpp
@@ -51,19 +51,7 @@ void JSXMLHttpRequestUpload::markChildren(MarkStack& markStack)
markStack.append(wrapper);
}
- markIfNotNull(markStack, m_impl->onabort());
- markIfNotNull(markStack, m_impl->onerror());
- markIfNotNull(markStack, m_impl->onload());
- markIfNotNull(markStack, m_impl->onloadstart());
- markIfNotNull(markStack, m_impl->onprogress());
-
- typedef XMLHttpRequestUpload::EventListenersMap EventListenersMap;
- typedef XMLHttpRequestUpload::ListenerVector ListenerVector;
- EventListenersMap& eventListeners = m_impl->eventListeners();
- for (EventListenersMap::iterator mapIter = eventListeners.begin(); mapIter != eventListeners.end(); ++mapIter) {
- for (ListenerVector::iterator vecIter = mapIter->second.begin(); vecIter != mapIter->second.end(); ++vecIter)
- (*vecIter)->markJSFunction(markStack);
- }
+ m_impl->markEventListeners(markStack);
}
JSValue JSXMLHttpRequestUpload::addEventListener(ExecState* exec, const ArgList& args)
@@ -71,10 +59,12 @@ JSValue JSXMLHttpRequestUpload::addEventListener(ExecState* exec, const ArgList&
JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->scriptExecutionContext());
if (!globalObject)
return jsUndefined();
- RefPtr<JSEventListener> listener = globalObject->findOrCreateJSEventListener(args.at(1));
- if (!listener)
+
+ JSValue listener = args.at(1);
+ if (!listener.isObject())
return jsUndefined();
- impl()->addEventListener(args.at(0).toString(exec), listener.release(), args.at(2).toBoolean(exec));
+
+ impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false), args.at(2).toBoolean(exec));
return jsUndefined();
}
@@ -83,10 +73,12 @@ JSValue JSXMLHttpRequestUpload::removeEventListener(ExecState* exec, const ArgLi
JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->scriptExecutionContext());
if (!globalObject)
return jsUndefined();
- JSEventListener* listener = globalObject->findJSEventListener(args.at(1));
- if (!listener)
+
+ JSValue listener = args.at(1);
+ if (!listener.isObject())
return jsUndefined();
- impl()->removeEventListener(args.at(0).toString(exec), listener, args.at(2).toBoolean(exec));
+
+ impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), false).get(), args.at(2).toBoolean(exec));
return jsUndefined();
}
diff --git a/WebCore/bindings/js/JSXSLTProcessorCustom.cpp b/WebCore/bindings/js/JSXSLTProcessorCustom.cpp
index 01e53a6..441bbc9 100644
--- a/WebCore/bindings/js/JSXSLTProcessorCustom.cpp
+++ b/WebCore/bindings/js/JSXSLTProcessorCustom.cpp
@@ -49,7 +49,7 @@ namespace WebCore {
JSValue JSXSLTProcessor::importStylesheet(ExecState*, const ArgList& args)
{
JSValue nodeVal = args.at(0);
- if (nodeVal.isObject(&JSNode::s_info)) {
+ if (nodeVal.inherits(&JSNode::s_info)) {
JSNode* node = static_cast<JSNode*>(asObject(nodeVal));
impl()->importStylesheet(node->impl());
return jsUndefined();
@@ -62,7 +62,7 @@ JSValue JSXSLTProcessor::transformToFragment(ExecState* exec, const ArgList& arg
{
JSValue nodeVal = args.at(0);
JSValue docVal = args.at(1);
- if (nodeVal.isObject(&JSNode::s_info) && docVal.isObject(&JSDocument::s_info)) {
+ if (nodeVal.inherits(&JSNode::s_info) && docVal.inherits(&JSDocument::s_info)) {
WebCore::Node* node = static_cast<JSNode*>(asObject(nodeVal))->impl();
Document* doc = static_cast<Document*>(static_cast<JSDocument*>(asObject(docVal))->impl());
return toJS(exec, impl()->transformToFragment(node, doc).get());
@@ -74,7 +74,7 @@ JSValue JSXSLTProcessor::transformToFragment(ExecState* exec, const ArgList& arg
JSValue JSXSLTProcessor::transformToDocument(ExecState* exec, const ArgList& args)
{
JSValue nodeVal = args.at(0);
- if (nodeVal.isObject(&JSNode::s_info)) {
+ if (nodeVal.inherits(&JSNode::s_info)) {
JSNode* node = static_cast<JSNode*>(asObject(nodeVal));
RefPtr<Document> resultDocument = impl()->transformToDocument(node->impl());
if (resultDocument)
diff --git a/WebCore/bindings/js/ScriptCachedFrameData.cpp b/WebCore/bindings/js/ScriptCachedFrameData.cpp
index 8852611..77b8ca4 100644
--- a/WebCore/bindings/js/ScriptCachedFrameData.cpp
+++ b/WebCore/bindings/js/ScriptCachedFrameData.cpp
@@ -86,7 +86,7 @@ void ScriptCachedFrameData::clear()
{
JSLock lock(SilenceAssertionsOnly);
- if (!m_window) {
+ if (m_window) {
m_window = 0;
gcController().garbageCollectSoon();
}
diff --git a/WebCore/bindings/js/ScriptCallFrame.cpp b/WebCore/bindings/js/ScriptCallFrame.cpp
index 58168d0..09752d1 100644
--- a/WebCore/bindings/js/ScriptCallFrame.cpp
+++ b/WebCore/bindings/js/ScriptCallFrame.cpp
@@ -40,7 +40,7 @@ namespace WebCore {
ScriptCallFrame::ScriptCallFrame(const UString& functionName, const UString& urlString, int lineNumber, const ArgList& args, unsigned skipArgumentCount)
: m_functionName(functionName)
- , m_sourceURL(urlString)
+ , m_sourceURL(ParsedURLString, urlString)
, m_lineNumber(lineNumber)
{
size_t argumentCount = args.size();
diff --git a/WebCore/bindings/js/ScriptController.cpp b/WebCore/bindings/js/ScriptController.cpp
index 8908155..45f8c75 100644
--- a/WebCore/bindings/js/ScriptController.cpp
+++ b/WebCore/bindings/js/ScriptController.cpp
@@ -33,16 +33,23 @@
#include "ScriptSourceCode.h"
#include "ScriptValue.h"
#include "Settings.h"
+#include "StorageNamespace.h"
#include "XSSAuditor.h"
#include "npruntime_impl.h"
#include "runtime_root.h"
#include <debugger/Debugger.h>
+#include <runtime/InitializeThreading.h>
#include <runtime/JSLock.h>
using namespace JSC;
namespace WebCore {
+void ScriptController::initializeThreading()
+{
+ JSC::initializeThreading();
+}
+
ScriptController::ScriptController(Frame* frame)
: m_frame(frame)
, m_handlerLineNumber(0)
@@ -84,12 +91,7 @@ ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode)
const SourceCode& jsSourceCode = sourceCode.jsSourceCode();
String sourceURL = jsSourceCode.provider()->url();
- if (sourceURL.isNull() && !m_XSSAuditor->canEvaluateJavaScriptURL(sourceCode.source())) {
- // This JavaScript URL is not safe to be evaluated.
- return JSValue();
- }
-
- if (!sourceURL.isNull() && !m_XSSAuditor->canEvaluate(sourceCode.source())) {
+ if (!m_XSSAuditor->canEvaluate(sourceCode.source())) {
// This script is not safe to be evaluated.
return JSValue();
}
@@ -130,6 +132,14 @@ ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode)
return JSValue();
}
+void ScriptController::evaluateInIsolatedWorld(unsigned /* worldID */, const Vector<ScriptSourceCode>& sourceCode)
+{
+ // FIXME: Actually support isolated worlds!
+ unsigned size = sourceCode.size();
+ for (unsigned i = 0; i < size; ++i)
+ evaluate(sourceCode[i]);
+}
+
void ScriptController::clearWindowShell()
{
if (!m_windowShell)
diff --git a/WebCore/bindings/js/ScriptController.h b/WebCore/bindings/js/ScriptController.h
index 4528495..9ae10fb 100644
--- a/WebCore/bindings/js/ScriptController.h
+++ b/WebCore/bindings/js/ScriptController.h
@@ -80,7 +80,12 @@ public:
return m_windowShell->window();
}
+ // This function must be called from the main thread. It is safe to call it repeatedly.
+ // Darwin is an exception to this rule: it is OK to call this function from any thread, even reentrantly.
+ static void initializeThreading();
+
ScriptValue evaluate(const ScriptSourceCode&);
+ void evaluateInIsolatedWorld(unsigned worldID, const Vector<ScriptSourceCode>&);
void setEventHandlerLineNumber(int lineno) { m_handlerLineNumber = lineno; }
int eventHandlerLineNumber() { return m_handlerLineNumber; }
diff --git a/WebCore/bindings/js/ScriptControllerHaiku.cpp b/WebCore/bindings/js/ScriptControllerHaiku.cpp
index b573b97..3fe471d 100644
--- a/WebCore/bindings/js/ScriptControllerHaiku.cpp
+++ b/WebCore/bindings/js/ScriptControllerHaiku.cpp
@@ -28,8 +28,8 @@
#include "ScriptController.h"
#include "PluginView.h"
-#include "runtime_root.h"
#include "runtime.h"
+#include "runtime_root.h"
namespace WebCore {
diff --git a/WebCore/bindings/js/ScriptEventListener.cpp b/WebCore/bindings/js/ScriptEventListener.cpp
index 878c535..0b0047b 100644
--- a/WebCore/bindings/js/ScriptEventListener.cpp
+++ b/WebCore/bindings/js/ScriptEventListener.cpp
@@ -33,12 +33,11 @@
#include "Attribute.h"
#include "Document.h"
+#include "EventListener.h"
#include "JSNode.h"
#include "Frame.h"
#include "XSSAuditor.h"
-#include <runtime/JSLock.h>
-
using namespace JSC;
namespace WebCore {
@@ -54,29 +53,25 @@ PassRefPtr<JSLazyEventListener> createAttributeEventListener(Node* node, Attribu
{
ASSERT(node);
- Frame* frame = node->document()->frame();
- if (!frame)
- return 0;
-
- ScriptController* scriptController = frame->script();
- if (!scriptController->isEnabled())
- return 0;
-
- if (!scriptController->xssAuditor()->canCreateInlineEventListener(attr->localName().string(), attr->value())) {
- // This script is not safe to execute.
- return 0;
- }
+ int lineNumber = 1;
+ String sourceURL;
- JSDOMWindow* globalObject = scriptController->globalObject();
-
- // Ensure that 'node' has a JavaScript wrapper to mark the event listener we're creating.
- {
- JSLock lock(SilenceAssertionsOnly);
- // FIXME: Should pass the global object associated with the node
- toJS(globalObject->globalExec(), globalObject, node);
+ // FIXME: We should be able to provide accurate source information for frameless documents, too (e.g. for importing nodes from XMLHttpRequest.responseXML).
+ if (Frame* frame = node->document()->frame()) {
+ ScriptController* scriptController = frame->script();
+ if (!scriptController->isEnabled())
+ return 0;
+
+ if (!scriptController->xssAuditor()->canCreateInlineEventListener(attr->localName().string(), attr->value())) {
+ // This script is not safe to execute.
+ return 0;
+ }
+
+ lineNumber = scriptController->eventHandlerLineNumber();
+ sourceURL = node->document()->url().string();
}
- return JSLazyEventListener::create(attr->localName().string(), eventParameterName(node->isSVGElement()), attr->value(), globalObject, node, scriptController->eventHandlerLineNumber());
+ return JSLazyEventListener::create(attr->localName().string(), eventParameterName(node->isSVGElement()), attr->value(), node, sourceURL, lineNumber);
}
PassRefPtr<JSLazyEventListener> createAttributeEventListener(Frame* frame, Attribute* attr)
@@ -84,19 +79,29 @@ PassRefPtr<JSLazyEventListener> createAttributeEventListener(Frame* frame, Attri
if (!frame)
return 0;
+ int lineNumber = 1;
+ String sourceURL;
+
ScriptController* scriptController = frame->script();
if (!scriptController->isEnabled())
return 0;
-
+
if (!scriptController->xssAuditor()->canCreateInlineEventListener(attr->localName().string(), attr->value())) {
// This script is not safe to execute.
return 0;
}
- // 'globalObject' is the JavaScript wrapper that will mark the event listener we're creating.
- JSDOMWindow* globalObject = scriptController->globalObject();
+ lineNumber = scriptController->eventHandlerLineNumber();
+ sourceURL = frame->document()->url().string();
+ return JSLazyEventListener::create(attr->localName().string(), eventParameterName(frame->document()->isSVGDocument()), attr->value(), 0, sourceURL, lineNumber);
+}
- return JSLazyEventListener::create(attr->localName().string(), eventParameterName(frame->document()->isSVGDocument()), attr->value(), globalObject, 0, scriptController->eventHandlerLineNumber());
+String getEventListenerHandlerBody(ScriptExecutionContext* context, ScriptState* scriptState, EventListener* eventListener)
+{
+ JSC::JSObject* functionObject = eventListener->jsFunction(context);
+ if (!functionObject)
+ return "";
+ return functionObject->toString(scriptState);
}
} // namespace WebCore
diff --git a/WebCore/bindings/js/ScriptEventListener.h b/WebCore/bindings/js/ScriptEventListener.h
index 8299d29..3396541 100644
--- a/WebCore/bindings/js/ScriptEventListener.h
+++ b/WebCore/bindings/js/ScriptEventListener.h
@@ -32,17 +32,20 @@
#define ScriptEventListener_h
#include "JSLazyEventListener.h"
+#include "ScriptState.h"
#include <wtf/PassRefPtr.h>
namespace WebCore {
class Attribute;
+ class EventListener;
class Frame;
class Node;
PassRefPtr<JSLazyEventListener> createAttributeEventListener(Node*, Attribute*);
PassRefPtr<JSLazyEventListener> createAttributeEventListener(Frame*, Attribute*);
+ String getEventListenerHandlerBody(ScriptExecutionContext*, ScriptState*, EventListener*);
} // namespace WebCore
diff --git a/WebCore/bindings/js/ScriptObject.cpp b/WebCore/bindings/js/ScriptObject.cpp
index beadc4a..b69ef2b 100644
--- a/WebCore/bindings/js/ScriptObject.cpp
+++ b/WebCore/bindings/js/ScriptObject.cpp
@@ -106,6 +106,14 @@ bool ScriptObject::set(const char* name, int value)
return handleException(m_scriptState);
}
+bool ScriptObject::set(const char* name, unsigned value)
+{
+ JSLock lock(SilenceAssertionsOnly);
+ PutPropertySlot slot;
+ jsObject()->put(m_scriptState, Identifier(m_scriptState, name), jsNumber(m_scriptState, value), slot);
+ return handleException(m_scriptState);
+}
+
bool ScriptObject::set(const char* name, bool value)
{
JSLock lock(SilenceAssertionsOnly);
@@ -128,6 +136,7 @@ bool ScriptGlobalObject::set(ScriptState* scriptState, const char* name, const S
}
#if ENABLE(JAVASCRIPT_DEBUGGER)
+#if ENABLE(INSPECTOR)
bool ScriptGlobalObject::set(ScriptState* scriptState, const char* name, InspectorBackend* value)
{
JSLock lock(SilenceAssertionsOnly);
@@ -135,6 +144,7 @@ bool ScriptGlobalObject::set(ScriptState* scriptState, const char* name, Inspect
globalObject->putDirect(Identifier(scriptState, name), toJS(scriptState, globalObject, value));
return handleException(scriptState);
}
+#endif // ENABLE(INSPECTOR)
#endif
bool ScriptGlobalObject::get(ScriptState* scriptState, const char* name, ScriptObject& value)
diff --git a/WebCore/bindings/js/ScriptObject.h b/WebCore/bindings/js/ScriptObject.h
index 50b63ad..31381f3 100644
--- a/WebCore/bindings/js/ScriptObject.h
+++ b/WebCore/bindings/js/ScriptObject.h
@@ -52,6 +52,7 @@ namespace WebCore {
bool set(const char* name, double);
bool set(const char* name, long long);
bool set(const char* name, int);
+ bool set(const char* name, unsigned);
bool set(const char* name, bool);
static ScriptObject createNew(ScriptState*);
@@ -63,7 +64,9 @@ namespace WebCore {
class ScriptGlobalObject {
public:
static bool set(ScriptState*, const char* name, const ScriptObject&);
+#if ENABLE(INSPECTOR)
static bool set(ScriptState*, const char* name, InspectorBackend*);
+#endif
static bool get(ScriptState*, const char* name, ScriptObject&);
static bool remove(ScriptState*, const char* name);
private:
diff --git a/WebCore/bindings/js/ScriptObjectQuarantine.cpp b/WebCore/bindings/js/ScriptObjectQuarantine.cpp
index 89553ef..b48556e 100644
--- a/WebCore/bindings/js/ScriptObjectQuarantine.cpp
+++ b/WebCore/bindings/js/ScriptObjectQuarantine.cpp
@@ -31,6 +31,8 @@
#include "config.h"
#include "ScriptObjectQuarantine.h"
+#if ENABLE(INSPECTOR)
+
#include "Document.h"
#include "Frame.h"
#include "JSDOMBinding.h"
@@ -38,6 +40,7 @@
#include "JSNode.h"
#include "ScriptObject.h"
#include "ScriptValue.h"
+#include "Storage.h"
#include <runtime/JSLock.h>
@@ -80,10 +83,11 @@ bool getQuarantinedScriptObject(Database* database, ScriptObject& quarantinedObj
#endif
#if ENABLE(DOM_STORAGE)
-bool getQuarantinedScriptObject(Frame* frame, Storage* storage, ScriptObject& quarantinedObject)
+bool getQuarantinedScriptObject(Storage* storage, ScriptObject& quarantinedObject)
{
- ASSERT(frame);
ASSERT(storage);
+ Frame* frame = storage->frame();
+ ASSERT(frame);
JSDOMGlobalObject* globalObject = toJSDOMWindow(frame);
ExecState* exec = globalObject->globalExec();
@@ -123,3 +127,5 @@ bool getQuarantinedScriptObject(DOMWindow* domWindow, ScriptObject& quarantinedO
} // namespace WebCore
+
+#endif // ENABLE(INSPECTOR)
diff --git a/WebCore/bindings/js/ScriptObjectQuarantine.h b/WebCore/bindings/js/ScriptObjectQuarantine.h
index d70acd7..df52379 100644
--- a/WebCore/bindings/js/ScriptObjectQuarantine.h
+++ b/WebCore/bindings/js/ScriptObjectQuarantine.h
@@ -37,7 +37,6 @@ namespace WebCore {
class Database;
class DOMWindow;
- class Frame;
class Node;
class ScriptObject;
class ScriptValue;
@@ -49,7 +48,7 @@ namespace WebCore {
bool getQuarantinedScriptObject(Database* database, ScriptObject& quarantinedObject);
#endif
#if ENABLE(DOM_STORAGE)
- bool getQuarantinedScriptObject(Frame* frame, Storage* storage, ScriptObject& quarantinedObject);
+ bool getQuarantinedScriptObject(Storage* storage, ScriptObject& quarantinedObject);
#endif
bool getQuarantinedScriptObject(Node* node, ScriptObject& quarantinedObject);
bool getQuarantinedScriptObject(DOMWindow* domWindow, ScriptObject& quarantinedObject);
diff --git a/WebCore/bindings/js/ScriptValue.cpp b/WebCore/bindings/js/ScriptValue.cpp
index d427cee..6eac102 100644
--- a/WebCore/bindings/js/ScriptValue.cpp
+++ b/WebCore/bindings/js/ScriptValue.cpp
@@ -74,4 +74,11 @@ bool ScriptValue::isUndefined() const
return m_value.get().isUndefined();
}
+bool ScriptValue::isObject() const
+{
+ if (!m_value)
+ return false;
+ return m_value.get().isObject();
+}
+
} // namespace WebCore
diff --git a/WebCore/bindings/js/ScriptValue.h b/WebCore/bindings/js/ScriptValue.h
index 209ce06..19bb693 100644
--- a/WebCore/bindings/js/ScriptValue.h
+++ b/WebCore/bindings/js/ScriptValue.h
@@ -50,6 +50,7 @@ public:
bool isEqual(ScriptState*, const ScriptValue&) const;
bool isNull() const;
bool isUndefined() const;
+ bool isObject() const;
bool hasNoValue() const { return m_value == JSC::JSValue(); }
private:
diff --git a/WebCore/bindings/js/SerializedScriptValue.cpp b/WebCore/bindings/js/SerializedScriptValue.cpp
new file mode 100644
index 0000000..48cd92d
--- /dev/null
+++ b/WebCore/bindings/js/SerializedScriptValue.cpp
@@ -0,0 +1,839 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "config.h"
+#include "SerializedScriptValue.h"
+
+#include <runtime/DateInstance.h>
+#include <runtime/ExceptionHelpers.h>
+#include <runtime/PropertyNameArray.h>
+#include <wtf/HashTraits.h>
+#include <wtf/Vector.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+class SerializedObject : public SharedSerializedData
+{
+public:
+ typedef Vector<RefPtr<StringImpl> > PropertyNameList;
+ typedef Vector<SerializedScriptValueData> ValueList;
+
+ void set(const Identifier& propertyName, const SerializedScriptValueData& value)
+ {
+ ASSERT(m_names.size() == m_values.size());
+ m_names.append(String(propertyName.ustring()).crossThreadString().impl());
+ m_values.append(value);
+ }
+
+ PropertyNameList& names() { return m_names; }
+
+ ValueList& values() { return m_values; }
+
+ static PassRefPtr<SerializedObject> create()
+ {
+ return adoptRef(new SerializedObject);
+ }
+
+ void clear()
+ {
+ m_names.clear();
+ m_values.clear();
+ }
+
+private:
+ SerializedObject() { }
+ PropertyNameList m_names;
+ ValueList m_values;
+};
+
+class SerializedArray : public SharedSerializedData
+{
+ typedef HashMap<unsigned, SerializedScriptValueData, DefaultHash<unsigned>::Hash, WTF::UnsignedWithZeroKeyHashTraits<unsigned> > SparseMap;
+public:
+ void setIndex(unsigned index, const SerializedScriptValueData& value)
+ {
+ ASSERT(index < m_length);
+ if (index == m_compactStorage.size())
+ m_compactStorage.append(value);
+ else
+ m_sparseStorage.set(index, value);
+ }
+
+ bool canDoFastRead(unsigned index) const
+ {
+ ASSERT(index < m_length);
+ return index < m_compactStorage.size();
+ }
+
+ const SerializedScriptValueData& getIndex(unsigned index)
+ {
+ ASSERT(index < m_compactStorage.size());
+ return m_compactStorage[index];
+ }
+
+ SerializedScriptValueData getSparseIndex(unsigned index, bool& hasIndex)
+ {
+ ASSERT(index >= m_compactStorage.size());
+ ASSERT(index < m_length);
+ SparseMap::iterator iter = m_sparseStorage.find(index);
+ if (iter == m_sparseStorage.end()) {
+ hasIndex = false;
+ return SerializedScriptValueData();
+ }
+ hasIndex = true;
+ return iter->second;
+ }
+
+ unsigned length() const
+ {
+ return m_length;
+ }
+
+ static PassRefPtr<SerializedArray> create(unsigned length)
+ {
+ return adoptRef(new SerializedArray(length));
+ }
+
+ void clear()
+ {
+ m_compactStorage.clear();
+ m_sparseStorage.clear();
+ m_length = 0;
+ }
+private:
+ SerializedArray(unsigned length)
+ : m_length(length)
+ {
+ }
+
+ Vector<SerializedScriptValueData> m_compactStorage;
+ SparseMap m_sparseStorage;
+ unsigned m_length;
+};
+
+SerializedScriptValueData::SerializedScriptValueData(RefPtr<SerializedObject> data)
+ : m_type(ObjectType)
+ , m_sharedData(data)
+{
+}
+
+SerializedScriptValueData::SerializedScriptValueData(RefPtr<SerializedArray> data)
+ : m_type(ArrayType)
+ , m_sharedData(data)
+{
+}
+
+SerializedArray* SharedSerializedData::asArray()
+{
+ return static_cast<SerializedArray*>(this);
+}
+
+SerializedObject* SharedSerializedData::asObject()
+{
+ return static_cast<SerializedObject*>(this);
+}
+
+static const unsigned maximumFilterRecursion = 40000;
+enum WalkerState { StateUnknown, ArrayStartState, ArrayStartVisitMember, ArrayEndVisitMember,
+ ObjectStartState, ObjectStartVisitMember, ObjectEndVisitMember };
+template <typename TreeWalker> typename TreeWalker::OutputType walk(TreeWalker& context, typename TreeWalker::InputType in)
+{
+ typedef typename TreeWalker::InputObject InputObject;
+ typedef typename TreeWalker::InputArray InputArray;
+ typedef typename TreeWalker::OutputObject OutputObject;
+ typedef typename TreeWalker::OutputArray OutputArray;
+ typedef typename TreeWalker::InputType InputType;
+ typedef typename TreeWalker::OutputType OutputType;
+ typedef typename TreeWalker::PropertyList PropertyList;
+
+ Vector<uint32_t, 16> indexStack;
+ Vector<uint32_t, 16> lengthStack;
+ Vector<PropertyList, 16> propertyStack;
+ Vector<InputObject, 16> inputObjectStack;
+ Vector<InputArray, 16> inputArrayStack;
+ Vector<OutputObject, 16> outputObjectStack;
+ Vector<OutputArray, 16> outputArrayStack;
+ Vector<WalkerState, 16> stateStack;
+ WalkerState state = StateUnknown;
+ InputType inValue = in;
+ OutputType outValue = context.null();
+
+ unsigned tickCount = context.ticksUntilNextCheck();
+ while (1) {
+ switch (state) {
+ arrayStartState:
+ case ArrayStartState: {
+ ASSERT(context.isArray(inValue));
+ if (inputObjectStack.size() + inputArrayStack.size() > maximumFilterRecursion) {
+ context.throwStackOverflow();
+ return context.null();
+ }
+
+ InputArray inArray = context.asInputArray(inValue);
+ unsigned length = context.length(inArray);
+ OutputArray outArray = context.createOutputArray(length);
+ if (!context.startArray(inArray, outArray))
+ return context.null();
+ inputArrayStack.append(inArray);
+ outputArrayStack.append(outArray);
+ indexStack.append(0);
+ lengthStack.append(length);
+ // fallthrough
+ }
+ arrayStartVisitMember:
+ case ArrayStartVisitMember: {
+ if (!--tickCount) {
+ if (context.didTimeOut()) {
+ context.throwInterruptedException();
+ return context.null();
+ }
+ tickCount = context.ticksUntilNextCheck();
+ }
+
+ InputArray array = inputArrayStack.last();
+ uint32_t index = indexStack.last();
+ if (index == lengthStack.last()) {
+ InputArray inArray = inputArrayStack.last();
+ OutputArray outArray = outputArrayStack.last();
+ context.endArray(inArray, outArray);
+ outValue = outArray;
+ inputArrayStack.removeLast();
+ outputArrayStack.removeLast();
+ indexStack.removeLast();
+ lengthStack.removeLast();
+ break;
+ }
+ if (context.canDoFastRead(array, index))
+ inValue = context.getIndex(array, index);
+ else {
+ bool hasIndex = false;
+ inValue = context.getSparseIndex(array, index, hasIndex);
+ if (!hasIndex) {
+ indexStack.last()++;
+ goto arrayStartVisitMember;
+ }
+ }
+
+ if (OutputType transformed = context.convertIfTerminal(inValue))
+ outValue = transformed;
+ else {
+ stateStack.append(ArrayEndVisitMember);
+ goto stateUnknown;
+ }
+ // fallthrough
+ }
+ case ArrayEndVisitMember: {
+ OutputArray outArray = outputArrayStack.last();
+ context.putProperty(outArray, indexStack.last(), outValue);
+ indexStack.last()++;
+ goto arrayStartVisitMember;
+ }
+ objectStartState:
+ case ObjectStartState: {
+ ASSERT(context.isObject(inValue));
+ if (inputObjectStack.size() + inputArrayStack.size() > maximumFilterRecursion) {
+ context.throwStackOverflow();
+ return context.null();
+ }
+ InputObject inObject = context.asInputObject(inValue);
+ OutputObject outObject = context.createOutputObject();
+ if (!context.startObject(inObject, outObject))
+ return context.null();
+ inputObjectStack.append(inObject);
+ outputObjectStack.append(outObject);
+ indexStack.append(0);
+ context.getPropertyNames(inObject, propertyStack);
+ // fallthrough
+ }
+ objectStartVisitMember:
+ case ObjectStartVisitMember: {
+ if (!--tickCount) {
+ if (context.didTimeOut()) {
+ context.throwInterruptedException();
+ return context.null();
+ }
+ tickCount = context.ticksUntilNextCheck();
+ }
+
+ InputObject object = inputObjectStack.last();
+ uint32_t index = indexStack.last();
+ PropertyList& properties = propertyStack.last();
+ if (index == properties.size()) {
+ InputObject inObject = inputObjectStack.last();
+ OutputObject outObject = outputObjectStack.last();
+ context.endObject(inObject, outObject);
+ outValue = outObject;
+ inputObjectStack.removeLast();
+ outputObjectStack.removeLast();
+ indexStack.removeLast();
+ propertyStack.removeLast();
+ break;
+ }
+ inValue = context.getProperty(object, properties[index], index);
+
+ if (context.shouldTerminate())
+ return context.null();
+
+ if (OutputType transformed = context.convertIfTerminal(inValue))
+ outValue = transformed;
+ else {
+ stateStack.append(ObjectEndVisitMember);
+ goto stateUnknown;
+ }
+ // fallthrough
+ }
+ case ObjectEndVisitMember: {
+ context.putProperty(outputObjectStack.last(), propertyStack.last()[indexStack.last()], outValue);
+ if (context.shouldTerminate())
+ return context.null();
+
+ indexStack.last()++;
+ goto objectStartVisitMember;
+ }
+ stateUnknown:
+ case StateUnknown:
+ if (OutputType transformed = context.convertIfTerminal(inValue)) {
+ outValue = transformed;
+ break;
+ }
+ if (context.isArray(inValue))
+ goto arrayStartState;
+ goto objectStartState;
+ }
+ if (stateStack.isEmpty())
+ break;
+
+ state = stateStack.last();
+ stateStack.removeLast();
+
+ if (!--tickCount) {
+ if (context.didTimeOut()) {
+ context.throwInterruptedException();
+ return context.null();
+ }
+ tickCount = context.ticksUntilNextCheck();
+ }
+ }
+ return outValue;
+}
+
+struct BaseWalker {
+ BaseWalker(ExecState* exec)
+ : m_exec(exec)
+ , m_timeoutChecker(exec->globalData().timeoutChecker)
+ {
+ m_timeoutChecker.reset();
+ }
+ ExecState* m_exec;
+ TimeoutChecker m_timeoutChecker;
+ MarkedArgumentBuffer m_gcBuffer;
+
+ bool shouldTerminate()
+ {
+ return m_exec->hadException();
+ }
+
+ unsigned ticksUntilNextCheck()
+ {
+ return m_timeoutChecker.ticksUntilNextCheck();
+ }
+
+ bool didTimeOut()
+ {
+ return m_timeoutChecker.didTimeOut(m_exec);
+ }
+
+ void throwStackOverflow()
+ {
+ m_exec->setException(createStackOverflowError(m_exec));
+ }
+
+ void throwInterruptedException()
+ {
+ m_exec->setException(createInterruptedExecutionException(&m_exec->globalData()));
+ }
+};
+
+struct SerializingTreeWalker : public BaseWalker {
+ typedef JSValue InputType;
+ typedef JSArray* InputArray;
+ typedef JSObject* InputObject;
+ typedef SerializedScriptValueData OutputType;
+ typedef RefPtr<SerializedArray> OutputArray;
+ typedef RefPtr<SerializedObject> OutputObject;
+ typedef PropertyNameArray PropertyList;
+
+ SerializingTreeWalker(ExecState* exec)
+ : BaseWalker(exec)
+ {
+ }
+
+ OutputType null() { return SerializedScriptValueData(); }
+
+ bool isArray(JSValue value)
+ {
+ if (!value.isObject())
+ return false;
+ JSObject* object = asObject(value);
+ return isJSArray(&m_exec->globalData(), object) || object->inherits(&JSArray::info);
+ }
+
+ bool isObject(JSValue value)
+ {
+ return value.isObject();
+ }
+
+ JSArray* asInputArray(JSValue value)
+ {
+ return asArray(value);
+ }
+
+ JSObject* asInputObject(JSValue value)
+ {
+ return asObject(value);
+ }
+
+ PassRefPtr<SerializedArray> createOutputArray(unsigned length)
+ {
+ return SerializedArray::create(length);
+ }
+
+ PassRefPtr<SerializedObject> createOutputObject()
+ {
+ return SerializedObject::create();
+ }
+
+ uint32_t length(JSValue array)
+ {
+ ASSERT(array.isObject());
+ JSObject* object = asObject(array);
+ return object->get(m_exec, m_exec->propertyNames().length).toUInt32(m_exec);
+ }
+
+ bool canDoFastRead(JSArray* array, unsigned index)
+ {
+ return isJSArray(&m_exec->globalData(), array) && array->canGetIndex(index);
+ }
+
+ JSValue getIndex(JSArray* array, unsigned index)
+ {
+ return array->getIndex(index);
+ }
+
+ JSValue getSparseIndex(JSObject* object, unsigned propertyName, bool& hasIndex)
+ {
+ PropertySlot slot(object);
+ if (object->getOwnPropertySlot(m_exec, propertyName, slot)) {
+ hasIndex = true;
+ return slot.getValue(m_exec, propertyName);
+ }
+ hasIndex = false;
+ return jsNull();
+ }
+
+ JSValue getProperty(JSObject* object, const Identifier& propertyName, unsigned)
+ {
+ PropertySlot slot(object);
+ if (object->getOwnPropertySlot(m_exec, propertyName, slot))
+ return slot.getValue(m_exec, propertyName);
+ return jsNull();
+ }
+
+ SerializedScriptValueData convertIfTerminal(JSValue value)
+ {
+ if (!value.isCell())
+ return SerializedScriptValueData(value);
+
+ if (value.isString())
+ return SerializedScriptValueData(asString(value)->value());
+
+ if (value.isNumber())
+ return SerializedScriptValueData(SerializedScriptValueData::NumberType, value.uncheckedGetNumber());
+
+ if (value.isObject() && asObject(value)->inherits(&DateInstance::info))
+ return SerializedScriptValueData(SerializedScriptValueData::DateType, asDateInstance(value)->internalNumber());
+
+ if (isArray(value))
+ return SerializedScriptValueData();
+
+ CallData unusedData;
+ if (value.isObject() && value.getCallData(unusedData) == CallTypeNone)
+ return SerializedScriptValueData();
+
+ // Any other types are expected to serialize as null.
+ return SerializedScriptValueData(jsNull());
+ }
+
+ void getPropertyNames(JSObject* object, Vector<PropertyNameArray, 16>& propertyStack)
+ {
+ propertyStack.append(PropertyNameArray(m_exec));
+ object->getOwnPropertyNames(m_exec, propertyStack.last());
+ }
+
+ void putProperty(RefPtr<SerializedArray> array, unsigned propertyName, const SerializedScriptValueData& value)
+ {
+ array->setIndex(propertyName, value);
+ }
+
+ void putProperty(RefPtr<SerializedObject> object, const Identifier& propertyName, const SerializedScriptValueData& value)
+ {
+ object->set(propertyName, value);
+ }
+
+ bool startArray(JSArray* inArray, RefPtr<SerializedArray>)
+ {
+ // Cycle detection
+ if (!m_cycleDetector.add(inArray).second) {
+ m_exec->setException(createTypeError(m_exec, "Cannot post cyclic structures."));
+ return false;
+ }
+ m_gcBuffer.append(inArray);
+ return true;
+ }
+
+ void endArray(JSArray* inArray, RefPtr<SerializedArray>)
+ {
+ m_cycleDetector.remove(inArray);
+ m_gcBuffer.removeLast();
+ }
+
+ bool startObject(JSObject* inObject, RefPtr<SerializedObject>)
+ {
+ // Cycle detection
+ if (!m_cycleDetector.add(inObject).second) {
+ m_exec->setException(createTypeError(m_exec, "Cannot post cyclic structures."));
+ return false;
+ }
+ m_gcBuffer.append(inObject);
+ return true;
+ }
+
+ void endObject(JSObject* inObject, RefPtr<SerializedObject>)
+ {
+ m_cycleDetector.remove(inObject);
+ m_gcBuffer.removeLast();
+ }
+
+private:
+ HashSet<JSObject*> m_cycleDetector;
+};
+
+SerializedScriptValueData SerializedScriptValueData::serialize(ExecState* exec, JSValue inValue)
+{
+ SerializingTreeWalker context(exec);
+ return walk<SerializingTreeWalker>(context, inValue);
+}
+
+
+struct DeserializingTreeWalker : public BaseWalker {
+ typedef SerializedScriptValueData InputType;
+ typedef RefPtr<SerializedArray> InputArray;
+ typedef RefPtr<SerializedObject> InputObject;
+ typedef JSValue OutputType;
+ typedef JSArray* OutputArray;
+ typedef JSObject* OutputObject;
+ typedef SerializedObject::PropertyNameList PropertyList;
+
+ DeserializingTreeWalker(ExecState* exec, bool mustCopy)
+ : BaseWalker(exec)
+ , m_mustCopy(mustCopy)
+ {
+ }
+
+ OutputType null() { return jsNull(); }
+
+ bool isArray(const SerializedScriptValueData& value)
+ {
+ return value.type() == SerializedScriptValueData::ArrayType;
+ }
+
+ bool isObject(const SerializedScriptValueData& value)
+ {
+ return value.type() == SerializedScriptValueData::ObjectType;
+ }
+
+ SerializedArray* asInputArray(const SerializedScriptValueData& value)
+ {
+ return value.asArray();
+ }
+
+ SerializedObject* asInputObject(const SerializedScriptValueData& value)
+ {
+ return value.asObject();
+ }
+
+ JSArray* createOutputArray(unsigned length)
+ {
+ JSArray* array = constructEmptyArray(m_exec);
+ array->setLength(length);
+ return array;
+ }
+
+ JSObject* createOutputObject()
+ {
+ return constructEmptyObject(m_exec);
+ }
+
+ uint32_t length(RefPtr<SerializedArray> array)
+ {
+ return array->length();
+ }
+
+ bool canDoFastRead(RefPtr<SerializedArray> array, unsigned index)
+ {
+ return array->canDoFastRead(index);
+ }
+
+ SerializedScriptValueData getIndex(RefPtr<SerializedArray> array, unsigned index)
+ {
+ return array->getIndex(index);
+ }
+
+ SerializedScriptValueData getSparseIndex(RefPtr<SerializedArray> array, unsigned propertyName, bool& hasIndex)
+ {
+ return array->getSparseIndex(propertyName, hasIndex);
+ }
+
+ SerializedScriptValueData getProperty(RefPtr<SerializedObject> object, const RefPtr<StringImpl>& propertyName, unsigned propertyIndex)
+ {
+ ASSERT(object->names()[propertyIndex] == propertyName);
+ UNUSED_PARAM(propertyName);
+ return object->values()[propertyIndex];
+ }
+
+ JSValue convertIfTerminal(SerializedScriptValueData& value)
+ {
+ switch (value.type()) {
+ case SerializedScriptValueData::ArrayType:
+ case SerializedScriptValueData::ObjectType:
+ return JSValue();
+ case SerializedScriptValueData::StringType:
+ return jsString(m_exec, value.asString().crossThreadString());
+ case SerializedScriptValueData::ImmediateType:
+ return value.asImmediate();
+ case SerializedScriptValueData::NumberType:
+ return jsNumber(m_exec, value.asDouble());
+ case SerializedScriptValueData::DateType:
+ return new (m_exec) DateInstance(m_exec, value.asDouble());
+ default:
+ ASSERT_NOT_REACHED();
+ return JSValue();
+ }
+ }
+
+ void getPropertyNames(RefPtr<SerializedObject> object, Vector<SerializedObject::PropertyNameList, 16>& properties)
+ {
+ properties.append(object->names());
+ }
+
+ void putProperty(JSArray* array, unsigned propertyName, JSValue value)
+ {
+ array->put(m_exec, propertyName, value);
+ }
+
+ void putProperty(JSObject* object, const RefPtr<StringImpl> propertyName, JSValue value)
+ {
+ object->putDirect(Identifier(m_exec, String(propertyName)), value);
+ }
+
+ bool startArray(RefPtr<SerializedArray>, JSArray* outArray)
+ {
+ m_gcBuffer.append(outArray);
+ return true;
+ }
+ void endArray(RefPtr<SerializedArray>, JSArray*)
+ {
+ m_gcBuffer.removeLast();
+ }
+ bool startObject(RefPtr<SerializedObject>, JSObject* outObject)
+ {
+ m_gcBuffer.append(outObject);
+ return true;
+ }
+ void endObject(RefPtr<SerializedObject>, JSObject*)
+ {
+ m_gcBuffer.removeLast();
+ }
+
+private:
+ bool m_mustCopy;
+};
+
+JSValue SerializedScriptValueData::deserialize(ExecState* exec, bool mustCopy) const
+{
+ DeserializingTreeWalker context(exec, mustCopy);
+ return walk<DeserializingTreeWalker>(context, *this);
+}
+
+struct TeardownTreeWalker {
+ typedef SerializedScriptValueData InputType;
+ typedef RefPtr<SerializedArray> InputArray;
+ typedef RefPtr<SerializedObject> InputObject;
+ typedef bool OutputType;
+ typedef bool OutputArray;
+ typedef bool OutputObject;
+ typedef SerializedObject::PropertyNameList PropertyList;
+
+ bool shouldTerminate()
+ {
+ return false;
+ }
+
+ unsigned ticksUntilNextCheck()
+ {
+ return 0xFFFFFFFF;
+ }
+
+ bool didTimeOut()
+ {
+ return false;
+ }
+
+ void throwStackOverflow()
+ {
+ }
+
+ void throwInterruptedException()
+ {
+ }
+
+ bool null() { return false; }
+
+ bool isArray(const SerializedScriptValueData& value)
+ {
+ return value.type() == SerializedScriptValueData::ArrayType;
+ }
+
+ bool isObject(const SerializedScriptValueData& value)
+ {
+ return value.type() == SerializedScriptValueData::ObjectType;
+ }
+
+ SerializedArray* asInputArray(const SerializedScriptValueData& value)
+ {
+ return value.asArray();
+ }
+
+ SerializedObject* asInputObject(const SerializedScriptValueData& value)
+ {
+ return value.asObject();
+ }
+
+ bool createOutputArray(unsigned)
+ {
+ return false;
+ }
+
+ bool createOutputObject()
+ {
+ return false;
+ }
+
+ uint32_t length(RefPtr<SerializedArray> array)
+ {
+ return array->length();
+ }
+
+ bool canDoFastRead(RefPtr<SerializedArray> array, unsigned index)
+ {
+ return array->canDoFastRead(index);
+ }
+
+ SerializedScriptValueData getIndex(RefPtr<SerializedArray> array, unsigned index)
+ {
+ return array->getIndex(index);
+ }
+
+ SerializedScriptValueData getSparseIndex(RefPtr<SerializedArray> array, unsigned propertyName, bool& hasIndex)
+ {
+ return array->getSparseIndex(propertyName, hasIndex);
+ }
+
+ SerializedScriptValueData getProperty(RefPtr<SerializedObject> object, const RefPtr<StringImpl>& propertyName, unsigned propertyIndex)
+ {
+ ASSERT(object->names()[propertyIndex] == propertyName);
+ UNUSED_PARAM(propertyName);
+ return object->values()[propertyIndex];
+ }
+
+ bool convertIfTerminal(SerializedScriptValueData& value)
+ {
+ switch (value.type()) {
+ case SerializedScriptValueData::ArrayType:
+ case SerializedScriptValueData::ObjectType:
+ return false;
+ case SerializedScriptValueData::StringType:
+ case SerializedScriptValueData::ImmediateType:
+ case SerializedScriptValueData::NumberType:
+ return true;
+ default:
+ ASSERT_NOT_REACHED();
+ return JSValue();
+ }
+ }
+
+ void getPropertyNames(RefPtr<SerializedObject> object, Vector<SerializedObject::PropertyNameList, 16>& properties)
+ {
+ properties.append(object->names());
+ }
+
+ void putProperty(bool, unsigned, bool)
+ {
+ }
+
+ void putProperty(bool, const RefPtr<StringImpl>&, bool)
+ {
+ }
+
+ bool startArray(RefPtr<SerializedArray>, bool)
+ {
+ return true;
+ }
+ void endArray(RefPtr<SerializedArray> array, bool)
+ {
+ array->clear();
+ }
+ bool startObject(RefPtr<SerializedObject>, bool)
+ {
+ return true;
+ }
+ void endObject(RefPtr<SerializedObject> object, bool)
+ {
+ object->clear();
+ }
+};
+
+void SerializedScriptValueData::tearDownSerializedData()
+{
+ if (m_sharedData && m_sharedData->refCount() > 1)
+ return;
+ TeardownTreeWalker context;
+ walk<TeardownTreeWalker>(context, *this);
+}
+
+}
diff --git a/WebCore/bindings/js/SerializedScriptValue.h b/WebCore/bindings/js/SerializedScriptValue.h
new file mode 100644
index 0000000..f8a126f
--- /dev/null
+++ b/WebCore/bindings/js/SerializedScriptValue.h
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef SerializedScriptValue_h
+#define SerializedScriptValue_h
+
+#include "ScriptValue.h"
+
+namespace WebCore {
+ class SerializedObject;
+ class SerializedArray;
+
+ class SharedSerializedData : public RefCounted<SharedSerializedData> {
+ public:
+ virtual ~SharedSerializedData() { }
+ SerializedArray* asArray();
+ SerializedObject* asObject();
+ };
+
+ class SerializedScriptValue;
+
+ class SerializedScriptValueData {
+ public:
+ enum SerializedType {
+ EmptyType,
+ DateType,
+ NumberType,
+ ImmediateType,
+ ObjectType,
+ ArrayType,
+ StringType
+ };
+
+ SerializedType type() const { return m_type; }
+ static SerializedScriptValueData serialize(JSC::ExecState*, JSC::JSValue);
+ JSC::JSValue deserialize(JSC::ExecState*, bool mustCopy) const;
+
+ ~SerializedScriptValueData()
+ {
+ if (m_sharedData)
+ tearDownSerializedData();
+ }
+
+ SerializedScriptValueData()
+ : m_type(EmptyType)
+ {
+ }
+
+ explicit SerializedScriptValueData(const String& string)
+ : m_type(StringType)
+ , m_string(string.crossThreadString()) // FIXME: Should be able to just share the Rep
+ {
+ }
+
+ explicit SerializedScriptValueData(JSC::JSValue value)
+ : m_type(ImmediateType)
+ {
+ ASSERT(!value.isCell());
+ m_data.m_immediate = JSC::JSValue::encode(value);
+ }
+
+ SerializedScriptValueData(SerializedType type, double value)
+ : m_type(type)
+ {
+ m_data.m_double = value;
+ }
+
+ SerializedScriptValueData(RefPtr<SerializedObject>);
+ SerializedScriptValueData(RefPtr<SerializedArray>);
+
+ JSC::JSValue asImmediate() const
+ {
+ ASSERT(m_type == ImmediateType);
+ return JSC::JSValue::decode(m_data.m_immediate);
+ }
+
+ double asDouble() const
+ {
+ ASSERT(m_type == NumberType || m_type == DateType);
+ return m_data.m_double;
+ }
+
+ String asString() const
+ {
+ ASSERT(m_type == StringType);
+ return m_string;
+ }
+
+ SerializedObject* asObject() const
+ {
+ ASSERT(m_type == ObjectType);
+ ASSERT(m_sharedData);
+ return m_sharedData->asObject();
+ }
+
+ SerializedArray* asArray() const
+ {
+ ASSERT(m_type == ArrayType);
+ ASSERT(m_sharedData);
+ return m_sharedData->asArray();
+ }
+
+ operator bool() const { return m_type != EmptyType; }
+
+ SerializedScriptValueData release()
+ {
+ SerializedScriptValueData result = *this;
+ *this = SerializedScriptValueData();
+ return result;
+ }
+
+ private:
+ void tearDownSerializedData();
+ SerializedType m_type;
+ RefPtr<SharedSerializedData> m_sharedData;
+ String m_string;
+ union {
+ double m_double;
+ JSC::EncodedJSValue m_immediate;
+ } m_data;
+ };
+
+ class SerializedScriptValue : public RefCounted<SerializedScriptValue> {
+ public:
+ static PassRefPtr<SerializedScriptValue> create(JSC::ExecState* exec, JSC::JSValue value)
+ {
+ return adoptRef(new SerializedScriptValue(SerializedScriptValueData::serialize(exec, value)));
+ }
+
+ static PassRefPtr<SerializedScriptValue> create(String string)
+ {
+ return adoptRef(new SerializedScriptValue(SerializedScriptValueData(string)));
+ }
+
+ static PassRefPtr<SerializedScriptValue> create()
+ {
+ return adoptRef(new SerializedScriptValue(SerializedScriptValueData()));
+ }
+
+ PassRefPtr<SerializedScriptValue> release()
+ {
+ PassRefPtr<SerializedScriptValue> result = adoptRef(new SerializedScriptValue(m_value));
+ m_value = SerializedScriptValueData();
+ result->m_mustCopy = true;
+ return result;
+ }
+
+ String toString()
+ {
+ if (m_value.type() != SerializedScriptValueData::StringType)
+ return "";
+ return m_value.asString();
+ }
+
+ JSC::JSValue deserialize(JSC::ExecState* exec)
+ {
+ if (!m_value)
+ return JSC::jsNull();
+ return m_value.deserialize(exec, m_mustCopy);
+ }
+
+ ~SerializedScriptValue() {}
+
+ private:
+ SerializedScriptValue(SerializedScriptValueData value)
+ : m_value(value)
+ , m_mustCopy(false)
+ {
+ }
+
+ SerializedScriptValueData m_value;
+ bool m_mustCopy;
+ };
+}
+
+#endif // SerializedScriptValue_h
diff --git a/WebCore/bindings/objc/DOM.mm b/WebCore/bindings/objc/DOM.mm
index 62bf1de..63a3b2a 100644
--- a/WebCore/bindings/objc/DOM.mm
+++ b/WebCore/bindings/objc/DOM.mm
@@ -29,21 +29,23 @@
#import "DOMInternal.h" // import first to make the private/public trick work
#import "DOM.h"
-#import "DOMRangeInternal.h"
#import "DOMElementInternal.h"
-#import "DOMNodeInternal.h"
#import "DOMHTMLCanvasElement.h"
+#import "DOMNodeInternal.h"
+#import "DOMPrivate.h"
+#import "DOMRangeInternal.h"
#import "Frame.h"
-#import "HTMLNames.h"
#import "HTMLElement.h"
-#import "RenderImage.h"
+#import "HTMLNames.h"
#import "NodeFilter.h"
+#import "RenderImage.h"
#import "WebScriptObjectPrivate.h"
#import <wtf/HashMap.h>
#if ENABLE(SVG_DOM_OBJC_BINDINGS)
#import "DOMSVG.h"
#import "SVGElementInstance.h"
+#import "SVGNames.h"
#endif
using namespace JSC;
@@ -154,9 +156,6 @@ static void createElementClassMap()
addElementClass(SVGNames::circleTag, [DOMSVGCircleElement class]);
addElementClass(SVGNames::clipPathTag, [DOMSVGClipPathElement class]);
addElementClass(SVGNames::cursorTag, [DOMSVGCursorElement class]);
-#if ENABLE(SVG_FONTS)
- addElementClass(SVGNames::definition_srcTag, [DOMSVGDefinitionSrcElement class]);
-#endif
addElementClass(SVGNames::defsTag, [DOMSVGDefsElement class]);
addElementClass(SVGNames::descTag, [DOMSVGDescElement class]);
addElementClass(SVGNames::ellipseTag, [DOMSVGEllipseElement class]);
@@ -359,20 +358,6 @@ id <DOMEventTarget> kit(WebCore::EventTarget* eventTarget)
return renderer->absoluteBoundingBoxRect();
}
-- (NSArray *)textRects
-{
- // FIXME: Could we move this function to WebCore::Node and autogenerate?
- core(self)->document()->updateLayoutIgnorePendingStylesheets();
- if (!core(self)->renderer())
- return nil;
- RefPtr<Range> range = Range::create(core(self)->document());
- WebCore::ExceptionCode ec = 0;
- range->selectNodeContents(core(self), ec);
- Vector<WebCore::IntRect> rects;
- range->textRects(rects);
- return kit(rects);
-}
-
- (NSArray *)lineBoxRects
{
return [self textRects];
@@ -392,6 +377,19 @@ id <DOMEventTarget> kit(WebCore::EventTarget* eventTarget)
return frame->nodeImage(node);
}
+- (NSArray *)textRects
+{
+ // FIXME: Could we move this function to WebCore::Node and autogenerate?
+ core(self)->document()->updateLayoutIgnorePendingStylesheets();
+ if (!core(self)->renderer())
+ return nil;
+ RefPtr<Range> range = Range::create(core(self)->document());
+ WebCore::ExceptionCode ec = 0;
+ range->selectNodeContents(core(self), ec);
+ Vector<WebCore::IntRect> rects;
+ range->textRects(rects);
+ return kit(rects);
+}
@end
@implementation DOMRange (DOMRangeExtensions)
diff --git a/WebCore/bindings/objc/DOMCSS.mm b/WebCore/bindings/objc/DOMCSS.mm
index 0149273..22a9cb2 100644
--- a/WebCore/bindings/objc/DOMCSS.mm
+++ b/WebCore/bindings/objc/DOMCSS.mm
@@ -47,6 +47,7 @@
#import "DOMStyleSheetInternal.h"
#import "DOMWebKitCSSKeyframeRule.h"
#import "DOMWebKitCSSKeyframesRule.h"
+#import "DOMWebKitCSSTransformValue.h"
#if ENABLE(SVG_DOM_OBJC_BINDINGS)
#import "DOMSVGPaint.h"
@@ -102,6 +103,8 @@ Class kitClass(WebCore::CSSValue* impl)
case WebCore::CSSValue::CSS_PRIMITIVE_VALUE:
return [DOMCSSPrimitiveValue class];
case WebCore::CSSValue::CSS_VALUE_LIST:
+ if (impl->isWebKitCSSTransformValue())
+ return [DOMWebKitCSSTransformValue class];
return [DOMCSSValueList class];
case WebCore::CSSValue::CSS_INHERIT:
case WebCore::CSSValue::CSS_INITIAL:
diff --git a/WebCore/bindings/objc/DOMInternal.h b/WebCore/bindings/objc/DOMInternal.h
index 48f5d2f..72f63d2 100644
--- a/WebCore/bindings/objc/DOMInternal.h
+++ b/WebCore/bindings/objc/DOMInternal.h
@@ -61,7 +61,6 @@ namespace WebCore {
// Create an NSMapTable mapping from pointers to ObjC objects held with zeroing weak references.
NSMapTable* createWrapperCache();
-NSMapTable* createWrapperCacheWithIntegerKeys(); // Same, but from integers to ObjC objects.
id createDOMWrapper(JSC::JSObject*, PassRefPtr<JSC::Bindings::RootObject> origin, PassRefPtr<JSC::Bindings::RootObject> current);
diff --git a/WebCore/bindings/objc/DOMInternal.mm b/WebCore/bindings/objc/DOMInternal.mm
index 9b26e59..993a3ad 100644
--- a/WebCore/bindings/objc/DOMInternal.mm
+++ b/WebCore/bindings/objc/DOMInternal.mm
@@ -49,18 +49,6 @@ NSMapTable* createWrapperCache()
#endif
}
-NSMapTable* createWrapperCacheWithIntegerKeys()
-{
-#ifdef BUILDING_ON_TIGER
- return NSCreateMapTable(NSIntMapKeyCallBacks, NSNonRetainedObjectMapValueCallBacks, 0);
-#else
- // NSMapTable with zeroing weak pointers is the recommended way to build caches like this under garbage collection.
- NSPointerFunctionsOptions keyOptions = NSPointerFunctionsOpaqueMemory | NSPointerFunctionsIntegerPersonality;
- NSPointerFunctionsOptions valueOptions = NSPointerFunctionsZeroingWeakMemory | NSPointerFunctionsObjectPersonality;
- return [[NSMapTable alloc] initWithKeyOptions:keyOptions valueOptions:valueOptions capacity:0];
-#endif
-}
-
NSObject* getDOMWrapper(DOMObjectInternal* impl)
{
if (!DOMWrapperCache)
diff --git a/WebCore/bindings/objc/DOMSVG.h b/WebCore/bindings/objc/DOMSVG.h
index f1321d8..cb74544 100644
--- a/WebCore/bindings/objc/DOMSVG.h
+++ b/WebCore/bindings/objc/DOMSVG.h
@@ -50,7 +50,6 @@
#import <WebCore/DOMSVGColor.h>
#import <WebCore/DOMSVGComponentTransferFunctionElement.h>
#import <WebCore/DOMSVGCursorElement.h>
-#import <WebCore/DOMSVGDefinitionSrcElement.h>
#import <WebCore/DOMSVGDefsElement.h>
#import <WebCore/DOMSVGDescElement.h>
#import <WebCore/DOMSVGDocument.h>
diff --git a/WebCore/bindings/objc/ObjCEventListener.h b/WebCore/bindings/objc/ObjCEventListener.h
index 6056b01..434ef45 100644
--- a/WebCore/bindings/objc/ObjCEventListener.h
+++ b/WebCore/bindings/objc/ObjCEventListener.h
@@ -39,13 +39,22 @@ namespace WebCore {
public:
static PassRefPtr<ObjCEventListener> wrap(id <DOMEventListener>);
+ static const ObjCEventListener* cast(const EventListener* listener)
+ {
+ return listener->type() == ObjCEventListenerType
+ ? static_cast<const ObjCEventListener*>(listener)
+ : 0;
+ }
+
+ virtual bool operator==(const EventListener& other);
+
private:
static ObjCEventListener* find(id <DOMEventListener>);
ObjCEventListener(id <DOMEventListener>);
virtual ~ObjCEventListener();
- virtual void handleEvent(Event*, bool isWindowEvent);
+ virtual void handleEvent(ScriptExecutionContext*, Event*);
id <DOMEventListener> m_listener;
};
diff --git a/WebCore/bindings/objc/ObjCEventListener.mm b/WebCore/bindings/objc/ObjCEventListener.mm
index 77c6ad2..d73ac30 100644
--- a/WebCore/bindings/objc/ObjCEventListener.mm
+++ b/WebCore/bindings/objc/ObjCEventListener.mm
@@ -56,7 +56,8 @@ PassRefPtr<ObjCEventListener> ObjCEventListener::wrap(id <DOMEventListener> list
}
ObjCEventListener::ObjCEventListener(id <DOMEventListener> listener)
- : m_listener([listener retain])
+ : EventListener(ObjCEventListenerType)
+ , m_listener([listener retain])
{
ListenerMap* map = listenerMap;
if (!map) {
@@ -72,9 +73,16 @@ ObjCEventListener::~ObjCEventListener()
[m_listener release];
}
-void ObjCEventListener::handleEvent(Event* event, bool)
+void ObjCEventListener::handleEvent(ScriptExecutionContext*, Event* event)
{
[m_listener handleEvent:kit(event)];
}
+bool ObjCEventListener::operator==(const EventListener& listener)
+{
+ if (const ObjCEventListener* objCEventListener = ObjCEventListener::cast(&listener))
+ return m_listener == objCEventListener->m_listener;
+ return false;
+}
+
} // namespace WebCore
diff --git a/WebCore/bindings/scripts/CodeGenerator.pm b/WebCore/bindings/scripts/CodeGenerator.pm
index 341c607..92bd390 100644
--- a/WebCore/bindings/scripts/CodeGenerator.pm
+++ b/WebCore/bindings/scripts/CodeGenerator.pm
@@ -4,6 +4,7 @@
# Copyright (C) 2005 Nikolas Zimmermann <wildfox@kde.org>
# Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
# Copyright (C) 2007 Apple Inc. All rights reserved.
+# Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
@@ -23,12 +24,16 @@
package CodeGenerator;
+use File::Find;
+
my $useDocument = "";
my $useGenerator = "";
my $useOutputDir = "";
my $useDirectories = "";
my $useLayerOnTop = 0;
my $preprocessor;
+my $writeDependencies = 0;
+my $defines = "";
my $codeGenerator = 0;
@@ -54,12 +59,8 @@ my %svgAnimatedTypeHash = ("SVGAnimatedAngle" => 1, "SVGAnimatedBoolean" => 1,
"SVGAnimatedRect" => 1, "SVGAnimatedString" => 1,
"SVGAnimatedTransformList" => 1);
-# Helpers for 'ScanDirectory'
-my $endCondition = 0;
-my $foundFilename = "";
-my @foundFilenames = ();
-my $ignoreParent = 1;
-my $defines = "";
+# Cache of IDL file pathnames.
+my $idlFiles;
# Default constructor
sub new
@@ -72,6 +73,7 @@ sub new
$useOutputDir = shift;
$useLayerOnTop = shift;
$preprocessor = shift;
+ $writeDependencies = shift;
bless($reference, $object);
return $reference;
@@ -95,7 +97,7 @@ sub ProcessDocument
# Dynamically load external code generation perl module
require $ifaceName . ".pm";
- $codeGenerator = $ifaceName->new($object, $useOutputDir, $useLayerOnTop, $preprocessor);
+ $codeGenerator = $ifaceName->new($object, $useOutputDir, $useLayerOnTop, $preprocessor, $writeDependencies);
unless (defined($codeGenerator)) {
my $classes = $useDocument->classes;
foreach my $class (@$classes) {
@@ -116,100 +118,83 @@ sub ProcessDocument
$codeGenerator->finish();
}
-# Necessary for V8 bindings to determine whether an interface is descendant from Node.
-# Node descendants are treated differently by DOMMap and this allows inferring the
-# type statically. See more at the original change: http://codereview.chromium.org/3195.
-# FIXME: Figure out a way to eliminate this JS bindings dichotomy.
-sub FindParentsRecursively
+sub ForAllParents
{
my $object = shift;
my $dataNode = shift;
- my @parents = ($dataNode->name);
- foreach (@{$dataNode->parents}) {
- my $interface = $object->StripModule($_);
-
- $endCondition = 0;
- $foundFilename = "";
- foreach (@{$useDirectories}) {
- $object->ScanDirectory("$interface.idl", $_, $_, 0) if ($foundFilename eq "");
- }
+ my $beforeRecursion = shift;
+ my $afterRecursion = shift;
+ my $parentsOnly = shift;
- if ($foundFilename ne "") {
- print " | |> Parsing parent IDL \"$foundFilename\" for interface \"$interface\"\n" if $verbose;
+ my $recurse;
+ $recurse = sub {
+ my $interface = shift;
- # Step #2: Parse the found IDL file (in quiet mode).
- my $parser = IDLParser->new(1);
- my $document = $parser->Parse($foundFilename, $defines, $preprocessor, 1);
+ for (@{$interface->parents}) {
+ my $interfaceName = $object->StripModule($_);
+ my $parentInterface = $object->ParseInterface($interfaceName, $parentsOnly);
- foreach my $class (@{$document->classes}) {
- @parents = (@parents, FindParentsRecursively($object, $class));
+ if ($beforeRecursion) {
+ &$beforeRecursion($parentInterface) eq 'prune' and next;
}
- } else {
- die("Could NOT find specified parent interface \"$interface\"!\n")
+ &$recurse($parentInterface);
+ &$afterRecursion($parentInterface) if $afterRecursion;
}
- }
- return @parents;
+ };
+
+ &$recurse($dataNode);
}
sub AddMethodsConstantsAndAttributesFromParentClasses
{
- # For the passed interface, recursively parse all parent
- # IDLs in order to find out all inherited properties/methods.
+ # Add to $dataNode all of its inherited interface members, except for those
+ # inherited through $dataNode's first listed parent. If an array reference
+ # is passed in as $parents, the names of all ancestor interfaces visited
+ # will be appended to the array. If $collectDirectParents is true, then
+ # even the names of $dataNode's first listed parent and its ancestors will
+ # be appended to $parents.
my $object = shift;
my $dataNode = shift;
+ my $parents = shift;
+ my $collectDirectParents = shift;
- my @parents = @{$dataNode->parents};
- my $parentsMax = @{$dataNode->parents};
+ my $first = 1;
- my $constantsRef = $dataNode->constants;
- my $functionsRef = $dataNode->functions;
- my $attributesRef = $dataNode->attributes;
+ $object->ForAllParents($dataNode, sub {
+ my $interface = shift;
- foreach (@{$dataNode->parents}) {
- if ($ignoreParent) {
+ if ($first) {
# Ignore first parent class, already handled by the generation itself.
- $ignoreParent = 0;
- next;
- }
-
- my $interface = $object->StripModule($_);
-
- # Step #1: Find the IDL file associated with 'interface'
- $endCondition = 0;
- $foundFilename = "";
+ $first = 0;
+
+ if ($collectDirectParents) {
+ # Just collect the names of the direct ancestor interfaces,
+ # if necessary.
+ push(@$parents, $interface->name);
+ $object->ForAllParents($interface, sub {
+ my $interface = shift;
+ push(@$parents, $interface->name);
+ }, undef, 1);
+ }
- foreach (@{$useDirectories}) {
- $object->ScanDirectory("$interface.idl", $_, $_, 0) if ($foundFilename eq "");
+ # Prune the recursion here.
+ return 'prune';
}
- if ($foundFilename ne "") {
- print " | |> Parsing parent IDL \"$foundFilename\" for interface \"$interface\"\n" if $verbose;
-
- # Step #2: Parse the found IDL file (in quiet mode).
- my $parser = IDLParser->new(1);
- my $document = $parser->Parse($foundFilename, $defines, $preprocessor);
+ # Collect the name of this additional parent.
+ push(@$parents, $interface->name) if $parents;
- foreach my $class (@{$document->classes}) {
- # Step #3: Enter recursive parent search
- AddMethodsConstantsAndAttributesFromParentClasses($object, $class);
+ print " | |> -> Inheriting "
+ . @{$interface->constants} . " constants, "
+ . @{$interface->functions} . " functions, "
+ . @{$interface->attributes} . " attributes...\n | |>\n" if $verbose;
- # Step #4: Collect constants & functions & attributes of this parent-class
- my $constantsMax = @{$class->constants};
- my $functionsMax = @{$class->functions};
- my $attributesMax = @{$class->attributes};
-
- print " | |> -> Inheriting $constantsMax constants, $functionsMax functions, $attributesMax attributes...\n | |>\n" if $verbose;
-
- # Step #5: Concatenate data
- push(@$constantsRef, $_) foreach (@{$class->constants});
- push(@$functionsRef, $_) foreach (@{$class->functions});
- push(@$attributesRef, $_) foreach (@{$class->attributes});
- }
- } else {
- die("Could NOT find specified parent interface \"$interface\"!\n");
- }
- }
+ # Add this parent's members to $dataNode.
+ push(@{$dataNode->constants}, @{$interface->constants});
+ push(@{$dataNode->functions}, @{$interface->functions});
+ push(@{$dataNode->attributes}, @{$interface->attributes});
+ });
}
sub GetMethodsAndAttributesFromParentClasses
@@ -220,76 +205,67 @@ sub GetMethodsAndAttributesFromParentClasses
my $object = shift;
my $dataNode = shift;
- my @parents = @{$dataNode->parents};
-
- return if @{$dataNode->parents} == 0;
-
my @parentList = ();
- foreach (@{$dataNode->parents}) {
- my $interface = $object->StripModule($_);
+ $object->ForAllParents($dataNode, undef, sub {
+ my $interface = shift;
- # Step #1: Find the IDL file associated with 'interface'
- $endCondition = 0;
- $foundFilename = "";
+ my $hash = {
+ "name" => $interface->name,
+ "functions" => $interface->functions,
+ "attributes" => $interface->attributes
+ };
- foreach (@{$useDirectories}) {
- $object->ScanDirectory("${interface}.idl", $_, $_, 0) if $foundFilename eq "";
- }
-
- die("Could NOT find specified parent interface \"$interface\"!\n") if $foundFilename eq "";
-
- print " | |> Parsing parent IDL \"$foundFilename\" for interface \"$interface\"\n" if $verbose;
+ unshift(@parentList, $hash);
+ });
- # Step #2: Parse the found IDL file (in quiet mode).
- my $parser = IDLParser->new(1);
- my $document = $parser->Parse($foundFilename, $defines);
+ return @parentList;
+}
- foreach my $class (@{$document->classes}) {
- # Step #3: Enter recursive parent search
- push(@parentList, GetMethodsAndAttributesFromParentClasses($object, $class));
+sub IDLFileForInterface
+{
+ my $object = shift;
+ my $interfaceName = shift;
- # Step #4: Collect constants & functions & attributes of this parent-class
+ unless ($idlFiles) {
+ my $sourceRoot = $ENV{SOURCE_ROOT};
+ my @directories = map { $_ = "$sourceRoot/$_" if $sourceRoot && -d "$sourceRoot/$_"; $_ } @$useDirectories;
- # print " | |> -> Inheriting $functionsMax functions amd $attributesMax attributes...\n | |>\n" if $verbose;
- my $hash = {
- "name" => $class->name,
- "functions" => $class->functions,
- "attributes" => $class->attributes
- };
+ $idlFiles = { };
- # Step #5: Concatenate data
- unshift(@parentList, $hash);
- }
+ my $wanted = sub {
+ $idlFiles->{$1} = $File::Find::name if /^([A-Z].*)\.idl$/;
+ $File::Find::prune = 1 if /^\../;
+ };
+ find($wanted, @directories);
}
- return @parentList;
+ return $idlFiles->{$interfaceName};
}
sub ParseInterface
{
- my ($object, $interfaceName) = @_;
+ my $object = shift;
+ my $interfaceName = shift;
+ my $parentsOnly = shift;
- # Step #1: Find the IDL file associated with 'interface'
- $endCondition = 0;
- $foundFilename = "";
+ return undef if $interfaceName eq 'Object';
- foreach (@{$useDirectories}) {
- $object->ScanDirectory("${interfaceName}.idl", $_, $_, 0) if $foundFilename eq "";
- }
- die "Could NOT find specified parent interface \"$interfaceName\"!\n" if $foundFilename eq "";
+ # Step #1: Find the IDL file associated with 'interface'
+ my $filename = $object->IDLFileForInterface($interfaceName)
+ or die("Could NOT find IDL file for interface \"$interfaceName\"!\n");
- print " | |> Parsing parent IDL \"$foundFilename\" for interface \"$interfaceName\"\n" if $verbose;
+ print " | |> Parsing parent IDL \"$filename\" for interface \"$interfaceName\"\n" if $verbose;
# Step #2: Parse the found IDL file (in quiet mode).
my $parser = IDLParser->new(1);
- my $document = $parser->Parse($foundFilename, $defines);
+ my $document = $parser->Parse($filename, $defines, $preprocessor, $parentsOnly);
foreach my $interface (@{$document->classes}) {
return $interface if $interface->name eq $interfaceName;
}
- die "Interface definition not found";
+ die("Could NOT find interface definition for $interface in $filename");
}
# Helpers for all CodeGenerator***.pm modules
@@ -348,56 +324,6 @@ sub IsSVGAnimatedType
return 0;
}
-# Internal Helper
-sub ScanDirectory
-{
- my $object = shift;
-
- my $interface = shift;
- my $directory = shift;
- my $useDirectory = shift;
- my $reportAllFiles = shift;
-
- return if ($endCondition eq 1) and ($reportAllFiles eq 0);
-
- my $sourceRoot = $ENV{SOURCE_ROOT};
- my $thisDir = $sourceRoot ? "$sourceRoot/$directory" : $directory;
-
- if (!opendir(DIR, $thisDir)) {
- opendir(DIR, $directory) or die "[ERROR] Can't open directory $thisDir or $directory: \"$!\"\n";
- $thisDir = $directory;
- }
-
- my @names = readdir(DIR) or die "[ERROR] Cant't read directory $thisDir \"$!\"\n";
- closedir(DIR);
-
- foreach my $name (@names) {
- # Skip if we already found the right file or
- # if we encounter 'exotic' stuff (ie. '.', '..', '.svn')
- next if ($endCondition eq 1) or ($name =~ /^\./);
-
- # Recurisvely enter directory
- if (-d "$thisDir/$name") {
- $object->ScanDirectory($interface, "$directory/$name", $useDirectory, $reportAllFiles);
- next;
- }
-
- # Check wheter we found the desired file
- my $condition = ($name eq $interface);
- $condition = 1 if ($interface eq "allidls") and ($name =~ /\.idl$/);
-
- if ($condition) {
- $foundFilename = "$thisDir/$name";
-
- if ($reportAllFiles eq 0) {
- $endCondition = 1;
- } else {
- push(@foundFilenames, $foundFilename);
- }
- }
- }
-}
-
# Uppercase the first letter while respecting WebKit style guidelines.
# E.g., xmlEncoding becomes XMLEncoding, but xmlllang becomes Xmllang.
sub WK_ucfirst
diff --git a/WebCore/bindings/scripts/CodeGeneratorCOM.pm b/WebCore/bindings/scripts/CodeGeneratorCOM.pm
index 6641305..4d5cb96 100644
--- a/WebCore/bindings/scripts/CodeGeneratorCOM.pm
+++ b/WebCore/bindings/scripts/CodeGeneratorCOM.pm
@@ -326,9 +326,8 @@ sub AddIncludesForTypeInCPPImplementation
sub GetAdditionalInterfaces
{
+ # This function does nothing, but it stays here for future multiple inheritance support.
my $type = $codeGenerator->StripModule(shift);
-
- return ("EventTarget") if $type eq "Node";
return ();
}
diff --git a/WebCore/bindings/scripts/CodeGeneratorJS.pm b/WebCore/bindings/scripts/CodeGeneratorJS.pm
index 1918aef..095c75f 100644
--- a/WebCore/bindings/scripts/CodeGeneratorJS.pm
+++ b/WebCore/bindings/scripts/CodeGeneratorJS.pm
@@ -4,6 +4,7 @@
# Copyright (C) 2006, 2007 Samuel Weinig <sam@webkit.org>
# Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org>
# Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+# Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
@@ -26,6 +27,7 @@ use File::stat;
my $module = "";
my $outputDir = "";
+my $writeDependencies = 0;
my @headerContentHeader = ();
my @headerContent = ();
@@ -34,6 +36,7 @@ my %headerIncludes = ();
my @implContentHeader = ();
my @implContent = ();
my %implIncludes = ();
+my @depsContent = ();
# Default .h template
my $headerTemplate = << "EOF";
@@ -66,6 +69,9 @@ sub new
$codeGenerator = shift;
$outputDir = shift;
+ shift; # $useLayerOnTop
+ shift; # $preprocessor
+ $writeDependencies = shift;
bless($reference, $object);
return $reference;
@@ -100,9 +106,16 @@ sub GenerateInterface
# Open files for writing
my $headerFileName = "$outputDir/JS$name.h";
my $implFileName = "$outputDir/JS$name.cpp";
+ my $depsFileName = "$outputDir/JS$name.dep";
+
+ # Remove old dependency file.
+ unlink($depsFileName);
open($IMPL, ">$implFileName") || die "Couldn't open file $implFileName";
open($HEADER, ">$headerFileName") || die "Couldn't open file $headerFileName";
+ if (@depsContent) {
+ open($DEPS, ">$depsFileName") || die "Couldn't open file $depsFileName";
+ }
}
# Params: 'idlDocument' struct
@@ -300,11 +313,11 @@ sub GenerateGetOwnPropertySlotBody
&$manualLookupGetterGeneration();
}
- if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}) {
+ if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
push(@getOwnPropertySlotImpl, " bool ok;\n");
push(@getOwnPropertySlotImpl, " unsigned index = propertyName.toUInt32(&ok, false);\n");
push(@getOwnPropertySlotImpl, " if (ok && index < static_cast<$implClassName*>(impl())->length()) {\n");
- if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"}) {
+ if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
push(@getOwnPropertySlotImpl, " slot.setValue(getByIndex(exec, index));\n");
} else {
push(@getOwnPropertySlotImpl, " slot.setCustomIndex(this, index, indexGetter);\n");
@@ -348,6 +361,99 @@ sub GenerateGetOwnPropertySlotBody
return @getOwnPropertySlotImpl;
}
+sub GenerateGetOwnPropertyDescriptorBody
+{
+ my ($dataNode, $interfaceName, $className, $implClassName, $hasAttributes, $inlined) = @_;
+
+ my $namespaceMaybe = ($inlined ? "JSC::" : "");
+
+ my @getOwnPropertyDescriptorImpl = ();
+
+ if ($interfaceName eq "NamedNodeMap" or $interfaceName eq "HTMLCollection") {
+ push(@getOwnPropertyDescriptorImpl, " ${namespaceMaybe}JSValue proto = prototype();\n");
+ push(@getOwnPropertyDescriptorImpl, " if (proto.isObject() && static_cast<${namespaceMaybe}JSObject*>(asObject(proto))->hasProperty(exec, propertyName))\n");
+ push(@getOwnPropertyDescriptorImpl, " return false;\n\n");
+ }
+
+ my $manualLookupGetterGeneration = sub {
+ my $requiresManualLookup = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasNameGetter"};
+ if ($requiresManualLookup) {
+ push(@getOwnPropertyDescriptorImpl, " const ${namespaceMaybe}HashEntry* entry = ${className}Table.entry(exec, propertyName);\n");
+ push(@getOwnPropertyDescriptorImpl, " if (entry) {\n");
+ push(@getOwnPropertyDescriptorImpl, " PropertySlot slot;\n");
+ push(@getOwnPropertyDescriptorImpl, " slot.setCustom(this, entry->propertyGetter());\n");
+ push(@getOwnPropertyDescriptorImpl, " descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());\n");
+ push(@getOwnPropertyDescriptorImpl, " return true;\n");
+ push(@getOwnPropertyDescriptorImpl, " }\n");
+ }
+ };
+
+ if (!$dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
+ &$manualLookupGetterGeneration();
+ }
+
+ if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
+ push(@getOwnPropertyDescriptorImpl, " bool ok;\n");
+ push(@getOwnPropertyDescriptorImpl, " unsigned index = propertyName.toUInt32(&ok, false);\n");
+ push(@getOwnPropertyDescriptorImpl, " if (ok && index < static_cast<$implClassName*>(impl())->length()) {\n");
+ if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
+ # Assume that if there's a setter, the index will be writable
+ if ($dataNode->extendedAttributes->{"HasIndexSetter"} || $dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {
+ push(@getOwnPropertyDescriptorImpl, " descriptor.setDescriptor(getByIndex(exec, index), ${namespaceMaybe}DontDelete);\n");
+ } else {
+ push(@getOwnPropertyDescriptorImpl, " descriptor.setDescriptor(getByIndex(exec, index), ${namespaceMaybe}DontDelete | ${namespaceMaybe}ReadOnly);\n");
+ }
+ } else {
+ push(@getOwnPropertyDescriptorImpl, " ${namespaceMaybe}PropertySlot slot;\n");
+ push(@getOwnPropertyDescriptorImpl, " slot.setCustomIndex(this, index, indexGetter);\n");
+ # Assume that if there's a setter, the index will be writable
+ if ($dataNode->extendedAttributes->{"HasIndexSetter"} || $dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {
+ push(@getOwnPropertyDescriptorImpl, " descriptor.setDescriptor(slot.getValue(exec, propertyName), ${namespaceMaybe}DontDelete);\n");
+ } else {
+ push(@getOwnPropertyDescriptorImpl, " descriptor.setDescriptor(slot.getValue(exec, propertyName), ${namespaceMaybe}DontDelete | ${namespaceMaybe}ReadOnly);\n");
+ }
+ }
+ push(@getOwnPropertyDescriptorImpl, " return true;\n");
+ push(@getOwnPropertyDescriptorImpl, " }\n");
+ }
+
+ if ($dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
+ push(@getOwnPropertyDescriptorImpl, " if (canGetItemsForName(exec, static_cast<$implClassName*>(impl()), propertyName)) {\n");
+ push(@getOwnPropertyDescriptorImpl, " ${namespaceMaybe}PropertySlot slot;\n");
+ push(@getOwnPropertyDescriptorImpl, " slot.setCustom(this, nameGetter);\n");
+ push(@getOwnPropertyDescriptorImpl, " descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);\n");
+ push(@getOwnPropertyDescriptorImpl, " return true;\n");
+ push(@getOwnPropertyDescriptorImpl, " }\n");
+ if ($inlined) {
+ $headerIncludes{"AtomicString.h"} = 1;
+ } else {
+ $implIncludes{"AtomicString.h"} = 1;
+ }
+ }
+
+ if ($dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
+ &$manualLookupGetterGeneration();
+ }
+
+ if ($dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"}) {
+ push(@getOwnPropertyDescriptorImpl, " if (getOwnPropertyDescriptorDelegate(exec, propertyName, descriptor))\n");
+ push(@getOwnPropertyDescriptorImpl, " return true;\n");
+ }
+
+ if ($hasAttributes) {
+ if ($inlined) {
+ die "Cannot inline if NoStaticTables is set." if ($dataNode->extendedAttributes->{"NoStaticTables"});
+ push(@getOwnPropertyDescriptorImpl, " return ${namespaceMaybe}getStaticValueDescriptor<$className, Base>(exec, s_info.staticPropHashTable, this, propertyName, descriptor);\n");
+ } else {
+ push(@getOwnPropertyDescriptorImpl, " return ${namespaceMaybe}getStaticValueDescriptor<$className, Base>(exec, " . hashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, descriptor);\n");
+ }
+ } else {
+ push(@getOwnPropertyDescriptorImpl, " return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);\n");
+ }
+
+ return @getOwnPropertyDescriptorImpl;
+}
+
sub GenerateHeader
{
my $object = shift;
@@ -356,11 +462,12 @@ sub GenerateHeader
my $interfaceName = $dataNode->name;
my $className = "JS$interfaceName";
my $implClassName = $interfaceName;
+ my @ancestorInterfaceNames = ();
# We only support multiple parents with SVG (for now).
if (@{$dataNode->parents} > 1) {
die "A class can't have more than one parent" unless $interfaceName =~ /SVG/;
- $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode);
+ $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode, \@ancestorInterfaceNames);
}
my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};
@@ -369,7 +476,9 @@ sub GenerateHeader
my $parentClassName = GetParentClassName($dataNode);
my $conditional = $dataNode->extendedAttributes->{"Conditional"};
my $needsSVGContext = IsSVGTypeNeedingContextParameter($interfaceName);
-
+ my $eventTarget = $dataNode->extendedAttributes->{"EventTarget"};
+ my $needsMarkChildren = $dataNode->extendedAttributes->{"CustomMarkFunction"} || $dataNode->extendedAttributes->{"EventTarget"};
+
# - Add default header template
@headerContentHeader = split("\r", $headerTemplate);
@@ -431,17 +540,17 @@ sub GenerateHeader
# Constructor
if ($interfaceName eq "DOMWindow") {
- push(@headerContent, " $className(PassRefPtr<JSC::Structure>, PassRefPtr<$implType>, JSDOMWindowShell*);\n");
+ push(@headerContent, " $className(NonNullPassRefPtr<JSC::Structure>, PassRefPtr<$implType>, JSDOMWindowShell*);\n");
} elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) {
- push(@headerContent, " $className(PassRefPtr<JSC::Structure>, PassRefPtr<$implType>);\n");
+ push(@headerContent, " $className(NonNullPassRefPtr<JSC::Structure>, PassRefPtr<$implType>);\n");
} elsif (IsSVGTypeNeedingContextParameter($implClassName)) {
- push(@headerContent, " $className(PassRefPtr<JSC::Structure>, JSDOMGlobalObject*, PassRefPtr<$implType>, SVGElement* context);\n");
+ push(@headerContent, " $className(NonNullPassRefPtr<JSC::Structure>, JSDOMGlobalObject*, PassRefPtr<$implType>, SVGElement* context);\n");
} else {
- push(@headerContent, " $className(PassRefPtr<JSC::Structure>, JSDOMGlobalObject*, PassRefPtr<$implType>);\n");
+ push(@headerContent, " $className(NonNullPassRefPtr<JSC::Structure>, JSDOMGlobalObject*, PassRefPtr<$implType>);\n");
}
# Destructor
- push(@headerContent, " virtual ~$className();\n") if (!$hasParent or $interfaceName eq "Document" or $interfaceName eq "DOMWindow");
+ push(@headerContent, " virtual ~$className();\n") if (!$hasParent or $eventTarget or $interfaceName eq "Document" or $interfaceName eq "DOMWindow");
# Prototype
push(@headerContent, " static JSC::JSObject* createPrototype(JSC::ExecState*, JSC::JSGlobalObject*);\n") unless ($dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"});
@@ -452,6 +561,7 @@ sub GenerateHeader
|| $dataNode->extendedAttributes->{"GenerateConstructor"}
|| $dataNode->extendedAttributes->{"HasIndexGetter"}
|| $dataNode->extendedAttributes->{"HasCustomIndexGetter"}
+ || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}
|| $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}
|| $dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"}
|| $dataNode->extendedAttributes->{"HasNameGetter"}
@@ -460,8 +570,10 @@ sub GenerateHeader
# Getters
if ($hasGetter) {
push(@headerContent, " virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&);\n");
- push(@headerContent, " virtual bool getOwnPropertySlot(JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&);\n") if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}) && !$dataNode->extendedAttributes->{"HasOverridingNameGetter"};
+ push(@headerContent, " virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&);\n");
+ push(@headerContent, " virtual bool getOwnPropertySlot(JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&);\n") if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) && !$dataNode->extendedAttributes->{"HasOverridingNameGetter"};
push(@headerContent, " bool getOwnPropertySlotDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n") if $dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"};
+ push(@headerContent, " bool getOwnPropertyDescriptorDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&);\n") if $dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"};
}
# Check if we have any writable properties
@@ -503,8 +615,8 @@ sub GenerateHeader
" }\n\n");
}
- # Custom mark function
- push(@headerContent, " virtual void markChildren(JSC::MarkStack&);\n\n") if $dataNode->extendedAttributes->{"CustomMarkFunction"};
+ # markChildren function
+ push(@headerContent, " virtual void markChildren(JSC::MarkStack&);\n\n") if $needsMarkChildren;
# Custom pushEventHandlerScope function
push(@headerContent, " virtual void pushEventHandlerScope(JSC::ExecState*, JSC::ScopeChain&) const;\n\n") if $dataNode->extendedAttributes->{"CustomPushEventHandlerScope"};
@@ -515,17 +627,23 @@ sub GenerateHeader
# Custom deleteProperty function
push(@headerContent, " virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier&);\n") if $dataNode->extendedAttributes->{"CustomDeleteProperty"};
- # Custom getPropertyNames function
- push(@headerContent, " virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&);\n") if ($dataNode->extendedAttributes->{"CustomGetPropertyNames"} || $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"});
+ # Custom getPropertyNames function exists on DOMWindow
+ push(@headerContent, " virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&);\n") if $interfaceName eq "DOMWindow";
+
+ # Custom defineProperty function exists on DOMWindow
+ push(@headerContent, " virtual bool defineOwnProperty(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&, bool shouldThrow);\n") if $interfaceName eq "DOMWindow";
+
+ # Custom getOwnPropertyNames function
+ push(@headerContent, " virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&);\n") if ($dataNode->extendedAttributes->{"CustomGetPropertyNames"} || $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"});
# Custom getPropertyAttributes function
push(@headerContent, " virtual bool getPropertyAttributes(JSC::ExecState*, const JSC::Identifier&, unsigned& attributes) const;\n") if $dataNode->extendedAttributes->{"CustomGetPropertyAttributes"};
# Custom defineGetter function
- push(@headerContent, " virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction);\n") if $dataNode->extendedAttributes->{"CustomDefineGetter"};
+ push(@headerContent, " virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction, unsigned attributes);\n") if $dataNode->extendedAttributes->{"CustomDefineGetter"};
# Custom defineSetter function
- push(@headerContent, " virtual void defineSetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction);\n") if $dataNode->extendedAttributes->{"CustomDefineSetter"};
+ push(@headerContent, " virtual void defineSetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction, unsigned attributes);\n") if $dataNode->extendedAttributes->{"CustomDefineSetter"};
# Custom lookupGetter function
push(@headerContent, " virtual JSC::JSValue lookupGetter(JSC::ExecState*, const JSC::Identifier& propertyName);\n") if $dataNode->extendedAttributes->{"CustomLookupGetter"};
@@ -599,7 +717,7 @@ sub GenerateHeader
if ($dataNode->extendedAttributes->{"HasIndexGetter"}) {
push(@headerContent, " static JSC::JSValue indexGetter(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&);\n");
}
- if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"}) {
+ if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
push(@headerContent, " JSC::JSValue getByIndex(JSC::ExecState*, unsigned index);\n");
}
@@ -621,6 +739,10 @@ sub GenerateHeader
push(@headerContent, "{\n");
push(@headerContent, GenerateGetOwnPropertySlotBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 1));
push(@headerContent, "}\n\n");
+ push(@headerContent, "ALWAYS_INLINE bool ${className}::getOwnPropertyDescriptor(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::PropertyDescriptor& descriptor)\n");
+ push(@headerContent, "{\n");
+ push(@headerContent, GenerateGetOwnPropertyDescriptorBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 1));
+ push(@headerContent, "}\n\n");
}
if (!$hasParent || $dataNode->extendedAttributes->{"GenerateToJS"} || $dataNode->extendedAttributes->{"CustomToJS"}) {
@@ -662,11 +784,19 @@ sub GenerateHeader
push(@headerContent, " static const JSC::ClassInfo s_info;\n");
if ($numFunctions > 0 || $numConstants > 0 || $dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}) {
push(@headerContent, " virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n");
+ push(@headerContent, " virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&);\n");
push(@headerContent, " bool getOwnPropertySlotDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n") if $dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"};
+ push(@headerContent, " bool getOwnPropertyDescriptorDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&);\n") if $dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"};
push(@headerContent,
" static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype)\n" .
" {\n" .
+ " return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType" . ($needsMarkChildren ? "" : ", JSC::HasDefaultMark") . "));\n" .
+ " }\n");
+ } elsif ($dataNode->extendedAttributes->{"CustomMarkFunction"}) {
+ push(@headerContent,
+ " static PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype)\n" .
+ " {\n" .
" return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType));\n" .
" }\n");
}
@@ -676,9 +806,9 @@ sub GenerateHeader
}
# Custom defineGetter function
- push(@headerContent, " virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction);\n") if $dataNode->extendedAttributes->{"CustomPrototypeDefineGetter"};
+ push(@headerContent, " virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction, unsigned attributes);\n") if $dataNode->extendedAttributes->{"CustomPrototypeDefineGetter"};
- push(@headerContent, " ${className}Prototype(PassRefPtr<JSC::Structure> structure) : JSC::JSObject(structure) { }\n");
+ push(@headerContent, " ${className}Prototype(NonNullPassRefPtr<JSC::Structure> structure) : JSC::JSObject(structure) { }\n");
push(@headerContent, "};\n\n");
@@ -718,6 +848,12 @@ sub GenerateHeader
push(@headerContent, "\n} // namespace WebCore\n\n");
push(@headerContent, "#endif // ${conditionalString}\n\n") if $conditional;
push(@headerContent, "#endif\n");
+
+ # - Generate dependencies.
+ if ($writeDependencies && @ancestorInterfaceNames) {
+ push(@depsContent, "$className.h : ", join(" ", map { "$_.idl" } @ancestorInterfaceNames), "\n");
+ push(@depsContent, map { "$_.idl :\n" } @ancestorInterfaceNames);
+ }
}
sub GenerateImplementation
@@ -734,6 +870,8 @@ sub GenerateImplementation
my $parentClassName = GetParentClassName($dataNode);
my $conditional = $dataNode->extendedAttributes->{"Conditional"};
my $visibleClassName = GetVisibleClassName($interfaceName);
+ my $eventTarget = $dataNode->extendedAttributes->{"EventTarget"};
+ my $needsMarkChildren = $dataNode->extendedAttributes->{"CustomMarkFunction"} || $dataNode->extendedAttributes->{"EventTarget"};
# - Add default header template
@implContentHeader = split("\r", $headerTemplate);
@@ -749,7 +887,7 @@ sub GenerateImplementation
AddIncludesForSVGAnimatedType($interfaceName) if $className =~ /^JSSVGAnimated/;
$implIncludes{"<wtf/GetPtr.h>"} = 1;
- $implIncludes{"<runtime/PropertyNameArray.h>"} = 1 if $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"};
+ $implIncludes{"<runtime/PropertyNameArray.h>"} = 1 if $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"};
AddIncludesForType($interfaceName);
@@ -933,6 +1071,25 @@ sub GenerateImplementation
push(@implContent, " return getStaticPropertySlot<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, slot);\n");
}
push(@implContent, "}\n\n");
+
+ push(@implContent, "bool ${className}Prototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)\n");
+ push(@implContent, "{\n");
+
+ if ($dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}) {
+ push(@implContent, " if (getOwnPropertyDescriptorDelegate(exec, propertyName, descriptor))\n");
+ push(@implContent, " return true;\n");
+ }
+
+ if ($numConstants eq 0 && $numFunctions eq 0) {
+ push(@implContent, " return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);\n");
+ } elsif ($numConstants eq 0) {
+ push(@implContent, " return getStaticFunctionDescriptor<JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, descriptor);\n");
+ } elsif ($numFunctions eq 0) {
+ push(@implContent, " return getStaticValueDescriptor<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, descriptor);\n");
+ } else {
+ push(@implContent, " return getStaticPropertyDescriptor<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, descriptor);\n");
+ }
+ push(@implContent, "}\n\n");
}
if ($dataNode->extendedAttributes->{"DelegatingPrototypePutFunction"}) {
@@ -980,15 +1137,15 @@ sub GenerateImplementation
# Constructor
if ($interfaceName eq "DOMWindow") {
AddIncludesForType("JSDOMWindowShell");
- push(@implContent, "${className}::$className(PassRefPtr<Structure> structure, PassRefPtr<$implType> impl, JSDOMWindowShell* shell)\n");
+ push(@implContent, "${className}::$className(NonNullPassRefPtr<Structure> structure, PassRefPtr<$implType> impl, JSDOMWindowShell* shell)\n");
push(@implContent, " : $parentClassName(structure, impl, shell)\n");
} elsif ($dataNode->extendedAttributes->{"IsWorkerContext"}) {
AddIncludesForType($interfaceName);
- push(@implContent, "${className}::$className(PassRefPtr<Structure> structure, PassRefPtr<$implType> impl)\n");
+ push(@implContent, "${className}::$className(NonNullPassRefPtr<Structure> structure, PassRefPtr<$implType> impl)\n");
push(@implContent, " : $parentClassName(structure, impl)\n");
} else {
my $contextArg = $needsSVGContext ? ", SVGElement* context" : "";
- push(@implContent, "${className}::$className(PassRefPtr<Structure> structure, JSDOMGlobalObject* globalObject, PassRefPtr<$implType> impl$contextArg)\n");
+ push(@implContent, "${className}::$className(NonNullPassRefPtr<Structure> structure, JSDOMGlobalObject* globalObject, PassRefPtr<$implType> impl$contextArg)\n");
if ($hasParent) {
push(@implContent, " : $parentClassName(structure, globalObject, impl" . ($parentNeedsSVGContext ? ", context" : "") . ")\n");
} else {
@@ -1000,17 +1157,17 @@ sub GenerateImplementation
push(@implContent, "}\n\n");
# Destructor
- if (!$hasParent || $interfaceName eq "DOMWindow") {
+ if (!$hasParent || $eventTarget) {
push(@implContent, "${className}::~$className()\n");
push(@implContent, "{\n");
+ if ($eventTarget) {
+ $implIncludes{"RegisteredEventListener.h"} = 1;
+ push(@implContent, " impl()->invalidateEventListeners();\n");
+ }
+
if ($interfaceName eq "Node") {
- $implIncludes{"RegisteredEventListener.h"} = 1;
- push(@implContent, " invalidateEventListeners(m_impl->eventListeners());\n");
- push(@implContent, " forgetDOMNode(m_impl->document(), m_impl.get());\n");
- } elsif ($interfaceName eq "DOMWindow") {
- $implIncludes{"RegisteredEventListener.h"} = 1;
- push(@implContent, " invalidateEventListeners(impl()->eventListeners());\n");
+ push(@implContent, " forgetDOMNode(impl()->document(), impl());\n");
} else {
if ($podType) {
my $animatedType = $implClassName;
@@ -1021,7 +1178,7 @@ sub GenerateImplementation
push(@implContent, " JSSVGDynamicPODTypeWrapperCache<$podType, $animatedType>::forgetWrapper(m_impl.get());\n");
}
}
- push(@implContent, " forgetDOMObject(*Heap::heap(this)->globalData(), m_impl.get());\n");
+ push(@implContent, " forgetDOMObject(*Heap::heap(this)->globalData(), impl());\n");
}
push(@implContent, "}\n\n");
@@ -1034,6 +1191,14 @@ sub GenerateImplementation
push(@implContent, "{\n forgetDOMObject(*Heap::heap(this)->globalData(), static_cast<${implClassName}*>(impl()));\n}\n\n");
}
+ if ($needsMarkChildren && !$dataNode->extendedAttributes->{"CustomMarkFunction"}) {
+ push(@implContent, "void ${className}::markChildren(MarkStack& markStack)\n");
+ push(@implContent, "{\n");
+ push(@implContent, " Base::markChildren(markStack);\n");
+ push(@implContent, " impl()->markEventListeners(markStack);\n");
+ push(@implContent, "}\n\n");
+ }
+
if (!$dataNode->extendedAttributes->{"ExtendsDOMGlobalObject"}) {
push(@implContent, "JSObject* ${className}::createPrototype(ExecState* exec, JSGlobalObject* globalObject)\n");
push(@implContent, "{\n");
@@ -1049,6 +1214,7 @@ sub GenerateImplementation
|| $dataNode->extendedAttributes->{"GenerateConstructor"}
|| $dataNode->extendedAttributes->{"HasIndexGetter"}
|| $dataNode->extendedAttributes->{"HasCustomIndexGetter"}
+ || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}
|| $dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"}
|| $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}
|| $dataNode->extendedAttributes->{"HasNameGetter"}
@@ -1061,14 +1227,18 @@ sub GenerateImplementation
push(@implContent, "{\n");
push(@implContent, GenerateGetOwnPropertySlotBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 0));
push(@implContent, "}\n\n");
+ push(@implContent, "bool ${className}::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)\n");
+ push(@implContent, "{\n");
+ push(@implContent, GenerateGetOwnPropertyDescriptorBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 0));
+ push(@implContent, "}\n\n");
}
- if (($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"})
+ if (($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"})
&& !$dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
push(@implContent, "bool ${className}::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)\n");
push(@implContent, "{\n");
push(@implContent, " if (propertyName < static_cast<$implClassName*>(impl())->length()) {\n");
- if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"}) {
+ if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
push(@implContent, " slot.setValue(getByIndex(exec, propertyName));\n");
} else {
push(@implContent, " slot.setCustomIndex(this, propertyName, indexGetter);\n");
@@ -1124,7 +1294,11 @@ sub GenerateImplementation
push(@implContent, " UNUSED_PARAM(exec);\n");
push(@implContent, " $implClassName* imp = static_cast<$implClassName*>(castedThis->impl());\n");
push(@implContent, " if (EventListener* listener = imp->$implGetterFunctionName()) {\n");
- push(@implContent, " if (JSObject* jsFunction = listener->jsFunction())\n");
+ if ($implClassName eq "Document" || $implClassName eq "WorkerContext" || $implClassName eq "SharedWorkerContext" || $implClassName eq "DedicatedWorkerContext") {
+ push(@implContent, " if (JSObject* jsFunction = listener->jsFunction(imp))\n");
+ } else {
+ push(@implContent, " if (JSObject* jsFunction = listener->jsFunction(imp->scriptExecutionContext()))\n");
+ }
push(@implContent, " return jsFunction;\n");
push(@implContent, " }\n");
push(@implContent, " return jsNull();\n");
@@ -1333,14 +1507,14 @@ sub GenerateImplementation
}
}
- if (($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}) && !$dataNode->extendedAttributes->{"CustomGetPropertyNames"}) {
- push(@implContent, "void ${className}::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)\n");
+ if (($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) && !$dataNode->extendedAttributes->{"CustomGetPropertyNames"}) {
+ push(@implContent, "void ${className}::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)\n");
push(@implContent, "{\n");
- if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}) {
+ if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
push(@implContent, " for (unsigned i = 0; i < static_cast<${implClassName}*>(impl())->length(); ++i)\n");
push(@implContent, " propertyNames.add(Identifier::from(exec, i));\n");
}
- push(@implContent, " Base::getPropertyNames(exec, propertyNames);\n");
+ push(@implContent, " Base::getOwnPropertyNames(exec, propertyNames);\n");
push(@implContent, "}\n\n");
}
@@ -1373,7 +1547,7 @@ sub GenerateImplementation
push(@implContent, " if (!castedThisObj)\n");
push(@implContent, " return throwError(exec, TypeError);\n");
} else {
- push(@implContent, " if (!thisValue.isObject(&${className}::s_info))\n");
+ push(@implContent, " if (!thisValue.inherits(&${className}::s_info))\n");
push(@implContent, " return throwError(exec, TypeError);\n");
push(@implContent, " $className* castedThisObj = static_cast<$className*>(asObject(thisValue));\n");
}
@@ -1507,6 +1681,17 @@ sub GenerateImplementation
$implIncludes{"Node.h"} = 1;
}
}
+
+ if ($dataNode->extendedAttributes->{"HasNumericIndexGetter"}) {
+ push(@implContent, "\nJSValue ${className}::getByIndex(ExecState* exec, unsigned index)\n");
+ push(@implContent, "{\n");
+ push(@implContent, " return jsNumber(exec, static_cast<$implClassName*>(impl())->item(index));\n");
+ push(@implContent, "}\n");
+ if ($interfaceName eq "HTMLCollection") {
+ $implIncludes{"JSNode.h"} = 1;
+ $implIncludes{"Node.h"} = 1;
+ }
+ }
if ((!$hasParent or $dataNode->extendedAttributes->{"GenerateToJS"}) and !$dataNode->extendedAttributes->{"CustomToJS"}) {
if ($podType) {
@@ -1537,7 +1722,7 @@ sub GenerateImplementation
push(@implContent, "{\n");
- push(@implContent, " return value.isObject(&${className}::s_info) ? " . ($podType ? "($podType) *" : "") . "static_cast<$className*>(asObject(value))->impl() : ");
+ push(@implContent, " return value.inherits(&${className}::s_info) ? " . ($podType ? "($podType) *" : "") . "static_cast<$className*>(asObject(value))->impl() : ");
if ($podType and $podType ne "float") {
push(@implContent, "$podType();\n}\n");
} else {
@@ -1657,6 +1842,11 @@ sub JSValueToNative
return "$value.toString(exec)";
}
+ if ($type eq "SerializedScriptValue") {
+ $implIncludes{"SerializedScriptValue.h"} = 1;
+ return "SerializedScriptValue::create(exec, $value)";
+ }
+
$implIncludes{"FloatPoint.h"} = 1 if $type eq "SVGPoint";
$implIncludes{"FloatRect.h"} = 1 if $type eq "SVGRect";
$implIncludes{"HTMLOptionElement.h"} = 1 if $type eq "HTMLOptionElement";
@@ -1762,6 +1952,9 @@ sub NativeToJSValue
$joinedName = $type;
$joinedName =~ s/Abs|Rel//;
$implIncludes{"$joinedName.h"} = 1;
+ } elsif ($type eq "SerializedScriptValue") {
+ $implIncludes{"$type.h"} = 1;
+ return "$value->deserialize(exec)";
} else {
# Default, include header with same name.
$implIncludes{"JS$type.h"} = 1;
@@ -2021,6 +2214,15 @@ sub WriteData
@headerContent = ();
%headerIncludes = ();
}
+
+ if (defined($DEPS)) {
+ # Write dependency file.
+ print $DEPS @depsContent;
+ close($DEPS);
+ undef($DEPS);
+
+ @depsContent = ();
+ }
}
sub constructorFor
@@ -2041,6 +2243,7 @@ public:
putDirect(exec->propertyNames().prototype, ${protoClassName}::self(exec, globalObject), None);
}
virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
+ virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
virtual const ClassInfo* classInfo() const { return &s_info; }
static const ClassInfo s_info;
@@ -2074,6 +2277,11 @@ bool ${constructorClassName}::getOwnPropertySlot(ExecState* exec, const Identifi
return getStaticValueSlot<${constructorClassName}, DOMObject>(exec, &${constructorClassName}Table, this, propertyName, slot);
}
+bool ${constructorClassName}::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
+{
+ return getStaticValueDescriptor<${constructorClassName}, DOMObject>(exec, &${constructorClassName}Table, this, propertyName, descriptor);
+}
+
EOF
$implJSCInclude{"JSNumberCell.h"} = 1; # FIXME: What is this for?
diff --git a/WebCore/bindings/scripts/CodeGeneratorObjC.pm b/WebCore/bindings/scripts/CodeGeneratorObjC.pm
index f449e19..317086b 100644
--- a/WebCore/bindings/scripts/CodeGeneratorObjC.pm
+++ b/WebCore/bindings/scripts/CodeGeneratorObjC.pm
@@ -4,6 +4,7 @@
# Copyright (C) 2006, 2007 Samuel Weinig <sam@webkit.org>
# Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org>
# Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+# Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
@@ -28,6 +29,7 @@ use File::stat;
# Global Variables
my $module = "";
my $outputDir = "";
+my $writeDependencies = 0;
my %publicInterfaces = ();
my $newPublicClass = 0;
my $interfaceAvailabilityVersion = "";
@@ -49,6 +51,7 @@ my @internalHeaderContent = ();
my @implContentHeader = ();
my @implContent = ();
my %implIncludes = ();
+my @depsContent = ();
# Hashes
my %protocolTypeHash = ("XPathNSResolver" => 1, "EventListener" => 1, "EventTarget" => 1, "NodeFilter" => 1,
@@ -194,6 +197,9 @@ sub new
$codeGenerator = shift;
$outputDir = shift;
+ shift; # $useLayerOnTop
+ shift; # $preprocessor
+ $writeDependencies = shift;
bless($reference, $object);
return $reference;
@@ -305,7 +311,7 @@ sub GetClassName
my $name = $codeGenerator->StripModule(shift);
# special cases
- return "NSString" if $codeGenerator->IsStringType($name);
+ return "NSString" if $codeGenerator->IsStringType($name) or $name eq "SerializedScriptValue";
return "NS$name" if IsNativeObjCType($name);
return "BOOL" if $name eq "boolean";
return "unsigned" if $name eq "unsigned long";
@@ -486,6 +492,11 @@ sub GetObjCTypeGetter
return "WTF::getPtr(nativeEventListener)" if $type eq "EventListener";
return "WTF::getPtr(nativeNodeFilter)" if $type eq "NodeFilter";
return "WTF::getPtr(nativeResolver)" if $type eq "XPathNSResolver";
+
+ if ($type eq "SerializedScriptValue") {
+ $implIncludes{"SerializedScriptValue.h"} = 1;
+ return "WebCore::SerializedScriptValue::create(WebCore::String($argName))";
+ }
return "core($argName)";
}
@@ -601,6 +612,11 @@ sub AddIncludesForType
return;
}
+ if ($type eq "SerializedScriptValue") {
+ $implIncludes{"SerializedScriptValue.h"} = 1;
+ return;
+ }
+
# FIXME: won't compile without these
$implIncludes{"CSSMutableStyleDeclaration.h"} = 1 if $type eq "CSSStyleDeclaration";
$implIncludes{"NameNodeList.h"} = 1 if $type eq "NodeList";
@@ -976,8 +992,10 @@ sub GenerateImplementation
my $object = shift;
my $dataNode = shift;
+ my @ancestorInterfaceNames = ();
+
if (@{$dataNode->parents} > 1) {
- $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode);
+ $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode, \@ancestorInterfaceNames);
}
my $interfaceName = $dataNode->name;
@@ -1204,6 +1222,9 @@ sub GenerateImplementation
} elsif ($idlType eq "Color") {
$getterContentHead = "WebCore::nsColor($getterContentHead";
$getterContentTail .= ")";
+ } elsif ($attribute->signature->type eq "SerializedScriptValue") {
+ $getterContentHead = "$getterContentHead";
+ $getterContentTail .= "->toString()";
} elsif (ConversionNeeded($attribute->signature->type)) {
$getterContentHead = "kit(WTF::getPtr($getterContentHead";
$getterContentTail .= "))";
@@ -1438,6 +1459,8 @@ sub GenerateImplementation
push(@functionContent, " return $toReturn;\n");
push(@functionContent, " return nil;\n");
}
+ } elsif ($returnType eq "SerializedScriptValue") {
+ $content = "foo";
} else {
if (ConversionNeeded($function->signature->type)) {
if ($codeGenerator->IsPodType($function->signature->type)) {
@@ -1543,6 +1566,12 @@ sub GenerateImplementation
# - End the ifdef conditional if necessary
push(@implContent, "\n#endif // ${conditionalString}\n") if $conditional;
+
+ # - Generate dependencies.
+ if ($writeDependencies && @ancestorInterfaceNames) {
+ push(@depsContent, "$className.h : ", join(" ", map { "$_.idl" } @ancestorInterfaceNames), "\n");
+ push(@depsContent, map { "$_.idl :\n" } @ancestorInterfaceNames);
+ }
}
# Internal helper
@@ -1556,12 +1585,14 @@ sub WriteData
my $privateHeaderFileName = "$outputDir/" . $name . "Private.h";
my $implFileName = "$outputDir/" . $name . ".mm";
my $internalHeaderFileName = "$outputDir/" . $name . "Internal.h";
+ my $depsFileName = "$outputDir/" . $name . ".dep";
# Remove old files.
unlink($headerFileName);
unlink($privateHeaderFileName);
unlink($implFileName);
unlink($internalHeaderFileName);
+ unlink($depsFileName);
# Write public header.
open(HEADER, ">$headerFileName") or die "Couldn't open file $headerFileName";
@@ -1624,6 +1655,14 @@ sub WriteData
@internalHeaderContent = ();
}
+
+ # Write dependency file.
+ if (@depsContent) {
+ open(DEPS, ">$depsFileName") or die "Couldn't open file $depsFileName";
+ print DEPS @depsContent;
+ close(DEPS);
+ @depsContent = ();
+ }
}
1;
diff --git a/WebCore/bindings/scripts/CodeGeneratorV8.pm b/WebCore/bindings/scripts/CodeGeneratorV8.pm
index 439f368..b65da53 100644
--- a/WebCore/bindings/scripts/CodeGeneratorV8.pm
+++ b/WebCore/bindings/scripts/CodeGeneratorV8.pm
@@ -5,6 +5,7 @@
# Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org>
# Copyright (C) 2006 Apple Computer, Inc.
# Copyright (C) 2007, 2008, 2009 Google Inc.
+# Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au>
#
# This file is part of the KDE project
#
@@ -90,26 +91,6 @@ sub leftShift($$) {
return (($value << $distance) & 0xFFFFFFFF);
}
-# Uppercase the first letter, while respecting WebKit style guidelines.
-# E.g., xmlEncoding becomes XMLEncoding, but xmlllang becomes Xmllang.
-sub WK_ucfirst
-{
- my $param = shift;
- my $ret = ucfirst($param);
- $ret =~ s/Xml/XML/ if $ret =~ /^Xml[^a-z]/;
- return $ret;
-}
-
-# Lowercase the first letter while respecting WebKit style guidelines.
-# URL becomes url, but SetURL becomes setURL.
-sub WK_lcfirst
-{
- my $param = shift;
- my $ret = lcfirst($param);
- $ret =~ s/uRL/url/;
- return $ret;
-}
-
# Workaround for V8 bindings difference where RGBColor is not a POD type.
sub IsPodType
{
@@ -266,7 +247,7 @@ sub GenerateHeader
# Copy contents of parent classes except the first parent or if it is
# EventTarget.
- $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode);
+ $codeGenerator->AddMethodsConstantsAndAttributesFromParentClasses($dataNode, \@allParents, 1);
my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};
my $conditionalString = GenerateConditionalString($dataNode);
@@ -345,6 +326,28 @@ sub IsNodeSubType
return 0;
}
+sub GetHiddenDependencyIndex
+{
+ my $dataNode = shift;
+ my $attribute = shift;
+ my $name = $dataNode->name;
+ return "V8Custom::kNodeEventListenerCacheIndex" if IsNodeSubType($dataNode);
+ return "V8Custom::kSVGElementInstanceEventListenerCacheIndex" if $name eq "SVGElementInstance";
+ return "V8Custom::kAbstractWorkerRequestCacheIndex" if $name eq "AbstractWorker";
+ return "V8Custom::kWorkerRequestCacheIndex" if $name eq "Worker";
+ return "V8Custom::kDedicatedWorkerContextRequestCacheIndex" if $name eq "DedicatedWorkerContext";
+ return "V8Custom::kWorkerContextRequestCacheIndex" if $name eq "WorkerContext";
+ return "V8Custom::kWorkerContextRequestCacheIndex" if $name eq "SharedWorkerContext";
+ return "V8Custom::kMessagePortRequestCacheIndex" if $name eq "MessagePort";
+ return "V8Custom::kWebSocketCacheIndex" if $name eq "WebSocket";
+ return "V8Custom::kXMLHttpRequestCacheIndex" if $name eq "XMLHttpRequest";
+ return "V8Custom::kXMLHttpRequestCacheIndex" if $name eq "XMLHttpRequestUpload";
+ return "V8Custom::kDOMApplicationCacheCacheIndex" if $name eq "DOMApplicationCache";
+ return "V8Custom::kNotificationRequestCacheIndex" if $name eq "Notification";
+ return "V8Custom::kDOMWindowEventListenerCacheIndex" if $name eq "DOMWindow";
+ die "Unexpected name " . $name . " when generating " . $attribute;
+}
+
sub HolderToNative
{
my $dataNode = shift;
@@ -513,11 +516,17 @@ END
}
} elsif ($attrExt->{"v8OnProto"} || $attrExt->{"V8DisallowShadowing"}) {
+ if ($classIndex eq "DOMWINDOW") {
+ push(@implContentDecls, <<END);
+ v8::Handle<v8::Object> holder = info.Holder();
+END
+ } else {
# perform lookup first
push(@implContentDecls, <<END);
v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::$classIndex, info.This());
if (holder.IsEmpty()) return v8::Undefined();
END
+ }
HolderToNative($dataNode, $implClassName, $classIndex);
} else {
push(@implContentDecls, <<END);
@@ -543,7 +552,7 @@ END
$attrName = $attribute->signature->extendedAttributes->{"v8referenceattr"};
}
- my $getterFunc = WK_lcfirst($attrName);
+ my $getterFunc = $codeGenerator->WK_lcfirst($attrName);
$getterFunc .= "Animated" if $codeGenerator->IsSVGAnimatedType($attribute->signature->type);
my $returnType = GetTypeFromSignature($attribute->signature);
@@ -582,7 +591,7 @@ END
my $getter = $getterString;
$getter =~ s/imp->//;
$getter =~ s/\(\)//;
- my $setter = "set" . WK_ucfirst($getter);
+ my $setter = "set" . $codeGenerator->WK_ucfirst($getter);
my $implClassIsAnimatedType = $codeGenerator->IsSVGAnimatedType($implClassName);
if (not $implClassIsAnimatedType and $codeGenerator->IsPodTypeWithWriteableProperties($attrType) and not defined $attribute->signature->extendedAttributes->{"Immutable"}) {
@@ -607,6 +616,10 @@ END
}
} else {
+ if ($attribute->signature->type eq "EventListener" && $dataNode->name eq "DOMWindow") {
+ push(@implContentDecls, " if (!imp->document())\n");
+ push(@implContentDecls, " return v8::Undefined();\n");
+ }
push(@implContentDecls, " $nativeType v = ");
push(@implContentDecls, "$getterString;\n");
@@ -685,11 +698,17 @@ sub GenerateNormalAttrSetter
push(@implContentDecls, " $implClassName* imp = &imp_instance;\n");
} elsif ($attrExt->{"v8OnProto"}) {
+ if ($classIndex eq "DOMWINDOW") {
+ push(@implContentDecls, <<END);
+ v8::Handle<v8::Object> holder = info.Holder();
+END
+ } else {
# perform lookup first
push(@implContentDecls, <<END);
v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::$classIndex, info.This());
- if (holder.IsEmpty()) return v8::Undefined();
+ if (holder.IsEmpty()) return;
END
+ }
HolderToNative($dataNode, $implClassName, $classIndex);
} else {
push(@implContentDecls, <<END);
@@ -699,7 +718,15 @@ END
}
my $nativeType = GetNativeTypeFromSignature($attribute->signature, 0);
- push(@implContentDecls, " $nativeType v = " . JSValueToNative($attribute->signature, "value") . ";\n");
+ if ($attribute->signature->type eq "EventListener") {
+ if ($dataNode->name eq "DOMWindow") {
+ push(@implContentDecls, " if (!imp->document())\n");
+ push(@implContentDecls, " return;\n");
+ }
+ push(@implContentDecls, " $nativeType v = V8DOMWrapper::getEventListener(imp, value, true, ListenerFindOrCreate);\n");
+ } else {
+ push(@implContentDecls, " $nativeType v = " . JSValueToNative($attribute->signature, "value") . ";\n");
+ }
my $result = "";
if ($nativeType eq "int" and $attribute->signature->extendedAttributes->{"ConvertFromString"}) {
@@ -724,13 +751,27 @@ END
if ($implClassName eq "double") {
push(@implContentDecls, " *imp = $result;\n");
} else {
- my $implSetterFunctionName = WK_ucfirst($attrName);
+ my $implSetterFunctionName = $codeGenerator->WK_ucfirst($attrName);
my $reflect = $attribute->signature->extendedAttributes->{"Reflect"};
my $reflectURL = $attribute->signature->extendedAttributes->{"ReflectURL"};
if ($reflect || $reflectURL) {
$implIncludes{"HTMLNames.h"} = 1;
my $contentAttributeName = ($reflect || $reflectURL) eq "1" ? $attrName : ($reflect || $reflectURL);
push(@implContentDecls, " imp->setAttribute(HTMLNames::${contentAttributeName}Attr, $result");
+ } elsif ($attribute->signature->type eq "EventListener") {
+ $implIncludes{"V8AbstractEventListener.h"} = 1;
+ $implIncludes{"V8CustomBinding.h"} = 1;
+ $cacheIndex = GetHiddenDependencyIndex($dataNode, $attrName);
+ push(@implContentDecls, " $nativeType old = imp->$attrName();\n");
+ push(@implContentDecls, " V8AbstractEventListener* oldListener = old ? V8AbstractEventListener::cast(old.get()) : 0;\n");
+ push(@implContentDecls, " if (oldListener) {\n");
+ push(@implContentDecls, " v8::Local<v8::Object> oldListenerObject = oldListener->getExistingListenerObject();\n");
+ push(@implContentDecls, " if (!oldListenerObject.IsEmpty())\n");
+ push(@implContentDecls, " removeHiddenDependency(holder, oldListenerObject, $cacheIndex);\n");
+ push(@implContentDecls, " }\n");
+ push(@implContentDecls, " imp->set$implSetterFunctionName($result);\n");
+ push(@implContentDecls, " if ($result)\n");
+ push(@implContentDecls, " createHiddenDependency(holder, value, $cacheIndex");
} else {
push(@implContentDecls, " imp->set$implSetterFunctionName(" . $result);
}
@@ -779,7 +820,7 @@ sub GenerateNewFunctionTemplate
my $customFunc = $function->signature->extendedAttributes->{"Custom"} ||
$function->signature->extendedAttributes->{"V8Custom"};
if ($customFunc eq 1) {
- $customFunc = $interfaceName . WK_ucfirst($name);
+ $customFunc = $interfaceName . $codeGenerator->WK_ucfirst($name);
}
return "v8::FunctionTemplate::New(V8Custom::v8${customFunc}Callback, v8::Handle<v8::Value>(), $signature)";
} else {
@@ -841,6 +882,11 @@ END
push(@implContentDecls, " ScriptCallStack callStack(args, $numParameters);\n");
$implIncludes{"ScriptCallStack.h"} = 1;
}
+ if ($function->signature->extendedAttributes->{"SVGCheckSecurityDocument"}) {
+ push(@implContentDecls,
+" if (!V8Proxy::checkNodeSecurity(imp->getSVGDocument(ec)))\n" .
+" return v8::Undefined();\n");
+ }
my $paramIndex = 0;
foreach my $parameter (@{$function->parameters}) {
@@ -893,7 +939,8 @@ END
sub GenerateBatchedAttributeData
{
- my $interfaceName = shift;
+ my $dataNode = shift;
+ my $interfaceName = $dataNode->name;
my $attributes = shift;
foreach my $attribute (@$attributes) {
@@ -926,7 +973,7 @@ sub GenerateBatchedAttributeData
"";
if ($customAccessor eq 1) {
# use the naming convension, interface + (capitalize) attr name
- $customAccessor = $interfaceName . WK_ucfirst($attrName);
+ $customAccessor = $interfaceName . $codeGenerator->WK_ucfirst($attrName);
}
my $getter;
@@ -950,79 +997,41 @@ sub GenerateBatchedAttributeData
my $constructorType = $codeGenerator->StripModule($attribute->signature->type);
$constructorType =~ s/Constructor$//;
my $constructorIndex = uc($constructorType);
- $data = "V8ClassIndex::${constructorIndex}";
- $getter = "${interfaceName}Internal::${interfaceName}ConstructorGetter";
- $setter = "0";
- $propAttr = "v8::ReadOnly";
-
- # EventListeners
- } elsif ($attribute->signature->type eq "EventListener") {
- if ($interfaceName eq "DOMWindow") {
- $getter = "V8Custom::v8DOMWindowEventHandlerAccessorGetter";
- $setter = "V8Custom::v8DOMWindowEventHandlerAccessorSetter";
- } elsif ($interfaceName eq "Element" || $interfaceName eq "Document" || $interfaceName eq "HTMLBodyElement" || $interfaceName eq "SVGElementInstance" || $interfaceName eq "HTMLFrameSetElement") {
- $getter = "V8Custom::v8NodeEventHandlerAccessorGetter";
- $setter = "V8Custom::v8NodeEventHandlerAccessorSetter";
- } elsif ($interfaceName eq "DOMApplicationCache") {
- $getter = "V8Custom::v8DOMApplicationCacheEventHandlerAccessorGetter";
- $setter = "V8Custom::v8DOMApplicationCacheEventHandlerAccessorSetter";
- } else {
+ if ($customAccessor) {
$getter = "V8Custom::v8${customAccessor}AccessorGetter";
- if ($interfaceName eq "WorkerContext" and $attrName eq "self") {
- $setter = "0";
- $propAttr = "v8::ReadOnly";
- } else {
- $setter = "V8Custom::v8${customAccessor}AccessorSetter";
- }
- }
-
- # Custom Getter and Setter
- } elsif ($attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
- $getter = "V8Custom::v8${customAccessor}AccessorGetter";
- if ($interfaceName eq "WorkerContext" and $attrName eq "self") {
- $setter = "0";
- $propAttr = "v8::ReadOnly";
} else {
- $hasCustomSetter = 1;
- $setter = "V8Custom::v8${customAccessor}AccessorSetter";
+ $data = "V8ClassIndex::${constructorIndex}";
+ $getter = "${interfaceName}Internal::${interfaceName}ConstructorGetter";
}
+ $setter = "0";
+ $propAttr = "v8::ReadOnly";
- # Custom Setter
- } elsif ($attrExt->{"CustomSetter"} || $attrExt->{"V8CustomSetter"}) {
- $hasCustomSetter = 1;
+ } else {
+ # Default Getter and Setter
$getter = "${interfaceName}Internal::${attrName}AttrGetter";
- $setter = "V8Custom::v8${customAccessor}AccessorSetter";
-
- # Custom Getter
- } elsif ($attrExt->{"CustomGetter"}) {
- $getter = "V8Custom::v8${customAccessor}AccessorGetter";
$setter = "${interfaceName}Internal::${attrName}AttrSetter";
- # Replaceable
- } elsif ($attrExt->{"Replaceable"}) {
- # Replaceable accessor is put on instance template with ReadOnly attribute.
- $getter = "${interfaceName}Internal::${attrName}AttrGetter";
- $setter = "0";
-
- # Mark to avoid duplicate v8::ReadOnly flags in output.
- $hasCustomSetter = 1;
-
- # Handle the special case of window.top being marked upstream as Replaceable.
- # FIXME: Investigate why [Replaceable] is not marked as ReadOnly
- # upstream and reach parity.
- if (!($interfaceName eq "DOMWindow" and $attrName eq "top")) {
- $propAttr .= "|v8::ReadOnly";
+ # Custom Setter
+ if ($attrExt->{"CustomSetter"} || $attrExt->{"V8CustomSetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
+ $hasCustomSetter = 1;
+ $setter = "V8Custom::v8${customAccessor}AccessorSetter";
}
- # Normal
- } else {
- $getter = "${interfaceName}Internal::${attrName}AttrGetter";
- $setter = "${interfaceName}Internal::${attrName}AttrSetter";
+ # Custom Getter
+ if ($attrExt->{"CustomGetter"} || $attrExt->{"Custom"} || $attrExt->{"V8Custom"}) {
+ $getter = "V8Custom::v8${customAccessor}AccessorGetter";
+ }
}
+ # Replaceable
if ($attrExt->{"Replaceable"} && !$hasCustomSetter) {
$setter = "0";
- $propAttr .= "|v8::ReadOnly";
+ # Handle the special case of window.top being marked as Replaceable.
+ # FIXME: Investigate whether we could treat window.top as replaceable
+ # and allow shadowing without it being a security hole.
+ if (!($interfaceName eq "DOMWindow" and $attrName eq "top")) {
+ $propAttr .= "|v8::ReadOnly";
+ }
}
# Read only attributes
@@ -1068,8 +1077,6 @@ sub GenerateImplementation
my $hasLegacyParent = $dataNode->extendedAttributes->{"LegacyParent"};
my $conditionalString = GenerateConditionalString($dataNode);
- @allParents = $codeGenerator->FindParentsRecursively($dataNode);
-
# - Add default header template
@implContentHeader = split("\r", $headerTemplate);
@@ -1104,20 +1111,16 @@ sub GenerateImplementation
# Generate special code for the constructor attributes.
if ($attrType =~ /Constructor$/) {
- $hasConstructors = 1;
+ if ($attribute->signature->extendedAttributes->{"CustomGetter"}) {
+ $implIncludes{"V8CustomBinding.h"} = 1;
+ } else {
+ $hasConstructors = 1;
+ }
next;
}
- # Make EventListeners always custom.
- # FIXME: make the perl code capable of generating the
- # event setters/getters. For now, WebKit has started removing the
- # [Custom] attribute, so just automatically insert it to avoid forking
- # other files. This should be okay because we can't generate stubs
- # for any event getter/setters anyway.
- if ($attrType eq "EventListener") {
- $attribute->signature->extendedAttributes->{"Custom"} = 1;
- $implIncludes{"V8CustomBinding.h"} = 1;
- next;
+ if ($attrType eq "EventListener" && $interfaceName eq "DOMWindow") {
+ $attribute->signature->extendedAttributes->{"v8OnProto"} = 1;
}
# Do not generate accessor if this is a custom attribute. The
@@ -1186,7 +1189,7 @@ sub GenerateImplementation
# Put the attributes that disallow shadowing on the shadow object.
$attributes = \@normal;
push(@implContent, "static const BatchedAttribute shadow_attrs[] = {\n");
- GenerateBatchedAttributeData($interfaceName, \@disallows_shadowing);
+ GenerateBatchedAttributeData($dataNode, \@disallows_shadowing);
push(@implContent, "};\n");
}
@@ -1194,7 +1197,7 @@ sub GenerateImplementation
if (@$attributes) {
$has_attributes = 1;
push(@implContent, "static const BatchedAttribute ${interfaceName}_attrs[] = {\n");
- GenerateBatchedAttributeData($interfaceName, $attributes);
+ GenerateBatchedAttributeData($dataNode, $attributes);
push(@implContent, "};\n");
}
@@ -1472,7 +1475,7 @@ sub GenerateFunctionCallString()
$paramName = "SVGPODListItem<" . GetNativeType($paramType, 1) . ">::copy($paramName)";
}
- if ($parameter->type eq "NodeFilter") {
+ if ($parameter->type eq "NodeFilter" || $parameter->type eq "XPathNSResolver") {
$functionString .= "$paramName.get()";
} else {
$functionString .= $paramName;
@@ -1590,7 +1593,7 @@ sub GetTypeFromSignature
my $signature = shift;
my $type = $codeGenerator->StripModule($signature->type);
- if (($type eq "DOMString") && $signature->extendedAttributes->{"V8Custom"}) {
+ if (($type eq "DOMString") && $signature->extendedAttributes->{"HintAtomic"}) {
$type = "AtomicString";
}
@@ -1605,6 +1608,11 @@ sub GetNativeTypeFromSignature
my $type = GetTypeFromSignature($signature);
+ if ($type eq "unsigned long" and $signature->extendedAttributes->{"IsIndex"}) {
+ # Special-case index arguments because we need to check that they aren't < 0.
+ return "int";
+ }
+
return GetNativeType($type, $isParameter);
}
@@ -1612,7 +1620,24 @@ sub IsRefPtrType
{
my $type = shift;
return 1 if $type eq "Attr";
+ return 1 if $type eq "CanvasArray";
+ return 1 if $type eq "CanvasArrayBuffer";
+ return 1 if $type eq "CanvasBooleanArray";
+ return 1 if $type eq "CanvasByteArray";
+ return 1 if $type eq "CanvasBuffer";
+ return 1 if $type eq "CanvasFloatArray";
+ return 1 if $type eq "CanvasFramebuffer";
return 1 if $type eq "CanvasGradient";
+ return 1 if $type eq "CanvasIntArray";
+ return 1 if $type eq "CanvasObject";
+ return 1 if $type eq "CanvasProgram";
+ return 1 if $type eq "CanvasRenderbuffer";
+ return 1 if $type eq "CanvasShader";
+ return 1 if $type eq "CanvasShortArray";
+ return 1 if $type eq "CanvasTexture";
+ return 1 if $type eq "CanvasUnsignedByteArray";
+ return 1 if $type eq "CanvasUnsignedIntArray";
+ return 1 if $type eq "CanvasUnsignedShortArray";
return 1 if $type eq "ClientRect";
return 1 if $type eq "ClientRectList";
return 1 if $type eq "CDATASection";
@@ -1636,6 +1661,7 @@ sub IsRefPtrType
return 1 if $type eq "Element";
return 1 if $type eq "EntityReference";
return 1 if $type eq "Event";
+ return 1 if $type eq "EventListener";
return 1 if $type eq "FileList";
return 1 if $type eq "HTMLCollection";
return 1 if $type eq "HTMLDocument";
@@ -1653,6 +1679,7 @@ sub IsRefPtrType
return 1 if $type eq "Plugin";
return 1 if $type eq "ProcessingInstruction";
return 1 if $type eq "Range";
+ return 1 if $type eq "RGBColor";
return 1 if $type eq "Text";
return 1 if $type eq "TextMetrics";
return 1 if $type eq "TimeRanges";
@@ -1708,7 +1735,8 @@ sub GetNativeType
return "int" if $type eq "int";
return "int" if $type eq "short" or $type eq "unsigned short";
- return "int" if $type eq "long" or $type eq "unsigned long";
+ return "unsigned" if $type eq "unsigned long";
+ return "int" if $type eq "long";
return "unsigned long long" if $type eq "unsigned long long";
return "bool" if $type eq "boolean";
return "String" if $type eq "DOMString";
@@ -1729,6 +1757,9 @@ sub GetNativeType
# temporary hack
return "RefPtr<NodeFilter>" if $type eq "NodeFilter";
+ # necessary as resolvers could be constructed on fly.
+ return "RefPtr<XPathNSResolver>" if $type eq "XPathNSResolver";
+
return "RefPtr<${type}>" if IsRefPtrType($type) and not $isParameter;
# Default, assume native type is a pointer with same type name as idl type
@@ -1739,6 +1770,19 @@ sub GetNativeType
my %typeCanFailConversion = (
"AtomicString" => 0,
"Attr" => 1,
+ "CanvasArray" => 0,
+ "CanvasBuffer" => 0,
+ "CanvasByteArray" => 0,
+ "CanvasFloatArray" => 0,
+ "CanvasFramebuffer" => 0,
+ "CanvasGradient" => 0,
+ "CanvasIntArray" => 0,
+ "CanvasPixelArray" => 0,
+ "CanvasProgram" => 0,
+ "CanvasRenderbuffer" => 0,
+ "CanvasShader" => 0,
+ "CanvasShortArray" => 0,
+ "CanvasTexture" => 0,
"CompareHow" => 0,
"DataGridColumn" => 0,
"DOMString" => 0,
@@ -1748,8 +1792,11 @@ my %typeCanFailConversion = (
"Event" => 0,
"EventListener" => 0,
"EventTarget" => 0,
+ "HTMLCanvasElement" => 0,
"HTMLElement" => 0,
+ "HTMLImageElement" => 0,
"HTMLOptionElement" => 0,
+ "HTMLVideoElement" => 0,
"Node" => 0,
"NodeFilter" => 0,
"MessagePort" => 0,
@@ -1837,7 +1884,11 @@ sub JSValueToNative
return "static_cast<Range::CompareHow>($value->Int32Value())" if $type eq "CompareHow";
return "static_cast<SVGPaint::SVGPaintType>($value->ToInt32()->Int32Value())" if $type eq "SVGPaintType";
- return "v8ValueToAtomicWebCoreString($value)" if $type eq "AtomicString";
+ if ($type eq "AtomicString") {
+ return "v8ValueToAtomicWebCoreStringWithNullCheck($value)" if $signature->extendedAttributes->{"ConvertNullToNullString"};
+ return "v8ValueToAtomicWebCoreString($value)";
+ }
+
return "toWebCoreString($value)" if $type eq "DOMUserData";
if ($type eq "DOMString") {
return "toWebCoreStringWithNullCheck($value)" if $signature->extendedAttributes->{"ConvertNullToNullString"};
@@ -1845,6 +1896,11 @@ sub JSValueToNative
return "toWebCoreString($value)";
}
+ if ($type eq "SerializedScriptValue") {
+ $implIncludes{"SerializedScriptValue.h"} = 1;
+ return "SerializedScriptValue::create($value)";
+ }
+
if ($type eq "NodeFilter") {
return "V8DOMWrapper::wrapNativeNodeFilter($value)";
}
@@ -1866,6 +1922,10 @@ sub JSValueToNative
return "V8Node::HasInstance($value) ? V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast($value)) : 0";
}
+ if ($type eq "XPathNSResolver") {
+ return "V8DOMWrapper::getXPathNSResolver($value)";
+ }
+
AddIncludesForType($type);
# $implIncludes{"$type.h"} = 1 unless AvoidInclusionOfType($type);
@@ -1917,10 +1977,16 @@ sub CreateCustomSignature
if ($first) { $first = 0; }
else { $result .= ", "; }
if (IsWrapperType($parameter->type)) {
- my $type = $parameter->type;
- my $header = GetV8HeaderName($type);
- $implIncludes{$header} = 1;
- $result .= "V8${type}::GetRawTemplate()";
+ if ($parameter->type eq "XPathNSResolver") {
+ # Special case for XPathNSResolver. All other browsers accepts a callable,
+ # so, even though it's against IDL, accept objects here.
+ $result .= "v8::Handle<v8::FunctionTemplate>()";
+ } else {
+ my $type = $parameter->type;
+ my $header = GetV8HeaderName($type);
+ $implIncludes{$header} = 1;
+ $result .= "V8${type}::GetRawTemplate()";
+ }
} else {
$result .= "v8::Handle<v8::FunctionTemplate>()";
}
@@ -2063,12 +2129,17 @@ sub ReturnNativeToJSValue
return "return V8DOMWrapper::convertEventListenerToV8Object($value)";
}
+ if ($type eq "SerializedScriptValue") {
+ $implIncludes{"$type.h"} = 1;
+ return "return v8String($value->toString())";
+ }
+
if ($type eq "DedicatedWorkerContext" or $type eq "WorkerContext" or $type eq "SharedWorkerContext") {
$implIncludes{"WorkerContextExecutionProxy.h"} = 1;
return "return WorkerContextExecutionProxy::convertWorkerContextToV8Object($value)";
}
- if ($type eq "WorkerLocation" or $type eq "WorkerNavigator") {
+ if ($type eq "WorkerLocation" or $type eq "WorkerNavigator" or $type eq "NotificationCenter") {
$implIncludes{"WorkerContextExecutionProxy.h"} = 1;
my $classIndex = uc($type);
diff --git a/WebCore/bindings/scripts/IDLParser.pm b/WebCore/bindings/scripts/IDLParser.pm
index c4cb041..4abdb45 100644
--- a/WebCore/bindings/scripts/IDLParser.pm
+++ b/WebCore/bindings/scripts/IDLParser.pm
@@ -309,7 +309,11 @@ sub ParseInterface
$methodException =~ s/\s+//g;
@{$newDataNode->raisesExceptions} = split(/,/, $methodException);
- my @params = split(/,/, $methodSignature);
+ # Split arguments at commas but only if the comma
+ # is not within attribute brackets, expressed here
+ # as being followed by a ']' without a preceding '['.
+ # Note that this assumes that attributes don't nest.
+ my @params = split(/,(?![^[]*\])/, $methodSignature);
foreach(@params) {
my $line = $_;
diff --git a/WebCore/bindings/scripts/generate-bindings.pl b/WebCore/bindings/scripts/generate-bindings.pl
index 9c374bf..c7adeb3 100755
--- a/WebCore/bindings/scripts/generate-bindings.pl
+++ b/WebCore/bindings/scripts/generate-bindings.pl
@@ -42,12 +42,14 @@ my $outputDirectory;
my $generator;
my $defines;
my $preprocessor;
+my $writeDependencies;
GetOptions('include=s@' => \@idlDirectories,
'outputDir=s' => \$outputDirectory,
'generator=s' => \$generator,
'defines=s' => \$defines,
- 'preprocessor=s' => \$preprocessor);
+ 'preprocessor=s' => \$preprocessor,
+ 'write-dependencies' => \$writeDependencies);
my $idlFile = $ARGV[0];
@@ -65,5 +67,5 @@ my $parser = IDLParser->new(1);
my $document = $parser->Parse($idlFile, $defines, $preprocessor);
# Generate desired output for given IDL file.
-my $codeGen = CodeGenerator->new(\@idlDirectories, $generator, $outputDirectory, 0, $preprocessor);
+my $codeGen = CodeGenerator->new(\@idlDirectories, $generator, $outputDirectory, 0, $preprocessor, $writeDependencies);
$codeGen->ProcessDocument($document, $defines);
diff --git a/WebCore/bindings/v8/ChildThreadDOMData.h b/WebCore/bindings/v8/ChildThreadDOMData.h
index ab90e5b..173a5e8 100644
--- a/WebCore/bindings/v8/ChildThreadDOMData.h
+++ b/WebCore/bindings/v8/ChildThreadDOMData.h
@@ -39,7 +39,9 @@ namespace WebCore {
class ChildThreadDOMData : public DOMData {
public:
ChildThreadDOMData();
+#if PLATFORM(ANDROID)
virtual ~ChildThreadDOMData() { }
+#endif
DOMDataStore& getStore();
diff --git a/WebCore/bindings/v8/DOMData.h b/WebCore/bindings/v8/DOMData.h
index 07e14e5..e67adb4 100644
--- a/WebCore/bindings/v8/DOMData.h
+++ b/WebCore/bindings/v8/DOMData.h
@@ -45,7 +45,9 @@ namespace WebCore {
class DOMData : public Noncopyable {
public:
DOMData();
+#if PLATFORM(ANDROID)
virtual ~DOMData() { }
+#endif
static DOMData* getCurrent();
static DOMData* getCurrentMainThread(); // Caller must be on the main thread.
diff --git a/WebCore/bindings/v8/DOMObjectsInclude.h b/WebCore/bindings/v8/DOMObjectsInclude.h
index 6f36f3b..fb7ba81 100644
--- a/WebCore/bindings/v8/DOMObjectsInclude.h
+++ b/WebCore/bindings/v8/DOMObjectsInclude.h
@@ -31,13 +31,31 @@
#ifndef DOMObjectsInclude_h
#define DOMObjectsInclude_h
-#include "AbstractWorker.h"
#include "BarInfo.h"
+#include "BeforeLoadEvent.h"
+#include "CanvasArray.h"
+#include "CanvasArrayBuffer.h"
+#include "CanvasBuffer.h"
+#include "CanvasByteArray.h"
+#include "CanvasFloatArray.h"
+#include "CanvasFramebuffer.h"
#include "CanvasGradient.h"
+#include "CanvasIntArray.h"
+#include "CanvasObject.h"
#include "CanvasPattern.h"
#include "CanvasPixelArray.h"
+#include "CanvasProgram.h"
+#include "CanvasRenderbuffer.h"
+#include "CanvasRenderingContext.h"
#include "CanvasRenderingContext2D.h"
+#include "CanvasRenderingContext3D.h"
+#include "CanvasShader.h"
+#include "CanvasShortArray.h"
+#include "CanvasUnsignedByteArray.h"
+#include "CanvasUnsignedIntArray.h"
+#include "CanvasUnsignedShortArray.h"
#include "CanvasStyle.h"
+#include "CanvasTexture.h"
#include "CharacterData.h"
#include "ClientRect.h"
#include "ClientRectList.h"
@@ -57,7 +75,6 @@
#include "CSSValueList.h"
#include "CSSVariablesDeclaration.h"
#include "CSSVariablesRule.h"
-#include "Database.h"
#include "DocumentType.h"
#include "DocumentFragment.h"
#include "DOMCoreException.h"
@@ -86,7 +103,6 @@
#include "HTMLSelectElement.h"
#include "HTMLOptionsCollection.h"
#include "ImageData.h"
-#include "InspectorBackend.h"
#include "KeyboardEvent.h"
#include "Location.h"
#include "Media.h"
@@ -106,6 +122,7 @@
#include "NodeIterator.h"
#include "OverflowEvent.h"
#include "Page.h"
+#include "PageTransitionEvent.h"
#include "Plugin.h"
#include "PluginArray.h"
#include "ProcessingInstruction.h"
@@ -118,11 +135,6 @@
#include "ScriptExecutionContext.h"
#include "SecurityOrigin.h"
#include "Settings.h"
-#include "SharedWorker.h"
-#include "SharedWorkerContext.h"
-#include "SQLTransaction.h"
-#include "SQLResultSet.h"
-#include "SQLResultSetRowList.h"
#include "StyleSheet.h"
#include "StyleSheetList.h"
#include "TextEvent.h"
@@ -135,9 +147,7 @@
#include "V8HTMLElement.h"
#include "V8LazyEventListener.h"
#include "V8NodeFilterCondition.h"
-#include "V8ObjectEventListener.h"
#include "ValidityState.h"
-#include "VoidCallback.h"
#include "WebKitAnimationEvent.h"
#include "WebKitCSSKeyframeRule.h"
#include "WebKitCSSKeyframesRule.h"
@@ -151,16 +161,18 @@
#include "XMLHttpRequestProgressEvent.h"
#include "XMLHttpRequestUpload.h"
#include "XMLSerializer.h"
-#include "XPathException.h"
-#include "XPathExpression.h"
-#include "XPathNSResolver.h"
-#include "XPathResult.h"
-#include "XSLTProcessor.h"
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
#include "DOMApplicationCache.h"
#endif
+#if ENABLE(DATABASE)
+#include "Database.h"
+#include "SQLTransaction.h"
+#include "SQLResultSet.h"
+#include "SQLResultSetRowList.h"
+#endif // DATABASE
+
#if ENABLE(DATAGRID)
#include "DataGridColumn.h"
#include "DataGridColumnList.h"
@@ -215,13 +227,21 @@
#include "V8SVGPODTypeWrapper.h"
#endif // SVG
+#if PLATFORM(ANDROID)
+// TODO: Upstream TOUCH_EVENTS guard.
#if ENABLE(TOUCH_EVENTS)
#include "Touch.h"
#include "TouchList.h"
#include "TouchEvent.h"
#endif
+#endif
+
+#if ENABLE(WEB_SOCKETS)
+#include "WebSocket.h"
+#endif
#if ENABLE(WORKERS)
+#include "AbstractWorker.h"
#include "DedicatedWorkerContext.h"
#include "Worker.h"
#include "WorkerContext.h"
@@ -229,10 +249,32 @@
#include "WorkerNavigator.h"
#endif // WORKERS
+#if ENABLE(SHARED_WORKERS)
+#include "SharedWorker.h"
+#include "SharedWorkerContext.h"
+#endif // SHARED_WORKERS
+
+#if ENABLE(NOTIFICATIONS)
+#include "Notification.h"
+#include "NotificationCenter.h"
+#endif // NOTIFICATIONS
+
#if ENABLE(XPATH)
#include "XPathEvaluator.h"
+#include "XPathException.h"
+#include "XPathExpression.h"
+#include "XPathNSResolver.h"
+#include "XPathResult.h"
#endif // XPATH
+#if ENABLE(XSLT)
+#include "XSLTProcessor.h"
+#endif // XSLT
+
+#if ENABLE(INSPECTOR)
+#include "InspectorBackend.h"
+#endif // INSPECTOR
+
namespace WebCore {
// A helper class for undetectable document.all
diff --git a/WebCore/bindings/v8/DateExtension.cpp b/WebCore/bindings/v8/DateExtension.cpp
new file mode 100644
index 0000000..778a15a
--- /dev/null
+++ b/WebCore/bindings/v8/DateExtension.cpp
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "DateExtension.h"
+
+#include "V8Proxy.h"
+#include "V8HiddenPropertyName.h"
+
+namespace WebCore {
+
+DateExtension* DateExtension::extension;
+
+static const char* dateExtensionName = "v8/DateExtension";
+static const char* dateExtensionScript =
+ "(function () {"
+ " var counter;"
+ " var orig_getTime;"
+ " function getTimeOverride() {"
+ " if (++counter > 1000)"
+ " OnSleepDetected();"
+ " return orig_getTime.call(this);"
+ " };"
+ " function enableSleepDetection(enable) {"
+ " if (enable) {"
+ " counter = 0;"
+ " orig_getTime = Date.prototype.getTime;"
+ " Date.prototype.getTime = getTimeOverride;"
+ " } else {"
+ " Date.prototype.getTime = orig_getTime;"
+ " }"
+ " };"
+ " native function Setup();"
+ " native function OnSleepDetected();"
+ " Setup(Date, enableSleepDetection);"
+ "})()";
+
+DateExtension::DateExtension() : v8::Extension(dateExtensionName, dateExtensionScript)
+{
+}
+
+DateExtension* DateExtension::get()
+{
+ if (!extension)
+ extension = new DateExtension();
+ return extension;
+}
+
+void DateExtension::setAllowSleep(bool allow)
+{
+ v8::Local<v8::Value> result = V8Proxy::retrieve()->context()->Global()->Get(v8::String::New("Date"));
+ if (result.IsEmpty())
+ return;
+
+ v8::Handle<v8::Object> dateObject = v8::Handle<v8::Object>::Cast(result);
+ if (dateObject.IsEmpty())
+ return;
+
+ v8::Local<v8::Value> sleepFunctionHandle = dateObject->GetHiddenValue(V8HiddenPropertyName::sleepFunction());
+ if (sleepFunctionHandle.IsEmpty() || !sleepFunctionHandle->IsFunction())
+ return;
+
+ v8::Handle<v8::Value> argv[1];
+ argv[0] = v8::String::New(allow ? "false" : "true");
+ v8::Handle<v8::Function>::Cast(sleepFunctionHandle)->Call(v8::Object::New(), 1, argv);
+}
+
+v8::Handle<v8::FunctionTemplate> DateExtension::GetNativeFunction(v8::Handle<v8::String> name)
+{
+ if (name->Equals(v8::String::New("Setup")))
+ return v8::FunctionTemplate::New(Setup);
+ if (name->Equals(v8::String::New("OnSleepDetected")))
+ return v8::FunctionTemplate::New(OnSleepDetected);
+
+ return v8::Handle<v8::FunctionTemplate>();
+}
+
+v8::Handle<v8::Value> DateExtension::Setup(const v8::Arguments& args)
+{
+ if (args.Length() != 2 || !args[0]->IsObject() || !args[1]->IsFunction())
+ return v8::Undefined();
+
+ v8::Handle<v8::Object> dateObject = v8::Handle<v8::Object>::Cast(args[0]);
+ v8::Handle<v8::Function> enableSleepDetectionFunction = v8::Handle<v8::Function>::Cast(args[1]);
+
+ dateObject->SetHiddenValue(V8HiddenPropertyName::sleepFunction(), enableSleepDetectionFunction);
+ return v8::Undefined();
+}
+
+v8::Handle<v8::Value> DateExtension::OnSleepDetected(const v8::Arguments&)
+{
+ v8::V8::TerminateExecution();
+ return v8::Undefined();
+}
+
+} // namespace WebCore
diff --git a/WebCore/bindings/v8/DateExtension.h b/WebCore/bindings/v8/DateExtension.h
new file mode 100644
index 0000000..2bccac4
--- /dev/null
+++ b/WebCore/bindings/v8/DateExtension.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DateExtension_h
+#define DateExtension_h
+
+#include <v8.h>
+
+namespace WebCore {
+
+// Prevent "sleep" calls in unload handlers.
+class DateExtension : public v8::Extension {
+public:
+ static DateExtension* get();
+ void setAllowSleep(bool allow);
+
+private:
+ DateExtension();
+ virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(v8::Handle<v8::String>);
+ static v8::Handle<v8::Value> Setup(const v8::Arguments&);
+ static v8::Handle<v8::Value> OnSleepDetected(const v8::Arguments&);
+
+ static DateExtension* extension;
+};
+
+} // namespace WebCore
+
+#endif // DateExtension_h
diff --git a/WebCore/bindings/v8/DerivedSourcesAllInOne.cpp b/WebCore/bindings/v8/DerivedSourcesAllInOne.cpp
index e52a505..98832f3 100644
--- a/WebCore/bindings/v8/DerivedSourcesAllInOne.cpp
+++ b/WebCore/bindings/v8/DerivedSourcesAllInOne.cpp
@@ -33,10 +33,28 @@
#include "bindings/V8Attr.cpp"
#include "bindings/V8BarInfo.cpp"
+#include "bindings/V8BeforeLoadEvent.cpp"
+#include "bindings/V8CanvasArray.cpp"
+#include "bindings/V8CanvasArrayBuffer.cpp"
+#include "bindings/V8CanvasBuffer.cpp"
+#include "bindings/V8CanvasByteArray.cpp"
+#include "bindings/V8CanvasFloatArray.cpp"
+#include "bindings/V8CanvasFramebuffer.cpp"
#include "bindings/V8CanvasGradient.cpp"
+#include "bindings/V8CanvasIntArray.cpp"
#include "bindings/V8CanvasPattern.cpp"
#include "bindings/V8CanvasPixelArray.cpp"
+#include "bindings/V8CanvasProgram.cpp"
+#include "bindings/V8CanvasRenderbuffer.cpp"
+#include "bindings/V8CanvasRenderingContext.cpp"
#include "bindings/V8CanvasRenderingContext2D.cpp"
+#include "bindings/V8CanvasRenderingContext3D.cpp"
+#include "bindings/V8CanvasShader.cpp"
+#include "bindings/V8CanvasShortArray.cpp"
+#include "bindings/V8CanvasTexture.cpp"
+#include "bindings/V8CanvasUnsignedByteArray.cpp"
+#include "bindings/V8CanvasUnsignedIntArray.cpp"
+#include "bindings/V8CanvasUnsignedShortArray.cpp"
#include "bindings/V8CDATASection.cpp"
#include "bindings/V8CharacterData.cpp"
#include "bindings/V8ClientRect.cpp"
@@ -150,11 +168,6 @@
#include "bindings/V8HTMLUListElement.cpp"
#include "bindings/V8HTMLVideoElement.cpp"
#include "bindings/V8ImageData.cpp"
-#if PLATFORM(ANDROID)
-// No inspector for now
-#else
-#include "bindings/V8InspectorBackend.cpp"
-#endif
#include "bindings/V8KeyboardEvent.cpp"
#include "bindings/V8Location.cpp"
#include "bindings/V8Media.cpp"
@@ -175,6 +188,7 @@
#include "bindings/V8NodeList.cpp"
#include "bindings/V8Notation.cpp"
#include "bindings/V8OverflowEvent.cpp"
+#include "bindings/V8PageTransitionEvent.cpp"
#include "bindings/V8Plugin.cpp"
#include "bindings/V8PluginArray.cpp"
#include "bindings/V8ProcessingInstruction.cpp"
@@ -207,6 +221,18 @@
#include "bindings/V8XMLHttpRequestUpload.cpp"
#include "bindings/V8XMLSerializer.cpp"
+#if ENABLE(OFFLINE_WEB_APPLICATIONS)
+#include "bindings/V8DOMApplicationCache.cpp"
+#endif
+
+#if ENABLE(DOM_STORAGE)
+#include "bindings/V8Storage.cpp"
+#include "bindings/V8StorageEvent.cpp"
+#endif
+
+#if ENABLE(WEB_SOCKETS)
+#include "bindings/V8WebSocket.cpp"
+#endif
#if ENABLE(DATABASE)
#include "bindings/V8Database.cpp"
@@ -216,14 +242,17 @@
#include "bindings/V8SQLTransaction.cpp"
#endif
-
-#if ENABLE(OFFLINE_WEB_APPLICATIONS)
-#include "bindings/V8DOMApplicationCache.cpp"
+#if ENABLE(WORKERS)
+#include "bindings/V8AbstractWorker.cpp"
+#include "bindings/V8DedicatedWorkerContext.cpp"
+#include "bindings/V8Worker.cpp"
+#include "bindings/V8WorkerContext.cpp"
+#include "bindings/V8WorkerLocation.cpp"
+#include "bindings/V8WorkerNavigator.cpp"
#endif
-#if ENABLE(DOM_STORAGE)
-#include "bindings/V8Storage.cpp"
-#include "bindings/V8StorageEvent.cpp"
+#if ENABLE(SHARED_WORKERS)
+#include "bindings/V8SharedWorker.cpp"
#endif
#if ENABLE(SVG)
@@ -251,7 +280,6 @@
#include "bindings/V8SVGClipPathElement.cpp"
#include "bindings/V8SVGColor.cpp"
#include "bindings/V8SVGCursorElement.cpp"
-#include "bindings/V8SVGDefinitionSrcElement.cpp"
#include "bindings/V8SVGDefsElement.cpp"
#include "bindings/V8SVGDescElement.cpp"
#include "bindings/V8SVGDocument.cpp"
@@ -339,16 +367,6 @@
#include "bindings/V8SVGZoomEvent.cpp"
#endif
-#if ENABLE(WORKERS)
-#include "bindings/V8AbstractWorker.cpp"
-#include "bindings/V8DedicatedWorkerContext.cpp"
-#include "bindings/V8SharedWorker.cpp"
-#include "bindings/V8Worker.cpp"
-#include "bindings/V8WorkerContext.cpp"
-#include "bindings/V8WorkerLocation.cpp"
-#include "bindings/V8WorkerNavigator.cpp"
-#endif
-
#if ENABLE(XPATH)
#include "bindings/V8XPathEvaluator.cpp"
#include "bindings/V8XPathException.cpp"
@@ -360,3 +378,15 @@
#if ENABLE(XSLT)
#include "bindings/V8XSLTProcessor.cpp"
#endif
+
+#if ENABLE(INSPECTOR)
+#include "bindings/V8InspectorBackend.cpp"
+#endif
+
+#if PLATFORM(ANDROID)
+// TODO: Upstream NOTIFICATIONS guard.
+#if ENABLE(NOTIFICATIONS)
+#include "bindings/V8Notification.cpp"
+#include "bindings/V8NotificationCenter.cpp"
+#endif
+#endif
diff --git a/WebCore/bindings/v8/NPV8Object.cpp b/WebCore/bindings/v8/NPV8Object.cpp
index cb2a6c1..13403ec 100644
--- a/WebCore/bindings/v8/NPV8Object.cpp
+++ b/WebCore/bindings/v8/NPV8Object.cpp
@@ -276,7 +276,7 @@ bool _NPN_EvaluateHelper(NPP npp, bool popupsAllowed, NPObject* npObject, NPStri
filename = "npscript";
WebCore::String script = WebCore::String::fromUTF8(npScript->UTF8Characters, npScript->UTF8Length);
- v8::Local<v8::Value> v8result = proxy->evaluate(WebCore::ScriptSourceCode(script, WebCore::KURL(filename)), 0);
+ v8::Local<v8::Value> v8result = proxy->evaluate(WebCore::ScriptSourceCode(script, WebCore::KURL(WebCore::ParsedURLString, filename)), 0);
if (v8result.IsEmpty())
return false;
@@ -413,8 +413,12 @@ bool _NPN_HasMethod(NPP npp, NPObject* npObject, NPIdentifier methodName)
void _NPN_SetException(NPObject* npObject, const NPUTF8 *message)
{
- if (npObject->_class != npScriptObjectClass)
+ if (npObject->_class != npScriptObjectClass) {
+ // We won't be able to find a proper scope for this exception, so just throw it.
+ // This is consistent with JSC, which throws a global exception all the time.
+ V8Proxy::throwError(V8Proxy::GeneralError, message);
return;
+ }
v8::HandleScope handleScope;
v8::Handle<v8::Context> context = toV8Context(0, npObject);
if (context.IsEmpty())
diff --git a/WebCore/bindings/v8/OwnHandle.h b/WebCore/bindings/v8/OwnHandle.h
index 6580674..17c551c 100644
--- a/WebCore/bindings/v8/OwnHandle.h
+++ b/WebCore/bindings/v8/OwnHandle.h
@@ -45,15 +45,13 @@ namespace WebCore {
v8::Handle<T> get() const { return m_handle; }
void set(v8::Handle<T> handle) { clear(); m_handle = v8::Persistent<T>::New(handle); }
- // FIXME: What if we release a weak handle? Won't the callback do the wrong thing?
- v8::Persistent<T> release() { v8::Persistent<T> result = m_handle; m_handle.Clear(); return result; }
- void adopt(v8::Persistent<T> handle) { clear(); m_handle = handle; }
-
// Note: This is clear in the OwnPtr sense, not the v8::Handle sense.
void clear()
{
if (m_handle.IsEmpty())
return;
+ if (m_handle.IsWeak())
+ m_handle.ClearWeak();
m_handle.Dispose();
m_handle.Clear();
}
diff --git a/WebCore/bindings/v8/ScheduledAction.cpp b/WebCore/bindings/v8/ScheduledAction.cpp
index 44e8a37..268e177 100644
--- a/WebCore/bindings/v8/ScheduledAction.cpp
+++ b/WebCore/bindings/v8/ScheduledAction.cpp
@@ -44,8 +44,9 @@
namespace WebCore {
-ScheduledAction::ScheduledAction(v8::Handle<v8::Function> func, int argc, v8::Handle<v8::Value> argv[])
- : m_code(String(), KURL(), 0)
+ScheduledAction::ScheduledAction(v8::Handle<v8::Context> context, v8::Handle<v8::Function> func, int argc, v8::Handle<v8::Value> argv[])
+ : m_context(context)
+ , m_code(String(), KURL(), 0)
{
m_function = v8::Persistent<v8::Function>::New(func);
@@ -107,7 +108,7 @@ void ScheduledAction::execute(V8Proxy* proxy)
LOCK_V8;
v8::HandleScope handleScope;
- v8::Local<v8::Context> v8Context = proxy->context();
+ v8::Handle<v8::Context> v8Context = v8::Local<v8::Context>::New(m_context.get());
if (v8Context.IsEmpty())
return; // JS may not be enabled.
@@ -136,7 +137,7 @@ void ScheduledAction::execute(WorkerContext* workerContext)
if (!m_function.IsEmpty() && m_function->IsFunction()) {
LOCK_V8;
v8::HandleScope handleScope;
- v8::Local<v8::Context> v8Context = scriptController->proxy()->context();
+ v8::Handle<v8::Context> v8Context = v8::Local<v8::Context>::New(m_context.get());
ASSERT(!v8Context.IsEmpty());
v8::Context::Scope scope(v8Context);
m_function->Call(v8Context->Global(), m_argc, m_argv);
diff --git a/WebCore/bindings/v8/ScheduledAction.h b/WebCore/bindings/v8/ScheduledAction.h
index 53694c7..003885f 100644
--- a/WebCore/bindings/v8/ScheduledAction.h
+++ b/WebCore/bindings/v8/ScheduledAction.h
@@ -31,7 +31,9 @@
#ifndef ScheduledAction_h
#define ScheduledAction_h
+#include "OwnHandle.h"
#include "ScriptSourceCode.h"
+#include "V8GCController.h"
#include <v8.h>
@@ -44,9 +46,10 @@ namespace WebCore {
class ScheduledAction {
public:
- ScheduledAction(v8::Handle<v8::Function>, int argc, v8::Handle<v8::Value> argv[]);
- explicit ScheduledAction(const WebCore::String& code, const KURL& url = KURL())
- : m_argc(0)
+ ScheduledAction(v8::Handle<v8::Context>, v8::Handle<v8::Function>, int argc, v8::Handle<v8::Value> argv[]);
+ explicit ScheduledAction(v8::Handle<v8::Context> context, const WebCore::String& code, const KURL& url = KURL())
+ : m_context(context)
+ , m_argc(0)
, m_argv(0)
, m_code(code, url)
{
@@ -61,6 +64,7 @@ namespace WebCore {
void execute(WorkerContext*);
#endif
+ OwnHandle<v8::Context> m_context;
v8::Persistent<v8::Function> m_function;
int m_argc;
v8::Persistent<v8::Value>* m_argv;
diff --git a/WebCore/bindings/v8/ScriptCallFrame.cpp b/WebCore/bindings/v8/ScriptCallFrame.cpp
index ab30862..4c29814 100644
--- a/WebCore/bindings/v8/ScriptCallFrame.cpp
+++ b/WebCore/bindings/v8/ScriptCallFrame.cpp
@@ -42,7 +42,7 @@ namespace WebCore {
ScriptCallFrame::ScriptCallFrame(const String& functionName, const String& urlString, int lineNumber, const v8::Arguments& arguments, unsigned skipArgumentCount)
: m_functionName(functionName)
- , m_sourceURL(urlString)
+ , m_sourceURL(ParsedURLString, urlString)
, m_lineNumber(lineNumber)
{
for (int i = 0; i < arguments.Length(); ++i)
diff --git a/WebCore/bindings/v8/ScriptController.cpp b/WebCore/bindings/v8/ScriptController.cpp
index 48c5115..85af072 100644
--- a/WebCore/bindings/v8/ScriptController.cpp
+++ b/WebCore/bindings/v8/ScriptController.cpp
@@ -51,7 +51,6 @@
#include "npruntime_priv.h"
#include "NPV8Object.h"
#include "ScriptSourceCode.h"
-#include "ScriptState.h"
#include "Widget.h"
#include "XSSAuditor.h"
@@ -61,6 +60,15 @@
namespace WebCore {
+void ScriptController::initializeThreading()
+{
+ static bool initializedThreading = false;
+ if (!initializedThreading) {
+ WTF::initializeThreading();
+ initializedThreading = true;
+ }
+}
+
void ScriptController::setFlags(const char* string, int length)
{
v8::V8::SetFlagsFromString(string, length);
@@ -96,7 +104,6 @@ ScriptController::ScriptController(Frame* frame)
, m_sourceURL(0)
, m_processingTimerCallback(false)
, m_paused(false)
- , m_scriptState(new ScriptState(frame))
, m_proxy(new V8Proxy(frame))
#if ENABLE(NETSCAPE_PLUGIN_API)
, m_windowScriptNPObject(0)
@@ -186,9 +193,14 @@ bool ScriptController::processingUserGesture() const
return false;
}
-void ScriptController::evaluateInNewWorld(const Vector<ScriptSourceCode>& sources, int extensionGroup)
+void ScriptController::evaluateInIsolatedWorld(unsigned worldID, const Vector<ScriptSourceCode>& sources)
+{
+ m_proxy->evaluateInIsolatedWorld(worldID, sources, 0);
+}
+
+void ScriptController::evaluateInIsolatedWorld(unsigned worldID, const Vector<ScriptSourceCode>& sources, int extensionGroup)
{
- m_proxy->evaluateInNewWorld(sources, extensionGroup);
+ m_proxy->evaluateInIsolatedWorld(worldID, sources, extensionGroup);
}
void ScriptController::evaluateInNewContext(const Vector<ScriptSourceCode>& sources, int extensionGroup)
@@ -202,12 +214,7 @@ ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode)
LOCK_V8;
String sourceURL = sourceCode.url();
- if (sourceURL.isNull() && !m_XSSAuditor->canEvaluateJavaScriptURL(sourceCode.source())) {
- // This JavaScript URL is not safe to be evaluated.
- return ScriptValue();
- }
-
- if (!sourceURL.isNull() && !m_XSSAuditor->canEvaluate(sourceCode.source())) {
+ if (!m_XSSAuditor->canEvaluate(sourceCode.source())) {
// This script is not safe to be evaluated.
return ScriptValue();
}
@@ -343,7 +350,7 @@ PassScriptInstance ScriptController::createScriptInstanceForWidget(Widget* widge
return V8ScriptInstance::create(wrapper);
}
-void ScriptController::cleanupScriptObjectsForPlugin(void* nativeHandle)
+void ScriptController::cleanupScriptObjectsForPlugin(Widget* nativeHandle)
{
PluginObjectMap::iterator it = m_pluginObjects.find(nativeHandle);
if (it == m_pluginObjects.end())
diff --git a/WebCore/bindings/v8/ScriptController.h b/WebCore/bindings/v8/ScriptController.h
index d614619..ec15103 100644
--- a/WebCore/bindings/v8/ScriptController.h
+++ b/WebCore/bindings/v8/ScriptController.h
@@ -46,7 +46,6 @@ namespace WebCore {
class Frame;
class HTMLPlugInElement;
class ScriptSourceCode;
- class ScriptState;
class String;
class Widget;
class XSSAuditor;
@@ -60,16 +59,27 @@ namespace WebCore {
// or this accessor should be made JSProxy*
V8Proxy* proxy() { return m_proxy.get(); }
+ // This function must be called from the main thread. It is safe to call it repeatedly.
+ static void initializeThreading();
+
// Evaluate a script file in the environment of this proxy.
// If succeeded, 'succ' is set to true and result is returned
// as a string.
ScriptValue evaluate(const ScriptSourceCode&);
- // Executes JavaScript in a new world associated with the web frame. The
- // script gets its own global scope, its own prototypes for intrinsic
- // JavaScript objects (String, Array, and so-on), and its own wrappers for
- // all DOM nodes and DOM constructors.
- void evaluateInNewWorld(const Vector<ScriptSourceCode>&, int extensionGroup);
+ void evaluateInIsolatedWorld(unsigned worldID, const Vector<ScriptSourceCode>&);
+
+ // Executes JavaScript in an isolated world. The script gets its own global scope,
+ // its own prototypes for intrinsic JavaScript objects (String, Array, and so-on),
+ // and its own wrappers for all DOM nodes and DOM constructors.
+ //
+ // If an isolated world with the specified ID already exists, it is reused.
+ // Otherwise, a new world is created.
+ //
+ // If the worldID is 0, a new world is always created.
+ //
+ // FIXME: Get rid of extensionGroup here.
+ void evaluateInIsolatedWorld(unsigned worldID, const Vector<ScriptSourceCode>&, int extensionGroup);
// Executes JavaScript in a new context associated with the web frame. The
// script gets its own global scope and its own prototypes for intrinsic
@@ -86,8 +96,6 @@ namespace WebCore {
// with what JSC does as well.
ScriptController* windowShell() { return this; }
- ScriptState* state() const { return m_scriptState.get(); }
-
XSSAuditor* xssAuditor() { return m_XSSAuditor.get(); }
void collectGarbage();
@@ -146,7 +154,7 @@ namespace WebCore {
void updateSecurityOrigin();
void clearScriptObjects();
void updatePlatformScriptObjects();
- void cleanupScriptObjectsForPlugin(void*);
+ void cleanupScriptObjectsForPlugin(Widget*);
#if ENABLE(NETSCAPE_PLUGIN_API)
NPObject* createScriptObjectForPluginElement(HTMLPlugInElement*);
@@ -160,9 +168,8 @@ namespace WebCore {
bool m_processingTimerCallback;
bool m_paused;
- OwnPtr<ScriptState> m_scriptState;
OwnPtr<V8Proxy> m_proxy;
- typedef HashMap<void*, NPObject*> PluginObjectMap;
+ typedef HashMap<Widget*, NPObject*> PluginObjectMap;
// A mapping between Widgets and their corresponding script object.
// This list is used so that when the plugin dies, we can immediately
diff --git a/WebCore/bindings/v8/ScriptEventListener.cpp b/WebCore/bindings/v8/ScriptEventListener.cpp
index 7a8aa64..16ca70f 100644
--- a/WebCore/bindings/v8/ScriptEventListener.cpp
+++ b/WebCore/bindings/v8/ScriptEventListener.cpp
@@ -33,7 +33,11 @@
#include "Attribute.h"
#include "Document.h"
+#include "EventListener.h"
#include "Frame.h"
+#include "ScriptScope.h"
+#include "V8AbstractEventListener.h"
+#include "V8Binding.h"
#include "XSSAuditor.h"
namespace WebCore {
@@ -68,4 +72,18 @@ PassRefPtr<V8LazyEventListener> createAttributeEventListener(Frame* frame, Attri
return V8LazyEventListener::create(frame, attr->value(), attr->localName().string(), frame->document()->isSVGDocument());
}
+String getEventListenerHandlerBody(ScriptExecutionContext*, ScriptState* scriptState, EventListener* listener)
+{
+ if (listener->type() != EventListener::JSEventListenerType)
+ return "";
+
+ ScriptScope scope(scriptState);
+ V8AbstractEventListener* v8Listener = static_cast<V8AbstractEventListener*>(listener);
+ v8::Handle<v8::Object> function = v8Listener->getListenerObject();
+ if (function.IsEmpty())
+ return "";
+
+ return toWebCoreStringWithNullCheck(function);
+}
+
} // namespace WebCore
diff --git a/WebCore/bindings/v8/ScriptEventListener.h b/WebCore/bindings/v8/ScriptEventListener.h
index 0171120..ce12a53 100644
--- a/WebCore/bindings/v8/ScriptEventListener.h
+++ b/WebCore/bindings/v8/ScriptEventListener.h
@@ -38,11 +38,14 @@
namespace WebCore {
class Attribute;
+ class EventListener;
class Frame;
class Node;
+ class ScriptState;
PassRefPtr<V8LazyEventListener> createAttributeEventListener(Node*, Attribute*);
PassRefPtr<V8LazyEventListener> createAttributeEventListener(Frame*, Attribute*);
+ String getEventListenerHandlerBody(ScriptExecutionContext*, ScriptState*, EventListener*);
} // namespace WebCore
diff --git a/WebCore/bindings/v8/ScriptFunctionCall.cpp b/WebCore/bindings/v8/ScriptFunctionCall.cpp
index 2fa43d5..9ff6b8c 100644
--- a/WebCore/bindings/v8/ScriptFunctionCall.cpp
+++ b/WebCore/bindings/v8/ScriptFunctionCall.cpp
@@ -31,8 +31,6 @@
#include "config.h"
#include "ScriptFunctionCall.h"
-#include "Document.h"
-#include "Frame.h"
#include "ScriptScope.h"
#include "ScriptState.h"
#include "ScriptString.h"
@@ -40,19 +38,13 @@
#include "V8Binding.h"
#include "V8Proxy.h"
+#include "V8Utilities.h"
#include <v8.h>
#include <wtf/OwnArrayPtr.h>
namespace WebCore {
-static void reportException(ScriptState* scriptState, v8::TryCatch &exceptionCatcher)
-{
- v8::Local<v8::Message> message = exceptionCatcher.Message();
- scriptState->frame()->document()->reportException(toWebCoreString(message->Get()), message->GetLineNumber(), toWebCoreString(message->GetScriptResourceName()));
- exceptionCatcher.Reset();
-}
-
ScriptFunctionCall::ScriptFunctionCall(ScriptState* scriptState, const ScriptObject& thisObject, const String& name)
: m_scriptState(scriptState)
, m_thisObject(thisObject)
diff --git a/WebCore/bindings/v8/ScriptObject.cpp b/WebCore/bindings/v8/ScriptObject.cpp
index b6943bd..ac8051d 100644
--- a/WebCore/bindings/v8/ScriptObject.cpp
+++ b/WebCore/bindings/v8/ScriptObject.cpp
@@ -97,6 +97,13 @@ bool ScriptObject::set(const char* name, int value)
return scope.success();
}
+bool ScriptObject::set(const char* name, unsigned value)
+{
+ ScriptScope scope(m_scriptState);
+ v8Object()->Set(v8::String::New(name), v8::Number::New(value));
+ return scope.success();
+}
+
bool ScriptObject::set(const char* name, bool value)
{
ScriptScope scope(m_scriptState);
diff --git a/WebCore/bindings/v8/ScriptObject.h b/WebCore/bindings/v8/ScriptObject.h
index dcee3a5..f741f89 100644
--- a/WebCore/bindings/v8/ScriptObject.h
+++ b/WebCore/bindings/v8/ScriptObject.h
@@ -53,6 +53,7 @@ namespace WebCore {
bool set(const char* name, double);
bool set(const char* name, long long);
bool set(const char* name, int);
+ bool set(const char* name, unsigned);
bool set(const char* name, bool);
static ScriptObject createNew(ScriptState*);
diff --git a/WebCore/bindings/v8/ScriptObjectQuarantine.cpp b/WebCore/bindings/v8/ScriptObjectQuarantine.cpp
index 053cf68..5dd0dc5 100644
--- a/WebCore/bindings/v8/ScriptObjectQuarantine.cpp
+++ b/WebCore/bindings/v8/ScriptObjectQuarantine.cpp
@@ -35,9 +35,11 @@
#include "Document.h"
#include "DOMWindow.h"
#include "Frame.h"
+#include "InspectorController.h"
#include "Page.h"
#include "ScriptObject.h"
#include "ScriptValue.h"
+#include "Storage.h"
#include "V8Binding.h"
#include "V8Proxy.h"
@@ -61,10 +63,11 @@ bool getQuarantinedScriptObject(Database* database, ScriptObject& quarantinedObj
return false;
}
-bool getQuarantinedScriptObject(Frame* frame, Storage* storage, ScriptObject& quarantinedObject)
+bool getQuarantinedScriptObject(Storage* storage, ScriptObject& quarantinedObject)
{
- ASSERT(frame);
ASSERT(storage);
+ Frame* frame = storage->frame();
+ ASSERT(frame);
#if ENABLE(DOM_STORAGE)
v8::HandleScope handleScope;
@@ -73,7 +76,8 @@ bool getQuarantinedScriptObject(Frame* frame, Storage* storage, ScriptObject& qu
v8::Context::Scope scope(context);
v8::Handle<v8::Value> v8Storage = V8DOMWrapper::convertToV8Object(V8ClassIndex::STORAGE, storage);
- quarantinedObject = ScriptObject(frame->script()->state(), v8::Local<v8::Object>(v8::Object::Cast(*v8Storage)));
+ ScriptState* scriptState = frame->page()->inspectorController()->frontendScriptState();
+ quarantinedObject = ScriptObject(scriptState, v8::Local<v8::Object>(v8::Object::Cast(*v8Storage)));
#else
ASSERT_NOT_REACHED();
quarantinedObject = ScriptObject();
@@ -94,7 +98,8 @@ bool getQuarantinedScriptObject(Node* node, ScriptObject& quarantinedObject)
v8::Context::Scope scope(context);
v8::Handle<v8::Value> v8Node = V8DOMWrapper::convertNodeToV8Object(node);
- quarantinedObject = ScriptObject(frame->script()->state(), v8::Local<v8::Object>(v8::Object::Cast(*v8Node)));
+ ScriptState* scriptState = frame->page()->inspectorController()->frontendScriptState();
+ quarantinedObject = ScriptObject(scriptState, v8::Local<v8::Object>(v8::Object::Cast(*v8Node)));
return true;
}
@@ -111,7 +116,8 @@ bool getQuarantinedScriptObject(DOMWindow* domWindow, ScriptObject& quarantinedO
v8::Context::Scope scope(context);
v8::Handle<v8::Value> v8DomWindow = V8DOMWrapper::convertToV8Object(V8ClassIndex::DOMWINDOW, domWindow);
- quarantinedObject = ScriptObject(frame->script()->state(), v8::Local<v8::Object>(v8::Object::Cast(*v8DomWindow)));
+ ScriptState* scriptState = frame->page()->inspectorController()->frontendScriptState();
+ quarantinedObject = ScriptObject(scriptState, v8::Local<v8::Object>(v8::Object::Cast(*v8DomWindow)));
return true;
}
diff --git a/WebCore/bindings/v8/ScriptObjectQuarantine.h b/WebCore/bindings/v8/ScriptObjectQuarantine.h
index 3b7ccff..712dd9b 100644
--- a/WebCore/bindings/v8/ScriptObjectQuarantine.h
+++ b/WebCore/bindings/v8/ScriptObjectQuarantine.h
@@ -42,7 +42,6 @@ namespace WebCore {
class Database;
class DOMWindow;
- class Frame;
class Node;
class ScriptObject;
class ScriptValue;
@@ -51,7 +50,7 @@ namespace WebCore {
ScriptValue quarantineValue(ScriptState*, const ScriptValue&);
bool getQuarantinedScriptObject(Database* database, ScriptObject& quarantinedObject);
- bool getQuarantinedScriptObject(Frame* frame, Storage* storage, ScriptObject& quarantinedObject);
+ bool getQuarantinedScriptObject(Storage* storage, ScriptObject& quarantinedObject);
bool getQuarantinedScriptObject(Node* node, ScriptObject& quarantinedObject);
bool getQuarantinedScriptObject(DOMWindow* domWindow, ScriptObject& quarantinedObject);
diff --git a/WebCore/bindings/v8/ScriptScope.cpp b/WebCore/bindings/v8/ScriptScope.cpp
index 52cab10..727ab25 100644
--- a/WebCore/bindings/v8/ScriptScope.cpp
+++ b/WebCore/bindings/v8/ScriptScope.cpp
@@ -36,14 +36,13 @@
#include "Document.h"
#include "Frame.h"
#include "V8Binding.h"
-#include "V8Proxy.h"
#include <v8.h>
namespace WebCore {
ScriptScope::ScriptScope(ScriptState* scriptState, bool reportExceptions)
- : m_context(V8Proxy::context(scriptState->frame()))
+ : m_context(scriptState->context())
, m_scope(m_context)
, m_scriptState(scriptState)
, m_reportExceptions(reportExceptions)
diff --git a/WebCore/bindings/v8/ScriptSourceCode.h b/WebCore/bindings/v8/ScriptSourceCode.h
index fea387a..5c16168 100644
--- a/WebCore/bindings/v8/ScriptSourceCode.h
+++ b/WebCore/bindings/v8/ScriptSourceCode.h
@@ -50,7 +50,7 @@ public:
// Not sure if that matters.
ScriptSourceCode(CachedScript* cs)
: m_source(cs->script())
- , m_url(cs->url())
+ , m_url(ParsedURLString, cs->url())
, m_startLine(1)
{
}
diff --git a/WebCore/bindings/v8/ScriptState.cpp b/WebCore/bindings/v8/ScriptState.cpp
index b9e240c..99557b5 100644
--- a/WebCore/bindings/v8/ScriptState.cpp
+++ b/WebCore/bindings/v8/ScriptState.cpp
@@ -42,9 +42,22 @@ namespace WebCore {
ScriptState::ScriptState(Frame* frame)
: m_frame(frame)
+ , m_context(v8::Persistent<v8::Context>::New(V8Proxy::mainWorldContext(frame)))
{
}
+ScriptState::ScriptState(Frame* frame, v8::Handle<v8::Context> context)
+ : m_frame(frame)
+ , m_context(v8::Persistent<v8::Context>::New(context))
+{
+}
+
+ScriptState::~ScriptState()
+{
+ m_context.Dispose();
+ m_context.Clear();
+}
+
ScriptState* scriptStateFromNode(Node* node)
{
// This should be never reached with V8 bindings (WebKit only uses it
@@ -55,7 +68,9 @@ ScriptState* scriptStateFromNode(Node* node)
ScriptState* scriptStateFromPage(Page* page)
{
- return page->mainFrame()->script()->state();
+ // This should be never reached with V8 bindings.
+ ASSERT_NOT_REACHED();
+ return 0;
}
}
diff --git a/WebCore/bindings/v8/ScriptState.h b/WebCore/bindings/v8/ScriptState.h
index 8fbcfa3..e44e914 100644
--- a/WebCore/bindings/v8/ScriptState.h
+++ b/WebCore/bindings/v8/ScriptState.h
@@ -32,16 +32,19 @@
#define ScriptState_h
#include <v8.h>
+#include <wtf/Noncopyable.h>
namespace WebCore {
class Node;
class Page;
class Frame;
- class ScriptState {
+ class ScriptState : public Noncopyable {
public:
ScriptState() { }
ScriptState(Frame* frame);
+ ScriptState(Frame* frame, v8::Handle<v8::Context> context);
+ ~ScriptState();
bool hadException() { return !m_exception.IsEmpty(); }
void setException(v8::Local<v8::Value> exception)
@@ -51,10 +54,15 @@ namespace WebCore {
v8::Local<v8::Value> exception() { return m_exception; }
Frame* frame() const { return m_frame; }
+ v8::Local<v8::Context> context() const
+ {
+ return v8::Local<v8::Context>::New(m_context);
+ }
private:
v8::Local<v8::Value> m_exception;
Frame* m_frame;
+ v8::Persistent<v8::Context> m_context;
};
ScriptState* scriptStateFromNode(Node*);
diff --git a/WebCore/bindings/v8/ScriptValue.h b/WebCore/bindings/v8/ScriptValue.h
index 004851b..a429593 100644
--- a/WebCore/bindings/v8/ScriptValue.h
+++ b/WebCore/bindings/v8/ScriptValue.h
@@ -110,7 +110,12 @@ public:
{
return m_value->IsUndefined();
}
-
+
+ bool isObject() const
+ {
+ return m_value->IsObject();
+ }
+
bool hasNoValue() const
{
return m_value.IsEmpty();
@@ -128,7 +133,7 @@ public:
m_value.Clear();
}
- ~ScriptValue()
+ virtual ~ScriptValue()
{
clear();
}
diff --git a/WebCore/bindings/v8/SerializedScriptValue.h b/WebCore/bindings/v8/SerializedScriptValue.h
new file mode 100644
index 0000000..26a4199
--- /dev/null
+++ b/WebCore/bindings/v8/SerializedScriptValue.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SerializedScriptValue_h
+#define SerializedScriptValue_h
+
+#include "ScriptValue.h"
+#include "V8Binding.h"
+#include <v8.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class SerializedScriptValue : public RefCounted<SerializedScriptValue> {
+public:
+ static PassRefPtr<SerializedScriptValue> create(String string)
+ {
+ return adoptRef(new SerializedScriptValue(string));
+ }
+
+ static PassRefPtr<SerializedScriptValue> create()
+ {
+ return adoptRef(new SerializedScriptValue());
+ }
+
+ PassRefPtr<SerializedScriptValue> release()
+ {
+ RefPtr<SerializedScriptValue> result = adoptRef(new SerializedScriptValue(m_data));
+ m_data = String();
+ return result.release();
+ }
+
+ String toString()
+ {
+ return m_data;
+ }
+
+private:
+ SerializedScriptValue(String string)
+ : m_data(string)
+ {
+ }
+
+ SerializedScriptValue() { }
+ String m_data;
+};
+
+} // namespace WebCore
+
+#endif // SerializedScriptValue_h
diff --git a/WebCore/bindings/v8/SharedPersistent.h b/WebCore/bindings/v8/SharedPersistent.h
new file mode 100644
index 0000000..c1232ae
--- /dev/null
+++ b/WebCore/bindings/v8/SharedPersistent.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SharedPersistent_h
+#define SharedPersistent_h
+
+#include <v8.h>
+
+namespace WebCore {
+
+ // A shareable reference to a v8 persistent handle. Using a shared
+ // persistent any number of objects can share a reference to a v8
+ // object and when it should no longer be accessible the object's
+ // owner can clear it.
+ template <typename T>
+ class SharedPersistent : public WTF::RefCounted<SharedPersistent<T> > {
+ public:
+ void set(v8::Persistent<T> value)
+ {
+ m_value = value;
+ }
+ v8::Persistent<T> get()
+ {
+ return m_value;
+ }
+ void disposeHandle()
+ {
+ if (!m_value.IsEmpty()) {
+ m_value.Dispose();
+ m_value.Clear();
+ }
+ }
+ static PassRefPtr<SharedPersistent<T> > create(v8::Persistent<T> value)
+ {
+ return adoptRef(new SharedPersistent<T>(value));
+ }
+ static PassRefPtr<SharedPersistent<T> > create()
+ {
+ return create(v8::Persistent<T>());
+ }
+ private:
+ explicit SharedPersistent(v8::Persistent<T> value) : m_value(value) { }
+ v8::Persistent<T> m_value;
+ };
+
+} // namespace WebCore
+
+#endif // SharedPersistent_h
diff --git a/WebCore/bindings/v8/V8AbstractEventListener.cpp b/WebCore/bindings/v8/V8AbstractEventListener.cpp
index 0c81846..032b6b9 100644
--- a/WebCore/bindings/v8/V8AbstractEventListener.cpp
+++ b/WebCore/bindings/v8/V8AbstractEventListener.cpp
@@ -31,17 +31,30 @@
#include "config.h"
#include "V8AbstractEventListener.h"
+#include "DateExtension.h"
#include "Document.h"
#include "Event.h"
#include "Frame.h"
#include "Tokenizer.h"
#include "V8Binding.h"
+#include "V8EventListenerList.h"
+#include "V8Proxy.h"
+#include "V8Utilities.h"
namespace WebCore {
-V8AbstractEventListener::V8AbstractEventListener(Frame* frame, bool isAttribute)
- : m_isAttribute(isAttribute)
+static void weakEventListenerCallback(v8::Persistent<v8::Value>, void* parameter)
+{
+ V8AbstractEventListener* listener = static_cast<V8AbstractEventListener*>(parameter);
+ listener->disposeListenerObject();
+}
+
+V8AbstractEventListener::V8AbstractEventListener(Frame* frame, PassRefPtr<V8ListenerGuard> guard, bool isAttribute)
+ : EventListener(JSEventListenerType)
+ , m_isWeak(true)
+ , m_isAttribute(isAttribute)
, m_frame(frame)
+ , m_guard(guard)
, m_lineNumber(0)
, m_columnNumber(0)
{
@@ -51,8 +64,7 @@ V8AbstractEventListener::V8AbstractEventListener(Frame* frame, bool isAttribute)
// We might be called directly from the parser.
v8::HandleScope handleScope;
- m_context.set(V8Proxy::context(m_frame));
- m_context.makeWeak();
+ m_context = V8Proxy::shared_context(m_frame);
// Get the position in the source if any.
if (m_isAttribute && m_frame->document()->tokenizer()) {
@@ -61,52 +73,17 @@ V8AbstractEventListener::V8AbstractEventListener(Frame* frame, bool isAttribute)
}
}
-void V8AbstractEventListener::invokeEventHandler(v8::Handle<v8::Context> v8Context, Event* event, v8::Handle<v8::Value> jsEvent, bool isWindowEvent)
+V8AbstractEventListener::~V8AbstractEventListener()
{
- // We push the event being processed into the global object, so that it can be exposed by DOMWindow's bindings.
- v8::Local<v8::String> eventSymbol = v8::String::NewSymbol("event");
- v8::Local<v8::Value> returnValue;
-
- {
- // Catch exceptions thrown in the event handler so they do not propagate to javascript code that caused the event to fire.
- v8::TryCatch tryCatch;
- tryCatch.SetVerbose(true);
-
- // Save the old 'event' property so we can restore it later.
- v8::Local<v8::Value> savedEvent = v8Context->Global()->GetHiddenValue(eventSymbol);
- tryCatch.Reset();
-
- // Make the event available in the global object, so DOMWindow can expose it.
- v8Context->Global()->SetHiddenValue(eventSymbol, jsEvent);
- tryCatch.Reset();
-
- // Call the event handler.
- returnValue = callListenerFunction(jsEvent, event, isWindowEvent);
- tryCatch.Reset();
-
- // Restore the old event. This must be done for all exit paths through this method.
- if (savedEvent.IsEmpty())
- v8Context->Global()->SetHiddenValue(eventSymbol, v8::Undefined());
- else
- v8Context->Global()->SetHiddenValue(eventSymbol, savedEvent);
- tryCatch.Reset();
+ if (!m_listener.IsEmpty()) {
+ v8::HandleScope scope;
+ v8::Local<v8::Object> listener = v8::Local<v8::Object>::New(m_listener);
+ V8EventListenerList::clearWrapper(listener, m_isAttribute);
}
-
- ASSERT(!V8Proxy::handleOutOfMemory() || returnValue.IsEmpty());
-
- if (returnValue.IsEmpty())
- return;
-
- if (!returnValue->IsNull() && !returnValue->IsUndefined() && event->storesResultAsString())
- event->storeResult(toWebCoreString(returnValue));
-
- // Prevent default action if the return value is false;
- // FIXME: Add example, and reference to bug entry.
- if (m_isAttribute && returnValue->IsBoolean() && !returnValue->BooleanValue())
- event->preventDefault();
+ disposeListenerObject();
}
-void V8AbstractEventListener::handleEvent(Event* event, bool isWindowEvent)
+void V8AbstractEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext, Event* event)
{
// EventListener could be disconnected from the frame.
if (disconnected())
@@ -119,7 +96,12 @@ void V8AbstractEventListener::handleEvent(Event* event, bool isWindowEvent)
LOCK_V8;
v8::HandleScope handleScope;
- v8::Handle<v8::Context> v8Context = m_context.get();
+ if (!m_context)
+ return;
+
+ // Create a new local handle since the persistent handle stored in
+ // m_context may be disposed before we're done.
+ v8::Handle<v8::Context> v8Context = v8::Local<v8::Context>::New(m_context->get());
if (v8Context.IsEmpty())
return;
@@ -132,7 +114,7 @@ void V8AbstractEventListener::handleEvent(Event* event, bool isWindowEvent)
// Get the V8 wrapper for the event object.
v8::Handle<v8::Value> jsEvent = V8DOMWrapper::convertEventToV8Object(event);
- invokeEventHandler(v8Context, event, jsEvent, isWindowEvent);
+ invokeEventHandler(v8Context, event, jsEvent);
Document::updateStyleForAllDocuments();
}
@@ -148,14 +130,83 @@ void V8AbstractEventListener::disposeListenerObject()
}
}
-v8::Local<v8::Object> V8AbstractEventListener::getReceiverObject(Event* event, bool isWindowEvent)
+void V8AbstractEventListener::setListenerObject(v8::Handle<v8::Object> listener)
+{
+ disposeListenerObject();
+ m_listener = v8::Persistent<v8::Object>::New(listener);
+#ifndef NDEBUG
+ V8GCController::registerGlobalHandle(EVENT_LISTENER, this, m_listener);
+#endif
+ if (m_isWeak)
+ m_listener.MakeWeak(this, &weakEventListenerCallback);
+}
+
+void V8AbstractEventListener::invokeEventHandler(v8::Handle<v8::Context> v8Context, Event* event, v8::Handle<v8::Value> jsEvent)
+{
+ // We push the event being processed into the global object, so that it can be exposed by DOMWindow's bindings.
+ v8::Local<v8::String> eventSymbol = v8::String::NewSymbol("event");
+ v8::Local<v8::Value> returnValue;
+
+ // In beforeunload/unload handlers, we want to avoid sleeps which do tight loops of calling Date.getTime().
+ if (event->type() == "beforeunload" || event->type() == "unload")
+ DateExtension::get()->setAllowSleep(false);
+
+ {
+ // Catch exceptions thrown in the event handler so they do not propagate to javascript code that caused the event to fire.
+ v8::TryCatch tryCatch;
+ tryCatch.SetVerbose(true);
+
+ // Save the old 'event' property so we can restore it later.
+ v8::Local<v8::Value> savedEvent = v8Context->Global()->GetHiddenValue(eventSymbol);
+ tryCatch.Reset();
+
+ // Make the event available in the global object, so DOMWindow can expose it.
+ v8Context->Global()->SetHiddenValue(eventSymbol, jsEvent);
+ tryCatch.Reset();
+
+ // Call the event handler.
+ tryCatch.SetVerbose(false); // We do not want to report the exception to the inspector console.
+ returnValue = callListenerFunction(jsEvent, event);
+ if (!tryCatch.CanContinue())
+ return;
+
+ // If an error occurs while handling the event, it should be reported.
+ if (tryCatch.HasCaught()) {
+ reportException(0, tryCatch);
+ tryCatch.Reset();
+ }
+
+ // Restore the old event. This must be done for all exit paths through this method.
+ tryCatch.SetVerbose(true);
+ if (savedEvent.IsEmpty())
+ v8Context->Global()->SetHiddenValue(eventSymbol, v8::Undefined());
+ else
+ v8Context->Global()->SetHiddenValue(eventSymbol, savedEvent);
+ tryCatch.Reset();
+ }
+
+ if (event->type() == "beforeunload" || event->type() == "unload")
+ DateExtension::get()->setAllowSleep(true);
+
+ ASSERT(!V8Proxy::handleOutOfMemory() || returnValue.IsEmpty());
+
+ if (returnValue.IsEmpty())
+ return;
+
+ if (!returnValue->IsNull() && !returnValue->IsUndefined() && event->storesResultAsString())
+ event->storeResult(toWebCoreString(returnValue));
+
+ // Prevent default action if the return value is false;
+ // FIXME: Add example, and reference to bug entry.
+ if (m_isAttribute && returnValue->IsBoolean() && !returnValue->BooleanValue())
+ event->preventDefault();
+}
+
+v8::Local<v8::Object> V8AbstractEventListener::getReceiverObject(Event* event)
{
if (!m_listener.IsEmpty() && !m_listener->IsFunction())
return v8::Local<v8::Object>::New(m_listener);
- if (isWindowEvent)
- return v8::Context::GetCurrent()->Global();
-
EventTarget* target = event->currentTarget();
v8::Handle<v8::Value> value = V8DOMWrapper::convertEventTargetToV8Object(target);
if (value.IsEmpty())
diff --git a/WebCore/bindings/v8/V8AbstractEventListener.h b/WebCore/bindings/v8/V8AbstractEventListener.h
index 1521941..c7736be 100644
--- a/WebCore/bindings/v8/V8AbstractEventListener.h
+++ b/WebCore/bindings/v8/V8AbstractEventListener.h
@@ -33,12 +33,39 @@
#include "EventListener.h"
#include "OwnHandle.h"
+#include "SharedPersistent.h"
#include <v8.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
namespace WebCore {
class Event;
class Frame;
+ class V8Proxy;
+
+ // Shared by listener objects and V8Proxy so that V8Proxy can
+ // silence listeners when needed.
+ class V8ListenerGuard : public RefCounted<V8ListenerGuard> {
+ public:
+ static PassRefPtr<V8ListenerGuard> create()
+ {
+ return adoptRef(new V8ListenerGuard);
+ }
+
+ bool isDisconnected() const { return m_disconnected; }
+
+ void disconnectListeners()
+ {
+ m_disconnected = true;
+ }
+
+ private:
+ V8ListenerGuard()
+ : m_disconnected(false) { }
+
+ bool m_disconnected;
+ };
// There are two kinds of event listeners: HTML or non-HMTL. onload,
// onfocus, etc (attributes) are always HTML event handler type; Event
@@ -50,54 +77,94 @@ namespace WebCore {
// but ALLOWs duplicated non-HTML event handlers.
class V8AbstractEventListener : public EventListener {
public:
- virtual ~V8AbstractEventListener() { }
+ virtual ~V8AbstractEventListener();
+
+ static const V8AbstractEventListener* cast(const EventListener* listener)
+ {
+ return listener->type() == JSEventListenerType
+ ? static_cast<const V8AbstractEventListener*>(listener)
+ : 0;
+ }
+
+ static V8AbstractEventListener* cast(EventListener* listener)
+ {
+ return const_cast<V8AbstractEventListener*>(cast(const_cast<const EventListener*>(listener)));
+ }
+
+ // Implementation of EventListener interface.
+
+ virtual bool operator==(const EventListener& other) { return this == &other; }
+
+ virtual void handleEvent(ScriptExecutionContext*, Event*);
// Returns the owner frame of the listener.
Frame* frame() { return m_frame; }
- virtual void handleEvent(Event*, bool isWindowEvent);
- void invokeEventHandler(v8::Handle<v8::Context>, Event*, v8::Handle<v8::Value> jsEvent, bool isWindowEvent);
+ virtual bool isLazy() const { return false; }
// Returns the listener object, either a function or an object.
- virtual v8::Local<v8::Object> getListenerObject()
+ v8::Local<v8::Object> getListenerObject()
{
+ prepareListenerObject();
return v8::Local<v8::Object>::New(m_listener);
}
+ v8::Local<v8::Object> getExistingListenerObject()
+ {
+ return v8::Local<v8::Object>::New(m_listener);
+ }
+
+ bool hasExistingListenerObject()
+ {
+ return !m_listener.IsEmpty();
+ }
+
// Dispose listener object and clear the handle.
void disposeListenerObject();
- virtual bool disconnected() const { return !m_frame; }
+ // Detach the listener from its owner frame.
+ void disconnectFrame() { m_frame = 0; }
- virtual bool isObjectListener() const { return false; }
+ virtual bool disconnected() const { return m_guard && m_guard->isDisconnected(); }
protected:
- v8::Persistent<v8::Object> m_listener;
+ V8AbstractEventListener(Frame*, PassRefPtr<V8ListenerGuard>, bool isAttribute);
- // Indicates if this is an HTML type listener.
- bool m_isAttribute;
+ virtual void prepareListenerObject() { }
- private:
- V8AbstractEventListener(Frame*, bool isInline);
+ void setListenerObject(v8::Handle<v8::Object> listener);
- virtual v8::Local<v8::Value> callListenerFunction(v8::Handle<v8::Value> jsevent, Event*, bool isWindowEvent) = 0;
+ void invokeEventHandler(v8::Handle<v8::Context>, Event*, v8::Handle<v8::Value> jsEvent);
// Get the receiver object to use for event listener call.
- v8::Local<v8::Object> getReceiverObject(Event*, bool isWindowEvent);
+ v8::Local<v8::Object> getReceiverObject(Event*);
+
+ int lineNumber() const { return m_lineNumber; }
+
+ private:
+ // Implementation of EventListener function.
+ virtual bool virtualisAttribute() const { return m_isAttribute; }
+
+ virtual v8::Local<v8::Value> callListenerFunction(v8::Handle<v8::Value> jsevent, Event*) = 0;
+
+ v8::Persistent<v8::Object> m_listener;
+
+ // Indicates if the above handle is weak.
+ bool m_isWeak;
+
+ // Indicates if this is an HTML type listener.
+ bool m_isAttribute;
// Frame to which the event listener is attached to. An event listener must be destroyed before its owner frame is
// deleted. See fast/dom/replaceChild.html
// FIXME: this could hold m_frame live until the event listener is deleted.
Frame* m_frame;
- OwnHandle<v8::Context> m_context;
+ RefPtr<SharedPersistent<v8::Context> > m_context;
+ RefPtr<V8ListenerGuard> m_guard;
// Position in the HTML source for HTML event listeners.
int m_lineNumber;
int m_columnNumber;
-
- friend class V8EventListener;
- friend class V8ObjectEventListener;
- friend class V8LazyEventListener;
};
} // namespace WebCore
diff --git a/WebCore/bindings/v8/V8Binding.cpp b/WebCore/bindings/v8/V8Binding.cpp
index 0da910b..9ac7eae 100644
--- a/WebCore/bindings/v8/V8Binding.cpp
+++ b/WebCore/bindings/v8/V8Binding.cpp
@@ -55,7 +55,8 @@ public:
#ifndef NDEBUG
m_threadId = WTF::currentThread();
#endif
- v8::V8::AdjustAmountOfExternalAllocatedMemory(2 * length());
+ ASSERT(!string.isNull());
+ v8::V8::AdjustAmountOfExternalAllocatedMemory(2 * string.length());
}
explicit WebCoreStringResource(const AtomicString& string)
@@ -65,7 +66,8 @@ public:
#ifndef NDEBUG
m_threadId = WTF::currentThread();
#endif
- v8::V8::AdjustAmountOfExternalAllocatedMemory(2 * length());
+ ASSERT(!string.isNull());
+ v8::V8::AdjustAmountOfExternalAllocatedMemory(2 * string.length());
}
virtual ~WebCoreStringResource()
@@ -73,18 +75,18 @@ public:
#ifndef NDEBUG
ASSERT(m_threadId == WTF::currentThread());
#endif
- int reducedExternalMemory = -2 * length();
- if (!m_plainString.impl()->inTable())
+ int reducedExternalMemory = -2 * m_plainString.length();
+ if (m_plainString.impl() != m_atomicString.impl() && !m_atomicString.isNull())
reducedExternalMemory *= 2;
v8::V8::AdjustAmountOfExternalAllocatedMemory(reducedExternalMemory);
}
- const uint16_t* data() const
+ virtual const uint16_t* data() const
{
- return reinterpret_cast<const uint16_t*>(m_plainString.characters());
+ return reinterpret_cast<const uint16_t*>(m_plainString.impl()->characters());
}
- size_t length() const { return m_plainString.length(); }
+ virtual size_t length() const { return m_plainString.impl()->length(); }
String webcoreString() { return m_plainString; }
@@ -95,12 +97,17 @@ public:
#endif
if (m_atomicString.isNull()) {
m_atomicString = AtomicString(m_plainString);
- if (!m_plainString.impl()->inTable())
- v8::V8::AdjustAmountOfExternalAllocatedMemory(2 * length());
+ ASSERT(!m_atomicString.isNull());
+ if (m_plainString.impl() != m_atomicString.impl())
+ v8::V8::AdjustAmountOfExternalAllocatedMemory(2 * m_atomicString.length());
}
return m_atomicString;
}
+ // Returns right string type based on a dummy parameter.
+ String string(String) { return webcoreString(); }
+ AtomicString string(AtomicString) { return atomicString(); }
+
static WebCoreStringResource* toStringResource(v8::Handle<v8::String> v8String)
{
return static_cast<WebCoreStringResource*>(v8String->GetExternalStringResource());
@@ -121,12 +128,17 @@ private:
#endif
};
-String v8StringToWebCoreString(v8::Handle<v8::String> v8String, ExternalMode external,
- StringType type)
+enum ExternalMode {
+ Externalize,
+ DoNotExternalize
+};
+
+template <typename StringType>
+static StringType v8StringToWebCoreString(v8::Handle<v8::String> v8String, ExternalMode external)
{
WebCoreStringResource* stringResource = WebCoreStringResource::toStringResource(v8String);
if (stringResource)
- return stringResource->webcoreString();
+ return stringResource->string(StringType());
int length = v8String->Length();
if (!length) {
@@ -134,44 +146,42 @@ String v8StringToWebCoreString(v8::Handle<v8::String> v8String, ExternalMode ext
return StringImpl::empty();
}
- UChar* buffer;
- String result = String::createUninitialized(length, buffer);
- v8String->Write(reinterpret_cast<uint16_t*>(buffer), 0, length);
-
- if (type == AtomicStringType)
- result = AtomicString(result);
+ StringType result;
+ static const int inlineBufferSize = 16;
+ if (length <= inlineBufferSize) {
+ UChar inlineBuffer[inlineBufferSize];
+ v8String->Write(reinterpret_cast<uint16_t*>(inlineBuffer), 0, length);
+ result = StringType(inlineBuffer, length);
+ } else {
+ UChar* buffer;
+ String tmp = String::createUninitialized(length, buffer);
+ v8String->Write(reinterpret_cast<uint16_t*>(buffer), 0, length);
+ result = StringType(tmp);
+ }
- if (external == Externalize) {
- WebCoreStringResource* resource = new WebCoreStringResource(result);
- if (!v8String->MakeExternal(resource)) {
+ if (external == Externalize && v8String->CanMakeExternal()) {
+ stringResource = new WebCoreStringResource(result);
+ if (!v8String->MakeExternal(stringResource)) {
// In case of a failure delete the external resource as it was not used.
- delete resource;
+ delete stringResource;
}
}
return result;
}
-AtomicString v8StringToAtomicWebCoreString(v8::Handle<v8::String> v8String)
+String v8StringToWebCoreString(v8::Handle<v8::String> v8String)
{
- WebCoreStringResource* stringResource = WebCoreStringResource::toStringResource(v8String);
- if (!stringResource) {
- // If this string hasn't been externalized, we force it now.
- String plain = v8StringToWebCoreString(v8String, Externalize, AtomicStringType);
- // If the string is empty there's no room to cache an atomic
- // string so we bail out.
- if (plain.isEmpty())
- return plain;
- stringResource = WebCoreStringResource::toStringResource(v8String);
- ASSERT(stringResource != NULL);
- }
- return stringResource->atomicString();
+ return v8StringToWebCoreString<String>(v8String, Externalize);
}
-String v8ValueToWebCoreString(v8::Handle<v8::Value> object)
+AtomicString v8StringToAtomicWebCoreString(v8::Handle<v8::String> v8String)
{
- if (object->IsString())
- return v8StringToWebCoreString(v8::Handle<v8::String>::Cast(object), Externalize, PlainStringType);
+ return v8StringToWebCoreString<AtomicString>(v8String, Externalize);
+}
+String v8NonStringValueToWebCoreString(v8::Handle<v8::Value> object)
+{
+ ASSERT(!object->IsString());
if (object->IsInt32()) {
int value = object->Int32Value();
// Most numbers used are <= 100. Even if they aren't used there's very little in using the space.
@@ -197,20 +207,13 @@ String v8ValueToWebCoreString(v8::Handle<v8::Value> object)
throwError(block.Exception());
return StringImpl::empty();
}
- return v8StringToWebCoreString(v8String, DoNotExternalize, PlainStringType);
-}
-
-AtomicString v8ValueToAtomicWebCoreString(v8::Handle<v8::Value> v8Value)
-{
- if (v8Value->IsString())
- return v8StringToAtomicWebCoreString(v8::Handle<v8::String>::Cast(v8Value));
- String string = v8ValueToWebCoreString(v8Value);
- return AtomicString(string);
+ return v8StringToWebCoreString<String>(v8String, DoNotExternalize);
}
-v8::Handle<v8::String> v8String(const String& string)
+AtomicString v8NonStringValueToAtomicWebCoreString(v8::Handle<v8::Value> object)
{
- return v8ExternalString(string);
+ ASSERT(!object->IsString());
+ return AtomicString(v8NonStringValueToWebCoreString(object));
}
static bool stringImplCacheEnabled = false;
@@ -261,7 +264,7 @@ v8::Local<v8::String> v8ExternalString(const String& string)
StringCache& stringCache = getStringCache();
v8::String* cachedV8String = stringCache.get(stringImpl);
if (cachedV8String)
- return v8::Local<v8::String>(cachedV8String);
+ return v8::Local<v8::String>::New(v8::Handle<v8::String>(cachedV8String));
v8::Local<v8::String> newString = makeExternalString(string);
if (newString.IsEmpty())
diff --git a/WebCore/bindings/v8/V8Binding.h b/WebCore/bindings/v8/V8Binding.h
index 4f36f00..a09102d 100644
--- a/WebCore/bindings/v8/V8Binding.h
+++ b/WebCore/bindings/v8/V8Binding.h
@@ -31,6 +31,7 @@
#ifndef V8Binding_h
#define V8Binding_h
+#include "AtomicString.h"
#include "MathExtras.h"
#include "PlatformString.h"
@@ -38,32 +39,31 @@
namespace WebCore {
- enum ExternalMode {
- Externalize,
- DoNotExternalize
- };
-
- enum StringType {
- PlainStringType,
- AtomicStringType
- };
-
// Convert v8 types to a WebCore::String. If the V8 string is not already
// an external string then it is transformed into an external string at this
// point to avoid repeated conversions.
- String v8StringToWebCoreString(v8::Handle<v8::String>, ExternalMode mode, StringType type);
- String v8ValueToWebCoreString(v8::Handle<v8::Value>);
+ String v8StringToWebCoreString(v8::Handle<v8::String>);
+ String v8NonStringValueToWebCoreString(v8::Handle<v8::Value>);
+ inline String v8ValueToWebCoreString(v8::Handle<v8::Value> value)
+ {
+ if (value->IsString())
+ return v8StringToWebCoreString(v8::Handle<v8::String>::Cast(value));
+ return v8NonStringValueToWebCoreString(value);
+ }
// Convert v8 types to a WebCore::AtomicString.
AtomicString v8StringToAtomicWebCoreString(v8::Handle<v8::String>);
- AtomicString v8ValueToAtomicWebCoreString(v8::Handle<v8::Value>);
-
- // Convert a string to a V8 string.
- v8::Handle<v8::String> v8String(const String&);
+ AtomicString v8NonStringValueToAtomicWebCoreString(v8::Handle<v8::Value>);
+ inline AtomicString v8ValueToAtomicWebCoreString(v8::Handle<v8::Value> value)
+ {
+ if (value->IsString())
+ return v8StringToAtomicWebCoreString(v8::Handle<v8::String>::Cast(value));
+ return v8NonStringValueToAtomicWebCoreString(value);
+ }
- inline String toString(const String& string)
- {
- return string;
+ inline String toString(const String& string)
+ {
+ return string;
}
// Return a V8 external string that shares the underlying buffer with the given
@@ -71,6 +71,12 @@ namespace WebCore {
// underlying buffer alive while the string is still live in the V8 engine.
v8::Local<v8::String> v8ExternalString(const String&);
+ // Convert a string to a V8 string.
+ inline v8::Handle<v8::String> v8String(const String& string)
+ {
+ return v8ExternalString(string);
+ }
+
// Enables caching v8 wrappers created for WebCore::StringImpl. Currently this cache requires
// all the calls (both to convert WebCore::String to v8::String and to GC the handle)
// to be performed on the main thread.
@@ -145,7 +151,7 @@ namespace WebCore {
{
return value ? v8::True() : v8::False();
}
-
+
inline String toWebCoreStringWithNullCheck(v8::Handle<v8::Value> value)
{
if (value->IsNull())
@@ -153,6 +159,13 @@ namespace WebCore {
return v8ValueToWebCoreString(value);
}
+ inline AtomicString v8ValueToAtomicWebCoreStringWithNullCheck(v8::Handle<v8::Value> value)
+ {
+ if (value->IsNull())
+ return AtomicString();
+ return v8ValueToAtomicWebCoreString(value);
+ }
+
inline String toWebCoreStringWithNullOrUndefinedCheck(v8::Handle<v8::Value> value)
{
if (value->IsNull() || value->IsUndefined())
diff --git a/WebCore/bindings/v8/V8DOMWrapper.cpp b/WebCore/bindings/v8/V8DOMWrapper.cpp
index 8a9741a..5a6b901 100644
--- a/WebCore/bindings/v8/V8DOMWrapper.cpp
+++ b/WebCore/bindings/v8/V8DOMWrapper.cpp
@@ -31,21 +31,32 @@
#include "config.h"
#include "V8DOMWrapper.h"
+#include "CSSMutableStyleDeclaration.h"
#if PLATFORM(CHROMIUM)
#include "ChromiumBridge.h"
#endif
-#include "CSSMutableStyleDeclaration.h"
#include "DOMObjectsInclude.h"
#include "DocumentLoader.h"
#include "FrameLoaderClient.h"
+#include "Notification.h"
+#if PLATFORM(ANDROID)
+// TODO: Upstream SVG guard.
+#if ENABLE(SVG)
+#include "SVGElementInstance.h"
+#endif
+#endif
#include "ScriptController.h"
+#include "V8AbstractEventListener.h"
#include "V8Binding.h"
#include "V8Collection.h"
#include "V8CustomBinding.h"
+#include "V8CustomEventListener.h"
#include "V8DOMMap.h"
#include "V8DOMWindow.h"
+#include "V8EventListenerList.h"
#include "V8Index.h"
#include "V8IsolatedWorld.h"
+#include "V8Proxy.h"
#include "WorkerContextExecutionProxy.h"
#include <algorithm>
@@ -337,6 +348,7 @@ v8::Persistent<v8::FunctionTemplate> V8DOMWrapper::getTemplate(V8ClassIndex::V8W
descriptor->PrototypeTemplate()->SetNamedPropertyHandler(USE_NAMED_PROPERTY_GETTER(DOMWindow));
descriptor->PrototypeTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(DOMWindow));
+ descriptor->PrototypeTemplate()->SetInternalFieldCount(V8Custom::kDOMWindowInternalFieldCount);
descriptor->SetHiddenPrototype(true);
@@ -381,6 +393,24 @@ v8::Persistent<v8::FunctionTemplate> V8DOMWrapper::getTemplate(V8ClassIndex::V8W
break;
}
+#if ENABLE(NOTIFICATIONS)
+ case V8ClassIndex::NOTIFICATION: {
+ // Reserve one more internal field for keeping event listeners.
+ v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate();
+ instanceTemplate->SetInternalFieldCount(V8Custom::kNotificationInternalFieldCount);
+ break;
+ }
+#endif // NOTIFICATIONS
+
+#if ENABLE(SVG)
+ case V8ClassIndex::SVGELEMENTINSTANCE: {
+ // Reserve one more internal field for keeping event listeners.
+ v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate();
+ instanceTemplate->SetInternalFieldCount(V8Custom::kSVGElementInstanceInternalFieldCount);
+ break;
+ }
+#endif
+
#if ENABLE(WORKERS)
case V8ClassIndex::ABSTRACTWORKER: {
// Reserve one more internal field for keeping event listeners.
@@ -424,20 +454,42 @@ v8::Persistent<v8::FunctionTemplate> V8DOMWrapper::getTemplate(V8ClassIndex::V8W
}
#endif
+#if ENABLE(3D_CANVAS)
// The following objects are created from JavaScript.
- case V8ClassIndex::DOMPARSER:
- descriptor->SetCallHandler(USE_CALLBACK(DOMParserConstructor));
+ case V8ClassIndex::CANVASARRAYBUFFER:
+ descriptor->SetCallHandler(USE_CALLBACK(CanvasArrayBufferConstructor));
break;
-#if ENABLE(VIDEO)
- case V8ClassIndex::HTMLAUDIOELEMENT:
- descriptor->SetCallHandler(USE_CALLBACK(HTMLAudioElementConstructor));
+ case V8ClassIndex::CANVASBYTEARRAY:
+ descriptor->SetCallHandler(USE_CALLBACK(CanvasByteArrayConstructor));
+ descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(CanvasByteArray), USE_INDEXED_PROPERTY_SETTER(CanvasByteArray));
break;
-#endif
- case V8ClassIndex::HTMLIMAGEELEMENT:
- descriptor->SetCallHandler(USE_CALLBACK(HTMLImageElementConstructor));
+ case V8ClassIndex::CANVASFLOATARRAY:
+ descriptor->SetCallHandler(USE_CALLBACK(CanvasFloatArrayConstructor));
+ descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(CanvasFloatArray), USE_INDEXED_PROPERTY_SETTER(CanvasFloatArray));
break;
- case V8ClassIndex::HTMLOPTIONELEMENT:
- descriptor->SetCallHandler(USE_CALLBACK(HTMLOptionElementConstructor));
+ case V8ClassIndex::CANVASINTARRAY:
+ descriptor->SetCallHandler(USE_CALLBACK(CanvasIntArrayConstructor));
+ descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(CanvasIntArray), USE_INDEXED_PROPERTY_SETTER(CanvasIntArray));
+ break;
+ case V8ClassIndex::CANVASSHORTARRAY:
+ descriptor->SetCallHandler(USE_CALLBACK(CanvasShortArrayConstructor));
+ descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(CanvasShortArray), USE_INDEXED_PROPERTY_SETTER(CanvasShortArray));
+ break;
+ case V8ClassIndex::CANVASUNSIGNEDBYTEARRAY:
+ descriptor->SetCallHandler(USE_CALLBACK(CanvasUnsignedByteArrayConstructor));
+ descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(CanvasUnsignedByteArray), USE_INDEXED_PROPERTY_SETTER(CanvasUnsignedByteArray));
+ break;
+ case V8ClassIndex::CANVASUNSIGNEDINTARRAY:
+ descriptor->SetCallHandler(USE_CALLBACK(CanvasUnsignedIntArrayConstructor));
+ descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(CanvasUnsignedIntArray), USE_INDEXED_PROPERTY_SETTER(CanvasUnsignedIntArray));
+ break;
+ case V8ClassIndex::CANVASUNSIGNEDSHORTARRAY:
+ descriptor->SetCallHandler(USE_CALLBACK(CanvasUnsignedShortArrayConstructor));
+ descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(CanvasUnsignedShortArray), USE_INDEXED_PROPERTY_SETTER(CanvasUnsignedShortArray));
+ break;
+#endif
+ case V8ClassIndex::DOMPARSER:
+ descriptor->SetCallHandler(USE_CALLBACK(DOMParserConstructor));
break;
case V8ClassIndex::WEBKITCSSMATRIX:
descriptor->SetCallHandler(USE_CALLBACK(WebKitCSSMatrixConstructor));
@@ -445,6 +497,15 @@ v8::Persistent<v8::FunctionTemplate> V8DOMWrapper::getTemplate(V8ClassIndex::V8W
case V8ClassIndex::WEBKITPOINT:
descriptor->SetCallHandler(USE_CALLBACK(WebKitPointConstructor));
break;
+#if ENABLE(WEB_SOCKETS)
+ case V8ClassIndex::WEBSOCKET: {
+ // Reserve one more internal field for keeping event listeners.
+ v8::Local<v8::ObjectTemplate> instanceTemplate = descriptor->InstanceTemplate();
+ instanceTemplate->SetInternalFieldCount(V8Custom::kWebSocketInternalFieldCount);
+ descriptor->SetCallHandler(USE_CALLBACK(WebSocketConstructor));
+ break;
+ }
+#endif
case V8ClassIndex::XMLSERIALIZER:
descriptor->SetCallHandler(USE_CALLBACK(XMLSerializerConstructor));
break;
@@ -482,6 +543,9 @@ v8::Persistent<v8::FunctionTemplate> V8DOMWrapper::getTemplate(V8ClassIndex::V8W
case V8ClassIndex::CLIENTRECTLIST:
descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(ClientRectList));
break;
+ case V8ClassIndex::FILELIST:
+ descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(FileList));
+ break;
#if ENABLE(DATAGRID)
case V8ClassIndex::DATAGRIDCOLUMNLIST:
descriptor->InstanceTemplate()->SetIndexedPropertyHandler(USE_INDEXED_PROPERTY_GETTER(DataGridColumnList));
@@ -534,6 +598,16 @@ v8::Local<v8::Function> V8DOMWrapper::getConstructor(V8ClassIndex::V8WrapperType
if (!frame)
return v8::Local<v8::Function>();
+#if ENABLE(WEB_SOCKETS)
+ // Make typeof(window.WebSocket) == 'undefined' when
+ // experimentalWebSocketEnabled is false.
+ if (type == V8ClassIndex::WEBSOCKET) {
+ Settings* settings = frame->settings();
+ if (!settings || !settings->experimentalWebSocketsEnabled())
+ return v8::Local<v8::Function>();
+ }
+#endif
+
v8::Handle<v8::Context> context = V8Proxy::context(frame);
if (context.IsEmpty())
return v8::Local<v8::Function>();
@@ -562,6 +636,7 @@ v8::Handle<v8::Value> V8DOMWrapper::convertToV8Object(V8ClassIndex::V8WrapperTyp
// These objects can be constructed under WorkerContextExecutionProxy. They need special
// handling, since if we proceed below V8Proxy::retrieve() will get called and will crash.
+ // TODO(ukai): websocket?
if ((type == V8ClassIndex::DOMCOREEXCEPTION
|| type == V8ClassIndex::RANGEEXCEPTION
|| type == V8ClassIndex::EVENTEXCEPTION
@@ -982,7 +1057,6 @@ V8ClassIndex::V8WrapperType V8DOMWrapper::htmlElementType(HTMLElement* element)
#if ENABLE(SVG_FONTS)
#define FOR_EACH_FONTS_TAG(macro) \
- macro(definition-src, DEFINITIONSRC) \
macro(font-face, FONTFACE) \
macro(font-face-format, FONTFACEFORMAT) \
macro(font-face-name, FONTFACENAME) \
@@ -1105,6 +1179,8 @@ v8::Handle<v8::Value> V8DOMWrapper::convertEventToV8Object(Event* event)
type = V8ClassIndex::OVERFLOWEVENT;
else if (event->isMessageEvent())
type = V8ClassIndex::MESSAGEEVENT;
+ else if (event->isPageTransitionEvent())
+ type = V8ClassIndex::PAGETRANSITIONEVENT;
else if (event->isProgressEvent()) {
if (event->isXMLHttpRequestProgressEvent())
type = V8ClassIndex::XMLHTTPREQUESTPROGRESSEVENT;
@@ -1155,30 +1231,30 @@ static const V8ClassIndex::V8WrapperType mapping[] = {
V8ClassIndex::NODE, // XPATH_NAMESPACE_NODE
};
-// Caller checks node is not null.
-v8::Handle<v8::Value> V8DOMWrapper::convertNodeToV8Object(Node* node)
+v8::Handle<v8::Value> V8DOMWrapper::convertDocumentToV8Object(Document* document)
{
- if (!node)
- return v8::Null();
-
// Find a proxy for this node.
//
// Note that if proxy is found, we might initialize the context which can
// instantiate a document wrapper. Therefore, we get the proxy before
// checking if the node already has a wrapper.
- V8Proxy* proxy = 0;
- Document* document = node->document();
- if (document) {
- Frame* frame = document->frame();
- proxy = V8Proxy::retrieve(frame);
- if (proxy)
- proxy->initContextIfNeeded();
- }
+ V8Proxy* proxy = V8Proxy::retrieve(document->frame());
+ if (proxy)
+ proxy->initContextIfNeeded();
DOMWrapperMap<Node>& domNodeMap = getDOMNodeMap();
- v8::Handle<v8::Object> wrapper = domNodeMap.get(node);
- if (!wrapper.IsEmpty())
- return wrapper;
+ v8::Handle<v8::Object> wrapper = domNodeMap.get(document);
+ if (wrapper.IsEmpty())
+ return convertNewNodeToV8Object(document, proxy, domNodeMap);
+
+ return wrapper;
+}
+
+// Caller checks node is not null.
+v8::Handle<v8::Value> V8DOMWrapper::convertNewNodeToV8Object(Node* node, V8Proxy* proxy, DOMWrapperMap<Node>& domNodeMap)
+{
+ if (!proxy && node->document())
+ proxy = V8Proxy::retrieve(node->document()->frame());
bool isDocument = false; // document type node has special handling
V8ClassIndex::V8WrapperType type;
@@ -1272,6 +1348,18 @@ v8::Handle<v8::Value> V8DOMWrapper::convertEventTargetToV8Object(EventTarget* ta
return convertToV8Object(V8ClassIndex::WORKER, worker);
#endif // WORKERS
+#if ENABLE(NOTIFICATIONS)
+ Notification* notification = target->toNotification();
+ if (notification)
+ return convertToV8Object(V8ClassIndex::NOTIFICATION, notification);
+#endif
+
+#if ENABLE(WEB_SOCKETS)
+ WebSocket* webSocket = target->toWebSocket();
+ if (webSocket)
+ return convertToV8Object(V8ClassIndex::WEBSOCKET, webSocket);
+#endif
+
Node* node = target->toNode();
if (node)
return convertNodeToV8Object(node);
@@ -1322,6 +1410,102 @@ v8::Handle<v8::Value> V8DOMWrapper::convertEventListenerToV8Object(EventListener
return v8listener->getListenerObject();
}
+PassRefPtr<EventListener> V8DOMWrapper::getEventListener(Node* node, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup)
+{
+ ScriptExecutionContext* context = node->scriptExecutionContext();
+ if (!context)
+ return 0;
+
+ V8Proxy* proxy = V8Proxy::retrieve(context);
+ // The document might be created using createDocument, which does
+ // not have a frame, use the active frame.
+ if (!proxy)
+ proxy = V8Proxy::retrieve(V8Proxy::retrieveFrameForEnteredContext());
+
+ if (proxy)
+ return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(proxy->frame(), proxy->listenerGuard(), value, isAttribute);
+
+ return 0;
+}
+
+#if PLATFORM(ANDROID)
+#if ENABLE(SVG)
+PassRefPtr<EventListener> V8DOMWrapper::getEventListener(SVGElementInstance* element, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup)
+{
+ return getEventListener(element->correspondingElement(), value, isAttribute, lookup);
+}
+#endif
+#endif
+
+PassRefPtr<EventListener> V8DOMWrapper::getEventListener(AbstractWorker* worker, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup)
+{
+ if (worker->scriptExecutionContext()->isWorkerContext()) {
+ WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve();
+ ASSERT(workerContextProxy);
+ return workerContextProxy->findOrCreateEventListener(value, isAttribute, lookup == ListenerFindOnly);
+ }
+
+ V8Proxy* proxy = V8Proxy::retrieve(worker->scriptExecutionContext());
+ if (proxy)
+ return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(proxy->frame(), proxy->listenerGuard(), value, isAttribute);
+
+ return 0;
+}
+
+#if ENABLE(NOTIFICATIONS)
+PassRefPtr<EventListener> V8DOMWrapper::getEventListener(Notification* notification, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup)
+{
+ if (notification->scriptExecutionContext()->isWorkerContext()) {
+ WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve();
+ ASSERT(workerContextProxy);
+ return workerContextProxy->findOrCreateEventListener(value, isAttribute, lookup == ListenerFindOnly);
+ }
+
+ V8Proxy* proxy = V8Proxy::retrieve(notification->scriptExecutionContext());
+ if (proxy)
+ return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(proxy->frame(), proxy->listenerGuard(), value, isAttribute);
+
+ return 0;
+}
+#endif
+
+PassRefPtr<EventListener> V8DOMWrapper::getEventListener(WorkerContext* workerContext, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup)
+{
+ WorkerContextExecutionProxy* workerContextProxy = workerContext->script()->proxy();
+ if (workerContextProxy)
+ return workerContextProxy->findOrCreateEventListener(value, isAttribute, lookup == ListenerFindOnly);
+
+ return 0;
+}
+
+PassRefPtr<EventListener> V8DOMWrapper::getEventListener(XMLHttpRequestUpload* upload, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup)
+{
+ return getEventListener(upload->associatedXMLHttpRequest(), value, isAttribute, lookup);
+}
+
+PassRefPtr<EventListener> V8DOMWrapper::getEventListener(EventTarget* eventTarget, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup)
+{
+ V8Proxy* proxy = V8Proxy::retrieve(eventTarget->scriptExecutionContext());
+ if (proxy)
+ return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(proxy->frame(), proxy->listenerGuard(), value, isAttribute);
+
+#if ENABLE(WORKERS)
+ WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve();
+ if (workerContextProxy)
+ return workerContextProxy->findOrCreateEventListener(value, isAttribute, lookup == ListenerFindOnly);
+#endif
+
+ return 0;
+}
+
+PassRefPtr<EventListener> V8DOMWrapper::getEventListener(V8Proxy* proxy, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup)
+{
+ if (proxy)
+ return (lookup == ListenerFindOnly) ? V8EventListenerList::findWrapper(value, isAttribute) : V8EventListenerList::findOrCreateWrapper<V8EventListener>(proxy->frame(), proxy->listenerGuard(), value, isAttribute);
+
+ return 0;
+}
+
v8::Handle<v8::Value> V8DOMWrapper::convertDOMImplementationToV8Object(DOMImplementation* impl)
{
v8::Handle<v8::Object> result = instantiateV8Object(V8ClassIndex::DOMIMPLEMENTATION, V8ClassIndex::DOMIMPLEMENTATION, impl);
diff --git a/WebCore/bindings/v8/V8DOMWrapper.h b/WebCore/bindings/v8/V8DOMWrapper.h
index 57b3a69..b5587d5 100644
--- a/WebCore/bindings/v8/V8DOMWrapper.h
+++ b/WebCore/bindings/v8/V8DOMWrapper.h
@@ -31,13 +31,18 @@
#ifndef V8DOMWrapper_h
#define V8DOMWrapper_h
+#include "Document.h"
#include "Event.h"
#include "Node.h"
#include "NodeFilter.h"
#include "PlatformString.h" // for WebCore::String
#include "V8CustomBinding.h"
+#include "V8CustomXPathNSResolver.h"
+#include "V8DOMMap.h"
#include "V8Index.h"
#include "V8Utilities.h"
+#include "V8XPathNSResolver.h"
+#include "XPathNSResolver.h"
#include <v8.h>
namespace WebCore {
@@ -86,8 +91,16 @@ namespace WebCore {
class StyleSheetList;
class V8EventListener;
class V8ObjectEventListener;
+#if ENABLE(WEB_SOCKETS)
+ class WebSocket;
+#endif
class WorkerContext;
+ enum ListenerLookupType {
+ ListenerFindOnly,
+ ListenerFindOrCreate,
+ };
+
class V8DOMWrapper {
public:
#ifndef NDEBUG
@@ -134,7 +147,26 @@ namespace WebCore {
return convertNodeToV8Object(node.get());
}
- static v8::Handle<v8::Value> convertNodeToV8Object(Node*);
+ static v8::Handle<v8::Value> convertNodeToV8Object(Node* node)
+ {
+ if (!node)
+ return v8::Null();
+
+ Document* document = node->document();
+ if (node == document)
+ return convertDocumentToV8Object(document);
+
+ DOMWrapperMap<Node>& domNodeMap = getDOMNodeMap();
+ v8::Handle<v8::Object> wrapper = domNodeMap.get(node);
+ if (wrapper.IsEmpty())
+ return convertNewNodeToV8Object(node, 0, domNodeMap);
+
+ return wrapper;
+ }
+
+ static v8::Handle<v8::Value> convertDocumentToV8Object(Document*);
+
+ static v8::Handle<v8::Value> convertNewNodeToV8Object(Node*, V8Proxy*, DOMWrapperMap<Node>&);
template <class C>
static C* convertToNativeObject(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Object> object)
@@ -184,13 +216,48 @@ namespace WebCore {
static v8::Handle<v8::Value> convertEventTargetToV8Object(EventTarget*);
// Wrap and unwrap JS event listeners.
- static v8::Handle<v8::Value> convertEventListenerToV8Object(PassRefPtr<Event> eventListener)
+ static v8::Handle<v8::Value> convertEventListenerToV8Object(PassRefPtr<EventListener> eventListener)
{
return convertEventListenerToV8Object(eventListener.get());
}
static v8::Handle<v8::Value> convertEventListenerToV8Object(EventListener*);
+ static PassRefPtr<EventListener> getEventListener(Node* node, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup);
+
+ static PassRefPtr<EventListener> getEventListener(SVGElementInstance* element, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup);
+
+ static PassRefPtr<EventListener> getEventListener(AbstractWorker* worker, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup);
+
+#if ENABLE(NOTIFICATIONS)
+ static PassRefPtr<EventListener> getEventListener(Notification* notification, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup);
+#endif
+
+ static PassRefPtr<EventListener> getEventListener(WorkerContext* workerContext, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup);
+
+ static PassRefPtr<EventListener> getEventListener(XMLHttpRequestUpload* upload, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup);
+
+ static PassRefPtr<EventListener> getEventListener(EventTarget* eventTarget, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup);
+
+ static PassRefPtr<EventListener> getEventListener(V8Proxy* proxy, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup);
+
+
+#if PLATFORM(ANDROID)
+// TODO: upstream XPATH guard.
+#if ENABLE(XPATH)
+ // XPath-related utilities
+ static RefPtr<XPathNSResolver> getXPathNSResolver(v8::Handle<v8::Value> value)
+ {
+ RefPtr<XPathNSResolver> resolver;
+ if (V8XPathNSResolver::HasInstance(value))
+ resolver = convertToNativeObject<XPathNSResolver>(V8ClassIndex::XPATHNSRESOLVER, v8::Handle<v8::Object>::Cast(value));
+ else if (value->IsObject())
+ resolver = V8CustomXPathNSResolver::create(value->ToObject());
+ return resolver;
+ }
+#endif
+#endif
+
// DOMImplementation is a singleton and it is handled in a special
// way. A wrapper is generated per document and stored in an
// internal field of the document.
diff --git a/WebCore/bindings/v8/V8EventListenerList.cpp b/WebCore/bindings/v8/V8EventListenerList.cpp
index c9aaa12..e37d630 100644
--- a/WebCore/bindings/v8/V8EventListenerList.cpp
+++ b/WebCore/bindings/v8/V8EventListenerList.cpp
@@ -31,165 +31,6 @@
#include "config.h"
#include "V8EventListenerList.h"
-#include "V8CustomEventListener.h"
-
namespace WebCore {
-V8EventListenerListIterator::V8EventListenerListIterator(V8EventListenerList* list)
- : m_list(list)
- , m_vectorIndex(0)
- , m_iter(list->m_table.begin())
-{
-}
-
-V8EventListenerListIterator::V8EventListenerListIterator(V8EventListenerList* list, bool shouldSeekToEnd)
- : m_list(list)
- , m_vectorIndex(0)
- , m_iter(list->m_table.begin())
-{
- if (shouldSeekToEnd)
- seekToEnd();
-}
-
-V8EventListenerListIterator::~V8EventListenerListIterator() { }
-
-void V8EventListenerListIterator::operator++()
-{
- if (m_iter != m_list->m_table.end()) {
- Vector<V8EventListener*>* vector = m_iter->second;
- if (m_vectorIndex + 1 < vector->size()) {
- m_vectorIndex++;
- return;
- }
- m_vectorIndex = 0;
- ++m_iter;
- }
-}
-
-bool V8EventListenerListIterator::operator==(const V8EventListenerListIterator& other)
-{
- return other.m_iter == m_iter && other.m_vectorIndex == m_vectorIndex && other.m_list == m_list;
-}
-
-bool V8EventListenerListIterator::operator!=(const V8EventListenerListIterator& other)
-{
- return !operator==(other);
-}
-
-V8EventListener* V8EventListenerListIterator::operator*()
-{
- if (m_iter != m_list->m_table.end()) {
- Vector<V8EventListener*>* vector = m_iter->second;
- if (m_vectorIndex < vector->size())
- return vector->at(m_vectorIndex);
- }
- return 0;
-}
-
-void V8EventListenerListIterator::seekToEnd()
-{
- m_iter = m_list->m_table.end();
- m_vectorIndex = 0;
-}
-
-
-V8EventListenerList::V8EventListenerList()
-{
-}
-
-V8EventListenerList::~V8EventListenerList()
-{
-}
-
-V8EventListenerListIterator V8EventListenerList::begin()
-{
- return iterator(this);
-}
-
-V8EventListenerListIterator V8EventListenerList::end()
-{
- return iterator(this, true);
-}
-
-
-static int getKey(v8::Local<v8::Object> object)
-{
- // 0 is a sentinel value for the HashMap key, so we map it to 1.
- int hash = object->GetIdentityHash();
- if (!hash)
- return 1;
- return hash;
-}
-
-void V8EventListenerList::add(V8EventListener* listener)
-{
- ASSERT(v8::Context::InContext());
- v8::HandleScope handleScope;
-
- v8::Local<v8::Object> object = listener->getListenerObject();
- int key = getKey(object);
- Vector<V8EventListener*>* vector = m_table.get(key);
- if (!vector) {
- vector = new Vector<V8EventListener*>();
- m_table.set(key, vector);
- }
- vector->append(listener);
- m_reverseTable.set(listener, key);
-}
-
-void V8EventListenerList::remove(V8EventListener* listener)
-{
- if (m_reverseTable.contains(listener)) {
- int key = m_reverseTable.get(listener);
- Vector<V8EventListener*>* vector = m_table.get(key);
- if (!vector)
- return;
- for (size_t j = 0; j < vector->size(); j++) {
- if (vector->at(j) == listener) {
- vector->remove(j);
- if (!vector->size()) {
- m_table.remove(key);
- delete vector;
- vector = 0;
- }
- m_reverseTable.remove(listener);
- return;
- }
- }
- }
-}
-
-void V8EventListenerList::clear()
-{
- m_table.clear();
- m_reverseTable.clear();
-}
-
-V8EventListener* V8EventListenerList::find(v8::Local<v8::Object> object, bool isAttribute)
-{
- ASSERT(v8::Context::InContext());
- int key = getKey(object);
-
- Vector<V8EventListener*>* vector = m_table.get(key);
- if (!vector)
- return 0;
-
- for (size_t i = 0; i < vector->size(); i++) {
- V8EventListener* element = vector->at(i);
- if (isAttribute == element->isAttribute() && object == element->getListenerObject())
- return element;
- }
- return 0;
-}
-
-PassRefPtr<V8EventListener> V8EventListenerList::findWrapper(v8::Local<v8::Value> object, bool isAttribute)
-{
- ASSERT(v8::Context::InContext());
- if (!object->IsObject())
- return 0;
-
- // FIXME: Should this be v8::Local<v8::Object>::Cast instead?
- return find(object->ToObject(), isAttribute);
-}
-
} // namespace WebCore
diff --git a/WebCore/bindings/v8/V8EventListenerList.h b/WebCore/bindings/v8/V8EventListenerList.h
index 4255050..506e5dc 100644
--- a/WebCore/bindings/v8/V8EventListenerList.h
+++ b/WebCore/bindings/v8/V8EventListenerList.h
@@ -32,92 +32,74 @@
#define V8EventListenerList_h
#include <v8.h>
-#include <wtf/Vector.h>
-#include <wtf/HashMap.h>
#include "PassRefPtr.h"
+#include "V8CustomEventListener.h"
+#include "V8HiddenPropertyName.h"
namespace WebCore {
class Frame;
class V8EventListener;
- class V8EventListenerListIterator;
- // This is a container for V8EventListener objects that uses the identity hash of the v8::Object to
- // speed up lookups
+ // This is a container for V8EventListener objects that uses hidden properties of v8::Object to speed up lookups.
class V8EventListenerList {
public:
- // Because v8::Object identity hashes are not guaranteed to be unique, we unfortunately can't just map
- // an int to V8EventListener. Instead we define a HashMap of int to Vector of V8EventListener
- // called a ListenerMultiMap.
- typedef Vector<V8EventListener*>* Values;
- struct ValuesTraits : HashTraits<Values> {
- static const bool needsDestruction = true;
- };
- typedef HashMap<int, Values, DefaultHash<int>::Hash, HashTraits<int>, ValuesTraits> ListenerMultiMap;
-
- V8EventListenerList();
- ~V8EventListenerList();
-
- friend class V8EventListenerListIterator;
- typedef V8EventListenerListIterator iterator;
-
- iterator begin();
- iterator end();
-
- void add(V8EventListener*);
- void remove(V8EventListener*);
- V8EventListener* find(v8::Local<v8::Object>, bool isAttribute);
- void clear();
- size_t size() { return m_table.size(); }
-
- PassRefPtr<V8EventListener> findWrapper(v8::Local<v8::Value>, bool isAttribute);
- template<typename WrapperType>
- PassRefPtr<V8EventListener> findOrCreateWrapper(Frame*, v8::Local<v8::Value>, bool isAttribute);
+ static PassRefPtr<V8EventListener> findWrapper(v8::Local<v8::Value> value, bool isAttribute)
+ {
+ ASSERT(v8::Context::InContext());
+ if (!value->IsObject())
+ return 0;
- private:
- ListenerMultiMap m_table;
+ v8::Handle<v8::String> wrapperProperty = getHiddenProperty(isAttribute);
+ return doFindWrapper(v8::Local<v8::Object>::Cast(value), wrapperProperty);
+ }
- // we also keep a reverse mapping of V8EventListener to v8::Object identity hash,
- // in order to speed up removal by V8EventListener
- HashMap<V8EventListener*, int> m_reverseTable;
- };
+ template<typename WrapperType, typename ContextType>
+ static PassRefPtr<V8EventListener> findOrCreateWrapper(ContextType*, PassRefPtr<V8ListenerGuard>, v8::Local<v8::Value>, bool isAttribute);
+
+ static void clearWrapper(v8::Handle<v8::Object> listenerObject, bool isAttribute)
+ {
+ v8::Handle<v8::String> wrapperProperty = getHiddenProperty(isAttribute);
+ listenerObject->DeleteHiddenValue(wrapperProperty);
+ }
- class V8EventListenerListIterator {
- public:
- ~V8EventListenerListIterator();
- void operator++();
- bool operator==(const V8EventListenerListIterator&);
- bool operator!=(const V8EventListenerListIterator&);
- V8EventListener* operator*();
private:
- friend class V8EventListenerList;
- explicit V8EventListenerListIterator(V8EventListenerList*);
- V8EventListenerListIterator(V8EventListenerList*, bool shouldSeekToEnd);
- void seekToEnd();
-
- V8EventListenerList* m_list;
- V8EventListenerList::ListenerMultiMap::iterator m_iter;
- size_t m_vectorIndex;
+ static V8EventListener* doFindWrapper(v8::Local<v8::Object> object, v8::Handle<v8::String> wrapperProperty)
+ {
+ ASSERT(v8::Context::InContext());
+ v8::HandleScope scope;
+ v8::Local<v8::Value> listener = object->GetHiddenValue(wrapperProperty);
+ if (listener.IsEmpty())
+ return 0;
+ return static_cast<V8EventListener*>(v8::External::Unwrap(listener));
+ }
+
+ static inline v8::Handle<v8::String> getHiddenProperty(bool isAttribute)
+ {
+ return isAttribute ? V8HiddenPropertyName::attributeListener() : V8HiddenPropertyName::listener();
+ }
};
- template<typename WrapperType>
- PassRefPtr<V8EventListener> V8EventListenerList::findOrCreateWrapper(Frame* frame, v8::Local<v8::Value> object, bool isAttribute)
+ template<typename WrapperType, typename ContextType>
+ PassRefPtr<V8EventListener> V8EventListenerList::findOrCreateWrapper(ContextType* context, PassRefPtr<V8ListenerGuard> guard, v8::Local<v8::Value> value, bool isAttribute)
{
ASSERT(v8::Context::InContext());
- if (!object->IsObject())
+ if (!value->IsObject())
return 0;
- // FIXME: Should this be v8::Local<v8::Object>::Cast instead?
- V8EventListener* wrapper = find(object->ToObject(), isAttribute);
+ v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(value);
+ v8::Handle<v8::String> wrapperProperty = getHiddenProperty(isAttribute);
+
+ V8EventListener* wrapper = doFindWrapper(object, wrapperProperty);
if (wrapper)
return wrapper;
- // Create a new one, and add to cache.
- RefPtr<WrapperType> newListener = WrapperType::create(frame, v8::Local<v8::Object>::Cast(object), isAttribute);
- add(newListener.get());
+ PassRefPtr<V8EventListener> wrapperPtr = WrapperType::create(context, guard, object, isAttribute);
+ if (wrapperPtr)
+ object->SetHiddenValue(wrapperProperty, v8::External::Wrap(wrapperPtr.get()));
- return newListener;
- };
+ return wrapperPtr;
+ }
} // namespace WebCore
diff --git a/WebCore/bindings/v8/V8HiddenPropertyName.cpp b/WebCore/bindings/v8/V8HiddenPropertyName.cpp
index 16ac232..d83573f 100644
--- a/WebCore/bindings/v8/V8HiddenPropertyName.cpp
+++ b/WebCore/bindings/v8/V8HiddenPropertyName.cpp
@@ -33,22 +33,21 @@
namespace WebCore {
-v8::Handle<v8::String> V8HiddenPropertyName::objectPrototype()
-{
- static v8::Persistent<v8::String>* string = createString("WebCore::V8HiddenPropertyName::objectPrototype");
-
- return *string;
+#define V8_AS_STRING(x) V8_AS_STRING_IMPL(x)
+#define V8_AS_STRING_IMPL(x) #x
+
+#define V8_DEFINE_PROPERTY(name) \
+v8::Handle<v8::String> V8HiddenPropertyName::name() \
+{ \
+ static v8::Persistent<v8::String>* string = createString("WebCore::V8HiddenPropertyName::" V8_AS_STRING(name)); \
+ return *string; \
}
-v8::Handle<v8::String> V8HiddenPropertyName::isolatedWorld()
-{
- static v8::Persistent<v8::String>* string = createString("WebCore::V8HiddenPropertyName::isolatedWorld");
-
- return *string;
-}
+V8_HIDDEN_PROPERTIES(V8_DEFINE_PROPERTY);
v8::Persistent<v8::String>* V8HiddenPropertyName::createString(const char* key)
{
+ v8::HandleScope scope;
return new v8::Persistent<v8::String>(v8::Persistent<v8::String>::New(v8::String::NewSymbol(key)));
}
diff --git a/WebCore/bindings/v8/V8HiddenPropertyName.h b/WebCore/bindings/v8/V8HiddenPropertyName.h
index 874b525..5ef89cb 100644
--- a/WebCore/bindings/v8/V8HiddenPropertyName.h
+++ b/WebCore/bindings/v8/V8HiddenPropertyName.h
@@ -35,10 +35,19 @@
namespace WebCore {
+#define V8_HIDDEN_PROPERTIES(V) \
+ V(objectPrototype) \
+ V(isolatedWorld) \
+ V(listener) \
+ V(attributeListener) \
+ V(sleepFunction) \
+ V(toStringString)
+
class V8HiddenPropertyName {
public:
- static v8::Handle<v8::String> objectPrototype();
- static v8::Handle<v8::String> isolatedWorld();
+#define V8_DECLARE_PROPERTY(name) static v8::Handle<v8::String> name();
+ V8_HIDDEN_PROPERTIES(V8_DECLARE_PROPERTY);
+#undef V8_DECLARE_PROPERTY
private:
static v8::Persistent<v8::String>* createString(const char* key);
diff --git a/WebCore/bindings/v8/V8Index.cpp b/WebCore/bindings/v8/V8Index.cpp
index 9efbc3d..2cbd16d 100644
--- a/WebCore/bindings/v8/V8Index.cpp
+++ b/WebCore/bindings/v8/V8Index.cpp
@@ -33,6 +33,8 @@
#include "V8Attr.h"
#include "V8BarInfo.h"
+#include "V8BeforeLoadEvent.h"
+#include "V8CanvasRenderingContext.h"
#include "V8CanvasRenderingContext2D.h"
#include "V8CanvasGradient.h"
#include "V8CanvasPattern.h"
@@ -107,6 +109,7 @@
#include "V8HTMLHtmlElement.h"
#include "V8HTMLIFrameElement.h"
#include "V8HTMLImageElement.h"
+#include "V8HTMLImageElementConstructor.h"
#include "V8HTMLInputElement.h"
#include "V8HTMLIsIndexElement.h"
#include "V8HTMLLabelElement.h"
@@ -121,6 +124,7 @@
#include "V8HTMLOListElement.h"
#include "V8HTMLOptGroupElement.h"
#include "V8HTMLOptionElement.h"
+#include "V8HTMLOptionElementConstructor.h"
#include "V8HTMLParagraphElement.h"
#include "V8HTMLParamElement.h"
#include "V8HTMLPreElement.h"
@@ -179,6 +183,7 @@
#include "V8Navigator.h"
#include "V8MimeType.h"
#include "V8MimeTypeArray.h"
+#include "V8PageTransitionEvent.h"
#include "V8Plugin.h"
#include "V8PluginArray.h"
#include "V8Range.h"
@@ -195,24 +200,11 @@
#include "V8XMLHttpRequestUpload.h"
#include "V8XMLSerializer.h"
#include "V8RGBColor.h"
-#include "V8VoidCallback.h"
-
-#if !PLATFORM(ANDROID)
-#include "V8InspectorBackend.h"
-#endif
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
#include "V8DOMApplicationCache.h"
#endif
-#if ENABLE(DATABASE)
-#include "V8Database.h"
-#include "V8SQLError.h"
-#include "V8SQLResultSet.h"
-#include "V8SQLResultSetRowList.h"
-#include "V8SQLTransaction.h"
-#endif
-
#if ENABLE(DOM_STORAGE)
#include "V8Storage.h"
#include "V8StorageEvent.h"
@@ -254,7 +246,6 @@
#endif
#if ENABLE(SVG_FONTS)
-#include "V8SVGDefinitionSrcElement.h"
#include "V8SVGFontFaceElement.h"
#include "V8SVGFontFaceFormatElement.h"
#include "V8SVGFontFaceNameElement.h"
@@ -370,6 +361,7 @@
#if ENABLE(VIDEO)
#include "V8HTMLAudioElement.h"
+#include "V8HTMLAudioElementConstructor.h"
#include "V8HTMLMediaElement.h"
#include "V8HTMLSourceElement.h"
#include "V8HTMLVideoElement.h"
@@ -377,6 +369,10 @@
#include "V8TimeRanges.h"
#endif
+#if ENABLE(WEB_SOCKETS)
+#include "V8WebSocket.h"
+#endif
+
#if ENABLE(WORKERS)
#include "V8AbstractWorker.h"
#include "V8DedicatedWorkerContext.h"
@@ -386,35 +382,76 @@
#include "V8WorkerNavigator.h"
#endif
+#if ENABLE(NOTIFICATIONS)
+#include "V8Notification.h"
+#include "V8NotificationCenter.h"
+#endif
+
#if ENABLE(SHARED_WORKERS)
#include "V8SharedWorker.h"
#endif
-#if ENABLE(GEOLOCATION)
-#include "V8Coordinates.h"
-#include "V8Geolocation.h"
-#include "V8Geoposition.h"
-#include "V8PositionError.h"
+#if ENABLE(3D_CANVAS)
+#include "V8CanvasRenderingContext3D.h"
+#include "V8CanvasArrayBuffer.h"
+#include "V8CanvasArray.h"
+#include "V8CanvasByteArray.h"
+#include "V8CanvasBuffer.h"
+#include "V8CanvasFloatArray.h"
+#include "V8CanvasFramebuffer.h"
+#include "V8CanvasIntArray.h"
+#include "V8CanvasProgram.h"
+#include "V8CanvasRenderbuffer.h"
+#include "V8CanvasShader.h"
+#include "V8CanvasShortArray.h"
+#include "V8CanvasTexture.h"
+#include "V8CanvasUnsignedByteArray.h"
+#include "V8CanvasUnsignedIntArray.h"
+#include "V8CanvasUnsignedShortArray.h"
#endif
-#if ENABLE(TOUCH_EVENTS)
-#include "V8Touch.h"
-#include "V8TouchList.h"
-#include "V8TouchEvent.h"
+#if ENABLE(DATABASE)
+#include "V8Database.h"
+#include "V8SQLError.h"
+#include "V8SQLResultSet.h"
+#include "V8SQLResultSetRowList.h"
+#include "V8SQLTransaction.h"
#endif
#if ENABLE(XPATH)
#include "V8XPathResult.h"
#include "V8XPathException.h"
#include "V8XPathExpression.h"
-#include "V8XPathEvaluator.h"
#include "V8XPathNSResolver.h"
+#include "V8XPathEvaluator.h"
#endif
#if ENABLE(XSLT)
#include "V8XSLTProcessor.h"
#endif
+#if ENABLE(INSPECTOR)
+#include "V8InspectorBackend.h"
+#endif
+
+#if PLATFORM(ANDROID)
+// TODO: Upstream these guards to webkit.org
+#if ENABLE(GEOLOCATION)
+#include "V8Coordinates.h"
+#include "V8Geolocation.h"
+#include "V8Geoposition.h"
+#include "V8PositionError.h"
+#endif
+
+#if ENABLE(TOUCH_EVENTS)
+#include "V8Touch.h"
+#include "V8TouchList.h"
+#include "V8TouchEvent.h"
+#endif
+
+#include "V8VoidCallback.h"
+#endif // PLATFORM(ANDROID)
+
namespace WebCore {
FunctionTemplateFactory V8ClassIndex::GetFactory(V8WrapperType type)
diff --git a/WebCore/bindings/v8/V8Index.h b/WebCore/bindings/v8/V8Index.h
index d6db4c6..179b963 100644
--- a/WebCore/bindings/v8/V8Index.h
+++ b/WebCore/bindings/v8/V8Index.h
@@ -54,6 +54,7 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)();
#if ENABLE(VIDEO)
#define VIDEO_HTMLELEMENT_TYPES(V) \
+ V(AUDIO, HTMLAudioElementConstructor) \
V(HTMLAUDIOELEMENT, HTMLAudioElement) \
V(HTMLMEDIAELEMENT, HTMLMediaElement) \
V(HTMLSOURCEELEMENT, HTMLSourceElement) \
@@ -82,16 +83,26 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)();
#endif
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
-#define APPLICATIONCACHE_NONNODE_WRAPPER_TYPES(V) \
+#define APPLICATIONCACHE_NONNODE_WRAPPER_TYPES(V) \
V(DOMAPPLICATIONCACHE, DOMApplicationCache)
#else
#define APPLICATIONCACHE_NONNODE_WRAPPER_TYPES(V)
#endif
+#if ENABLE(NOTIFICATIONS)
+#define NOTIFICATIONS_NONNODE_WRAPPER_TYPES(V) \
+ V(NOTIFICATION, Notification) \
+ V(NOTIFICATIONCENTER, NotificationCenter)
+#else
+#define NOTIFICATIONS_NONNODE_WRAPPER_TYPES(V)
+#endif
+
#if ENABLE(SHARED_WORKERS)
#define SHARED_WORKER_ACTIVE_OBJECT_WRAPPER_TYPES(V) \
V(SHAREDWORKER, SharedWorker)
-#define SHARED_WORKER_NONNODE_WRAPPER_TYPES(V)
+
+#define SHARED_WORKER_NONNODE_WRAPPER_TYPES(V) \
+ V(SHAREDWORKERCONTEXT, SharedWorkerContext)
#else
#define SHARED_WORKER_ACTIVE_OBJECT_WRAPPER_TYPES(V)
#define SHARED_WORKER_NONNODE_WRAPPER_TYPES(V)
@@ -109,7 +120,9 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)();
V(ENTITY, Entity) \
V(ENTITYREFERENCE, EntityReference) \
V(HTMLDOCUMENT, HTMLDocument) \
+ V(IMAGE, HTMLImageElementConstructor) \
V(NODE, Node) \
+ V(OPTION, HTMLOptionElementConstructor) \
V(NOTATION, Notation) \
V(PROCESSINGINSTRUCTION, ProcessingInstruction) \
V(TEXT, Text) \
@@ -216,7 +229,6 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)();
#if ENABLE(SVG_FONTS)
#define SVG_FONTS_ELEMENT_TYPES(V) \
- V(SVGDEFINITIONSRCELEMENT, SVGDefinitionSrcElement) \
V(SVGFONTFACEELEMENT, SVGFontFaceElement) \
V(SVGFONTFACEFORMATELEMENT, SVGFontFaceFormatElement) \
V(SVGFONTFACENAMEELEMENT, SVGFontFaceNameElement) \
@@ -289,13 +301,21 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)();
#endif // SVG
+#if ENABLE(WEB_SOCKETS)
+#define WEBSOCKET_ACTIVE_OBJECT_WRAPPER_TYPES(V) \
+ V(WEBSOCKET, WebSocket)
+#else
+#define WEBSOCKET_ACTIVE_OBJECT_WRAPPER_TYPES(V)
+#endif
+
// ACTIVE_DOM_OBJECT_TYPES are DOM_OBJECT_TYPES that need special treatement
// during GC.
#define ACTIVE_DOM_OBJECT_TYPES(V) \
V(MESSAGEPORT, MessagePort) \
V(XMLHTTPREQUEST, XMLHttpRequest) \
WORKER_ACTIVE_OBJECT_WRAPPER_TYPES(V) \
- SHARED_WORKER_ACTIVE_OBJECT_WRAPPER_TYPES(V)
+ SHARED_WORKER_ACTIVE_OBJECT_WRAPPER_TYPES(V) \
+ WEBSOCKET_ACTIVE_OBJECT_WRAPPER_TYPES(V)
// NOTE: DOM_OBJECT_TYPES is split into two halves because
// Visual Studio's Intellinonsense crashes when macros get
@@ -303,8 +323,10 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)();
// DOM_OBJECT_TYPES are non-node DOM types.
#define DOM_OBJECT_TYPES_1(V) \
V(BARINFO, BarInfo) \
+ V(BEFORELOADEVENT, BeforeLoadEvent) \
V(CANVASGRADIENT, CanvasGradient) \
V(CANVASPATTERN, CanvasPattern) \
+ V(CANVASRENDERINGCONTEXT, CanvasRenderingContext) \
V(CANVASRENDERINGCONTEXT2D, CanvasRenderingContext2D) \
V(CLIENTRECT, ClientRect) \
V(CLIENTRECTLIST, ClientRectList) \
@@ -359,6 +381,7 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)();
V(NODEITERATOR, NodeIterator) \
V(NODELIST, NodeList) \
V(OVERFLOWEVENT, OverflowEvent) \
+ V(PAGETRANSITIONEVENT, PageTransitionEvent) \
V(PLUGIN, Plugin) \
V(PLUGINARRAY, PluginArray) \
V(PROGRESSEVENT, ProgressEvent) \
@@ -374,7 +397,6 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)();
V(TREEWALKER, TreeWalker) \
V(UIEVENT, UIEvent) \
V(VALIDITYSTATE, ValidityState) \
- V(VOIDCALLBACK, VoidCallback) \
V(WEBKITANIMATIONEVENT, WebKitAnimationEvent) \
V(WEBKITCSSKEYFRAMERULE, WebKitCSSKeyframeRule) \
V(WEBKITCSSKEYFRAMESRULE, WebKitCSSKeyframesRule) \
@@ -391,27 +413,10 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)();
APPLICATIONCACHE_NONNODE_WRAPPER_TYPES(V) \
DATAGRID_NONNODE_TYPES(V) \
VIDEO_NONNODE_TYPES(V) \
+ NOTIFICATIONS_NONNODE_WRAPPER_TYPES(V) \
SHARED_WORKER_NONNODE_WRAPPER_TYPES(V) \
WORKER_NONNODE_WRAPPER_TYPES(V)
-#if ENABLE(XPATH)
-#define DOM_OBJECT_XPATH_TYPES(V) \
- V(XPATHEVALUATOR, XPathEvaluator) \
- V(XPATHEXCEPTION, XPathException) \
- V(XPATHEXPRESSION, XPathExpression) \
- V(XPATHNSRESOLVER, XPathNSResolver) \
- V(XPATHRESULT, XPathResult)
-#else
-#define DOM_OBJECT_XPATH_TYPES(V)
-#endif
-
-#if ENABLE(XSLT)
-#define DOM_OBJECT_XSLT_TYPES(V) \
- V(XSLTPROCESSOR, XSLTProcessor)
-#else
-#define DOM_OBJECT_XSLT_TYPES(V)
-#endif
-
#if ENABLE(DATABASE)
#define DOM_OBJECT_DATABASE_TYPES(V) \
V(DATABASE, Database) \
@@ -438,6 +443,53 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)();
#define DOM_OBJECT_WORKERS_TYPES(V)
#endif
+#if ENABLE(3D_CANVAS)
+#define DOM_OBJECT_3D_CANVAS_TYPES(V) \
+ V(CANVASARRAY, CanvasArray) \
+ V(CANVASARRAYBUFFER, CanvasArrayBuffer) \
+ V(CANVASBUFFER, CanvasBuffer) \
+ V(CANVASBYTEARRAY, CanvasByteArray) \
+ V(CANVASFLOATARRAY, CanvasFloatArray) \
+ V(CANVASFRAMEBUFFER, CanvasFramebuffer) \
+ V(CANVASINTARRAY, CanvasIntArray) \
+ V(CANVASPROGRAM, CanvasProgram) \
+ V(CANVASRENDERBUFFER, CanvasRenderbuffer) \
+ V(CANVASRENDERINGCONTEXT3D, CanvasRenderingContext3D) \
+ V(CANVASSHADER, CanvasShader) \
+ V(CANVASSHORTARRAY, CanvasShortArray) \
+ V(CANVASTEXTURE, CanvasTexture) \
+ V(CANVASUNSIGNEDBYTEARRAY, CanvasUnsignedByteArray) \
+ V(CANVASUNSIGNEDINTARRAY, CanvasUnsignedIntArray) \
+ V(CANVASUNSIGNEDSHORTARRAY, CanvasUnsignedShortArray)
+#else
+#define DOM_OBJECT_3D_CANVAS_TYPES(V)
+#endif
+
+#if ENABLE(XPATH)
+#define DOM_OBJECT_XPATH_TYPES(V) \
+ V(XPATHEVALUATOR, XPathEvaluator) \
+ V(XPATHEXCEPTION, XPathException) \
+ V(XPATHEXPRESSION, XPathExpression) \
+ V(XPATHNSRESOLVER, XPathNSResolver) \
+ V(XPATHRESULT, XPathResult)
+#else
+#define DOM_OBJECT_XPATH_TYPES(V)
+#endif
+
+#if ENABLE(XSLT)
+#define DOM_OBJECT_XSLT_TYPES(V) \
+ V(XSLTPROCESSOR, XSLTProcessor)
+#else
+#define DOM_OBJECT_XSLT_TYPES(V)
+#endif
+
+#if ENABLE(INSPECTOR)
+#define DOM_OBJECT_INSPECTOR_TYPES(V) \
+ V(INSPECTORBACKEND, InspectorBackend)
+#else
+#define DOM_OBJECT_INSPECTOR_TYPES(V)
+#endif
+
#if ENABLE(GEOLOCATION)
#define DOM_OBJECT_GEOLOCATION_TYPES(V) \
V(COORDINATES, Coordinates) \
@@ -448,6 +500,8 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)();
#define DOM_OBJECT_GEOLOCATION_TYPES(V)
#endif
+#if PLATFORM(ANDROID)
+// TODO: Upstream this guard.
#if ENABLE(TOUCH_EVENTS)
#define DOM_OBJECT_TOUCH_EVENT_TYPES(V) \
V(TOUCHLIST, TouchList) \
@@ -456,26 +510,30 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)();
#else
#define DOM_OBJECT_TOUCH_EVENT_TYPES(V)
#endif
+#endif
-#if PLATFORM(CHROMIUM)
+#if PLATFORM(ANDROID)
+#define DOM_OBJECT_VOIDCALLBACK_TYPES(V) \
+ V(VOIDCALLBACK, VoidCallback)
+#else
+#define DOM_OBJECT_VOIDCALLBACK_TYPES(V)
+#endif
+
+#if PLATFORM(ANDROID)
+// This block is modified, but is not Android-specific.
#define DOM_OBJECT_TYPES(V) \
DOM_OBJECT_TYPES_1(V) \
DOM_OBJECT_TYPES_2(V) \
DOM_OBJECT_DATABASE_TYPES(V) \
DOM_OBJECT_STORAGE_TYPES(V) \
DOM_OBJECT_WORKERS_TYPES(V) \
+ DOM_OBJECT_3D_CANVAS_TYPES(V) \
DOM_OBJECT_XPATH_TYPES(V) \
DOM_OBJECT_XSLT_TYPES(V) \
- V(INSPECTORBACKEND, InspectorBackend)
-#elif PLATFORM(ANDROID)
-#define DOM_OBJECT_TYPES(V) \
- DOM_OBJECT_TYPES_1(V) \
- DOM_OBJECT_TYPES_2(V) \
- DOM_OBJECT_DATABASE_TYPES(V) \
DOM_OBJECT_GEOLOCATION_TYPES(V) \
- DOM_OBJECT_STORAGE_TYPES(V) \
DOM_OBJECT_TOUCH_EVENT_TYPES(V) \
- DOM_OBJECT_WORKERS_TYPES(V)
+ DOM_OBJECT_VOIDCALLBACK_TYPES(V) \
+ DOM_OBJECT_INSPECTOR_TYPES(V)
#endif
#if ENABLE(SVG)
diff --git a/WebCore/bindings/v8/V8IsolatedWorld.cpp b/WebCore/bindings/v8/V8IsolatedWorld.cpp
index 1457545..d4e4f52 100644
--- a/WebCore/bindings/v8/V8IsolatedWorld.cpp
+++ b/WebCore/bindings/v8/V8IsolatedWorld.cpp
@@ -43,34 +43,29 @@
namespace WebCore {
-static int isolatedWorldCount = 0;
+int V8IsolatedWorld::isolatedWorldCount = 0;
-static void contextWeakReferenceCallback(v8::Persistent<v8::Value> object, void* isolated_world)
+void V8IsolatedWorld::contextWeakReferenceCallback(v8::Persistent<v8::Value> object, void* isolated_world)
{
// Our context is going away. Time to clean up the world.
V8IsolatedWorld* world = static_cast<V8IsolatedWorld*>(isolated_world);
delete world;
}
-void V8IsolatedWorld::evaluate(const Vector<ScriptSourceCode>& sources, V8Proxy* proxy, int extensionGroup)
+V8IsolatedWorld::V8IsolatedWorld(V8Proxy* proxy, int extensionGroup)
{
+ ++isolatedWorldCount;
+
v8::HandleScope scope;
- v8::Persistent<v8::Context> context = proxy->createNewContext(v8::Handle<v8::Object>(), extensionGroup);
+ m_context = SharedPersistent<v8::Context>::create(proxy->createNewContext(v8::Handle<v8::Object>(), extensionGroup));
// Run code in the new context.
- v8::Context::Scope context_scope(context);
-
- // The lifetime of this object is controlled by the V8 GC.
- // We need to create the world before touching DOM wrappers.
- V8IsolatedWorld* world = new V8IsolatedWorld(context);
+ v8::Context::Scope context_scope(m_context->get());
- V8Proxy::installHiddenObjectPrototype(context);
- proxy->installDOMWindow(context, proxy->frame()->domWindow());
-
- proxy->frame()->loader()->client()->didCreateIsolatedScriptContext();
+ m_context->get()->Global()->SetHiddenValue(V8HiddenPropertyName::isolatedWorld(), v8::External::Wrap(this));
- for (size_t i = 0; i < sources.size(); ++i)
- proxy->evaluate(sources[i], 0);
+ V8Proxy::installHiddenObjectPrototype(m_context->get());
+ proxy->installDOMWindow(m_context->get(), proxy->frame()->domWindow());
// Using the default security token means that the canAccess is always
// called, which is slow.
@@ -78,40 +73,24 @@ void V8IsolatedWorld::evaluate(const Vector<ScriptSourceCode>& sources, V8Proxy*
// created contexts so that they can all be updated when the
// document domain
// changes.
- // FIXME: Move this statement above proxy->evaluate? It seems like we
- // should set up the token before running the script.
- context->UseDefaultSecurityToken();
+ m_context->get()->UseDefaultSecurityToken();
- context.Dispose();
- // WARNING! This might well delete |world|.
+ proxy->frame()->loader()->client()->didCreateIsolatedScriptContext();
}
-V8IsolatedWorld::V8IsolatedWorld(v8::Handle<v8::Context> context)
- : m_context(v8::Persistent<v8::Context>::New(context))
+void V8IsolatedWorld::destroy()
{
- ++isolatedWorldCount;
- m_context.MakeWeak(this, &contextWeakReferenceCallback);
- m_context->Global()->SetHiddenValue(V8HiddenPropertyName::isolatedWorld(), v8::External::Wrap(this));
+ m_context->get().MakeWeak(this, &contextWeakReferenceCallback);
}
V8IsolatedWorld::~V8IsolatedWorld()
{
--isolatedWorldCount;
- m_context.Dispose();
- m_context.Clear();
+ m_context->disposeHandle();
}
-V8IsolatedWorld* V8IsolatedWorld::getEntered()
+V8IsolatedWorld* V8IsolatedWorld::getEnteredImpl()
{
- if (isolatedWorldCount == 0) {
- // This is a temporary performance optimization. Essentially,
- // GetHiddenValue is too slow for this code path. We need to get the
- // V8 team to add a real property to v8::Context for isolated worlds.
- // Until then, we optimize the common case of not having any isolated
- // worlds at all.
- return 0;
- }
-
if (!v8::Context::InContext())
return 0;
v8::HandleScope scope;
diff --git a/WebCore/bindings/v8/V8IsolatedWorld.h b/WebCore/bindings/v8/V8IsolatedWorld.h
index 2036e65..15d8711 100644
--- a/WebCore/bindings/v8/V8IsolatedWorld.h
+++ b/WebCore/bindings/v8/V8IsolatedWorld.h
@@ -35,6 +35,7 @@
#include "V8DOMMap.h"
#include "V8Index.h"
+#include "V8Proxy.h"
#include "V8Utilities.h"
#include "ScriptSourceCode.h" // for WebCore::ScriptSourceCode
@@ -57,11 +58,14 @@ namespace WebCore {
//
class V8IsolatedWorld {
public:
- ~V8IsolatedWorld();
+ // Creates an isolated world. To destroy it, call destroy().
+ // This will delete the isolated world when the context it owns is GC'd.
+ V8IsolatedWorld(V8Proxy* proxy, int extensionGroup);
- // Evaluate JavaScript in a new isolated world. The script has access
- // to the DOM of the document associated with |proxy|.
- static void evaluate(const Vector<ScriptSourceCode>& sources, V8Proxy* proxy, int extensionGroup);
+ // Call this to destroy the isolated world. It will be deleted sometime
+ // after this call, once all script references to the world's context
+ // have been dropped.
+ void destroy();
// Returns the isolated world associated with
// v8::Context::GetEntered(). Because worlds are isolated, the entire
@@ -71,26 +75,42 @@ namespace WebCore {
// FIXME: Consider edge cases with DOM mutation events that might
// violate this invariant.
//
- static V8IsolatedWorld* getEntered();
+ static V8IsolatedWorld* getEntered()
+ {
+ // This is a temporary performance optimization. Essentially,
+ // GetHiddenValue is too slow for this code path. We need to get the
+ // V8 team to add a real property to v8::Context for isolated worlds.
+ // Until then, we optimize the common case of not having any isolated
+ // worlds at all.
+ if (!isolatedWorldCount)
+ return 0;
+ return getEnteredImpl();
+ }
- v8::Handle<v8::Context> context() { return m_context; }
+ v8::Handle<v8::Context> context() { return m_context->get(); }
+ PassRefPtr<SharedPersistent<v8::Context> > shared_context() { return m_context; }
DOMDataStore* getDOMDataStore() const { return m_domDataStore.getStore(); }
private:
- // The lifetime of an isolated world is managed by the V8 garbage
- // collector. In particular, the object created by this constructor is
- // freed when |context| is garbage collected.
- explicit V8IsolatedWorld(v8::Handle<v8::Context> context);
+ ~V8IsolatedWorld();
+
+ static V8IsolatedWorld* getEnteredImpl();
+
+ // Called by the garbage collector when our JavaScript context is about
+ // to be destroyed.
+ static void contextWeakReferenceCallback(v8::Persistent<v8::Value> object, void* isolated_world);
// The v8::Context for the isolated world. This object is keep on the
// heap as long as |m_context| has not been garbage collected.
- v8::Persistent<v8::Context> m_context;
+ RefPtr<SharedPersistent<v8::Context> > m_context;
// The backing store for the isolated world's DOM wrappers. This class
// doesn't have visibility into the wrappers. This handle simply helps
// manage their lifetime.
DOMDataStoreHandle m_domDataStore;
+
+ static int isolatedWorldCount;
};
} // namespace WebCore
diff --git a/WebCore/bindings/v8/V8LazyEventListener.cpp b/WebCore/bindings/v8/V8LazyEventListener.cpp
index 59fa7be..9b58571 100644
--- a/WebCore/bindings/v8/V8LazyEventListener.cpp
+++ b/WebCore/bindings/v8/V8LazyEventListener.cpp
@@ -33,199 +33,115 @@
#include "Frame.h"
#include "V8Binding.h"
+#include "V8HiddenPropertyName.h"
#include "V8Proxy.h"
+#include <wtf/StdLibExtras.h>
+
namespace WebCore {
-V8LazyEventListener::V8LazyEventListener(Frame *frame, const String& code, const String& functionName, bool isSVGEvent)
- : V8AbstractEventListener(frame, true)
+V8LazyEventListener::V8LazyEventListener(Frame* frame, const String& code, const String& functionName, bool isSVGEvent)
+ : V8AbstractEventListener(frame, 0, true)
, m_code(code)
, m_functionName(functionName)
, m_isSVGEvent(isSVGEvent)
- , m_compiled(false)
- , m_wrappedFunctionCompiled(false)
-{
-}
-
-V8LazyEventListener::~V8LazyEventListener()
{
- disposeListenerObject();
-
- // Dispose wrapped function
- if (!m_wrappedFunction.IsEmpty()) {
-#ifndef NDEBUG
- V8GCController::unregisterGlobalHandle(this, m_wrappedFunction);
-#endif
- m_wrappedFunction.Dispose();
- m_wrappedFunction.Clear();
- }
}
-v8::Local<v8::Function> V8LazyEventListener::getListenerFunction()
+v8::Local<v8::Value> V8LazyEventListener::callListenerFunction(v8::Handle<v8::Value> jsEvent, Event* event)
{
- if (m_compiled) {
- ASSERT(m_listener.IsEmpty() || m_listener->IsFunction());
- return m_listener.IsEmpty() ? v8::Local<v8::Function>() : v8::Local<v8::Function>::New(v8::Persistent<v8::Function>::Cast(m_listener));
- }
-
- m_compiled = true;
-
- ASSERT(m_frame);
-
- {
- // Switch to the context of m_frame.
- v8::HandleScope handleScope;
-
- // Use the outer scope to hold context.
- v8::Handle<v8::Context> v8Context = V8Proxy::mainWorldContext(m_frame);
- // Bail out if we could not get the context.
- if (v8Context.IsEmpty())
- return v8::Local<v8::Function>();
-
- v8::Context::Scope scope(v8Context);
-
- // Wrap function around the event code. The parenthesis around the function are needed so that evaluating the code yields
- // the function value. Without the parenthesis the function value is thrown away.
-
- // Make it an anonymous function to avoid name conflict for cases like
- // <body onload='onload()'>
- // <script> function onload() { alert('hi'); } </script>.
- // Set function name to function object instead.
- // See issue 944690.
- //
- // The ECMAScript spec says (very obliquely) that the parameter to an event handler is named "evt".
- //
- // Don't use new lines so that lines in the modified handler
- // have the same numbers as in the original code.
- String code = "(function (evt) {";
- code.append(m_code);
- code.append("\n})");
-
- v8::Handle<v8::String> codeExternalString = v8ExternalString(code);
- v8::Handle<v8::Script> script = V8Proxy::compileScript(codeExternalString, m_frame->document()->url(), m_lineNumber - 1);
- if (!script.IsEmpty()) {
- V8Proxy* proxy = V8Proxy::retrieve(m_frame);
- ASSERT(proxy);
- v8::Local<v8::Value> value = proxy->runScript(script, false);
- if (!value.IsEmpty()) {
- ASSERT(value->IsFunction());
- v8::Local<v8::Function> listenerFunction = v8::Local<v8::Function>::Cast(value);
- listenerFunction->SetName(v8::String::New(fromWebCoreString(m_functionName), m_functionName.length()));
-
- m_listener = v8::Persistent<v8::Function>::New(listenerFunction);
-#ifndef NDEBUG
- V8GCController::registerGlobalHandle(EVENT_LISTENER, this, m_listener);
-#endif
- }
- }
- }
-
- ASSERT(m_listener.IsEmpty() || m_listener->IsFunction());
- return m_listener.IsEmpty() ? v8::Local<v8::Function>() : v8::Local<v8::Function>::New(v8::Persistent<v8::Function>::Cast(m_listener));
-}
-
-v8::Local<v8::Value> V8LazyEventListener::callListenerFunction(v8::Handle<v8::Value> jsEvent, Event* event, bool isWindowEvent)
-{
- v8::Local<v8::Function> handlerFunction = getWrappedListenerFunction();
- v8::Local<v8::Object> receiver = getReceiverObject(event, isWindowEvent);
+ v8::Local<v8::Function> handlerFunction = v8::Local<v8::Function>::Cast(getListenerObject());
+ v8::Local<v8::Object> receiver = getReceiverObject(event);
if (handlerFunction.IsEmpty() || receiver.IsEmpty())
return v8::Local<v8::Value>();
v8::Handle<v8::Value> parameters[1] = { jsEvent };
- V8Proxy* proxy = V8Proxy::retrieve(m_frame);
+ V8Proxy* proxy = V8Proxy::retrieve(frame());
return proxy->callFunction(handlerFunction, receiver, 1, parameters);
}
-
static v8::Handle<v8::Value> V8LazyEventListenerToString(const v8::Arguments& args)
{
- return args.Callee()->GetHiddenValue(v8::String::New("toStringString"));
+ return args.Holder()->GetHiddenValue(V8HiddenPropertyName::toStringString());
}
-
-v8::Local<v8::Function> V8LazyEventListener::getWrappedListenerFunction()
+void V8LazyEventListener::prepareListenerObject()
{
- if (m_wrappedFunctionCompiled) {
- ASSERT(m_wrappedFunction.IsEmpty() || m_wrappedFunction->IsFunction());
- return m_wrappedFunction.IsEmpty() ? v8::Local<v8::Function>() : v8::Local<v8::Function>::New(m_wrappedFunction);
- }
-
- m_wrappedFunctionCompiled = true;
-
- {
- // Switch to the context of m_frame.
- v8::HandleScope handleScope;
-
- // Use the outer scope to hold context.
- v8::Handle<v8::Context> v8Context = V8Proxy::mainWorldContext(m_frame);
- // Bail out if we cannot get the context.
- if (v8Context.IsEmpty())
- return v8::Local<v8::Function>();
-
- v8::Context::Scope scope(v8Context);
-
- // FIXME: cache the wrapper function.
-
- // Nodes other than the document object, when executing inline event handlers push document, form, and the target node on the scope chain.
- // We do this by using 'with' statement.
- // See chrome/fast/forms/form-action.html
- // chrome/fast/forms/selected-index-value.html
- // base/fast/overflow/onscroll-layer-self-destruct.html
- //
- // Don't use new lines so that lines in the modified handler
- // have the same numbers as in the original code.
- String code = "(function (evt) {" \
- "with (this.ownerDocument ? this.ownerDocument : {}) {" \
- "with (this.form ? this.form : {}) {" \
- "with (this) {" \
- "return (function(evt){";
- code.append(m_code);
- // Insert '\n' otherwise //-style comments could break the handler.
- code.append( "\n}).call(this, evt);}}}})");
- v8::Handle<v8::String> codeExternalString = v8ExternalString(code);
- v8::Handle<v8::Script> script = V8Proxy::compileScript(codeExternalString, m_frame->document()->url(), m_lineNumber);
- if (!script.IsEmpty()) {
- V8Proxy* proxy = V8Proxy::retrieve(m_frame);
- ASSERT(proxy);
- v8::Local<v8::Value> value = proxy->runScript(script, false);
- if (!value.IsEmpty()) {
- ASSERT(value->IsFunction());
-
- m_wrappedFunction = v8::Persistent<v8::Function>::New(v8::Local<v8::Function>::Cast(value));
-
- // Change the toString function on the wrapper function to avoid it returning the source for the actual wrapper function. Instead
- // it returns source for a clean wrapper function with the event argument wrapping the event source code. The reason for this
- // is that some web sites uses toString on event functions and the evals the source returned (some times a RegExp is applied as
- // well) for some other use. That fails miserably if the actual wrapper source is returned.
- v8::Local<v8::FunctionTemplate> toStringTemplate = v8::FunctionTemplate::New(V8LazyEventListenerToString);
- v8::Local<v8::Function> toStringFunction;
- if (!toStringTemplate.IsEmpty())
- toStringFunction = toStringTemplate->GetFunction();
- if (!toStringFunction.IsEmpty()) {
- String toStringResult = "function ";
- toStringResult.append(m_functionName);
- toStringResult.append("(");
- if (m_isSVGEvent)
- toStringResult.append("evt");
- else
- toStringResult.append("event");
- toStringResult.append(") {\n ");
- toStringResult.append(m_code);
- toStringResult.append("\n}");
- toStringFunction->SetHiddenValue(v8::String::New("toStringString"), v8ExternalString(toStringResult));
- m_wrappedFunction->Set(v8::String::New("toString"), toStringFunction);
- }
-
-#ifndef NDEBUG
- V8GCController::registerGlobalHandle(EVENT_LISTENER, this, m_wrappedFunction);
-#endif
- m_wrappedFunction->SetName(v8::String::New(fromWebCoreString(m_functionName), m_functionName.length()));
+ if (hasExistingListenerObject())
+ return;
+
+ // Switch to the context of m_frame.
+ v8::HandleScope handleScope;
+
+ // Use the outer scope to hold context.
+ v8::Handle<v8::Context> v8Context = V8Proxy::mainWorldContext(frame());
+ // Bail out if we cannot get the context.
+ if (v8Context.IsEmpty())
+ return;
+
+ v8::Context::Scope scope(v8Context);
+
+ // FIXME: cache the wrapper function.
+
+ // Nodes other than the document object, when executing inline event handlers push document, form, and the target node on the scope chain.
+ // We do this by using 'with' statement.
+ // See chrome/fast/forms/form-action.html
+ // chrome/fast/forms/selected-index-value.html
+ // base/fast/overflow/onscroll-layer-self-destruct.html
+ //
+ // Don't use new lines so that lines in the modified handler
+ // have the same numbers as in the original code.
+ String code = "(function (evt) {" \
+ "with (this.ownerDocument ? this.ownerDocument : {}) {" \
+ "with (this.form ? this.form : {}) {" \
+ "with (this) {" \
+ "return (function(evt){";
+ code.append(m_code);
+ // Insert '\n' otherwise //-style comments could break the handler.
+ code.append( "\n}).call(this, evt);}}}})");
+ v8::Handle<v8::String> codeExternalString = v8ExternalString(code);
+ v8::Handle<v8::Script> script = V8Proxy::compileScript(codeExternalString, frame()->document()->url(), lineNumber());
+ if (!script.IsEmpty()) {
+ V8Proxy* proxy = V8Proxy::retrieve(frame());
+ ASSERT(proxy);
+ v8::Local<v8::Value> value = proxy->runScript(script, false);
+ if (!value.IsEmpty()) {
+ ASSERT(value->IsFunction());
+
+ v8::Local<v8::Function> wrappedFunction = v8::Local<v8::Function>::Cast(value);
+
+ // Change the toString function on the wrapper function to avoid it
+ // returning the source for the actual wrapper function. Instead it
+ // returns source for a clean wrapper function with the event
+ // argument wrapping the event source code. The reason for this is
+ // that some web sites use toString on event functions and eval the
+ // source returned (sometimes a RegExp is applied as well) for some
+ // other use. That fails miserably if the actual wrapper source is
+ // returned.
+ DEFINE_STATIC_LOCAL(v8::Persistent<v8::FunctionTemplate>, toStringTemplate, ());
+ if (toStringTemplate.IsEmpty())
+ toStringTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(V8LazyEventListenerToString));
+ v8::Local<v8::Function> toStringFunction;
+ if (!toStringTemplate.IsEmpty())
+ toStringFunction = toStringTemplate->GetFunction();
+ if (!toStringFunction.IsEmpty()) {
+ String toStringResult = "function ";
+ toStringResult.append(m_functionName);
+ toStringResult.append("(");
+ toStringResult.append(m_isSVGEvent ? "evt" : "event");
+ toStringResult.append(") {\n ");
+ toStringResult.append(m_code);
+ toStringResult.append("\n}");
+ wrappedFunction->SetHiddenValue(V8HiddenPropertyName::toStringString(), v8ExternalString(toStringResult));
+ wrappedFunction->Set(v8::String::New("toString"), toStringFunction);
}
+
+ wrappedFunction->SetName(v8::String::New(fromWebCoreString(m_functionName), m_functionName.length()));
+
+ setListenerObject(wrappedFunction);
}
}
-
- return v8::Local<v8::Function>::New(m_wrappedFunction);
}
} // namespace WebCore
diff --git a/WebCore/bindings/v8/V8LazyEventListener.h b/WebCore/bindings/v8/V8LazyEventListener.h
index 62d9342..ba460e6 100644
--- a/WebCore/bindings/v8/V8LazyEventListener.h
+++ b/WebCore/bindings/v8/V8LazyEventListener.h
@@ -50,30 +50,19 @@ namespace WebCore {
return adoptRef(new V8LazyEventListener(frame, code, functionName, isSVGEvent));
}
- // For lazy event listener, the listener object is the same as its listener
- // function without additional scope chains.
- virtual v8::Local<v8::Object> getListenerObject() { return getWrappedListenerFunction(); }
+ virtual bool isLazy() const { return true; }
+
+ protected:
+ virtual void prepareListenerObject();
private:
V8LazyEventListener(Frame*, const String& code, const String& functionName, bool isSVGEvent);
- virtual ~V8LazyEventListener();
- virtual bool virtualisAttribute() const { return true; }
+ virtual v8::Local<v8::Value> callListenerFunction(v8::Handle<v8::Value> jsEvent, Event*);
String m_code;
String m_functionName;
bool m_isSVGEvent;
- bool m_compiled;
-
- // If the event listener is on a non-document dom node, we compile the function with some implicit scope chains before it.
- bool m_wrappedFunctionCompiled;
- v8::Persistent<v8::Function> m_wrappedFunction;
-
- v8::Local<v8::Function> getWrappedListenerFunction();
-
- virtual v8::Local<v8::Value> callListenerFunction(v8::Handle<v8::Value> jsEvent, Event*, bool isWindowEvent);
-
- v8::Local<v8::Function> getListenerFunction();
};
} // namespace WebCore
diff --git a/WebCore/bindings/v8/V8ObjectEventListener.cpp b/WebCore/bindings/v8/V8ObjectEventListener.cpp
deleted file mode 100644
index f10766c..0000000
--- a/WebCore/bindings/v8/V8ObjectEventListener.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2006, 2007, 2008, 2009 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "V8ObjectEventListener.h"
-
-#include "Frame.h"
-#include "V8Proxy.h"
-
-namespace WebCore {
-
-static void weakObjectEventListenerCallback(v8::Persistent<v8::Value>, void* parameter)
-{
- V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(parameter);
-
- // Remove the wrapper
- Frame* frame = listener->frame();
- if (frame) {
- V8Proxy* proxy = V8Proxy::retrieve(frame);
- if (proxy)
- proxy->objectListeners()->remove(listener);
-
- // Because the listener is no longer in the list, it must be disconnected from the frame to avoid dangling frame pointer
- // in the destructor.
- listener->disconnectFrame();
- }
- listener->disposeListenerObject();
-}
-
-// An object event listener wrapper only holds a weak reference to the
-// JS function. A strong reference can create a cycle.
-//
-// The lifetime of these objects is bounded by the life time of the JS
-// wrapper of XHR or Node. So we can create a hidden reference from
-// the JS wrapper to to its JS function.
-//
-// (map)
-// XHR or Node <---------- JS_wrapper
-// | (hidden) : ^
-// V V : (may be reachable by closure)
-// V8_listener --------> JS_function
-// (weak) <-- may create a cycle if it is strong
-//
-// The persistent reference is made weak in the constructor of
-// V8ObjectEventListener.
-
-V8ObjectEventListener::V8ObjectEventListener(Frame* frame, v8::Local<v8::Object> listener, bool isInline)
- : V8EventListener(frame, listener, isInline)
-{
- m_listener.MakeWeak(this, weakObjectEventListenerCallback);
-}
-
-V8ObjectEventListener::~V8ObjectEventListener()
-{
- if (m_frame) {
- ASSERT(!m_listener.IsEmpty());
- V8Proxy* proxy = V8Proxy::retrieve(m_frame);
- if (proxy)
- proxy->objectListeners()->remove(this);
- }
-
- disposeListenerObject();
-}
-
-} // namespace WebCore
diff --git a/WebCore/bindings/v8/V8Proxy.cpp b/WebCore/bindings/v8/V8Proxy.cpp
index 1cfafb8..dd3c218 100644
--- a/WebCore/bindings/v8/V8Proxy.cpp
+++ b/WebCore/bindings/v8/V8Proxy.cpp
@@ -32,11 +32,14 @@
#include "V8Proxy.h"
#include "CSSMutableStyleDeclaration.h"
-#include "CString.h"
+#include "DateExtension.h"
#include "DOMObjectsInclude.h"
#include "DocumentLoader.h"
#include "FrameLoaderClient.h"
+#include "Page.h"
+#include "PageGroup.h"
#include "ScriptController.h"
+#include "StorageNamespace.h"
#include "V8Binding.h"
#include "V8Collection.h"
#include "V8ConsoleMessage.h"
@@ -47,6 +50,8 @@
#include "V8Index.h"
#include "V8IsolatedWorld.h"
+#include <algorithm>
+#include <utility>
#include <v8.h>
#include <v8-debug.h>
#include <wtf/Assertions.h>
@@ -62,12 +67,16 @@
#include "TimeCounter.h"
#endif
+#if PLATFORM(ANDROID)
+#include "CString.h"
+#endif
+
namespace WebCore {
v8::Persistent<v8::Context> V8Proxy::m_utilityContext;
// Static list of registered extensions
-V8ExtensionList V8Proxy::m_extensions;
+V8Extensions V8Proxy::m_extensions;
const char* V8Proxy::kContextDebugDataType = "type";
const char* V8Proxy::kContextDebugDataValue = "value";
@@ -213,6 +222,14 @@ static void reportFatalErrorInV8(const char* location, const char* message)
handleFatalErrorInV8();
}
+V8Proxy::V8Proxy(Frame* frame)
+ : m_frame(frame),
+ m_context(SharedPersistent<v8::Context>::create()),
+ m_listenerGuard(V8ListenerGuard::create()),
+ m_inlineCode(false),
+ m_timerCallback(false),
+ m_recursion(0) { }
+
V8Proxy::~V8Proxy()
{
clearForClose();
@@ -230,22 +247,6 @@ void V8Proxy::destroyGlobal()
}
}
-static void disconnectEventListenersInList(V8EventListenerList& list)
-{
- V8EventListenerList::iterator it = list.begin();
- while (it != list.end()) {
- (*it)->disconnectFrame();
- ++it;
- }
- list.clear();
-}
-
-void V8Proxy::disconnectEventListeners()
-{
- disconnectEventListenersInList(m_eventListeners);
- disconnectEventListenersInList(m_objectListeners);
-}
-
v8::Handle<v8::Script> V8Proxy::compileScript(v8::Handle<v8::String> code, const String& fileName, int baseLine)
#ifdef ANDROID_INSTRUMENT
{
@@ -296,10 +297,32 @@ bool V8Proxy::handleOutOfMemory()
return true;
}
-void V8Proxy::evaluateInNewWorld(const Vector<ScriptSourceCode>& sources, int extensionGroup)
+void V8Proxy::evaluateInIsolatedWorld(int worldID, const Vector<ScriptSourceCode>& sources, int extensionGroup)
{
initContextIfNeeded();
- V8IsolatedWorld::evaluate(sources, this, extensionGroup);
+
+ v8::HandleScope handleScope;
+ V8IsolatedWorld* world = 0;
+
+ if (worldID > 0) {
+ IsolatedWorldMap::iterator iter = m_isolatedWorlds.find(worldID);
+ if (iter != m_isolatedWorlds.end()) {
+ world = iter->second;
+ } else {
+ world = new V8IsolatedWorld(this, extensionGroup);
+ m_isolatedWorlds.set(worldID, world);
+ }
+ } else {
+ world = new V8IsolatedWorld(this, extensionGroup);
+ }
+
+ v8::Local<v8::Context> context = v8::Local<v8::Context>::New(world->context());
+ v8::Context::Scope context_scope(context);
+ for (size_t i = 0; i < sources.size(); ++i)
+ evaluate(sources[i], 0);
+
+ if (worldID == 0)
+ world->destroy();
}
void V8Proxy::evaluateInNewContext(const Vector<ScriptSourceCode>& sources, int extensionGroup)
@@ -309,7 +332,7 @@ void V8Proxy::evaluateInNewContext(const Vector<ScriptSourceCode>& sources, int
v8::HandleScope handleScope;
// Set up the DOM window as the prototype of the new global object.
- v8::Handle<v8::Context> windowContext = m_context;
+ v8::Handle<v8::Context> windowContext = context();
v8::Handle<v8::Object> windowGlobal = windowContext->Global();
v8::Handle<v8::Object> windowWrapper = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, windowGlobal);
@@ -357,29 +380,31 @@ v8::Local<v8::Value> V8Proxy::evaluate(const ScriptSourceCode& source, Node* nod
ASSERT(v8::Context::InContext());
LOCK_V8;
- // Compile the script.
- v8::Local<v8::String> code = v8ExternalString(source.source());
-#if PLATFORM(CHROMIUM)
- // TODO(andreip): ChromeBridge->BrowserBridge?
- ChromiumBridge::traceEventBegin("v8.compile", node, "");
-#endif
-
- // NOTE: For compatibility with WebCore, ScriptSourceCode's line starts at
- // 1, whereas v8 starts at 0.
- v8::Handle<v8::Script> script = compileScript(code, source.url(), source.startLine() - 1);
-#if PLATFORM(CHROMIUM)
- // TODO(andreip): ChromeBridge->BrowserBridge?
- ChromiumBridge::traceEventEnd("v8.compile", node, "");
- ChromiumBridge::traceEventBegin("v8.run", node, "");
-#endif
v8::Local<v8::Value> result;
{
- // Isolate exceptions that occur when executing the code. These
- // exceptions should not interfere with javascript code we might
- // evaluate from C++ when returning from here.
+ // Isolate exceptions that occur when compiling and executing
+ // the code. These exceptions should not interfere with
+ // javascript code we might evaluate from C++ when returning
+ // from here.
v8::TryCatch tryCatch;
tryCatch.SetVerbose(true);
+ // Compile the script.
+ v8::Local<v8::String> code = v8ExternalString(source.source());
+#if PLATFORM(CHROMIUM)
+ // TODO(andreip): ChromeBridge->BrowserBridge?
+ ChromiumBridge::traceEventBegin("v8.compile", node, "");
+#endif
+
+ // NOTE: For compatibility with WebCore, ScriptSourceCode's line starts at
+ // 1, whereas v8 starts at 0.
+ v8::Handle<v8::Script> script = compileScript(code, source.url(), source.startLine() - 1);
+#if PLATFORM(CHROMIUM)
+ // TODO(andreip): ChromeBridge->BrowserBridge?
+ ChromiumBridge::traceEventEnd("v8.compile", node, "");
+
+ ChromiumBridge::traceEventBegin("v8.run", node, "");
+#endif
// Set inlineCode to true for <a href="javascript:doSomething()">
// and false for <script>doSomething</script>. We make a rough guess at
// this based on whether the script source has a URL.
@@ -431,15 +456,18 @@ v8::Local<v8::Value> V8Proxy::runScriptInternal(v8::Handle<v8::Script> script, b
v8::Local<v8::Value> result;
{
V8ConsoleMessage::Scope scope;
- m_recursion++;
// See comment in V8Proxy::callFunction.
m_frame->keepAlive();
+ m_recursion++;
result = script->Run();
m_recursion--;
}
+ // Release the storage mutex if applicable.
+ releaseStorageMutex();
+
if (handleOutOfMemory())
ASSERT(result.IsEmpty());
@@ -461,14 +489,21 @@ v8::Local<v8::Value> V8Proxy::callFunction(v8::Handle<v8::Function> function, v8
#ifdef ANDROID_INSTRUMENT
android::TimeCounter::start(android::TimeCounter::JavaScriptExecuteTimeCounter);
#endif
-
- // For now, we don't put any artificial limitations on the depth
- // of recursion that stems from calling functions. This is in
- // contrast to the script evaluations.
v8::Local<v8::Value> result;
{
V8ConsoleMessage::Scope scope;
+ if (m_recursion >= kMaxRecursionDepth) {
+ v8::Local<v8::String> code = v8::String::New("throw new RangeError('Maximum call stack size exceeded.')");
+ if (code.IsEmpty())
+ return result;
+ v8::Local<v8::Script> script = v8::Script::Compile(code);
+ if (script.IsEmpty())
+ return result;
+ script->Run();
+ return result;
+ }
+
// Evaluating the JavaScript could cause the frame to be deallocated,
// so we start the keep alive timer here.
// Frame::keepAlive method adds the ref count of the frame and sets a
@@ -476,9 +511,14 @@ v8::Local<v8::Value> V8Proxy::callFunction(v8::Handle<v8::Function> function, v8
// execution finishs before firing the timer.
m_frame->keepAlive();
+ m_recursion++;
result = function->Call(receiver, argc, args);
+ m_recursion--;
}
+ // Release the storage mutex if applicable.
+ releaseStorageMutex();
+
if (v8::V8::IsDead())
handleFatalErrorInV8();
@@ -508,17 +548,13 @@ v8::Local<v8::Value> V8Proxy::newInstance(v8::Handle<v8::Function> constructor,
return result;
}
-v8::Local<v8::Object> V8Proxy::createWrapperFromCache(V8ClassIndex::V8WrapperType type)
+v8::Local<v8::Object> V8Proxy::createWrapperFromCacheSlowCase(V8ClassIndex::V8WrapperType type)
{
- int classIndex = V8ClassIndex::ToInt(type);
- v8::Local<v8::Object> clone(m_wrapperBoilerplates->CloneElementAt(classIndex));
- if (!clone.IsEmpty())
- return clone;
-
// Not in cache.
+ int classIndex = V8ClassIndex::ToInt(type);
initContextIfNeeded();
- v8::Context::Scope scope(m_context);
- v8::Local<v8::Function> function = V8DOMWrapper::getConstructor(type, getHiddenObjectPrototype(m_context));
+ v8::Context::Scope scope(context());
+ v8::Local<v8::Function> function = V8DOMWrapper::getConstructor(type, getHiddenObjectPrototype(context()));
v8::Local<v8::Object> instance = SafeAllocation::newInstance(function);
if (!instance.IsEmpty()) {
m_wrapperBoilerplates->Set(v8::Integer::New(classIndex), instance);
@@ -531,9 +567,9 @@ bool V8Proxy::isContextInitialized()
{
// m_context, m_global, and m_wrapperBoilerplates should
// all be non-empty if if m_context is non-empty.
- ASSERT(m_context.IsEmpty() || !m_global.IsEmpty());
- ASSERT(m_context.IsEmpty() || !m_wrapperBoilerplates.IsEmpty());
- return !m_context.IsEmpty();
+ ASSERT(context().IsEmpty() || !m_global.IsEmpty());
+ ASSERT(context().IsEmpty() || !m_wrapperBoilerplates.IsEmpty());
+ return !context().IsEmpty();
}
DOMWindow* V8Proxy::retrieveWindow(v8::Handle<v8::Context> context)
@@ -547,7 +583,14 @@ DOMWindow* V8Proxy::retrieveWindow(v8::Handle<v8::Context> context)
Frame* V8Proxy::retrieveFrame(v8::Handle<v8::Context> context)
{
- return retrieveWindow(context)->frame();
+ DOMWindow* window = retrieveWindow(context);
+ Frame* frame = window->frame();
+ if (frame && frame->domWindow() == window)
+ return frame;
+ // We return 0 here because |context| is detached from the Frame. If we
+ // did return |frame| we could get in trouble because the frame could be
+ // navigated to another security origin.
+ return 0;
}
Frame* V8Proxy::retrieveFrameForEnteredContext()
@@ -701,21 +744,20 @@ void V8Proxy::updateDocumentWrapperCache()
clearDocumentWrapperCache();
return;
}
- m_context->Global()->ForceSet(v8::String::New("document"), documentWrapper, static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete));
+ context()->Global()->ForceSet(v8::String::New("document"), documentWrapper, static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete));
}
void V8Proxy::clearDocumentWrapperCache()
{
- ASSERT(!m_context.IsEmpty());
- m_context->Global()->ForceDelete(v8::String::New("document"));
+ ASSERT(!context().IsEmpty());
+ context()->Global()->ForceDelete(v8::String::New("document"));
}
void V8Proxy::disposeContextHandles()
{
- if (!m_context.IsEmpty()) {
+ if (!context().IsEmpty()) {
m_frame->loader()->client()->didDestroyScriptContextForFrame();
- m_context.Dispose();
- m_context.Clear();
+ shared_context()->disposeHandle();
}
if (!m_wrapperBoilerplates.IsEmpty()) {
@@ -727,9 +769,40 @@ void V8Proxy::disposeContextHandles()
}
}
+void V8Proxy::releaseStorageMutex()
+{
+ // If we've just left a top level script context and local storage has been
+ // instantiated, we must ensure that any storage locks have been freed.
+ // Per http://dev.w3.org/html5/spec/Overview.html#storage-mutex
+ if (m_recursion != 0)
+ return;
+ Page* page = m_frame->page();
+ if (!page)
+ return;
+ if (page->group().hasLocalStorage())
+ page->group().localStorage()->unlock();
+}
+
+void V8Proxy::disconnectEventListeners()
+{
+ m_listenerGuard->disconnectListeners();
+ m_listenerGuard = V8ListenerGuard::create();
+}
+
+void V8Proxy::resetIsolatedWorlds()
+{
+ for (IsolatedWorldMap::iterator iter = m_isolatedWorlds.begin();
+ iter != m_isolatedWorlds.end(); ++iter) {
+ iter->second->destroy();
+ }
+ m_isolatedWorlds.clear();
+}
+
void V8Proxy::clearForClose()
{
- if (!m_context.IsEmpty()) {
+ resetIsolatedWorlds();
+
+ if (!context().IsEmpty()) {
LOCK_V8;
v8::HandleScope handleScope;
@@ -741,13 +814,14 @@ void V8Proxy::clearForClose()
void V8Proxy::clearForNavigation()
{
disconnectEventListeners();
+ resetIsolatedWorlds();
- if (!m_context.IsEmpty()) {
+ if (!context().IsEmpty()) {
LOCK_V8;
v8::HandleScope handle;
clearDocumentWrapper();
- v8::Context::Scope contextScope(m_context);
+ v8::Context::Scope contextScope(context());
// Clear the document wrapper cache before turning on access checks on
// the old DOMWindow wrapper. This way, access to the document wrapper
@@ -760,7 +834,7 @@ void V8Proxy::clearForNavigation()
wrapper->TurnOnAccessCheck();
// Separate the context from its global object.
- m_context->DetachGlobal();
+ context()->DetachGlobal();
disposeContextHandles();
}
@@ -771,7 +845,7 @@ void V8Proxy::setSecurityToken()
Document* document = m_frame->document();
// Setup security origin and security token.
if (!document) {
- m_context->UseDefaultSecurityToken();
+ context()->UseDefaultSecurityToken();
return;
}
@@ -791,14 +865,14 @@ void V8Proxy::setSecurityToken()
// case, we use the global object as the security token to avoid
// calling canAccess when a script accesses its own objects.
if (token.isEmpty() || token == "null") {
- m_context->UseDefaultSecurityToken();
+ context()->UseDefaultSecurityToken();
return;
}
CString utf8Token = token.utf8();
// NOTE: V8 does identity comparison in fast path, must use a symbol
// as the security token.
- m_context->SetSecurityToken(v8::String::NewSymbol(utf8Token.data(), utf8Token.length()));
+ context()->SetSecurityToken(v8::String::NewSymbol(utf8Token.data(), utf8Token.length()));
}
void V8Proxy::updateDocument()
@@ -816,6 +890,10 @@ void V8Proxy::updateDocument()
// global object wrapper succeed.
initContextIfNeeded();
+ // Bail out if context initialization failed.
+ if (context().IsEmpty())
+ return;
+
// We have a new document and we need to update the cache.
updateDocumentWrapperCache();
@@ -930,21 +1008,26 @@ v8::Persistent<v8::Context> V8Proxy::createNewContext(v8::Handle<v8::Object> glo
// Install a security handler with V8.
globalTemplate->SetAccessCheckCallbacks(V8Custom::v8DOMWindowNamedSecurityCheck, V8Custom::v8DOMWindowIndexedSecurityCheck, v8::Integer::New(V8ClassIndex::DOMWINDOW));
+ globalTemplate->SetInternalFieldCount(V8Custom::kDOMWindowInternalFieldCount);
+
+ // Used to avoid sleep calls in unload handlers.
+ if (!registeredExtensionWithV8(DateExtension::get()))
+ registerExtension(DateExtension::get(), String());
// Dynamically tell v8 about our extensions now.
OwnArrayPtr<const char*> extensionNames(new const char*[m_extensions.size()]);
int index = 0;
- for (V8ExtensionList::iterator it = m_extensions.begin(); it != m_extensions.end(); ++it) {
- if (it->group && it->group != extensionGroup)
+ for (size_t i = 0; i < m_extensions.size(); ++i) {
+ if (m_extensions[i].group && m_extensions[i].group != extensionGroup)
continue;
// Note: we check the loader URL here instead of the document URL
// because we might be currently loading an URL into a blank page.
// See http://code.google.com/p/chromium/issues/detail?id=10924
- if (it->scheme.length() > 0 && (it->scheme != m_frame->loader()->activeDocumentLoader()->url().protocol() || it->scheme != m_frame->page()->mainFrame()->loader()->activeDocumentLoader()->url().protocol()))
+ if (m_extensions[i].scheme.length() > 0 && (m_extensions[i].scheme != m_frame->loader()->activeDocumentLoader()->url().protocol() || m_extensions[i].scheme != m_frame->page()->mainFrame()->loader()->activeDocumentLoader()->url().protocol()))
continue;
- extensionNames[index++] = it->extension->name();
+ extensionNames[index++] = m_extensions[i].extension->name();
}
v8::ExtensionConfiguration extensions(index, extensionNames.get());
result = v8::Context::New(&extensions, globalTemplate, global);
@@ -967,12 +1050,14 @@ bool V8Proxy::installDOMWindow(v8::Handle<v8::Context> context, DOMWindow* windo
// Wrap the window.
V8DOMWrapper::setDOMWrapper(jsWindow, V8ClassIndex::ToInt(V8ClassIndex::DOMWINDOW), window);
+ V8DOMWrapper::setDOMWrapper(v8::Handle<v8::Object>::Cast(jsWindow->GetPrototype()), V8ClassIndex::ToInt(V8ClassIndex::DOMWINDOW), window);
window->ref();
V8DOMWrapper::setJSWrapperForDOMObject(window, v8::Persistent<v8::Object>::New(jsWindow));
// Insert the window instance as the prototype of the shadow object.
v8::Handle<v8::Object> v8Global = context->Global();
+ V8DOMWrapper::setDOMWrapper(v8::Handle<v8::Object>::Cast(v8Global->GetPrototype()), V8ClassIndex::ToInt(V8ClassIndex::DOMWINDOW), window);
v8Global->Set(implicitProtoString, jsWindow);
return true;
}
@@ -1015,7 +1100,7 @@ bool V8Proxy::installDOMWindow(v8::Handle<v8::Context> context, DOMWindow* windo
void V8Proxy::initContextIfNeeded()
{
// Bail out if the context has already been initialized.
- if (!m_context.IsEmpty())
+ if (!context().IsEmpty())
return;
#ifdef ANDROID_INSTRUMENT
@@ -1044,17 +1129,18 @@ void V8Proxy::initContextIfNeeded()
isV8Initialized = true;
}
- m_context = createNewContext(m_global, 0);
- if (m_context.IsEmpty())
+
+ v8::Persistent<v8::Context> context = createNewContext(m_global, 0);
+ if (context.IsEmpty())
return;
+ m_context->set(context);
+
- // Starting from now, use local context only.
- v8::Local<v8::Context> v8Context = context();
- v8::Context::Scope contextScope(v8Context);
+ v8::Context::Scope contextScope(context);
// Store the first global object created so we can reuse it.
if (m_global.IsEmpty()) {
- m_global = v8::Persistent<v8::Object>::New(v8Context->Global());
+ m_global = v8::Persistent<v8::Object>::New(context->Global());
// Bail out if allocation of the first global objects fails.
if (m_global.IsEmpty()) {
disposeContextHandles();
@@ -1065,7 +1151,7 @@ void V8Proxy::initContextIfNeeded()
#endif
}
- installHiddenObjectPrototype(m_context);
+ installHiddenObjectPrototype(context);
m_wrapperBoilerplates = v8::Persistent<v8::Array>::New(v8::Array::New(V8ClassIndex::WRAPPER_TYPE_COUNT));
// Bail out if allocation failed.
if (m_wrapperBoilerplates.IsEmpty()) {
@@ -1076,7 +1162,7 @@ void V8Proxy::initContextIfNeeded()
V8GCController::registerGlobalHandle(PROXY, this, m_wrapperBoilerplates);
#endif
- if (!installDOMWindow(v8Context, m_frame->domWindow()))
+ if (!installDOMWindow(context, m_frame->domWindow()))
disposeContextHandles();
updateDocument();
@@ -1162,6 +1248,23 @@ v8::Local<v8::Context> V8Proxy::context(Frame* frame)
return context;
}
+PassRefPtr<SharedPersistent<v8::Context> > V8Proxy::shared_context(Frame* frame)
+{
+ V8Proxy *proxy = V8Proxy::retrieve(frame);
+ if (!proxy)
+ return 0;
+
+ proxy->initContextIfNeeded();
+ RefPtr<SharedPersistent<v8::Context> > context = proxy->shared_context();
+ if (V8IsolatedWorld* world = V8IsolatedWorld::getEntered()) {
+ context = world->shared_context();
+ if (frame != V8Proxy::retrieveFrame(context->get()))
+ return 0;
+ }
+
+ return context;
+}
+
v8::Local<v8::Context> V8Proxy::mainWorldContext(Frame* frame)
{
V8Proxy* proxy = retrieve(frame);
@@ -1169,7 +1272,7 @@ v8::Local<v8::Context> V8Proxy::mainWorldContext(Frame* frame)
return v8::Local<v8::Context>();
proxy->initContextIfNeeded();
- return proxy->context();
+ return v8::Local<v8::Context>::New(proxy->context());
}
v8::Local<v8::Context> V8Proxy::currentContext()
@@ -1279,14 +1382,21 @@ String V8Proxy::sourceName()
#endif
}
-void V8Proxy::registerExtensionWithV8(v8::Extension* extension) {
+void V8Proxy::registerExtensionWithV8(v8::Extension* extension)
+{
// If the extension exists in our list, it was already registered with V8.
- for (V8ExtensionList::iterator it = m_extensions.begin(); it != m_extensions.end(); ++it) {
- if (it->extension == extension)
- return;
+ if (!registeredExtensionWithV8(extension))
+ v8::RegisterExtension(extension);
+}
+
+bool V8Proxy::registeredExtensionWithV8(v8::Extension* extension)
+{
+ for (size_t i = 0; i < m_extensions.size(); ++i) {
+ if (m_extensions[i].extension == extension)
+ return true;
}
- v8::RegisterExtension(extension);
+ return false;
}
void V8Proxy::registerExtension(v8::Extension* extension, const String& schemeRestriction)
@@ -1306,17 +1416,17 @@ void V8Proxy::registerExtension(v8::Extension* extension, int extensionGroup)
bool V8Proxy::setContextDebugId(int debugId)
{
ASSERT(debugId > 0);
- if (m_context.IsEmpty())
+ if (context().IsEmpty())
return false;
v8::HandleScope scope;
- if (!m_context->GetData()->IsUndefined())
+ if (!context()->GetData()->IsUndefined())
return false;
- v8::Context::Scope contextScope(m_context);
+ v8::Context::Scope contextScope(context());
v8::Handle<v8::Object> contextData = v8::Object::New();
contextData->Set(v8::String::New(kContextDebugDataType), v8::String::New("page"));
contextData->Set(v8::String::New(kContextDebugDataValue), v8::Integer::New(debugId));
- m_context->SetData(contextData);
+ context()->SetData(contextData);
return true;
}
diff --git a/WebCore/bindings/v8/V8Proxy.h b/WebCore/bindings/v8/V8Proxy.h
index d8f546c..30f682d 100644
--- a/WebCore/bindings/v8/V8Proxy.h
+++ b/WebCore/bindings/v8/V8Proxy.h
@@ -31,20 +31,14 @@
#ifndef V8Proxy_h
#define V8Proxy_h
-#include "Node.h"
-#include "NodeFilter.h"
-#include "PlatformString.h" // for WebCore::String
#include "ScriptSourceCode.h" // for WebCore::ScriptSourceCode
#include "SecurityOrigin.h" // for WebCore::SecurityOrigin
-#include "V8CustomBinding.h"
-#include "V8DOMMap.h"
+#include "SharedPersistent.h"
+#include "V8AbstractEventListener.h"
#include "V8DOMWrapper.h"
-#include "V8EventListenerList.h"
#include "V8GCController.h"
#include "V8Index.h"
-#include "V8Utilities.h"
#include <v8.h>
-#include <wtf/Assertions.h>
#include <wtf/PassRefPtr.h> // so generated bindings don't have to
#include <wtf/Vector.h>
@@ -57,49 +51,14 @@
namespace WebCore {
- class CSSRule;
- class CSSRuleList;
- class CSSStyleDeclaration;
- class CSSValue;
- class CSSValueList;
- class ClientRectList;
- class DOMImplementation;
class DOMWindow;
- class Document;
- class Element;
- class Event;
- class EventListener;
- class EventTarget;
class Frame;
- class HTMLCollection;
- class HTMLDocument;
- class HTMLElement;
- class HTMLOptionsCollection;
- class MediaList;
- class MimeType;
- class MimeTypeArray;
- class NamedNodeMap;
- class Navigator;
class Node;
- class NodeFilter;
- class NodeList;
- class Plugin;
- class PluginArray;
class SVGElement;
-#if ENABLE(SVG)
- class SVGElementInstance;
-#endif
- class Screen;
class ScriptExecutionContext;
-#if ENABLE(DOM_STORAGE)
- class Storage;
- class StorageEvent;
-#endif
class String;
- class StyleSheet;
- class StyleSheetList;
class V8EventListener;
- class V8ObjectEventListener;
+ class V8IsolatedWorld;
// FIXME: use standard logging facilities in WebCore.
void logInfo(Frame*, const String& message, const String& url);
@@ -145,7 +104,7 @@ namespace WebCore {
int group;
v8::Extension* extension;
};
- typedef WTF::Vector<V8ExtensionInfo> V8ExtensionList;
+ typedef WTF::Vector<V8ExtensionInfo> V8Extensions;
class V8Proxy {
public:
@@ -158,7 +117,7 @@ namespace WebCore {
GeneralError
};
- explicit V8Proxy(Frame* frame) : m_frame(frame), m_inlineCode(false), m_timerCallback(false), m_recursion(0) { }
+ explicit V8Proxy(Frame*);
~V8Proxy();
@@ -196,9 +155,6 @@ namespace WebCore {
bool isEnabled();
- V8EventListenerList* eventListeners() { return &m_eventListeners; }
- V8EventListenerList* objectListeners() { return &m_objectListeners; }
-
#if ENABLE(SVG)
static void setSVGContext(void*, SVGElement*);
static SVGElement* svgContext(void*);
@@ -211,7 +167,7 @@ namespace WebCore {
// global scope, its own prototypes for intrinsic JavaScript objects (String,
// Array, and so-on), and its own wrappers for all DOM nodes and DOM
// constructors.
- void evaluateInNewWorld(const Vector<ScriptSourceCode>& sources, int extensionGroup);
+ void evaluateInIsolatedWorld(int worldId, const Vector<ScriptSourceCode>& sources, int extensionGroup);
// Evaluate JavaScript in a new context. The script gets its own global scope
// and its own prototypes for intrinsic JavaScript objects (String, Array,
@@ -239,7 +195,12 @@ namespace WebCore {
// To create JS Wrapper objects, we create a cache of a 'boiler plate'
// object, and then simply Clone that object each time we need a new one.
// This is faster than going through the full object creation process.
- v8::Local<v8::Object> createWrapperFromCache(V8ClassIndex::V8WrapperType);
+ v8::Local<v8::Object> createWrapperFromCache(V8ClassIndex::V8WrapperType type)
+ {
+ int classIndex = V8ClassIndex::ToInt(type);
+ v8::Local<v8::Object> clone(m_wrapperBoilerplates->CloneElementAt(classIndex));
+ return clone.IsEmpty() ? createWrapperFromCacheSlowCase(type) : clone;
+ }
// Returns the window object associated with a context.
static DOMWindow* retrieveWindow(v8::Handle<v8::Context>);
@@ -290,6 +251,7 @@ namespace WebCore {
// Returns V8 Context of a frame. If none exists, creates
// a new context. It is potentially slow and consumes memory.
static v8::Local<v8::Context> context(Frame*);
+ static PassRefPtr<SharedPersistent<v8::Context> > shared_context(Frame*);
static v8::Local<v8::Context> mainWorldContext(Frame*);
static v8::Local<v8::Context> currentContext();
@@ -334,10 +296,19 @@ namespace WebCore {
static int sourceLineNumber();
static String sourceName();
- // Returns a local handle of the context.
- v8::Local<v8::Context> context()
+ v8::Handle<v8::Context> context()
+ {
+ return m_context->get();
+ }
+
+ PassRefPtr<SharedPersistent<v8::Context> > shared_context()
+ {
+ return m_context;
+ }
+
+ PassRefPtr<V8ListenerGuard> listenerGuard()
{
- return v8::Local<v8::Context>::New(m_context);
+ return m_listenerGuard;
}
bool setContextDebugId(int id);
@@ -368,7 +339,6 @@ namespace WebCore {
static const char* kContextDebugDataType;
static const char* kContextDebugDataValue;
- void disconnectEventListeners();
void setSecurityToken();
void clearDocumentWrapper();
@@ -382,6 +352,14 @@ namespace WebCore {
// Dispose global handles of m_contexts and friends.
void disposeContextHandles();
+ // If m_recursionCount is 0, let LocalStorage know so we can release
+ // the storage mutex.
+ void releaseStorageMutex();
+
+ void disconnectEventListeners();
+
+ void resetIsolatedWorlds();
+
static bool canAccessPrivate(DOMWindow*);
static const char* rangeExceptionName(int exceptionCode);
@@ -407,11 +385,17 @@ namespace WebCore {
return v8::Local<v8::Context>::New(m_utilityContext);
}
+ v8::Local<v8::Object> createWrapperFromCacheSlowCase(V8ClassIndex::V8WrapperType);
+
static void registerExtensionWithV8(v8::Extension*);
+ static bool registeredExtensionWithV8(v8::Extension*);
Frame* m_frame;
- v8::Persistent<v8::Context> m_context;
+ RefPtr<SharedPersistent<v8::Context> > m_context;
+
+ RefPtr<V8ListenerGuard> m_listenerGuard;
+
// For each possible type of wrapper, we keep a boilerplate object.
// The boilerplate is used to create additional wrappers of the same
// type. We keep a single persistent handle to an array of the
@@ -426,14 +410,6 @@ namespace WebCore {
int m_handlerLineNumber;
- // A list of event listeners created for this frame,
- // the list gets cleared when removing all timeouts.
- V8EventListenerList m_eventListeners;
-
- // A list of event listeners create for XMLHttpRequest object for this frame,
- // the list gets cleared when removing all timeouts.
- V8EventListenerList m_objectListeners;
-
// True for <a href="javascript:foo()"> and false for <script>foo()</script>.
// Only valid during execution.
bool m_inlineCode;
@@ -447,8 +423,18 @@ namespace WebCore {
// excessive recursion in the binding layer.
int m_recursion;
- // List of extensions registered with the context.
- static V8ExtensionList m_extensions;
+ // All of the extensions registered with the context.
+ static V8Extensions m_extensions;
+
+ // The isolated worlds we are tracking for this frame. We hold them alive
+ // here so that they can be used again by future calls to
+ // evaluateInIsolatedWorld().
+ //
+ // Note: although the pointer is raw, the instance is kept alive by a strong
+ // reference to the v8 context it contains, which is not made weak until we
+ // call world->destroy().
+ typedef HashMap<int, V8IsolatedWorld*> IsolatedWorldMap;
+ IsolatedWorldMap m_isolatedWorlds;
};
template <int tag, typename T>
diff --git a/WebCore/bindings/v8/V8Utilities.cpp b/WebCore/bindings/v8/V8Utilities.cpp
index c1ac6d4..a66f435 100644
--- a/WebCore/bindings/v8/V8Utilities.cpp
+++ b/WebCore/bindings/v8/V8Utilities.cpp
@@ -33,8 +33,15 @@
#include <v8.h>
+#include "Document.h"
+#include "Frame.h"
+#include "ScriptExecutionContext.h"
+#include "ScriptState.h"
#include "V8CustomBinding.h"
+#include "V8Binding.h"
#include "V8Proxy.h"
+#include "WorkerContext.h"
+#include "WorkerContextExecutionProxy.h"
#include <wtf/Assertions.h>
#include "Frame.h"
@@ -43,7 +50,7 @@ namespace WebCore {
// Use an array to hold dependents. It works like a ref-counted scheme.
// A value can be added more than once to the DOM object.
-void createHiddenDependency(v8::Local<v8::Object> object, v8::Local<v8::Value> value, int cacheIndex)
+void createHiddenDependency(v8::Handle<v8::Object> object, v8::Local<v8::Value> value, int cacheIndex)
{
v8::Local<v8::Value> cache = object->GetInternalField(cacheIndex);
if (cache->IsNull() || cache->IsUndefined()) {
@@ -55,7 +62,7 @@ void createHiddenDependency(v8::Local<v8::Object> object, v8::Local<v8::Value> v
cacheArray->Set(v8::Integer::New(cacheArray->Length()), value);
}
-void removeHiddenDependency(v8::Local<v8::Object> object, v8::Local<v8::Value> value, int cacheIndex)
+void removeHiddenDependency(v8::Handle<v8::Object> object, v8::Local<v8::Value> value, int cacheIndex)
{
v8::Local<v8::Value> cache = object->GetInternalField(cacheIndex);
if (!cache->IsArray())
@@ -98,7 +105,46 @@ void navigateIfAllowed(Frame* frame, const KURL& url, bool lockHistory, bool loc
return;
if (!protocolIsJavaScript(url) || ScriptController::isSafeScript(frame))
- frame->loader()->scheduleLocationChange(url.string(), callingFrame->loader()->outgoingReferrer(), lockHistory, lockBackForwardList, processingUserGesture());
+ frame->redirectScheduler()->scheduleLocationChange(url.string(), callingFrame->loader()->outgoingReferrer(), lockHistory, lockBackForwardList, processingUserGesture());
+}
+
+ScriptExecutionContext* getScriptExecutionContext(ScriptState* scriptState)
+{
+#if ENABLE(WORKERS)
+ WorkerContextExecutionProxy* proxy = WorkerContextExecutionProxy::retrieve();
+ if (proxy)
+ return proxy->workerContext()->scriptExecutionContext();
+#endif
+
+ if (scriptState)
+ return scriptState->frame()->document()->scriptExecutionContext();
+ else {
+ Frame* frame = V8Proxy::retrieveFrameForCurrentContext();
+ if (frame)
+ return frame->document()->scriptExecutionContext();
+ }
+
+ return 0;
+}
+
+void reportException(ScriptState* scriptState, v8::TryCatch& exceptionCatcher)
+{
+ String errorMessage;
+ int lineNumber = 0;
+ String sourceURL;
+
+ // There can be a situation that an exception is thrown without setting a message.
+ v8::Local<v8::Message> message = exceptionCatcher.Message();
+ if (message.IsEmpty())
+ errorMessage = toWebCoreString(exceptionCatcher.Exception()->ToString());
+ else {
+ errorMessage = toWebCoreString(message->Get());
+ lineNumber = message->GetLineNumber();
+ sourceURL = toWebCoreString(message->GetScriptResourceName());
+ }
+
+ getScriptExecutionContext(scriptState)->reportException(errorMessage, lineNumber, sourceURL);
+ exceptionCatcher.Reset();
}
} // namespace WebCore
diff --git a/WebCore/bindings/v8/V8Utilities.h b/WebCore/bindings/v8/V8Utilities.h
index 3e59d34..1a713c9 100644
--- a/WebCore/bindings/v8/V8Utilities.h
+++ b/WebCore/bindings/v8/V8Utilities.h
@@ -44,17 +44,26 @@ namespace WebCore {
class Frame;
class KURL;
+ class ScriptExecutionContext;
+ class ScriptState;
class String;
// Use an array to hold dependents. It works like a ref-counted scheme. A value can be added more than once to the DOM object.
- void createHiddenDependency(v8::Local<v8::Object>, v8::Local<v8::Value>, int cacheIndex);
- void removeHiddenDependency(v8::Local<v8::Object>, v8::Local<v8::Value>, int cacheIndex);
+ void createHiddenDependency(v8::Handle<v8::Object>, v8::Local<v8::Value>, int cacheIndex);
+ void removeHiddenDependency(v8::Handle<v8::Object>, v8::Local<v8::Value>, int cacheIndex);
bool processingUserGesture();
bool shouldAllowNavigation(Frame*);
KURL completeURL(const String& relativeURL);
void navigateIfAllowed(Frame*, const KURL&, bool lockHistory, bool lockBackForwardList);
+ ScriptExecutionContext* getScriptExecutionContext(ScriptState*);
+ inline ScriptExecutionContext* getScriptExecutionContext() {
+ return getScriptExecutionContext(0);
+ }
+
+ void reportException(ScriptState*, v8::TryCatch&);
+
class AllowAllocation {
public:
inline AllowAllocation()
diff --git a/WebCore/bindings/v8/V8WorkerContextEventListener.cpp b/WebCore/bindings/v8/V8WorkerContextEventListener.cpp
index 862cd2d..24e493c 100644
--- a/WebCore/bindings/v8/V8WorkerContextEventListener.cpp
+++ b/WebCore/bindings/v8/V8WorkerContextEventListener.cpp
@@ -41,20 +41,13 @@
namespace WebCore {
-V8WorkerContextEventListener::V8WorkerContextEventListener(WorkerContextExecutionProxy* proxy, v8::Local<v8::Object> listener, bool isInline)
- : V8EventListener(0, listener, isInline)
+V8WorkerContextEventListener::V8WorkerContextEventListener(WorkerContextExecutionProxy* proxy, PassRefPtr<V8ListenerGuard> guard, v8::Local<v8::Object> listener, bool isInline)
+ : V8EventListener(0, guard, listener, isInline)
, m_proxy(proxy)
{
}
-V8WorkerContextEventListener::~V8WorkerContextEventListener()
-{
- if (m_proxy)
- m_proxy->removeEventListener(this);
- disposeListenerObject();
-}
-
-void V8WorkerContextEventListener::handleEvent(Event* event, bool isWindowEvent)
+void V8WorkerContextEventListener::handleEvent(ScriptExecutionContext*, Event* event)
{
// Is the EventListener disconnected?
if (disconnected())
@@ -77,7 +70,7 @@ void V8WorkerContextEventListener::handleEvent(Event* event, bool isWindowEvent)
// Get the V8 wrapper for the event object.
v8::Handle<v8::Value> jsEvent = WorkerContextExecutionProxy::convertEventToV8Object(event);
- invokeEventHandler(context, event, jsEvent, isWindowEvent);
+ invokeEventHandler(context, event, jsEvent);
}
bool V8WorkerContextEventListener::reportError(const String& message, const String& url, int lineNumber)
@@ -98,6 +91,7 @@ bool V8WorkerContextEventListener::reportError(const String& message, const Stri
// Enter the V8 context in which to perform the event handling.
v8::Context::Scope scope(context);
+ v8::Local<v8::Object> listener = getListenerObject();
v8::Local<v8::Value> returnValue;
{
// Catch exceptions thrown in calling the function so they do not propagate to javascript code that caused the event to fire.
@@ -105,8 +99,8 @@ bool V8WorkerContextEventListener::reportError(const String& message, const Stri
tryCatch.SetVerbose(true);
// Call the function.
- if (!m_listener.IsEmpty() && m_listener->IsFunction()) {
- v8::Local<v8::Function> callFunction = v8::Local<v8::Function>::New(v8::Persistent<v8::Function>::Cast(m_listener));
+ if (!listener.IsEmpty() && listener->IsFunction()) {
+ v8::Local<v8::Function> callFunction = v8::Local<v8::Function>::Cast(listener);
v8::Local<v8::Object> thisValue = v8::Context::GetCurrent()->Global();
v8::Handle<v8::Value> parameters[3] = { v8String(message), v8String(url), v8::Integer::New(lineNumber) };
@@ -126,10 +120,10 @@ bool V8WorkerContextEventListener::reportError(const String& message, const Stri
return errorHandled;
}
-v8::Local<v8::Value> V8WorkerContextEventListener::callListenerFunction(v8::Handle<v8::Value> jsEvent, Event* event, bool isWindowEvent)
+v8::Local<v8::Value> V8WorkerContextEventListener::callListenerFunction(v8::Handle<v8::Value> jsEvent, Event* event)
{
v8::Local<v8::Function> handlerFunction = getListenerFunction();
- v8::Local<v8::Object> receiver = getReceiverObject(event, isWindowEvent);
+ v8::Local<v8::Object> receiver = getReceiverObject(event);
if (handlerFunction.IsEmpty() || receiver.IsEmpty())
return v8::Local<v8::Value>();
@@ -141,13 +135,12 @@ v8::Local<v8::Value> V8WorkerContextEventListener::callListenerFunction(v8::Hand
return result;
}
-v8::Local<v8::Object> V8WorkerContextEventListener::getReceiverObject(Event* event, bool isWindowEvent)
+v8::Local<v8::Object> V8WorkerContextEventListener::getReceiverObject(Event* event)
{
- if (!m_listener.IsEmpty() && !m_listener->IsFunction())
- return v8::Local<v8::Object>::New(m_listener);
+ v8::Local<v8::Object> listener = getListenerObject();
- if (isWindowEvent)
- return v8::Context::GetCurrent()->Global();
+ if (!listener.IsEmpty() && !listener->IsFunction())
+ return listener;
EventTarget* target = event->currentTarget();
v8::Handle<v8::Value> value = WorkerContextExecutionProxy::convertEventTargetToV8Object(target);
diff --git a/WebCore/bindings/v8/V8WorkerContextEventListener.h b/WebCore/bindings/v8/V8WorkerContextEventListener.h
index c901c51..3752533 100644
--- a/WebCore/bindings/v8/V8WorkerContextEventListener.h
+++ b/WebCore/bindings/v8/V8WorkerContextEventListener.h
@@ -44,23 +44,21 @@ namespace WebCore {
class V8WorkerContextEventListener : public V8EventListener {
public:
- static PassRefPtr<V8WorkerContextEventListener> create(WorkerContextExecutionProxy* proxy, v8::Local<v8::Object> listener, bool isInline)
+ static PassRefPtr<V8WorkerContextEventListener> create(WorkerContextExecutionProxy* proxy, PassRefPtr<V8ListenerGuard> guard, v8::Local<v8::Object> listener, bool isInline)
{
- return adoptRef(new V8WorkerContextEventListener(proxy, listener, isInline));
+ return adoptRef(new V8WorkerContextEventListener(proxy, guard, listener, isInline));
}
- V8WorkerContextEventListener(WorkerContextExecutionProxy*, v8::Local<v8::Object> listener, bool isInline);
- virtual ~V8WorkerContextEventListener();
- virtual void handleEvent(Event*, bool isWindowEvent);
+ virtual void handleEvent(ScriptExecutionContext*, Event*);
virtual bool reportError(const String& message, const String& url, int lineNumber);
- virtual bool disconnected() const { return !m_proxy; }
WorkerContextExecutionProxy* proxy() const { return m_proxy; }
- void disconnect() { m_proxy = 0; }
private:
- virtual v8::Local<v8::Value> callListenerFunction(v8::Handle<v8::Value> jsEvent, Event*, bool isWindowEvent);
- v8::Local<v8::Object> getReceiverObject(Event*, bool isWindowEvent);
+ V8WorkerContextEventListener(WorkerContextExecutionProxy*, PassRefPtr<V8ListenerGuard>, v8::Local<v8::Object> listener, bool isInline);
+
+ virtual v8::Local<v8::Value> callListenerFunction(v8::Handle<v8::Value> jsEvent, Event*);
+ v8::Local<v8::Object> getReceiverObject(Event*);
WorkerContextExecutionProxy* m_proxy;
};
diff --git a/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp b/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp
index ba858cf..90c1f6f 100644
--- a/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp
+++ b/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp
@@ -38,6 +38,8 @@
#include "DOMCoreException.h"
#include "DedicatedWorkerContext.h"
#include "Event.h"
+#include "Notification.h"
+#include "NotificationCenter.h"
#include "EventException.h"
#include "MessagePort.h"
#include "RangeException.h"
@@ -46,7 +48,9 @@
#include "V8Index.h"
#include "V8Proxy.h"
#include "V8WorkerContextEventListener.h"
-#include "V8WorkerContextObjectEventListener.h"
+#if ENABLE(WEB_SOCKETS)
+#include "WebSocket.h"
+#endif
#include "Worker.h"
#include "WorkerContext.h"
#include "WorkerLocation.h"
@@ -66,6 +70,7 @@ static void reportFatalErrorInV8(const char* location, const char* message)
WorkerContextExecutionProxy::WorkerContextExecutionProxy(WorkerContext* workerContext)
: m_workerContext(workerContext)
, m_recursion(0)
+ , m_listenerGuard(V8ListenerGuard::create())
{
initV8IfNeeded();
}
@@ -77,13 +82,7 @@ WorkerContextExecutionProxy::~WorkerContextExecutionProxy()
void WorkerContextExecutionProxy::dispose()
{
- // Disconnect all event listeners.
- if (m_listeners.get()) {
- for (V8EventListenerList::iterator iterator(m_listeners->begin()); iterator != m_listeners->end(); ++iterator)
- static_cast<V8WorkerContextEventListener*>(*iterator)->disconnect();
-
- m_listeners->clear();
- }
+ m_listenerGuard->disconnectListeners();
// Detach all events from their JS wrappers.
for (size_t eventIndex = 0; eventIndex < m_events.size(); ++eventIndex) {
@@ -169,8 +168,6 @@ void WorkerContextExecutionProxy::initContextIfNeeded()
// Insert the object instance as the prototype of the shadow object.
v8::Handle<v8::Object> globalObject = m_context->Global();
globalObject->Set(implicitProtoString, jsWorkerContext);
-
- m_listeners.set(new V8EventListenerList());
}
v8::Handle<v8::Value> WorkerContextExecutionProxy::convertToV8Object(V8ClassIndex::V8WrapperType type, void* impl)
@@ -224,6 +221,14 @@ v8::Handle<v8::Value> WorkerContextExecutionProxy::convertToV8Object(V8ClassInde
case V8ClassIndex::WORKERNAVIGATOR:
static_cast<WorkerNavigator*>(impl)->ref();
break;
+#if ENABLE(NOTIFICATIONS)
+ case V8ClassIndex::NOTIFICATIONCENTER:
+ static_cast<NotificationCenter*>(impl)->ref();
+ break;
+ case V8ClassIndex::NOTIFICATION:
+ static_cast<Notification*>(impl)->ref();
+ break;
+#endif
case V8ClassIndex::DOMCOREEXCEPTION:
static_cast<DOMCoreException*>(impl)->ref();
break;
@@ -398,40 +403,9 @@ v8::Local<v8::Value> WorkerContextExecutionProxy::runScript(v8::Handle<v8::Scrip
return result;
}
-PassRefPtr<V8EventListener> WorkerContextExecutionProxy::findOrCreateEventListenerHelper(v8::Local<v8::Value> object, bool isInline, bool findOnly, bool createObjectEventListener)
-{
- if (!object->IsObject())
- return 0;
-
- V8EventListener* listener = m_listeners->find(object->ToObject(), isInline);
- if (findOnly)
- return listener;
-
- // Create a new one, and add to cache.
- RefPtr<V8EventListener> newListener;
- if (createObjectEventListener)
- newListener = V8WorkerContextObjectEventListener::create(this, v8::Local<v8::Object>::Cast(object), isInline);
- else
- newListener = V8WorkerContextEventListener::create(this, v8::Local<v8::Object>::Cast(object), isInline);
-
- m_listeners->add(newListener.get());
-
- return newListener.release();
-}
-
PassRefPtr<V8EventListener> WorkerContextExecutionProxy::findOrCreateEventListener(v8::Local<v8::Value> object, bool isInline, bool findOnly)
{
- return findOrCreateEventListenerHelper(object, isInline, findOnly, false);
-}
-
-PassRefPtr<V8EventListener> WorkerContextExecutionProxy::findOrCreateObjectEventListener(v8::Local<v8::Value> object, bool isInline, bool findOnly)
-{
- return findOrCreateEventListenerHelper(object, isInline, findOnly, true);
-}
-
-void WorkerContextExecutionProxy::removeEventListener(V8EventListener* listener)
-{
- m_listeners->remove(listener);
+ return findOnly ? V8EventListenerList::findWrapper(object, isInline) : V8EventListenerList::findOrCreateWrapper<V8WorkerContextEventListener>(this, m_listenerGuard, object, isInline);
}
void WorkerContextExecutionProxy::trackEvent(Event* event)
diff --git a/WebCore/bindings/v8/WorkerContextExecutionProxy.h b/WebCore/bindings/v8/WorkerContextExecutionProxy.h
index 75024df..a08395c 100644
--- a/WebCore/bindings/v8/WorkerContextExecutionProxy.h
+++ b/WebCore/bindings/v8/WorkerContextExecutionProxy.h
@@ -64,12 +64,8 @@ namespace WebCore {
WorkerContextExecutionProxy(WorkerContext*);
~WorkerContextExecutionProxy();
- void removeEventListener(V8EventListener*);
-
// Finds/creates event listener wrappers.
PassRefPtr<V8EventListener> findOrCreateEventListener(v8::Local<v8::Value> listener, bool isInline, bool findOnly);
- PassRefPtr<V8EventListener> findOrCreateObjectEventListener(v8::Local<v8::Value> object, bool isInline, bool findOnly);
- PassRefPtr<V8EventListener> findOrCreateEventListenerHelper(v8::Local<v8::Value> object, bool isInline, bool findOnly, bool createObjectEventListener);
// Track the event so that we can detach it from the JS wrapper when a worker
// terminates. This is needed because we need to be able to dispose these
@@ -114,8 +110,8 @@ namespace WebCore {
WorkerContext* m_workerContext;
v8::Persistent<v8::Context> m_context;
int m_recursion;
+ RefPtr<V8ListenerGuard> m_listenerGuard;
- OwnPtr<V8EventListenerList> m_listeners;
Vector<Event*> m_events;
};
diff --git a/WebCore/bindings/v8/custom/V8AbstractWorkerCustom.cpp b/WebCore/bindings/v8/custom/V8AbstractWorkerCustom.cpp
index ce759eb..0240895 100644
--- a/WebCore/bindings/v8/custom/V8AbstractWorkerCustom.cpp
+++ b/WebCore/bindings/v8/custom/V8AbstractWorkerCustom.cpp
@@ -38,75 +38,18 @@
#include "ScriptExecutionContext.h"
#include "V8Binding.h"
#include "V8CustomBinding.h"
-#include "V8ObjectEventListener.h"
#include "V8Proxy.h"
#include "V8Utilities.h"
#include "WorkerContextExecutionProxy.h"
namespace WebCore {
-PassRefPtr<EventListener> getEventListener(AbstractWorker* worker, v8::Local<v8::Value> value, bool isAttribute, bool findOnly)
-{
- if (worker->scriptExecutionContext()->isWorkerContext()) {
- WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve();
- ASSERT(workerContextProxy);
- return workerContextProxy->findOrCreateObjectEventListener(value, isAttribute, findOnly);
- }
-
- V8Proxy* proxy = V8Proxy::retrieve(worker->scriptExecutionContext());
- if (proxy) {
- V8EventListenerList* list = proxy->objectListeners();
- return findOnly ? list->findWrapper(value, isAttribute) : list->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, isAttribute);
- }
-
- return 0;
-}
-
-ACCESSOR_GETTER(AbstractWorkerOnerror)
-{
- INC_STATS(L"DOM.AbstractWorker.onerror._get");
- AbstractWorker* worker = V8DOMWrapper::convertToNativeObject<AbstractWorker>(V8ClassIndex::ABSTRACTWORKER, info.Holder());
- if (worker->onerror()) {
- V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(worker->onerror());
- v8::Local<v8::Object> v8Listener = listener->getListenerObject();
- return v8Listener;
- }
- return v8::Undefined();
-}
-
-ACCESSOR_SETTER(AbstractWorkerOnerror)
-{
- INC_STATS(L"DOM.AbstractWorker.onerror._set");
- AbstractWorker* worker = V8DOMWrapper::convertToNativeObject<AbstractWorker>(V8ClassIndex::ABSTRACTWORKER, info.Holder());
- V8ObjectEventListener* oldListener = static_cast<V8ObjectEventListener*>(worker->onerror());
- if (value->IsNull()) {
- if (oldListener) {
- v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject();
- removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kAbstractWorkerRequestCacheIndex);
- }
-
- // Clear the listener.
- worker->setOnerror(0);
- } else {
- RefPtr<EventListener> listener = getEventListener(worker, value, true, false);
- if (listener) {
- if (oldListener) {
- v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject();
- removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kAbstractWorkerRequestCacheIndex);
- }
-
- worker->setOnerror(listener);
- createHiddenDependency(info.Holder(), value, V8Custom::kAbstractWorkerRequestCacheIndex);
- }
- }
-}
-
CALLBACK_FUNC_DECL(AbstractWorkerAddEventListener)
{
INC_STATS(L"DOM.AbstractWorker.addEventListener()");
AbstractWorker* worker = V8DOMWrapper::convertToNativeObject<AbstractWorker>(V8ClassIndex::ABSTRACTWORKER, args.Holder());
- RefPtr<EventListener> listener = getEventListener(worker, args[1], false, false);
+ RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(worker, args[1], false, ListenerFindOrCreate);
if (listener) {
String type = toWebCoreString(args[0]);
bool useCapture = args[2]->BooleanValue();
@@ -122,7 +65,7 @@ CALLBACK_FUNC_DECL(AbstractWorkerRemoveEventListener)
INC_STATS(L"DOM.AbstractWorker.removeEventListener()");
AbstractWorker* worker = V8DOMWrapper::convertToNativeObject<AbstractWorker>(V8ClassIndex::ABSTRACTWORKER, args.Holder());
- RefPtr<EventListener> listener = getEventListener(worker, args[1], false, true);
+ RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(worker, args[1], false, ListenerFindOnly);
if (listener) {
String type = toWebCoreString(args[0]);
bool useCapture = args[2]->BooleanValue();
diff --git a/WebCore/bindings/v8/custom/V8CanvasArrayBufferCustom.cpp b/WebCore/bindings/v8/custom/V8CanvasArrayBufferCustom.cpp
new file mode 100644
index 0000000..4a85e82
--- /dev/null
+++ b/WebCore/bindings/v8/custom/V8CanvasArrayBufferCustom.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(3D_CANVAS)
+
+#include "CanvasArrayBuffer.h"
+
+#include "V8Binding.h"
+#include "V8CanvasArrayBuffer.h"
+#include "V8CustomBinding.h"
+#include "V8Proxy.h"
+
+namespace WebCore {
+
+CALLBACK_FUNC_DECL(CanvasArrayBufferConstructor)
+{
+ INC_STATS("DOM.CanvasArrayBuffer.Contructor");
+
+ if (!args.IsConstructCall())
+ return throwError("DOM object constructor cannot be called as a function.");
+
+ int argLen = args.Length();
+ // Supported constructors:
+ // CanvasArrayBuffer(n) where n is an integer:
+ // -- create an empty buffer of n bytes
+
+ if (argLen != 1)
+ return throwError("Wrong number of arguments specified to constructor (requires 1)");
+
+ int len = 0;
+ if (!args[0]->IsInt32())
+ return throwError("Argument to CanvasArrayBuffer constructor was not an integer");
+ len = toInt32(args[0]);
+ RefPtr<CanvasArrayBuffer> buffer = CanvasArrayBuffer::create(len);
+ // Transform the holder into a wrapper object for the array.
+ V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::CANVASARRAYBUFFER), buffer.get());
+ return toV8(buffer.release(), args.Holder());
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/bindings/v8/custom/V8CanvasArrayCustom.h b/WebCore/bindings/v8/custom/V8CanvasArrayCustom.h
new file mode 100644
index 0000000..311b838
--- /dev/null
+++ b/WebCore/bindings/v8/custom/V8CanvasArrayCustom.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(3D_CANVAS)
+
+#include "CanvasArrayBuffer.h"
+
+#include "V8Binding.h"
+#include "V8CanvasArrayBuffer.h"
+#include "V8CustomBinding.h"
+#include "V8Proxy.h"
+
+namespace WebCore {
+
+ // Template function used by the CanvasArray*Constructor callbacks.
+ template<class ArrayClass>
+ v8::Handle<v8::Value> constructCanvasArray(const v8::Arguments& args,
+ int classIndex)
+ {
+ if (!args.IsConstructCall())
+ return throwError("DOM object constructor cannot be called as a function.");
+
+ int argLen = args.Length();
+ // Supported constructors:
+ // Canvas<T>Array(n) where n is an integer:
+ // -- create an empty array of n elements
+ // Canvas<T>Array(arr) where arr is an array:
+ // -- create a Canvas<T>Array containing the contents of "arr"
+ // Canvas<T>Array(buf, offset, length)
+ // -- create a Canvas<T>Array pointing to the CanvasArrayBuffer
+ // "buf", starting at the specified offset, for the given
+ // length
+
+ if (argLen == 0)
+ return throwError("No arguments specified to constructor");
+
+ // See whether the first argument is a CanvasArrayBuffer.
+ if (V8CanvasArrayBuffer::HasInstance(args[0])) {
+ if (argLen > 3)
+ return throwError("Wrong number of arguments to new Canvas<T>Array(CanvasArrayBuffer, int, int)");
+
+ CanvasArrayBuffer* buf =
+ V8DOMWrapper::convertToNativeObject<CanvasArrayBuffer>(V8ClassIndex::CANVASARRAYBUFFER,
+ args[0]->ToObject());
+ if (buf == NULL)
+ return throwError("Could not convert argument 0 to a CanvasArrayBuffer");
+ bool ok;
+ int offset = 0;
+ if (argLen > 1) {
+ offset = toInt32(args[1], ok);
+ if (!ok)
+ return throwError("Could not convert argument 1 to an integer");
+ }
+ int length = buf->byteLength() - offset;
+ if (argLen > 2) {
+ length = toInt32(args[2], ok);
+ if (!ok)
+ return throwError("Could not convert argument 2 to an integer");
+ }
+ if (length < 0)
+ return throwError("Length / offset out of range");
+
+ RefPtr<ArrayClass> array = ArrayClass::create(buf, offset, length);
+ if (array == NULL)
+ return throwError("Invalid arguments to new Canvas<T>Array(CanvasArrayBuffer, int, int)");
+ // Transform the holder into a wrapper object for the array.
+ V8DOMWrapper::setDOMWrapper(args.Holder(), classIndex, array.get());
+ return toV8(array.release(), args.Holder());
+ }
+
+ int len = 0;
+ v8::Handle<v8::Array> srcArray;
+ if (argLen != 1)
+ return throwError("Wrong number of arguments to new Canvas<T>Array(int / array)");
+
+ if (args[0]->IsInt32()) {
+ len = toInt32(args[0]);
+ } else if (args[0]->IsArray()) {
+ srcArray = v8::Local<v8::Array>::Cast(args[0]);
+ if (srcArray.IsEmpty())
+ return throwError("Could not convert argument 0 to an array");
+ len = srcArray->Length();
+ } else
+ return throwError("Could not convert argument 0 to either an int32 or an array");
+
+ RefPtr<ArrayClass> array = ArrayClass::create(len);
+ if (!srcArray.IsEmpty()) {
+ // Need to copy the incoming array into the newly created CanvasArray.
+ for (int i = 0; i < len; i++) {
+ v8::Local<v8::Value> val = srcArray->Get(v8::Integer::New(i));
+ if (!val->IsNumber()) {
+ char buf[256];
+ sprintf(buf, "Could not convert array element %d to a number", i);
+ return throwError(buf);
+ }
+ array->set(i, val->NumberValue());
+ }
+ }
+
+ // Transform the holder into a wrapper object for the array.
+ V8DOMWrapper::setDOMWrapper(args.Holder(), classIndex, array.get());
+ return toV8(array.release(), args.Holder());
+ }
+
+}
+
+#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/bindings/v8/custom/V8CanvasByteArrayCustom.cpp b/WebCore/bindings/v8/custom/V8CanvasByteArrayCustom.cpp
new file mode 100644
index 0000000..503e5e8
--- /dev/null
+++ b/WebCore/bindings/v8/custom/V8CanvasByteArrayCustom.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(3D_CANVAS)
+
+#include "CanvasArrayBuffer.h"
+#include "CanvasByteArray.h"
+
+#include "V8Binding.h"
+#include "V8CanvasArrayBuffer.h"
+#include "V8CanvasArrayCustom.h"
+#include "V8CustomBinding.h"
+#include "V8Proxy.h"
+
+namespace WebCore {
+
+CALLBACK_FUNC_DECL(CanvasByteArrayConstructor)
+{
+ INC_STATS("DOM.CanvasByteArray.Contructor");
+
+ return constructCanvasArray<CanvasByteArray>(args, V8ClassIndex::ToInt(V8ClassIndex::CANVASBYTEARRAY));
+}
+
+// Get the specified value from the byte buffer and return it wrapped as a JavaScript Number object to V8. Accesses outside the valid byte buffer range return "undefined".
+INDEXED_PROPERTY_GETTER(CanvasByteArray)
+{
+ INC_STATS("DOM.CanvasByteArray.IndexedPropertyGetter");
+ CanvasByteArray* byteBuffer = V8DOMWrapper::convertToNativeObject<CanvasByteArray>(V8ClassIndex::CANVASBYTEARRAY, info.Holder());
+
+ if ((index < 0) || (index >= byteBuffer->length()))
+ return v8::Undefined();
+ signed char result;
+ if (!byteBuffer->get(index, result))
+ return v8::Undefined();
+ return v8::Number::New(result);
+}
+
+// Set the specified value in the byte buffer. Accesses outside the valid byte buffer range are silently ignored.
+INDEXED_PROPERTY_SETTER(CanvasByteArray)
+{
+ INC_STATS("DOM.CanvasByteArray.IndexedPropertySetter");
+ CanvasByteArray* array = V8DOMWrapper::convertToNativeObject<CanvasByteArray>(V8ClassIndex::CANVASBYTEARRAY, info.Holder());
+
+ if ((index >= 0) && (index < array->length())) {
+ if (!value->IsNumber())
+ return throwError("Could not convert value argument to a number");
+ array->set(index, value->NumberValue());
+ }
+ return value;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/bindings/v8/custom/V8CanvasFloatArrayCustom.cpp b/WebCore/bindings/v8/custom/V8CanvasFloatArrayCustom.cpp
new file mode 100644
index 0000000..b3c1d62
--- /dev/null
+++ b/WebCore/bindings/v8/custom/V8CanvasFloatArrayCustom.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(3D_CANVAS)
+
+#include "CanvasArrayBuffer.h"
+#include "CanvasFloatArray.h"
+
+#include "V8Binding.h"
+#include "V8CanvasArrayBuffer.h"
+#include "V8CanvasArrayCustom.h"
+#include "V8CustomBinding.h"
+#include "V8Proxy.h"
+
+namespace WebCore {
+
+CALLBACK_FUNC_DECL(CanvasFloatArrayConstructor)
+{
+ INC_STATS("DOM.CanvasFloatArray.Contructor");
+
+ return constructCanvasArray<CanvasFloatArray>(args, V8ClassIndex::ToInt(V8ClassIndex::CANVASFLOATARRAY));
+}
+
+// Get the specified value from the array and return it wrapped as a JavaScript Number object to V8. Accesses outside the valid array range return "undefined".
+INDEXED_PROPERTY_GETTER(CanvasFloatArray)
+{
+ INC_STATS("DOM.CanvasFloatArray.IndexedPropertyGetter");
+ CanvasFloatArray* array = V8DOMWrapper::convertToNativeObject<CanvasFloatArray>(V8ClassIndex::CANVASFLOATARRAY, info.Holder());
+
+ if ((index < 0) || (index >= array->length()))
+ return v8::Undefined();
+ float result;
+ if (!array->get(index, result))
+ return v8::Undefined();
+ return v8::Number::New(result);
+}
+
+// Set the specified value in the array. Accesses outside the valid array range are silently ignored.
+INDEXED_PROPERTY_SETTER(CanvasFloatArray)
+{
+ INC_STATS("DOM.CanvasFloatArray.IndexedPropertySetter");
+ CanvasFloatArray* array = V8DOMWrapper::convertToNativeObject<CanvasFloatArray>(V8ClassIndex::CANVASFLOATARRAY, info.Holder());
+
+ if ((index >= 0) && (index < array->length()))
+ array->set(index, value->NumberValue());
+ return value;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/bindings/v8/custom/V8CanvasIntArrayCustom.cpp b/WebCore/bindings/v8/custom/V8CanvasIntArrayCustom.cpp
new file mode 100644
index 0000000..6f35db8
--- /dev/null
+++ b/WebCore/bindings/v8/custom/V8CanvasIntArrayCustom.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(3D_CANVAS)
+
+#include "CanvasArrayBuffer.h"
+#include "CanvasIntArray.h"
+
+#include "V8Binding.h"
+#include "V8CanvasArrayBuffer.h"
+#include "V8CanvasArrayCustom.h"
+#include "V8CustomBinding.h"
+#include "V8Proxy.h"
+
+namespace WebCore {
+
+CALLBACK_FUNC_DECL(CanvasIntArrayConstructor)
+{
+ INC_STATS("DOM.CanvasIntArray.Contructor");
+
+ return constructCanvasArray<CanvasIntArray>(args, V8ClassIndex::ToInt(V8ClassIndex::CANVASINTARRAY));
+}
+
+// Get the specified value from the integer array and return it wrapped as a JavaScript Number object to V8. Accesses outside the valid pixel buffer range return "undefined".
+INDEXED_PROPERTY_GETTER(CanvasIntArray)
+{
+ INC_STATS("DOM.CanvasIntArray.IndexedPropertyGetter");
+ CanvasIntArray* array = V8DOMWrapper::convertToNativeObject<CanvasIntArray>(V8ClassIndex::CANVASINTARRAY, info.Holder());
+
+ if ((index < 0) || (index >= array->length()))
+ return v8::Undefined();
+ int result;
+ if (!array->get(index, result))
+ return v8::Undefined();
+ return v8::Number::New(result);
+}
+
+// Set the specified value in the integer array. Accesses outside the valid integer array range are silently ignored.
+INDEXED_PROPERTY_SETTER(CanvasIntArray)
+{
+ INC_STATS("DOM.CanvasIntArray.IndexedPropertySetter");
+ CanvasIntArray* array = V8DOMWrapper::convertToNativeObject<CanvasIntArray>(V8ClassIndex::CANVASINTARRAY, info.Holder());
+
+ if ((index >= 0) && (index < array->length())) {
+ if (!value->IsNumber())
+ return throwError("Could not convert value argument to a number");
+ array->set(index, value->NumberValue());
+ }
+ return value;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/bindings/v8/custom/V8CanvasRenderingContext3DCustom.cpp b/WebCore/bindings/v8/custom/V8CanvasRenderingContext3DCustom.cpp
new file mode 100644
index 0000000..c109bb8
--- /dev/null
+++ b/WebCore/bindings/v8/custom/V8CanvasRenderingContext3DCustom.cpp
@@ -0,0 +1,597 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(3D_CANVAS)
+
+#include "CanvasRenderingContext3D.h"
+
+#include "ExceptionCode.h"
+
+#include "NotImplemented.h"
+
+#include <wtf/FastMalloc.h>
+
+#include "V8Binding.h"
+#include "V8CanvasArray.h"
+#include "V8CanvasByteArray.h"
+#include "V8CanvasFloatArray.h"
+#include "V8CanvasIntArray.h"
+#include "V8CanvasShortArray.h"
+#include "V8CanvasUnsignedByteArray.h"
+#include "V8CanvasUnsignedIntArray.h"
+#include "V8CanvasUnsignedShortArray.h"
+#include "V8HTMLImageElement.h"
+#include "V8Proxy.h"
+
+namespace WebCore {
+
+// Allocates new storage via tryFastMalloc.
+// Returns NULL if array failed to convert for any reason.
+static float* jsArrayToFloatArray(v8::Handle<v8::Array> array, uint32_t len)
+{
+ // Convert the data element-by-element.
+ float* data;
+ if (!tryFastMalloc(len * sizeof(float)).getValue(data))
+ return 0;
+ for (uint32_t i = 0; i < len; i++) {
+ v8::Local<v8::Value> val = array->Get(v8::Integer::New(i));
+ if (!val->IsNumber()) {
+ fastFree(data);
+ return 0;
+ }
+ data[i] = toFloat(val);
+ }
+ return data;
+}
+
+// Allocates new storage via tryFastMalloc.
+// Returns NULL if array failed to convert for any reason.
+static int* jsArrayToIntArray(v8::Handle<v8::Array> array, uint32_t len)
+{
+ // Convert the data element-by-element.
+ int* data;
+ if (!tryFastMalloc(len * sizeof(int)).getValue(data))
+ return 0;
+ for (uint32_t i = 0; i < len; i++) {
+ v8::Local<v8::Value> val = array->Get(v8::Integer::New(i));
+ bool ok;
+ int ival = toInt32(val, ok);
+ if (!ok) {
+ fastFree(data);
+ return 0;
+ }
+ data[i] = ival;
+ }
+ return data;
+}
+
+CALLBACK_FUNC_DECL(CanvasRenderingContext3DBufferData)
+{
+ INC_STATS("DOM.CanvasRenderingContext3D.bufferData()");
+
+ // Forms:
+ // * bufferData(GLenum target, CanvasArray data, GLenum usage);
+ // - Sets the buffer's data from the given CanvasArray
+ // * bufferData(GLenum target, GLsizeiptr size, GLenum usage);
+ // - Sets the size of the buffer to the given size in bytes
+ if (args.Length() != 3) {
+ V8Proxy::setDOMException(SYNTAX_ERR);
+ return notHandledByInterceptor();
+ }
+
+ CanvasRenderingContext3D* context =
+ V8DOMWrapper::convertDOMWrapperToNative<CanvasRenderingContext3D>(args.Holder());
+ bool ok;
+ int target = toInt32(args[0], ok);
+ if (!ok) {
+ V8Proxy::setDOMException(SYNTAX_ERR);
+ return notHandledByInterceptor();
+ }
+ int usage = toInt32(args[2], ok);
+ if (!ok) {
+ V8Proxy::setDOMException(SYNTAX_ERR);
+ return notHandledByInterceptor();
+ }
+ if (args[1]->IsInt32()) {
+ int size = toInt32(args[1]);
+ context->bufferData(target, size, usage);
+ } else if (V8CanvasArray::HasInstance(args[1])) {
+ CanvasArray* array = V8DOMWrapper::convertToNativeObject<CanvasArray>(V8ClassIndex::CANVASARRAY, args[1]->ToObject());
+ context->bufferData(target, array, usage);
+ } else {
+ V8Proxy::setDOMException(SYNTAX_ERR);
+ return notHandledByInterceptor();
+ }
+ return v8::Undefined();
+}
+
+CALLBACK_FUNC_DECL(CanvasRenderingContext3DBufferSubData)
+{
+ INC_STATS("DOM.CanvasRenderingContext3D.bufferSubData()");
+
+ // Forms:
+ // * bufferSubData(GLenum target, GLintptr offset, CanvasArray data);
+ if (args.Length() != 3) {
+ V8Proxy::setDOMException(SYNTAX_ERR);
+ return notHandledByInterceptor();
+ }
+
+ CanvasRenderingContext3D* context =
+ V8DOMWrapper::convertDOMWrapperToNative<CanvasRenderingContext3D>(args.Holder());
+ bool ok;
+ int target = toInt32(args[0], ok);
+ if (!ok) {
+ V8Proxy::setDOMException(SYNTAX_ERR);
+ return notHandledByInterceptor();
+ }
+ int offset = toInt32(args[1], ok);
+ if (!ok) {
+ V8Proxy::setDOMException(SYNTAX_ERR);
+ return notHandledByInterceptor();
+ }
+ if (!V8CanvasArray::HasInstance(args[2])) {
+ V8Proxy::setDOMException(SYNTAX_ERR);
+ return notHandledByInterceptor();
+ }
+ CanvasArray* array = V8DOMWrapper::convertToNativeObject<CanvasArray>(V8ClassIndex::CANVASARRAY, args[2]->ToObject());
+ context->bufferSubData(target, offset, array);
+ return v8::Undefined();
+}
+
+CALLBACK_FUNC_DECL(CanvasRenderingContext3DTexImage2D)
+{
+ INC_STATS("DOM.CanvasRenderingContext3D.texImage2D()");
+
+ // Currently supported forms:
+ // * void texImage2D(in GLenum target, in GLint level,
+ // in GLint internalformat,
+ // in GLsizei width, in GLsizei height, in GLint border,
+ // in GLenum format, in GLenum type, in CanvasArray pixels);
+ // * void texImage2D(in GLenum target, in GLint level, in HTMLImageElement image,
+ // [Optional] in GLboolean flipY, [Optional] in GLboolean premultiplyAlpha);
+ if (args.Length() != 3 &&
+ args.Length() != 4 &&
+ args.Length() != 5 &&
+ args.Length() != 9) {
+ V8Proxy::setDOMException(SYNTAX_ERR);
+ return notHandledByInterceptor();
+ }
+
+ CanvasRenderingContext3D* context =
+ V8DOMWrapper::convertDOMWrapperToNative<CanvasRenderingContext3D>(args.Holder());
+ bool ok;
+ int target = toInt32(args[0], ok);
+ if (!ok) {
+ V8Proxy::setDOMException(SYNTAX_ERR);
+ return notHandledByInterceptor();
+ }
+ int level = toInt32(args[1], ok);
+ if (!ok) {
+ V8Proxy::setDOMException(SYNTAX_ERR);
+ return notHandledByInterceptor();
+ }
+
+ ExceptionCode ec = 0;
+ if (args.Length() == 3 ||
+ args.Length() == 4 ||
+ args.Length() == 5) {
+ v8::Handle<v8::Value> arg = args[2];
+ if (V8HTMLImageElement::HasInstance(arg)) {
+ HTMLImageElement* image_element = V8DOMWrapper::convertDOMWrapperToNode<HTMLImageElement>(v8::Handle<v8::Object>::Cast(arg));
+ bool flipY = false;
+ bool premultiplyAlpha = false;
+ if (args.Length() >= 4)
+ flipY = args[3]->BooleanValue();
+ if (args.Length() >= 5)
+ premultiplyAlpha = args[4]->BooleanValue();
+ context->texImage2D(target, level, image_element, flipY, premultiplyAlpha, ec);
+ } else {
+ // FIXME: consider different / better exception type.
+ V8Proxy::setDOMException(SYNTAX_ERR);
+ return notHandledByInterceptor();
+ }
+ // Fall through
+ } else if (args.Length() == 9) {
+ int internalformat = toInt32(args[2], ok);
+ if (!ok) {
+ V8Proxy::setDOMException(SYNTAX_ERR);
+ return notHandledByInterceptor();
+ }
+ int width = toInt32(args[3], ok);
+ if (!ok) {
+ V8Proxy::setDOMException(SYNTAX_ERR);
+ return notHandledByInterceptor();
+ }
+ int height = toInt32(args[4], ok);
+ if (!ok) {
+ V8Proxy::setDOMException(SYNTAX_ERR);
+ return notHandledByInterceptor();
+ }
+ int border = toInt32(args[5], ok);
+ if (!ok) {
+ V8Proxy::setDOMException(SYNTAX_ERR);
+ return notHandledByInterceptor();
+ }
+ int format = toInt32(args[6], ok);
+ if (!ok) {
+ V8Proxy::setDOMException(SYNTAX_ERR);
+ return notHandledByInterceptor();
+ }
+ int type = toInt32(args[7], ok);
+ if (!ok) {
+ V8Proxy::setDOMException(SYNTAX_ERR);
+ return notHandledByInterceptor();
+ }
+ v8::Handle<v8::Value> arg = args[8];
+ if (V8CanvasArray::HasInstance(arg)) {
+ CanvasArray* array = V8DOMWrapper::convertToNativeObject<CanvasArray>(V8ClassIndex::CANVASARRAY, arg->ToObject());
+ // FIXME: must do validation similar to JOGL's to ensure that
+ // the incoming array is of the appropriate length and type
+ context->texImage2D(target,
+ level,
+ internalformat,
+ width,
+ height,
+ border,
+ format,
+ type,
+ array,
+ ec);
+ // Fall through
+ } else {
+ V8Proxy::setDOMException(SYNTAX_ERR);
+ return notHandledByInterceptor();
+ }
+ } else {
+ ASSERT_NOT_REACHED();
+ V8Proxy::setDOMException(SYNTAX_ERR);
+ return notHandledByInterceptor();
+ }
+ if (ec) {
+ V8Proxy::setDOMException(ec);
+ return v8::Handle<v8::Value>();
+ }
+ return v8::Undefined();
+}
+
+CALLBACK_FUNC_DECL(CanvasRenderingContext3DTexSubImage2D)
+{
+ INC_STATS("DOM.CanvasRenderingContext3D.texSubImage2D()");
+
+ // FIXME: implement
+ notImplemented();
+
+ return v8::Undefined();
+}
+
+enum FunctionToCall {
+ kUniform1v, kUniform2v, kUniform3v, kUniform4v,
+ kVertexAttrib1v, kVertexAttrib2v, kVertexAttrib3v, kVertexAttrib4v
+};
+
+static v8::Handle<v8::Value> vertexAttribAndUniformHelperf(const v8::Arguments& args,
+ FunctionToCall functionToCall) {
+ // Forms:
+ // * glUniform1fv(GLint location, Array data);
+ // * glUniform1fv(GLint location, CanvasFloatArray data);
+ // * glUniform2fv(GLint location, Array data);
+ // * glUniform2fv(GLint location, CanvasFloatArray data);
+ // * glUniform3fv(GLint location, Array data);
+ // * glUniform3fv(GLint location, CanvasFloatArray data);
+ // * glUniform4fv(GLint location, Array data);
+ // * glUniform4fv(GLint location, CanvasFloatArray data);
+ // * glVertexAttrib1fv(GLint location, Array data);
+ // * glVertexAttrib1fv(GLint location, CanvasFloatArray data);
+ // * glVertexAttrib2fv(GLint location, Array data);
+ // * glVertexAttrib2fv(GLint location, CanvasFloatArray data);
+ // * glVertexAttrib3fv(GLint location, Array data);
+ // * glVertexAttrib3fv(GLint location, CanvasFloatArray data);
+ // * glVertexAttrib4fv(GLint location, Array data);
+ // * glVertexAttrib4fv(GLint location, CanvasFloatArray data);
+
+ if (args.Length() != 3) {
+ V8Proxy::setDOMException(SYNTAX_ERR);
+ return notHandledByInterceptor();
+ }
+
+ CanvasRenderingContext3D* context =
+ V8DOMWrapper::convertDOMWrapperToNative<CanvasRenderingContext3D>(args.Holder());
+ bool ok;
+ int location = toInt32(args[0], ok);
+ if (!ok) {
+ V8Proxy::setDOMException(SYNTAX_ERR);
+ return notHandledByInterceptor();
+ }
+ if (V8CanvasFloatArray::HasInstance(args[1])) {
+ CanvasFloatArray* array =
+ V8DOMWrapper::convertToNativeObject<CanvasFloatArray>(V8ClassIndex::CANVASFLOATARRAY, args[1]->ToObject());
+ ASSERT(array != NULL);
+ switch (functionToCall) {
+ case kUniform1v: context->uniform1fv(location, array); break;
+ case kUniform2v: context->uniform2fv(location, array); break;
+ case kUniform3v: context->uniform3fv(location, array); break;
+ case kUniform4v: context->uniform4fv(location, array); break;
+ case kVertexAttrib1v: context->vertexAttrib1fv(location, array); break;
+ case kVertexAttrib2v: context->vertexAttrib2fv(location, array); break;
+ case kVertexAttrib3v: context->vertexAttrib3fv(location, array); break;
+ case kVertexAttrib4v: context->vertexAttrib4fv(location, array); break;
+ default: ASSERT_NOT_REACHED(); break;
+ }
+ return v8::Undefined();
+ }
+
+ v8::Handle<v8::Array> array =
+ v8::Local<v8::Array>::Cast(args[1]);
+ if (array.IsEmpty()) {
+ V8Proxy::setDOMException(SYNTAX_ERR);
+ return notHandledByInterceptor();
+ }
+ uint32_t len = array->Length();
+ float* data = jsArrayToFloatArray(array, len);
+ if (!data) {
+ // FIXME: consider different / better exception type.
+ V8Proxy::setDOMException(SYNTAX_ERR);
+ return notHandledByInterceptor();
+ }
+ switch (functionToCall) {
+ case kUniform1v: context->uniform1fv(location, data, len); break;
+ case kUniform2v: context->uniform2fv(location, data, len); break;
+ case kUniform3v: context->uniform3fv(location, data, len); break;
+ case kUniform4v: context->uniform4fv(location, data, len); break;
+ case kVertexAttrib1v: context->vertexAttrib1fv(location, data, len); break;
+ case kVertexAttrib2v: context->vertexAttrib2fv(location, data, len); break;
+ case kVertexAttrib3v: context->vertexAttrib3fv(location, data, len); break;
+ case kVertexAttrib4v: context->vertexAttrib4fv(location, data, len); break;
+ default: ASSERT_NOT_REACHED(); break;
+ }
+ fastFree(data);
+ return v8::Undefined();
+}
+
+static v8::Handle<v8::Value> uniformHelperi(const v8::Arguments& args,
+ FunctionToCall functionToCall) {
+ // Forms:
+ // * glUniform1iv(GLint location, Array data);
+ // * glUniform1iv(GLint location, CanvasIntArray data);
+ // * glUniform2iv(GLint location, Array data);
+ // * glUniform2iv(GLint location, CanvasIntArray data);
+ // * glUniform3iv(GLint location, Array data);
+ // * glUniform3iv(GLint location, CanvasIntArray data);
+ // * glUniform4iv(GLint location, Array data);
+ // * glUniform4iv(GLint location, CanvasIntArray data);
+
+ if (args.Length() != 3) {
+ V8Proxy::setDOMException(SYNTAX_ERR);
+ return notHandledByInterceptor();
+ }
+
+ CanvasRenderingContext3D* context =
+ V8DOMWrapper::convertDOMWrapperToNative<CanvasRenderingContext3D>(args.Holder());
+ bool ok;
+ int location = toInt32(args[0], ok);
+ if (!ok) {
+ V8Proxy::setDOMException(SYNTAX_ERR);
+ return notHandledByInterceptor();
+ }
+ if (V8CanvasIntArray::HasInstance(args[1])) {
+ CanvasIntArray* array =
+ V8DOMWrapper::convertToNativeObject<CanvasIntArray>(V8ClassIndex::CANVASINTARRAY, args[1]->ToObject());
+ ASSERT(array != NULL);
+ switch (functionToCall) {
+ case kUniform1v: context->uniform1iv(location, array); break;
+ case kUniform2v: context->uniform2iv(location, array); break;
+ case kUniform3v: context->uniform3iv(location, array); break;
+ case kUniform4v: context->uniform4iv(location, array); break;
+ default: ASSERT_NOT_REACHED(); break;
+ }
+ return v8::Undefined();
+ }
+
+ v8::Handle<v8::Array> array =
+ v8::Local<v8::Array>::Cast(args[1]);
+ if (array.IsEmpty()) {
+ V8Proxy::setDOMException(SYNTAX_ERR);
+ return notHandledByInterceptor();
+ }
+ uint32_t len = array->Length();
+ int* data = jsArrayToIntArray(array, len);
+ if (!data) {
+ // FIXME: consider different / better exception type.
+ V8Proxy::setDOMException(SYNTAX_ERR);
+ return notHandledByInterceptor();
+ }
+ switch (functionToCall) {
+ case kUniform1v: context->uniform1iv(location, data, len); break;
+ case kUniform2v: context->uniform2iv(location, data, len); break;
+ case kUniform3v: context->uniform3iv(location, data, len); break;
+ case kUniform4v: context->uniform4iv(location, data, len); break;
+ default: ASSERT_NOT_REACHED(); break;
+ }
+ fastFree(data);
+ return v8::Undefined();
+}
+
+CALLBACK_FUNC_DECL(CanvasRenderingContext3DUniform1fv)
+{
+ INC_STATS("DOM.CanvasRenderingContext3D.uniform1fv()");
+ return vertexAttribAndUniformHelperf(args, kUniform1v);
+}
+
+CALLBACK_FUNC_DECL(CanvasRenderingContext3DUniform1iv)
+{
+ INC_STATS("DOM.CanvasRenderingContext3D.uniform1iv()");
+ return uniformHelperi(args, kUniform1v);
+}
+
+CALLBACK_FUNC_DECL(CanvasRenderingContext3DUniform2fv)
+{
+ INC_STATS("DOM.CanvasRenderingContext3D.uniform2fv()");
+ return vertexAttribAndUniformHelperf(args, kUniform2v);
+}
+
+CALLBACK_FUNC_DECL(CanvasRenderingContext3DUniform2iv)
+{
+ INC_STATS("DOM.CanvasRenderingContext3D.uniform2iv()");
+ return uniformHelperi(args, kUniform2v);
+}
+
+CALLBACK_FUNC_DECL(CanvasRenderingContext3DUniform3fv)
+{
+ INC_STATS("DOM.CanvasRenderingContext3D.uniform3fv()");
+ return vertexAttribAndUniformHelperf(args, kUniform3v);
+}
+
+CALLBACK_FUNC_DECL(CanvasRenderingContext3DUniform3iv)
+{
+ INC_STATS("DOM.CanvasRenderingContext3D.uniform3iv()");
+ return uniformHelperi(args, kUniform3v);
+}
+
+CALLBACK_FUNC_DECL(CanvasRenderingContext3DUniform4fv)
+{
+ INC_STATS("DOM.CanvasRenderingContext3D.uniform4fv()");
+ return vertexAttribAndUniformHelperf(args, kUniform4v);
+}
+
+CALLBACK_FUNC_DECL(CanvasRenderingContext3DUniform4iv)
+{
+ INC_STATS("DOM.CanvasRenderingContext3D.uniform4iv()");
+ return uniformHelperi(args, kUniform4v);
+}
+
+static v8::Handle<v8::Value> uniformMatrixHelper(const v8::Arguments& args,
+ int matrixSize)
+{
+ // Forms:
+ // * glUniformMatrix2fv(GLint location, GLboolean transpose, Array data);
+ // * glUniformMatrix2fv(GLint location, GLboolean transpose, CanvasFloatArray data);
+ // * glUniformMatrix3fv(GLint location, GLboolean transpose, Array data);
+ // * glUniformMatrix3fv(GLint location, GLboolean transpose, CanvasFloatArray data);
+ // * glUniformMatrix4fv(GLint location, GLboolean transpose, Array data);
+ // * glUniformMatrix4fv(GLint location, GLboolean transpose, CanvasFloatArray data);
+ //
+ // FIXME: need to change to accept CanvasFloatArray as well.
+ if (args.Length() != 3) {
+ V8Proxy::setDOMException(SYNTAX_ERR);
+ return notHandledByInterceptor();
+ }
+
+ CanvasRenderingContext3D* context =
+ V8DOMWrapper::convertDOMWrapperToNative<CanvasRenderingContext3D>(args.Holder());
+ bool ok;
+ int location = toInt32(args[0], ok);
+ if (!ok) {
+ V8Proxy::setDOMException(SYNTAX_ERR);
+ return notHandledByInterceptor();
+ }
+ bool transpose = args[1]->BooleanValue();
+ if (V8CanvasFloatArray::HasInstance(args[2])) {
+ CanvasFloatArray* array =
+ V8DOMWrapper::convertToNativeObject<CanvasFloatArray>(V8ClassIndex::CANVASFLOATARRAY, args[2]->ToObject());
+ ASSERT(array != NULL);
+ switch (matrixSize) {
+ case 2: context->uniformMatrix2fv(location, transpose, array); break;
+ case 3: context->uniformMatrix3fv(location, transpose, array); break;
+ case 4: context->uniformMatrix4fv(location, transpose, array); break;
+ default: ASSERT_NOT_REACHED(); break;
+ }
+ return v8::Undefined();
+ }
+
+ v8::Handle<v8::Array> array =
+ v8::Local<v8::Array>::Cast(args[2]);
+ if (array.IsEmpty()) {
+ V8Proxy::setDOMException(SYNTAX_ERR);
+ return notHandledByInterceptor();
+ }
+ uint32_t len = array->Length();
+ float* data = jsArrayToFloatArray(array, len);
+ if (!data) {
+ // FIXME: consider different / better exception type.
+ V8Proxy::setDOMException(SYNTAX_ERR);
+ return notHandledByInterceptor();
+ }
+ switch (matrixSize) {
+ case 2: context->uniformMatrix2fv(location, transpose, data, len); break;
+ case 3: context->uniformMatrix3fv(location, transpose, data, len); break;
+ case 4: context->uniformMatrix4fv(location, transpose, data, len); break;
+ default: ASSERT_NOT_REACHED(); break;
+ }
+ fastFree(data);
+ return v8::Undefined();
+}
+
+CALLBACK_FUNC_DECL(CanvasRenderingContext3DUniformMatrix2fv)
+{
+ INC_STATS("DOM.CanvasRenderingContext3D.uniformMatrix2fv()");
+ return uniformMatrixHelper(args, 2);
+}
+
+CALLBACK_FUNC_DECL(CanvasRenderingContext3DUniformMatrix3fv)
+{
+ INC_STATS("DOM.CanvasRenderingContext3D.uniformMatrix3fv()");
+ return uniformMatrixHelper(args, 3);
+}
+
+CALLBACK_FUNC_DECL(CanvasRenderingContext3DUniformMatrix4fv)
+{
+ INC_STATS("DOM.CanvasRenderingContext3D.uniformMatrix4fv()");
+ return uniformMatrixHelper(args, 4);
+}
+
+CALLBACK_FUNC_DECL(CanvasRenderingContext3DVertexAttrib1fv)
+{
+ INC_STATS("DOM.CanvasRenderingContext3D.vertexAttrib1fv()");
+ return vertexAttribAndUniformHelperf(args, kVertexAttrib1v);
+}
+
+CALLBACK_FUNC_DECL(CanvasRenderingContext3DVertexAttrib2fv)
+{
+ INC_STATS("DOM.CanvasRenderingContext3D.vertexAttrib2fv()");
+ return vertexAttribAndUniformHelperf(args, kVertexAttrib2v);
+}
+
+CALLBACK_FUNC_DECL(CanvasRenderingContext3DVertexAttrib3fv)
+{
+ INC_STATS("DOM.CanvasRenderingContext3D.vertexAttrib3fv()");
+ return vertexAttribAndUniformHelperf(args, kVertexAttrib3v);
+}
+
+CALLBACK_FUNC_DECL(CanvasRenderingContext3DVertexAttrib4fv)
+{
+ INC_STATS("DOM.CanvasRenderingContext3D.vertexAttrib4fv()");
+ return vertexAttribAndUniformHelperf(args, kVertexAttrib4v);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/bindings/v8/custom/V8CanvasShortArrayCustom.cpp b/WebCore/bindings/v8/custom/V8CanvasShortArrayCustom.cpp
new file mode 100644
index 0000000..8b83022
--- /dev/null
+++ b/WebCore/bindings/v8/custom/V8CanvasShortArrayCustom.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(3D_CANVAS)
+
+#include "CanvasArrayBuffer.h"
+#include "CanvasShortArray.h"
+
+#include "V8Binding.h"
+#include "V8CanvasArrayBuffer.h"
+#include "V8CanvasArrayCustom.h"
+#include "V8CustomBinding.h"
+#include "V8Proxy.h"
+
+namespace WebCore {
+
+CALLBACK_FUNC_DECL(CanvasShortArrayConstructor)
+{
+ INC_STATS("DOM.CanvasShortArray.Contructor");
+
+ return constructCanvasArray<CanvasShortArray>(args, V8ClassIndex::ToInt(V8ClassIndex::CANVASSHORTARRAY));
+}
+
+// Get the specified value from the array and return it wrapped as a JavaScript Number object to V8. Accesses outside the valid array range return "undefined".
+INDEXED_PROPERTY_GETTER(CanvasShortArray)
+{
+ INC_STATS("DOM.CanvasShortArray.IndexedPropertyGetter");
+ CanvasShortArray* array = V8DOMWrapper::convertToNativeObject<CanvasShortArray>(V8ClassIndex::CANVASSHORTARRAY, info.Holder());
+
+ if ((index < 0) || (index >= array->length()))
+ return v8::Undefined();
+ short result;
+ if (!array->get(index, result))
+ return v8::Undefined();
+ return v8::Number::New(result);
+}
+
+// Set the specified value in the array. Accesses outside the valid array range are silently ignored.
+INDEXED_PROPERTY_SETTER(CanvasShortArray)
+{
+ INC_STATS("DOM.CanvasShortArray.IndexedPropertySetter");
+ CanvasShortArray* array = V8DOMWrapper::convertToNativeObject<CanvasShortArray>(V8ClassIndex::CANVASSHORTARRAY, info.Holder());
+
+ if ((index >= 0) && (index < array->length())) {
+ if (!value->IsNumber())
+ return throwError("Could not convert value argument to a number");
+ array->set(index, value->NumberValue());
+ }
+ return value;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/bindings/v8/custom/V8CanvasUnsignedByteArrayCustom.cpp b/WebCore/bindings/v8/custom/V8CanvasUnsignedByteArrayCustom.cpp
new file mode 100644
index 0000000..62ab880
--- /dev/null
+++ b/WebCore/bindings/v8/custom/V8CanvasUnsignedByteArrayCustom.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(3D_CANVAS)
+
+#include "CanvasArrayBuffer.h"
+#include "CanvasUnsignedByteArray.h"
+
+#include "V8Binding.h"
+#include "V8CanvasArrayBuffer.h"
+#include "V8CanvasArrayCustom.h"
+#include "V8CustomBinding.h"
+#include "V8Proxy.h"
+
+namespace WebCore {
+
+CALLBACK_FUNC_DECL(CanvasUnsignedByteArrayConstructor)
+{
+ INC_STATS("DOM.CanvasUnsignedByteArray.Contructor");
+
+ return constructCanvasArray<CanvasUnsignedByteArray>(args, V8ClassIndex::ToInt(V8ClassIndex::CANVASUNSIGNEDBYTEARRAY));
+}
+
+// Get the specified value from the array and return it wrapped as a JavaScript Number object to V8. Accesses outside the valid array range return "undefined".
+INDEXED_PROPERTY_GETTER(CanvasUnsignedByteArray)
+{
+ INC_STATS("DOM.CanvasUnsignedByteArray.IndexedPropertyGetter");
+ CanvasUnsignedByteArray* array = V8DOMWrapper::convertToNativeObject<CanvasUnsignedByteArray>(V8ClassIndex::CANVASUNSIGNEDBYTEARRAY, info.Holder());
+
+ if ((index < 0) || (index >= array->length()))
+ return v8::Undefined();
+ unsigned char result;
+ if (!array->get(index, result))
+ return v8::Undefined();
+ return v8::Number::New(result);
+}
+
+// Set the specified value in the array. Accesses outside the valid array range are silently ignored.
+INDEXED_PROPERTY_SETTER(CanvasUnsignedByteArray)
+{
+ INC_STATS("DOM.CanvasUnsignedByteArray.IndexedPropertySetter");
+ CanvasUnsignedByteArray* array = V8DOMWrapper::convertToNativeObject<CanvasUnsignedByteArray>(V8ClassIndex::CANVASUNSIGNEDBYTEARRAY, info.Holder());
+
+ if ((index >= 0) && (index < array->length())) {
+ if (!value->IsNumber())
+ return throwError("Could not convert value argument to a number");
+ array->set(index, value->NumberValue());
+ }
+ return value;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/bindings/v8/custom/V8CanvasUnsignedIntArrayCustom.cpp b/WebCore/bindings/v8/custom/V8CanvasUnsignedIntArrayCustom.cpp
new file mode 100644
index 0000000..94ec7d0
--- /dev/null
+++ b/WebCore/bindings/v8/custom/V8CanvasUnsignedIntArrayCustom.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(3D_CANVAS)
+
+#include "CanvasArrayBuffer.h"
+#include "CanvasUnsignedIntArray.h"
+
+#include "V8Binding.h"
+#include "V8CanvasArrayBuffer.h"
+#include "V8CanvasArrayCustom.h"
+#include "V8CustomBinding.h"
+#include "V8Proxy.h"
+
+namespace WebCore {
+
+CALLBACK_FUNC_DECL(CanvasUnsignedIntArrayConstructor)
+{
+ INC_STATS("DOM.CanvasUnsignedIntArray.Contructor");
+
+ return constructCanvasArray<CanvasUnsignedIntArray>(args, V8ClassIndex::ToInt(V8ClassIndex::CANVASUNSIGNEDINTARRAY));
+}
+
+// Get the specified value from the integer array and return it wrapped as a JavaScript Number object to V8. Accesses outside the valid pixel buffer range return "undefined".
+INDEXED_PROPERTY_GETTER(CanvasUnsignedIntArray)
+{
+ INC_STATS("DOM.CanvasUnsignedIntArray.IndexedPropertyGetter");
+ CanvasUnsignedIntArray* array = V8DOMWrapper::convertToNativeObject<CanvasUnsignedIntArray>(V8ClassIndex::CANVASUNSIGNEDINTARRAY, info.Holder());
+
+ if ((index < 0) || (index >= array->length()))
+ return v8::Undefined();
+ unsigned int result;
+ if (!array->get(index, result))
+ return v8::Undefined();
+ return v8::Number::New(result);
+}
+
+// Set the specified value in the integer array. Accesses outside the valid integer array range are silently ignored.
+INDEXED_PROPERTY_SETTER(CanvasUnsignedIntArray)
+{
+ INC_STATS("DOM.CanvasUnsignedIntArray.IndexedPropertySetter");
+ CanvasUnsignedIntArray* array = V8DOMWrapper::convertToNativeObject<CanvasUnsignedIntArray>(V8ClassIndex::CANVASUNSIGNEDINTARRAY, info.Holder());
+
+ if ((index >= 0) && (index < array->length())) {
+ if (!value->IsNumber())
+ return throwError("Could not convert value argument to a number");
+ array->set(index, value->NumberValue());
+ }
+ return value;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/bindings/v8/custom/V8CanvasUnsignedShortArrayCustom.cpp b/WebCore/bindings/v8/custom/V8CanvasUnsignedShortArrayCustom.cpp
new file mode 100644
index 0000000..eeef82c
--- /dev/null
+++ b/WebCore/bindings/v8/custom/V8CanvasUnsignedShortArrayCustom.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(3D_CANVAS)
+
+#include "CanvasArrayBuffer.h"
+#include "CanvasUnsignedShortArray.h"
+
+#include "V8Binding.h"
+#include "V8CanvasArrayBuffer.h"
+#include "V8CanvasArrayCustom.h"
+#include "V8CustomBinding.h"
+#include "V8Proxy.h"
+
+namespace WebCore {
+
+CALLBACK_FUNC_DECL(CanvasUnsignedShortArrayConstructor)
+{
+ INC_STATS("DOM.CanvasUnsignedShortArray.Contructor");
+
+ return constructCanvasArray<CanvasUnsignedShortArray>(args, V8ClassIndex::ToInt(V8ClassIndex::CANVASUNSIGNEDSHORTARRAY));
+}
+
+// Get the specified value from the array and return it wrapped as a JavaScript Number object to V8. Accesses outside the valid array range return "undefined".
+INDEXED_PROPERTY_GETTER(CanvasUnsignedShortArray)
+{
+ INC_STATS("DOM.CanvasUnsignedShortArray.IndexedPropertyGetter");
+ CanvasUnsignedShortArray* array = V8DOMWrapper::convertToNativeObject<CanvasUnsignedShortArray>(V8ClassIndex::CANVASUNSIGNEDSHORTARRAY, info.Holder());
+
+ if ((index < 0) || (index >= array->length()))
+ return v8::Undefined();
+ unsigned short result;
+ if (!array->get(index, result))
+ return v8::Undefined();
+ return v8::Number::New(result);
+}
+
+// Set the specified value in the array. Accesses outside the valid array range are silently ignored.
+INDEXED_PROPERTY_SETTER(CanvasUnsignedShortArray)
+{
+ INC_STATS("DOM.CanvasUnsignedShortArray.IndexedPropertySetter");
+ CanvasUnsignedShortArray* array = V8DOMWrapper::convertToNativeObject<CanvasUnsignedShortArray>(V8ClassIndex::CANVASUNSIGNEDSHORTARRAY, info.Holder());
+
+ if ((index >= 0) && (index < array->length())) {
+ if (!value->IsNumber())
+ return throwError("Could not convert value argument to a number");
+ array->set(index, value->NumberValue());
+ }
+ return value;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(3D_CANVAS)
diff --git a/WebCore/bindings/v8/custom/V8CustomBinding.h b/WebCore/bindings/v8/custom/V8CustomBinding.h
index 22b4a94..82ce1c1 100644
--- a/WebCore/bindings/v8/custom/V8CustomBinding.h
+++ b/WebCore/bindings/v8/custom/V8CustomBinding.h
@@ -135,6 +135,16 @@ namespace WebCore {
static const int kAbstractWorkerInternalFieldCount = kDefaultWrapperInternalFieldCount + 1;
#endif
+#if ENABLE(NOTIFICATIONS)
+ static const int kNotificationRequestCacheIndex = kDefaultWrapperInternalFieldCount + 0;
+ static const int kNotificationInternalFieldCount = kDefaultWrapperInternalFieldCount + 1;
+#endif
+
+#if ENABLE(SVG)
+ static const int kSVGElementInstanceEventListenerCacheIndex = kDefaultWrapperInternalFieldCount + 0;
+ static const int kSVGElementInstanceInternalFieldCount = kDefaultWrapperInternalFieldCount + 1;
+#endif
+
static const int kDOMWindowConsoleIndex = kDefaultWrapperInternalFieldCount + 0;
static const int kDOMWindowHistoryIndex = kDefaultWrapperInternalFieldCount + 1;
static const int kDOMWindowLocationbarIndex = kDefaultWrapperInternalFieldCount + 2;
@@ -148,7 +158,8 @@ namespace WebCore {
static const int kDOMWindowToolbarIndex = kDefaultWrapperInternalFieldCount + 10;
static const int kDOMWindowLocationIndex = kDefaultWrapperInternalFieldCount + 11;
static const int kDOMWindowDOMSelectionIndex = kDefaultWrapperInternalFieldCount + 12;
- static const int kDOMWindowInternalFieldCount = kDefaultWrapperInternalFieldCount + 13;
+ static const int kDOMWindowEventListenerCacheIndex = kDefaultWrapperInternalFieldCount + 13;
+ static const int kDOMWindowInternalFieldCount = kDefaultWrapperInternalFieldCount + 14;
static const int kStyleSheetOwnerNodeIndex = kDefaultWrapperInternalFieldCount + 0;
static const int kStyleSheetInternalFieldCount = kDefaultWrapperInternalFieldCount + 1;
@@ -158,6 +169,11 @@ namespace WebCore {
static const int kDOMApplicationCacheFieldCount = kDefaultWrapperInternalFieldCount + 1;
#endif
+#if ENABLE(WEB_SOCKETS)
+ static const int kWebSocketCacheIndex = kDefaultWrapperInternalFieldCount + 0;
+ static const int kWebSocketInternalFieldCount = kDefaultWrapperInternalFieldCount + 1;
+#endif
+
#define DECLARE_PROPERTY_ACCESSOR_GETTER(NAME) \
static v8::Handle<v8::Value> v8##NAME##AccessorGetter( \
v8::Local<v8::String> name, const v8::AccessorInfo& info)
@@ -218,11 +234,18 @@ namespace WebCore {
DECLARE_PROPERTY_ACCESSOR(CanvasRenderingContext2DStrokeStyle);
DECLARE_PROPERTY_ACCESSOR(CanvasRenderingContext2DFillStyle);
- DECLARE_PROPERTY_ACCESSOR_GETTER(DOMWindowEvent);
+ DECLARE_PROPERTY_ACCESSOR(DOMWindowEvent);
DECLARE_PROPERTY_ACCESSOR_GETTER(DOMWindowCrypto);
DECLARE_PROPERTY_ACCESSOR_SETTER(DOMWindowLocation);
DECLARE_PROPERTY_ACCESSOR_SETTER(DOMWindowOpener);
+#if ENABLE(VIDEO)
+ DECLARE_PROPERTY_ACCESSOR_GETTER(DOMWindowAudio);
+#endif
+
+ DECLARE_PROPERTY_ACCESSOR_GETTER(DOMWindowImage);
+ DECLARE_PROPERTY_ACCESSOR_GETTER(DOMWindowOption);
+
DECLARE_PROPERTY_ACCESSOR(DocumentLocation);
DECLARE_PROPERTY_ACCESSOR(DocumentImplementation);
DECLARE_PROPERTY_ACCESSOR_GETTER(EventSrcElement);
@@ -231,7 +254,6 @@ namespace WebCore {
DECLARE_PROPERTY_ACCESSOR_GETTER(EventClipboardData);
DECLARE_PROPERTY_ACCESSOR(DOMWindowEventHandler);
- DECLARE_PROPERTY_ACCESSOR(NodeEventHandler);
DECLARE_CALLBACK(HTMLCanvasElementGetContext);
@@ -319,6 +341,38 @@ namespace WebCore {
DECLARE_CALLBACK(CanvasRenderingContext2DStrokeText);
DECLARE_CALLBACK(CanvasRenderingContext2DPutImageData);
+#if ENABLE(3D_CANVAS)
+ DECLARE_CALLBACK(CanvasRenderingContext3DBufferData);
+ DECLARE_CALLBACK(CanvasRenderingContext3DBufferSubData);
+ DECLARE_CALLBACK(CanvasRenderingContext3DSizeof);
+ DECLARE_CALLBACK(CanvasRenderingContext3DTexImage2D);
+ DECLARE_CALLBACK(CanvasRenderingContext3DTexSubImage2D);
+ DECLARE_CALLBACK(CanvasRenderingContext3DUniform1fv);
+ DECLARE_CALLBACK(CanvasRenderingContext3DUniform1iv);
+ DECLARE_CALLBACK(CanvasRenderingContext3DUniform2fv);
+ DECLARE_CALLBACK(CanvasRenderingContext3DUniform2iv);
+ DECLARE_CALLBACK(CanvasRenderingContext3DUniform3fv);
+ DECLARE_CALLBACK(CanvasRenderingContext3DUniform3iv);
+ DECLARE_CALLBACK(CanvasRenderingContext3DUniform4fv);
+ DECLARE_CALLBACK(CanvasRenderingContext3DUniform4iv);
+ DECLARE_CALLBACK(CanvasRenderingContext3DUniformMatrix2fv);
+ DECLARE_CALLBACK(CanvasRenderingContext3DUniformMatrix3fv);
+ DECLARE_CALLBACK(CanvasRenderingContext3DUniformMatrix4fv);
+ DECLARE_CALLBACK(CanvasRenderingContext3DVertexAttrib1fv);
+ DECLARE_CALLBACK(CanvasRenderingContext3DVertexAttrib2fv);
+ DECLARE_CALLBACK(CanvasRenderingContext3DVertexAttrib3fv);
+ DECLARE_CALLBACK(CanvasRenderingContext3DVertexAttrib4fv);
+
+ DECLARE_CALLBACK(CanvasArrayBufferConstructor);
+ DECLARE_CALLBACK(CanvasByteArrayConstructor);
+ DECLARE_CALLBACK(CanvasFloatArrayConstructor);
+ DECLARE_CALLBACK(CanvasIntArrayConstructor);
+ DECLARE_CALLBACK(CanvasShortArrayConstructor);
+ DECLARE_CALLBACK(CanvasUnsignedByteArrayConstructor);
+ DECLARE_CALLBACK(CanvasUnsignedIntArrayConstructor);
+ DECLARE_CALLBACK(CanvasUnsignedShortArrayConstructor);
+#endif
+
DECLARE_PROPERTY_ACCESSOR_GETTER(ClipboardTypes);
DECLARE_CALLBACK(ClipboardClearData);
DECLARE_CALLBACK(ClipboardGetData);
@@ -400,14 +454,22 @@ namespace WebCore {
DECLARE_CALLBACK(InspectorBackendAddSourceToFrame);
DECLARE_CALLBACK(InspectorBackendSearch);
DECLARE_CALLBACK(InspectorBackendSetting);
+ DECLARE_CALLBACK(InspectorBackendDatabaseForId);
DECLARE_CALLBACK(InspectorBackendInspectedWindow);
DECLARE_CALLBACK(InspectorBackendSetSetting);
DECLARE_CALLBACK(InspectorBackendCurrentCallFrame);
DECLARE_CALLBACK(InspectorBackendDebuggerEnabled);
DECLARE_CALLBACK(InspectorBackendPauseOnExceptions);
DECLARE_CALLBACK(InspectorBackendProfilerEnabled);
+ DECLARE_CALLBACK(InspectorBackendNodeForId);
+ DECLARE_CALLBACK(InspectorBackendWrapObject);
+ DECLARE_CALLBACK(InspectorBackendUnwrapObject);
+ DECLARE_CALLBACK(InspectorBackendPushNodePathToFrontend);
#if ENABLE(DATABASE)
- DECLARE_CALLBACK(InspectorBackendDatabaseTableNames);
+ DECLARE_CALLBACK(InspectorBackendSelectDatabase);
+#endif
+#if ENABLE(DOM_STORAGE)
+ DECLARE_CALLBACK(InspectorBackendSelectDOMStorage);
#endif
DECLARE_CALLBACK(InspectorBackendWrapCallback);
@@ -445,21 +507,52 @@ namespace WebCore {
DECLARE_INDEXED_PROPERTY_SETTER(HTMLSelectElementCollection);
DECLARE_NAMED_PROPERTY_GETTER(HTMLCollection);
+#if ENABLE(3D_CANVAS)
+ DECLARE_INDEXED_PROPERTY_GETTER(CanvasByteArray);
+ DECLARE_INDEXED_PROPERTY_SETTER(CanvasByteArray);
+
+ DECLARE_INDEXED_PROPERTY_GETTER(CanvasFloatArray);
+ DECLARE_INDEXED_PROPERTY_SETTER(CanvasFloatArray);
+
+ DECLARE_INDEXED_PROPERTY_GETTER(CanvasIntArray);
+ DECLARE_INDEXED_PROPERTY_SETTER(CanvasIntArray);
+#endif
+
DECLARE_INDEXED_PROPERTY_GETTER(CanvasPixelArray);
DECLARE_INDEXED_PROPERTY_SETTER(CanvasPixelArray);
+#if ENABLE(3D_CANVAS)
+ DECLARE_INDEXED_PROPERTY_GETTER(CanvasShortArray);
+ DECLARE_INDEXED_PROPERTY_SETTER(CanvasShortArray);
+
+ DECLARE_INDEXED_PROPERTY_GETTER(CanvasUnsignedByteArray);
+ DECLARE_INDEXED_PROPERTY_SETTER(CanvasUnsignedByteArray);
+
+ DECLARE_INDEXED_PROPERTY_GETTER(CanvasUnsignedIntArray);
+ DECLARE_INDEXED_PROPERTY_SETTER(CanvasUnsignedIntArray);
+
+ DECLARE_INDEXED_PROPERTY_GETTER(CanvasUnsignedShortArray);
+ DECLARE_INDEXED_PROPERTY_SETTER(CanvasUnsignedShortArray);
+#endif
+
+ DECLARE_PROPERTY_ACCESSOR_GETTER(MessageEventPorts);
+ DECLARE_CALLBACK(MessageEventInitMessageEvent);
+
DECLARE_PROPERTY_ACCESSOR(MessagePortOnmessage);
DECLARE_PROPERTY_ACCESSOR(MessagePortOnclose);
- DECLARE_CALLBACK(MessagePortStartConversation);
DECLARE_CALLBACK(MessagePortAddEventListener);
+ DECLARE_CALLBACK(MessagePortPostMessage);
DECLARE_CALLBACK(MessagePortRemoveEventListener);
+ DECLARE_CALLBACK(MessagePortStartConversation);
DECLARE_CALLBACK(DatabaseChangeVersion);
DECLARE_CALLBACK(DatabaseTransaction);
+ DECLARE_CALLBACK(DatabaseReadTransaction);
DECLARE_CALLBACK(SQLTransactionExecuteSql);
DECLARE_CALLBACK(SQLResultSetRowListItem);
DECLARE_INDEXED_PROPERTY_GETTER(ClientRectList);
+ DECLARE_INDEXED_PROPERTY_GETTER(FileList);
#if ENABLE(DATAGRID)
DECLARE_PROPERTY_ACCESSOR(HTMLDataGridElementDataSource);
@@ -496,8 +589,10 @@ namespace WebCore {
DECLARE_CALLBACK(AbstractWorkerRemoveEventListener);
DECLARE_PROPERTY_ACCESSOR(DedicatedWorkerContextOnmessage);
+ DECLARE_CALLBACK(DedicatedWorkerContextPostMessage);
DECLARE_PROPERTY_ACCESSOR(WorkerOnmessage);
+ DECLARE_CALLBACK(WorkerPostMessage);
DECLARE_CALLBACK(WorkerConstructor);
DECLARE_PROPERTY_ACCESSOR_GETTER(WorkerContextSelf);
@@ -509,7 +604,17 @@ namespace WebCore {
DECLARE_CALLBACK(WorkerContextClearInterval);
DECLARE_CALLBACK(WorkerContextAddEventListener);
DECLARE_CALLBACK(WorkerContextRemoveEventListener);
-#endif
+#endif // ENABLE(WORKERS)
+
+#if ENABLE(NOTIFICATIONS)
+ DECLARE_CALLBACK(NotificationCenterRequestPermission);
+ DECLARE_CALLBACK(NotificationCenterCreateNotification);
+ DECLARE_CALLBACK(NotificationCenterCreateHTMLNotification);
+
+ DECLARE_CALLBACK(NotificationAddEventListener);
+ DECLARE_CALLBACK(NotificationRemoveEventListener);
+ DECLARE_PROPERTY_ACCESSOR(NotificationEventHandler);
+#endif // ENABLE(NOTIFICATIONS)
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
DECLARE_PROPERTY_ACCESSOR(DOMApplicationCacheEventHandler);
@@ -528,6 +633,15 @@ namespace WebCore {
DECLARE_PROPERTY_ACCESSOR_GETTER(CoordinatesHeading);
DECLARE_PROPERTY_ACCESSOR_GETTER(CoordinatesSpeed);
+#if ENABLE(WEB_SOCKETS)
+ DECLARE_PROPERTY_ACCESSOR(WebSocketOnopen);
+ DECLARE_PROPERTY_ACCESSOR(WebSocketOnmessage);
+ DECLARE_PROPERTY_ACCESSOR(WebSocketOnclose);
+ DECLARE_CALLBACK(WebSocketConstructor);
+ DECLARE_CALLBACK(WebSocketSend);
+ DECLARE_CALLBACK(WebSocketClose);
+#endif
+
#undef DECLARE_INDEXED_ACCESS_CHECK
#undef DECLARE_NAMED_ACCESS_CHECK
diff --git a/WebCore/bindings/v8/custom/V8CustomEventListener.cpp b/WebCore/bindings/v8/custom/V8CustomEventListener.cpp
index 305da8d..91abecd 100644
--- a/WebCore/bindings/v8/custom/V8CustomEventListener.cpp
+++ b/WebCore/bindings/v8/custom/V8CustomEventListener.cpp
@@ -35,37 +35,25 @@
namespace WebCore {
-V8EventListener::V8EventListener(Frame* frame, v8::Local<v8::Object> listener, bool isAttribute)
- : V8AbstractEventListener(frame, isAttribute)
+V8EventListener::V8EventListener(Frame* frame, PassRefPtr<V8ListenerGuard> guard, v8::Local<v8::Object> listener, bool isAttribute)
+ : V8AbstractEventListener(frame, guard, isAttribute)
{
- m_listener = v8::Persistent<v8::Object>::New(listener);
-#ifndef NDEBUG
- V8GCController::registerGlobalHandle(EVENT_LISTENER, this, m_listener);
-#endif
-}
-
-V8EventListener::~V8EventListener()
-{
- if (m_frame) {
- V8Proxy* proxy = V8Proxy::retrieve(m_frame);
- if (proxy)
- proxy->eventListeners()->remove(this);
- }
-
- disposeListenerObject();
+ setListenerObject(listener);
}
v8::Local<v8::Function> V8EventListener::getListenerFunction()
{
+ v8::Local<v8::Object> listener = getListenerObject();
+
// Has the listener been disposed?
- if (m_listener.IsEmpty())
+ if (listener.IsEmpty())
return v8::Local<v8::Function>();
- if (m_listener->IsFunction())
- return v8::Local<v8::Function>::New(v8::Persistent<v8::Function>::Cast(m_listener));
+ if (listener->IsFunction())
+ return v8::Local<v8::Function>::Cast(listener);
- if (m_listener->IsObject()) {
- v8::Local<v8::Value> property = m_listener->Get(v8::String::NewSymbol("handleEvent"));
+ if (listener->IsObject()) {
+ v8::Local<v8::Value> property = listener->Get(v8::String::NewSymbol("handleEvent"));
if (property->IsFunction())
return v8::Local<v8::Function>::Cast(property);
}
@@ -73,16 +61,16 @@ v8::Local<v8::Function> V8EventListener::getListenerFunction()
return v8::Local<v8::Function>();
}
-v8::Local<v8::Value> V8EventListener::callListenerFunction(v8::Handle<v8::Value> jsEvent, Event* event, bool isWindowEvent)
+v8::Local<v8::Value> V8EventListener::callListenerFunction(v8::Handle<v8::Value> jsEvent, Event* event)
{
v8::Local<v8::Function> handlerFunction = getListenerFunction();
- v8::Local<v8::Object> receiver = getReceiverObject(event, isWindowEvent);
+ v8::Local<v8::Object> receiver = getReceiverObject(event);
if (handlerFunction.IsEmpty() || receiver.IsEmpty())
return v8::Local<v8::Value>();
v8::Handle<v8::Value> parameters[1] = { jsEvent };
- V8Proxy* proxy = V8Proxy::retrieve(m_frame);
+ V8Proxy* proxy = V8Proxy::retrieve(frame());
if (!proxy)
return v8::Local<v8::Value>();
return proxy->callFunction(handlerFunction, receiver, 1, parameters);
diff --git a/WebCore/bindings/v8/custom/V8CustomEventListener.h b/WebCore/bindings/v8/custom/V8CustomEventListener.h
index 20adf99..e34f24f 100644
--- a/WebCore/bindings/v8/custom/V8CustomEventListener.h
+++ b/WebCore/bindings/v8/custom/V8CustomEventListener.h
@@ -44,23 +44,19 @@ namespace WebCore {
// that can handle the event.
class V8EventListener : public V8AbstractEventListener {
public:
- static PassRefPtr<V8EventListener> create(Frame* frame, v8::Local<v8::Object> listener, bool isAttribute)
+ static PassRefPtr<V8EventListener> create(Frame* frame, PassRefPtr<V8ListenerGuard> guard, v8::Local<v8::Object> listener, bool isAttribute)
{
- return adoptRef(new V8EventListener(frame, listener, isAttribute));
+ return adoptRef(new V8EventListener(frame, guard, listener, isAttribute));
}
- // Detach the listener from its owner frame.
- void disconnectFrame() { m_frame = 0; }
-
protected:
- V8EventListener(Frame*, v8::Local<v8::Object> listener, bool isAttribute);
- virtual ~V8EventListener();
+ V8EventListener(Frame*, PassRefPtr<V8ListenerGuard>, v8::Local<v8::Object> listener, bool isAttribute);
+
v8::Local<v8::Function> getListenerFunction();
private:
- virtual v8::Local<v8::Value> callListenerFunction(v8::Handle<v8::Value> jsEvent, Event*, bool isWindowEvent);
- virtual bool virtualisAttribute() const { return m_isAttribute; }
- };
+ virtual v8::Local<v8::Value> callListenerFunction(v8::Handle<v8::Value> jsEvent, Event*);
+ };
} // namespace WebCore
diff --git a/WebCore/bindings/v8/custom/V8DOMApplicationCacheCustom.cpp b/WebCore/bindings/v8/custom/V8DOMApplicationCacheCustom.cpp
index 7a3bfe6..134de95 100644
--- a/WebCore/bindings/v8/custom/V8DOMApplicationCacheCustom.cpp
+++ b/WebCore/bindings/v8/custom/V8DOMApplicationCacheCustom.cpp
@@ -37,77 +37,19 @@
#include "V8Binding.h"
#include "V8CustomBinding.h"
#include "V8Document.h"
-#include "V8ObjectEventListener.h"
#include "V8Proxy.h"
#include "V8Utilities.h"
#include "WorkerContextExecutionProxy.h"
namespace WebCore {
-static const bool kFindOnly = true;
-static const bool kFindOrCreate = false;
-
-static PassRefPtr<EventListener> argumentToEventListener(DOMApplicationCache* appcache, v8::Local<v8::Value> value, bool findOnly)
-{
- V8Proxy* proxy = V8Proxy::retrieve(appcache->scriptExecutionContext());
- if (proxy)
- return findOnly ? proxy->objectListeners()->findWrapper(value, false)
- : proxy->objectListeners()->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, false);
- return 0;
-}
-
-static v8::Local<v8::Object> eventListenerToV8Object(EventListener* listener)
-{
- return (static_cast<V8ObjectEventListener*>(listener))->getListenerObject();
-}
-
-static inline ApplicationCacheHost::EventID toEventID(v8::Local<v8::String> value)
-{
- String key = toWebCoreString(value);
- ASSERT(key.startsWith("on"));
- return DOMApplicationCache::toEventID(key.substring(2));
-}
-
-// Handles appcache.onfooevent attribute getting
-ACCESSOR_GETTER(DOMApplicationCacheEventHandler)
-{
- INC_STATS("DOMApplicationCache.onevent_getter");
- DOMApplicationCache* appcache = V8DOMWrapper::convertToNativeObject<DOMApplicationCache>(V8ClassIndex::DOMAPPLICATIONCACHE, info.Holder());
- EventListener* listener = appcache->getAttributeEventListener(toEventID(name));
- if (!listener)
- return v8::Null();
- return eventListenerToV8Object(listener);
-}
-
-// Handles appcache.onfooevent attribute setting
-ACCESSOR_SETTER(DOMApplicationCacheEventHandler)
-{
- INC_STATS("DOMApplicationCache.onevent_setter");
- DOMApplicationCache* appcache = V8DOMWrapper::convertToNativeObject<DOMApplicationCache>(V8ClassIndex::DOMAPPLICATIONCACHE, info.Holder());
- ApplicationCacheHost::EventID eventType = toEventID(name);
-
- if (EventListener* oldListener = appcache->getAttributeEventListener(eventType)) {
- v8::Local<v8::Object> object = eventListenerToV8Object(oldListener);
- removeHiddenDependency(info.Holder(), object, V8Custom::kDOMApplicationCacheCacheIndex);
- appcache->clearAttributeEventListener(eventType);
- }
-
- if (value->IsFunction()) {
- RefPtr<EventListener> newListener = argumentToEventListener(appcache, value, kFindOrCreate);
- if (newListener) {
- createHiddenDependency(info.Holder(), value, V8Custom::kDOMApplicationCacheCacheIndex);
- appcache->setAttributeEventListener(eventType, newListener);
- }
- }
-}
-
// Handles appcache.addEventListner(name, func, capture) method calls
CALLBACK_FUNC_DECL(DOMApplicationCacheAddEventListener)
{
INC_STATS("DOMApplicationCache.addEventListener()");
DOMApplicationCache* appcache = V8DOMWrapper::convertToNativeObject<DOMApplicationCache>(V8ClassIndex::DOMAPPLICATIONCACHE, args.Holder());
- RefPtr<EventListener> listener = argumentToEventListener(appcache, args[1], kFindOrCreate);
+ RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(appcache, args[1], false, ListenerFindOrCreate);
if (listener) {
createHiddenDependency(args.Holder(), args[1], V8Custom::kDOMApplicationCacheCacheIndex);
String eventType = toWebCoreString(args[0]);
@@ -123,7 +65,7 @@ CALLBACK_FUNC_DECL(DOMApplicationCacheRemoveEventListener)
INC_STATS("DOMApplicationCache.removeEventListener()");
DOMApplicationCache* appcache = V8DOMWrapper::convertToNativeObject<DOMApplicationCache>(V8ClassIndex::DOMAPPLICATIONCACHE, args.Holder());
- RefPtr<EventListener> listener = argumentToEventListener(appcache, args[1], kFindOnly);
+ RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(appcache, args[1], false, ListenerFindOnly);
if (listener) {
removeHiddenDependency(args.Holder(), args[1], V8Custom::kDOMApplicationCacheCacheIndex);
String eventType = toWebCoreString(args[0]);
diff --git a/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp b/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp
index 7d0b9e6..0dc5a96 100644
--- a/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp
+++ b/WebCore/bindings/v8/custom/V8DOMWindowCustom.cpp
@@ -34,6 +34,7 @@
#include "V8Binding.h"
#include "V8CustomBinding.h"
#include "V8CustomEventListener.h"
+#include "V8MessagePortCustom.h"
#include "V8Proxy.h"
#include "V8Utilities.h"
@@ -48,6 +49,7 @@
#include "PlatformScreen.h"
#include "ScheduledAction.h"
#include "ScriptSourceCode.h"
+#include "SerializedScriptValue.h"
#include "Settings.h"
#include "WindowFeatures.h"
@@ -64,32 +66,44 @@ v8::Handle<v8::Value> V8Custom::WindowSetTimeoutImpl(const v8::Arguments& args,
if (argumentCount < 1)
return v8::Undefined();
- DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder());
-
- if (!imp->frame())
- return v8::Undefined();
-
- if (!V8Proxy::canAccessFrame(imp->frame(), true))
- return v8::Undefined();
+ v8::Handle<v8::Value> function = args[0];
- ScriptExecutionContext* scriptContext = static_cast<ScriptExecutionContext*>(imp->frame()->document());
+ WebCore::String functionString;
+ if (!function->IsFunction()) {
+ if (function->IsString())
+ functionString = toWebCoreString(function);
+ else {
+ v8::Handle<v8::Value> v8String = function->ToString();
- v8::Handle<v8::Value> function = args[0];
+ // Bail out if string conversion failed.
+ if (v8String.IsEmpty())
+ return v8::Undefined();
- int32_t timeout = 0;
- if (argumentCount >= 2)
- timeout = args[1]->Int32Value();
+ functionString = toWebCoreString(v8String);
+ }
- int id;
- if (function->IsString()) {
// Don't allow setting timeouts to run empty functions!
// (Bug 1009597)
- WebCore::String functionString = toWebCoreString(function);
if (functionString.length() == 0)
return v8::Undefined();
+ }
+
+ int32_t timeout = 0;
+ if (argumentCount >= 2)
+ timeout = args[1]->Int32Value();
+
+ DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder());
+
+ if (!V8Proxy::canAccessFrame(imp->frame(), true))
+ return v8::Undefined();
- id = DOMTimer::install(scriptContext, new ScheduledAction(functionString), timeout, singleShot);
- } else if (function->IsFunction()) {
+ ScriptExecutionContext* scriptContext = static_cast<ScriptExecutionContext*>(imp->document());
+
+ if (!scriptContext)
+ return v8::Undefined();
+
+ int id;
+ if (function->IsFunction()) {
int paramCount = argumentCount >= 2 ? argumentCount - 2 : 0;
v8::Local<v8::Value>* params = 0;
if (paramCount > 0) {
@@ -100,14 +114,14 @@ v8::Handle<v8::Value> V8Custom::WindowSetTimeoutImpl(const v8::Arguments& args,
}
// params is passed to action, and released in action's destructor
- ScheduledAction* action = new ScheduledAction(v8::Handle<v8::Function>::Cast(function), paramCount, params);
+ ScheduledAction* action = new ScheduledAction(V8Proxy::context(imp->frame()), v8::Handle<v8::Function>::Cast(function), paramCount, params);
delete[] params;
id = DOMTimer::install(scriptContext, action, timeout, singleShot);
- } else
- // FIXME(fqian): what's the right return value if failed.
- return v8::Undefined();
+ } else {
+ id = DOMTimer::install(scriptContext, new ScheduledAction(V8Proxy::context(imp->frame()), functionString), timeout, singleShot);
+ }
return v8::Integer::New(id);
}
@@ -145,14 +159,37 @@ static v8::Handle<v8::Value> convertBase64(const String& str, bool encode)
ACCESSOR_GETTER(DOMWindowEvent)
{
+ v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, info.This());
+ if (holder.IsEmpty())
+ return v8::Undefined();
+
+ Frame* frame = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder)->frame();
+ if (!V8Proxy::canAccessFrame(frame, true))
+ return v8::Undefined();
+
+ v8::Local<v8::Context> context = V8Proxy::context(frame);
v8::Local<v8::String> eventSymbol = v8::String::NewSymbol("event");
- v8::Local<v8::Context> context = v8::Context::GetCurrent();
v8::Handle<v8::Value> jsEvent = context->Global()->GetHiddenValue(eventSymbol);
if (jsEvent.IsEmpty())
return v8::Undefined();
return jsEvent;
}
+ACCESSOR_SETTER(DOMWindowEvent)
+{
+ v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, info.This());
+ if (holder.IsEmpty())
+ return;
+
+ Frame* frame = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder)->frame();
+ if (!V8Proxy::canAccessFrame(frame, true))
+ return;
+
+ v8::Local<v8::Context> context = V8Proxy::context(frame);
+ v8::Local<v8::String> eventSymbol = v8::String::NewSymbol("event");
+ context->Global()->SetHiddenValue(eventSymbol, value);
+}
+
ACCESSOR_GETTER(DOMWindowCrypto)
{
// FIXME: Implement me.
@@ -161,11 +198,7 @@ ACCESSOR_GETTER(DOMWindowCrypto)
ACCESSOR_SETTER(DOMWindowLocation)
{
- v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, info.This());
- if (holder.IsEmpty())
- return;
-
- DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder);
+ DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, info.Holder());
WindowSetLocation(imp, toWebCoreString(value));
}
@@ -194,18 +227,42 @@ ACCESSOR_SETTER(DOMWindowOpener)
info.This()->Set(name, value);
}
+#if ENABLE(VIDEO)
+
+ACCESSOR_GETTER(DOMWindowAudio)
+{
+ DOMWindow* window = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, info.Holder());
+ return V8DOMWrapper::getConstructor(V8ClassIndex::AUDIO, window);
+}
+
+#endif
+
+ACCESSOR_GETTER(DOMWindowImage)
+{
+ DOMWindow* window = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, info.Holder());
+ return V8DOMWrapper::getConstructor(V8ClassIndex::IMAGE, window);
+}
+
+ACCESSOR_GETTER(DOMWindowOption)
+{
+ DOMWindow* window = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, info.Holder());
+ return V8DOMWrapper::getConstructor(V8ClassIndex::OPTION, window);
+}
+
CALLBACK_FUNC_DECL(DOMWindowAddEventListener)
{
INC_STATS("DOM.DOMWindow.addEventListener()");
+
+ String eventType = toWebCoreString(args[0]);
+ bool useCapture = args[2]->BooleanValue();
+
DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder());
if (!V8Proxy::canAccessFrame(imp->frame(), true))
return v8::Undefined();
- if (!imp->frame())
- return v8::Undefined(); // DOMWindow could be disconnected from the frame
-
- Document* doc = imp->frame()->document();
+ Document* doc = imp->document();
+
if (!doc)
return v8::Undefined();
@@ -214,12 +271,11 @@ CALLBACK_FUNC_DECL(DOMWindowAddEventListener)
if (!proxy)
return v8::Undefined();
- RefPtr<EventListener> listener = proxy->eventListeners()->findOrCreateWrapper<V8EventListener>(proxy->frame(), args[1], false);
+ RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(proxy, args[1], false, ListenerFindOrCreate);
if (listener) {
- String eventType = toWebCoreString(args[0]);
- bool useCapture = args[2]->BooleanValue();
imp->addEventListener(eventType, listener, useCapture);
+ createHiddenDependency(args.Holder(), args[1], V8Custom::kDOMWindowEventListenerCacheIndex);
}
return v8::Undefined();
@@ -229,15 +285,17 @@ CALLBACK_FUNC_DECL(DOMWindowAddEventListener)
CALLBACK_FUNC_DECL(DOMWindowRemoveEventListener)
{
INC_STATS("DOM.DOMWindow.removeEventListener()");
+
+ String eventType = toWebCoreString(args[0]);
+ bool useCapture = args[2]->BooleanValue();
+
DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder());
if (!V8Proxy::canAccessFrame(imp->frame(), true))
return v8::Undefined();
- if (!imp->frame())
- return v8::Undefined();
+ Document* doc = imp->document();
- Document* doc = imp->frame()->document();
if (!doc)
return v8::Undefined();
@@ -245,12 +303,11 @@ CALLBACK_FUNC_DECL(DOMWindowRemoveEventListener)
if (!proxy)
return v8::Undefined();
- RefPtr<EventListener> listener = proxy->eventListeners()->findWrapper(args[1], false);
+ RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(proxy, args[1], false, ListenerFindOnly);
if (listener) {
- String eventType = toWebCoreString(args[0]);
- bool useCapture = args[2]->BooleanValue();
imp->removeEventListener(eventType, listener.get(), useCapture);
+ removeHiddenDependency(args.Holder(), args[1], V8Custom::kDOMWindowEventListenerCacheIndex);
}
return v8::Undefined();
@@ -265,8 +322,8 @@ CALLBACK_FUNC_DECL(DOMWindowPostMessage)
ASSERT(source->frame());
v8::TryCatch tryCatch;
- String message = toWebCoreString(args[0]);
- MessagePort* port = 0;
+ RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(toWebCoreString(args[0]));
+ MessagePortArray portArray;
String targetOrigin;
// This function has variable arguments and can either be:
@@ -274,8 +331,8 @@ CALLBACK_FUNC_DECL(DOMWindowPostMessage)
// or
// postMessage(message, targetOrigin);
if (args.Length() > 2) {
- if (V8DOMWrapper::isWrapperOfType(args[1], V8ClassIndex::MESSAGEPORT))
- port = V8DOMWrapper::convertToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, v8::Handle<v8::Object>::Cast(args[1]));
+ if (!getMessagePortArray(args[1], portArray))
+ return v8::Undefined();
targetOrigin = toWebCoreStringWithNullOrUndefinedCheck(args[2]);
} else {
targetOrigin = toWebCoreStringWithNullOrUndefinedCheck(args[1]);
@@ -285,16 +342,18 @@ CALLBACK_FUNC_DECL(DOMWindowPostMessage)
return v8::Undefined();
ExceptionCode ec = 0;
- window->postMessage(message, port, targetOrigin, source, ec);
- if (ec)
- V8Proxy::setDOMException(ec);
-
- return v8::Undefined();
+ window->postMessage(message.release(), &portArray, targetOrigin, source, ec);
+ return throwError(ec);
}
CALLBACK_FUNC_DECL(DOMWindowAtob)
{
INC_STATS("DOM.DOMWindow.atob()");
+
+ if (args[0]->IsNull())
+ return v8String("");
+ String str = toWebCoreString(args[0]);
+
DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder());
if (!V8Proxy::canAccessFrame(imp->frame(), true))
@@ -303,16 +362,17 @@ CALLBACK_FUNC_DECL(DOMWindowAtob)
if (args.Length() < 1)
return throwError("Not enough arguments", V8Proxy::SyntaxError);
- if (args[0]->IsNull())
- return v8String("");
-
- String str = toWebCoreString(args[0]);
return convertBase64(str, false);
}
CALLBACK_FUNC_DECL(DOMWindowBtoa)
{
INC_STATS("DOM.DOMWindow.btoa()");
+
+ if (args[0]->IsNull())
+ return v8String("");
+ String str = toWebCoreString(args[0]);
+
DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder());
if (!V8Proxy::canAccessFrame(imp->frame(), true))
@@ -321,10 +381,6 @@ CALLBACK_FUNC_DECL(DOMWindowBtoa)
if (args.Length() < 1)
return throwError("Not enough arguments", V8Proxy::SyntaxError);
- if (args[0]->IsNull())
- return v8String("");
-
- String str = toWebCoreString(args[0]);
return convertBase64(str, true);
}
@@ -335,7 +391,10 @@ CALLBACK_FUNC_DECL(DOMWindowBtoa)
CALLBACK_FUNC_DECL(DOMWindowToString)
{
INC_STATS("DOM.DOMWindow.toString()");
- return args.This()->ObjectProtoToString();
+ v8::Handle<v8::Object> domWrapper = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, args.This());
+ if (domWrapper.IsEmpty())
+ return args.This()->ObjectProtoToString();
+ return domWrapper->ObjectProtoToString();
}
CALLBACK_FUNC_DECL(DOMWindowNOP)
@@ -344,84 +403,6 @@ CALLBACK_FUNC_DECL(DOMWindowNOP)
return v8::Undefined();
}
-static String eventNameFromAttributeName(const String& name)
-{
- ASSERT(name.startsWith("on"));
- String eventType = name.substring(2);
-
- if (eventType.startsWith("w")) {
- switch(eventType[eventType.length() - 1]) {
- case 't':
- eventType = "webkitAnimationStart";
- break;
- case 'n':
- eventType = "webkitAnimationIteration";
- break;
- case 'd':
- ASSERT(eventType.length() > 7);
- if (eventType[7] == 'a')
- eventType = "webkitAnimationEnd";
- else
- eventType = "webkitTransitionEnd";
- break;
- }
- }
-
- return eventType;
-}
-
-ACCESSOR_SETTER(DOMWindowEventHandler)
-{
- v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, info.This());
- if (holder.IsEmpty())
- return;
-
- DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder);
- if (!imp->frame())
- return;
-
- Document* doc = imp->frame()->document();
- if (!doc)
- return;
-
- String key = toWebCoreString(name);
- String eventType = eventNameFromAttributeName(key);
-
- if (value->IsNull()) {
- // Clear the event listener
- imp->clearAttributeEventListener(eventType);
- } else {
- V8Proxy* proxy = V8Proxy::retrieve(imp->frame());
- if (!proxy)
- return;
-
- RefPtr<EventListener> listener = proxy->eventListeners()->findOrCreateWrapper<V8EventListener>(proxy->frame(), value, true);
- if (listener)
- imp->setAttributeEventListener(eventType, listener);
- }
-}
-
-ACCESSOR_GETTER(DOMWindowEventHandler)
-{
- v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, info.This());
- if (holder.IsEmpty())
- return v8::Undefined();
-
- DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder);
- if (!imp->frame())
- return v8::Undefined();
-
- Document* doc = imp->frame()->document();
- if (!doc)
- return v8::Undefined();
-
- String key = toWebCoreString(name);
- String eventType = eventNameFromAttributeName(key);
-
- EventListener* listener = imp->getAttributeEventListener(eventType);
- return V8DOMWrapper::convertEventListenerToV8Object(listener);
-}
-
static bool canShowModalDialogNow(const Frame* frame)
{
// A frame can out live its page. See bug 1219613.
@@ -512,7 +493,7 @@ static Frame* createWindow(Frame* callingFrame,
return 0;
newFrame->loader()->setOpener(openerFrame);
- newFrame->loader()->setOpenedByDOM();
+ newFrame->page()->setOpenedByDOM();
// Set dialog arguments on the global object of the new frame.
if (!dialogArgs.IsEmpty()) {
@@ -525,13 +506,13 @@ static Frame* createWindow(Frame* callingFrame,
if (protocolIsJavaScript(url) || ScriptController::isSafeScript(newFrame)) {
KURL completedUrl =
- url.isEmpty() ? KURL("") : completeURL(url);
+ url.isEmpty() ? KURL(ParsedURLString, "") : completeURL(url);
bool userGesture = processingUserGesture();
if (created)
newFrame->loader()->changeLocation(completedUrl, referrer, false, false, userGesture);
else if (!url.isEmpty())
- newFrame->loader()->scheduleLocationChange(completedUrl.string(), referrer, false, userGesture);
+ newFrame->redirectScheduler()->scheduleLocationChange(completedUrl.string(), referrer, false, userGesture);
}
return newFrame;
@@ -542,11 +523,16 @@ static Frame* createWindow(Frame* callingFrame,
CALLBACK_FUNC_DECL(DOMWindowShowModalDialog)
{
INC_STATS("DOM.DOMWindow.showModalDialog()");
+
+ String url = toWebCoreStringWithNullOrUndefinedCheck(args[0]);
+ v8::Local<v8::Value> dialogArgs = args[1];
+ String featureArgs = toWebCoreStringWithNullOrUndefinedCheck(args[2]);
+
DOMWindow* window = V8DOMWrapper::convertToNativeObject<DOMWindow>(
V8ClassIndex::DOMWINDOW, args.Holder());
Frame* frame = window->frame();
- if (!frame || !V8Proxy::canAccessFrame(frame, true))
+ if (!V8Proxy::canAccessFrame(frame, true))
return v8::Undefined();
Frame* callingFrame = V8Proxy::retrieveFrameForCallingContext();
@@ -560,10 +546,6 @@ CALLBACK_FUNC_DECL(DOMWindowShowModalDialog)
if (!canShowModalDialogNow(frame) || !allowPopUp())
return v8::Undefined();
- String url = toWebCoreStringWithNullOrUndefinedCheck(args[0]);
- v8::Local<v8::Value> dialogArgs = args[1];
- String featureArgs = toWebCoreStringWithNullOrUndefinedCheck(args[2]);
-
const HashMap<String, String> features = parseModalDialogFeatures(featureArgs);
const bool trusted = false;
@@ -631,10 +613,14 @@ CALLBACK_FUNC_DECL(DOMWindowShowModalDialog)
CALLBACK_FUNC_DECL(DOMWindowOpen)
{
INC_STATS("DOM.DOMWindow.open()");
+
+ String urlString = toWebCoreStringWithNullOrUndefinedCheck(args[0]);
+ AtomicString frameName = (args[1]->IsUndefined() || args[1]->IsNull()) ? "_blank" : AtomicString(toWebCoreString(args[1]));
+
DOMWindow* parent = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, args.Holder());
Frame* frame = parent->frame();
- if (!frame || !V8Proxy::canAccessFrame(frame, true))
+ if (!V8Proxy::canAccessFrame(frame, true))
return v8::Undefined();
Frame* callingFrame = V8Proxy::retrieveFrameForCallingContext();
@@ -649,9 +635,6 @@ CALLBACK_FUNC_DECL(DOMWindowOpen)
if (!page)
return v8::Undefined();
- String urlString = toWebCoreStringWithNullOrUndefinedCheck(args[0]);
- AtomicString frameName = (args[1]->IsUndefined() || args[1]->IsNull()) ? "_blank" : AtomicString(toWebCoreString(args[1]));
-
// Because FrameTree::find() returns true for empty strings, we must check
// for empty framenames. Otherwise, illegitimate window.open() calls with
// no name will pass right through the popup blocker.
@@ -687,7 +670,7 @@ CALLBACK_FUNC_DECL(DOMWindowOpen)
// the outgoingReferrer. We replicate that behavior here.
String referrer = enteredFrame->loader()->outgoingReferrer();
- frame->loader()->scheduleLocationChange(completedUrl, referrer, false, userGesture);
+ frame->redirectScheduler()->scheduleLocationChange(completedUrl, referrer, false, userGesture);
}
return V8DOMWrapper::convertToV8Object(V8ClassIndex::DOMWINDOW, frame->domWindow());
}
@@ -756,11 +739,8 @@ CALLBACK_FUNC_DECL(DOMWindowOpen)
INDEXED_PROPERTY_GETTER(DOMWindow)
{
INC_STATS("DOM.DOMWindow.IndexedPropertyGetter");
- v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, info.This());
- if (holder.IsEmpty())
- return notHandledByInterceptor();
- DOMWindow* window = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder);
+ DOMWindow* window = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, info.Holder());
if (!window)
return notHandledByInterceptor();
@@ -780,11 +760,8 @@ NAMED_PROPERTY_GETTER(DOMWindow)
{
INC_STATS("DOM.DOMWindow.NamedPropertyGetter");
- v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, info.This());
- if (holder.IsEmpty())
- return notHandledByInterceptor();
-
- DOMWindow* window = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder);
+ // TODO(antonm): investigate what convertToNativeObject does for the case of DOMWINDOW.
+ DOMWindow* window = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, info.Holder());
if (!window)
return notHandledByInterceptor();
@@ -800,12 +777,13 @@ NAMED_PROPERTY_GETTER(DOMWindow)
return V8DOMWrapper::convertToV8Object(V8ClassIndex::DOMWINDOW, child->domWindow());
// Search IDL functions defined in the prototype
- v8::Handle<v8::Value> result = holder->GetRealNamedPropertyInPrototypeChain(name);
+ v8::Handle<v8::Value> result = info.Holder()->GetRealNamedProperty(name);
if (!result.IsEmpty())
return result;
// Search named items in the document.
Document* doc = frame->document();
+
if (doc) {
RefPtr<HTMLCollection> items = doc->windowNamedItems(propName);
if (items->length() >= 1) {
@@ -826,13 +804,13 @@ void V8Custom::WindowSetLocation(DOMWindow* window, const String& relativeURL)
if (!frame)
return;
- if (!shouldAllowNavigation(frame))
- return;
-
KURL url = completeURL(relativeURL);
if (url.isNull())
return;
+ if (!shouldAllowNavigation(frame))
+ return;
+
navigateIfAllowed(frame, url, false, false);
}
@@ -853,12 +831,15 @@ CALLBACK_FUNC_DECL(DOMWindowSetInterval)
void V8Custom::ClearTimeoutImpl(const v8::Arguments& args)
{
+ int handle = toInt32(args[0]);
+
v8::Handle<v8::Object> holder = args.Holder();
DOMWindow* imp = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, holder);
if (!V8Proxy::canAccessFrame(imp->frame(), true))
return;
- ScriptExecutionContext* context = static_cast<ScriptExecutionContext*>(imp->frame()->document());
- int handle = toInt32(args[0]);
+ ScriptExecutionContext* context = static_cast<ScriptExecutionContext*>(imp->document());
+ if (!context)
+ return;
DOMTimer::removeById(context, handle);
}
diff --git a/WebCore/bindings/v8/custom/V8DatabaseCustom.cpp b/WebCore/bindings/v8/custom/V8DatabaseCustom.cpp
index 300e829..9ddd620 100644
--- a/WebCore/bindings/v8/custom/V8DatabaseCustom.cpp
+++ b/WebCore/bindings/v8/custom/V8DatabaseCustom.cpp
@@ -45,13 +45,50 @@ namespace WebCore {
CALLBACK_FUNC_DECL(DatabaseChangeVersion)
{
INC_STATS("DOM.Database.changeVersion()");
+
+ if (args.Length() < 2)
+ return throwError("The old and new version strings are required.", V8Proxy::SyntaxError);
+
+ if (!(args[0]->IsString() && args[1]->IsString()))
+ return throwError("The old and new versions must be strings.");
+
+ Database* database = V8DOMWrapper::convertToNativeObject<Database>(V8ClassIndex::DATABASE, args.Holder());
+
+ Frame* frame = V8Proxy::retrieveFrameForCurrentContext();
+ if (!frame)
+ return v8::Undefined();
+
+ RefPtr<V8CustomSQLTransactionCallback> callback;
+ if (args.Length() > 2) {
+ if (!args[2]->IsObject())
+ return throwError("changeVersion transaction callback must be of valid type.");
+
+ callback = V8CustomSQLTransactionCallback::create(args[2], frame);
+ }
+
+ RefPtr<V8CustomSQLTransactionErrorCallback> errorCallback;
+ if (args.Length() > 3) {
+ if (!args[3]->IsObject())
+ return throwError("changeVersion error callback must be of valid type.");
+
+ errorCallback = V8CustomSQLTransactionErrorCallback::create(args[3], frame);
+ }
+
+ RefPtr<V8CustomVoidCallback> successCallback;
+ if (args.Length() > 4) {
+ if (!args[4]->IsObject())
+ return throwError("changeVersion success callback must be of valid type.");
+
+ successCallback = V8CustomVoidCallback::create(args[4], frame);
+ }
+
+ database->changeVersion(toWebCoreString(args[0]), toWebCoreString(args[1]), callback.release(), errorCallback.release(), successCallback.release());
+
return v8::Undefined();
}
-CALLBACK_FUNC_DECL(DatabaseTransaction)
+static v8::Handle<v8::Value> createTransaction(const v8::Arguments& args, bool readOnly)
{
- INC_STATS("DOM.Database.transaction()");
-
if (!args.Length())
return throwError("Transaction callback is required.", V8Proxy::SyntaxError);
@@ -76,18 +113,28 @@ CALLBACK_FUNC_DECL(DatabaseTransaction)
RefPtr<V8CustomVoidCallback> successCallback;
if (args.Length() > 2) {
- if (!args[1]->IsObject())
+ if (!args[2]->IsObject())
return throwError("Transaction success callback must be of valid type.");
successCallback = V8CustomVoidCallback::create(args[2], frame);
}
- database->transaction(callback.release(), errorCallback.release(), successCallback.release());
-
+ database->transaction(callback.release(), errorCallback.release(), successCallback.release(), readOnly);
return v8::Undefined();
}
+CALLBACK_FUNC_DECL(DatabaseTransaction)
+{
+ INC_STATS("DOM.Database.transaction()");
+ return createTransaction(args, false);
+}
+
+CALLBACK_FUNC_DECL(DatabaseReadTransaction)
+{
+ INC_STATS("DOM.Database.readTransaction()");
+ return createTransaction(args, true);
+}
+
} // namespace WebCore
#endif
-
diff --git a/WebCore/bindings/v8/custom/V8DedicatedWorkerContextCustom.cpp b/WebCore/bindings/v8/custom/V8DedicatedWorkerContextCustom.cpp
index f13e45e..263c005 100644
--- a/WebCore/bindings/v8/custom/V8DedicatedWorkerContextCustom.cpp
+++ b/WebCore/bindings/v8/custom/V8DedicatedWorkerContextCustom.cpp
@@ -35,48 +35,26 @@
#include "WorkerContextExecutionProxy.h"
#include "DedicatedWorkerContext.h"
+#include "V8Binding.h"
+#include "V8MessagePortCustom.h"
#include "V8Proxy.h"
#include "V8WorkerContextEventListener.h"
namespace WebCore {
-ACCESSOR_GETTER(DedicatedWorkerContextOnmessage)
+CALLBACK_FUNC_DECL(DedicatedWorkerContextPostMessage)
{
- INC_STATS(L"DOM.DedicatedWorkerContext.onmessage._get");
- DedicatedWorkerContext* workerContext = V8DOMWrapper::convertToNativeObject<DedicatedWorkerContext>(V8ClassIndex::DEDICATEDWORKERCONTEXT, info.Holder());
- if (workerContext->onmessage()) {
- V8WorkerContextEventListener* listener = static_cast<V8WorkerContextEventListener*>(workerContext->onmessage());
- v8::Local<v8::Object> v8Listener = listener->getListenerObject();
- return v8Listener;
- }
- return v8::Undefined();
-}
-
-ACCESSOR_SETTER(DedicatedWorkerContextOnmessage)
-{
- INC_STATS(L"DOM.DedicatedWorkerContext.onmessage._set");
- DedicatedWorkerContext* workerContext = V8DOMWrapper::convertToNativeObject<DedicatedWorkerContext>(V8ClassIndex::DEDICATEDWORKERCONTEXT, info.Holder());
- V8WorkerContextEventListener* oldListener = static_cast<V8WorkerContextEventListener*>(workerContext->onmessage());
- if (value->IsNull()) {
- if (workerContext->onmessage()) {
- v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject();
- removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kDedicatedWorkerContextRequestCacheIndex);
- }
-
- // Clear the listener.
- workerContext->setOnmessage(0);
- } else {
- RefPtr<V8EventListener> listener = workerContext->script()->proxy()->findOrCreateEventListener(v8::Local<v8::Object>::Cast(value), false, false);
- if (listener) {
- if (oldListener) {
- v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject();
- removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kDedicatedWorkerContextRequestCacheIndex);
- }
-
- workerContext->setOnmessage(listener);
- createHiddenDependency(info.Holder(), value, V8Custom::kDedicatedWorkerContextRequestCacheIndex);
- }
+ INC_STATS(L"DOM.DedicatedWorkerContext.postMessage");
+ DedicatedWorkerContext* workerContext = V8DOMWrapper::convertToNativeObject<DedicatedWorkerContext>(V8ClassIndex::DEDICATEDWORKERCONTEXT, args.Holder());
+ RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(v8ValueToWebCoreString(args[0]));
+ MessagePortArray portArray;
+ if (args.Length() > 1) {
+ if (!getMessagePortArray(args[1], portArray))
+ return v8::Undefined();
}
+ ExceptionCode ec = 0;
+ workerContext->postMessage(message.release(), &portArray, ec);
+ return throwError(ec);
}
} // namespace WebCore
diff --git a/WebCore/bindings/v8/custom/V8DocumentCustom.cpp b/WebCore/bindings/v8/custom/V8DocumentCustom.cpp
index 80d204b..8b77a3a 100644
--- a/WebCore/bindings/v8/custom/V8DocumentCustom.cpp
+++ b/WebCore/bindings/v8/custom/V8DocumentCustom.cpp
@@ -31,10 +31,12 @@
#include "config.h"
#include "Document.h"
+#include "CanvasRenderingContext.h"
#include "ExceptionCode.h"
#include "Node.h"
#include "XPathNSResolver.h"
#include "XPathResult.h"
+#include "CanvasRenderingContext.h"
#include "V8Binding.h"
#include "V8CustomBinding.h"
@@ -62,12 +64,8 @@ CALLBACK_FUNC_DECL(DocumentEvaluate)
if (V8Node::HasInstance(args[1]))
contextNode = V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[1]));
- RefPtr<XPathNSResolver> resolver;
- if (V8XPathNSResolver::HasInstance(args[2]))
- resolver = V8DOMWrapper::convertToNativeObject<XPathNSResolver>(V8ClassIndex::XPATHNSRESOLVER, v8::Handle<v8::Object>::Cast(args[2]));
- else if (args[2]->IsObject())
- resolver = V8CustomXPathNSResolver::create(args[2]->ToObject());
- else if (!args[2]->IsNull() && !args[2]->IsUndefined())
+ RefPtr<XPathNSResolver> resolver = V8DOMWrapper::getXPathNSResolver(args[2]);
+ if (!resolver && !args[2]->IsNull() && !args[2]->IsUndefined())
return throwError(TYPE_MISMATCH_ERR);
int type = toInt32(args[3]);
@@ -99,8 +97,17 @@ CALLBACK_FUNC_DECL(DocumentGetCSSCanvasContext)
String name = toWebCoreString(args[1]);
int width = toInt32(args[2]);
int height = toInt32(args[3]);
- CanvasRenderingContext2D* result = imp->getCSSCanvasContext(contextId, name, width, height);
- return V8DOMWrapper::convertToV8Object(V8ClassIndex::CANVASRENDERINGCONTEXT2D, result);
+ CanvasRenderingContext* result = imp->getCSSCanvasContext(contextId, name, width, height);
+ if (!result)
+ return v8::Undefined();
+ if (result->is2d())
+ return V8DOMWrapper::convertToV8Object(V8ClassIndex::CANVASRENDERINGCONTEXT2D, result);
+#if ENABLE(3D_CANVAS)
+ else if (result->is3d())
+ return V8DOMWrapper::convertToV8Object(V8ClassIndex::CANVASRENDERINGCONTEXT3D, result);
+#endif // ENABLE(3D_CANVAS)
+ ASSERT_NOT_REACHED();
+ return v8::Undefined();
}
} // namespace WebCore
diff --git a/WebCore/bindings/v8/V8WorkerContextObjectEventListener.cpp b/WebCore/bindings/v8/custom/V8FileListCustom.cpp
index ce56563..bc533cf 100644
--- a/WebCore/bindings/v8/V8WorkerContextObjectEventListener.cpp
+++ b/WebCore/bindings/v8/custom/V8FileListCustom.cpp
@@ -29,31 +29,26 @@
*/
#include "config.h"
+#include "FileList.h"
-#if ENABLE(WORKERS)
+#include "File.h"
+#include "V8Binding.h"
+#include "V8CustomBinding.h"
+#include "V8Proxy.h"
-#include "V8WorkerContextObjectEventListener.h"
-
-#include "WorkerContextExecutionProxy.h"
+#include <wtf/RefPtr.h>
namespace WebCore {
-static void weakObjectEventListenerCallback(v8::Persistent<v8::Value>, void* parameter)
+INDEXED_PROPERTY_GETTER(FileList)
{
- V8WorkerContextObjectEventListener* listener = static_cast<V8WorkerContextObjectEventListener*>(parameter);
-
- // Remove the wrapper
- listener->proxy()->removeEventListener(listener);
-
- listener->disposeListenerObject();
-}
+ INC_STATS("DOM.FileList.IndexedPropertyGetter");
+ FileList* fileList = V8DOMWrapper::convertToNativeObject<FileList>(V8ClassIndex::FILELIST, info.Holder());
+ RefPtr<File> file = fileList->item(index);
+ if (!file)
+ return notHandledByInterceptor();
-V8WorkerContextObjectEventListener::V8WorkerContextObjectEventListener(WorkerContextExecutionProxy* proxy, v8::Local<v8::Object> listener, bool isInline)
- : V8WorkerContextEventListener(proxy, listener, isInline)
-{
- m_listener.MakeWeak(this, weakObjectEventListenerCallback);
+ return V8DOMWrapper::convertToV8Object(V8ClassIndex::FILE, file.release());
}
} // namespace WebCore
-
-#endif // WORKERS
diff --git a/WebCore/bindings/v8/custom/V8GeolocationCustom.cpp b/WebCore/bindings/v8/custom/V8GeolocationCustom.cpp
index 7bc687c..b4fd9f5 100644
--- a/WebCore/bindings/v8/custom/V8GeolocationCustom.cpp
+++ b/WebCore/bindings/v8/custom/V8GeolocationCustom.cpp
@@ -130,13 +130,7 @@ static PassRefPtr<PositionOptions> createPositionOptions(v8::Local<v8::Value> va
return 0;
}
double timeoutDouble = timeoutNumber->Value();
- // V8 does not export a public symbol for infinity, so we must use a
- // platform type. On Android, it seems that V8 uses 0xf70f000000000000,
- // which is the standard way to represent infinity in a double. However,
- // numeric_limits<double>::infinity uses the system HUGE_VAL, which is
- // different. Therefore we test using isinf() and check that the value
- // is positive, which seems to handle things correctly.
- // If the value is infinity, there's nothing to do.
+ // If the value is positive infinity, there's nothing to do.
if (!(isinf(timeoutDouble) && timeoutDouble > 0)) {
v8::Local<v8::Int32> timeoutInt32 = timeoutValue->ToInt32();
if (timeoutInt32.IsEmpty()) {
@@ -161,7 +155,7 @@ static PassRefPtr<PositionOptions> createPositionOptions(v8::Local<v8::Value> va
}
double maximumAgeDouble = maximumAgeNumber->Value();
if (isinf(maximumAgeDouble) && maximumAgeDouble > 0) {
- // If the value is infinity, clear maximumAge.
+ // If the value is positive infinity, clear maximumAge.
options->clearMaximumAge();
} else {
v8::Local<v8::Int32> maximumAgeInt32 = maximumAgeValue->ToInt32();
diff --git a/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.cpp b/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.cpp
index 6f9b761..c735c49 100644
--- a/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.cpp
+++ b/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.cpp
@@ -29,8 +29,9 @@
*/
#include "config.h"
-#include "HTMLAudioElement.h"
+#include "V8HTMLAudioElementConstructor.h"
+#include "HTMLAudioElement.h"
#include "Document.h"
#include "Frame.h"
#include "HTMLNames.h"
@@ -42,6 +43,24 @@
namespace WebCore {
+v8::Persistent<v8::FunctionTemplate> V8HTMLAudioElementConstructor::GetTemplate()
+{
+ static v8::Persistent<v8::FunctionTemplate> cachedTemplate;
+ if (!cachedTemplate.IsEmpty())
+ return cachedTemplate;
+
+ v8::HandleScope scope;
+ v8::Local<v8::FunctionTemplate> result = v8::FunctionTemplate::New(USE_CALLBACK(HTMLAudioElementConstructor));
+
+ v8::Local<v8::ObjectTemplate> instance = result->InstanceTemplate();
+ instance->SetInternalFieldCount(V8Custom::kNodeMinimumInternalFieldCount);
+ result->SetClassName(v8::String::New("HTMLAudioElement"));
+ result->Inherit(V8DOMWrapper::getTemplate(V8ClassIndex::HTMLAUDIOELEMENT));
+
+ cachedTemplate = v8::Persistent<v8::FunctionTemplate>::New(result);
+ return cachedTemplate;
+}
+
CALLBACK_FUNC_DECL(HTMLAudioElementConstructor)
{
INC_STATS("DOM.HTMLAudioElement.Contructor");
diff --git a/WebCore/bindings/js/JSSharedWorkerContextCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.h
index dca3536..ac4b46d 100644..100755
--- a/WebCore/bindings/js/JSSharedWorkerContextCustom.cpp
+++ b/WebCore/bindings/v8/custom/V8HTMLAudioElementConstructor.h
@@ -28,23 +28,20 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "config.h"
+#ifndef V8HTMLAudioElementConstructor_h
+#define V8HTMLAudioElementConstructor_h
-#if ENABLE(SHARED_WORKERS)
-
-#include "JSSharedWorkerContext.h"
-
-using namespace JSC;
+#include <v8.h>
namespace WebCore {
-void JSSharedWorkerContext::markChildren(MarkStack& markStack)
-{
- Base::markChildren(markStack);
+class V8HTMLAudioElementConstructor {
+private:
+ static v8::Persistent<v8::FunctionTemplate> GetTemplate();
- markIfNotNull(markStack, impl()->onconnect());
-}
+ friend class V8ClassIndex;
+};
-} // namespace WebCore
+}
-#endif // ENABLE(SHARED_WORKERS)
+#endif // V8HTMLAudioElementConstructor_h
diff --git a/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp
index 6ba9367..4116673 100644
--- a/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp
+++ b/WebCore/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp
@@ -30,7 +30,9 @@
#include "config.h"
#include "HTMLCanvasElement.h"
+#include "CanvasRenderingContext.h"
+#include "CanvasRenderingContext.h"
#include "V8Binding.h"
#include "V8CustomBinding.h"
#include "V8Node.h"
@@ -44,8 +46,17 @@ CALLBACK_FUNC_DECL(HTMLCanvasElementGetContext)
v8::Handle<v8::Object> holder = args.Holder();
HTMLCanvasElement* imp = V8DOMWrapper::convertDOMWrapperToNode<HTMLCanvasElement>(holder);
String contextId = toWebCoreString(args[0]);
- CanvasRenderingContext2D* result = imp->getContext(contextId);
- return V8DOMWrapper::convertToV8Object(V8ClassIndex::CANVASRENDERINGCONTEXT2D, result);
+ CanvasRenderingContext* result = imp->getContext(contextId);
+ if (!result)
+ return v8::Undefined();
+ if (result->is2d())
+ return V8DOMWrapper::convertToV8Object(V8ClassIndex::CANVASRENDERINGCONTEXT2D, result);
+#if ENABLE(3D_CANVAS)
+ else if (result->is3d())
+ return V8DOMWrapper::convertToV8Object(V8ClassIndex::CANVASRENDERINGCONTEXT3D, result);
+#endif
+ ASSERT_NOT_REACHED();
+ return v8::Undefined();
}
} // namespace WebCore
diff --git a/WebCore/bindings/v8/custom/V8HTMLFrameElementCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLFrameElementCustom.cpp
index 4f865dd..2f55758 100644
--- a/WebCore/bindings/v8/custom/V8HTMLFrameElementCustom.cpp
+++ b/WebCore/bindings/v8/custom/V8HTMLFrameElementCustom.cpp
@@ -30,6 +30,7 @@
#include "config.h"
#include "HTMLFrameElement.h"
+#include "HTMLNames.h"
#include "V8Binding.h"
#include "V8CustomBinding.h"
@@ -37,6 +38,8 @@
namespace WebCore {
+using namespace HTMLNames;
+
ACCESSOR_SETTER(HTMLFrameElementSrc)
{
HTMLFrameElement* frame = V8DOMWrapper::convertDOMWrapperToNode<HTMLFrameElement>(info.Holder());
@@ -45,7 +48,7 @@ ACCESSOR_SETTER(HTMLFrameElementSrc)
if (!allowSettingFrameSrcToJavascriptUrl(frame, srcValue))
return;
- frame->setSrc(srcValue);
+ frame->setAttribute(srcAttr, srcValue);
}
ACCESSOR_SETTER(HTMLFrameElementLocation)
diff --git a/WebCore/bindings/v8/custom/V8HTMLIFrameElementCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLIFrameElementCustom.cpp
index ce2c29a..a4863e8 100644
--- a/WebCore/bindings/v8/custom/V8HTMLIFrameElementCustom.cpp
+++ b/WebCore/bindings/v8/custom/V8HTMLIFrameElementCustom.cpp
@@ -30,6 +30,7 @@
#include "config.h"
#include "HTMLIFrameElement.h"
+#include "HTMLNames.h"
#include "V8Binding.h"
#include "V8CustomBinding.h"
@@ -37,6 +38,8 @@
namespace WebCore {
+using namespace HTMLNames;
+
ACCESSOR_SETTER(HTMLIFrameElementSrc)
{
HTMLIFrameElement* iframe = V8DOMWrapper::convertDOMWrapperToNode<HTMLIFrameElement>(info.Holder());
@@ -45,7 +48,7 @@ ACCESSOR_SETTER(HTMLIFrameElementSrc)
if (!allowSettingFrameSrcToJavascriptUrl(iframe, v))
return;
- iframe->setSrc(v);
+ iframe->setAttribute(srcAttr, v);
}
} // namespace WebCore
diff --git a/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.cpp b/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.cpp
index 91ebd5f..71c99cf 100644
--- a/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.cpp
+++ b/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.cpp
@@ -29,8 +29,9 @@
*/
#include "config.h"
-#include "HTMLImageElement.h"
+#include "V8HTMLImageElementConstructor.h"
+#include "HTMLImageElement.h"
#include "Document.h"
#include "Frame.h"
#include "HTMLNames.h"
@@ -42,6 +43,24 @@
namespace WebCore {
+v8::Persistent<v8::FunctionTemplate> V8HTMLImageElementConstructor::GetTemplate()
+{
+ static v8::Persistent<v8::FunctionTemplate> cachedTemplate;
+ if (!cachedTemplate.IsEmpty())
+ return cachedTemplate;
+
+ v8::HandleScope scope;
+ v8::Local<v8::FunctionTemplate> result = v8::FunctionTemplate::New(USE_CALLBACK(HTMLImageElementConstructor));
+
+ v8::Local<v8::ObjectTemplate> instance = result->InstanceTemplate();
+ instance->SetInternalFieldCount(V8Custom::kNodeMinimumInternalFieldCount);
+ result->SetClassName(v8::String::New("HTMLImageElement"));
+ result->Inherit(V8DOMWrapper::getTemplate(V8ClassIndex::HTMLIMAGEELEMENT));
+
+ cachedTemplate = v8::Persistent<v8::FunctionTemplate>::New(result);
+ return cachedTemplate;
+}
+
CALLBACK_FUNC_DECL(HTMLImageElementConstructor)
{
INC_STATS("DOM.HTMLImageElement.Contructor");
diff --git a/WebCore/bindings/v8/V8WorkerContextObjectEventListener.h b/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.h
index 6471637..cdce0e0 100644..100755
--- a/WebCore/bindings/v8/V8WorkerContextObjectEventListener.h
+++ b/WebCore/bindings/v8/custom/V8HTMLImageElementConstructor.h
@@ -28,32 +28,20 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef V8WorkerContextObjectEventListener_h
-#define V8WorkerContextObjectEventListener_h
+#ifndef V8HTMLImageElementConstructor_h
+#define V8HTMLImageElementConstructor_h
-#if ENABLE(WORKERS)
-
-#include "V8WorkerContextEventListener.h"
#include <v8.h>
-#include <wtf/PassRefPtr.h>
namespace WebCore {
- class WorkerContextExecutionProxy;
-
- class V8WorkerContextObjectEventListener : public V8WorkerContextEventListener {
- public:
- static PassRefPtr<V8WorkerContextObjectEventListener> create(WorkerContextExecutionProxy* proxy, v8::Local<v8::Object> listener, bool isInline)
- {
- return adoptRef(new V8WorkerContextObjectEventListener(proxy, listener, isInline));
- }
-
+ class V8HTMLImageElementConstructor {
private:
- V8WorkerContextObjectEventListener(WorkerContextExecutionProxy*, v8::Local<v8::Object> listener, bool isInline);
- };
+ static v8::Persistent<v8::FunctionTemplate> GetTemplate();
-} // namespace WebCore
+ friend class V8ClassIndex;
+ };
-#endif // WORKERS
+}
-#endif // V8WorkerContextObjectEventListener_h
+#endif // V8HTMLImageElementConstructor_h
diff --git a/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.cpp b/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.cpp
index c22d127..f9c9cb4 100644
--- a/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.cpp
+++ b/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.cpp
@@ -29,8 +29,9 @@
*/
#include "config.h"
-#include "HTMLOptionElement.h"
+#include "V8HTMLOptionElementConstructor.h"
+#include "HTMLOptionElement.h"
#include "Document.h"
#include "Frame.h"
#include "HTMLNames.h"
@@ -43,6 +44,24 @@
namespace WebCore {
+v8::Persistent<v8::FunctionTemplate> V8HTMLOptionElementConstructor::GetTemplate()
+{
+ static v8::Persistent<v8::FunctionTemplate> cachedTemplate;
+ if (!cachedTemplate.IsEmpty())
+ return cachedTemplate;
+
+ v8::HandleScope scope;
+ v8::Local<v8::FunctionTemplate> result = v8::FunctionTemplate::New(USE_CALLBACK(HTMLOptionElementConstructor));
+
+ v8::Local<v8::ObjectTemplate> instance = result->InstanceTemplate();
+ instance->SetInternalFieldCount(V8Custom::kNodeMinimumInternalFieldCount);
+ result->SetClassName(v8::String::New("HTMLOptionElement"));
+ result->Inherit(V8DOMWrapper::getTemplate(V8ClassIndex::HTMLOPTIONELEMENT));
+
+ cachedTemplate = v8::Persistent<v8::FunctionTemplate>::New(result);
+ return cachedTemplate;
+}
+
CALLBACK_FUNC_DECL(HTMLOptionElementConstructor)
{
INC_STATS("DOM.HTMLOptionElement.Contructor");
diff --git a/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.h b/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.h
new file mode 100755
index 0000000..70076a5
--- /dev/null
+++ b/WebCore/bindings/v8/custom/V8HTMLOptionElementConstructor.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef V8HTMLOptionElementConstructor_h
+#define V8HTMLOptionElementConstructor_h
+
+#include <v8.h>
+
+namespace WebCore {
+
+ class V8HTMLOptionElementConstructor {
+ private:
+ static v8::Persistent<v8::FunctionTemplate> GetTemplate();
+
+ friend class V8ClassIndex;
+ };
+
+}
+
+#endif // V8HTMLOptionElementConstructor_h
diff --git a/WebCore/bindings/v8/custom/V8InspectorBackendCustom.cpp b/WebCore/bindings/v8/custom/V8InspectorBackendCustom.cpp
index 2571df4..ec9b034 100644
--- a/WebCore/bindings/v8/custom/V8InspectorBackendCustom.cpp
+++ b/WebCore/bindings/v8/custom/V8InspectorBackendCustom.cpp
@@ -31,6 +31,7 @@
#include "config.h"
#include "InspectorBackend.h"
+#include "Database.h"
#include "DOMWindow.h"
#include "Frame.h"
#include "FrameLoader.h"
@@ -57,13 +58,8 @@ CALLBACK_FUNC_DECL(InspectorBackendHighlightDOMNode)
if (args.Length() < 1)
return v8::Undefined();
- Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0]));
- if (!node)
- return v8::Undefined();
-
InspectorBackend* inspectorBackend = V8DOMWrapper::convertToNativeObject<InspectorBackend>(V8ClassIndex::INSPECTORBACKEND, args.Holder());
- inspectorBackend->highlight(node);
-
+ inspectorBackend->highlight(args[0]->ToInt32()->Value());
return v8::Undefined();
}
@@ -107,11 +103,17 @@ CALLBACK_FUNC_DECL(InspectorBackendSearch)
}
#if ENABLE(DATABASE)
-CALLBACK_FUNC_DECL(InspectorBackendDatabaseTableNames)
+CALLBACK_FUNC_DECL(InspectorBackendDatabaseForId)
{
- INC_STATS("InspectorBackend.databaseTableNames()");
- v8::Local<v8::Array> result = v8::Array::New(0);
- return result;
+ INC_STATS("InspectorBackend.databaseForId()");
+ if (args.Length() < 1)
+ return v8::Undefined();
+
+ InspectorBackend* inspectorBackend = V8DOMWrapper::convertToNativeObject<InspectorBackend>(V8ClassIndex::INSPECTORBACKEND, args.Holder());
+ Database* database = inspectorBackend->databaseForId(args[0]->ToInt32()->Value());
+ if (!database)
+ return v8::Undefined();
+ return V8DOMWrapper::convertToV8Object<Database>(V8ClassIndex::DATABASE, database);
}
#endif
@@ -215,4 +217,90 @@ CALLBACK_FUNC_DECL(InspectorBackendWrapCallback)
return args[0];
}
+CALLBACK_FUNC_DECL(InspectorBackendNodeForId)
+{
+ INC_STATS("InspectorBackend.nodeForId()");
+ if (args.Length() < 1)
+ return v8::Undefined();
+
+ InspectorBackend* inspectorBackend = V8DOMWrapper::convertToNativeObject<InspectorBackend>(V8ClassIndex::INSPECTORBACKEND, args.Holder());
+
+ Node* node = inspectorBackend->nodeForId(args[0]->ToInt32()->Value());
+ if (!node)
+ return v8::Undefined();
+
+ InspectorController* ic = inspectorBackend->inspectorController();
+ if (!ic)
+ return v8::Undefined();
+
+ return V8DOMWrapper::convertToV8Object(V8ClassIndex::NODE, node);
+}
+
+CALLBACK_FUNC_DECL(InspectorBackendWrapObject)
+{
+ INC_STATS("InspectorBackend.wrapObject()");
+ if (args.Length() < 2)
+ return v8::Undefined();
+
+ InspectorBackend* inspectorBackend = V8DOMWrapper::convertToNativeObject<InspectorBackend>(V8ClassIndex::INSPECTORBACKEND, args.Holder());
+ return inspectorBackend->wrapObject(ScriptValue(args[0]), toWebCoreStringWithNullCheck(args[1])).v8Value();
+}
+
+CALLBACK_FUNC_DECL(InspectorBackendUnwrapObject)
+{
+ INC_STATS("InspectorBackend.unwrapObject()");
+ if (args.Length() < 1)
+ return v8::Undefined();
+
+ InspectorBackend* inspectorBackend = V8DOMWrapper::convertToNativeObject<InspectorBackend>(V8ClassIndex::INSPECTORBACKEND, args.Holder());
+ return inspectorBackend->unwrapObject(toWebCoreStringWithNullCheck(args[0])).v8Value();
+}
+
+CALLBACK_FUNC_DECL(InspectorBackendPushNodePathToFrontend)
+{
+ INC_STATS("InspectorBackend.pushNodePathToFrontend()");
+ if (args.Length() < 2)
+ return v8::Undefined();
+
+ InspectorBackend* inspectorBackend = V8DOMWrapper::convertToNativeObject<InspectorBackend>(V8ClassIndex::INSPECTORBACKEND, args.Holder());
+ Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0]));
+ bool selectInUI = args[1]->ToBoolean()->Value();
+ if (node)
+ return v8::Number::New(inspectorBackend->pushNodePathToFrontend(node, selectInUI));
+
+ return v8::Undefined();
+}
+
+#if ENABLE(DATABASE)
+CALLBACK_FUNC_DECL(InspectorBackendSelectDatabase)
+{
+ INC_STATS("InspectorBackend.selectDatabase()");
+ if (args.Length() < 1)
+ return v8::Undefined();
+
+ InspectorBackend* inspectorBackend = V8DOMWrapper::convertToNativeObject<InspectorBackend>(V8ClassIndex::INSPECTORBACKEND, args.Holder());
+ Database* database = V8DOMWrapper::convertToNativeObject<Database>(V8ClassIndex::DATABASE, v8::Handle<v8::Object>::Cast(args[0]));
+ if (database)
+ inspectorBackend->selectDatabase(database);
+
+ return v8::Undefined();
+}
+#endif
+
+#if ENABLE(DOM_STORAGE)
+CALLBACK_FUNC_DECL(InspectorBackendSelectDOMStorage)
+{
+ INC_STATS("InspectorBackend.selectDOMStorage()");
+ if (args.Length() < 1)
+ return v8::Undefined();
+
+ InspectorBackend* inspectorBackend = V8DOMWrapper::convertToNativeObject<InspectorBackend>(V8ClassIndex::INSPECTORBACKEND, args.Holder());
+ Storage* storage = V8DOMWrapper::convertToNativeObject<Storage>(V8ClassIndex::STORAGE, v8::Handle<v8::Object>::Cast(args[0]));
+ if (storage)
+ inspectorBackend->selectDOMStorage(storage);
+
+ return v8::Undefined();
+}
+#endif
+
} // namespace WebCore
diff --git a/WebCore/bindings/v8/custom/V8LocationCustom.cpp b/WebCore/bindings/v8/custom/V8LocationCustom.cpp
index 3f3ff6b..1ed4c51 100644
--- a/WebCore/bindings/v8/custom/V8LocationCustom.cpp
+++ b/WebCore/bindings/v8/custom/V8LocationCustom.cpp
@@ -128,13 +128,13 @@ ACCESSOR_SETTER(LocationHref)
if (!frame)
return;
- if (!shouldAllowNavigation(frame))
- return;
-
KURL url = completeURL(toWebCoreString(value));
if (url.isNull())
return;
+ if (!shouldAllowNavigation(frame))
+ return;
+
navigateIfAllowed(frame, url, false, false);
}
@@ -274,7 +274,7 @@ CALLBACK_FUNC_DECL(LocationReload)
return v8::Undefined();
if (!protocolIsJavaScript(frame->loader()->url()))
- frame->loader()->scheduleRefresh(processingUserGesture());
+ frame->redirectScheduler()->scheduleRefresh(processingUserGesture());
return v8::Undefined();
}
@@ -288,13 +288,13 @@ CALLBACK_FUNC_DECL(LocationReplace)
if (!frame)
return v8::Undefined();
- if (!shouldAllowNavigation(frame))
- return v8::Undefined();
-
KURL url = completeURL(toWebCoreString(args[0]));
if (url.isNull())
return v8::Undefined();
+ if (!shouldAllowNavigation(frame))
+ return v8::Undefined();
+
navigateIfAllowed(frame, url, true, true);
return v8::Undefined();
}
@@ -309,13 +309,13 @@ CALLBACK_FUNC_DECL(LocationAssign)
if (!frame)
return v8::Undefined();
- if (!shouldAllowNavigation(frame))
- return v8::Undefined();
-
KURL url = completeURL(toWebCoreString(args[0]));
if (url.isNull())
return v8::Undefined();
+ if (!shouldAllowNavigation(frame))
+ return v8::Undefined();
+
navigateIfAllowed(frame, url, false, false);
return v8::Undefined();
}
diff --git a/WebCore/bindings/v8/custom/V8MessageChannelConstructor.cpp b/WebCore/bindings/v8/custom/V8MessageChannelConstructor.cpp
index f45aecf..ca02b16 100644
--- a/WebCore/bindings/v8/custom/V8MessageChannelConstructor.cpp
+++ b/WebCore/bindings/v8/custom/V8MessageChannelConstructor.cpp
@@ -36,6 +36,7 @@
#include "Document.h"
#include "Frame.h"
+#include "V8Utilities.h"
#include "WorkerContext.h"
#include "WorkerContextExecutionProxy.h"
@@ -52,16 +53,9 @@ CALLBACK_FUNC_DECL(MessageChannelConstructor)
return throwError("DOM object constructor cannot be called as a function.");
// Get the ScriptExecutionContext (WorkerContext or Document)
- ScriptExecutionContext* context = 0;
- WorkerContextExecutionProxy* proxy = WorkerContextExecutionProxy::retrieve();
- if (proxy)
- context = proxy->workerContext();
- else {
- Frame* frame = V8Proxy::retrieveFrameForCurrentContext();
- if (!frame)
- return v8::Undefined();
- context = frame->document();
- }
+ ScriptExecutionContext* context = getScriptExecutionContext();
+ if (!context)
+ return v8::Undefined();
// Note: it's OK to let this RefPtr go out of scope because we also call
// SetDOMWrapper(), which effectively holds a reference to obj.
diff --git a/WebCore/bindings/v8/custom/V8MessageEventCustom.cpp b/WebCore/bindings/v8/custom/V8MessageEventCustom.cpp
new file mode 100644
index 0000000..c5af635
--- /dev/null
+++ b/WebCore/bindings/v8/custom/V8MessageEventCustom.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "MessageEvent.h"
+#include "SerializedScriptValue.h"
+
+#include "V8Binding.h"
+#include "V8CustomBinding.h"
+#include "V8DOMWindow.h"
+#include "V8MessagePortCustom.h"
+#include "V8Proxy.h"
+
+namespace WebCore {
+
+ACCESSOR_GETTER(MessageEventPorts)
+{
+ INC_STATS("DOM.MessageEvent.ports");
+ MessageEvent* event = V8DOMWrapper::convertToNativeObject<MessageEvent>(V8ClassIndex::MESSAGEEVENT, info.Holder());
+
+ MessagePortArray* ports = event->ports();
+ if (!ports || ports->isEmpty())
+ return v8::Null();
+
+ v8::Local<v8::Array> portArray = v8::Array::New(ports->size());
+ for (size_t i = 0; i < ports->size(); ++i)
+ portArray->Set(v8::Integer::New(i), V8DOMWrapper::convertToV8Object(V8ClassIndex::MESSAGEPORT, (*ports)[i].get()));
+
+ return portArray;
+}
+
+CALLBACK_FUNC_DECL(MessageEventInitMessageEvent)
+{
+ INC_STATS("DOM.MessageEvent.initMessageEvent");
+ MessageEvent* event = V8DOMWrapper::convertToNativeObject<MessageEvent>(V8ClassIndex::MESSAGEEVENT, args.Holder());
+ String typeArg = v8ValueToWebCoreString(args[0]);
+ bool canBubbleArg = args[1]->BooleanValue();
+ bool cancelableArg = args[2]->BooleanValue();
+ RefPtr<SerializedScriptValue> dataArg = SerializedScriptValue::create(v8ValueToWebCoreString(args[3]));
+ String originArg = v8ValueToWebCoreString(args[4]);
+ String lastEventIdArg = v8ValueToWebCoreString(args[5]);
+ DOMWindow* sourceArg = V8DOMWindow::HasInstance(args[6]) ? V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, v8::Handle<v8::Object>::Cast(args[6])) : 0;
+ OwnPtr<MessagePortArray> portArray;
+
+ if (!isUndefinedOrNull(args[7])) {
+ portArray = new MessagePortArray();
+ if (!getMessagePortArray(args[7], *portArray))
+ return v8::Undefined();
+ }
+ event->initMessageEvent(typeArg, canBubbleArg, cancelableArg, dataArg.release(), originArg, lastEventIdArg, sourceArg, portArray.release());
+ return v8::Undefined();
+ }
+
+} // namespace WebCore
diff --git a/WebCore/bindings/v8/custom/V8MessagePortCustom.cpp b/WebCore/bindings/v8/custom/V8MessagePortCustom.cpp
index 95d248c..0d8631f 100644
--- a/WebCore/bindings/v8/custom/V8MessagePortCustom.cpp
+++ b/WebCore/bindings/v8/custom/V8MessagePortCustom.cpp
@@ -32,66 +32,22 @@
#include "ExceptionCode.h"
#include "MessagePort.h"
+#include "SerializedScriptValue.h"
#include "V8Binding.h"
#include "V8CustomBinding.h"
-#include "V8ObjectEventListener.h"
+#include "V8MessagePortCustom.h"
+#include "V8MessagePort.h"
#include "V8Proxy.h"
#include "V8Utilities.h"
#include "WorkerContextExecutionProxy.h"
namespace WebCore {
-PassRefPtr<EventListener> getEventListener(MessagePort* messagePort, v8::Local<v8::Value> value, bool findOnly, bool createObjectEventListener)
-{
- V8Proxy* proxy = V8Proxy::retrieve(messagePort->scriptExecutionContext());
- if (proxy) {
- V8EventListenerList* list = proxy->objectListeners();
- return findOnly ? list->findWrapper(value, false) : list->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, false);
- }
-
-#if ENABLE(WORKERS)
- WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve();
- if (workerContextProxy)
- return workerContextProxy->findOrCreateEventListenerHelper(value, false, findOnly, createObjectEventListener);
-#endif
-
- return PassRefPtr<EventListener>();
-}
-
-ACCESSOR_GETTER(MessagePortOnmessage)
-{
- INC_STATS("DOM.MessagePort.onmessage._get");
- MessagePort* messagePort = V8DOMWrapper::convertToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, info.Holder());
- return V8DOMWrapper::convertEventListenerToV8Object(messagePort->onmessage());
-}
-
-ACCESSOR_SETTER(MessagePortOnmessage)
-{
- INC_STATS("DOM.MessagePort.onmessage._set");
- MessagePort* messagePort = V8DOMWrapper::convertToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, info.Holder());
- if (value->IsNull()) {
- if (messagePort->onmessage()) {
- V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(messagePort->onmessage());
- removeHiddenDependency(info.Holder(), listener->getListenerObject(), V8Custom::kMessagePortRequestCacheIndex);
- }
-
- // Clear the listener.
- messagePort->setOnmessage(0);
-
- } else {
- RefPtr<EventListener> listener = getEventListener(messagePort, value, false, false);
- if (listener) {
- messagePort->setOnmessage(listener);
- createHiddenDependency(info.Holder(), value, V8Custom::kMessagePortRequestCacheIndex);
- }
- }
-}
-
CALLBACK_FUNC_DECL(MessagePortAddEventListener)
{
INC_STATS("DOM.MessagePort.addEventListener()");
MessagePort* messagePort = V8DOMWrapper::convertToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, args.Holder());
- RefPtr<EventListener> listener = getEventListener(messagePort, args[1], false, true);
+ RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(messagePort, args[1], false, ListenerFindOrCreate);
if (listener) {
String type = toWebCoreString(args[0]);
bool useCapture = args[2]->BooleanValue();
@@ -106,7 +62,7 @@ CALLBACK_FUNC_DECL(MessagePortRemoveEventListener)
{
INC_STATS("DOM.MessagePort.removeEventListener()");
MessagePort* messagePort = V8DOMWrapper::convertToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, args.Holder());
- RefPtr<EventListener> listener = getEventListener(messagePort, args[1], true, true);
+ RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(messagePort, args[1], false, ListenerFindOnly);
if (listener) {
String type = toWebCoreString(args[0]);
bool useCapture = args[2]->BooleanValue();
@@ -118,4 +74,64 @@ CALLBACK_FUNC_DECL(MessagePortRemoveEventListener)
return v8::Undefined();
}
+CALLBACK_FUNC_DECL(MessagePortPostMessage)
+{
+ INC_STATS("DOM.MessagePort.postMessage");
+ MessagePort* messagePort = V8DOMWrapper::convertToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, args.Holder());
+ RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(toWebCoreString(args[0]));
+ MessagePortArray portArray;
+ if (args.Length() > 1) {
+ if (!getMessagePortArray(args[1], portArray))
+ return v8::Undefined();
+ }
+ ExceptionCode ec = 0;
+ messagePort->postMessage(message.release(), &portArray, ec);
+ return throwError(ec);
+}
+
+bool getMessagePortArray(v8::Local<v8::Value> value, MessagePortArray& portArray)
+{
+ if (isUndefinedOrNull(value)) {
+ portArray.resize(0);
+ return true;
+ }
+
+ if (!value->IsObject()) {
+ throwError("MessagePortArray argument must be an object");
+ return false;
+ }
+ uint32_t length = 0;
+ v8::Local<v8::Object> ports = v8::Local<v8::Object>::Cast(value);
+
+ if (value->IsArray()) {
+ v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(value);
+ length = array->Length();
+ } else {
+ // Sequence-type object - get the length attribute
+ v8::Local<v8::Value> sequenceLength = ports->Get(v8::String::New("length"));
+ if (!sequenceLength->IsNumber()) {
+ throwError("MessagePortArray argument has no length attribute");
+ return false;
+ }
+ length = sequenceLength->Uint32Value();
+ }
+ portArray.resize(length);
+
+ for (unsigned int i = 0; i < length; ++i) {
+ v8::Local<v8::Value> port = ports->Get(v8::Integer::New(i));
+ // Validation of non-null objects, per HTML5 spec 8.3.3.
+ if (isUndefinedOrNull(port)) {
+ throwError(INVALID_STATE_ERR);
+ return false;
+ }
+ // Validation of Objects implementing an interface, per WebIDL spec 4.1.15.
+ if (!V8MessagePort::HasInstance(port)) {
+ throwError("MessagePortArray argument must contain only MessagePorts");
+ return false;
+ }
+ portArray[i] = V8DOMWrapper::convertToNativeObject<MessagePort>(V8ClassIndex::MESSAGEPORT, v8::Handle<v8::Object>::Cast(port));
+ }
+ return true;
+}
+
} // namespace WebCore
diff --git a/WebCore/bindings/v8/V8ObjectEventListener.h b/WebCore/bindings/v8/custom/V8MessagePortCustom.h
index 3c5ae10..7ab502b 100644
--- a/WebCore/bindings/v8/V8ObjectEventListener.h
+++ b/WebCore/bindings/v8/custom/V8MessagePortCustom.h
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2006, 2007, 2008, 2009 Google Inc. All rights reserved.
+ * Copyright (c) 2008, 2009 Google Inc.
+ * All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -28,32 +29,20 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef V8ObjectEventListener_h
-#define V8ObjectEventListener_h
+#ifndef V8MessagePortCustom_h
+#define V8MessagePortCustom_h
-#include "V8CustomEventListener.h"
#include <v8.h>
-#include <wtf/PassRefPtr.h>
-namespace WebCore {
-
- class Frame;
+#include "MessagePort.h"
- // V8ObjectEventListener is a special listener wrapper for objects not in the DOM. It keeps the JS listener as a weak pointer.
- class V8ObjectEventListener : public V8EventListener {
- public:
- static PassRefPtr<V8ObjectEventListener> create(Frame* frame, v8::Local<v8::Object> listener, bool isInline)
- {
- return adoptRef(new V8ObjectEventListener(frame, listener, isInline));
- }
-
- virtual bool isObjectListener() const { return true; }
+namespace WebCore {
- private:
- V8ObjectEventListener(Frame*, v8::Local<v8::Object> listener, bool isInline);
- virtual ~V8ObjectEventListener();
- };
+ // Helper function which pulls the values out of a JS sequence and into a MessagePortArray.
+ // Also validates the elements per sections 4.1.13 and 4.1.15 of the WebIDL spec and section 8.3.3 of the HTML5 spec and generates exceptions as appropriate.
+ // Returns true if the array was filled, or false if the passed value was not of an appropriate type.
+ bool getMessagePortArray(v8::Local<v8::Value>, MessagePortArray&);
} // namespace WebCore
-#endif // V8ObjectEventListener_h
+#endif // V8MessagePortCustom_h
diff --git a/WebCore/bindings/v8/custom/V8NodeCustom.cpp b/WebCore/bindings/v8/custom/V8NodeCustom.cpp
index 6b0d740..9b4b9aa 100644
--- a/WebCore/bindings/v8/custom/V8NodeCustom.cpp
+++ b/WebCore/bindings/v8/custom/V8NodeCustom.cpp
@@ -39,76 +39,18 @@
#include "V8CustomBinding.h"
#include "V8CustomEventListener.h"
#include "V8Node.h"
-#include "V8ObjectEventListener.h"
#include "V8Proxy.h"
#include <wtf/RefPtr.h>
namespace WebCore {
-static inline String toEventType(v8::Local<v8::String> value)
-{
- String key = toWebCoreString(value);
- ASSERT(key.startsWith("on"));
- return key.substring(2);
-}
-
-static PassRefPtr<EventListener> getEventListener(Node* node, v8::Local<v8::Value> value, bool isAttribute, bool findOnly)
-{
- V8Proxy* proxy = V8Proxy::retrieve(node->scriptExecutionContext());
- // The document might be created using createDocument, which does
- // not have a frame, use the active frame.
- if (!proxy)
- proxy = V8Proxy::retrieve(V8Proxy::retrieveFrameForEnteredContext());
-
- if (proxy) {
- V8EventListenerList* list = proxy->objectListeners();
- return findOnly ? list->findWrapper(value, isAttribute) : list->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, isAttribute);
- }
-
- return 0;
-}
-
-ACCESSOR_SETTER(NodeEventHandler)
-{
- Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(info.Holder());
- String eventType = toEventType(name);
-
- // Remove hidden dependency on the old event handler.
- if (EventListener* listener = node->getAttributeEventListener(eventType)) {
- if (static_cast<V8AbstractEventListener*>(listener)->isObjectListener()) {
- v8::Local<v8::Object> v8Listener = static_cast<V8ObjectEventListener*>(listener)->getListenerObject();
- removeHiddenDependency(info.Holder(), v8Listener, V8Custom::kNodeEventListenerCacheIndex);
- }
- }
-
- // Set handler if the value is a function.
- if (value->IsFunction()) {
- RefPtr<EventListener> listener = getEventListener(node, value, true, false);
- if (listener) {
- node->setAttributeEventListener(eventType, listener);
- createHiddenDependency(info.Holder(), value, V8Custom::kNodeEventListenerCacheIndex);
- }
- } else {
- // Otherwise, clear the handler.
- node->clearAttributeEventListener(eventType);
- }
-}
-
-ACCESSOR_GETTER(NodeEventHandler)
-{
- Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(info.Holder());
-
- EventListener* listener = node->getAttributeEventListener(toEventType(name));
- return V8DOMWrapper::convertEventListenerToV8Object(listener);
-}
-
CALLBACK_FUNC_DECL(NodeAddEventListener)
{
INC_STATS("DOM.Node.addEventListener()");
Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(args.Holder());
- RefPtr<EventListener> listener = getEventListener(node, args[1], false, false);
+ RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(node, args[1], false, ListenerFindOrCreate);
if (listener) {
String type = toWebCoreString(args[0]);
bool useCapture = args[2]->BooleanValue();
@@ -126,9 +68,9 @@ CALLBACK_FUNC_DECL(NodeRemoveEventListener)
// It is possbile that the owner document of the node is detached
// from the frame.
// See issue http://b/878909
- RefPtr<EventListener> listener = getEventListener(node, args[1], false, true);
+ RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(node, args[1], false, ListenerFindOnly);
if (listener) {
- String type = toWebCoreString(args[0]);
+ AtomicString type = v8ValueToAtomicWebCoreString(args[0]);
bool useCapture = args[2]->BooleanValue();
node->removeEventListener(type, listener.get(), useCapture);
removeHiddenDependency(args.Holder(), args[1], V8Custom::kNodeEventListenerCacheIndex);
diff --git a/WebCore/bindings/v8/custom/V8NotificationCenterCustom.cpp b/WebCore/bindings/v8/custom/V8NotificationCenterCustom.cpp
new file mode 100644
index 0000000..bd5fb4a
--- /dev/null
+++ b/WebCore/bindings/v8/custom/V8NotificationCenterCustom.cpp
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(NOTIFICATIONS)
+
+#include "NotImplemented.h"
+#include "Notification.h"
+#include "NotificationCenter.h"
+#include "V8Binding.h"
+#include "V8CustomBinding.h"
+#include "V8CustomEventListener.h"
+#include "V8CustomVoidCallback.h"
+#include "V8Proxy.h"
+#include "V8Utilities.h"
+#include "WorkerContext.h"
+#include "WorkerContextExecutionProxy.h"
+
+namespace WebCore {
+
+CALLBACK_FUNC_DECL(NotificationAddEventListener)
+{
+ INC_STATS("DOM.Notification.addEventListener()");
+ Notification* notification = V8DOMWrapper::convertToNativeObject<Notification>(V8ClassIndex::NOTIFICATION, args.Holder());
+
+ RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(notification, args[1], false, ListenerFindOrCreate);
+ if (listener) {
+ String type = toWebCoreString(args[0]);
+ bool useCapture = args[2]->BooleanValue();
+ notification->addEventListener(type, listener, useCapture);
+ createHiddenDependency(args.Holder(), args[1], V8Custom::kNotificationRequestCacheIndex);
+ }
+
+ return v8::Undefined();
+}
+
+CALLBACK_FUNC_DECL(NotificationRemoveEventListener)
+{
+ INC_STATS("DOM.Notification.removeEventListener()");
+ Notification* notification = V8DOMWrapper::convertToNativeObject<Notification>(V8ClassIndex::NOTIFICATION, args.Holder());
+
+ RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(notification, args[1], false, ListenerFindOnly);
+ if (listener) {
+ String type = toWebCoreString(args[0]);
+ bool useCapture = args[2]->BooleanValue();
+ notification->removeEventListener(type, listener.get(), useCapture);
+ removeHiddenDependency(args.Holder(), args[1], V8Custom::kNotificationRequestCacheIndex);
+ }
+
+ return v8::Undefined();
+}
+
+CALLBACK_FUNC_DECL(NotificationCenterCreateHTMLNotification)
+{
+ INC_STATS(L"DOM.NotificationCenter.CreateHTMLNotification()");
+ NotificationCenter* notificationCenter = V8DOMWrapper::convertToNativeObject<NotificationCenter>(V8ClassIndex::NOTIFICATIONCENTER, args.Holder());
+ ScriptExecutionContext* context = notificationCenter->context();
+ ExceptionCode ec = 0;
+ String url = toWebCoreString(args[0]);
+ RefPtr<Notification> notification = Notification::create(url, context, ec, notificationCenter->presenter());
+
+ if (ec)
+ return throwError(ec);
+
+ if (context->isWorkerContext())
+ return WorkerContextExecutionProxy::convertToV8Object(V8ClassIndex::NOTIFICATION, notification.get());
+
+ return V8DOMWrapper::convertToV8Object(V8ClassIndex::NOTIFICATION, notification.get());
+}
+
+CALLBACK_FUNC_DECL(NotificationCenterCreateNotification)
+{
+ INC_STATS(L"DOM.NotificationCenter.CreateNotification()");
+ NotificationCenter* notificationCenter = V8DOMWrapper::convertToNativeObject<NotificationCenter>(V8ClassIndex::NOTIFICATIONCENTER, args.Holder());
+ NotificationContents contents(toWebCoreString(args[0]), toWebCoreString(args[1]), toWebCoreString(args[2]));
+
+ ScriptExecutionContext* context = notificationCenter->context();
+ ExceptionCode ec = 0;
+ RefPtr<Notification> notification = Notification::create(contents, context, ec, notificationCenter->presenter());
+
+ if (ec)
+ return throwError(ec);
+
+ if (context->isWorkerContext())
+ return WorkerContextExecutionProxy::convertToV8Object(V8ClassIndex::NOTIFICATION, notification.get());
+
+ return V8DOMWrapper::convertToV8Object(V8ClassIndex::NOTIFICATION, notification.get());
+}
+
+CALLBACK_FUNC_DECL(NotificationCenterRequestPermission)
+{
+ INC_STATS(L"DOM.NotificationCenter.RequestPermission()");
+ NotificationCenter* notificationCenter = V8DOMWrapper::convertToNativeObject<NotificationCenter>(V8ClassIndex::NOTIFICATIONCENTER, args.Holder());
+ ScriptExecutionContext* context = notificationCenter->context();
+
+ // Requesting permission is only valid from a page context.
+ if (context->isWorkerContext())
+ return throwError(NOT_SUPPORTED_ERR);
+
+ RefPtr<V8CustomVoidCallback> callback;
+ if (args.Length() > 0) {
+ if (!args[0]->IsObject())
+ return throwError("Callback must be of valid type.", V8Proxy::TypeError);
+
+ callback = V8CustomVoidCallback::create(args[0], V8Proxy::retrieveFrameForCurrentContext());
+ }
+
+ notificationCenter->requestPermission(callback.release());
+ return v8::Undefined();
+}
+
+
+} // namespace WebCore
+
+#endif // ENABLE(NOTIFICATIONS)
diff --git a/WebCore/bindings/v8/custom/V8SVGElementInstanceCustom.cpp b/WebCore/bindings/v8/custom/V8SVGElementInstanceCustom.cpp
index ce9c345..dff4ff4 100644
--- a/WebCore/bindings/v8/custom/V8SVGElementInstanceCustom.cpp
+++ b/WebCore/bindings/v8/custom/V8SVGElementInstanceCustom.cpp
@@ -49,15 +49,12 @@ CALLBACK_FUNC_DECL(SVGElementInstanceAddEventListener)
INC_STATS("DOM.SVGElementInstance.AddEventListener()");
SVGElementInstance* instance = V8DOMWrapper::convertDOMWrapperToNative<SVGElementInstance>(args.Holder());
- V8Proxy* proxy = V8Proxy::retrieve(instance->scriptExecutionContext());
- if (!proxy)
- return v8::Undefined();
-
- RefPtr<EventListener> listener = proxy->eventListeners()->findOrCreateWrapper<V8EventListener>(proxy->frame(), args[1], false);
+ RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(instance, args[1], false, ListenerFindOrCreate);
if (listener) {
String type = toWebCoreString(args[0]);
bool useCapture = args[2]->BooleanValue();
instance->addEventListener(type, listener, useCapture);
+ createHiddenDependency(args.Holder(), args[1], V8Custom::kNodeEventListenerCacheIndex);
}
return v8::Undefined();
@@ -68,15 +65,12 @@ CALLBACK_FUNC_DECL(SVGElementInstanceRemoveEventListener)
INC_STATS("DOM.SVGElementInstance.RemoveEventListener()");
SVGElementInstance* instance = V8DOMWrapper::convertDOMWrapperToNative<SVGElementInstance>(args.Holder());
- V8Proxy* proxy = V8Proxy::retrieve(instance->scriptExecutionContext());
- if (!proxy)
- return v8::Undefined();
-
- RefPtr<EventListener> listener = proxy->eventListeners()->findWrapper(args[1], false);
+ RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(instance, args[1], false, ListenerFindOnly);
if (listener) {
String type = toWebCoreString(args[0]);
bool useCapture = args[2]->BooleanValue();
instance->removeEventListener(type, listener.get(), useCapture);
+ removeHiddenDependency(args.Holder(), args[1], V8Custom::kNodeEventListenerCacheIndex);
}
return v8::Undefined();
diff --git a/WebCore/bindings/v8/custom/V8SharedWorkerCustom.cpp b/WebCore/bindings/v8/custom/V8SharedWorkerCustom.cpp
index 3ab2f8e..e470bc8 100644
--- a/WebCore/bindings/v8/custom/V8SharedWorkerCustom.cpp
+++ b/WebCore/bindings/v8/custom/V8SharedWorkerCustom.cpp
@@ -53,12 +53,15 @@ CALLBACK_FUNC_DECL(SharedWorkerConstructor)
if (!args.IsConstructCall())
return throwError("DOM object constructor cannot be called as a function.");
- if (args.Length() < 2)
+ if (args.Length() < 1)
return throwError("Not enough arguments", V8Proxy::SyntaxError);
v8::TryCatch tryCatch;
v8::Handle<v8::String> scriptUrl = args[0]->ToString();
- v8::Handle<v8::String> name = args[1]->ToString();
+ String name;
+ if (args.Length() > 1)
+ name = toWebCoreString(args[1]->ToString());
+
if (tryCatch.HasCaught())
return throwError(tryCatch.Exception());
@@ -66,21 +69,14 @@ CALLBACK_FUNC_DECL(SharedWorkerConstructor)
return v8::Undefined();
// Get the script execution context.
- ScriptExecutionContext* context = 0;
- WorkerContextExecutionProxy* proxy = WorkerContextExecutionProxy::retrieve();
- if (proxy)
- context = proxy->workerContext();
- else {
- Frame* frame = V8Proxy::retrieveFrame();
- if (!frame)
- return v8::Undefined();
- context = frame->document();
- }
+ ScriptExecutionContext* context = getScriptExecutionContext();
+ if (!context)
+ return v8::Undefined();
// Create the worker object.
// Note: it's OK to let this RefPtr go out of scope because we also call SetDOMWrapper(), which effectively holds a reference to obj.
ExceptionCode ec = 0;
- RefPtr<SharedWorker> obj = SharedWorker::create(toWebCoreString(scriptUrl), toWebCoreString(name), context, ec);
+ RefPtr<SharedWorker> obj = SharedWorker::create(toWebCoreString(scriptUrl), name, context, ec);
// Setup the standard wrapper object internal fields.
v8::Handle<v8::Object> wrapperObject = args.Holder();
diff --git a/WebCore/bindings/v8/custom/V8WebKitPointConstructor.cpp b/WebCore/bindings/v8/custom/V8WebKitPointConstructor.cpp
index dd19a88..b2a807d 100755
--- a/WebCore/bindings/v8/custom/V8WebKitPointConstructor.cpp
+++ b/WebCore/bindings/v8/custom/V8WebKitPointConstructor.cpp
@@ -30,17 +30,38 @@
#include "config.h"
+#include "V8Binding.h"
#include "V8CustomBinding.h"
+#include "V8DOMWrapper.h"
#include "V8Index.h"
#include "V8Proxy.h"
#include "WebKitPoint.h"
+#include <wtf/MathExtras.h>
+
namespace WebCore {
CALLBACK_FUNC_DECL(WebKitPointConstructor)
{
INC_STATS("DOM.WebKitPoint.Constructor");
- return V8Proxy::constructDOMObject<V8ClassIndex::WEBKITPOINT, WebKitPoint>(args);
+ float x = 0;
+ float y = 0;
+ if (args.Length() > 1) {
+ if (!args[0]->IsUndefined()) {
+ x = toFloat(args[0]);
+ if (isnan(x))
+ x = 0;
+ }
+ if (!args[1]->IsUndefined()) {
+ y = toFloat(args[1]);
+ if (isnan(y))
+ y = 0;
+ }
+ }
+ PassRefPtr<WebKitPoint> point = WebKitPoint::create(x, y);
+ point->ref();
+ V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::WEBKITPOINT, point.get());
+ return args.Holder();
}
} // namespace WebCore
diff --git a/WebCore/bindings/v8/custom/V8WebSocketCustom.cpp b/WebCore/bindings/v8/custom/V8WebSocketCustom.cpp
new file mode 100644
index 0000000..f498e4f
--- /dev/null
+++ b/WebCore/bindings/v8/custom/V8WebSocketCustom.cpp
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(WEB_SOCKETS)
+
+#include "WebSocket.h"
+
+#include "Frame.h"
+#include "Settings.h"
+#include "V8Binding.h"
+#include "V8Proxy.h"
+#include "V8Utilities.h"
+#include "WorkerContext.h"
+#include "WorkerContextExecutionProxy.h"
+
+namespace WebCore {
+
+// ??? AddEventListener, RemoveEventListener
+
+CALLBACK_FUNC_DECL(WebSocketConstructor)
+{
+ INC_STATS("DOM.WebSocket.Constructor");
+
+ if (!args.IsConstructCall())
+ return throwError("DOM object custructor cannot be called as a function.");
+ if (args.Length() == 0)
+ return throwError("Not enough arguments", V8Proxy::SyntaxError);
+
+ v8::TryCatch tryCatch;
+ v8::Handle<v8::String> urlstring = args[0]->ToString();
+ if (tryCatch.HasCaught())
+ return throwError(tryCatch.Exception());
+ if (urlstring.IsEmpty())
+ return throwError("Empty URL", V8Proxy::SyntaxError);
+
+ // Get the script execution context.
+ ScriptExecutionContext* context = 0;
+ // TODO: Workers
+ if (!context) {
+ Frame* frame = V8Proxy::retrieveFrameForCurrentContext();
+ if (!frame)
+ return throwError("WebSocket constructor's associated frame is not available", V8Proxy::ReferenceError);
+ context = frame->document();
+ }
+
+ const KURL& url = context->completeURL(toWebCoreString(urlstring));
+
+ RefPtr<WebSocket> webSocket = WebSocket::create(context);
+ ExceptionCode ec = 0;
+
+ if (args.Length() < 2)
+ webSocket->connect(url, ec);
+ else {
+ v8::TryCatch tryCatchProtocol;
+ v8::Handle<v8::String> protocol = args[1]->ToString();
+ if (tryCatchProtocol.HasCaught())
+ return throwError(tryCatchProtocol.Exception());
+ webSocket->connect(url, toWebCoreString(protocol), ec);
+ }
+ if (ec)
+ return throwError(ec);
+
+ // Setup the standard wrapper object internal fields.
+ V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::WEBSOCKET), webSocket.get());
+
+ // Add object to the wrapper map.
+ webSocket->ref();
+ V8DOMWrapper::setJSWrapperForActiveDOMObject(webSocket.get(), v8::Persistent<v8::Object>::New(args.Holder()));
+
+ return args.Holder();
+}
+
+CALLBACK_FUNC_DECL(WebSocketSend)
+{
+ INC_STATS("DOM.WebSocket.send()");
+ WebSocket* webSocket = V8DOMWrapper::convertToNativeObject<WebSocket>(V8ClassIndex::WEBSOCKET, args.Holder());
+
+ ExceptionCode ec = 0;
+ bool ret = false;
+ if (args.Length() < 1)
+ return throwError("Not enough arguments", V8Proxy::SyntaxError);
+ else {
+ String msg = toWebCoreString(args[0]);
+ ret = webSocket->send(msg, ec);
+ }
+ if (ec)
+ return throwError(ec);
+ return v8Boolean(ret);
+}
+
+CALLBACK_FUNC_DECL(WebSocketClose)
+{
+ INC_STATS("DOM.WebSocket.close()");
+ WebSocket* webSocket = V8DOMWrapper::convertToNativeObject<WebSocket>(V8ClassIndex::WEBSOCKET, args.Holder());
+
+ webSocket->close();
+ return v8::Undefined();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_SOCKETS)
diff --git a/WebCore/bindings/v8/custom/V8WorkerContextCustom.cpp b/WebCore/bindings/v8/custom/V8WorkerContextCustom.cpp
index b526040..21b3c30 100755
--- a/WebCore/bindings/v8/custom/V8WorkerContextCustom.cpp
+++ b/WebCore/bindings/v8/custom/V8WorkerContextCustom.cpp
@@ -52,45 +52,6 @@ ACCESSOR_GETTER(WorkerContextSelf)
return WorkerContextExecutionProxy::convertWorkerContextToV8Object(workerContext);
}
-ACCESSOR_GETTER(WorkerContextOnerror)
-{
- INC_STATS(L"DOM.WorkerContext.onerror._get");
- WorkerContext* workerContext = V8DOMWrapper::convertToNativeObject<WorkerContext>(V8ClassIndex::WORKERCONTEXT, info.Holder());
- if (workerContext->onerror()) {
- V8WorkerContextEventListener* listener = static_cast<V8WorkerContextEventListener*>(workerContext->onerror());
- v8::Local<v8::Object> v8Listener = listener->getListenerObject();
- return v8Listener;
- }
- return v8::Undefined();
-}
-
-ACCESSOR_SETTER(WorkerContextOnerror)
-{
- INC_STATS(L"DOM.WorkerContext.onerror._set");
- WorkerContext* workerContext = V8DOMWrapper::convertToNativeObject<WorkerContext>(V8ClassIndex::WORKERCONTEXT, info.Holder());
- V8WorkerContextEventListener* oldListener = static_cast<V8WorkerContextEventListener*>(workerContext->onerror());
- if (value->IsNull()) {
- if (workerContext->onerror()) {
- v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject();
- removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kWorkerContextRequestCacheIndex);
- }
-
- // Clear the listener.
- workerContext->setOnerror(0);
- } else {
- RefPtr<V8EventListener> listener = workerContext->script()->proxy()->findOrCreateEventListener(v8::Local<v8::Object>::Cast(value), true, false);
- if (listener) {
- if (oldListener) {
- v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject();
- removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kWorkerContextRequestCacheIndex);
- }
-
- workerContext->setOnerror(listener);
- createHiddenDependency(info.Holder(), value, V8Custom::kWorkerContextRequestCacheIndex);
- }
- }
-}
-
v8::Handle<v8::Value> SetTimeoutOrInterval(const v8::Arguments& args, bool singleShot)
{
WorkerContext* workerContext = V8DOMWrapper::convertDOMWrapperToNative<WorkerContext>(args.Holder());
@@ -103,9 +64,10 @@ v8::Handle<v8::Value> SetTimeoutOrInterval(const v8::Arguments& args, bool singl
int32_t timeout = argumentCount >= 2 ? args[1]->Int32Value() : 0;
int timerId;
+ v8::Handle<v8::Context> v8Context = workerContext->script()->proxy()->context();
if (function->IsString()) {
WebCore::String stringFunction = toWebCoreString(function);
- timerId = DOMTimer::install(workerContext, new ScheduledAction(stringFunction, workerContext->url()), timeout, singleShot);
+ timerId = DOMTimer::install(workerContext, new ScheduledAction(v8Context, stringFunction, workerContext->url()), timeout, singleShot);
} else if (function->IsFunction()) {
size_t paramCount = argumentCount >= 2 ? argumentCount - 2 : 0;
v8::Local<v8::Value>* params = 0;
@@ -115,7 +77,7 @@ v8::Handle<v8::Value> SetTimeoutOrInterval(const v8::Arguments& args, bool singl
params[i] = args[i+2];
}
// ScheduledAction takes ownership of actual params and releases them in its destructor.
- ScheduledAction* action = new ScheduledAction(v8::Handle<v8::Function>::Cast(function), paramCount, params);
+ ScheduledAction* action = new ScheduledAction(v8Context, v8::Handle<v8::Function>::Cast(function), paramCount, params);
delete [] params;
timerId = DOMTimer::install(workerContext, action, timeout, singleShot);
} else
@@ -170,8 +132,7 @@ CALLBACK_FUNC_DECL(WorkerContextAddEventListener)
INC_STATS(L"DOM.WorkerContext.addEventListener()");
WorkerContext* workerContext = V8DOMWrapper::convertDOMWrapperToNative<WorkerContext>(args.Holder());
- RefPtr<V8EventListener> listener = workerContext->script()->proxy()->findOrCreateEventListener(v8::Local<v8::Object>::Cast(args[1]), false, false);
-
+ RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(workerContext, args[1], false, ListenerFindOrCreate);
if (listener) {
String type = toWebCoreString(args[0]);
bool useCapture = args[2]->BooleanValue();
@@ -186,10 +147,8 @@ CALLBACK_FUNC_DECL(WorkerContextRemoveEventListener)
{
INC_STATS(L"DOM.WorkerContext.removeEventListener()");
WorkerContext* workerContext = V8DOMWrapper::convertDOMWrapperToNative<WorkerContext>(args.Holder());
- WorkerContextExecutionProxy* proxy = workerContext->script()->proxy();
-
- RefPtr<V8EventListener> listener = proxy->findOrCreateEventListener(v8::Local<v8::Object>::Cast(args[1]), false, true);
+ RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(workerContext, args[1], false, ListenerFindOnly);
if (listener) {
String type = toWebCoreString(args[0]);
bool useCapture = args[2]->BooleanValue();
@@ -197,7 +156,6 @@ CALLBACK_FUNC_DECL(WorkerContextRemoveEventListener)
removeHiddenDependency(args.Holder(), args[1], V8Custom::kWorkerContextRequestCacheIndex);
}
-
return v8::Undefined();
}
diff --git a/WebCore/bindings/v8/custom/V8WorkerCustom.cpp b/WebCore/bindings/v8/custom/V8WorkerCustom.cpp
index 32450b8..454e41f 100755
--- a/WebCore/bindings/v8/custom/V8WorkerCustom.cpp
+++ b/WebCore/bindings/v8/custom/V8WorkerCustom.cpp
@@ -36,9 +36,10 @@
#include "ExceptionCode.h"
#include "Frame.h"
+#include "SerializedScriptValue.h"
#include "V8Binding.h"
#include "V8CustomBinding.h"
-#include "V8ObjectEventListener.h"
+#include "V8MessagePortCustom.h"
#include "V8Proxy.h"
#include "V8Utilities.h"
#include "WorkerContext.h"
@@ -65,16 +66,9 @@ CALLBACK_FUNC_DECL(WorkerConstructor)
return v8::Undefined();
// Get the script execution context.
- ScriptExecutionContext* context = 0;
- WorkerContextExecutionProxy* proxy = WorkerContextExecutionProxy::retrieve();
- if (proxy)
- context = proxy->workerContext();
- else {
- Frame* frame = V8Proxy::retrieveFrameForCurrentContext();
- if (!frame)
- return v8::Undefined();
- context = frame->document();
- }
+ ScriptExecutionContext* context = getScriptExecutionContext();
+ if (!context)
+ return v8::Undefined();
// Create the worker object.
// Note: it's OK to let this RefPtr go out of scope because we also call setDOMWrapper(), which effectively holds a reference to obj.
@@ -93,60 +87,19 @@ CALLBACK_FUNC_DECL(WorkerConstructor)
return wrapperObject;
}
-PassRefPtr<EventListener> getEventListener(Worker* worker, v8::Local<v8::Value> value, bool isAttribute, bool findOnly)
-{
- if (worker->scriptExecutionContext()->isWorkerContext()) {
- WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve();
- ASSERT(workerContextProxy);
- return workerContextProxy->findOrCreateObjectEventListener(value, isAttribute, findOnly);
- }
-
- V8Proxy* proxy = V8Proxy::retrieve(worker->scriptExecutionContext());
- if (proxy) {
- V8EventListenerList* list = proxy->objectListeners();
- return findOnly ? list->findWrapper(value, isAttribute) : list->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, isAttribute);
- }
-
- return 0;
-}
-
-ACCESSOR_GETTER(WorkerOnmessage)
-{
- INC_STATS(L"DOM.Worker.onmessage._get");
- Worker* worker = V8DOMWrapper::convertToNativeObject<Worker>(V8ClassIndex::WORKER, info.Holder());
- if (worker->onmessage()) {
- V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(worker->onmessage());
- v8::Local<v8::Object> v8Listener = listener->getListenerObject();
- return v8Listener;
- }
- return v8::Undefined();
-}
-
-ACCESSOR_SETTER(WorkerOnmessage)
+CALLBACK_FUNC_DECL(WorkerPostMessage)
{
- INC_STATS(L"DOM.Worker.onmessage._set");
- Worker* worker = V8DOMWrapper::convertToNativeObject<Worker>(V8ClassIndex::WORKER, info.Holder());
- V8ObjectEventListener* oldListener = static_cast<V8ObjectEventListener*>(worker->onmessage());
- if (value->IsNull()) {
- if (oldListener) {
- v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject();
- removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kWorkerRequestCacheIndex);
- }
-
- // Clear the listener.
- worker->setOnmessage(0);
- } else {
- RefPtr<EventListener> listener = getEventListener(worker, value, true, false);
- if (listener) {
- if (oldListener) {
- v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject();
- removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kWorkerRequestCacheIndex);
- }
-
- worker->setOnmessage(listener);
- createHiddenDependency(info.Holder(), value, V8Custom::kWorkerRequestCacheIndex);
- }
+ INC_STATS("DOM.Worker.postMessage");
+ Worker* worker = V8DOMWrapper::convertToNativeObject<Worker>(V8ClassIndex::WORKER, args.Holder());
+ RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(toWebCoreString(args[0]));
+ MessagePortArray portArray;
+ if (args.Length() > 1) {
+ if (!getMessagePortArray(args[1], portArray))
+ return v8::Undefined();
}
+ ExceptionCode ec = 0;
+ worker->postMessage(message.release(), &portArray, ec);
+ return throwError(ec);
}
} // namespace WebCore
diff --git a/WebCore/bindings/v8/custom/V8XMLHttpRequestConstructor.cpp b/WebCore/bindings/v8/custom/V8XMLHttpRequestConstructor.cpp
index 02ce8e2..af647cd 100644
--- a/WebCore/bindings/v8/custom/V8XMLHttpRequestConstructor.cpp
+++ b/WebCore/bindings/v8/custom/V8XMLHttpRequestConstructor.cpp
@@ -33,8 +33,8 @@
#include "Frame.h"
#include "V8Binding.h"
#include "V8CustomBinding.h"
-#include "V8ObjectEventListener.h"
#include "V8Proxy.h"
+#include "V8Utilities.h"
#include "XMLHttpRequest.h"
#include "WorkerContext.h"
#include "WorkerContextExecutionProxy.h"
@@ -50,20 +50,9 @@ CALLBACK_FUNC_DECL(XMLHttpRequestConstructor)
// Expect no parameters.
// Allocate a XMLHttpRequest object as its internal field.
- ScriptExecutionContext* context = 0;
-#if ENABLE(WORKERS)
- WorkerContextExecutionProxy* proxy = WorkerContextExecutionProxy::retrieve();
- if (proxy)
- context = proxy->workerContext();
- else {
-#endif
- Frame* frame = V8Proxy::retrieveFrameForCurrentContext();
- if (!frame)
- return throwError("XMLHttpRequest constructor's associated frame is not available", V8Proxy::ReferenceError);
- context = frame->document();
-#if ENABLE(WORKERS)
- }
-#endif
+ ScriptExecutionContext* context = getScriptExecutionContext();
+ if (!context)
+ return throwError("XMLHttpRequest constructor's associated context is not available", V8Proxy::ReferenceError);
RefPtr<XMLHttpRequest> xmlHttpRequest = XMLHttpRequest::create(context);
V8DOMWrapper::setDOMWrapper(args.Holder(), V8ClassIndex::ToInt(V8ClassIndex::XMLHTTPREQUEST), xmlHttpRequest.get());
diff --git a/WebCore/bindings/v8/custom/V8XMLHttpRequestCustom.cpp b/WebCore/bindings/v8/custom/V8XMLHttpRequestCustom.cpp
index 7204a61..39105de 100644
--- a/WebCore/bindings/v8/custom/V8XMLHttpRequestCustom.cpp
+++ b/WebCore/bindings/v8/custom/V8XMLHttpRequestCustom.cpp
@@ -33,10 +33,10 @@
#include "Frame.h"
#include "V8Binding.h"
-#include "V8Document.h"
#include "V8CustomBinding.h"
+#include "V8Document.h"
+#include "V8File.h"
#include "V8HTMLDocument.h"
-#include "V8ObjectEventListener.h"
#include "V8Proxy.h"
#include "V8Utilities.h"
#include "WorkerContext.h"
@@ -44,227 +44,6 @@
namespace WebCore {
-static PassRefPtr<EventListener> getEventListener(XMLHttpRequest* xmlHttpRequest, v8::Local<v8::Value> value, bool findOnly)
-{
-#if ENABLE(WORKERS)
- WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve();
- if (workerContextProxy)
- return workerContextProxy->findOrCreateObjectEventListener(value, false, findOnly);
-#endif
-
- V8Proxy* proxy = V8Proxy::retrieve(xmlHttpRequest->scriptExecutionContext());
- if (proxy) {
- V8EventListenerList* list = proxy->objectListeners();
- return findOnly ? list->findWrapper(value, false) : list->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, false);
- }
-
- return PassRefPtr<EventListener>();
-}
-
-ACCESSOR_GETTER(XMLHttpRequestOnabort)
-{
- INC_STATS("DOM.XMLHttpRequest.onabort._get");
- XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder());
- if (xmlHttpRequest->onabort()) {
- V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onabort());
- v8::Local<v8::Object> v8Listener = listener->getListenerObject();
- return v8Listener;
- }
- return v8::Null();
-}
-
-ACCESSOR_SETTER(XMLHttpRequestOnabort)
-{
- INC_STATS("DOM.XMLHttpRequest.onabort._set");
- XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder());
- if (value->IsNull()) {
- if (xmlHttpRequest->onabort()) {
- V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onabort());
- v8::Local<v8::Object> v8Listener = listener->getListenerObject();
- removeHiddenDependency(info.Holder(), v8Listener, V8Custom::kXMLHttpRequestCacheIndex);
- }
-
- // Clear the listener.
- xmlHttpRequest->setOnabort(0);
- } else {
- RefPtr<EventListener> listener = getEventListener(xmlHttpRequest, value, false);
- if (listener) {
- xmlHttpRequest->setOnabort(listener);
- createHiddenDependency(info.Holder(), value, V8Custom::kXMLHttpRequestCacheIndex);
- }
- }
-}
-
-ACCESSOR_GETTER(XMLHttpRequestOnerror)
-{
- INC_STATS("DOM.XMLHttpRequest.onerror._get");
- XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder());
- if (xmlHttpRequest->onerror()) {
- RefPtr<V8ObjectEventListener> listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onerror());
- v8::Local<v8::Object> v8Listener = listener->getListenerObject();
- return v8Listener;
- }
- return v8::Null();
-}
-
-ACCESSOR_SETTER(XMLHttpRequestOnerror)
-{
- INC_STATS("DOM.XMLHttpRequest.onerror._set");
- XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder());
- if (value->IsNull()) {
- if (xmlHttpRequest->onerror()) {
- V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onerror());
- v8::Local<v8::Object> v8Listener = listener->getListenerObject();
- removeHiddenDependency(info.Holder(), v8Listener, V8Custom::kXMLHttpRequestCacheIndex);
- }
-
- // Clear the listener.
- xmlHttpRequest->setOnerror(0);
- } else {
- RefPtr<EventListener> listener = getEventListener(xmlHttpRequest, value, false);
- if (listener) {
- xmlHttpRequest->setOnerror(listener);
- createHiddenDependency(info.Holder(), value, V8Custom::kXMLHttpRequestCacheIndex);
- }
- }
-}
-
-ACCESSOR_GETTER(XMLHttpRequestOnload)
-{
- INC_STATS("DOM.XMLHttpRequest.onload._get");
- XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder());
- if (xmlHttpRequest->onload()) {
- V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onload());
- v8::Local<v8::Object> v8Listener = listener->getListenerObject();
- return v8Listener;
- }
- return v8::Null();
-}
-
-ACCESSOR_SETTER(XMLHttpRequestOnload)
-{
- INC_STATS("DOM.XMLHttpRequest.onload._set");
- XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder());
- if (value->IsNull()) {
- if (xmlHttpRequest->onload()) {
- V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onload());
- v8::Local<v8::Object> v8Listener = listener->getListenerObject();
- removeHiddenDependency(info.Holder(), v8Listener, V8Custom::kXMLHttpRequestCacheIndex);
- }
-
- xmlHttpRequest->setOnload(0);
-
- } else {
- RefPtr<EventListener> listener = getEventListener(xmlHttpRequest, value, false);
- if (listener) {
- xmlHttpRequest->setOnload(listener.get());
- createHiddenDependency(info.Holder(), value, V8Custom::kXMLHttpRequestCacheIndex);
- }
- }
-}
-
-ACCESSOR_GETTER(XMLHttpRequestOnloadstart)
-{
- INC_STATS("DOM.XMLHttpRequest.onloadstart._get");
- XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder());
- if (xmlHttpRequest->onloadstart()) {
- V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onloadstart());
- v8::Local<v8::Object> v8Listener = listener->getListenerObject();
- return v8Listener;
- }
- return v8::Null();
-}
-
-ACCESSOR_SETTER(XMLHttpRequestOnloadstart)
-{
- INC_STATS("DOM.XMLHttpRequest.onloadstart._set");
- XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder());
- if (value->IsNull()) {
- if (xmlHttpRequest->onloadstart()) {
- V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onloadstart());
- v8::Local<v8::Object> v8Listener = listener->getListenerObject();
- removeHiddenDependency(info.Holder(), v8Listener, V8Custom::kXMLHttpRequestCacheIndex);
- }
-
- // Clear the listener.
- xmlHttpRequest->setOnloadstart(0);
- } else {
- RefPtr<EventListener> listener = getEventListener(xmlHttpRequest, value, false);
- if (listener) {
- xmlHttpRequest->setOnloadstart(listener);
- createHiddenDependency(info.Holder(), value, V8Custom::kXMLHttpRequestCacheIndex);
- }
- }
-}
-
-ACCESSOR_GETTER(XMLHttpRequestOnprogress)
-{
- INC_STATS("DOM.XMLHttpRequest.onprogress._get");
- XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder());
- if (xmlHttpRequest->onprogress()) {
- V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onprogress());
- v8::Local<v8::Object> v8Listener = listener->getListenerObject();
- return v8Listener;
- }
- return v8::Null();
-}
-
-ACCESSOR_SETTER(XMLHttpRequestOnprogress)
-{
- INC_STATS("DOM.XMLHttpRequest.onprogress._set");
- XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder());
- if (value->IsNull()) {
- if (xmlHttpRequest->onprogress()) {
- V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onprogress());
- v8::Local<v8::Object> v8Listener = listener->getListenerObject();
- removeHiddenDependency(info.Holder(), v8Listener, V8Custom::kXMLHttpRequestCacheIndex);
- }
-
- // Clear the listener.
- xmlHttpRequest->setOnprogress(0);
- } else {
- RefPtr<EventListener> listener = getEventListener(xmlHttpRequest, value, false);
- if (listener) {
- xmlHttpRequest->setOnprogress(listener);
- createHiddenDependency(info.Holder(), value, V8Custom::kXMLHttpRequestCacheIndex);
- }
- }
-}
-
-ACCESSOR_GETTER(XMLHttpRequestOnreadystatechange)
-{
- INC_STATS("DOM.XMLHttpRequest.onreadystatechange._get");
- XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder());
- if (xmlHttpRequest->onreadystatechange()) {
- V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onreadystatechange());
- v8::Local<v8::Object> v8Listener = listener->getListenerObject();
- return v8Listener;
- }
- return v8::Null();
-}
-
-ACCESSOR_SETTER(XMLHttpRequestOnreadystatechange)
-{
- INC_STATS("DOM.XMLHttpRequest.onreadystatechange._set");
- XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, info.Holder());
- if (value->IsNull()) {
- if (xmlHttpRequest->onreadystatechange()) {
- V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequest->onreadystatechange());
- v8::Local<v8::Object> v8Listener = listener->getListenerObject();
- removeHiddenDependency(info.Holder(), v8Listener, V8Custom::kXMLHttpRequestCacheIndex);
- }
-
- // Clear the listener.
- xmlHttpRequest->setOnreadystatechange(0);
- } else {
- RefPtr<EventListener> listener = getEventListener(xmlHttpRequest, value, false);
- if (listener) {
- xmlHttpRequest->setOnreadystatechange(listener.get());
- createHiddenDependency(info.Holder(), value, V8Custom::kXMLHttpRequestCacheIndex);
- }
- }
-}
-
ACCESSOR_GETTER(XMLHttpRequestResponseText)
{
// FIXME: This is only needed because webkit set this getter as custom.
@@ -279,7 +58,7 @@ CALLBACK_FUNC_DECL(XMLHttpRequestAddEventListener)
INC_STATS("DOM.XMLHttpRequest.addEventListener()");
XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder());
- RefPtr<EventListener> listener = getEventListener(xmlHttpRequest, args[1], false);
+ RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(xmlHttpRequest, args[1], false, ListenerFindOrCreate);
if (listener) {
String type = toWebCoreString(args[0]);
bool useCapture = args[2]->BooleanValue();
@@ -295,7 +74,7 @@ CALLBACK_FUNC_DECL(XMLHttpRequestRemoveEventListener)
INC_STATS("DOM.XMLHttpRequest.removeEventListener()");
XMLHttpRequest* xmlHttpRequest = V8DOMWrapper::convertToNativeObject<XMLHttpRequest>(V8ClassIndex::XMLHTTPREQUEST, args.Holder());
- RefPtr<EventListener> listener = getEventListener(xmlHttpRequest, args[1], true);
+ RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(xmlHttpRequest, args[1], false, ListenerFindOnly);
if (listener) {
String type = toWebCoreString(args[0]);
bool useCapture = args[2]->BooleanValue();
@@ -323,22 +102,9 @@ CALLBACK_FUNC_DECL(XMLHttpRequestOpen)
String method = toWebCoreString(args[0]);
String urlstring = toWebCoreString(args[1]);
- ScriptExecutionContext* context = 0;
-#if ENABLE(WORKERS)
- WorkerContextExecutionProxy* workerContextProxy = WorkerContextExecutionProxy::retrieve();
- if (workerContextProxy) {
- context = workerContextProxy->workerContext();
- ASSERT(context);
- }
-#endif
-
- if (!context) {
- V8Proxy* proxy = V8Proxy::retrieve();
- if (!proxy)
- return v8::Undefined();
- context = proxy->frame()->document();
- ASSERT(context);
- }
+ ScriptExecutionContext* context = getScriptExecutionContext();
+ if (!context)
+ return v8::Undefined();
KURL url = context->completeURL(urlstring);
@@ -379,12 +145,16 @@ CALLBACK_FUNC_DECL(XMLHttpRequestSend)
xmlHttpRequest->send(ec);
else {
v8::Handle<v8::Value> arg = args[0];
- // FIXME: upstream handles "File" objects too.
if (IsDocumentType(arg)) {
v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg);
Document* document = V8DOMWrapper::convertDOMWrapperToNode<Document>(object);
ASSERT(document);
xmlHttpRequest->send(document, ec);
+ } else if (V8File::HasInstance(arg)) {
+ v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg);
+ File* file = V8DOMWrapper::convertDOMWrapperToNative<File>(object);
+ ASSERT(file);
+ xmlHttpRequest->send(file, ec);
} else
xmlHttpRequest->send(toWebCoreStringWithNullCheck(arg), ec);
}
diff --git a/WebCore/bindings/v8/custom/V8XMLHttpRequestUploadCustom.cpp b/WebCore/bindings/v8/custom/V8XMLHttpRequestUploadCustom.cpp
index bbc69dd..9323f71 100644
--- a/WebCore/bindings/v8/custom/V8XMLHttpRequestUploadCustom.cpp
+++ b/WebCore/bindings/v8/custom/V8XMLHttpRequestUploadCustom.cpp
@@ -34,7 +34,6 @@
#include "ExceptionCode.h"
#include "V8Binding.h"
#include "V8CustomBinding.h"
-#include "V8ObjectEventListener.h"
#include "V8Proxy.h"
#include "V8Utilities.h"
#include "XMLHttpRequest.h"
@@ -43,212 +42,14 @@
namespace WebCore {
-ACCESSOR_GETTER(XMLHttpRequestUploadOnabort)
-{
- INC_STATS("DOM.XMLHttpRequestUpload.onabort._get");
- XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder());
- if (xmlHttpRequestUpload->onabort()) {
- V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onabort());
- v8::Local<v8::Object> v8Listener = listener->getListenerObject();
- return v8Listener;
- }
- return v8::Null();
-}
-
-ACCESSOR_SETTER(XMLHttpRequestUploadOnabort)
-{
- INC_STATS("DOM.XMLHttpRequestUpload.onabort._set");
- XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder());
- if (value->IsNull()) {
- if (xmlHttpRequestUpload->onabort()) {
- V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onabort());
- v8::Local<v8::Object> v8Listener = listener->getListenerObject();
- removeHiddenDependency(info.Holder(), v8Listener, V8Custom::kXMLHttpRequestCacheIndex);
- }
-
- // Clear the listener.
- xmlHttpRequestUpload->setOnabort(0);
- } else {
- XMLHttpRequest* xmlHttpRequest = xmlHttpRequestUpload->associatedXMLHttpRequest();
- V8Proxy* proxy = V8Proxy::retrieve(xmlHttpRequest->scriptExecutionContext());
- if (!proxy)
- return;
-
- RefPtr<EventListener> listener = proxy->objectListeners()->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, false);
- if (listener) {
- xmlHttpRequestUpload->setOnabort(listener);
- createHiddenDependency(info.Holder(), value, V8Custom::kXMLHttpRequestCacheIndex);
- }
- }
-}
-
-ACCESSOR_GETTER(XMLHttpRequestUploadOnerror)
-{
- INC_STATS("DOM.XMLHttpRequestUpload.onerror._get");
- XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder());
- if (xmlHttpRequestUpload->onerror()) {
- V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onerror());
- v8::Local<v8::Object> v8Listener = listener->getListenerObject();
- return v8Listener;
- }
- return v8::Null();
-}
-
-ACCESSOR_SETTER(XMLHttpRequestUploadOnerror)
-{
- INC_STATS("DOM.XMLHttpRequestUpload.onerror._set");
- XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder());
- if (value->IsNull()) {
- if (xmlHttpRequestUpload->onerror()) {
- V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onerror());
- v8::Local<v8::Object> v8Listener = listener->getListenerObject();
- removeHiddenDependency(info.Holder(), v8Listener, V8Custom::kXMLHttpRequestCacheIndex);
- }
-
- // Clear the listener.
- xmlHttpRequestUpload->setOnerror(0);
- } else {
- XMLHttpRequest* xmlHttpRequest = xmlHttpRequestUpload->associatedXMLHttpRequest();
- V8Proxy* proxy = V8Proxy::retrieve(xmlHttpRequest->scriptExecutionContext());
- if (!proxy)
- return;
-
- RefPtr<EventListener> listener = proxy->objectListeners()->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, false);
- if (listener) {
- xmlHttpRequestUpload->setOnerror(listener);
- createHiddenDependency(info.Holder(), value, V8Custom::kXMLHttpRequestCacheIndex);
- }
- }
-}
-
-ACCESSOR_GETTER(XMLHttpRequestUploadOnload)
-{
- INC_STATS("DOM.XMLHttpRequestUpload.onload._get");
- XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder());
- if (xmlHttpRequestUpload->onload()) {
- V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onload());
- v8::Local<v8::Object> v8Listener = listener->getListenerObject();
- return v8Listener;
- }
- return v8::Null();
-}
-
-ACCESSOR_SETTER(XMLHttpRequestUploadOnload)
-{
- INC_STATS("DOM.XMLHttpRequestUpload.onload._set");
- XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder());
- if (value->IsNull()) {
- if (xmlHttpRequestUpload->onload()) {
- V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onload());
- v8::Local<v8::Object> v8Listener = listener->getListenerObject();
- removeHiddenDependency(info.Holder(), v8Listener, V8Custom::kXMLHttpRequestCacheIndex);
- }
-
- // Clear the listener.
- xmlHttpRequestUpload->setOnload(0);
- } else {
- XMLHttpRequest* xmlHttpRequest = xmlHttpRequestUpload->associatedXMLHttpRequest();
- V8Proxy* proxy = V8Proxy::retrieve(xmlHttpRequest->scriptExecutionContext());
- if (!proxy)
- return;
-
- RefPtr<EventListener> listener = proxy->objectListeners()->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, false);
- if (listener) {
- xmlHttpRequestUpload->setOnload(listener);
- createHiddenDependency(info.Holder(), value, V8Custom::kXMLHttpRequestCacheIndex);
- }
- }
-}
-
-ACCESSOR_GETTER(XMLHttpRequestUploadOnloadstart)
-{
- INC_STATS("DOM.XMLHttpRequestUpload.onloadstart._get");
- XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder());
- if (xmlHttpRequestUpload->onloadstart()) {
- V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onloadstart());
- v8::Local<v8::Object> v8Listener = listener->getListenerObject();
- return v8Listener;
- }
- return v8::Null();
-}
-
-ACCESSOR_SETTER(XMLHttpRequestUploadOnloadstart)
-{
- INC_STATS("DOM.XMLHttpRequestUpload.onloadstart._set");
- XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder());
- if (value->IsNull()) {
- if (xmlHttpRequestUpload->onloadstart()) {
- V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onloadstart());
- v8::Local<v8::Object> v8Listener = listener->getListenerObject();
- removeHiddenDependency(info.Holder(), v8Listener, V8Custom::kXMLHttpRequestCacheIndex);
- }
-
- // Clear the listener.
- xmlHttpRequestUpload->setOnloadstart(0);
- } else {
- XMLHttpRequest* xmlHttpRequest = xmlHttpRequestUpload->associatedXMLHttpRequest();
- V8Proxy* proxy = V8Proxy::retrieve(xmlHttpRequest->scriptExecutionContext());
- if (!proxy)
- return;
-
- RefPtr<EventListener> listener = proxy->objectListeners()->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, false);
- if (listener) {
- xmlHttpRequestUpload->setOnloadstart(listener);
- createHiddenDependency(info.Holder(), value, V8Custom::kXMLHttpRequestCacheIndex);
- }
- }
-}
-
-ACCESSOR_GETTER(XMLHttpRequestUploadOnprogress)
-{
- INC_STATS("DOM.XMLHttpRequestUpload.onprogress._get");
- XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder());
- if (xmlHttpRequestUpload->onprogress()) {
- V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onprogress());
- v8::Local<v8::Object> v8Listener = listener->getListenerObject();
- return v8Listener;
- }
- return v8::Null();
-}
-
-ACCESSOR_SETTER(XMLHttpRequestUploadOnprogress)
-{
- INC_STATS("DOM.XMLHttpRequestUpload.onprogress._set");
- XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, info.Holder());
- if (value->IsNull()) {
- if (xmlHttpRequestUpload->onprogress()) {
- V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(xmlHttpRequestUpload->onprogress());
- v8::Local<v8::Object> v8Listener = listener->getListenerObject();
- removeHiddenDependency(info.Holder(), v8Listener, V8Custom::kXMLHttpRequestCacheIndex);
- }
-
- // Clear the listener.
- xmlHttpRequestUpload->setOnprogress(0);
- } else {
- XMLHttpRequest* xmlHttpRequest = xmlHttpRequestUpload->associatedXMLHttpRequest();
- V8Proxy* proxy = V8Proxy::retrieve(xmlHttpRequest->scriptExecutionContext());
- if (!proxy)
- return;
-
- RefPtr<EventListener> listener = proxy->objectListeners()->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, false);
- if (listener) {
- xmlHttpRequestUpload->setOnprogress(listener);
- createHiddenDependency(info.Holder(), value, V8Custom::kXMLHttpRequestCacheIndex);
- }
- }
-}
-
CALLBACK_FUNC_DECL(XMLHttpRequestUploadAddEventListener)
{
INC_STATS("DOM.XMLHttpRequestUpload.addEventListener()");
XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, args.Holder());
XMLHttpRequest* xmlHttpRequest = xmlHttpRequestUpload->associatedXMLHttpRequest();
- V8Proxy* proxy = V8Proxy::retrieve(xmlHttpRequest->scriptExecutionContext());
- if (!proxy)
- return v8::Undefined();
- RefPtr<EventListener> listener = proxy->objectListeners()->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), args[1], false);
+ RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(xmlHttpRequest, args[1], false, ListenerFindOrCreate);
if (listener) {
String type = toWebCoreString(args[0]);
bool useCapture = args[2]->BooleanValue();
@@ -265,12 +66,8 @@ CALLBACK_FUNC_DECL(XMLHttpRequestUploadRemoveEventListener)
XMLHttpRequestUpload* xmlHttpRequestUpload = V8DOMWrapper::convertToNativeObject<XMLHttpRequestUpload>(V8ClassIndex::XMLHTTPREQUESTUPLOAD, args.Holder());
XMLHttpRequest* xmlHttpRequest = xmlHttpRequestUpload->associatedXMLHttpRequest();
- V8Proxy* proxy = V8Proxy::retrieve(xmlHttpRequest->scriptExecutionContext());
- if (!proxy)
- return v8::Undefined(); // Probably leaked.
-
- RefPtr<EventListener> listener = proxy->objectListeners()->findWrapper(args[1], false);
+ RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(xmlHttpRequest, args[1], false, ListenerFindOnly);
if (listener) {
String type = toWebCoreString(args[0]);
bool useCapture = args[2]->BooleanValue();
diff --git a/WebCore/bindings/v8/npruntime.cpp b/WebCore/bindings/v8/npruntime.cpp
index 64a1927..35015b0 100644
--- a/WebCore/bindings/v8/npruntime.cpp
+++ b/WebCore/bindings/v8/npruntime.cpp
@@ -39,7 +39,7 @@
// The static initializer here should work okay, but we want to avoid
// static initialization in general.
-namespace {
+namespace npruntime {
// We use StringKey here as the key-type to avoid a string copy to
// construct the map key and for faster comparisons than strcmp.
@@ -112,7 +112,10 @@ struct StringKeyHash {
static const bool safeToCompareToEmptyOrDeleted = true;
};
-} // namespace
+} // namespace npruntime
+
+using npruntime::StringKey;
+using npruntime::StringKeyHash;
// Implement HashTraits<StringKey>
struct StringKeyHashTraits : WTF::GenericHashTraits<StringKey> {
@@ -309,6 +312,15 @@ void _NPN_DeallocateObject(NPObject* npObject)
}
}
+#if PLATFORM(ANDROID)
+// Android uses NPN_ReleaseObject (the 'public' version of _NPN_ReleaseObject)
+// in WebCoreFrameBridge.cpp. See http://trac.webkit.org/changeset/47021.
+// TODO: Upstream this to webkit.org.
+void NPN_ReleaseObject(NPObject *obj)
+{
+ _NPN_ReleaseObject(obj);
+}
+#endif
void _NPN_ReleaseObject(NPObject* npObject)
{
ASSERT(npObject);