diff options
Diffstat (limited to 'WebCore/bindings')
53 files changed, 729 insertions, 295 deletions
diff --git a/WebCore/bindings/generic/RuntimeEnabledFeatures.cpp b/WebCore/bindings/generic/RuntimeEnabledFeatures.cpp index 7d4e5c1..153f995 100644 --- a/WebCore/bindings/generic/RuntimeEnabledFeatures.cpp +++ b/WebCore/bindings/generic/RuntimeEnabledFeatures.cpp @@ -47,6 +47,7 @@ bool RuntimeEnabledFeatures::isIndexedDBEnabled = false; bool RuntimeEnabledFeatures::isWebGLEnabled = false; bool RuntimeEnabledFeatures::isPushStateEnabled = false; bool RuntimeEnabledFeatures::isTouchEnabled = true; +bool RuntimeEnabledFeatures::isDeviceOrientationEnabled = true; #if ENABLE(VIDEO) diff --git a/WebCore/bindings/generic/RuntimeEnabledFeatures.h b/WebCore/bindings/generic/RuntimeEnabledFeatures.h index 73bbf0f..d8eae23 100644 --- a/WebCore/bindings/generic/RuntimeEnabledFeatures.h +++ b/WebCore/bindings/generic/RuntimeEnabledFeatures.h @@ -113,6 +113,11 @@ public: static bool ontouchcancelEnabled() { return isTouchEnabled; } #endif + static void setDeviceOrientationEnabled(bool isEnabled) { isDeviceOrientationEnabled = isEnabled; } + static bool deviceOrientationEnabled() { return isDeviceOrientationEnabled; } + static bool deviceOrientationEventEnabled() { return isDeviceOrientationEnabled; } + static bool ondeviceorientationEnabled() { return isDeviceOrientationEnabled; } + private: // Never instantiate. RuntimeEnabledFeatures() { } @@ -126,6 +131,7 @@ private: static bool isWebGLEnabled; static bool isPushStateEnabled; static bool isTouchEnabled; + static bool isDeviceOrientationEnabled; }; } // namespace WebCore diff --git a/WebCore/bindings/js/JSBindingsAllInOne.cpp b/WebCore/bindings/js/JSBindingsAllInOne.cpp index 373c0e0..b517496 100644 --- a/WebCore/bindings/js/JSBindingsAllInOne.cpp +++ b/WebCore/bindings/js/JSBindingsAllInOne.cpp @@ -62,6 +62,7 @@ #include "JSDebugWrapperSet.cpp" #include "JSDedicatedWorkerContextCustom.cpp" #include "JSDesktopNotificationsCustom.cpp" +#include "JSDeviceOrientationEventCustom.cpp" #include "JSDocumentCustom.cpp" #include "JSElementCustom.cpp" #include "JSEventCustom.cpp" diff --git a/WebCore/bindings/js/JSCanvasRenderingContext2DCustom.cpp b/WebCore/bindings/js/JSCanvasRenderingContext2DCustom.cpp index e88afc2..8221fed 100644 --- a/WebCore/bindings/js/JSCanvasRenderingContext2DCustom.cpp +++ b/WebCore/bindings/js/JSCanvasRenderingContext2DCustom.cpp @@ -51,10 +51,8 @@ static JSValue toJS(ExecState* exec, CanvasStyle* style) return jsString(exec, style->color()); } -static PassRefPtr<CanvasStyle> toHTMLCanvasStyle(ExecState* exec, JSValue value) +static PassRefPtr<CanvasStyle> toHTMLCanvasStyle(ExecState*, JSValue value) { - if (value.isString()) - return CanvasStyle::create(ustringToString(asString(value)->value(exec))); if (!value.isObject()) return 0; JSObject* object = asObject(value); @@ -74,6 +72,10 @@ JSValue JSCanvasRenderingContext2D::strokeStyle(ExecState* exec) const void JSCanvasRenderingContext2D::setStrokeStyle(ExecState* exec, JSValue value) { CanvasRenderingContext2D* context = static_cast<CanvasRenderingContext2D*>(impl()); + if (value.isString()) { + context->setStrokeColor(ustringToString(asString(value)->value(exec))); + return; + } context->setStrokeStyle(toHTMLCanvasStyle(exec, value)); } @@ -86,6 +88,10 @@ JSValue JSCanvasRenderingContext2D::fillStyle(ExecState* exec) const void JSCanvasRenderingContext2D::setFillStyle(ExecState* exec, JSValue value) { CanvasRenderingContext2D* context = static_cast<CanvasRenderingContext2D*>(impl()); + if (value.isString()) { + context->setFillColor(ustringToString(asString(value)->value(exec))); + return; + } context->setFillStyle(toHTMLCanvasStyle(exec, value)); } @@ -260,9 +266,8 @@ JSValue JSCanvasRenderingContext2D::drawImage(ExecState* exec) return throwSyntaxError(exec); } #endif - } else { - setDOMException(exec, TYPE_MISMATCH_ERR); - } + } else + return throwTypeError(exec); return jsUndefined(); } diff --git a/WebCore/bindings/js/JSConsoleCustom.cpp b/WebCore/bindings/js/JSConsoleCustom.cpp index b9b407c..3ad34a3 100644 --- a/WebCore/bindings/js/JSConsoleCustom.cpp +++ b/WebCore/bindings/js/JSConsoleCustom.cpp @@ -28,9 +28,7 @@ #include "JSConsole.h" #include "Console.h" -#include "JSMemoryInfo.h" #include "JSScriptProfile.h" -#include "MemoryInfo.h" #include "ScriptCallStack.h" #include "ScriptProfile.h" #include <runtime/JSArray.h> @@ -57,9 +55,4 @@ JSValue JSConsole::profiles(ExecState* exec) const #endif -JSValue JSConsole::memory(ExecState* exec) const -{ - return toJS(exec, MemoryInfo::create()); -} - } // namespace WebCore diff --git a/WebCore/bindings/js/JSDeviceOrientationEventCustom.cpp b/WebCore/bindings/js/JSDeviceOrientationEventCustom.cpp new file mode 100644 index 0000000..05f8755 --- /dev/null +++ b/WebCore/bindings/js/JSDeviceOrientationEventCustom.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2010 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``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 "JSDeviceOrientationEvent.h" + +#if ENABLE(DEVICE_ORIENTATION) + +#include "DeviceOrientation.h" +#include "DeviceOrientationEvent.h" + +using namespace JSC; + +namespace WebCore { + +JSValue JSDeviceOrientationEvent::alpha(ExecState* exec) const +{ + DeviceOrientationEvent* imp = static_cast<DeviceOrientationEvent*>(impl()); + if (!imp->orientation()->canProvideAlpha()) + return jsNull(); + return jsNumber(exec, imp->orientation()->alpha()); +} + +JSValue JSDeviceOrientationEvent::beta(ExecState* exec) const +{ + DeviceOrientationEvent* imp = static_cast<DeviceOrientationEvent*>(impl()); + if (!imp->orientation()->canProvideBeta()) + return jsNull(); + return jsNumber(exec, imp->orientation()->beta()); +} + +JSValue JSDeviceOrientationEvent::gamma(ExecState* exec) const +{ + DeviceOrientationEvent* imp = static_cast<DeviceOrientationEvent*>(impl()); + if (!imp->orientation()->canProvideGamma()) + return jsNull(); + return jsNumber(exec, imp->orientation()->gamma()); +} + +JSValue JSDeviceOrientationEvent::initDeviceOrientationEvent(ExecState* exec) +{ + const String& type = ustringToString(exec->argument(0).toString(exec)); + bool bubbles = exec->argument(1).toBoolean(exec); + bool cancelable = exec->argument(2).toBoolean(exec); + // If alpha, beta or gamma are null or undefined, mark them as not provided. + // Otherwise, use the standard JavaScript conversion. + bool alphaProvided = !exec->argument(3).isUndefinedOrNull(); + double alpha = exec->argument(3).toNumber(exec); + bool betaProvided = !exec->argument(4).isUndefinedOrNull(); + double beta = exec->argument(4).toNumber(exec); + bool gammaProvided = !exec->argument(5).isUndefinedOrNull(); + double gamma = exec->argument(5).toNumber(exec); + RefPtr<DeviceOrientation> orientation = DeviceOrientation::create(alphaProvided, alpha, betaProvided, beta, gammaProvided, gamma); + DeviceOrientationEvent* imp = static_cast<DeviceOrientationEvent*>(impl()); + imp->initDeviceOrientationEvent(type, bubbles, cancelable, orientation.get()); + return jsUndefined(); +} + +} // namespace WebCore + +#endif // ENABLE(DEVICE_ORIENTATION) diff --git a/WebCore/bindings/js/ScriptArray.cpp b/WebCore/bindings/js/ScriptArray.cpp index caecc40..119d303 100644 --- a/WebCore/bindings/js/ScriptArray.cpp +++ b/WebCore/bindings/js/ScriptArray.cpp @@ -31,6 +31,8 @@ #include "config.h" #include "ScriptArray.h" +#include "SerializedScriptValue.h" + #include <runtime/JSLock.h> using namespace JSC; @@ -62,6 +64,19 @@ bool ScriptArray::set(unsigned index, const ScriptObject& value) return handleException(m_scriptState); } +bool ScriptArray::set(unsigned index, SerializedScriptValue* value) +{ + ScriptValue scriptValue = ScriptValue::deserialize(m_scriptState, value); + if (scriptValue.hasNoValue()) { + ASSERT_NOT_REACHED(); + return false; + } + + JSLock lock(SilenceAssertionsOnly); + jsArray()->put(m_scriptState, index, scriptValue.jsValue()); + return handleException(m_scriptState); +} + bool ScriptArray::set(unsigned index, const String& value) { JSLock lock(SilenceAssertionsOnly); diff --git a/WebCore/bindings/js/ScriptArray.h b/WebCore/bindings/js/ScriptArray.h index 9240368..2badd09 100644 --- a/WebCore/bindings/js/ScriptArray.h +++ b/WebCore/bindings/js/ScriptArray.h @@ -37,23 +37,25 @@ #include <runtime/JSArray.h> namespace WebCore { - - class ScriptArray : public ScriptObject { - public: - ScriptArray(ScriptState*, JSC::JSArray*); - ScriptArray() {} - JSC::JSArray* jsArray() const { return asArray(jsValue()); } - - bool set(unsigned index, const ScriptObject&); - bool set(unsigned index, const String&); - bool set(unsigned index, double); - bool set(unsigned index, long long); - bool set(unsigned index, int); - bool set(unsigned index, bool); - unsigned length(); - - static ScriptArray createNew(ScriptState*); - }; +class SerializedScriptValue; + +class ScriptArray : public ScriptObject { +public: + ScriptArray(ScriptState*, JSC::JSArray*); + ScriptArray() {} + JSC::JSArray* jsArray() const { return asArray(jsValue()); } + + bool set(unsigned index, const ScriptObject&); + bool set(unsigned index, SerializedScriptValue*); + bool set(unsigned index, const String&); + bool set(unsigned index, double); + bool set(unsigned index, long long); + bool set(unsigned index, int); + bool set(unsigned index, bool); + unsigned length(); + + static ScriptArray createNew(ScriptState*); +}; } #endif // ScriptArray_h diff --git a/WebCore/bindings/js/ScriptCallStack.cpp b/WebCore/bindings/js/ScriptCallStack.cpp index c9bb8b0..de61b07 100644 --- a/WebCore/bindings/js/ScriptCallStack.cpp +++ b/WebCore/bindings/js/ScriptCallStack.cpp @@ -91,11 +91,21 @@ void ScriptCallStack::initialize() if (!m_caller || m_initialized) return; - JSValue func = m_exec->interpreter()->retrieveCaller(m_exec, m_caller); - while (!func.isNull()) { - JSFunction* jsFunction = asFunction(func); - m_frames.append(ScriptCallFrame(jsFunction->name(m_exec), UString(), 0, 0, 0)); - func = m_exec->interpreter()->retrieveCaller(m_exec, jsFunction); + int signedLineNumber; + intptr_t sourceID; + UString urlString; + JSValue function; + // callFrame must exist if m_caller is not null. + CallFrame* callFrame = m_exec->callerFrame(); + while (true) { + ASSERT(callFrame); + m_exec->interpreter()->retrieveLastCaller(callFrame, signedLineNumber, sourceID, urlString, function); + if (!function) + break; + JSFunction* jsFunction = asFunction(function); + unsigned lineNumber = signedLineNumber >= 0 ? signedLineNumber : 0; + m_frames.append(ScriptCallFrame(jsFunction->name(m_exec), urlString, lineNumber, m_exec, 0)); + callFrame = callFrame->callerFrame(); } m_initialized = true; } diff --git a/WebCore/bindings/js/ScriptController.cpp b/WebCore/bindings/js/ScriptController.cpp index 0aa8f52..98022d9 100644 --- a/WebCore/bindings/js/ScriptController.cpp +++ b/WebCore/bindings/js/ScriptController.cpp @@ -379,6 +379,12 @@ PassRefPtr<Bindings::RootObject> ScriptController::createRootObject(void* native return rootObject.release(); } +#if ENABLE(INSPECTOR) +void ScriptController::setCaptureCallStackForUncaughtExceptions(bool) +{ +} +#endif + #if ENABLE(NETSCAPE_PLUGIN_API) NPObject* ScriptController::windowScriptNPObject() diff --git a/WebCore/bindings/js/ScriptController.h b/WebCore/bindings/js/ScriptController.h index c382a93..80155e4 100644 --- a/WebCore/bindings/js/ScriptController.h +++ b/WebCore/bindings/js/ScriptController.h @@ -151,6 +151,10 @@ public: PassRefPtr<JSC::Bindings::RootObject> createRootObject(void* nativeHandle); +#if ENABLE(INSPECTOR) + static void setCaptureCallStackForUncaughtExceptions(bool); +#endif + #if PLATFORM(MAC) #if ENABLE(JAVA_BRIDGE) static void initJavaJSBindings(); diff --git a/WebCore/bindings/js/ScriptDebugServer.cpp b/WebCore/bindings/js/ScriptDebugServer.cpp index 0a40f13..d71034b 100644 --- a/WebCore/bindings/js/ScriptDebugServer.cpp +++ b/WebCore/bindings/js/ScriptDebugServer.cpp @@ -200,7 +200,7 @@ void ScriptDebugServer::setPauseOnExceptionsState(PauseOnExceptionsState pause) m_pauseOnExceptionsState = pause; } -void ScriptDebugServer::pauseProgram() +void ScriptDebugServer::pause() { m_pauseOnNextStatement = true; } diff --git a/WebCore/bindings/js/ScriptDebugServer.h b/WebCore/bindings/js/ScriptDebugServer.h index 6a8209b..fd8976b 100644 --- a/WebCore/bindings/js/ScriptDebugServer.h +++ b/WebCore/bindings/js/ScriptDebugServer.h @@ -67,6 +67,8 @@ public: void removeBreakpoint(const String& sourceID, unsigned lineNumber); void clearBreakpoints(); void setBreakpointsActivated(bool activated); + void activateBreakpoints() { setBreakpointsActivated(true); } + void deactivateBreakpoints() { setBreakpointsActivated(false); } enum PauseOnExceptionsState { DontPauseOnExceptions, @@ -76,7 +78,7 @@ public: PauseOnExceptionsState pauseOnExceptionsState() const { return m_pauseOnExceptionsState; } void setPauseOnExceptionsState(PauseOnExceptionsState); - void pauseProgram(); + void pause(); void continueProgram(); void stepIntoStatement(); void stepOverStatement(); diff --git a/WebCore/bindings/js/StringSourceProvider.h b/WebCore/bindings/js/StringSourceProvider.h index 2a18006..478c1d1 100644 --- a/WebCore/bindings/js/StringSourceProvider.h +++ b/WebCore/bindings/js/StringSourceProvider.h @@ -49,10 +49,6 @@ namespace WebCore { : ScriptSourceProvider(stringToUString(url)) , m_source(source) { - if (m_source.length()) { - bool scratch = false; - m_source = String(source.impl()->copyStringWithoutBOMs(false, scratch)); - } } String m_source; diff --git a/WebCore/bindings/objc/WebScriptObject.mm b/WebCore/bindings/objc/WebScriptObject.mm index 3f224f1..37874ac 100644 --- a/WebCore/bindings/objc/WebScriptObject.mm +++ b/WebCore/bindings/objc/WebScriptObject.mm @@ -433,6 +433,27 @@ static void getListFromNSArray(ExecState *exec, NSArray *array, RootObject* root _didExecute(self); } +- (BOOL)hasWebScriptKey:(NSString *)key +{ + if (![self _isSafeScript]) + return NO; + + ExecState* exec = [self _rootObject]->globalObject()->globalExec(); + ASSERT(!exec->hadException()); + + JSLock lock(SilenceAssertionsOnly); + BOOL result = [self _imp]->hasProperty(exec, Identifier(exec, stringToUString(String(key)))); + + if (exec->hadException()) { + addExceptionToConsole(exec); + exec->clearException(); + } + + _didExecute(self); + + return result; +} + - (NSString *)stringRepresentation { if (![self _isSafeScript]) { diff --git a/WebCore/bindings/objc/WebScriptObjectPrivate.h b/WebCore/bindings/objc/WebScriptObjectPrivate.h index 3a424ce..5da1dde 100644 --- a/WebCore/bindings/objc/WebScriptObjectPrivate.h +++ b/WebCore/bindings/objc/WebScriptObjectPrivate.h @@ -59,6 +59,16 @@ namespace WebCore { - (JSC::Bindings::RootObject*)_originRootObject; @end +@interface WebScriptObject (StagedForPublic) +/*! + @method hasWebScriptKey: + @param name The name of the property to check for. + @discussion Checks for the existence of the property on the object in the script environment. + @result Returns YES if the property exists, NO otherwise. + */ +- (BOOL)hasWebScriptKey:(NSString *)name; +@end + @interface WebScriptObjectPrivate : NSObject { @public diff --git a/WebCore/bindings/scripts/CodeGenerator.pm b/WebCore/bindings/scripts/CodeGenerator.pm index d106920..363fdc5 100644 --- a/WebCore/bindings/scripts/CodeGenerator.pm +++ b/WebCore/bindings/scripts/CodeGenerator.pm @@ -31,6 +31,7 @@ use File::Find; my $useDocument = ""; my $useGenerator = ""; my $useOutputDir = ""; +my $useOutputHeadersDir = ""; my $useDirectories = ""; my $useLayerOnTop = 0; my $preprocessor; @@ -80,6 +81,7 @@ sub new $useDirectories = shift; $useGenerator = shift; $useOutputDir = shift; + $useOutputHeadersDir = shift; $useLayerOnTop = shift; $preprocessor = shift; $writeDependencies = shift; @@ -107,7 +109,7 @@ sub ProcessDocument require $ifaceName . ".pm"; # Dynamically load external code generation perl module - $codeGenerator = $ifaceName->new($object, $useOutputDir, $useLayerOnTop, $preprocessor, $writeDependencies, $verbose); + $codeGenerator = $ifaceName->new($object, $useOutputDir, $useOutputHeadersDir, $useLayerOnTop, $preprocessor, $writeDependencies, $verbose); unless (defined($codeGenerator)) { my $classes = $useDocument->classes; foreach my $class (@$classes) { @@ -467,4 +469,28 @@ sub SetterExpressionPrefix return "$functionName($contentAttributeName, " } +sub ShouldCheckEnums +{ + my $dataNode = shift; + return not $dataNode->extendedAttributes->{"DontCheckEnums"}; +} + +sub GenerateCompileTimeCheckForEnumsIfNeeded +{ + my ($object, $dataNode) = @_; + my $interfaceName = $dataNode->name; + my @checks = (); + # If necessary, check that all constants are available as enums with the same value. + if (ShouldCheckEnums($dataNode) && @{$dataNode->constants}) { + push(@checks, "\n"); + foreach my $constant (@{$dataNode->constants}) { + my $name = $constant->name; + my $value = $constant->value; + push(@checks, "COMPILE_ASSERT($value == ${interfaceName}::$name, ${interfaceName}Enum${name}IsWrongUseDontCheckEnums);\n"); + } + push(@checks, "\n"); + } + return @checks; +} + 1; diff --git a/WebCore/bindings/scripts/CodeGeneratorCPP.pm b/WebCore/bindings/scripts/CodeGeneratorCPP.pm index 7df91ca..9e254af 100644 --- a/WebCore/bindings/scripts/CodeGeneratorCPP.pm +++ b/WebCore/bindings/scripts/CodeGeneratorCPP.pm @@ -98,6 +98,7 @@ sub new $codeGenerator = shift; $outputDir = shift; + shift; # $outputHeadersDir shift; # $useLayerOnTop shift; # $preprocessor shift; # $writeDependencies diff --git a/WebCore/bindings/scripts/CodeGeneratorJS.pm b/WebCore/bindings/scripts/CodeGeneratorJS.pm index a0a2098..d992d89 100644 --- a/WebCore/bindings/scripts/CodeGeneratorJS.pm +++ b/WebCore/bindings/scripts/CodeGeneratorJS.pm @@ -73,6 +73,7 @@ sub new $codeGenerator = shift; $outputDir = shift; + shift; # $outputHeadersDir shift; # $useLayerOnTop shift; # $preprocessor $writeDependencies = shift; @@ -1242,6 +1243,8 @@ sub GenerateImplementation \@hashKeys, \@hashSpecials, \@hashValue1, \@hashValue2); + push(@implContent, $codeGenerator->GenerateCompileTimeCheckForEnumsIfNeeded($dataNode)); + my $protoClassName = "${className}Prototype"; GenerateConstructorDeclaration(\@implContent, $className, $dataNode) unless $dataNode->extendedAttributes->{"CustomConstructFunction"}; diff --git a/WebCore/bindings/scripts/CodeGeneratorObjC.pm b/WebCore/bindings/scripts/CodeGeneratorObjC.pm index 7d66979..91cbd0b 100644 --- a/WebCore/bindings/scripts/CodeGeneratorObjC.pm +++ b/WebCore/bindings/scripts/CodeGeneratorObjC.pm @@ -199,6 +199,7 @@ sub new $codeGenerator = shift; $outputDir = shift; + shift; # $outputHeadersDir shift; # $useLayerOnTop shift; # $preprocessor $writeDependencies = shift; diff --git a/WebCore/bindings/scripts/CodeGeneratorV8.pm b/WebCore/bindings/scripts/CodeGeneratorV8.pm index 383bb74..c963e04 100644 --- a/WebCore/bindings/scripts/CodeGeneratorV8.pm +++ b/WebCore/bindings/scripts/CodeGeneratorV8.pm @@ -30,6 +30,7 @@ use Digest::MD5; my $module = ""; my $outputDir = ""; +my $outputHeadersDir = ""; my @headerContent = (); my @implContentHeader = (); @@ -71,6 +72,7 @@ sub new $codeGenerator = shift; $outputDir = shift; + $outputHeadersDir = shift; bless($reference, $object); return $reference; @@ -110,7 +112,7 @@ sub GenerateInterface my $name = $dataNode->name; # Open files for writing - my $headerFileName = "$outputDir/V8$name.h"; + my $headerFileName = "$outputHeadersDir/V8$name.h"; my $implFileName = "$outputDir/V8$name.cpp"; open($IMPL, ">$implFileName") || die "Couldn't open file $implFileName"; @@ -273,13 +275,6 @@ END END } - if ($implClassName eq "HTMLDocument") { - push(@headerContent, <<END); - static v8::Local<v8::Object> WrapInShadowObject(v8::Local<v8::Object> wrapper, Node* impl); - static v8::Handle<v8::Value> GetNamedProperty(HTMLDocument* htmlDocument, const AtomicString& key); -END - } - my @enabledAtRuntime; foreach my $function (@{$dataNode->functions}) { my $name = $function->signature->name; @@ -367,6 +362,9 @@ sub GetInternalFields if (IsSubType($dataNode, "Document")) { push(@customInternalFields, "implementationIndex"); + if ($name eq "HTMLDocument") { + push(@customInternalFields, ("markerIndex", "shadowIndex")); + } } elsif ($name eq "DOMWindow") { push(@customInternalFields, "enteredIsolatedWorldIndex"); } @@ -403,6 +401,7 @@ END my %indexerSpecialCases = ( "Storage" => 1, "HTMLAppletElement" => 1, + "HTMLDocument" => 1, "HTMLEmbedElement" => 1, "HTMLObjectElement" => 1 ); @@ -429,10 +428,6 @@ sub GenerateHeaderNamedAndIndexedPropertyAccessors if ($interfaceName eq "HTMLSelectElement" || $interfaceName eq "HTMLAppletElement" || $interfaceName eq "HTMLEmbedElement" || $interfaceName eq "HTMLObjectElement") { $hasCustomNamedGetter = 1; } - if ($interfaceName eq "HTMLDocument") { - $hasCustomNamedGetter = 0; - $hasCustomIndexedGetter = 0; - } my $isIndexerSpecialCase = exists $indexerSpecialCases{$interfaceName}; if ($hasCustomIndexedGetter || $isIndexerSpecialCase) { @@ -461,7 +456,7 @@ END static v8::Handle<v8::Value> namedPropertySetter(v8::Local<v8::String>, v8::Local<v8::Value>, const v8::AccessorInfo&); END } - if ($hasCustomDeleters) { + if ($hasCustomDeleters || $interfaceName eq "HTMLDocument") { push(@headerContent, <<END); static v8::Handle<v8::Boolean> namedPropertyDeleter(v8::Local<v8::String>, const v8::AccessorInfo&); END @@ -1478,10 +1473,6 @@ sub GenerateImplementationNamedPropertyGetter $hasCustomGetter = 1; } - if ($interfaceName eq "HTMLDocument") { - $hasCustomGetter = 0; - } - my $hasGetter = $dataNode->extendedAttributes->{"HasNameGetter"} || $hasCustomGetter || $namedPropertyGetter; if (!$hasGetter) { return; @@ -1497,7 +1488,8 @@ END } my $hasSetter = $dataNode->extendedAttributes->{"DelegatingPutFunction"}; - my $hasDeleter = $dataNode->extendedAttributes->{"CustomDeleteProperty"}; + # FIXME: Try to remove hard-coded HTMLDocument reference by aligning handling of document.all with JSC bindings. + my $hasDeleter = $dataNode->extendedAttributes->{"CustomDeleteProperty"} || $interfaceName eq "HTMLDocument"; my $hasEnumerator = $dataNode->extendedAttributes->{"CustomGetPropertyNames"}; my $setOn = "Instance"; @@ -1753,6 +1745,7 @@ END } if ($has_constants) { push(@implContent, "};\n"); + push(@implContent, $codeGenerator->GenerateCompileTimeCheckForEnumsIfNeeded($dataNode)); } push(@implContentDecls, "} // namespace ${interfaceName}Internal\n\n"); @@ -1981,11 +1974,6 @@ END instance->SetAccessCheckCallbacks(V8DOMWindow::namedSecurityCheck, V8DOMWindow::indexedSecurityCheck, v8::External::Wrap(&V8DOMWindow::info), false); END } - if ($interfaceName eq "HTMLDocument") { - push(@implContent, <<END); - desc->SetHiddenPrototype(true); -END - } if ($interfaceName eq "Location") { push(@implContent, <<END); diff --git a/WebCore/bindings/scripts/IDLParser.pm b/WebCore/bindings/scripts/IDLParser.pm index e250a4d..927deb9 100644 --- a/WebCore/bindings/scripts/IDLParser.pm +++ b/WebCore/bindings/scripts/IDLParser.pm @@ -329,11 +329,13 @@ sub ParseInterface my $line = $_; $line =~ /$IDLStructure::interfaceParameterSelector/; - my $paramExtendedAttributes = (defined($1) ? $1 : " "); chop($paramExtendedAttributes); - my $paramType = (defined($2) ? $2 : die("Parsing error!\nSource:\n$line\n)")); - my $paramName = (defined($3) ? $3 : die("Parsing error!\nSource:\n$line\n)")); + my $paramDirection = $1; + my $paramExtendedAttributes = (defined($2) ? $2 : " "); chop($paramExtendedAttributes); + my $paramType = (defined($3) ? $3 : die("Parsing error!\nSource:\n$line\n)")); + my $paramName = (defined($4) ? $4 : die("Parsing error!\nSource:\n$line\n)")); my $paramDataNode = new domSignature(); + $paramDataNode->direction($paramDirection); $paramDataNode->name($paramName); $paramDataNode->type($paramType); $paramDataNode->extendedAttributes(parseExtendedAttributes($paramExtendedAttributes)); diff --git a/WebCore/bindings/scripts/IDLStructure.pm b/WebCore/bindings/scripts/IDLStructure.pm index d61fce1..2eda696 100644 --- a/WebCore/bindings/scripts/IDLStructure.pm +++ b/WebCore/bindings/scripts/IDLStructure.pm @@ -59,6 +59,7 @@ struct( domAttribute => { # Used to represent a map of 'variable name' <-> 'variable type' struct( domSignature => { + direction => '$', # Variable direction (in or out) name => '$', # Variable name type => '$', # Variable type extendedAttributes => '$' # Extended attributes @@ -100,7 +101,7 @@ our $exceptionSubSelector = '{\s*' . $supportedTypes . '\s*(' . $idlType . '*)\s our $interfaceSelector = 'interface\s*((?:' . $extendedAttributeSyntax . ' )?)(' . $idlIdNs . '*)\s*(?::(\s*[^{]*))?{([a-zA-Z0-9_=\s(),;:\[\]&\|]*)'; our $interfaceMethodSelector = '\s*((?:' . $extendedAttributeSyntax . ' )?)' . $supportedTypes . '\s*(' . $idlIdNs . '*)\s*\(\s*([a-zA-Z0-9:\s,=\[\]]*)'; -our $interfaceParameterSelector = 'in\s*((?:' . $extendedAttributeSyntax . ' )?)' . $supportedTypes . '\s*(' . $idlIdNs . '*)'; +our $interfaceParameterSelector = '(in|out)\s*((?:' . $extendedAttributeSyntax . ' )?)' . $supportedTypes . '\s*(' . $idlIdNs . '*)'; our $interfaceAttributeSelector = '\s*(readonly attribute|attribute)\s*(' . $extendedAttributeSyntax . ' )?' . $supportedTypes . '\s*(' . $idlType . '*)'; diff --git a/WebCore/bindings/scripts/generate-bindings.pl b/WebCore/bindings/scripts/generate-bindings.pl index b293b3c..57a3928 100755 --- a/WebCore/bindings/scripts/generate-bindings.pl +++ b/WebCore/bindings/scripts/generate-bindings.pl @@ -39,8 +39,10 @@ use CodeGenerator; my @idlDirectories; my $outputDirectory; +my $outputHeadersDirectory; my $generator; my $defines; +my $filename; my $prefix; my $preprocessor; my $writeDependencies; @@ -48,8 +50,10 @@ my $verbose; GetOptions('include=s@' => \@idlDirectories, 'outputDir=s' => \$outputDirectory, + 'outputHeadersDir=s' => \$outputHeadersDirectory, 'generator=s' => \$generator, 'defines=s' => \$defines, + 'filename=s' => \$filename, 'prefix=s' => \$prefix, 'preprocessor=s' => \$preprocessor, 'verbose' => \$verbose, @@ -62,6 +66,9 @@ die('Must specify generator') unless defined($generator); die('Must specify output directory.') unless defined($outputDirectory); die('Must specify defines') unless defined($defines); +if (!$outputHeadersDirectory) { + $outputHeadersDirectory = $outputDirectory; +} if ($verbose) { print "$generator: $idlFile\n"; } @@ -72,5 +79,5 @@ my $parser = IDLParser->new(!$verbose); my $document = $parser->Parse($idlFile, $defines, $preprocessor); # Generate desired output for given IDL file. -my $codeGen = CodeGenerator->new(\@idlDirectories, $generator, $outputDirectory, 0, $preprocessor, $writeDependencies, $verbose); +my $codeGen = CodeGenerator->new(\@idlDirectories, $generator, $outputDirectory, $outputHeadersDirectory, 0, $preprocessor, $writeDependencies, $verbose); $codeGen->ProcessDocument($document, $defines); diff --git a/WebCore/bindings/scripts/test/CPP/WebDOMTestObj.h b/WebCore/bindings/scripts/test/CPP/WebDOMTestObj.h index 1eb5ed3..86c7169 100644 --- a/WebCore/bindings/scripts/test/CPP/WebDOMTestObj.h +++ b/WebCore/bindings/scripts/test/CPP/WebDOMTestObj.h @@ -42,6 +42,14 @@ public: WebDOMTestObj(const WebDOMTestObj&); ~WebDOMTestObj(); + enum { + WEBDOM_CONST_VALUE_0 = 0, + WEBDOM_CONST_VALUE_1 = 1, + WEBDOM_CONST_VALUE_2 = 2, + WEBDOM_CONST_VALUE_4 = 4, + WEBDOM_CONST_VALUE_8 = 8 + }; + int readOnlyIntAttr() const; WebDOMString readOnlyStringAttr() const; WebDOMTestObj readOnlyTestObjAttr() const; diff --git a/WebCore/bindings/scripts/test/JS/JSTestObj.cpp b/WebCore/bindings/scripts/test/JS/JSTestObj.cpp index 2f561f9..6e667f7 100644 --- a/WebCore/bindings/scripts/test/JS/JSTestObj.cpp +++ b/WebCore/bindings/scripts/test/JS/JSTestObj.cpp @@ -100,13 +100,25 @@ static JSC_CONST_HASHTABLE HashTable JSTestObjTable = { 68, 63, JSTestObjTableVa #define THUNK_GENERATOR(generator) #endif -static const HashTableValue JSTestObjConstructorTableValues[1] = +static const HashTableValue JSTestObjConstructorTableValues[6] = { + { "CONST_VALUE_0", DontDelete | ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjCONST_VALUE_0), (intptr_t)0 THUNK_GENERATOR(0) }, + { "CONST_VALUE_1", DontDelete | ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjCONST_VALUE_1), (intptr_t)0 THUNK_GENERATOR(0) }, + { "CONST_VALUE_2", DontDelete | ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjCONST_VALUE_2), (intptr_t)0 THUNK_GENERATOR(0) }, + { "CONST_VALUE_4", DontDelete | ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjCONST_VALUE_4), (intptr_t)0 THUNK_GENERATOR(0) }, + { "CONST_VALUE_8", DontDelete | ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjCONST_VALUE_8), (intptr_t)0 THUNK_GENERATOR(0) }, { 0, 0, 0, 0 THUNK_GENERATOR(0) } }; #undef THUNK_GENERATOR -static JSC_CONST_HASHTABLE HashTable JSTestObjConstructorTable = { 1, 0, JSTestObjConstructorTableValues, 0 }; +static JSC_CONST_HASHTABLE HashTable JSTestObjConstructorTable = { 16, 15, JSTestObjConstructorTableValues, 0 }; + +COMPILE_ASSERT(0 == TestObj::CONST_VALUE_0, TestObjEnumCONST_VALUE_0IsWrongUseDontCheckEnums); +COMPILE_ASSERT(1 == TestObj::CONST_VALUE_1, TestObjEnumCONST_VALUE_1IsWrongUseDontCheckEnums); +COMPILE_ASSERT(2 == TestObj::CONST_VALUE_2, TestObjEnumCONST_VALUE_2IsWrongUseDontCheckEnums); +COMPILE_ASSERT(4 == TestObj::CONST_VALUE_4, TestObjEnumCONST_VALUE_4IsWrongUseDontCheckEnums); +COMPILE_ASSERT(8 == TestObj::CONST_VALUE_8, TestObjEnumCONST_VALUE_8IsWrongUseDontCheckEnums); + class JSTestObjConstructor : public DOMConstructorObject { public: JSTestObjConstructor(JSC::ExecState*, JSDOMGlobalObject*); @@ -148,8 +160,13 @@ bool JSTestObjConstructor::getOwnPropertyDescriptor(ExecState* exec, const Ident #define THUNK_GENERATOR(generator) #endif -static const HashTableValue JSTestObjPrototypeTableValues[31] = +static const HashTableValue JSTestObjPrototypeTableValues[36] = { + { "CONST_VALUE_0", DontDelete | ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjCONST_VALUE_0), (intptr_t)0 THUNK_GENERATOR(0) }, + { "CONST_VALUE_1", DontDelete | ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjCONST_VALUE_1), (intptr_t)0 THUNK_GENERATOR(0) }, + { "CONST_VALUE_2", DontDelete | ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjCONST_VALUE_2), (intptr_t)0 THUNK_GENERATOR(0) }, + { "CONST_VALUE_4", DontDelete | ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjCONST_VALUE_4), (intptr_t)0 THUNK_GENERATOR(0) }, + { "CONST_VALUE_8", DontDelete | ReadOnly, (intptr_t)static_cast<PropertySlot::GetValueFunc>(jsTestObjCONST_VALUE_8), (intptr_t)0 THUNK_GENERATOR(0) }, { "voidMethod", DontDelete | Function, (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionVoidMethod), (intptr_t)0 THUNK_GENERATOR(0) }, { "voidMethodWithArgs", DontDelete | Function, (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionVoidMethodWithArgs), (intptr_t)3 THUNK_GENERATOR(0) }, { "intMethod", DontDelete | Function, (intptr_t)static_cast<NativeFunction>(jsTestObjPrototypeFunctionIntMethod), (intptr_t)0 THUNK_GENERATOR(0) }, @@ -184,7 +201,7 @@ static const HashTableValue JSTestObjPrototypeTableValues[31] = }; #undef THUNK_GENERATOR -static JSC_CONST_HASHTABLE HashTable JSTestObjPrototypeTable = { 130, 127, JSTestObjPrototypeTableValues, 0 }; +static JSC_CONST_HASHTABLE HashTable JSTestObjPrototypeTable = { 132, 127, JSTestObjPrototypeTableValues, 0 }; const ClassInfo JSTestObjPrototype::s_info = { "TestObjPrototype", 0, &JSTestObjPrototypeTable, 0 }; JSObject* JSTestObjPrototype::self(ExecState* exec, JSGlobalObject* globalObject) @@ -194,12 +211,12 @@ JSObject* JSTestObjPrototype::self(ExecState* exec, JSGlobalObject* globalObject bool JSTestObjPrototype::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { - return getStaticFunctionSlot<JSObject>(exec, &JSTestObjPrototypeTable, this, propertyName, slot); + return getStaticPropertySlot<JSTestObjPrototype, JSObject>(exec, &JSTestObjPrototypeTable, this, propertyName, slot); } bool JSTestObjPrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) { - return getStaticFunctionDescriptor<JSObject>(exec, &JSTestObjPrototypeTable, this, propertyName, descriptor); + return getStaticPropertyDescriptor<JSTestObjPrototype, JSObject>(exec, &JSTestObjPrototypeTable, this, propertyName, descriptor); } const ClassInfo JSTestObj::s_info = { "TestObj", 0, &JSTestObjTable, 0 }; @@ -1228,6 +1245,33 @@ EncodedJSValue JSC_HOST_CALL jsTestObjPrototypeFunctionOverloadedMethod(ExecStat return throwVMTypeError(exec); } +// Constant getters + +JSValue jsTestObjCONST_VALUE_0(ExecState* exec, JSValue, const Identifier&) +{ + return jsNumber(exec, static_cast<int>(0)); +} + +JSValue jsTestObjCONST_VALUE_1(ExecState* exec, JSValue, const Identifier&) +{ + return jsNumber(exec, static_cast<int>(1)); +} + +JSValue jsTestObjCONST_VALUE_2(ExecState* exec, JSValue, const Identifier&) +{ + return jsNumber(exec, static_cast<int>(2)); +} + +JSValue jsTestObjCONST_VALUE_4(ExecState* exec, JSValue, const Identifier&) +{ + return jsNumber(exec, static_cast<int>(4)); +} + +JSValue jsTestObjCONST_VALUE_8(ExecState* exec, JSValue, const Identifier&) +{ + return jsNumber(exec, static_cast<int>(8)); +} + JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, TestObj* object) { return getDOMObjectWrapper<JSTestObj>(exec, globalObject, object); diff --git a/WebCore/bindings/scripts/test/JS/JSTestObj.h b/WebCore/bindings/scripts/test/JS/JSTestObj.h index c83e568..84122b7 100644 --- a/WebCore/bindings/scripts/test/JS/JSTestObj.h +++ b/WebCore/bindings/scripts/test/JS/JSTestObj.h @@ -173,6 +173,13 @@ JSC::JSValue jsTestObjId(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&); void setJSTestObjId(JSC::ExecState*, JSC::JSObject*, JSC::JSValue); JSC::JSValue jsTestObjHash(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&); JSC::JSValue jsTestObjConstructor(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&); +// Constants + +JSC::JSValue jsTestObjCONST_VALUE_0(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&); +JSC::JSValue jsTestObjCONST_VALUE_1(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&); +JSC::JSValue jsTestObjCONST_VALUE_2(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&); +JSC::JSValue jsTestObjCONST_VALUE_4(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&); +JSC::JSValue jsTestObjCONST_VALUE_8(JSC::ExecState*, JSC::JSValue, const JSC::Identifier&); } // namespace WebCore diff --git a/WebCore/bindings/scripts/test/ObjC/DOMTestObj.h b/WebCore/bindings/scripts/test/ObjC/DOMTestObj.h index 1eac990..33c3a2d 100644 --- a/WebCore/bindings/scripts/test/ObjC/DOMTestObj.h +++ b/WebCore/bindings/scripts/test/ObjC/DOMTestObj.h @@ -34,6 +34,14 @@ @class NSString; @protocol DOMEventListener; +enum { + DOM_CONST_VALUE_0 = 0, + DOM_CONST_VALUE_1 = 1, + DOM_CONST_VALUE_2 = 2, + DOM_CONST_VALUE_4 = 4, + DOM_CONST_VALUE_8 = 8 +}; + @interface DOMTestObj : DOMObject - (int)readOnlyIntAttr; - (NSString *)readOnlyStringAttr; diff --git a/WebCore/bindings/scripts/test/TestObj.idl b/WebCore/bindings/scripts/test/TestObj.idl index 43fc211..f9d41d7 100644 --- a/WebCore/bindings/scripts/test/TestObj.idl +++ b/WebCore/bindings/scripts/test/TestObj.idl @@ -129,5 +129,12 @@ module test { readonly attribute long description; attribute long id; readonly attribute DOMString hash; + + // Check constants and enums. + const unsigned short CONST_VALUE_0 = 0; + const unsigned short CONST_VALUE_1 = 1; + const unsigned short CONST_VALUE_2 = 2; + const unsigned short CONST_VALUE_4 = 4; + const unsigned short CONST_VALUE_8 = 8; }; } diff --git a/WebCore/bindings/scripts/test/V8/V8TestObj.cpp b/WebCore/bindings/scripts/test/V8/V8TestObj.cpp index 0b9d034..c348726 100644 --- a/WebCore/bindings/scripts/test/V8/V8TestObj.cpp +++ b/WebCore/bindings/scripts/test/V8/V8TestObj.cpp @@ -1015,6 +1015,20 @@ static const BatchedCallback TestObjCallbacks[] = { {"methodWithNonOptionalArgAndTwoOptionalArgs", TestObjInternal::methodWithNonOptionalArgAndTwoOptionalArgsCallback}, {"overloadedMethod", TestObjInternal::overloadedMethodCallback}, }; +static const BatchedConstant TestObjConsts[] = { + {"CONST_VALUE_0", static_cast<signed int>(0)}, + {"CONST_VALUE_1", static_cast<signed int>(1)}, + {"CONST_VALUE_2", static_cast<signed int>(2)}, + {"CONST_VALUE_4", static_cast<signed int>(4)}, + {"CONST_VALUE_8", static_cast<signed int>(8)}, +}; + +COMPILE_ASSERT(0 == TestObj::CONST_VALUE_0, TestObjEnumCONST_VALUE_0IsWrongUseDontCheckEnums); +COMPILE_ASSERT(1 == TestObj::CONST_VALUE_1, TestObjEnumCONST_VALUE_1IsWrongUseDontCheckEnums); +COMPILE_ASSERT(2 == TestObj::CONST_VALUE_2, TestObjEnumCONST_VALUE_2IsWrongUseDontCheckEnums); +COMPILE_ASSERT(4 == TestObj::CONST_VALUE_4, TestObjEnumCONST_VALUE_4IsWrongUseDontCheckEnums); +COMPILE_ASSERT(8 == TestObj::CONST_VALUE_8, TestObjEnumCONST_VALUE_8IsWrongUseDontCheckEnums); + static v8::Persistent<v8::FunctionTemplate> ConfigureV8TestObjTemplate(v8::Persistent<v8::FunctionTemplate> desc) { v8::Local<v8::Signature> defaultSignature = configureTemplate(desc, "TestObj", v8::Persistent<v8::FunctionTemplate>(), V8TestObj::internalFieldCount, @@ -1059,6 +1073,7 @@ static v8::Persistent<v8::FunctionTemplate> ConfigureV8TestObjTemplate(v8::Persi v8::Handle<v8::FunctionTemplate> customArgsAndExceptionArgv[customArgsAndExceptionArgc] = { V8log::GetRawTemplate() }; v8::Handle<v8::Signature> customArgsAndExceptionSignature = v8::Signature::New(desc, customArgsAndExceptionArgc, customArgsAndExceptionArgv); proto->Set(v8::String::New("customArgsAndException"), v8::FunctionTemplate::New(TestObjInternal::customArgsAndExceptionCallback, v8::Handle<v8::Value>(), customArgsAndExceptionSignature)); + batchConfigureConstants(desc, proto, TestObjConsts, sizeof(TestObjConsts) / sizeof(*TestObjConsts)); // Custom toString template desc->Set(getToStringName(), getToStringTemplate()); diff --git a/WebCore/bindings/v8/DOMData.h b/WebCore/bindings/v8/DOMData.h index 4d7331b..c8b4a41 100644 --- a/WebCore/bindings/v8/DOMData.h +++ b/WebCore/bindings/v8/DOMData.h @@ -79,14 +79,25 @@ namespace WebCore { template<typename T> void DOMData::handleWeakObject(DOMDataStore::DOMWrapperMapType mapType, v8::Persistent<v8::Object> v8Object, T* domObject) { + WrapperTypeInfo* type = V8DOMWrapper::domWrapperType(v8Object); DOMDataList& list = DOMDataStore::allStores(); + bool found = false; for (size_t i = 0; i < list.size(); ++i) { DOMDataStore* store = list[i]; ASSERT(store->domData()->owningThread() == WTF::currentThread()); DOMWrapperMap<T>* domMap = static_cast<DOMWrapperMap<T>*>(store->getDOMWrapperMap(mapType)); - if (domMap->removeIfPresent(domObject, v8Object)) - store->domData()->derefObject(V8DOMWrapper::domWrapperType(v8Object), domObject); + if (domMap->removeIfPresent(domObject, v8Object)) { + derefObject(type, domObject); + found = true; + } + } + + // If not found, it means map for the wrapper has been already destroyed, just dispose the + // handle and deref the object to fight memory leak. + if (!found) { + v8Object.Dispose(); + derefObject(type, domObject); } } diff --git a/WebCore/bindings/v8/DOMDataStore.cpp b/WebCore/bindings/v8/DOMDataStore.cpp index 5d609d8..0b06a69 100644 --- a/WebCore/bindings/v8/DOMDataStore.cpp +++ b/WebCore/bindings/v8/DOMDataStore.cpp @@ -163,10 +163,15 @@ void DOMDataStore::weakNodeCallback(v8::Persistent<v8::Value> v8Object, void* do DOMDataStore* store = list[i]; if (store->domNodeMap().removeIfPresent(node, v8Object)) { ASSERT(store->domData()->owningThread() == WTF::currentThread()); - node->deref(); // Nobody overrides Node::deref so it's safe - break; // There might be at most one wrapper for the node in world's maps + node->deref(); // Nobody overrides Node::deref so it's safe + return; // There might be at most one wrapper for the node in world's maps } } + + // If not found, it means map for the wrapper has been already destroyed, just dispose the + // handle and deref the object to fight memory leak. + v8Object.Dispose(); + node->deref(); // Nobody overrides Node::deref so it's safe } bool DOMDataStore::IntrusiveDOMWrapperMap::removeIfPresent(Node* obj, v8::Persistent<v8::Data> value) diff --git a/WebCore/bindings/v8/ScriptArray.cpp b/WebCore/bindings/v8/ScriptArray.cpp index a199a6c..7119b27 100644 --- a/WebCore/bindings/v8/ScriptArray.cpp +++ b/WebCore/bindings/v8/ScriptArray.cpp @@ -31,11 +31,11 @@ #include "config.h" #include "ScriptArray.h" -#include "ScriptScope.h" -#include "ScriptState.h" - #include "Document.h" #include "Frame.h" +#include "ScriptScope.h" +#include "ScriptState.h" +#include "SerializedScriptValue.h" #include "V8Binding.h" #include "V8Proxy.h" @@ -57,6 +57,19 @@ bool ScriptArray::set(unsigned index, const ScriptObject& value) return scope.success(); } +bool ScriptArray::set(unsigned index, SerializedScriptValue* value) +{ + ScriptValue scriptValue = ScriptValue::deserialize(m_scriptState, value); + if (scriptValue.hasNoValue()) { + ASSERT_NOT_REACHED(); + return false; + } + + ScriptScope scope(m_scriptState); + v8Object()->Set(v8::Integer::New(index), scriptValue.v8Value()); + return scope.success(); +} + bool ScriptArray::set(unsigned index, const String& value) { ScriptScope scope(m_scriptState); diff --git a/WebCore/bindings/v8/ScriptArray.h b/WebCore/bindings/v8/ScriptArray.h index 9f40fbf..9aa8764 100644 --- a/WebCore/bindings/v8/ScriptArray.h +++ b/WebCore/bindings/v8/ScriptArray.h @@ -36,24 +36,26 @@ #include <v8.h> namespace WebCore { - class ScriptState; - - class ScriptArray : public ScriptObject { - public: - ScriptArray(ScriptState* scriptState, v8::Handle<v8::Array>); - ScriptArray() {}; - virtual ~ScriptArray() {} - - bool set(unsigned index, const ScriptObject&); - bool set(unsigned index, const String&); - bool set(unsigned index, double); - bool set(unsigned index, long long); - bool set(unsigned index, int); - bool set(unsigned index, bool); - unsigned length(); - - static ScriptArray createNew(ScriptState*); - }; +class ScriptState; +class SerializedScriptValue; + +class ScriptArray : public ScriptObject { +public: + ScriptArray(ScriptState* scriptState, v8::Handle<v8::Array>); + ScriptArray() {}; + virtual ~ScriptArray() {} + + bool set(unsigned index, const ScriptObject&); + bool set(unsigned index, SerializedScriptValue*); + bool set(unsigned index, const String&); + bool set(unsigned index, double); + bool set(unsigned index, long long); + bool set(unsigned index, int); + bool set(unsigned index, bool); + unsigned length(); + + static ScriptArray createNew(ScriptState*); +}; } #endif // ScriptArray_h diff --git a/WebCore/bindings/v8/ScriptCallFrame.cpp b/WebCore/bindings/v8/ScriptCallFrame.cpp index 4c29814..9554f67 100644 --- a/WebCore/bindings/v8/ScriptCallFrame.cpp +++ b/WebCore/bindings/v8/ScriptCallFrame.cpp @@ -45,10 +45,17 @@ ScriptCallFrame::ScriptCallFrame(const String& functionName, const String& urlSt , m_sourceURL(ParsedURLString, urlString) , m_lineNumber(lineNumber) { - for (int i = 0; i < arguments.Length(); ++i) + for (int i = skipArgumentCount; i < arguments.Length(); ++i) m_arguments.append(ScriptValue(arguments[i])); } +ScriptCallFrame::ScriptCallFrame(const String& functionName, const String& urlString, int lineNumber) + : m_functionName(functionName) + , m_sourceURL(ParsedURLString, urlString) + , m_lineNumber(lineNumber) +{ +} + ScriptCallFrame::~ScriptCallFrame() { } diff --git a/WebCore/bindings/v8/ScriptCallFrame.h b/WebCore/bindings/v8/ScriptCallFrame.h index 50357cf..8d1972f 100644 --- a/WebCore/bindings/v8/ScriptCallFrame.h +++ b/WebCore/bindings/v8/ScriptCallFrame.h @@ -50,6 +50,7 @@ namespace WebCore { class ScriptCallFrame { public: ScriptCallFrame(const String& functionName, const String& urlString, int lineNumber, const v8::Arguments&, unsigned skipArgumentCount); + ScriptCallFrame(const String& functionName, const String& urlString, int lineNumber); ~ScriptCallFrame(); const ScriptString& functionName() const { return m_functionName; } diff --git a/WebCore/bindings/v8/ScriptCallStack.cpp b/WebCore/bindings/v8/ScriptCallStack.cpp index d62175a..98ddb90 100644 --- a/WebCore/bindings/v8/ScriptCallStack.cpp +++ b/WebCore/bindings/v8/ScriptCallStack.cpp @@ -32,68 +32,122 @@ #include "ScriptCallStack.h" #include "InspectorValues.h" -#include "ScriptScope.h" #include "ScriptController.h" #include "ScriptDebugServer.h" +#include "ScriptScope.h" #include "V8Binding.h" #include <v8-debug.h> namespace WebCore { -ScriptCallStack* ScriptCallStack::create(const v8::Arguments& arguments, unsigned skipArgumentCount) { - String sourceName; - int sourceLineNumber; - String funcName; - if (!callLocation(&sourceName, &sourceLineNumber, &funcName)) - return 0; - return new ScriptCallStack(arguments, skipArgumentCount, sourceName, sourceLineNumber, funcName); -} - -bool ScriptCallStack::callLocation(String* sourceName, int* sourceLineNumber, String* functionName) +static void getFrameLocation(v8::Handle<v8::StackFrame> frame, String* sourceName, int* sourceLineNumber, String* functionName) { - v8::HandleScope scope; - v8::Context::Scope contextScope(v8::Context::GetCurrent()); - v8::Handle<v8::StackTrace> stackTrace(v8::StackTrace::CurrentStackTrace(1)); - if (stackTrace.IsEmpty()) - return false; - if (stackTrace->GetFrameCount() <= 0) { - // Successfully grabbed stack trace, but there are no frames. - // Fallback to setting lineNumber to 0, and source and function name to "undefined". - *sourceName = toWebCoreString(v8::Undefined()); - *sourceLineNumber = 0; - *functionName = toWebCoreString(v8::Undefined()); - return true; - } - v8::Handle<v8::StackFrame> frame = stackTrace->GetFrame(0); - // There must be at least one valid frame. ASSERT(!frame.IsEmpty()); v8::Local<v8::String> sourceNameValue(frame->GetScriptName()); v8::Local<v8::String> functionNameValue(frame->GetFunctionName()); *sourceName = sourceNameValue.IsEmpty() ? "" : toWebCoreString(sourceNameValue); *functionName = functionNameValue.IsEmpty() ? "" : toWebCoreString(functionNameValue); *sourceLineNumber = frame->GetLineNumber(); - return true; } -ScriptCallStack::ScriptCallStack(const v8::Arguments& arguments, unsigned skipArgumentCount, String sourceName, int sourceLineNumber, String functionName) - : m_lastCaller(functionName, sourceName, sourceLineNumber, arguments, skipArgumentCount) - , m_scriptState(ScriptState::current()) +static void getTopFrameLocation(v8::Handle<v8::StackTrace> stackTrace, String* sourceName, int* sourceLineNumber, String* functionName) +{ + if (stackTrace->GetFrameCount() <= 0) { + // Successfully grabbed stack trace, but there are no frames. It may happen in case of a syntax error for example. + // Fallback to setting lineNumber to 0, and source and function name to "undefined". + *sourceName = "undefined"; + *sourceLineNumber = 0; + *functionName = "undefined"; + } else { + v8::Handle<v8::StackFrame> frame = stackTrace->GetFrame(0); + getFrameLocation(frame, sourceName, sourceLineNumber, functionName); + } +} + +static PassOwnPtr<ScriptCallFrame> toScriptCallFrame(v8::Handle<v8::StackFrame> frame) +{ + String sourceName; + int sourceLineNumber; + String functionName; + getFrameLocation(frame, &sourceName, &sourceLineNumber, &functionName); + return new ScriptCallFrame(functionName, sourceName, sourceLineNumber); +} + +static void toScriptCallFramesVector(v8::Local<v8::Context> context, v8::Handle<v8::StackTrace> stackTrace, Vector<OwnPtr<ScriptCallFrame> >& scriptCallFrames) +{ + v8::Context::Scope contextScope(context); + int frameCount = stackTrace->GetFrameCount(); + for (int i = 0; i < frameCount; i++) { + v8::Local<v8::StackFrame> stackFrame = stackTrace->GetFrame(i); + scriptCallFrames.append(toScriptCallFrame(stackFrame)); + } +} + +const int ScriptCallStack::maxCallStackSizeToCapture = 200; + +PassOwnPtr<ScriptCallStack> ScriptCallStack::create(const v8::Arguments& arguments, unsigned skipArgumentCount, int framCountLimit) +{ + v8::HandleScope scope; + v8::Local<v8::Context> context = v8::Context::GetCurrent(); + v8::Context::Scope contextScope(context); + v8::Handle<v8::StackTrace> stackTrace(v8::StackTrace::CurrentStackTrace(framCountLimit)); + + if (stackTrace.IsEmpty()) + return 0; + + String sourceName; + int sourceLineNumber; + String functionName; + getTopFrameLocation(stackTrace, &sourceName, &sourceLineNumber, &functionName); + + Vector<OwnPtr<ScriptCallFrame> > scriptCallFrames; + if (framCountLimit > 1) + toScriptCallFramesVector(context, stackTrace, scriptCallFrames); + + return new ScriptCallStack(ScriptState::forContext(context), new ScriptCallFrame(functionName, sourceName, sourceLineNumber, arguments, skipArgumentCount), scriptCallFrames); +} + +PassOwnPtr<ScriptCallStack> ScriptCallStack::create(ScriptState* state, v8::Handle<v8::StackTrace> stackTrace) +{ + v8::HandleScope scope; + Vector<OwnPtr<ScriptCallFrame> > scriptCallFrames; + toScriptCallFramesVector(state->context(), stackTrace, scriptCallFrames); + + String sourceName; + int sourceLineNumber; + String functionName; + getTopFrameLocation(stackTrace, &sourceName, &sourceLineNumber, &functionName); + + return new ScriptCallStack(state, new ScriptCallFrame(functionName, sourceName, sourceLineNumber), scriptCallFrames); +} + +ScriptCallStack::ScriptCallStack(ScriptState* scriptState, PassOwnPtr<ScriptCallFrame> topFrame, Vector<OwnPtr<ScriptCallFrame> >& scriptCallFrames) + : m_topFrame(topFrame) + , m_scriptState(scriptState) { + m_scriptCallFrames.swap(scriptCallFrames); } ScriptCallStack::~ScriptCallStack() { } -const ScriptCallFrame& ScriptCallStack::at(unsigned index) const +const ScriptCallFrame& ScriptCallStack::at(unsigned index) { - // Currently, only one ScriptCallFrame is supported. When we can get - // a full stack trace from V8, we can do this right. - ASSERT(index == 0); - return m_lastCaller; + if (!index && m_topFrame) + return *m_topFrame; + return *m_scriptCallFrames.at(index); } +unsigned ScriptCallStack::size() +{ + if (m_scriptCallFrames.isEmpty()) + return 1; + return m_scriptCallFrames.size(); +} + + bool ScriptCallStack::stackTrace(int frameLimit, const RefPtr<InspectorArray>& stackTrace) { #if ENABLE(INSPECTOR) diff --git a/WebCore/bindings/v8/ScriptCallStack.h b/WebCore/bindings/v8/ScriptCallStack.h index 80d5f76..b608563 100644 --- a/WebCore/bindings/v8/ScriptCallStack.h +++ b/WebCore/bindings/v8/ScriptCallStack.h @@ -48,7 +48,10 @@ class InspectorArray; class ScriptCallStack : public Noncopyable { public: - static ScriptCallStack* create(const v8::Arguments&, unsigned skipArgumentCount = 0); + static const int maxCallStackSizeToCapture; + + static PassOwnPtr<ScriptCallStack> create(const v8::Arguments&, unsigned skipArgumentCount = 0, int framCountLimit = 1); + static PassOwnPtr<ScriptCallStack> create(ScriptState*, v8::Handle<v8::StackTrace>); ~ScriptCallStack(); // Returns false if there is no running JavaScript or if fetching the stack failed. @@ -62,20 +65,19 @@ public: // } static bool stackTrace(int frameLimit, const RefPtr<InspectorArray>& stackTrace); - const ScriptCallFrame& at(unsigned) const; - // FIXME: implement retrieving and storing call stack trace - unsigned size() const { return 1; } + const ScriptCallFrame& at(unsigned); + unsigned size(); ScriptState* state() const { return m_scriptState; } ScriptState* globalState() const { return m_scriptState; } private: - ScriptCallStack(const v8::Arguments& arguments, unsigned skipArgumentCount, String sourceName, int sourceLineNumber, String funcName); - - static bool callLocation(String* sourceName, int* sourceLineNumber, String* functionName); + ScriptCallStack(ScriptState* scriptState, PassOwnPtr<ScriptCallFrame> topFrame, Vector<OwnPtr<ScriptCallFrame> >& scriptCallFrames); + ScriptCallStack(ScriptState* scriptState, v8::Handle<v8::StackTrace> stackTrace); - ScriptCallFrame m_lastCaller; + OwnPtr<ScriptCallFrame> m_topFrame; ScriptState* m_scriptState; + Vector<OwnPtr<ScriptCallFrame> > m_scriptCallFrames; }; } // namespace WebCore diff --git a/WebCore/bindings/v8/ScriptController.cpp b/WebCore/bindings/v8/ScriptController.cpp index 2396de0..a27c5cf 100644 --- a/WebCore/bindings/v8/ScriptController.cpp +++ b/WebCore/bindings/v8/ScriptController.cpp @@ -34,6 +34,7 @@ #include "PlatformBridge.h" #include "Document.h" +#include "ScriptCallStack.h" #include "ScriptableDocumentParser.h" #include "DOMWindow.h" #include "Event.h" @@ -464,6 +465,13 @@ void ScriptController::clearWindowShell(bool) m_proxy->clearForNavigation(); } +#if ENABLE(INSPECTOR) +void ScriptController::setCaptureCallStackForUncaughtExceptions(bool) +{ + v8::V8::SetCaptureStackTraceForUncaughtExceptions(true, ScriptCallStack::maxCallStackSizeToCapture); +} +#endif + void ScriptController::attachDebugger(void*) { notImplemented(); @@ -476,12 +484,10 @@ void ScriptController::updateDocument() void ScriptController::namedItemAdded(HTMLDocument* doc, const AtomicString& name) { - m_proxy->windowShell()->namedItemAdded(doc, name); } void ScriptController::namedItemRemoved(HTMLDocument* doc, const AtomicString& name) { - m_proxy->windowShell()->namedItemRemoved(doc, name); } } // namespace WebCore diff --git a/WebCore/bindings/v8/ScriptController.h b/WebCore/bindings/v8/ScriptController.h index 75ae0bf..04a15f6 100644 --- a/WebCore/bindings/v8/ScriptController.h +++ b/WebCore/bindings/v8/ScriptController.h @@ -116,6 +116,10 @@ public: static bool canAccessFromCurrentOrigin(Frame*); +#if ENABLE(INSPECTOR) + static void setCaptureCallStackForUncaughtExceptions(bool); +#endif + bool canExecuteScripts(ReasonForCallingCanExecuteScripts); // FIXME: void* is a compile hack. diff --git a/WebCore/bindings/v8/ScriptDebugServer.cpp b/WebCore/bindings/v8/ScriptDebugServer.cpp index 138237b..0a432b7 100644 --- a/WebCore/bindings/v8/ScriptDebugServer.cpp +++ b/WebCore/bindings/v8/ScriptDebugServer.cpp @@ -44,7 +44,6 @@ namespace WebCore { -#if ENABLE(V8_SCRIPT_DEBUG_SERVER) static Frame* retrieveFrame(v8::Handle<v8::Context> context) { if (context.IsEmpty()) @@ -61,7 +60,6 @@ static Frame* retrieveFrame(v8::Handle<v8::Context> context) return V8Proxy::retrieveFrame(context); } -#endif ScriptDebugServer& ScriptDebugServer::shared() { @@ -83,9 +81,13 @@ void ScriptDebugServer::setDebuggerScriptSource(const String& scriptSource) void ScriptDebugServer::addListener(ScriptDebugListener* listener, Page* page) { -#if ENABLE(V8_SCRIPT_DEBUG_SERVER) if (!m_enabled) return; + + V8Proxy* proxy = V8Proxy::retrieve(page->mainFrame()); + if (!proxy) + return; + v8::HandleScope scope; v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); v8::Context::Scope contextScope(debuggerContext); @@ -96,7 +98,7 @@ void ScriptDebugServer::addListener(ScriptDebugListener* listener, Page* page) v8::Debug::SetDebugEventListener2(&ScriptDebugServer::v8DebugEventCallback); } m_listenersMap.set(page, listener); - V8Proxy* proxy = V8Proxy::retrieve(page->mainFrame()); + v8::Local<v8::Context> context = proxy->mainWorldContext(); v8::Handle<v8::Function> getScriptsFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("getScripts"))); @@ -108,7 +110,6 @@ void ScriptDebugServer::addListener(ScriptDebugListener* listener, Page* page) v8::Handle<v8::Array> scriptsArray = v8::Handle<v8::Array>::Cast(value); for (unsigned i = 0; i < scriptsArray->Length(); ++i) dispatchDidParseSource(listener, v8::Handle<v8::Object>::Cast(scriptsArray->Get(v8::Integer::New(i)))); -#endif } void ScriptDebugServer::removeListener(ScriptDebugListener* listener, Page* page) @@ -128,7 +129,6 @@ void ScriptDebugServer::removeListener(ScriptDebugListener* listener, Page* page bool ScriptDebugServer::setBreakpoint(const String& sourceID, ScriptBreakpoint breakpoint, unsigned lineNumber, unsigned* actualLineNumber) { -#if ENABLE(V8_SCRIPT_DEBUG_SERVER) v8::HandleScope scope; v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); v8::Context::Scope contextScope(debuggerContext); @@ -146,14 +146,10 @@ bool ScriptDebugServer::setBreakpoint(const String& sourceID, ScriptBreakpoint b ASSERT(result->Int32Value() >= 0); *actualLineNumber = result->Int32Value(); return true; -#else - return false; -#endif } void ScriptDebugServer::removeBreakpoint(const String& sourceID, unsigned lineNumber) { -#if ENABLE(V8_SCRIPT_DEBUG_SERVER) v8::HandleScope scope; v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); v8::Context::Scope contextScope(debuggerContext); @@ -164,12 +160,10 @@ void ScriptDebugServer::removeBreakpoint(const String& sourceID, unsigned lineNu v8::Handle<v8::Function> removeBreakpointFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("removeBreakpoint"))); v8::Debug::Call(removeBreakpointFunction, args); -#endif } void ScriptDebugServer::clearBreakpoints() { -#if ENABLE(V8_SCRIPT_DEBUG_SERVER) ensureDebuggerScriptCompiled(); v8::HandleScope scope; v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); @@ -177,12 +171,10 @@ void ScriptDebugServer::clearBreakpoints() v8::Handle<v8::Function> clearBreakpoints = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("clearBreakpoints"))); v8::Debug::Call(clearBreakpoints); -#endif } void ScriptDebugServer::setBreakpointsActivated(bool enabled) { -#if ENABLE(V8_SCRIPT_DEBUG_SERVER) ensureDebuggerScriptCompiled(); v8::HandleScope scope; v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); @@ -192,12 +184,10 @@ void ScriptDebugServer::setBreakpointsActivated(bool enabled) args->Set(v8::String::New("enabled"), v8::Boolean::New(enabled)); v8::Handle<v8::Function> setBreakpointsActivated = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("setBreakpointsActivated"))); v8::Debug::Call(setBreakpointsActivated, args); -#endif } ScriptDebugServer::PauseOnExceptionsState ScriptDebugServer::pauseOnExceptionsState() { -#if ENABLE(V8_SCRIPT_DEBUG_SERVER) ensureDebuggerScriptCompiled(); v8::HandleScope scope; v8::Context::Scope contextScope(v8::Debug::GetDebugContext()); @@ -206,14 +196,10 @@ ScriptDebugServer::PauseOnExceptionsState ScriptDebugServer::pauseOnExceptionsSt v8::Handle<v8::Value> argv[] = { v8::Handle<v8::Value>() }; v8::Handle<v8::Value> result = function->Call(m_debuggerScript.get(), 0, argv); return static_cast<ScriptDebugServer::PauseOnExceptionsState>(result->Int32Value()); -#else - return DontPauseOnExceptions; -#endif } void ScriptDebugServer::setPauseOnExceptionsState(PauseOnExceptionsState pauseOnExceptionsState) { -#if ENABLE(V8_SCRIPT_DEBUG_SERVER) ensureDebuggerScriptCompiled(); v8::HandleScope scope; v8::Context::Scope contextScope(v8::Debug::GetDebugContext()); @@ -221,54 +207,44 @@ void ScriptDebugServer::setPauseOnExceptionsState(PauseOnExceptionsState pauseOn v8::Handle<v8::Function> setPauseOnExceptionsFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("setPauseOnExceptionsState"))); v8::Handle<v8::Value> argv[] = { v8::Int32::New(pauseOnExceptionsState) }; setPauseOnExceptionsFunction->Call(m_debuggerScript.get(), 1, argv); -#endif } void ScriptDebugServer::continueProgram() { -#if ENABLE(V8_SCRIPT_DEBUG_SERVER) if (m_pausedPage) m_clientMessageLoop->quitNow(); didResume(); -#endif } void ScriptDebugServer::stepIntoStatement() { -#if ENABLE(V8_SCRIPT_DEBUG_SERVER) ASSERT(m_pausedPage); v8::Handle<v8::Function> function = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("stepIntoStatement"))); v8::Handle<v8::Value> argv[] = { m_executionState.get() }; function->Call(m_debuggerScript.get(), 1, argv); continueProgram(); -#endif } void ScriptDebugServer::stepOverStatement() { -#if ENABLE(V8_SCRIPT_DEBUG_SERVER) ASSERT(m_pausedPage); v8::Handle<v8::Function> function = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("stepOverStatement"))); v8::Handle<v8::Value> argv[] = { m_executionState.get() }; function->Call(m_debuggerScript.get(), 1, argv); continueProgram(); -#endif } void ScriptDebugServer::stepOutOfFunction() { -#if ENABLE(V8_SCRIPT_DEBUG_SERVER) ASSERT(m_pausedPage); v8::Handle<v8::Function> function = v8::Local<v8::Function>::Cast(m_debuggerScript.get()->Get(v8::String::New("stepOutOfFunction"))); v8::Handle<v8::Value> argv[] = { m_executionState.get() }; function->Call(m_debuggerScript.get(), 1, argv); continueProgram(); -#endif } bool ScriptDebugServer::editScriptSource(const String& sourceID, const String& newContent, String& newSourceOrErrorMessage) { -#if ENABLE(V8_SCRIPT_DEBUG_SERVER) ensureDebuggerScriptCompiled(); v8::HandleScope scope; @@ -295,9 +271,6 @@ bool ScriptDebugServer::editScriptSource(const String& sourceID, const String& n if (m_currentCallFrame) m_currentCallFrame.clear(); return true; -#else - return false; -#endif } PassRefPtr<JavaScriptCallFrame> ScriptDebugServer::currentCallFrame() @@ -321,7 +294,6 @@ bool ScriptDebugServer::isDebuggerAlwaysEnabled() return m_enabled; } -#if ENABLE(V8_SCRIPT_DEBUG_SERVER) void ScriptDebugServer::v8DebugEventCallback(const v8::Debug::EventDetails& eventDetails) { ScriptDebugServer::shared().handleV8DebugEvent(eventDetails); @@ -376,7 +348,6 @@ void ScriptDebugServer::handleV8DebugEvent(const v8::Debug::EventDetails& eventD } } } -#endif void ScriptDebugServer::dispatchDidParseSource(ScriptDebugListener* listener, v8::Handle<v8::Object> object) { diff --git a/WebCore/bindings/v8/ScriptDebugServer.h b/WebCore/bindings/v8/ScriptDebugServer.h index 26ca785..a55388f 100644 --- a/WebCore/bindings/v8/ScriptDebugServer.h +++ b/WebCore/bindings/v8/ScriptDebugServer.h @@ -59,6 +59,8 @@ public: void removeBreakpoint(const String& sourceID, unsigned lineNumber); void clearBreakpoints(); void setBreakpointsActivated(bool activated); + void activateBreakpoints() { setBreakpointsActivated(true); } + void deactivateBreakpoints() { setBreakpointsActivated(false); } enum PauseOnExceptionsState { DontPauseOnExceptions, @@ -68,7 +70,7 @@ public: PauseOnExceptionsState pauseOnExceptionsState(); void setPauseOnExceptionsState(PauseOnExceptionsState pauseOnExceptionsState); - void pauseProgram() { } + void pause() { } void continueProgram(); void stepIntoStatement(); void stepOverStatement(); @@ -101,10 +103,8 @@ private: ScriptDebugServer(); ~ScriptDebugServer() { } -#if ENABLE(V8_SCRIPT_DEBUG_SERVER) static void v8DebugEventCallback(const v8::Debug::EventDetails& eventDetails); void handleV8DebugEvent(const v8::Debug::EventDetails& eventDetails); -#endif void dispatchDidParseSource(ScriptDebugListener* listener, v8::Handle<v8::Object> sourceObject); diff --git a/WebCore/bindings/v8/ScriptSourceCode.h b/WebCore/bindings/v8/ScriptSourceCode.h index 485daea..dbc9d5e 100644 --- a/WebCore/bindings/v8/ScriptSourceCode.h +++ b/WebCore/bindings/v8/ScriptSourceCode.h @@ -46,14 +46,6 @@ public: , m_url(url) , m_startLine(startLine) { - // FIXME: Copying the source to strip BOMs isn't strictly necessary - // because V8 treats BOMs as whitespace. However, it is here because it - // must be in sync with CachedScript::script() which strips the BOMs. We - // should investigate the performance implications. - if (m_source.length()) { - bool scratch = false; - m_source = String(source.impl()->copyStringWithoutBOMs(false, scratch)); - } } // We lose the encoding information from CachedScript. diff --git a/WebCore/bindings/v8/V8ConsoleMessage.cpp b/WebCore/bindings/v8/V8ConsoleMessage.cpp index d9fe069..8b6bb17 100644 --- a/WebCore/bindings/v8/V8ConsoleMessage.cpp +++ b/WebCore/bindings/v8/V8ConsoleMessage.cpp @@ -36,6 +36,7 @@ #include "Frame.h" #include "OwnPtr.h" #include "Page.h" +#include "ScriptCallStack.h" #include "V8Binding.h" #include "V8Proxy.h" @@ -52,14 +53,7 @@ V8ConsoleMessage::V8ConsoleMessage(const String& string, const String& sourceID, void V8ConsoleMessage::dispatchNow(Page* page) { - ASSERT(page); - - // Process any delayed messages to make sure that messages - // appear in the right order in the console. - processDelayed(); - - Console* console = page->mainFrame()->domWindow()->console(); - console->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, m_string, m_lineNumber, m_sourceID); + dispatchNow(page, 0); } void V8ConsoleMessage::dispatchLater() @@ -118,11 +112,33 @@ void V8ConsoleMessage::handler(v8::Handle<v8::Message> message, v8::Handle<v8::V ASSERT(!errorMessageString.IsEmpty()); String errorMessage = toWebCoreString(errorMessageString); + v8::Handle<v8::StackTrace> stackTrace = message->GetStackTrace(); + OwnPtr<ScriptCallStack> callStack; + // Currently stack trace is only collected when inspector is open. + if (!stackTrace.IsEmpty() && stackTrace->GetFrameCount() > 0) { + v8::Local<v8::Context> context = v8::Context::GetEntered(); + ScriptState* scriptState = ScriptState::forContext(context); + callStack = ScriptCallStack::create(scriptState, stackTrace); + } + v8::Handle<v8::Value> resourceName = message->GetScriptResourceName(); bool useURL = resourceName.IsEmpty() || !resourceName->IsString(); String resourceNameString = useURL ? frame->document()->url() : toWebCoreString(resourceName); V8ConsoleMessage consoleMessage(errorMessage, resourceNameString, message->GetLineNumber()); - consoleMessage.dispatchNow(page); + consoleMessage.dispatchNow(page, callStack.get()); +} + +void V8ConsoleMessage::dispatchNow(Page* page, ScriptCallStack* callStack) +{ + ASSERT(page); + + // Process any delayed messages to make sure that messages + // appear in the right order in the console. + processDelayed(); + + Console* console = page->mainFrame()->domWindow()->console(); + MessageType messageType = callStack ? UncaughtExceptionMessageType : LogMessageType; + console->addMessage(JSMessageSource, messageType, ErrorMessageLevel, m_string, m_lineNumber, m_sourceID, callStack); } } // namespace WebCore diff --git a/WebCore/bindings/v8/V8ConsoleMessage.h b/WebCore/bindings/v8/V8ConsoleMessage.h index a8f75ee..387b5ee 100644 --- a/WebCore/bindings/v8/V8ConsoleMessage.h +++ b/WebCore/bindings/v8/V8ConsoleMessage.h @@ -36,8 +36,9 @@ #include <wtf/Vector.h> namespace WebCore { - + class Page; + class ScriptCallStack; // V8ConsoleMessage encapsulates everything needed to // log messages originating from JavaScript to the console. @@ -80,6 +81,8 @@ namespace WebCore { const String m_sourceID; const unsigned m_lineNumber; + void dispatchNow(Page*, ScriptCallStack*); + // All delayed messages are stored in this vector. If the vector // is 0, there are no delayed messages. static Vector<V8ConsoleMessage>* m_delayedMessages; diff --git a/WebCore/bindings/v8/V8DOMMap.h b/WebCore/bindings/v8/V8DOMMap.h index a7e03a0..d8d5c04 100644 --- a/WebCore/bindings/v8/V8DOMMap.h +++ b/WebCore/bindings/v8/V8DOMMap.h @@ -74,13 +74,7 @@ namespace WebCore { public: typedef AbstractWeakReferenceMap<KeyType, ValueType> Parent; WeakReferenceMap(v8::WeakReferenceCallback callback) : Parent(callback) { } - virtual ~WeakReferenceMap() - { - #ifndef NDEBUG - if (m_map.size() > 0) - fprintf(stderr, "Leak %d JS wrappers.\n", m_map.size()); - #endif - } + virtual ~WeakReferenceMap() { } // Get the JS wrapper object of an object. virtual v8::Persistent<ValueType> get(KeyType* obj) @@ -135,7 +129,6 @@ namespace WebCore { protected: HashMap<KeyType*, ValueType*> m_map; - v8::WeakReferenceCallback m_weakReferenceCallback; }; template <class KeyType> class DOMWrapperMap : public WeakReferenceMap<KeyType, v8::Object> { diff --git a/WebCore/bindings/v8/V8DOMWindowShell.cpp b/WebCore/bindings/v8/V8DOMWindowShell.cpp index 99fea4c..c7c77d3 100644 --- a/WebCore/bindings/v8/V8DOMWindowShell.cpp +++ b/WebCore/bindings/v8/V8DOMWindowShell.cpp @@ -50,7 +50,6 @@ #include "V8DOMWindow.h" #include "V8Document.h" #include "V8GCForContextDispose.h" -#include "V8HTMLDocument.h" #include "V8HiddenPropertyName.h" #include "V8History.h" #include "V8Location.h" @@ -415,12 +414,6 @@ void V8DOMWindowShell::clearDocumentWrapper() } } -static void checkDocumentWrapper(v8::Handle<v8::Object> wrapper, Document* document) -{ - ASSERT(V8Document::toNative(wrapper) == document); - ASSERT(!document->isHTMLDocument() || (V8Document::toNative(v8::Handle<v8::Object>::Cast(wrapper->GetPrototype())) == document)); -} - void V8DOMWindowShell::updateDocumentWrapperCache() { v8::HandleScope handleScope; @@ -439,10 +432,6 @@ void V8DOMWindowShell::updateDocumentWrapperCache() } v8::Handle<v8::Value> documentWrapper = toV8(m_frame->document()); - ASSERT(documentWrapper == m_document || m_document.IsEmpty()); - if (m_document.IsEmpty()) - updateDocumentWrapper(v8::Handle<v8::Object>::Cast(documentWrapper)); - checkDocumentWrapper(m_document, m_frame->document()); // If instantiation of the document wrapper fails, clear the cache // and let the DOMWindow accessor handle access to the document. @@ -520,39 +509,6 @@ void V8DOMWindowShell::updateDocument() updateSecurityOrigin(); } -v8::Handle<v8::Value> getter(v8::Local<v8::String> property, const v8::AccessorInfo& info) -{ - // FIXME(antonm): consider passing AtomicStringImpl directly. - AtomicString name = v8StringToAtomicWebCoreString(property); - HTMLDocument* htmlDocument = V8HTMLDocument::toNative(info.Holder()); - ASSERT(htmlDocument); - return V8HTMLDocument::GetNamedProperty(htmlDocument, name); -} - -void V8DOMWindowShell::namedItemAdded(HTMLDocument* doc, const AtomicString& name) -{ - initContextIfNeeded(); - - v8::HandleScope handleScope; - v8::Context::Scope contextScope(m_context); - - ASSERT(!m_document.IsEmpty()); - checkDocumentWrapper(m_document, doc); - m_document->SetAccessor(v8String(name), getter); -} - -void V8DOMWindowShell::namedItemRemoved(HTMLDocument* doc, const AtomicString& name) -{ - initContextIfNeeded(); - - v8::HandleScope handleScope; - v8::Context::Scope contextScope(m_context); - - ASSERT(!m_document.IsEmpty()); - checkDocumentWrapper(m_document, doc); - m_document->Delete(v8String(name)); -} - void V8DOMWindowShell::updateSecurityOrigin() { v8::HandleScope scope; diff --git a/WebCore/bindings/v8/V8DOMWindowShell.h b/WebCore/bindings/v8/V8DOMWindowShell.h index 3cf1b52..f4eaff2 100644 --- a/WebCore/bindings/v8/V8DOMWindowShell.h +++ b/WebCore/bindings/v8/V8DOMWindowShell.h @@ -31,7 +31,6 @@ #ifndef V8DOMWindowShell_h #define V8DOMWindowShell_h -#include "AtomicString.h" #include "WrapperTypeInfo.h" #include <wtf/HashMap.h> #include <wtf/PassRefPtr.h> @@ -42,7 +41,6 @@ namespace WebCore { class DOMWindow; class Frame; -class HTMLDocument; class String; // V8WindowShell represents all the per-global object state for a Frame that @@ -56,9 +54,6 @@ public: // Update document object of the frame. void updateDocument(); - void namedItemAdded(HTMLDocument*, const AtomicString&); - void namedItemRemoved(HTMLDocument*, const AtomicString&); - // Update the security origin of a document // (e.g., after setting docoument.domain). void updateSecurityOrigin(); diff --git a/WebCore/bindings/v8/V8DOMWrapper.cpp b/WebCore/bindings/v8/V8DOMWrapper.cpp index b5703d2..4a09c34 100644 --- a/WebCore/bindings/v8/V8DOMWrapper.cpp +++ b/WebCore/bindings/v8/V8DOMWrapper.cpp @@ -284,8 +284,6 @@ v8::Local<v8::Object> V8DOMWrapper::instantiateV8Object(V8Proxy* proxy, WrapperT if (!instance.IsEmpty()) { // Avoid setting the DOM wrapper for failed allocations. setDOMWrapper(instance, type, impl); - if (type == &V8HTMLDocument::info) - instance = V8HTMLDocument::WrapInShadowObject(instance, static_cast<Node*>(impl)); } return instance; } diff --git a/WebCore/bindings/v8/custom/V8ConsoleCustom.cpp b/WebCore/bindings/v8/custom/V8ConsoleCustom.cpp index 62838a0..baffbd4 100644 --- a/WebCore/bindings/v8/custom/V8ConsoleCustom.cpp +++ b/WebCore/bindings/v8/custom/V8ConsoleCustom.cpp @@ -33,10 +33,9 @@ #include "V8Console.h" #include "Console.h" -#include "MemoryInfo.h" +#include "ScriptCallStack.h" #include "ScriptProfile.h" #include "V8Binding.h" -#include "V8MemoryInfo.h" #include "V8Proxy.h" #include "V8ScriptProfile.h" @@ -59,10 +58,26 @@ v8::Handle<v8::Value> V8Console::profilesAccessorGetter(v8::Local<v8::String> na } #endif -v8::Handle<v8::Value> V8Console::memoryAccessorGetter(v8::Local<v8::String>, const v8::AccessorInfo&) +v8::Handle<v8::Value> V8Console::traceCallback(const v8::Arguments& args) { - INC_STATS("DOM.Console.memoryAccessorGetter"); - return toV8(MemoryInfo::create()); + INC_STATS("DOM.Console.traceCallback"); + Console* imp = V8Console::toNative(args.Holder()); + v8::HandleScope handleScope; + ScriptState* scriptState = ScriptState::current(); + v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(ScriptCallStack::maxCallStackSizeToCapture); + OwnPtr<ScriptCallStack> callStack(ScriptCallStack::create(scriptState, stackTrace)); + imp->trace(callStack.get()); + return v8::Handle<v8::Value>(); +} + +v8::Handle<v8::Value> V8Console::assertCallback(const v8::Arguments& args) +{ + INC_STATS("DOM.Console.assertCallback"); + Console* imp = V8Console::toNative(args.Holder()); + OwnPtr<ScriptCallStack> callStack(ScriptCallStack::create(args, 1, ScriptCallStack::maxCallStackSizeToCapture)); + bool condition = args[0]->BooleanValue(); + imp->assertCondition(condition, callStack.get()); + return v8::Handle<v8::Value>(); } } // namespace WebCore diff --git a/WebCore/bindings/v8/custom/V8DeviceOrientationEventCustom.cpp b/WebCore/bindings/v8/custom/V8DeviceOrientationEventCustom.cpp new file mode 100644 index 0000000..26cc6cc --- /dev/null +++ b/WebCore/bindings/v8/custom/V8DeviceOrientationEventCustom.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2010 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``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 "V8DeviceOrientationEvent.h" + +#if ENABLE(DEVICE_ORIENTATION) + +#include "DeviceOrientation.h" +#include "V8Binding.h" +#include "V8Proxy.h" + +#include <v8.h> + +namespace WebCore { + +v8::Handle<v8::Value> V8DeviceOrientationEvent::alphaAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.DeviceOrientationEvent.alpha._get"); + v8::Handle<v8::Object> holder = info.Holder(); + DeviceOrientationEvent* imp = V8DeviceOrientationEvent::toNative(holder); + if (!imp->orientation()->canProvideAlpha()) + return v8::Null(); + return v8::Number::New(imp->orientation()->alpha()); +} + +v8::Handle<v8::Value> V8DeviceOrientationEvent::betaAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.DeviceOrientationEvent.beta._get"); + v8::Handle<v8::Object> holder = info.Holder(); + DeviceOrientationEvent* imp = V8DeviceOrientationEvent::toNative(holder); + if (!imp->orientation()->canProvideBeta()) + return v8::Null(); + return v8::Number::New(imp->orientation()->beta()); +} + +v8::Handle<v8::Value> V8DeviceOrientationEvent::gammaAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) +{ + INC_STATS("DOM.DeviceOrientationEvent.gamma._get"); + v8::Handle<v8::Object> holder = info.Holder(); + DeviceOrientationEvent* imp = V8DeviceOrientationEvent::toNative(holder); + if (!imp->orientation()->canProvideGamma()) + return v8::Null(); + return v8::Number::New(imp->orientation()->gamma()); +} + +v8::Handle<v8::Value> V8DeviceOrientationEvent::initDeviceOrientationEventCallback(const v8::Arguments& args) +{ + DeviceOrientationEvent* imp = V8DeviceOrientationEvent::toNative(args.Holder()); + V8Parameter<> type = args[0]; + bool bubbles = args[1]->BooleanValue(); + bool cancelable = args[2]->BooleanValue(); + // If alpha, beta or gamma are null or undefined, mark them as not provided. + // Otherwise, use the standard JavaScript conversion. + bool alphaProvided = !isUndefinedOrNull(args[3]); + double alpha = static_cast<double>(args[3]->NumberValue()); + bool betaProvided = !isUndefinedOrNull(args[4]); + double beta = static_cast<double>(args[4]->NumberValue()); + bool gammaProvided = !isUndefinedOrNull(args[5]); + double gamma = static_cast<double>(args[5]->NumberValue()); + RefPtr<DeviceOrientation> orientation = DeviceOrientation::create(alphaProvided, alpha, betaProvided, beta, gammaProvided, gamma); + imp->initDeviceOrientationEvent(type, bubbles, cancelable, orientation.get()); + return v8::Handle<v8::Value>(); +} + +} // namespace WebCore + +#endif // ENABLE(DEVICE_ORIENTATION) diff --git a/WebCore/bindings/v8/custom/V8HTMLDocumentCustom.cpp b/WebCore/bindings/v8/custom/V8HTMLDocumentCustom.cpp index 09f0a6f..86f2eb5 100644 --- a/WebCore/bindings/v8/custom/V8HTMLDocumentCustom.cpp +++ b/WebCore/bindings/v8/custom/V8HTMLDocumentCustom.cpp @@ -49,37 +49,48 @@ namespace WebCore { -v8::Local<v8::Object> V8HTMLDocument::WrapInShadowObject(v8::Local<v8::Object> wrapper, Node* impl) +v8::Handle<v8::Boolean> V8HTMLDocument::namedPropertyDeleter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { - DEFINE_STATIC_LOCAL(v8::Persistent<v8::FunctionTemplate>, shadowTemplate, ()); - if (shadowTemplate.IsEmpty()) { - shadowTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New()); - if (shadowTemplate.IsEmpty()) - return v8::Local<v8::Object>(); - shadowTemplate->SetClassName(v8::String::New("HTMLDocument")); - shadowTemplate->Inherit(V8HTMLDocument::GetTemplate()); - shadowTemplate->InstanceTemplate()->SetInternalFieldCount(V8HTMLDocument::internalFieldCount); - } - - v8::Local<v8::Function> shadowConstructor = shadowTemplate->GetFunction(); - if (shadowConstructor.IsEmpty()) - return v8::Local<v8::Object>(); - - v8::Local<v8::Object> shadow = shadowConstructor->NewInstance(); - if (shadow.IsEmpty()) - return v8::Local<v8::Object>(); - V8DOMWrapper::setDOMWrapper(shadow, &V8HTMLDocument::info, impl); - shadow->SetPrototype(wrapper); - return shadow; + // Only handle document.all. Insert the marker object into the + // shadow internal field to signal that document.all is no longer + // shadowed. + AtomicString key = v8StringToAtomicWebCoreString(name); + DEFINE_STATIC_LOCAL(const AtomicString, all, ("all")); + if (key != all) + return deletionNotHandledByInterceptor(); + + ASSERT(info.Holder()->InternalFieldCount() == V8HTMLDocument::internalFieldCount); + v8::Local<v8::Value> marker = info.Holder()->GetInternalField(V8HTMLDocument::markerIndex); + info.Holder()->SetInternalField(V8HTMLDocument::shadowIndex, marker); + return v8::True(); } -v8::Handle<v8::Value> V8HTMLDocument::GetNamedProperty(HTMLDocument* htmlDocument, const AtomicString& key) +v8::Handle<v8::Value> V8HTMLDocument::namedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) { - ASSERT(htmlDocument->hasNamedItem(key.impl()) || htmlDocument->hasExtraNamedItem(key.impl())); + INC_STATS("DOM.HTMLDocument.NamedPropertyGetter"); + AtomicString key = v8StringToAtomicWebCoreString(name); + + // Special case for document.all. If the value in the shadow + // internal field is not the marker object, then document.all has + // been temporarily shadowed and we return the value. + DEFINE_STATIC_LOCAL(const AtomicString, all, ("all")); + if (key == all) { + ASSERT(info.Holder()->InternalFieldCount() == V8HTMLDocument::internalFieldCount); + v8::Local<v8::Value> marker = info.Holder()->GetInternalField(V8HTMLDocument::markerIndex); + v8::Local<v8::Value> value = info.Holder()->GetInternalField(V8HTMLDocument::shadowIndex); + if (marker != value) + return value; + } + + HTMLDocument* htmlDocument = V8HTMLDocument::toNative(info.Holder()); + + // Fast case for named elements that are not there. + if (!htmlDocument->hasNamedItem(key.impl()) && !htmlDocument->hasExtraNamedItem(key.impl())) + return v8::Handle<v8::Value>(); RefPtr<HTMLCollection> items = htmlDocument->documentNamedItems(key); if (!items->length()) - return v8::Handle<v8::Value>(); + return notHandledByInterceptor(); if (items->length() == 1) { Node* node = items->firstItem(); @@ -93,6 +104,13 @@ v8::Handle<v8::Value> V8HTMLDocument::GetNamedProperty(HTMLDocument* htmlDocumen return toV8(items.release()); } +v8::Handle<v8::Value> V8HTMLDocument::indexedPropertyGetter(uint32_t index, const v8::AccessorInfo &info) +{ + INC_STATS("DOM.HTMLDocument.IndexedPropertyGetter"); + v8::Local<v8::Integer> indexV8 = v8::Integer::NewFromUnsigned(index); + return namedPropertyGetter(indexV8->ToString(), info); +} + // HTMLDocument ---------------------------------------------------------------- // Concatenates "args" to a string. If args is empty, returns empty string. @@ -175,8 +193,10 @@ v8::Handle<v8::Value> V8HTMLDocument::allAccessorGetter(v8::Local<v8::String> na void V8HTMLDocument::allAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) { - // Just emulate a normal JS behaviour---install a property on this. - info.This()->ForceSet(name, value); + INC_STATS("DOM.HTMLDocument.all._set"); + v8::Handle<v8::Object> holder = info.Holder(); + ASSERT(info.Holder()->InternalFieldCount() == V8HTMLDocument::internalFieldCount); + info.Holder()->SetInternalField(V8HTMLDocument::shadowIndex, value); } v8::Handle<v8::Value> toV8(HTMLDocument* impl, bool forceNewObject) @@ -190,6 +210,12 @@ v8::Handle<v8::Value> toV8(HTMLDocument* impl, bool forceNewObject) if (V8Proxy* proxy = V8Proxy::retrieve(impl->frame())) proxy->windowShell()->updateDocumentWrapper(wrapper); } + // Create marker object and insert it in two internal fields. + // This is used to implement temporary shadowing of document.all. + ASSERT(wrapper->InternalFieldCount() == V8HTMLDocument::internalFieldCount); + v8::Local<v8::Object> marker = v8::Object::New(); + wrapper->SetInternalField(V8HTMLDocument::markerIndex, marker); + wrapper->SetInternalField(V8HTMLDocument::shadowIndex, marker); return wrapper; } diff --git a/WebCore/bindings/v8/custom/V8SQLTransactionSyncCustom.cpp b/WebCore/bindings/v8/custom/V8SQLTransactionSyncCustom.cpp index 8ef11ce..495a8e4 100644 --- a/WebCore/bindings/v8/custom/V8SQLTransactionSyncCustom.cpp +++ b/WebCore/bindings/v8/custom/V8SQLTransactionSyncCustom.cpp @@ -41,6 +41,7 @@ #include "V8Binding.h" #include "V8BindingMacros.h" #include "V8Proxy.h" +#include "V8SQLResultSet.h" #include <wtf/Vector.h> using namespace WTF; @@ -90,10 +91,10 @@ v8::Handle<v8::Value> V8SQLTransactionSync::executeSqlCallback(const v8::Argumen SQLTransactionSync* transaction = V8SQLTransactionSync::toNative(args.Holder()); ExceptionCode ec = 0; - transaction->executeSQL(statement, sqlValues, ec); + v8::Handle<v8::Value> result = toV8(transaction->executeSQL(statement, sqlValues, ec)); V8Proxy::setDOMException(ec); - return v8::Undefined(); + return result; } } // namespace WebCore |