diff --git a/Atom.xcodeproj/project.pbxproj b/Atom.xcodeproj/project.pbxproj index 5c31c82cd..1d199c755 100644 --- a/Atom.xcodeproj/project.pbxproj +++ b/Atom.xcodeproj/project.pbxproj @@ -7,6 +7,11 @@ objects = { /* Begin PBXBuildFile section */ + 040BDC9114D71A5600CEE2A4 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 040BDC8E14D71A5600CEE2A4 /* JavaScriptCore.framework */; }; + 040BDC9314D71A5600CEE2A4 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 040BDC9014D71A5600CEE2A4 /* WebKit.framework */; }; + 040BDC9414D71A6400CEE2A4 /* JavaScriptCore.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 040BDC8E14D71A5600CEE2A4 /* JavaScriptCore.framework */; }; + 040BDC9514D71A6400CEE2A4 /* WebCore.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 040BDC8F14D71A5600CEE2A4 /* WebCore.framework */; }; + 040BDC9614D71A6400CEE2A4 /* WebKit.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 040BDC9014D71A5600CEE2A4 /* WebKit.framework */; }; 043D7E4C145794990078D710 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 043D7E4B145794990078D710 /* Cocoa.framework */; }; 043D7E56145794990078D710 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 043D7E54145794990078D710 /* InfoPlist.strings */; }; 043D7E58145794990078D710 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 043D7E57145794990078D710 /* main.m */; }; @@ -24,14 +29,30 @@ 043D7E8E145795B20078D710 /* AtomWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 043D7E83145795B20078D710 /* AtomWindow.xib */; }; 043D7E94145795B70078D710 /* AtomApp.m in Sources */ = {isa = PBXBuildFile; fileRef = 043D7E91145795B70078D710 /* AtomApp.m */; }; 043D7E95145795B70078D710 /* AtomController.m in Sources */ = {isa = PBXBuildFile; fileRef = 043D7E93145795B70078D710 /* AtomController.m */; }; - 047F26021457978C006DC904 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 047F26011457978C006DC904 /* JavaScriptCore.framework */; }; - 047F260414579792006DC904 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 047F260314579792006DC904 /* WebKit.framework */; }; 047F260E145883B9006DC904 /* Icon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 047F260D145883B9006DC904 /* Icon.icns */; }; EC846C4114B529120021AF1F /* FileSystemHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = EC846C4014B529120021AF1F /* FileSystemHelper.m */; }; ECBB172814A4F92400ACAAC1 /* AtomMenuItem.m in Sources */ = {isa = PBXBuildFile; fileRef = ECBB172714A4F92400ACAAC1 /* AtomMenuItem.m */; }; /* End PBXBuildFile section */ +/* Begin PBXCopyFilesBuildPhase section */ + 040BDC8A14D70E1100CEE2A4 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 040BDC9414D71A6400CEE2A4 /* JavaScriptCore.framework in CopyFiles */, + 040BDC9514D71A6400CEE2A4 /* WebCore.framework in CopyFiles */, + 040BDC9614D71A6400CEE2A4 /* WebKit.framework in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ + 040BDC8E14D71A5600CEE2A4 /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = frameworks/JavaScriptCore.framework; sourceTree = ""; }; + 040BDC8F14D71A5600CEE2A4 /* WebCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebCore.framework; path = frameworks/WebCore.framework; sourceTree = ""; }; + 040BDC9014D71A5600CEE2A4 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = frameworks/WebKit.framework; sourceTree = ""; }; 043D7E47145794990078D710 /* Atom.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Atom.app; sourceTree = BUILT_PRODUCTS_DIR; }; 043D7E4B145794990078D710 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 043D7E4E145794990078D710 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; @@ -68,8 +89,6 @@ 043D7E91145795B70078D710 /* AtomApp.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AtomApp.m; path = Classes/AtomApp.m; sourceTree = ""; }; 043D7E92145795B70078D710 /* AtomController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AtomController.h; path = Classes/AtomController.h; sourceTree = ""; }; 043D7E93145795B70078D710 /* AtomController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AtomController.m; path = Classes/AtomController.m; sourceTree = ""; }; - 047F26011457978C006DC904 /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; - 047F260314579792006DC904 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; 047F260D145883B9006DC904 /* Icon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = Icon.icns; sourceTree = ""; }; EC846C3F14B529120021AF1F /* FileSystemHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FileSystemHelper.h; path = Classes/FileSystemHelper.h; sourceTree = ""; }; EC846C4014B529120021AF1F /* FileSystemHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FileSystemHelper.m; path = Classes/FileSystemHelper.m; sourceTree = ""; }; @@ -82,9 +101,9 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 047F260414579792006DC904 /* WebKit.framework in Frameworks */, - 047F26021457978C006DC904 /* JavaScriptCore.framework in Frameworks */, 043D7E4C145794990078D710 /* Cocoa.framework in Frameworks */, + 040BDC9114D71A5600CEE2A4 /* JavaScriptCore.framework in Frameworks */, + 040BDC9314D71A5600CEE2A4 /* WebKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -111,8 +130,9 @@ 043D7E4A145794990078D710 /* Frameworks */ = { isa = PBXGroup; children = ( - 047F260314579792006DC904 /* WebKit.framework */, - 047F26011457978C006DC904 /* JavaScriptCore.framework */, + 040BDC8E14D71A5600CEE2A4 /* JavaScriptCore.framework */, + 040BDC8F14D71A5600CEE2A4 /* WebCore.framework */, + 040BDC9014D71A5600CEE2A4 /* WebKit.framework */, 043D7E4B145794990078D710 /* Cocoa.framework */, 043D7E4D145794990078D710 /* Other Frameworks */, ); @@ -203,6 +223,7 @@ isa = PBXNativeTarget; buildConfigurationList = 043D7E651457949A0078D710 /* Build configuration list for PBXNativeTarget "Atom" */; buildPhases = ( + 040BDC8A14D70E1100CEE2A4 /* CopyFiles */, 043D7E43145794990078D710 /* Sources */, 043D7E44145794990078D710 /* Frameworks */, 043D7E45145794990078D710 /* Resources */, @@ -374,9 +395,14 @@ 043D7E661457949A0078D710 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/frameworks\"", + ); GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "Atom/Atom-Prefix.pch"; INFOPLIST_FILE = "Atom/Atom-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks"; PRODUCT_NAME = "$(TARGET_NAME)"; STRINGS_FILE_OUTPUT_ENCODING = "UTF-8"; WRAPPER_EXTENSION = app; @@ -386,9 +412,14 @@ 043D7E671457949A0078D710 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/frameworks\"", + ); GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "Atom/Atom-Prefix.pch"; INFOPLIST_FILE = "Atom/Atom-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "@loader_path/../Frameworks"; PRODUCT_NAME = "$(TARGET_NAME)"; STRINGS_FILE_OUTPUT_ENCODING = "UTF-8"; WRAPPER_EXTENSION = app; diff --git a/frameworks/JavaScriptCore.framework/Headers b/frameworks/JavaScriptCore.framework/Headers new file mode 120000 index 000000000..a177d2a6b --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Headers @@ -0,0 +1 @@ +Versions/Current/Headers \ No newline at end of file diff --git a/frameworks/JavaScriptCore.framework/JavaScriptCore b/frameworks/JavaScriptCore.framework/JavaScriptCore new file mode 120000 index 000000000..c9c4e6012 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/JavaScriptCore @@ -0,0 +1 @@ +Versions/Current/JavaScriptCore \ No newline at end of file diff --git a/frameworks/JavaScriptCore.framework/PrivateHeaders b/frameworks/JavaScriptCore.framework/PrivateHeaders new file mode 120000 index 000000000..d8e564526 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/PrivateHeaders @@ -0,0 +1 @@ +Versions/Current/PrivateHeaders \ No newline at end of file diff --git a/frameworks/JavaScriptCore.framework/Resources b/frameworks/JavaScriptCore.framework/Resources new file mode 120000 index 000000000..953ee36f3 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Resources @@ -0,0 +1 @@ +Versions/Current/Resources \ No newline at end of file diff --git a/frameworks/JavaScriptCore.framework/Versions/A/Headers/JSBase.h b/frameworks/JavaScriptCore.framework/Versions/A/Headers/JSBase.h new file mode 100644 index 000000000..fed54fe23 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/Headers/JSBase.h @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2006 Apple Computer, 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 JSBase_h +#define JSBase_h + +#ifndef __cplusplus +#include +#endif + +/* JavaScript engine interface */ + +/*! @typedef JSContextGroupRef A group that associates JavaScript contexts with one another. Contexts in the same group may share and exchange JavaScript objects. */ +typedef const struct OpaqueJSContextGroup* JSContextGroupRef; + +/*! @typedef JSContextRef A JavaScript execution context. Holds the global object and other execution state. */ +typedef const struct OpaqueJSContext* JSContextRef; + +/*! @typedef JSGlobalContextRef A global JavaScript execution context. A JSGlobalContext is a JSContext. */ +typedef struct OpaqueJSContext* JSGlobalContextRef; + +/*! @typedef JSStringRef A UTF16 character buffer. The fundamental string representation in JavaScript. */ +typedef struct OpaqueJSString* JSStringRef; + +/*! @typedef JSClassRef A JavaScript class. Used with JSObjectMake to construct objects with custom behavior. */ +typedef struct OpaqueJSClass* JSClassRef; + +/*! @typedef JSPropertyNameArrayRef An array of JavaScript property names. */ +typedef struct OpaqueJSPropertyNameArray* JSPropertyNameArrayRef; + +/*! @typedef JSPropertyNameAccumulatorRef An ordered set used to collect the names of a JavaScript object's properties. */ +typedef struct OpaqueJSPropertyNameAccumulator* JSPropertyNameAccumulatorRef; + + +/* JavaScript data types */ + +/*! @typedef JSValueRef A JavaScript value. The base type for all JavaScript values, and polymorphic functions on them. */ +typedef const struct OpaqueJSValue* JSValueRef; + +/*! @typedef JSObjectRef A JavaScript object. A JSObject is a JSValue. */ +typedef struct OpaqueJSValue* JSObjectRef; + +/* JavaScript symbol exports */ +/* These rules should stay the same as in WebKit2/Shared/API/c/WKBase.h */ + +#undef JS_EXPORT +#if defined(JS_NO_EXPORT) +#define JS_EXPORT +#elif defined(__GNUC__) && !defined(__CC_ARM) && !defined(__ARMCC__) +#define JS_EXPORT __attribute__((visibility("default"))) +#elif defined(WIN32) || defined(_WIN32) || defined(_WIN32_WCE) || defined(__CC_ARM) || defined(__ARMCC__) +#if defined(BUILDING_JavaScriptCore) || defined(BUILDING_WTF) +#define JS_EXPORT __declspec(dllexport) +#else +#define JS_EXPORT __declspec(dllimport) +#endif +#else /* !defined(JS_NO_EXPORT) */ +#define JS_EXPORT +#endif /* defined(JS_NO_EXPORT) */ + +/* JS tests uses WTF but has no config.h, so we need to set the export defines here. */ +#ifndef WTF_EXPORT_PRIVATE +#define WTF_EXPORT_PRIVATE JS_EXPORT +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Script Evaluation */ + +/*! +@function JSEvaluateScript +@abstract Evaluates a string of JavaScript. +@param ctx The execution context to use. +@param script A JSString containing the script to evaluate. +@param thisObject The object to use as "this," or NULL to use the global object as "this." +@param sourceURL A JSString containing a URL for the script's source file. This is only used when reporting exceptions. Pass NULL if you do not care to include source file information in exceptions. +@param startingLineNumber An integer value specifying the script's starting line number in the file located at sourceURL. This is only used when reporting exceptions. +@param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. +@result The JSValue that results from evaluating script, or NULL if an exception is thrown. +*/ +JS_EXPORT JSValueRef JSEvaluateScript(JSContextRef ctx, JSStringRef script, JSObjectRef thisObject, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception); + +/*! +@function JSCheckScriptSyntax +@abstract Checks for syntax errors in a string of JavaScript. +@param ctx The execution context to use. +@param script A JSString containing the script to check for syntax errors. +@param sourceURL A JSString containing a URL for the script's source file. This is only used when reporting exceptions. Pass NULL if you do not care to include source file information in exceptions. +@param startingLineNumber An integer value specifying the script's starting line number in the file located at sourceURL. This is only used when reporting exceptions. +@param exception A pointer to a JSValueRef in which to store a syntax error exception, if any. Pass NULL if you do not care to store a syntax error exception. +@result true if the script is syntactically correct, otherwise false. +*/ +JS_EXPORT bool JSCheckScriptSyntax(JSContextRef ctx, JSStringRef script, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception); + +/*! +@function JSGarbageCollect +@abstract Performs a JavaScript garbage collection. +@param ctx The execution context to use. +@discussion JavaScript values that are on the machine stack, in a register, + protected by JSValueProtect, set as the global object of an execution context, + or reachable from any such value will not be collected. + + During JavaScript execution, you are not required to call this function; the + JavaScript engine will garbage collect as needed. JavaScript values created + within a context group are automatically destroyed when the last reference + to the context group is released. +*/ +JS_EXPORT void JSGarbageCollect(JSContextRef ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* JSBase_h */ diff --git a/frameworks/JavaScriptCore.framework/Versions/A/Headers/JSContextRef.h b/frameworks/JavaScriptCore.framework/Versions/A/Headers/JSContextRef.h new file mode 100644 index 000000000..c5c8a71e6 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/Headers/JSContextRef.h @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2006 Apple Computer, 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 JSContextRef_h +#define JSContextRef_h + +#include +#include +#include + +#ifndef __cplusplus +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/*! +@function +@abstract Creates a JavaScript context group. +@discussion A JSContextGroup associates JavaScript contexts with one another. + Contexts in the same group may share and exchange JavaScript objects. Sharing and/or exchanging + JavaScript objects between contexts in different groups will produce undefined behavior. + When objects from the same context group are used in multiple threads, explicit + synchronization is required. +@result The created JSContextGroup. +*/ +JS_EXPORT JSContextGroupRef JSContextGroupCreate() AVAILABLE_IN_WEBKIT_VERSION_4_0; + +/*! +@function +@abstract Retains a JavaScript context group. +@param group The JSContextGroup to retain. +@result A JSContextGroup that is the same as group. +*/ +JS_EXPORT JSContextGroupRef JSContextGroupRetain(JSContextGroupRef group) AVAILABLE_IN_WEBKIT_VERSION_4_0; + +/*! +@function +@abstract Releases a JavaScript context group. +@param group The JSContextGroup to release. +*/ +JS_EXPORT void JSContextGroupRelease(JSContextGroupRef group) AVAILABLE_IN_WEBKIT_VERSION_4_0; + +/*! +@function +@abstract Creates a global JavaScript execution context. +@discussion JSGlobalContextCreate allocates a global object and populates it with all the + built-in JavaScript objects, such as Object, Function, String, and Array. + + In WebKit version 4.0 and later, the context is created in a unique context group. + Therefore, scripts may execute in it concurrently with scripts executing in other contexts. + However, you may not use values created in the context in other contexts. +@param globalObjectClass The class to use when creating the global object. Pass + NULL to use the default object class. +@result A JSGlobalContext with a global object of class globalObjectClass. +*/ +JS_EXPORT JSGlobalContextRef JSGlobalContextCreate(JSClassRef globalObjectClass) AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER; + +/*! +@function +@abstract Creates a global JavaScript execution context in the context group provided. +@discussion JSGlobalContextCreateInGroup allocates a global object and populates it with + all the built-in JavaScript objects, such as Object, Function, String, and Array. +@param globalObjectClass The class to use when creating the global object. Pass + NULL to use the default object class. +@param group The context group to use. The created global context retains the group. + Pass NULL to create a unique group for the context. +@result A JSGlobalContext with a global object of class globalObjectClass and a context + group equal to group. +*/ +JS_EXPORT JSGlobalContextRef JSGlobalContextCreateInGroup(JSContextGroupRef group, JSClassRef globalObjectClass) AVAILABLE_IN_WEBKIT_VERSION_4_0; + +/*! +@function +@abstract Retains a global JavaScript execution context. +@param ctx The JSGlobalContext to retain. +@result A JSGlobalContext that is the same as ctx. +*/ +JS_EXPORT JSGlobalContextRef JSGlobalContextRetain(JSGlobalContextRef ctx); + +/*! +@function +@abstract Releases a global JavaScript execution context. +@param ctx The JSGlobalContext to release. +*/ +JS_EXPORT void JSGlobalContextRelease(JSGlobalContextRef ctx); + +/*! +@function +@abstract Gets the global object of a JavaScript execution context. +@param ctx The JSContext whose global object you want to get. +@result ctx's global object. +*/ +JS_EXPORT JSObjectRef JSContextGetGlobalObject(JSContextRef ctx); + +/*! +@function +@abstract Gets the context group to which a JavaScript execution context belongs. +@param ctx The JSContext whose group you want to get. +@result ctx's group. +*/ +JS_EXPORT JSContextGroupRef JSContextGetGroup(JSContextRef ctx) AVAILABLE_IN_WEBKIT_VERSION_4_0; + +#ifdef __cplusplus +} +#endif + +#endif /* JSContextRef_h */ diff --git a/frameworks/JavaScriptCore.framework/Versions/A/Headers/JSObjectRef.h b/frameworks/JavaScriptCore.framework/Versions/A/Headers/JSObjectRef.h new file mode 100644 index 000000000..5014726bc --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/Headers/JSObjectRef.h @@ -0,0 +1,694 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2008 Kelvin W Sherlock (ksherlock@gmail.com) + * + * 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 JSObjectRef_h +#define JSObjectRef_h + +#include +#include +#include + +#ifndef __cplusplus +#include +#endif +#include /* for size_t */ + +#ifdef __cplusplus +extern "C" { +#endif + +/*! +@enum JSPropertyAttribute +@constant kJSPropertyAttributeNone Specifies that a property has no special attributes. +@constant kJSPropertyAttributeReadOnly Specifies that a property is read-only. +@constant kJSPropertyAttributeDontEnum Specifies that a property should not be enumerated by JSPropertyEnumerators and JavaScript for...in loops. +@constant kJSPropertyAttributeDontDelete Specifies that the delete operation should fail on a property. +*/ +enum { + kJSPropertyAttributeNone = 0, + kJSPropertyAttributeReadOnly = 1 << 1, + kJSPropertyAttributeDontEnum = 1 << 2, + kJSPropertyAttributeDontDelete = 1 << 3 +}; + +/*! +@typedef JSPropertyAttributes +@abstract A set of JSPropertyAttributes. Combine multiple attributes by logically ORing them together. +*/ +typedef unsigned JSPropertyAttributes; + +/*! +@enum JSClassAttribute +@constant kJSClassAttributeNone Specifies that a class has no special attributes. +@constant kJSClassAttributeNoAutomaticPrototype Specifies that a class should not automatically generate a shared prototype for its instance objects. Use kJSClassAttributeNoAutomaticPrototype in combination with JSObjectSetPrototype to manage prototypes manually. +*/ +enum { + kJSClassAttributeNone = 0, + kJSClassAttributeNoAutomaticPrototype = 1 << 1 +}; + +/*! +@typedef JSClassAttributes +@abstract A set of JSClassAttributes. Combine multiple attributes by logically ORing them together. +*/ +typedef unsigned JSClassAttributes; + +/*! +@typedef JSObjectInitializeCallback +@abstract The callback invoked when an object is first created. +@param ctx The execution context to use. +@param object The JSObject being created. +@discussion If you named your function Initialize, you would declare it like this: + +void Initialize(JSContextRef ctx, JSObjectRef object); + +Unlike the other object callbacks, the initialize callback is called on the least +derived class (the parent class) first, and the most derived class last. +*/ +typedef void +(*JSObjectInitializeCallback) (JSContextRef ctx, JSObjectRef object); + +/*! +@typedef JSObjectFinalizeCallback +@abstract The callback invoked when an object is finalized (prepared for garbage collection). An object may be finalized on any thread. +@param object The JSObject being finalized. +@discussion If you named your function Finalize, you would declare it like this: + +void Finalize(JSObjectRef object); + +The finalize callback is called on the most derived class first, and the least +derived class (the parent class) last. + +You must not call any function that may cause a garbage collection or an allocation +of a garbage collected object from within a JSObjectFinalizeCallback. This includes +all functions that have a JSContextRef parameter. +*/ +typedef void +(*JSObjectFinalizeCallback) (JSObjectRef object); + +/*! +@typedef JSObjectHasPropertyCallback +@abstract The callback invoked when determining whether an object has a property. +@param ctx The execution context to use. +@param object The JSObject to search for the property. +@param propertyName A JSString containing the name of the property look up. +@result true if object has the property, otherwise false. +@discussion If you named your function HasProperty, you would declare it like this: + +bool HasProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName); + +If this function returns false, the hasProperty request forwards to object's statically declared properties, then its parent class chain (which includes the default object class), then its prototype chain. + +This callback enables optimization in cases where only a property's existence needs to be known, not its value, and computing its value would be expensive. + +If this callback is NULL, the getProperty callback will be used to service hasProperty requests. +*/ +typedef bool +(*JSObjectHasPropertyCallback) (JSContextRef ctx, JSObjectRef object, JSStringRef propertyName); + +/*! +@typedef JSObjectGetPropertyCallback +@abstract The callback invoked when getting a property's value. +@param ctx The execution context to use. +@param object The JSObject to search for the property. +@param propertyName A JSString containing the name of the property to get. +@param exception A pointer to a JSValueRef in which to return an exception, if any. +@result The property's value if object has the property, otherwise NULL. +@discussion If you named your function GetProperty, you would declare it like this: + +JSValueRef GetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception); + +If this function returns NULL, the get request forwards to object's statically declared properties, then its parent class chain (which includes the default object class), then its prototype chain. +*/ +typedef JSValueRef +(*JSObjectGetPropertyCallback) (JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception); + +/*! +@typedef JSObjectSetPropertyCallback +@abstract The callback invoked when setting a property's value. +@param ctx The execution context to use. +@param object The JSObject on which to set the property's value. +@param propertyName A JSString containing the name of the property to set. +@param value A JSValue to use as the property's value. +@param exception A pointer to a JSValueRef in which to return an exception, if any. +@result true if the property was set, otherwise false. +@discussion If you named your function SetProperty, you would declare it like this: + +bool SetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception); + +If this function returns false, the set request forwards to object's statically declared properties, then its parent class chain (which includes the default object class). +*/ +typedef bool +(*JSObjectSetPropertyCallback) (JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception); + +/*! +@typedef JSObjectDeletePropertyCallback +@abstract The callback invoked when deleting a property. +@param ctx The execution context to use. +@param object The JSObject in which to delete the property. +@param propertyName A JSString containing the name of the property to delete. +@param exception A pointer to a JSValueRef in which to return an exception, if any. +@result true if propertyName was successfully deleted, otherwise false. +@discussion If you named your function DeleteProperty, you would declare it like this: + +bool DeleteProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception); + +If this function returns false, the delete request forwards to object's statically declared properties, then its parent class chain (which includes the default object class). +*/ +typedef bool +(*JSObjectDeletePropertyCallback) (JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception); + +/*! +@typedef JSObjectGetPropertyNamesCallback +@abstract The callback invoked when collecting the names of an object's properties. +@param ctx The execution context to use. +@param object The JSObject whose property names are being collected. +@param accumulator A JavaScript property name accumulator in which to accumulate the names of object's properties. +@discussion If you named your function GetPropertyNames, you would declare it like this: + +void GetPropertyNames(JSContextRef ctx, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames); + +Property name accumulators are used by JSObjectCopyPropertyNames and JavaScript for...in loops. + +Use JSPropertyNameAccumulatorAddName to add property names to accumulator. A class's getPropertyNames callback only needs to provide the names of properties that the class vends through a custom getProperty or setProperty callback. Other properties, including statically declared properties, properties vended by other classes, and properties belonging to object's prototype, are added independently. +*/ +typedef void +(*JSObjectGetPropertyNamesCallback) (JSContextRef ctx, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames); + +/*! +@typedef JSObjectCallAsFunctionCallback +@abstract The callback invoked when an object is called as a function. +@param ctx The execution context to use. +@param function A JSObject that is the function being called. +@param thisObject A JSObject that is the 'this' variable in the function's scope. +@param argumentCount An integer count of the number of arguments in arguments. +@param arguments A JSValue array of the arguments passed to the function. +@param exception A pointer to a JSValueRef in which to return an exception, if any. +@result A JSValue that is the function's return value. +@discussion If you named your function CallAsFunction, you would declare it like this: + +JSValueRef CallAsFunction(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception); + +If your callback were invoked by the JavaScript expression 'myObject.myFunction()', function would be set to myFunction, and thisObject would be set to myObject. + +If this callback is NULL, calling your object as a function will throw an exception. +*/ +typedef JSValueRef +(*JSObjectCallAsFunctionCallback) (JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception); + +/*! +@typedef JSObjectCallAsConstructorCallback +@abstract The callback invoked when an object is used as a constructor in a 'new' expression. +@param ctx The execution context to use. +@param constructor A JSObject that is the constructor being called. +@param argumentCount An integer count of the number of arguments in arguments. +@param arguments A JSValue array of the arguments passed to the function. +@param exception A pointer to a JSValueRef in which to return an exception, if any. +@result A JSObject that is the constructor's return value. +@discussion If you named your function CallAsConstructor, you would declare it like this: + +JSObjectRef CallAsConstructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception); + +If your callback were invoked by the JavaScript expression 'new myConstructor()', constructor would be set to myConstructor. + +If this callback is NULL, using your object as a constructor in a 'new' expression will throw an exception. +*/ +typedef JSObjectRef +(*JSObjectCallAsConstructorCallback) (JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception); + +/*! +@typedef JSObjectHasInstanceCallback +@abstract hasInstance The callback invoked when an object is used as the target of an 'instanceof' expression. +@param ctx The execution context to use. +@param constructor The JSObject that is the target of the 'instanceof' expression. +@param possibleInstance The JSValue being tested to determine if it is an instance of constructor. +@param exception A pointer to a JSValueRef in which to return an exception, if any. +@result true if possibleInstance is an instance of constructor, otherwise false. +@discussion If you named your function HasInstance, you would declare it like this: + +bool HasInstance(JSContextRef ctx, JSObjectRef constructor, JSValueRef possibleInstance, JSValueRef* exception); + +If your callback were invoked by the JavaScript expression 'someValue instanceof myObject', constructor would be set to myObject and possibleInstance would be set to someValue. + +If this callback is NULL, 'instanceof' expressions that target your object will return false. + +Standard JavaScript practice calls for objects that implement the callAsConstructor callback to implement the hasInstance callback as well. +*/ +typedef bool +(*JSObjectHasInstanceCallback) (JSContextRef ctx, JSObjectRef constructor, JSValueRef possibleInstance, JSValueRef* exception); + +/*! +@typedef JSObjectConvertToTypeCallback +@abstract The callback invoked when converting an object to a particular JavaScript type. +@param ctx The execution context to use. +@param object The JSObject to convert. +@param type A JSType specifying the JavaScript type to convert to. +@param exception A pointer to a JSValueRef in which to return an exception, if any. +@result The objects's converted value, or NULL if the object was not converted. +@discussion If you named your function ConvertToType, you would declare it like this: + +JSValueRef ConvertToType(JSContextRef ctx, JSObjectRef object, JSType type, JSValueRef* exception); + +If this function returns false, the conversion request forwards to object's parent class chain (which includes the default object class). + +This function is only invoked when converting an object to number or string. An object converted to boolean is 'true.' An object converted to object is itself. +*/ +typedef JSValueRef +(*JSObjectConvertToTypeCallback) (JSContextRef ctx, JSObjectRef object, JSType type, JSValueRef* exception); + +/*! +@struct JSStaticValue +@abstract This structure describes a statically declared value property. +@field name A null-terminated UTF8 string containing the property's name. +@field getProperty A JSObjectGetPropertyCallback to invoke when getting the property's value. +@field setProperty A JSObjectSetPropertyCallback to invoke when setting the property's value. May be NULL if the ReadOnly attribute is set. +@field attributes A logically ORed set of JSPropertyAttributes to give to the property. +*/ +typedef struct { + const char* name; + JSObjectGetPropertyCallback getProperty; + JSObjectSetPropertyCallback setProperty; + JSPropertyAttributes attributes; +} JSStaticValue; + +/*! +@struct JSStaticFunction +@abstract This structure describes a statically declared function property. +@field name A null-terminated UTF8 string containing the property's name. +@field callAsFunction A JSObjectCallAsFunctionCallback to invoke when the property is called as a function. +@field attributes A logically ORed set of JSPropertyAttributes to give to the property. +*/ +typedef struct { + const char* name; + JSObjectCallAsFunctionCallback callAsFunction; + JSPropertyAttributes attributes; +} JSStaticFunction; + +/*! +@struct JSClassDefinition +@abstract This structure contains properties and callbacks that define a type of object. All fields other than the version field are optional. Any pointer may be NULL. +@field version The version number of this structure. The current version is 0. +@field attributes A logically ORed set of JSClassAttributes to give to the class. +@field className A null-terminated UTF8 string containing the class's name. +@field parentClass A JSClass to set as the class's parent class. Pass NULL use the default object class. +@field staticValues A JSStaticValue array containing the class's statically declared value properties. Pass NULL to specify no statically declared value properties. The array must be terminated by a JSStaticValue whose name field is NULL. +@field staticFunctions A JSStaticFunction array containing the class's statically declared function properties. Pass NULL to specify no statically declared function properties. The array must be terminated by a JSStaticFunction whose name field is NULL. +@field initialize The callback invoked when an object is first created. Use this callback to initialize the object. +@field finalize The callback invoked when an object is finalized (prepared for garbage collection). Use this callback to release resources allocated for the object, and perform other cleanup. +@field hasProperty The callback invoked when determining whether an object has a property. If this field is NULL, getProperty is called instead. The hasProperty callback enables optimization in cases where only a property's existence needs to be known, not its value, and computing its value is expensive. +@field getProperty The callback invoked when getting a property's value. +@field setProperty The callback invoked when setting a property's value. +@field deleteProperty The callback invoked when deleting a property. +@field getPropertyNames The callback invoked when collecting the names of an object's properties. +@field callAsFunction The callback invoked when an object is called as a function. +@field hasInstance The callback invoked when an object is used as the target of an 'instanceof' expression. +@field callAsConstructor The callback invoked when an object is used as a constructor in a 'new' expression. +@field convertToType The callback invoked when converting an object to a particular JavaScript type. +@discussion The staticValues and staticFunctions arrays are the simplest and most efficient means for vending custom properties. Statically declared properties autmatically service requests like getProperty, setProperty, and getPropertyNames. Property access callbacks are required only to implement unusual properties, like array indexes, whose names are not known at compile-time. + +If you named your getter function "GetX" and your setter function "SetX", you would declare a JSStaticValue array containing "X" like this: + +JSStaticValue StaticValueArray[] = { + { "X", GetX, SetX, kJSPropertyAttributeNone }, + { 0, 0, 0, 0 } +}; + +Standard JavaScript practice calls for storing function objects in prototypes, so they can be shared. The default JSClass created by JSClassCreate follows this idiom, instantiating objects with a shared, automatically generating prototype containing the class's function objects. The kJSClassAttributeNoAutomaticPrototype attribute specifies that a JSClass should not automatically generate such a prototype. The resulting JSClass instantiates objects with the default object prototype, and gives each instance object its own copy of the class's function objects. + +A NULL callback specifies that the default object callback should substitute, except in the case of hasProperty, where it specifies that getProperty should substitute. +*/ +typedef struct { + int version; /* current (and only) version is 0 */ + JSClassAttributes attributes; + + const char* className; + JSClassRef parentClass; + + const JSStaticValue* staticValues; + const JSStaticFunction* staticFunctions; + + JSObjectInitializeCallback initialize; + JSObjectFinalizeCallback finalize; + JSObjectHasPropertyCallback hasProperty; + JSObjectGetPropertyCallback getProperty; + JSObjectSetPropertyCallback setProperty; + JSObjectDeletePropertyCallback deleteProperty; + JSObjectGetPropertyNamesCallback getPropertyNames; + JSObjectCallAsFunctionCallback callAsFunction; + JSObjectCallAsConstructorCallback callAsConstructor; + JSObjectHasInstanceCallback hasInstance; + JSObjectConvertToTypeCallback convertToType; +} JSClassDefinition; + +/*! +@const kJSClassDefinitionEmpty +@abstract A JSClassDefinition structure of the current version, filled with NULL pointers and having no attributes. +@discussion Use this constant as a convenience when creating class definitions. For example, to create a class definition with only a finalize method: + +JSClassDefinition definition = kJSClassDefinitionEmpty; +definition.finalize = Finalize; +*/ +JS_EXPORT extern const JSClassDefinition kJSClassDefinitionEmpty; + +/*! +@function +@abstract Creates a JavaScript class suitable for use with JSObjectMake. +@param definition A JSClassDefinition that defines the class. +@result A JSClass with the given definition. Ownership follows the Create Rule. +*/ +JS_EXPORT JSClassRef JSClassCreate(const JSClassDefinition* definition); + +/*! +@function +@abstract Retains a JavaScript class. +@param jsClass The JSClass to retain. +@result A JSClass that is the same as jsClass. +*/ +JS_EXPORT JSClassRef JSClassRetain(JSClassRef jsClass); + +/*! +@function +@abstract Releases a JavaScript class. +@param jsClass The JSClass to release. +*/ +JS_EXPORT void JSClassRelease(JSClassRef jsClass); + +/*! +@function +@abstract Creates a JavaScript object. +@param ctx The execution context to use. +@param jsClass The JSClass to assign to the object. Pass NULL to use the default object class. +@param data A void* to set as the object's private data. Pass NULL to specify no private data. +@result A JSObject with the given class and private data. +@discussion The default object class does not allocate storage for private data, so you must provide a non-NULL jsClass to JSObjectMake if you want your object to be able to store private data. + +data is set on the created object before the intialize methods in its class chain are called. This enables the initialize methods to retrieve and manipulate data through JSObjectGetPrivate. +*/ +JS_EXPORT JSObjectRef JSObjectMake(JSContextRef ctx, JSClassRef jsClass, void* data); + +/*! +@function +@abstract Convenience method for creating a JavaScript function with a given callback as its implementation. +@param ctx The execution context to use. +@param name A JSString containing the function's name. This will be used when converting the function to string. Pass NULL to create an anonymous function. +@param callAsFunction The JSObjectCallAsFunctionCallback to invoke when the function is called. +@result A JSObject that is a function. The object's prototype will be the default function prototype. +*/ +JS_EXPORT JSObjectRef JSObjectMakeFunctionWithCallback(JSContextRef ctx, JSStringRef name, JSObjectCallAsFunctionCallback callAsFunction); + +/*! +@function +@abstract Convenience method for creating a JavaScript constructor. +@param ctx The execution context to use. +@param jsClass A JSClass that is the class your constructor will assign to the objects its constructs. jsClass will be used to set the constructor's .prototype property, and to evaluate 'instanceof' expressions. Pass NULL to use the default object class. +@param callAsConstructor A JSObjectCallAsConstructorCallback to invoke when your constructor is used in a 'new' expression. Pass NULL to use the default object constructor. +@result A JSObject that is a constructor. The object's prototype will be the default object prototype. +@discussion The default object constructor takes no arguments and constructs an object of class jsClass with no private data. +*/ +JS_EXPORT JSObjectRef JSObjectMakeConstructor(JSContextRef ctx, JSClassRef jsClass, JSObjectCallAsConstructorCallback callAsConstructor); + +/*! + @function + @abstract Creates a JavaScript Array object. + @param ctx The execution context to use. + @param argumentCount An integer count of the number of arguments in arguments. + @param arguments A JSValue array of data to populate the Array with. Pass NULL if argumentCount is 0. + @param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. + @result A JSObject that is an Array. + @discussion The behavior of this function does not exactly match the behavior of the built-in Array constructor. Specifically, if one argument + is supplied, this function returns an array with one element. + */ +JS_EXPORT JSObjectRef JSObjectMakeArray(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) AVAILABLE_IN_WEBKIT_VERSION_4_0; + +/*! + @function + @abstract Creates a JavaScript Date object, as if by invoking the built-in Date constructor. + @param ctx The execution context to use. + @param argumentCount An integer count of the number of arguments in arguments. + @param arguments A JSValue array of arguments to pass to the Date Constructor. Pass NULL if argumentCount is 0. + @param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. + @result A JSObject that is a Date. + */ +JS_EXPORT JSObjectRef JSObjectMakeDate(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) AVAILABLE_IN_WEBKIT_VERSION_4_0; + +/*! + @function + @abstract Creates a JavaScript Error object, as if by invoking the built-in Error constructor. + @param ctx The execution context to use. + @param argumentCount An integer count of the number of arguments in arguments. + @param arguments A JSValue array of arguments to pass to the Error Constructor. Pass NULL if argumentCount is 0. + @param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. + @result A JSObject that is a Error. + */ +JS_EXPORT JSObjectRef JSObjectMakeError(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) AVAILABLE_IN_WEBKIT_VERSION_4_0; + +/*! + @function + @abstract Creates a JavaScript RegExp object, as if by invoking the built-in RegExp constructor. + @param ctx The execution context to use. + @param argumentCount An integer count of the number of arguments in arguments. + @param arguments A JSValue array of arguments to pass to the RegExp Constructor. Pass NULL if argumentCount is 0. + @param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. + @result A JSObject that is a RegExp. + */ +JS_EXPORT JSObjectRef JSObjectMakeRegExp(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) AVAILABLE_IN_WEBKIT_VERSION_4_0; + +/*! +@function +@abstract Creates a function with a given script as its body. +@param ctx The execution context to use. +@param name A JSString containing the function's name. This will be used when converting the function to string. Pass NULL to create an anonymous function. +@param parameterCount An integer count of the number of parameter names in parameterNames. +@param parameterNames A JSString array containing the names of the function's parameters. Pass NULL if parameterCount is 0. +@param body A JSString containing the script to use as the function's body. +@param sourceURL A JSString containing a URL for the script's source file. This is only used when reporting exceptions. Pass NULL if you do not care to include source file information in exceptions. +@param startingLineNumber An integer value specifying the script's starting line number in the file located at sourceURL. This is only used when reporting exceptions. +@param exception A pointer to a JSValueRef in which to store a syntax error exception, if any. Pass NULL if you do not care to store a syntax error exception. +@result A JSObject that is a function, or NULL if either body or parameterNames contains a syntax error. The object's prototype will be the default function prototype. +@discussion Use this method when you want to execute a script repeatedly, to avoid the cost of re-parsing the script before each execution. +*/ +JS_EXPORT JSObjectRef JSObjectMakeFunction(JSContextRef ctx, JSStringRef name, unsigned parameterCount, const JSStringRef parameterNames[], JSStringRef body, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception); + +/*! +@function +@abstract Gets an object's prototype. +@param ctx The execution context to use. +@param object A JSObject whose prototype you want to get. +@result A JSValue that is the object's prototype. +*/ +JS_EXPORT JSValueRef JSObjectGetPrototype(JSContextRef ctx, JSObjectRef object); + +/*! +@function +@abstract Sets an object's prototype. +@param ctx The execution context to use. +@param object The JSObject whose prototype you want to set. +@param value A JSValue to set as the object's prototype. +*/ +JS_EXPORT void JSObjectSetPrototype(JSContextRef ctx, JSObjectRef object, JSValueRef value); + +/*! +@function +@abstract Tests whether an object has a given property. +@param object The JSObject to test. +@param propertyName A JSString containing the property's name. +@result true if the object has a property whose name matches propertyName, otherwise false. +*/ +JS_EXPORT bool JSObjectHasProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName); + +/*! +@function +@abstract Gets a property from an object. +@param ctx The execution context to use. +@param object The JSObject whose property you want to get. +@param propertyName A JSString containing the property's name. +@param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. +@result The property's value if object has the property, otherwise the undefined value. +*/ +JS_EXPORT JSValueRef JSObjectGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception); + +/*! +@function +@abstract Sets a property on an object. +@param ctx The execution context to use. +@param object The JSObject whose property you want to set. +@param propertyName A JSString containing the property's name. +@param value A JSValue to use as the property's value. +@param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. +@param attributes A logically ORed set of JSPropertyAttributes to give to the property. +*/ +JS_EXPORT void JSObjectSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSPropertyAttributes attributes, JSValueRef* exception); + +/*! +@function +@abstract Deletes a property from an object. +@param ctx The execution context to use. +@param object The JSObject whose property you want to delete. +@param propertyName A JSString containing the property's name. +@param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. +@result true if the delete operation succeeds, otherwise false (for example, if the property has the kJSPropertyAttributeDontDelete attribute set). +*/ +JS_EXPORT bool JSObjectDeleteProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception); + +/*! +@function +@abstract Gets a property from an object by numeric index. +@param ctx The execution context to use. +@param object The JSObject whose property you want to get. +@param propertyIndex An integer value that is the property's name. +@param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. +@result The property's value if object has the property, otherwise the undefined value. +@discussion Calling JSObjectGetPropertyAtIndex is equivalent to calling JSObjectGetProperty with a string containing propertyIndex, but JSObjectGetPropertyAtIndex provides optimized access to numeric properties. +*/ +JS_EXPORT JSValueRef JSObjectGetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef* exception); + +/*! +@function +@abstract Sets a property on an object by numeric index. +@param ctx The execution context to use. +@param object The JSObject whose property you want to set. +@param propertyIndex The property's name as a number. +@param value A JSValue to use as the property's value. +@param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. +@discussion Calling JSObjectSetPropertyAtIndex is equivalent to calling JSObjectSetProperty with a string containing propertyIndex, but JSObjectSetPropertyAtIndex provides optimized access to numeric properties. +*/ +JS_EXPORT void JSObjectSetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef value, JSValueRef* exception); + +/*! +@function +@abstract Gets an object's private data. +@param object A JSObject whose private data you want to get. +@result A void* that is the object's private data, if the object has private data, otherwise NULL. +*/ +JS_EXPORT void* JSObjectGetPrivate(JSObjectRef object); + +/*! +@function +@abstract Sets a pointer to private data on an object. +@param object The JSObject whose private data you want to set. +@param data A void* to set as the object's private data. +@result true if object can store private data, otherwise false. +@discussion The default object class does not allocate storage for private data. Only objects created with a non-NULL JSClass can store private data. +*/ +JS_EXPORT bool JSObjectSetPrivate(JSObjectRef object, void* data); + +/*! +@function +@abstract Tests whether an object can be called as a function. +@param ctx The execution context to use. +@param object The JSObject to test. +@result true if the object can be called as a function, otherwise false. +*/ +JS_EXPORT bool JSObjectIsFunction(JSContextRef ctx, JSObjectRef object); + +/*! +@function +@abstract Calls an object as a function. +@param ctx The execution context to use. +@param object The JSObject to call as a function. +@param thisObject The object to use as "this," or NULL to use the global object as "this." +@param argumentCount An integer count of the number of arguments in arguments. +@param arguments A JSValue array of arguments to pass to the function. Pass NULL if argumentCount is 0. +@param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. +@result The JSValue that results from calling object as a function, or NULL if an exception is thrown or object is not a function. +*/ +JS_EXPORT JSValueRef JSObjectCallAsFunction(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception); + +/*! +@function +@abstract Tests whether an object can be called as a constructor. +@param ctx The execution context to use. +@param object The JSObject to test. +@result true if the object can be called as a constructor, otherwise false. +*/ +JS_EXPORT bool JSObjectIsConstructor(JSContextRef ctx, JSObjectRef object); + +/*! +@function +@abstract Calls an object as a constructor. +@param ctx The execution context to use. +@param object The JSObject to call as a constructor. +@param argumentCount An integer count of the number of arguments in arguments. +@param arguments A JSValue array of arguments to pass to the constructor. Pass NULL if argumentCount is 0. +@param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. +@result The JSObject that results from calling object as a constructor, or NULL if an exception is thrown or object is not a constructor. +*/ +JS_EXPORT JSObjectRef JSObjectCallAsConstructor(JSContextRef ctx, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception); + +/*! +@function +@abstract Gets the names of an object's enumerable properties. +@param ctx The execution context to use. +@param object The object whose property names you want to get. +@result A JSPropertyNameArray containing the names object's enumerable properties. Ownership follows the Create Rule. +*/ +JS_EXPORT JSPropertyNameArrayRef JSObjectCopyPropertyNames(JSContextRef ctx, JSObjectRef object); + +/*! +@function +@abstract Retains a JavaScript property name array. +@param array The JSPropertyNameArray to retain. +@result A JSPropertyNameArray that is the same as array. +*/ +JS_EXPORT JSPropertyNameArrayRef JSPropertyNameArrayRetain(JSPropertyNameArrayRef array); + +/*! +@function +@abstract Releases a JavaScript property name array. +@param array The JSPropetyNameArray to release. +*/ +JS_EXPORT void JSPropertyNameArrayRelease(JSPropertyNameArrayRef array); + +/*! +@function +@abstract Gets a count of the number of items in a JavaScript property name array. +@param array The array from which to retrieve the count. +@result An integer count of the number of names in array. +*/ +JS_EXPORT size_t JSPropertyNameArrayGetCount(JSPropertyNameArrayRef array); + +/*! +@function +@abstract Gets a property name at a given index in a JavaScript property name array. +@param array The array from which to retrieve the property name. +@param index The index of the property name to retrieve. +@result A JSStringRef containing the property name. +*/ +JS_EXPORT JSStringRef JSPropertyNameArrayGetNameAtIndex(JSPropertyNameArrayRef array, size_t index); + +/*! +@function +@abstract Adds a property name to a JavaScript property name accumulator. +@param accumulator The accumulator object to which to add the property name. +@param propertyName The property name to add. +*/ +JS_EXPORT void JSPropertyNameAccumulatorAddName(JSPropertyNameAccumulatorRef accumulator, JSStringRef propertyName); + +#ifdef __cplusplus +} +#endif + +#endif /* JSObjectRef_h */ diff --git a/frameworks/JavaScriptCore.framework/Versions/A/Headers/JSStringRef.h b/frameworks/JavaScriptCore.framework/Versions/A/Headers/JSStringRef.h new file mode 100644 index 000000000..75d73c919 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/Headers/JSStringRef.h @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2006 Apple Computer, 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 JSStringRef_h +#define JSStringRef_h + +#include + +#ifndef __cplusplus +#include +#endif +#include /* for size_t */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(WIN32) && !defined(_WIN32) \ + && !((defined(__CC_ARM) || defined(__ARMCC__)) && !defined(__linux__)) /* RVCT */ +/*! +@typedef JSChar +@abstract A Unicode character. +*/ + typedef unsigned short JSChar; +#else + typedef wchar_t JSChar; +#endif + +/*! +@function +@abstract Creates a JavaScript string from a buffer of Unicode characters. +@param chars The buffer of Unicode characters to copy into the new JSString. +@param numChars The number of characters to copy from the buffer pointed to by chars. +@result A JSString containing chars. Ownership follows the Create Rule. +*/ +JS_EXPORT JSStringRef JSStringCreateWithCharacters(const JSChar* chars, size_t numChars); +/*! +@function +@abstract Creates a JavaScript string from a null-terminated UTF8 string. +@param string The null-terminated UTF8 string to copy into the new JSString. +@result A JSString containing string. Ownership follows the Create Rule. +*/ +JS_EXPORT JSStringRef JSStringCreateWithUTF8CString(const char* string); + +/*! +@function +@abstract Retains a JavaScript string. +@param string The JSString to retain. +@result A JSString that is the same as string. +*/ +JS_EXPORT JSStringRef JSStringRetain(JSStringRef string); +/*! +@function +@abstract Releases a JavaScript string. +@param string The JSString to release. +*/ +JS_EXPORT void JSStringRelease(JSStringRef string); + +/*! +@function +@abstract Returns the number of Unicode characters in a JavaScript string. +@param string The JSString whose length (in Unicode characters) you want to know. +@result The number of Unicode characters stored in string. +*/ +JS_EXPORT size_t JSStringGetLength(JSStringRef string); +/*! +@function +@abstract Returns a pointer to the Unicode character buffer that + serves as the backing store for a JavaScript string. +@param string The JSString whose backing store you want to access. +@result A pointer to the Unicode character buffer that serves as string's + backing store, which will be deallocated when string is deallocated. +*/ +JS_EXPORT const JSChar* JSStringGetCharactersPtr(JSStringRef string); + +/*! +@function +@abstract Returns the maximum number of bytes a JavaScript string will + take up if converted into a null-terminated UTF8 string. +@param string The JSString whose maximum converted size (in bytes) you + want to know. +@result The maximum number of bytes that could be required to convert string into a + null-terminated UTF8 string. The number of bytes that the conversion actually ends + up requiring could be less than this, but never more. +*/ +JS_EXPORT size_t JSStringGetMaximumUTF8CStringSize(JSStringRef string); +/*! +@function +@abstract Converts a JavaScript string into a null-terminated UTF8 string, + and copies the result into an external byte buffer. +@param string The source JSString. +@param buffer The destination byte buffer into which to copy a null-terminated + UTF8 representation of string. On return, buffer contains a UTF8 string + representation of string. If bufferSize is too small, buffer will contain only + partial results. If buffer is not at least bufferSize bytes in size, + behavior is undefined. +@param bufferSize The size of the external buffer in bytes. +@result The number of bytes written into buffer (including the null-terminator byte). +*/ +JS_EXPORT size_t JSStringGetUTF8CString(JSStringRef string, char* buffer, size_t bufferSize); + +/*! +@function +@abstract Tests whether two JavaScript strings match. +@param a The first JSString to test. +@param b The second JSString to test. +@result true if the two strings match, otherwise false. +*/ +JS_EXPORT bool JSStringIsEqual(JSStringRef a, JSStringRef b); +/*! +@function +@abstract Tests whether a JavaScript string matches a null-terminated UTF8 string. +@param a The JSString to test. +@param b The null-terminated UTF8 string to test. +@result true if the two strings match, otherwise false. +*/ +JS_EXPORT bool JSStringIsEqualToUTF8CString(JSStringRef a, const char* b); + +#ifdef __cplusplus +} +#endif + +#endif /* JSStringRef_h */ diff --git a/frameworks/JavaScriptCore.framework/Versions/A/Headers/JSStringRefCF.h b/frameworks/JavaScriptCore.framework/Versions/A/Headers/JSStringRefCF.h new file mode 100644 index 000000000..a42476561 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/Headers/JSStringRefCF.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2006, 2007 Apple Computer, 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 JSStringRefCF_h +#define JSStringRefCF_h + +#include "JSBase.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* CFString convenience methods */ + +/*! +@function +@abstract Creates a JavaScript string from a CFString. +@discussion This function is optimized to take advantage of cases when + CFStringGetCharactersPtr returns a valid pointer. +@param string The CFString to copy into the new JSString. +@result A JSString containing string. Ownership follows the Create Rule. +*/ +JS_EXPORT JSStringRef JSStringCreateWithCFString(CFStringRef string); +/*! +@function +@abstract Creates a CFString from a JavaScript string. +@param alloc The alloc parameter to pass to CFStringCreate. +@param string The JSString to copy into the new CFString. +@result A CFString containing string. Ownership follows the Create Rule. +*/ +JS_EXPORT CFStringRef JSStringCopyCFString(CFAllocatorRef alloc, JSStringRef string); + +#ifdef __cplusplus +} +#endif + +#endif /* JSStringRefCF_h */ diff --git a/frameworks/JavaScriptCore.framework/Versions/A/Headers/JSValueRef.h b/frameworks/JavaScriptCore.framework/Versions/A/Headers/JSValueRef.h new file mode 100644 index 000000000..4186db822 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/Headers/JSValueRef.h @@ -0,0 +1,301 @@ +/* + * Copyright (C) 2006 Apple Computer, 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 JSValueRef_h +#define JSValueRef_h + +#include +#include + +#ifndef __cplusplus +#include +#endif + +/*! +@enum JSType +@abstract A constant identifying the type of a JSValue. +@constant kJSTypeUndefined The unique undefined value. +@constant kJSTypeNull The unique null value. +@constant kJSTypeBoolean A primitive boolean value, one of true or false. +@constant kJSTypeNumber A primitive number value. +@constant kJSTypeString A primitive string value. +@constant kJSTypeObject An object value (meaning that this JSValueRef is a JSObjectRef). +*/ +typedef enum { + kJSTypeUndefined, + kJSTypeNull, + kJSTypeBoolean, + kJSTypeNumber, + kJSTypeString, + kJSTypeObject +} JSType; + +#ifdef __cplusplus +extern "C" { +#endif + +/*! +@function +@abstract Returns a JavaScript value's type. +@param ctx The execution context to use. +@param value The JSValue whose type you want to obtain. +@result A value of type JSType that identifies value's type. +*/ +JS_EXPORT JSType JSValueGetType(JSContextRef ctx, JSValueRef value); + +/*! +@function +@abstract Tests whether a JavaScript value's type is the undefined type. +@param ctx The execution context to use. +@param value The JSValue to test. +@result true if value's type is the undefined type, otherwise false. +*/ +JS_EXPORT bool JSValueIsUndefined(JSContextRef ctx, JSValueRef value); + +/*! +@function +@abstract Tests whether a JavaScript value's type is the null type. +@param ctx The execution context to use. +@param value The JSValue to test. +@result true if value's type is the null type, otherwise false. +*/ +JS_EXPORT bool JSValueIsNull(JSContextRef ctx, JSValueRef value); + +/*! +@function +@abstract Tests whether a JavaScript value's type is the boolean type. +@param ctx The execution context to use. +@param value The JSValue to test. +@result true if value's type is the boolean type, otherwise false. +*/ +JS_EXPORT bool JSValueIsBoolean(JSContextRef ctx, JSValueRef value); + +/*! +@function +@abstract Tests whether a JavaScript value's type is the number type. +@param ctx The execution context to use. +@param value The JSValue to test. +@result true if value's type is the number type, otherwise false. +*/ +JS_EXPORT bool JSValueIsNumber(JSContextRef ctx, JSValueRef value); + +/*! +@function +@abstract Tests whether a JavaScript value's type is the string type. +@param ctx The execution context to use. +@param value The JSValue to test. +@result true if value's type is the string type, otherwise false. +*/ +JS_EXPORT bool JSValueIsString(JSContextRef ctx, JSValueRef value); + +/*! +@function +@abstract Tests whether a JavaScript value's type is the object type. +@param ctx The execution context to use. +@param value The JSValue to test. +@result true if value's type is the object type, otherwise false. +*/ +JS_EXPORT bool JSValueIsObject(JSContextRef ctx, JSValueRef value); + +/*! +@function +@abstract Tests whether a JavaScript value is an object with a given class in its class chain. +@param ctx The execution context to use. +@param value The JSValue to test. +@param jsClass The JSClass to test against. +@result true if value is an object and has jsClass in its class chain, otherwise false. +*/ +JS_EXPORT bool JSValueIsObjectOfClass(JSContextRef ctx, JSValueRef value, JSClassRef jsClass); + +/* Comparing values */ + +/*! +@function +@abstract Tests whether two JavaScript values are equal, as compared by the JS == operator. +@param ctx The execution context to use. +@param a The first value to test. +@param b The second value to test. +@param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. +@result true if the two values are equal, false if they are not equal or an exception is thrown. +*/ +JS_EXPORT bool JSValueIsEqual(JSContextRef ctx, JSValueRef a, JSValueRef b, JSValueRef* exception); + +/*! +@function +@abstract Tests whether two JavaScript values are strict equal, as compared by the JS === operator. +@param ctx The execution context to use. +@param a The first value to test. +@param b The second value to test. +@result true if the two values are strict equal, otherwise false. +*/ +JS_EXPORT bool JSValueIsStrictEqual(JSContextRef ctx, JSValueRef a, JSValueRef b); + +/*! +@function +@abstract Tests whether a JavaScript value is an object constructed by a given constructor, as compared by the JS instanceof operator. +@param ctx The execution context to use. +@param value The JSValue to test. +@param constructor The constructor to test against. +@param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. +@result true if value is an object constructed by constructor, as compared by the JS instanceof operator, otherwise false. +*/ +JS_EXPORT bool JSValueIsInstanceOfConstructor(JSContextRef ctx, JSValueRef value, JSObjectRef constructor, JSValueRef* exception); + +/* Creating values */ + +/*! +@function +@abstract Creates a JavaScript value of the undefined type. +@param ctx The execution context to use. +@result The unique undefined value. +*/ +JS_EXPORT JSValueRef JSValueMakeUndefined(JSContextRef ctx); + +/*! +@function +@abstract Creates a JavaScript value of the null type. +@param ctx The execution context to use. +@result The unique null value. +*/ +JS_EXPORT JSValueRef JSValueMakeNull(JSContextRef ctx); + +/*! +@function +@abstract Creates a JavaScript value of the boolean type. +@param ctx The execution context to use. +@param boolean The bool to assign to the newly created JSValue. +@result A JSValue of the boolean type, representing the value of boolean. +*/ +JS_EXPORT JSValueRef JSValueMakeBoolean(JSContextRef ctx, bool boolean); + +/*! +@function +@abstract Creates a JavaScript value of the number type. +@param ctx The execution context to use. +@param number The double to assign to the newly created JSValue. +@result A JSValue of the number type, representing the value of number. +*/ +JS_EXPORT JSValueRef JSValueMakeNumber(JSContextRef ctx, double number); + +/*! +@function +@abstract Creates a JavaScript value of the string type. +@param ctx The execution context to use. +@param string The JSString to assign to the newly created JSValue. The + newly created JSValue retains string, and releases it upon garbage collection. +@result A JSValue of the string type, representing the value of string. +*/ +JS_EXPORT JSValueRef JSValueMakeString(JSContextRef ctx, JSStringRef string); + +/* Converting to and from JSON formatted strings */ + +/*! + @function + @abstract Creates a JavaScript value from a JSON formatted string. + @param ctx The execution context to use. + @param string The JSString containing the JSON string to be parsed. + @result A JSValue containing the parsed value, or NULL if the input is invalid. + */ +JS_EXPORT JSValueRef JSValueMakeFromJSONString(JSContextRef ctx, JSStringRef string) AVAILABLE_AFTER_WEBKIT_VERSION_4_0; + +/*! + @function + @abstract Creates a JavaScript string containing the JSON serialized representation of a JS value. + @param ctx The execution context to use. + @param value The value to serialize. + @param indent The number of spaces to indent when nesting. If 0, the resulting JSON will not contains newlines. The size of the indent is clamped to 10 spaces. + @param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. + @result A JSString with the result of serialization, or NULL if an exception is thrown. + */ +JS_EXPORT JSStringRef JSValueCreateJSONString(JSContextRef ctx, JSValueRef value, unsigned indent, JSValueRef* exception) AVAILABLE_AFTER_WEBKIT_VERSION_4_0; + +/* Converting to primitive values */ + +/*! +@function +@abstract Converts a JavaScript value to boolean and returns the resulting boolean. +@param ctx The execution context to use. +@param value The JSValue to convert. +@result The boolean result of conversion. +*/ +JS_EXPORT bool JSValueToBoolean(JSContextRef ctx, JSValueRef value); + +/*! +@function +@abstract Converts a JavaScript value to number and returns the resulting number. +@param ctx The execution context to use. +@param value The JSValue to convert. +@param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. +@result The numeric result of conversion, or NaN if an exception is thrown. +*/ +JS_EXPORT double JSValueToNumber(JSContextRef ctx, JSValueRef value, JSValueRef* exception); + +/*! +@function +@abstract Converts a JavaScript value to string and copies the result into a JavaScript string. +@param ctx The execution context to use. +@param value The JSValue to convert. +@param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. +@result A JSString with the result of conversion, or NULL if an exception is thrown. Ownership follows the Create Rule. +*/ +JS_EXPORT JSStringRef JSValueToStringCopy(JSContextRef ctx, JSValueRef value, JSValueRef* exception); + +/*! +@function +@abstract Converts a JavaScript value to object and returns the resulting object. +@param ctx The execution context to use. +@param value The JSValue to convert. +@param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. +@result The JSObject result of conversion, or NULL if an exception is thrown. +*/ +JS_EXPORT JSObjectRef JSValueToObject(JSContextRef ctx, JSValueRef value, JSValueRef* exception); + +/* Garbage collection */ +/*! +@function +@abstract Protects a JavaScript value from garbage collection. +@param ctx The execution context to use. +@param value The JSValue to protect. +@discussion Use this method when you want to store a JSValue in a global or on the heap, where the garbage collector will not be able to discover your reference to it. + +A value may be protected multiple times and must be unprotected an equal number of times before becoming eligible for garbage collection. +*/ +JS_EXPORT void JSValueProtect(JSContextRef ctx, JSValueRef value); + +/*! +@function +@abstract Unprotects a JavaScript value from garbage collection. +@param ctx The execution context to use. +@param value The JSValue to unprotect. +@discussion A value may be protected multiple times and must be unprotected an + equal number of times before becoming eligible for garbage collection. +*/ +JS_EXPORT void JSValueUnprotect(JSContextRef ctx, JSValueRef value); + +#ifdef __cplusplus +} +#endif + +#endif /* JSValueRef_h */ diff --git a/frameworks/JavaScriptCore.framework/Versions/A/Headers/JavaScript.h b/frameworks/JavaScriptCore.framework/Versions/A/Headers/JavaScript.h new file mode 100644 index 000000000..f8d92d8f9 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/Headers/JavaScript.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2006 Apple Inc. All rights reserved. + * Copyright (C) 2008 Alp Toker + * + * 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 JavaScript_h +#define JavaScript_h + +#include +#include +#include +#include +#include + +#endif /* JavaScript_h */ diff --git a/frameworks/JavaScriptCore.framework/Versions/A/Headers/JavaScriptCore.h b/frameworks/JavaScriptCore.framework/Versions/A/Headers/JavaScriptCore.h new file mode 100644 index 000000000..87d601851 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/Headers/JavaScriptCore.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2006, 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. + */ + +#ifndef JavaScriptCore_h +#define JavaScriptCore_h + +#include +#include + +#endif /* JavaScriptCore_h */ diff --git a/frameworks/JavaScriptCore.framework/Versions/A/Headers/WebKitAvailability.h b/frameworks/JavaScriptCore.framework/Versions/A/Headers/WebKitAvailability.h new file mode 100644 index 000000000..0e4f091cc --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/Headers/WebKitAvailability.h @@ -0,0 +1,904 @@ +/* + * Copyright (C) 2008, 2009, 2010 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 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 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 __WebKitAvailability__ +#define __WebKitAvailability__ + +/* The structure of this header is based on AvailabilityMacros.h. The major difference is that the availability + macros are defined in terms of WebKit version numbers rather than Mac OS X system version numbers, as WebKit + releases span multiple versions of Mac OS X. +*/ + +#define WEBKIT_VERSION_1_0 0x0100 +#define WEBKIT_VERSION_1_1 0x0110 +#define WEBKIT_VERSION_1_2 0x0120 +#define WEBKIT_VERSION_1_3 0x0130 +#define WEBKIT_VERSION_2_0 0x0200 +#define WEBKIT_VERSION_3_0 0x0300 +#define WEBKIT_VERSION_3_1 0x0310 +#define WEBKIT_VERSION_4_0 0x0400 +#define WEBKIT_VERSION_LATEST 0x9999 + +#ifdef __APPLE__ +#include +#else +/* + * For non-Mac platforms, require the newest version. + */ +#define WEBKIT_VERSION_MIN_REQUIRED WEBKIT_VERSION_LATEST +/* + * only certain compilers support __attribute__((deprecated)) + */ +#if defined(__GNUC__) && ((__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1))) + #define DEPRECATED_ATTRIBUTE __attribute__((deprecated)) +#else + #define DEPRECATED_ATTRIBUTE +#endif +#endif + +/* The versions of GCC that shipped with Xcode prior to 3.0 (GCC build number < 5400) did not support attributes on methods. + If we are building with one of these versions, we need to omit the attribute. We achieve this by wrapping the annotation + in WEBKIT_OBJC_METHOD_ANNOTATION, which will remove the annotation when an old version of GCC is in use and will otherwise + expand to the annotation. The same is needed for protocol methods. +*/ +#if defined(__APPLE_CC__) && __APPLE_CC__ < 5400 + #define WEBKIT_OBJC_METHOD_ANNOTATION(ANNOTATION) +#else + #define WEBKIT_OBJC_METHOD_ANNOTATION(ANNOTATION) ANNOTATION +#endif + + +/* If minimum WebKit version is not specified, assume the version that shipped with the target Mac OS X version */ +#ifndef WEBKIT_VERSION_MIN_REQUIRED + #if !defined(MAC_OS_X_VERSION_10_2) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_2 + #error WebKit was not available prior to Mac OS X 10.2 + #elif !defined(MAC_OS_X_VERSION_10_3) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_3 + /* WebKit 1.0 is the only version available on Mac OS X 10.2. */ + #define WEBKIT_VERSION_MIN_REQUIRED WEBKIT_VERSION_1_0 + #elif !defined(MAC_OS_X_VERSION_10_4) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_4 + /* WebKit 1.1 is the version that shipped on Mac OS X 10.3. */ + #define WEBKIT_VERSION_MIN_REQUIRED WEBKIT_VERSION_1_1 + #elif !defined(MAC_OS_X_VERSION_10_5) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 + /* WebKit 2.0 is the version that shipped on Mac OS X 10.4. */ + #define WEBKIT_VERSION_MIN_REQUIRED WEBKIT_VERSION_2_0 + #elif !defined(MAC_OS_X_VERSION_10_6) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6 + /* WebKit 3.0 is the version that shipped on Mac OS X 10.5. */ + #define WEBKIT_VERSION_MIN_REQUIRED WEBKIT_VERSION_3_0 + #elif !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7 + /* WebKit 4.0 is the version that shipped on Mac OS X 10.6. */ + #define WEBKIT_VERSION_MIN_REQUIRED WEBKIT_VERSION_4_0 + #else + #define WEBKIT_VERSION_MIN_REQUIRED WEBKIT_VERSION_LATEST + #endif +#endif + + +/* If maximum WebKit version is not specified, assume largerof(latest, minimum) */ +#ifndef WEBKIT_VERSION_MAX_ALLOWED + #if WEBKIT_VERSION_MIN_REQUIRED > WEBKIT_VERSION_LATEST + #define WEBKIT_VERSION_MAX_ALLOWED WEBKIT_VERSION_MIN_REQUIRED + #else + #define WEBKIT_VERSION_MAX_ALLOWED WEBKIT_VERSION_LATEST + #endif +#endif + + +/* Sanity check the configured values */ +#if WEBKIT_VERSION_MAX_ALLOWED < WEBKIT_VERSION_MIN_REQUIRED + #error WEBKIT_VERSION_MAX_ALLOWED must be >= WEBKIT_VERSION_MIN_REQUIRED +#endif +#if WEBKIT_VERSION_MIN_REQUIRED < WEBKIT_VERSION_1_0 + #error WEBKIT_VERSION_MIN_REQUIRED must be >= WEBKIT_VERSION_1_0 +#endif + + + + + + +/* + * AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER + * + * Used on functions introduced in WebKit 1.0 + */ +#define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER + +/* + * AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED + * + * Used on functions introduced in WebKit 1.0, + * and deprecated in WebKit 1.0 + */ +#define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED DEPRECATED_ATTRIBUTE + +/* + * DEPRECATED_IN_WEBKIT_VERSION_1_0_AND_LATER + * + * Used on types deprecated in WebKit 1.0 + */ +#define DEPRECATED_IN_WEBKIT_VERSION_1_0_AND_LATER DEPRECATED_ATTRIBUTE + + + + + + +/* + * AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER + * + * Used on declarations introduced in WebKit 1.1 + */ +#if WEBKIT_VERSION_MAX_ALLOWED < WEBKIT_VERSION_1_1 + #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER UNAVAILABLE_ATTRIBUTE +#elif WEBKIT_VERSION_MIN_REQUIRED < WEBKIT_VERSION_1_1 + #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER WEAK_IMPORT_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED + * + * Used on declarations introduced in WebKit 1.1, + * and deprecated in WebKit 1.1 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_1_1 + #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_1_1 + * + * Used on declarations introduced in WebKit 1.0, + * but later deprecated in WebKit 1.1 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_1_1 + #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_1_1 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_1_1 AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER +#endif + +/* + * DEPRECATED_IN_WEBKIT_VERSION_1_1_AND_LATER + * + * Used on types deprecated in WebKit 1.1 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_1_1 + #define DEPRECATED_IN_WEBKIT_VERSION_1_1_AND_LATER DEPRECATED_ATTRIBUTE +#else + #define DEPRECATED_IN_WEBKIT_VERSION_1_1_AND_LATER +#endif + + + + + + +/* + * AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER + * + * Used on declarations introduced in WebKit 1.2 + */ +#if WEBKIT_VERSION_MAX_ALLOWED < WEBKIT_VERSION_1_2 + #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER UNAVAILABLE_ATTRIBUTE +#elif WEBKIT_VERSION_MIN_REQUIRED < WEBKIT_VERSION_1_2 + #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER WEAK_IMPORT_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED + * + * Used on declarations introduced in WebKit 1.2, + * and deprecated in WebKit 1.2 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_1_2 + #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_1_2 + * + * Used on declarations introduced in WebKit 1.0, + * but later deprecated in WebKit 1.2 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_1_2 + #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_1_2 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_1_2 AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_1_2 + * + * Used on declarations introduced in WebKit 1.1, + * but later deprecated in WebKit 1.2 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_1_2 + #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_1_2 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_1_2 AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER +#endif + +/* + * DEPRECATED_IN_WEBKIT_VERSION_1_2_AND_LATER + * + * Used on types deprecated in WebKit 1.2 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_1_2 + #define DEPRECATED_IN_WEBKIT_VERSION_1_2_AND_LATER DEPRECATED_ATTRIBUTE +#else + #define DEPRECATED_IN_WEBKIT_VERSION_1_2_AND_LATER +#endif + + + + + + +/* + * AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER + * + * Used on declarations introduced in WebKit 1.3 + */ +#if WEBKIT_VERSION_MAX_ALLOWED < WEBKIT_VERSION_1_3 + #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER UNAVAILABLE_ATTRIBUTE +#elif WEBKIT_VERSION_MIN_REQUIRED < WEBKIT_VERSION_1_3 + #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER WEAK_IMPORT_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED + * + * Used on declarations introduced in WebKit 1.3, + * and deprecated in WebKit 1.3 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_1_3 + #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_1_3 + * + * Used on declarations introduced in WebKit 1.0, + * but later deprecated in WebKit 1.3 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_1_3 + #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_1_3 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_1_3 AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_1_3 + * + * Used on declarations introduced in WebKit 1.1, + * but later deprecated in WebKit 1.3 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_1_3 + #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_1_3 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_1_3 AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_1_3 + * + * Used on declarations introduced in WebKit 1.2, + * but later deprecated in WebKit 1.3 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_1_3 + #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_1_3 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_1_3 AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER +#endif + +/* + * DEPRECATED_IN_WEBKIT_VERSION_1_3_AND_LATER + * + * Used on types deprecated in WebKit 1.3 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_1_3 + #define DEPRECATED_IN_WEBKIT_VERSION_1_3_AND_LATER DEPRECATED_ATTRIBUTE +#else + #define DEPRECATED_IN_WEBKIT_VERSION_1_3_AND_LATER +#endif + + + + + + +/* + * AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER + * + * Used on declarations introduced in WebKit 2.0 + */ +#if WEBKIT_VERSION_MAX_ALLOWED < WEBKIT_VERSION_2_0 + #define AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER UNAVAILABLE_ATTRIBUTE +#elif WEBKIT_VERSION_MIN_REQUIRED < WEBKIT_VERSION_2_0 + #define AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER WEAK_IMPORT_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED + * + * Used on declarations introduced in WebKit 2.0, + * and deprecated in WebKit 2.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_2_0 + #define AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_2_0 + * + * Used on declarations introduced in WebKit 1.0, + * but later deprecated in WebKit 2.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_2_0 + #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_2_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_2_0 AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_2_0 + * + * Used on declarations introduced in WebKit 1.1, + * but later deprecated in WebKit 2.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_2_0 + #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_2_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_2_0 AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_2_0 + * + * Used on declarations introduced in WebKit 1.2, + * but later deprecated in WebKit 2.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_2_0 + #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_2_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_2_0 AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_2_0 + * + * Used on declarations introduced in WebKit 1.3, + * but later deprecated in WebKit 2.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_2_0 + #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_2_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_2_0 AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER +#endif + +/* + * DEPRECATED_IN_WEBKIT_VERSION_2_0_AND_LATER + * + * Used on types deprecated in WebKit 2.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_2_0 + #define DEPRECATED_IN_WEBKIT_VERSION_2_0_AND_LATER DEPRECATED_ATTRIBUTE +#else + #define DEPRECATED_IN_WEBKIT_VERSION_2_0_AND_LATER +#endif + + + + + + +/* + * AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER + * + * Used on declarations introduced in WebKit 3.0 + */ +#if WEBKIT_VERSION_MAX_ALLOWED < WEBKIT_VERSION_3_0 + #define AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER UNAVAILABLE_ATTRIBUTE +#elif WEBKIT_VERSION_MIN_REQUIRED < WEBKIT_VERSION_3_0 + #define AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER WEAK_IMPORT_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER_BUT_DEPRECATED + * + * Used on declarations introduced in WebKit 3.0, + * and deprecated in WebKit 3.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_3_0 + #define AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER_BUT_DEPRECATED DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER_BUT_DEPRECATED AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_0 + * + * Used on declarations introduced in WebKit 1.0, + * but later deprecated in WebKit 3.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_3_0 + #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_0 AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_0 + * + * Used on declarations introduced in WebKit 1.1, + * but later deprecated in WebKit 3.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_3_0 + #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_0 AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_0 + * + * Used on declarations introduced in WebKit 1.2, + * but later deprecated in WebKit 3.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_3_0 + #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_0 AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_0 + * + * Used on declarations introduced in WebKit 1.3, + * but later deprecated in WebKit 3.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_3_0 + #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_0 AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_0 + * + * Used on declarations introduced in WebKit 2.0, + * but later deprecated in WebKit 3.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_3_0 + #define AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_0 AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER +#endif + +/* + * DEPRECATED_IN_WEBKIT_VERSION_3_0_AND_LATER + * + * Used on types deprecated in WebKit 3.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_3_0 + #define DEPRECATED_IN_WEBKIT_VERSION_3_0_AND_LATER DEPRECATED_ATTRIBUTE +#else + #define DEPRECATED_IN_WEBKIT_VERSION_3_0_AND_LATER +#endif + + + + + + +/* + * AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER + * + * Used on declarations introduced in WebKit 3.1 + */ +#if WEBKIT_VERSION_MAX_ALLOWED < WEBKIT_VERSION_3_1 + #define AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER UNAVAILABLE_ATTRIBUTE +#elif WEBKIT_VERSION_MIN_REQUIRED < WEBKIT_VERSION_3_1 + #define AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER WEAK_IMPORT_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER_BUT_DEPRECATED + * + * Used on declarations introduced in WebKit 3.1, + * and deprecated in WebKit 3.1 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_3_1 + #define AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER_BUT_DEPRECATED DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER_BUT_DEPRECATED AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_1 + * + * Used on declarations introduced in WebKit 1.0, + * but later deprecated in WebKit 3.1 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_3_1 + #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_1 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_1 AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_1 + * + * Used on declarations introduced in WebKit 1.1, + * but later deprecated in WebKit 3.1 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_3_1 + #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_1 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_1 AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_1 + * + * Used on declarations introduced in WebKit 1.2, + * but later deprecated in WebKit 3.1 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_3_1 + #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_1 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_1 AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_1 + * + * Used on declarations introduced in WebKit 1.3, + * but later deprecated in WebKit 3.1 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_3_1 + #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_1 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_1 AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_1 + * + * Used on declarations introduced in WebKit 2.0, + * but later deprecated in WebKit 3.1 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_3_1 + #define AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_1 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_1 AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_1 + * + * Used on declarations introduced in WebKit 3.0, + * but later deprecated in WebKit 3.1 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_3_1 + #define AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_1 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_3_1 AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER +#endif + +/* + * DEPRECATED_IN_WEBKIT_VERSION_3_1_AND_LATER + * + * Used on types deprecated in WebKit 3.1 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_3_1 + #define DEPRECATED_IN_WEBKIT_VERSION_3_1_AND_LATER DEPRECATED_ATTRIBUTE +#else + #define DEPRECATED_IN_WEBKIT_VERSION_3_1_AND_LATER +#endif + + + + + + +/* + * AVAILABLE_IN_WEBKIT_VERSION_4_0 + * + * Used on declarations introduced in WebKit 4.0 + */ +#if WEBKIT_VERSION_MAX_ALLOWED < WEBKIT_VERSION_4_0 + #define AVAILABLE_IN_WEBKIT_VERSION_4_0 UNAVAILABLE_ATTRIBUTE +#elif WEBKIT_VERSION_MIN_REQUIRED < WEBKIT_VERSION_4_0 + #define AVAILABLE_IN_WEBKIT_VERSION_4_0 WEAK_IMPORT_ATTRIBUTE +#else + #define AVAILABLE_IN_WEBKIT_VERSION_4_0 +#endif + +/* + * AVAILABLE_IN_WEBKIT_VERSION_4_0_BUT_DEPRECATED + * + * Used on declarations introduced in WebKit 4.0, + * and deprecated in WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_4_0 + #define AVAILABLE_IN_WEBKIT_VERSION_4_0_BUT_DEPRECATED DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_IN_WEBKIT_VERSION_4_0_BUT_DEPRECATED AVAILABLE_IN_WEBKIT_VERSION_4_0 +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 + * + * Used on declarations introduced in WebKit 1.0, + * but later deprecated in WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_4_0 + #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 + * + * Used on declarations introduced in WebKit 1.1, + * but later deprecated in WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_4_0 + #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 + * + * Used on declarations introduced in WebKit 1.2, + * but later deprecated in WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_4_0 + #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 + * + * Used on declarations introduced in WebKit 1.3, + * but later deprecated in WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_4_0 + #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 + * + * Used on declarations introduced in WebKit 2.0, + * but later deprecated in WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_4_0 + #define AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 + * + * Used on declarations introduced in WebKit 3.0, + * but later deprecated in WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_4_0 + #define AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 + * + * Used on declarations introduced in WebKit 3.1, + * but later deprecated in WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_4_0 + #define AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER +#endif + +/* + * DEPRECATED_IN_WEBKIT_VERSION_4_0 + * + * Used on types deprecated in WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_4_0 + #define DEPRECATED_IN_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE +#else + #define DEPRECATED_IN_WEBKIT_VERSION_4_0 +#endif + + + + + + +/* + * AVAILABLE_AFTER_WEBKIT_VERSION_4_0 + * + * Used on declarations introduced after WebKit 4.0 + */ +#if WEBKIT_VERSION_MAX_ALLOWED < WEBKIT_VERSION_LATEST + #define AVAILABLE_AFTER_WEBKIT_VERSION_4_0 UNAVAILABLE_ATTRIBUTE +#elif WEBKIT_VERSION_MIN_REQUIRED < WEBKIT_VERSION_LATEST + #define AVAILABLE_AFTER_WEBKIT_VERSION_4_0 WEAK_IMPORT_ATTRIBUTE +#else + #define AVAILABLE_AFTER_WEBKIT_VERSION_4_0 +#endif + +/* + * AVAILABLE_AFTER_WEBKIT_VERSION_4_0_BUT_DEPRECATED + * + * Used on declarations introduced after WebKit 4.0, + * and deprecated after WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST + #define AVAILABLE_AFTER_WEBKIT_VERSION_4_0_BUT_DEPRECATED DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_AFTER_WEBKIT_VERSION_4_0_BUT_DEPRECATED AVAILABLE_AFTER_WEBKIT_VERSION_4_0 +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 + * + * Used on declarations introduced in WebKit 1.0, + * but later deprecated after WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST + #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 + * + * Used on declarations introduced in WebKit 1.1, + * but later deprecated after WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST + #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 + * + * Used on declarations introduced in WebKit 1.2, + * but later deprecated after WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST + #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 + * + * Used on declarations introduced in WebKit 1.3, + * but later deprecated after WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST + #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 + * + * Used on declarations introduced in WebKit 2.0, + * but later deprecated after WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST + #define AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 + * + * Used on declarations introduced in WebKit 3.0, + * but later deprecated after WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST + #define AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 + * + * Used on declarations introduced in WebKit 3.1, + * but later deprecated after WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST + #define AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_4_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 + * + * Used on declarations introduced in WebKit 4.0 + * but later deprecated after WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST + #define AVAILABLE_WEBKIT_VERSION_4_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_4_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_4_0_AND_LATER +#endif + +/* + * DEPRECATED_AFTER_WEBKIT_VERSION_4_0 + * + * Used on types deprecated after WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST + #define DEPRECATED_AFTER_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE +#else + #define DEPRECATED_AFTER_WEBKIT_VERSION_4_0 +#endif + + +#endif /* __WebKitAvailability__ */ diff --git a/frameworks/JavaScriptCore.framework/Versions/A/JavaScriptCore b/frameworks/JavaScriptCore.framework/Versions/A/JavaScriptCore new file mode 100755 index 000000000..9b5a933e9 Binary files /dev/null and b/frameworks/JavaScriptCore.framework/Versions/A/JavaScriptCore differ diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/APICast.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/APICast.h new file mode 100644 index 000000000..4294d3d68 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/APICast.h @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2006 Apple Computer, 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 APICast_h +#define APICast_h + +#include "JSAPIValueWrapper.h" +#include "JSGlobalObject.h" +#include "JSValue.h" +#include + +namespace JSC { + class ExecState; + class PropertyNameArray; + class JSGlobalData; + class JSObject; + class JSValue; +} + +typedef const struct OpaqueJSContextGroup* JSContextGroupRef; +typedef const struct OpaqueJSContext* JSContextRef; +typedef struct OpaqueJSContext* JSGlobalContextRef; +typedef struct OpaqueJSPropertyNameAccumulator* JSPropertyNameAccumulatorRef; +typedef const struct OpaqueJSValue* JSValueRef; +typedef struct OpaqueJSValue* JSObjectRef; + +/* Opaque typing convenience methods */ + +inline JSC::ExecState* toJS(JSContextRef c) +{ + ASSERT(c); + return reinterpret_cast(const_cast(c)); +} + +inline JSC::ExecState* toJS(JSGlobalContextRef c) +{ + ASSERT(c); + return reinterpret_cast(c); +} + +inline JSC::JSValue toJS(JSC::ExecState* exec, JSValueRef v) +{ + ASSERT_UNUSED(exec, exec); + ASSERT(v); +#if USE(JSVALUE32_64) + JSC::JSCell* jsCell = reinterpret_cast(const_cast(v)); + if (!jsCell) + return JSC::JSValue(); + if (jsCell->isAPIValueWrapper()) + return static_cast(jsCell)->value(); + return jsCell; +#else + return JSC::JSValue::decode(reinterpret_cast(const_cast(v))); +#endif +} + +inline JSC::JSValue toJSForGC(JSC::ExecState* exec, JSValueRef v) +{ + ASSERT_UNUSED(exec, exec); + ASSERT(v); +#if USE(JSVALUE32_64) + JSC::JSCell* jsCell = reinterpret_cast(const_cast(v)); + if (!jsCell) + return JSC::JSValue(); + return jsCell; +#else + return JSC::JSValue::decode(reinterpret_cast(const_cast(v))); +#endif +} + +inline JSC::JSObject* toJS(JSObjectRef o) +{ + return reinterpret_cast(o); +} + +inline JSC::PropertyNameArray* toJS(JSPropertyNameAccumulatorRef a) +{ + return reinterpret_cast(a); +} + +inline JSC::JSGlobalData* toJS(JSContextGroupRef g) +{ + return reinterpret_cast(const_cast(g)); +} + +inline JSValueRef toRef(JSC::ExecState* exec, JSC::JSValue v) +{ +#if USE(JSVALUE32_64) + if (!v) + return 0; + if (!v.isCell()) + return reinterpret_cast(JSC::jsAPIValueWrapper(exec, v).asCell()); + return reinterpret_cast(v.asCell()); +#else + UNUSED_PARAM(exec); + return reinterpret_cast(JSC::JSValue::encode(v)); +#endif +} + +inline JSObjectRef toRef(JSC::JSObject* o) +{ + return reinterpret_cast(o); +} + +inline JSObjectRef toRef(const JSC::JSObject* o) +{ + return reinterpret_cast(const_cast(o)); +} + +inline JSContextRef toRef(JSC::ExecState* e) +{ + return reinterpret_cast(e); +} + +inline JSGlobalContextRef toGlobalRef(JSC::ExecState* e) +{ + ASSERT(e == e->lexicalGlobalObject()->globalExec()); + return reinterpret_cast(e); +} + +inline JSPropertyNameAccumulatorRef toRef(JSC::PropertyNameArray* l) +{ + return reinterpret_cast(l); +} + +inline JSContextGroupRef toRef(JSC::JSGlobalData* g) +{ + return reinterpret_cast(g); +} + +#endif // APICast_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/APIShims.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/APIShims.h new file mode 100644 index 000000000..02495110b --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/APIShims.h @@ -0,0 +1,102 @@ +/* + * 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 APIShims_h +#define APIShims_h + +#include "CallFrame.h" +#include "GCActivityCallback.h" +#include "JSLock.h" +#include + +namespace JSC { + +class APIEntryShimWithoutLock { +protected: + APIEntryShimWithoutLock(JSGlobalData* globalData, bool registerThread) + : m_globalData(globalData) + , m_entryIdentifierTable(wtfThreadData().setCurrentIdentifierTable(globalData->identifierTable)) + { + UNUSED_PARAM(registerThread); + if (registerThread) + globalData->heap.machineThreads().addCurrentThread(); + m_globalData->heap.activityCallback()->synchronize(); + m_globalData->timeoutChecker.start(); + } + + ~APIEntryShimWithoutLock() + { + m_globalData->timeoutChecker.stop(); + wtfThreadData().setCurrentIdentifierTable(m_entryIdentifierTable); + } + +private: + JSGlobalData* m_globalData; + IdentifierTable* m_entryIdentifierTable; +}; + +class APIEntryShim : public APIEntryShimWithoutLock { +public: + // Normal API entry + APIEntryShim(ExecState* exec, bool registerThread = true) + : APIEntryShimWithoutLock(&exec->globalData(), registerThread) + , m_lock(exec) + { + } + + // JSPropertyNameAccumulator only has a globalData. + APIEntryShim(JSGlobalData* globalData, bool registerThread = true) + : APIEntryShimWithoutLock(globalData, registerThread) + , m_lock(globalData->isSharedInstance() ? LockForReal : SilenceAssertionsOnly) + { + } + +private: + JSLock m_lock; +}; + +class APICallbackShim { +public: + APICallbackShim(ExecState* exec) + : m_dropAllLocks(exec) + , m_globalData(&exec->globalData()) + { + wtfThreadData().resetCurrentIdentifierTable(); + } + + ~APICallbackShim() + { + m_globalData->heap.activityCallback()->synchronize(); + wtfThreadData().setCurrentIdentifierTable(m_globalData->identifierTable); + } + +private: + JSLock::DropAllLocks m_dropAllLocks; + JSGlobalData* m_globalData; +}; + +} + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ASCIICType.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ASCIICType.h new file mode 100644 index 000000000..17006ae2d --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ASCIICType.h @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2007, 2008, 2009, 2011 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 WTF_ASCIICType_h +#define WTF_ASCIICType_h + +#include + +// The behavior of many of the functions in the header is dependent +// on the current locale. But in the WebKit project, all uses of those functions +// are in code processing something that's not locale-specific. These equivalents +// for some of the functions are named more explicitly, not dependent +// on the C library locale, and we should also optimize them as needed. + +// All functions return false or leave the character unchanged if passed a character +// that is outside the range 0-7F. So they can be used on Unicode strings or +// characters if the intent is to do processing only if the character is ASCII. + +namespace WTF { + +template inline bool isASCII(CharType c) +{ + return !(c & ~0x7F); +} + +template inline bool isASCIIAlpha(CharType c) +{ + return (c | 0x20) >= 'a' && (c | 0x20) <= 'z'; +} + +template inline bool isASCIIDigit(CharType c) +{ + return c >= '0' && c <= '9'; +} + +template inline bool isASCIIAlphanumeric(CharType c) +{ + return isASCIIDigit(c) || isASCIIAlpha(c); +} + +template inline bool isASCIIHexDigit(CharType c) +{ + return isASCIIDigit(c) || ((c | 0x20) >= 'a' && (c | 0x20) <= 'f'); +} + +template inline bool isASCIILower(CharType c) +{ + return c >= 'a' && c <= 'z'; +} + +template inline bool isASCIIOctalDigit(CharType c) +{ + return (c >= '0') & (c <= '7'); +} + +template inline bool isASCIIPrintable(CharType c) +{ + return c >= ' ' && c <= '~'; +} + +/* + Statistics from a run of Apple's page load test for callers of isASCIISpace: + + character count + --------- ----- + non-spaces 689383 + 20 space 294720 + 0A \n 89059 + 09 \t 28320 + 0D \r 0 + 0C \f 0 + 0B \v 0 + */ +template inline bool isASCIISpace(CharType c) +{ + return c <= ' ' && (c == ' ' || (c <= 0xD && c >= 0x9)); +} + +template inline bool isASCIIUpper(CharType c) +{ + return c >= 'A' && c <= 'Z'; +} + +template inline CharType toASCIILower(CharType c) +{ + return c | ((c >= 'A' && c <= 'Z') << 5); +} + +template inline CharType toASCIIUpper(CharType c) +{ + return c & ~((c >= 'a' && c <= 'z') << 5); +} + +template inline int toASCIIHexValue(CharType c) +{ + ASSERT(isASCIIHexDigit(c)); + return c < 'A' ? c - '0' : (c - 'A' + 10) & 0xF; +} + +template inline int toASCIIHexValue(CharType upperValue, CharType lowerValue) +{ + ASSERT(isASCIIHexDigit(upperValue) && isASCIIHexDigit(lowerValue)); + return ((toASCIIHexValue(upperValue) << 4) & 0xF0) | toASCIIHexValue(lowerValue); +} + +inline char lowerNibbleToASCIIHexDigit(char c) +{ + char nibble = c & 0xF; + return nibble < 10 ? '0' + nibble : 'A' + nibble - 10; +} + +inline char upperNibbleToASCIIHexDigit(char c) +{ + char nibble = (c >> 4) & 0xF; + return nibble < 10 ? '0' + nibble : 'A' + nibble - 10; +} + +} + +using WTF::isASCII; +using WTF::isASCIIAlpha; +using WTF::isASCIIAlphanumeric; +using WTF::isASCIIDigit; +using WTF::isASCIIHexDigit; +using WTF::isASCIILower; +using WTF::isASCIIOctalDigit; +using WTF::isASCIIPrintable; +using WTF::isASCIISpace; +using WTF::isASCIIUpper; +using WTF::toASCIIHexValue; +using WTF::toASCIILower; +using WTF::toASCIIUpper; +using WTF::lowerNibbleToASCIIHexDigit; +using WTF::upperNibbleToASCIIHexDigit; + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ASCIIFastPath.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ASCIIFastPath.h new file mode 100644 index 000000000..ace1a687d --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ASCIIFastPath.h @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef ASCIIFastPath_h +#define ASCIIFastPath_h + +#include +#include + +namespace WTF { + +// Assuming that a pointer is the size of a "machine word", then +// uintptr_t is an integer type that is also a machine word. +typedef uintptr_t MachineWord; +const uintptr_t machineWordAlignmentMask = sizeof(MachineWord) - 1; + +inline bool isAlignedToMachineWord(const void* pointer) +{ + return !(reinterpret_cast(pointer) & machineWordAlignmentMask); +} + +template inline T* alignToMachineWord(T* pointer) +{ + return reinterpret_cast(reinterpret_cast(pointer) & ~machineWordAlignmentMask); +} + +template struct NonASCIIMask; +template<> struct NonASCIIMask<4, UChar> { + static inline uint32_t value() { return 0xFF80FF80U; } +}; +template<> struct NonASCIIMask<4, LChar> { + static inline uint32_t value() { return 0x80808080U; } +}; +template<> struct NonASCIIMask<8, UChar> { + static inline uint64_t value() { return 0xFF80FF80FF80FF80ULL; } +}; +template<> struct NonASCIIMask<8, LChar> { + static inline uint64_t value() { return 0x8080808080808080ULL; } +}; + + +template +inline bool isAllASCII(MachineWord word) +{ + return !(word & NonASCIIMask::value()); +} + +// Note: This function assume the input is likely all ASCII, and +// does not leave early if it is not the case. +template +inline bool charactersAreAllASCII(const CharacterType* characters, size_t length) +{ + MachineWord allCharBits = 0; + const CharacterType* end = characters + length; + + // Prologue: align the input. + while (!isAlignedToMachineWord(characters) && characters != end) { + allCharBits |= *characters; + ++characters; + } + + // Compare the values of CPU word size. + const CharacterType* wordEnd = alignToMachineWord(end); + const size_t loopIncrement = sizeof(MachineWord) / sizeof(CharacterType); + while (characters < wordEnd) { + allCharBits |= *(reinterpret_cast(characters)); + characters += loopIncrement; + } + + // Process the remaining bytes. + while (characters != end) { + allCharBits |= *characters; + ++characters; + } + + MachineWord nonASCIIBitMask = NonASCIIMask::value(); + return !(allCharBits & nonASCIIBitMask); +} + + +} // namespace WTF + +#endif // ASCIIFastPath_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/AVLTree.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/AVLTree.h new file mode 100644 index 000000000..ec8a63951 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/AVLTree.h @@ -0,0 +1,960 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * Based on Abstract AVL Tree Template v1.5 by Walt Karas + * . + * + * 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 AVL_TREE_H_ +#define AVL_TREE_H_ + +#include "Assertions.h" +#include + +namespace WTF { + +// Here is the reference class for BSet. +// +// class BSet +// { +// public: +// +// class ANY_bitref +// { +// public: +// operator bool (); +// void operator = (bool b); +// }; +// +// // Does not have to initialize bits. +// BSet(); +// +// // Must return a valid value for index when 0 <= index < maxDepth +// ANY_bitref operator [] (unsigned index); +// +// // Set all bits to 1. +// void set(); +// +// // Set all bits to 0. +// void reset(); +// }; + +template +class AVLTreeDefaultBSet { +public: + bool& operator[](unsigned i) { ASSERT(i < maxDepth); return m_data[i]; } + void set() { for (unsigned i = 0; i < maxDepth; ++i) m_data[i] = true; } + void reset() { for (unsigned i = 0; i < maxDepth; ++i) m_data[i] = false; } + +private: + FixedArray m_data; +}; + +// How to determine maxDepth: +// d Minimum number of nodes +// 2 2 +// 3 4 +// 4 7 +// 5 12 +// 6 20 +// 7 33 +// 8 54 +// 9 88 +// 10 143 +// 11 232 +// 12 376 +// 13 609 +// 14 986 +// 15 1,596 +// 16 2,583 +// 17 4,180 +// 18 6,764 +// 19 10,945 +// 20 17,710 +// 21 28,656 +// 22 46,367 +// 23 75,024 +// 24 121,392 +// 25 196,417 +// 26 317,810 +// 27 514,228 +// 28 832,039 +// 29 1,346,268 +// 30 2,178,308 +// 31 3,524,577 +// 32 5,702,886 +// 33 9,227,464 +// 34 14,930,351 +// 35 24,157,816 +// 36 39,088,168 +// 37 63,245,985 +// 38 102,334,154 +// 39 165,580,140 +// 40 267,914,295 +// 41 433,494,436 +// 42 701,408,732 +// 43 1,134,903,169 +// 44 1,836,311,902 +// 45 2,971,215,072 +// +// E.g., if, in a particular instantiation, the maximum number of nodes in a tree instance is 1,000,000, the maximum depth should be 28. +// You pick 28 because MN(28) is 832,039, which is less than or equal to 1,000,000, and MN(29) is 1,346,268, which is strictly greater than 1,000,000. + +template > +class AVLTree { +public: + + typedef typename Abstractor::key key; + typedef typename Abstractor::handle handle; + typedef typename Abstractor::size size; + + enum SearchType { + EQUAL = 1, + LESS = 2, + GREATER = 4, + LESS_EQUAL = EQUAL | LESS, + GREATER_EQUAL = EQUAL | GREATER + }; + + + Abstractor& abstractor() { return abs; } + + inline handle insert(handle h); + + inline handle search(key k, SearchType st = EQUAL); + inline handle search_least(); + inline handle search_greatest(); + + inline handle remove(key k); + + inline handle subst(handle new_node); + + void purge() { abs.root = null(); } + + bool is_empty() { return abs.root == null(); } + + AVLTree() { abs.root = null(); } + + class Iterator { + public: + + // Initialize depth to invalid value, to indicate iterator is + // invalid. (Depth is zero-base.) + Iterator() { depth = ~0U; } + + void start_iter(AVLTree &tree, key k, SearchType st = EQUAL) + { + // Mask of high bit in an int. + const int MASK_HIGH_BIT = (int) ~ ((~ (unsigned) 0) >> 1); + + // Save the tree that we're going to iterate through in a + // member variable. + tree_ = &tree; + + int cmp, target_cmp; + handle h = tree_->abs.root; + unsigned d = 0; + + depth = ~0U; + + if (h == null()) + // Tree is empty. + return; + + if (st & LESS) + // Key can be greater than key of starting node. + target_cmp = 1; + else if (st & GREATER) + // Key can be less than key of starting node. + target_cmp = -1; + else + // Key must be same as key of starting node. + target_cmp = 0; + + for (;;) { + cmp = cmp_k_n(k, h); + if (cmp == 0) { + if (st & EQUAL) { + // Equal node was sought and found as starting node. + depth = d; + break; + } + cmp = -target_cmp; + } else if (target_cmp != 0) { + if (!((cmp ^ target_cmp) & MASK_HIGH_BIT)) { + // cmp and target_cmp are both negative or both positive. + depth = d; + } + } + h = cmp < 0 ? get_lt(h) : get_gt(h); + if (h == null()) + break; + branch[d] = cmp > 0; + path_h[d++] = h; + } + } + + void start_iter_least(AVLTree &tree) + { + tree_ = &tree; + + handle h = tree_->abs.root; + + depth = ~0U; + + branch.reset(); + + while (h != null()) { + if (depth != ~0U) + path_h[depth] = h; + depth++; + h = get_lt(h); + } + } + + void start_iter_greatest(AVLTree &tree) + { + tree_ = &tree; + + handle h = tree_->abs.root; + + depth = ~0U; + + branch.set(); + + while (h != null()) { + if (depth != ~0U) + path_h[depth] = h; + depth++; + h = get_gt(h); + } + } + + handle operator*() + { + if (depth == ~0U) + return null(); + + return depth == 0 ? tree_->abs.root : path_h[depth - 1]; + } + + void operator++() + { + if (depth != ~0U) { + handle h = get_gt(**this); + if (h == null()) { + do { + if (depth == 0) { + depth = ~0U; + break; + } + depth--; + } while (branch[depth]); + } else { + branch[depth] = true; + path_h[depth++] = h; + for (;;) { + h = get_lt(h); + if (h == null()) + break; + branch[depth] = false; + path_h[depth++] = h; + } + } + } + } + + void operator--() + { + if (depth != ~0U) { + handle h = get_lt(**this); + if (h == null()) + do { + if (depth == 0) { + depth = ~0U; + break; + } + depth--; + } while (!branch[depth]); + else { + branch[depth] = false; + path_h[depth++] = h; + for (;;) { + h = get_gt(h); + if (h == null()) + break; + branch[depth] = true; + path_h[depth++] = h; + } + } + } + } + + void operator++(int) { ++(*this); } + void operator--(int) { --(*this); } + + protected: + + // Tree being iterated over. + AVLTree *tree_; + + // Records a path into the tree. If branch[n] is true, indicates + // take greater branch from the nth node in the path, otherwise + // take the less branch. branch[0] gives branch from root, and + // so on. + BSet branch; + + // Zero-based depth of path into tree. + unsigned depth; + + // Handles of nodes in path from root to current node (returned by *). + handle path_h[maxDepth - 1]; + + int cmp_k_n(key k, handle h) { return tree_->abs.compare_key_node(k, h); } + int cmp_n_n(handle h1, handle h2) { return tree_->abs.compare_node_node(h1, h2); } + handle get_lt(handle h) { return tree_->abs.get_less(h); } + handle get_gt(handle h) { return tree_->abs.get_greater(h); } + handle null() { return tree_->abs.null(); } + }; + + template + bool build(fwd_iter p, size num_nodes) + { + if (num_nodes == 0) { + abs.root = null(); + return true; + } + + // Gives path to subtree being built. If branch[N] is false, branch + // less from the node at depth N, if true branch greater. + BSet branch; + + // If rem[N] is true, then for the current subtree at depth N, it's + // greater subtree has one more node than it's less subtree. + BSet rem; + + // Depth of root node of current subtree. + unsigned depth = 0; + + // Number of nodes in current subtree. + size num_sub = num_nodes; + + // The algorithm relies on a stack of nodes whose less subtree has + // been built, but whose right subtree has not yet been built. The + // stack is implemented as linked list. The nodes are linked + // together by having the "greater" handle of a node set to the + // next node in the list. "less_parent" is the handle of the first + // node in the list. + handle less_parent = null(); + + // h is root of current subtree, child is one of its children. + handle h, child; + + for (;;) { + while (num_sub > 2) { + // Subtract one for root of subtree. + num_sub--; + rem[depth] = !!(num_sub & 1); + branch[depth++] = false; + num_sub >>= 1; + } + + if (num_sub == 2) { + // Build a subtree with two nodes, slanting to greater. + // I arbitrarily chose to always have the extra node in the + // greater subtree when there is an odd number of nodes to + // split between the two subtrees. + + h = *p; + p++; + child = *p; + p++; + set_lt(child, null()); + set_gt(child, null()); + set_bf(child, 0); + set_gt(h, child); + set_lt(h, null()); + set_bf(h, 1); + } else { // num_sub == 1 + // Build a subtree with one node. + + h = *p; + p++; + set_lt(h, null()); + set_gt(h, null()); + set_bf(h, 0); + } + + while (depth) { + depth--; + if (!branch[depth]) + // We've completed a less subtree. + break; + + // We've completed a greater subtree, so attach it to + // its parent (that is less than it). We pop the parent + // off the stack of less parents. + child = h; + h = less_parent; + less_parent = get_gt(h); + set_gt(h, child); + // num_sub = 2 * (num_sub - rem[depth]) + rem[depth] + 1 + num_sub <<= 1; + num_sub += 1 - rem[depth]; + if (num_sub & (num_sub - 1)) + // num_sub is not a power of 2 + set_bf(h, 0); + else + // num_sub is a power of 2 + set_bf(h, 1); + } + + if (num_sub == num_nodes) + // We've completed the full tree. + break; + + // The subtree we've completed is the less subtree of the + // next node in the sequence. + + child = h; + h = *p; + p++; + set_lt(h, child); + + // Put h into stack of less parents. + set_gt(h, less_parent); + less_parent = h; + + // Proceed to creating greater than subtree of h. + branch[depth] = true; + num_sub += rem[depth++]; + + } // end for (;;) + + abs.root = h; + + return true; + } + +protected: + + friend class Iterator; + + // Create a class whose sole purpose is to take advantage of + // the "empty member" optimization. + struct abs_plus_root : public Abstractor { + // The handle of the root element in the AVL tree. + handle root; + }; + + abs_plus_root abs; + + + handle get_lt(handle h) { return abs.get_less(h); } + void set_lt(handle h, handle lh) { abs.set_less(h, lh); } + + handle get_gt(handle h) { return abs.get_greater(h); } + void set_gt(handle h, handle gh) { abs.set_greater(h, gh); } + + int get_bf(handle h) { return abs.get_balance_factor(h); } + void set_bf(handle h, int bf) { abs.set_balance_factor(h, bf); } + + int cmp_k_n(key k, handle h) { return abs.compare_key_node(k, h); } + int cmp_n_n(handle h1, handle h2) { return abs.compare_node_node(h1, h2); } + + handle null() { return abs.null(); } + +private: + + // Balances subtree, returns handle of root node of subtree + // after balancing. + handle balance(handle bal_h) + { + handle deep_h; + + // Either the "greater than" or the "less than" subtree of + // this node has to be 2 levels deeper (or else it wouldn't + // need balancing). + + if (get_bf(bal_h) > 0) { + // "Greater than" subtree is deeper. + + deep_h = get_gt(bal_h); + + if (get_bf(deep_h) < 0) { + handle old_h = bal_h; + bal_h = get_lt(deep_h); + + set_gt(old_h, get_lt(bal_h)); + set_lt(deep_h, get_gt(bal_h)); + set_lt(bal_h, old_h); + set_gt(bal_h, deep_h); + + int bf = get_bf(bal_h); + if (bf != 0) { + if (bf > 0) { + set_bf(old_h, -1); + set_bf(deep_h, 0); + } else { + set_bf(deep_h, 1); + set_bf(old_h, 0); + } + set_bf(bal_h, 0); + } else { + set_bf(old_h, 0); + set_bf(deep_h, 0); + } + } else { + set_gt(bal_h, get_lt(deep_h)); + set_lt(deep_h, bal_h); + if (get_bf(deep_h) == 0) { + set_bf(deep_h, -1); + set_bf(bal_h, 1); + } else { + set_bf(deep_h, 0); + set_bf(bal_h, 0); + } + bal_h = deep_h; + } + } else { + // "Less than" subtree is deeper. + + deep_h = get_lt(bal_h); + + if (get_bf(deep_h) > 0) { + handle old_h = bal_h; + bal_h = get_gt(deep_h); + set_lt(old_h, get_gt(bal_h)); + set_gt(deep_h, get_lt(bal_h)); + set_gt(bal_h, old_h); + set_lt(bal_h, deep_h); + + int bf = get_bf(bal_h); + if (bf != 0) { + if (bf < 0) { + set_bf(old_h, 1); + set_bf(deep_h, 0); + } else { + set_bf(deep_h, -1); + set_bf(old_h, 0); + } + set_bf(bal_h, 0); + } else { + set_bf(old_h, 0); + set_bf(deep_h, 0); + } + } else { + set_lt(bal_h, get_gt(deep_h)); + set_gt(deep_h, bal_h); + if (get_bf(deep_h) == 0) { + set_bf(deep_h, 1); + set_bf(bal_h, -1); + } else { + set_bf(deep_h, 0); + set_bf(bal_h, 0); + } + bal_h = deep_h; + } + } + + return bal_h; + } + +}; + +template +inline typename AVLTree::handle +AVLTree::insert(handle h) +{ + set_lt(h, null()); + set_gt(h, null()); + set_bf(h, 0); + + if (abs.root == null()) + abs.root = h; + else { + // Last unbalanced node encountered in search for insertion point. + handle unbal = null(); + // Parent of last unbalanced node. + handle parent_unbal = null(); + // Balance factor of last unbalanced node. + int unbal_bf; + + // Zero-based depth in tree. + unsigned depth = 0, unbal_depth = 0; + + // Records a path into the tree. If branch[n] is true, indicates + // take greater branch from the nth node in the path, otherwise + // take the less branch. branch[0] gives branch from root, and + // so on. + BSet branch; + + handle hh = abs.root; + handle parent = null(); + int cmp; + + do { + if (get_bf(hh) != 0) { + unbal = hh; + parent_unbal = parent; + unbal_depth = depth; + } + cmp = cmp_n_n(h, hh); + if (cmp == 0) + // Duplicate key. + return hh; + parent = hh; + hh = cmp < 0 ? get_lt(hh) : get_gt(hh); + branch[depth++] = cmp > 0; + } while (hh != null()); + + // Add node to insert as leaf of tree. + if (cmp < 0) + set_lt(parent, h); + else + set_gt(parent, h); + + depth = unbal_depth; + + if (unbal == null()) + hh = abs.root; + else { + cmp = branch[depth++] ? 1 : -1; + unbal_bf = get_bf(unbal); + if (cmp < 0) + unbal_bf--; + else // cmp > 0 + unbal_bf++; + hh = cmp < 0 ? get_lt(unbal) : get_gt(unbal); + if ((unbal_bf != -2) && (unbal_bf != 2)) { + // No rebalancing of tree is necessary. + set_bf(unbal, unbal_bf); + unbal = null(); + } + } + + if (hh != null()) + while (h != hh) { + cmp = branch[depth++] ? 1 : -1; + if (cmp < 0) { + set_bf(hh, -1); + hh = get_lt(hh); + } else { // cmp > 0 + set_bf(hh, 1); + hh = get_gt(hh); + } + } + + if (unbal != null()) { + unbal = balance(unbal); + if (parent_unbal == null()) + abs.root = unbal; + else { + depth = unbal_depth - 1; + cmp = branch[depth] ? 1 : -1; + if (cmp < 0) + set_lt(parent_unbal, unbal); + else // cmp > 0 + set_gt(parent_unbal, unbal); + } + } + } + + return h; +} + +template +inline typename AVLTree::handle +AVLTree::search(key k, typename AVLTree::SearchType st) +{ + const int MASK_HIGH_BIT = (int) ~ ((~ (unsigned) 0) >> 1); + + int cmp, target_cmp; + handle match_h = null(); + handle h = abs.root; + + if (st & LESS) + target_cmp = 1; + else if (st & GREATER) + target_cmp = -1; + else + target_cmp = 0; + + while (h != null()) { + cmp = cmp_k_n(k, h); + if (cmp == 0) { + if (st & EQUAL) { + match_h = h; + break; + } + cmp = -target_cmp; + } else if (target_cmp != 0) + if (!((cmp ^ target_cmp) & MASK_HIGH_BIT)) + // cmp and target_cmp are both positive or both negative. + match_h = h; + h = cmp < 0 ? get_lt(h) : get_gt(h); + } + + return match_h; +} + +template +inline typename AVLTree::handle +AVLTree::search_least() +{ + handle h = abs.root, parent = null(); + + while (h != null()) { + parent = h; + h = get_lt(h); + } + + return parent; +} + +template +inline typename AVLTree::handle +AVLTree::search_greatest() +{ + handle h = abs.root, parent = null(); + + while (h != null()) { + parent = h; + h = get_gt(h); + } + + return parent; +} + +template +inline typename AVLTree::handle +AVLTree::remove(key k) +{ + // Zero-based depth in tree. + unsigned depth = 0, rm_depth; + + // Records a path into the tree. If branch[n] is true, indicates + // take greater branch from the nth node in the path, otherwise + // take the less branch. branch[0] gives branch from root, and + // so on. + BSet branch; + + handle h = abs.root; + handle parent = null(), child; + int cmp, cmp_shortened_sub_with_path = 0; + + for (;;) { + if (h == null()) + // No node in tree with given key. + return null(); + cmp = cmp_k_n(k, h); + if (cmp == 0) + // Found node to remove. + break; + parent = h; + h = cmp < 0 ? get_lt(h) : get_gt(h); + branch[depth++] = cmp > 0; + cmp_shortened_sub_with_path = cmp; + } + handle rm = h; + handle parent_rm = parent; + rm_depth = depth; + + // If the node to remove is not a leaf node, we need to get a + // leaf node, or a node with a single leaf as its child, to put + // in the place of the node to remove. We will get the greatest + // node in the less subtree (of the node to remove), or the least + // node in the greater subtree. We take the leaf node from the + // deeper subtree, if there is one. + + if (get_bf(h) < 0) { + child = get_lt(h); + branch[depth] = false; + cmp = -1; + } else { + child = get_gt(h); + branch[depth] = true; + cmp = 1; + } + depth++; + + if (child != null()) { + cmp = -cmp; + do { + parent = h; + h = child; + if (cmp < 0) { + child = get_lt(h); + branch[depth] = false; + } else { + child = get_gt(h); + branch[depth] = true; + } + depth++; + } while (child != null()); + + if (parent == rm) + // Only went through do loop once. Deleted node will be replaced + // in the tree structure by one of its immediate children. + cmp_shortened_sub_with_path = -cmp; + else + cmp_shortened_sub_with_path = cmp; + + // Get the handle of the opposite child, which may not be null. + child = cmp > 0 ? get_lt(h) : get_gt(h); + } + + if (parent == null()) + // There were only 1 or 2 nodes in this tree. + abs.root = child; + else if (cmp_shortened_sub_with_path < 0) + set_lt(parent, child); + else + set_gt(parent, child); + + // "path" is the parent of the subtree being eliminated or reduced + // from a depth of 2 to 1. If "path" is the node to be removed, we + // set path to the node we're about to poke into the position of the + // node to be removed. + handle path = parent == rm ? h : parent; + + if (h != rm) { + // Poke in the replacement for the node to be removed. + set_lt(h, get_lt(rm)); + set_gt(h, get_gt(rm)); + set_bf(h, get_bf(rm)); + if (parent_rm == null()) + abs.root = h; + else { + depth = rm_depth - 1; + if (branch[depth]) + set_gt(parent_rm, h); + else + set_lt(parent_rm, h); + } + } + + if (path != null()) { + // Create a temporary linked list from the parent of the path node + // to the root node. + h = abs.root; + parent = null(); + depth = 0; + while (h != path) { + if (branch[depth++]) { + child = get_gt(h); + set_gt(h, parent); + } else { + child = get_lt(h); + set_lt(h, parent); + } + parent = h; + h = child; + } + + // Climb from the path node to the root node using the linked + // list, restoring the tree structure and rebalancing as necessary. + bool reduced_depth = true; + int bf; + cmp = cmp_shortened_sub_with_path; + for (;;) { + if (reduced_depth) { + bf = get_bf(h); + if (cmp < 0) + bf++; + else // cmp > 0 + bf--; + if ((bf == -2) || (bf == 2)) { + h = balance(h); + bf = get_bf(h); + } else + set_bf(h, bf); + reduced_depth = (bf == 0); + } + if (parent == null()) + break; + child = h; + h = parent; + cmp = branch[--depth] ? 1 : -1; + if (cmp < 0) { + parent = get_lt(h); + set_lt(h, child); + } else { + parent = get_gt(h); + set_gt(h, child); + } + } + abs.root = h; + } + + return rm; +} + +template +inline typename AVLTree::handle +AVLTree::subst(handle new_node) +{ + handle h = abs.root; + handle parent = null(); + int cmp, last_cmp; + + /* Search for node already in tree with same key. */ + for (;;) { + if (h == null()) + /* No node in tree with same key as new node. */ + return null(); + cmp = cmp_n_n(new_node, h); + if (cmp == 0) + /* Found the node to substitute new one for. */ + break; + last_cmp = cmp; + parent = h; + h = cmp < 0 ? get_lt(h) : get_gt(h); + } + + /* Copy tree housekeeping fields from node in tree to new node. */ + set_lt(new_node, get_lt(h)); + set_gt(new_node, get_gt(h)); + set_bf(new_node, get_bf(h)); + + if (parent == null()) + /* New node is also new root. */ + abs.root = new_node; + else { + /* Make parent point to new node. */ + if (last_cmp < 0) + set_lt(parent, new_node); + else + set_gt(parent, new_node); + } + + return h; +} + +} + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Alignment.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Alignment.h new file mode 100644 index 000000000..9b443efc6 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Alignment.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WTF_Alignment_h +#define WTF_Alignment_h + +#include "Platform.h" +#include + +namespace WTF { + +#if COMPILER(GCC) || COMPILER(MINGW) || COMPILER(RVCT) || COMPILER(GCCE) || (COMPILER(SUNCC) && __SUNPRO_CC > 0x590) + #define WTF_ALIGN_OF(type) __alignof__(type) + #define WTF_ALIGNED(variable_type, variable, n) variable_type variable __attribute__((__aligned__(n))) +#elif COMPILER(MSVC) + #define WTF_ALIGN_OF(type) __alignof(type) + #define WTF_ALIGNED(variable_type, variable, n) __declspec(align(n)) variable_type variable +#else + #error WTF_ALIGN macros need alignment control. +#endif + +#if COMPILER(GCC) && !COMPILER(INTEL) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 303) + typedef char __attribute__((__may_alias__)) AlignedBufferChar; +#else + typedef char AlignedBufferChar; +#endif + + template struct AlignedBuffer; + template struct AlignedBuffer { AlignedBufferChar buffer[size]; }; + template struct AlignedBuffer { WTF_ALIGNED(AlignedBufferChar, buffer[size], 2); }; + template struct AlignedBuffer { WTF_ALIGNED(AlignedBufferChar, buffer[size], 4); }; + template struct AlignedBuffer { WTF_ALIGNED(AlignedBufferChar, buffer[size], 8); }; + template struct AlignedBuffer { WTF_ALIGNED(AlignedBufferChar, buffer[size], 16); }; + template struct AlignedBuffer { WTF_ALIGNED(AlignedBufferChar, buffer[size], 32); }; + template struct AlignedBuffer { WTF_ALIGNED(AlignedBufferChar, buffer[size], 64); }; + + template + void swap(AlignedBuffer& a, AlignedBuffer& b) + { + for (size_t i = 0; i < size; ++i) + std::swap(a.buffer[i], b.buffer[i]); + } + +} + +#endif // WTF_Alignment_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/AllocationSpace.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/AllocationSpace.h new file mode 100644 index 000000000..45a6b5a3e --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/AllocationSpace.h @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2011 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 INC. 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 INC. 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 AllocationSpace_h +#define AllocationSpace_h + +#include "MarkedBlockSet.h" +#include "MarkedSpace.h" + +#include + +namespace JSC { + +class Heap; +class MarkedBlock; + +class AllocationSpace { +public: + AllocationSpace(Heap* heap) + : m_heap(heap) + , m_markedSpace(heap) + { + } + + typedef HashSet::iterator BlockIterator; + + MarkedBlockSet& blocks() { return m_blocks; } + MarkedSpace::SizeClass& sizeClassFor(size_t bytes) { return m_markedSpace.sizeClassFor(bytes); } + size_t waterMark() { return m_markedSpace.waterMark(); } + +#if ENABLE(GGC) + void gatherDirtyCells(MarkedBlock::DirtyCellVector&); +#endif + + template typename Functor::ReturnType forEachCell(Functor&); + template typename Functor::ReturnType forEachCell(); + template typename Functor::ReturnType forEachBlock(Functor&); + template typename Functor::ReturnType forEachBlock(); + + void canonicalizeCellLivenessData() { m_markedSpace.canonicalizeCellLivenessData(); } + void resetAllocator() { m_markedSpace.resetAllocator(); } + + void* allocate(size_t); + void freeBlocks(MarkedBlock*); + void shrink(); + +private: + enum AllocationEffort { AllocationCanFail, AllocationMustSucceed }; + + void* allocate(MarkedSpace::SizeClass&); + void* tryAllocate(MarkedSpace::SizeClass&); + JS_EXPORT_PRIVATE void* allocateSlowCase(MarkedSpace::SizeClass&); + MarkedBlock* allocateBlock(size_t cellSize, AllocationEffort); + + Heap* m_heap; + MarkedSpace m_markedSpace; + MarkedBlockSet m_blocks; +}; + +template inline typename Functor::ReturnType AllocationSpace::forEachCell(Functor& functor) +{ + canonicalizeCellLivenessData(); + + BlockIterator end = m_blocks.set().end(); + for (BlockIterator it = m_blocks.set().begin(); it != end; ++it) + (*it)->forEachCell(functor); + return functor.returnValue(); +} + +template inline typename Functor::ReturnType AllocationSpace::forEachCell() +{ + Functor functor; + return forEachCell(functor); +} + +template inline typename Functor::ReturnType AllocationSpace::forEachBlock(Functor& functor) +{ + BlockIterator end = m_blocks.set().end(); + for (BlockIterator it = m_blocks.set().begin(); it != end; ++it) + functor(*it); + return functor.returnValue(); +} + +template inline typename Functor::ReturnType AllocationSpace::forEachBlock() +{ + Functor functor; + return forEachBlock(functor); +} + +inline void* AllocationSpace::allocate(MarkedSpace::SizeClass& sizeClass) +{ + // This is a light-weight fast path to cover the most common case. + MarkedBlock::FreeCell* firstFreeCell = sizeClass.firstFreeCell; + if (UNLIKELY(!firstFreeCell)) + return allocateSlowCase(sizeClass); + + sizeClass.firstFreeCell = firstFreeCell->next; + return firstFreeCell; +} + +inline void* AllocationSpace::allocate(size_t bytes) +{ + MarkedSpace::SizeClass& sizeClass = sizeClassFor(bytes); + return allocate(sizeClass); +} + +} + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/AlwaysInline.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/AlwaysInline.h new file mode 100644 index 000000000..de12ddd90 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/AlwaysInline.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2005, 2007, 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +/* This file is no longer necessary, since all the functionality has been moved to Compiler.h. */ + +#include "Platform.h" diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ArgList.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ArgList.h new file mode 100644 index 000000000..1512a0fa1 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ArgList.h @@ -0,0 +1,183 @@ +/* + * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) + * Copyright (C) 2003, 2007, 2008, 2009 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef ArgList_h +#define ArgList_h + +#include "CallFrame.h" +#include "Register.h" +#include "WriteBarrier.h" +#include +#include + +namespace JSC { + + class SlotVisitor; + + class MarkedArgumentBuffer { + WTF_MAKE_NONCOPYABLE(MarkedArgumentBuffer); + friend class JSGlobalData; + friend class ArgList; + + private: + static const size_t inlineCapacity = 8; + typedef Vector VectorType; + typedef HashSet ListSet; + + public: + // Constructor for a read-write list, to which you may append values. + // FIXME: Remove all clients of this API, then remove this API. + MarkedArgumentBuffer() + : m_size(0) + , m_capacity(inlineCapacity) + , m_buffer(&m_inlineBuffer[m_capacity - 1]) + , m_markSet(0) + { + } + + ~MarkedArgumentBuffer() + { + if (m_markSet) + m_markSet->remove(this); + + if (EncodedJSValue* base = mallocBase()) + delete [] base; + } + + size_t size() const { return m_size; } + bool isEmpty() const { return !m_size; } + + JSValue at(int i) const + { + if (i >= m_size) + return jsUndefined(); + + return JSValue::decode(slotFor(i)); + } + + void clear() + { + m_size = 0; + } + + void append(JSValue v) + { + if (m_size >= m_capacity) + return slowAppend(v); + + slotFor(m_size) = JSValue::encode(v); + ++m_size; + } + + void removeLast() + { + ASSERT(m_size); + m_size--; + } + + JSValue last() + { + ASSERT(m_size); + return JSValue::decode(slotFor(m_size - 1)); + } + + static void markLists(HeapRootVisitor&, ListSet&); + + private: + JS_EXPORT_PRIVATE void slowAppend(JSValue); + + EncodedJSValue& slotFor(int item) const + { + return m_buffer[-item]; + } + + EncodedJSValue* mallocBase() + { + if (m_capacity == static_cast(inlineCapacity)) + return 0; + return &slotFor(m_capacity - 1); + } + + int m_size; + int m_capacity; + EncodedJSValue m_inlineBuffer[inlineCapacity]; + EncodedJSValue* m_buffer; + ListSet* m_markSet; + + private: + // Prohibits new / delete, which would break GC. + void* operator new(size_t size) + { + return fastMalloc(size); + } + void operator delete(void* p) + { + fastFree(p); + } + + void* operator new[](size_t); + void operator delete[](void*); + + void* operator new(size_t, void*); + void operator delete(void*, size_t); + }; + + class ArgList { + friend class JIT; + public: + ArgList() + : m_args(0) + , m_argCount(0) + { + } + + ArgList(ExecState* exec) + : m_args(reinterpret_cast(&exec[CallFrame::argumentOffset(0)])) + , m_argCount(exec->argumentCount()) + { + } + + ArgList(const MarkedArgumentBuffer& args) + : m_args(reinterpret_cast(args.m_buffer)) + , m_argCount(args.size()) + { + } + + JSValue at(int i) const + { + if (i >= m_argCount) + return jsUndefined(); + return m_args[-i]; + } + + bool isEmpty() const { return !m_argCount; } + size_t size() const { return m_argCount; } + + JS_EXPORT_PRIVATE void getSlice(int startIndex, ArgList& result) const; + + private: + JSValue* m_args; + int m_argCount; + }; + +} // namespace JSC + +#endif // ArgList_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ArrayBuffer.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ArrayBuffer.h new file mode 100644 index 000000000..ee95f5bc6 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ArrayBuffer.h @@ -0,0 +1,220 @@ +/* + * 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 ArrayBuffer_h +#define ArrayBuffer_h + +#include +#include +#include +#include + +namespace WTF { + +class ArrayBuffer; +class ArrayBufferView; + +class ArrayBufferContents { + WTF_MAKE_NONCOPYABLE(ArrayBufferContents); +public: + ArrayBufferContents() + : m_data(0) + , m_sizeInBytes(0) + { } + + inline ~ArrayBufferContents(); + + void* data() { return m_data; } + unsigned sizeInBytes() { return m_sizeInBytes; } + +private: + ArrayBufferContents(void* data, unsigned sizeInBytes) + : m_data(data) + , m_sizeInBytes(sizeInBytes) + { } + + friend class ArrayBuffer; + + static inline void tryAllocate(unsigned numElements, unsigned elementByteSize, ArrayBufferContents&); + void transfer(ArrayBufferContents& other) + { + ASSERT(!other.m_data); + other.m_data = m_data; + other.m_sizeInBytes = m_sizeInBytes; + m_data = 0; + m_sizeInBytes = 0; + } + + void* m_data; + unsigned m_sizeInBytes; +}; + +class ArrayBuffer : public RefCounted { +public: + static inline PassRefPtr create(unsigned numElements, unsigned elementByteSize); + static inline PassRefPtr create(ArrayBuffer*); + static inline PassRefPtr create(const void* source, unsigned byteLength); + static inline PassRefPtr create(ArrayBufferContents&); + + inline void* data(); + inline const void* data() const; + inline unsigned byteLength() const; + + inline PassRefPtr slice(int begin, int end) const; + inline PassRefPtr slice(int begin) const; + + void addView(ArrayBufferView*); + void removeView(ArrayBufferView*); + + bool transfer(ArrayBufferContents&, Vector >& neuteredViews); + bool isNeutered() { return !m_contents.m_data; } + + ~ArrayBuffer() { } + +private: + inline ArrayBuffer(ArrayBufferContents&); + inline PassRefPtr sliceImpl(unsigned begin, unsigned end) const; + inline unsigned clampIndex(int index) const; + static inline int clampValue(int x, int left, int right); + + ArrayBufferContents m_contents; + ArrayBufferView* m_firstView; +}; + +int ArrayBuffer::clampValue(int x, int left, int right) +{ + ASSERT(left <= right); + if (x < left) + x = left; + if (right < x) + x = right; + return x; +} + +PassRefPtr ArrayBuffer::create(unsigned numElements, unsigned elementByteSize) +{ + ArrayBufferContents contents; + ArrayBufferContents::tryAllocate(numElements, elementByteSize, contents); + if (!contents.m_data) + return 0; + return adoptRef(new ArrayBuffer(contents)); +} + +PassRefPtr ArrayBuffer::create(ArrayBuffer* other) +{ + return ArrayBuffer::create(other->data(), other->byteLength()); +} + +PassRefPtr ArrayBuffer::create(const void* source, unsigned byteLength) +{ + ArrayBufferContents contents; + ArrayBufferContents::tryAllocate(byteLength, 1, contents); + if (!contents.m_data) + return 0; + RefPtr buffer = adoptRef(new ArrayBuffer(contents)); + memcpy(buffer->data(), source, byteLength); + return buffer.release(); +} + +PassRefPtr ArrayBuffer::create(ArrayBufferContents& contents) +{ + return adoptRef(new ArrayBuffer(contents)); +} + +ArrayBuffer::ArrayBuffer(ArrayBufferContents& contents) + : m_firstView(0) +{ + contents.transfer(m_contents); +} + +void* ArrayBuffer::data() +{ + return m_contents.m_data; +} + +const void* ArrayBuffer::data() const +{ + return m_contents.m_data; +} + +unsigned ArrayBuffer::byteLength() const +{ + return m_contents.m_sizeInBytes; +} + +PassRefPtr ArrayBuffer::slice(int begin, int end) const +{ + return sliceImpl(clampIndex(begin), clampIndex(end)); +} + +PassRefPtr ArrayBuffer::slice(int begin) const +{ + return sliceImpl(clampIndex(begin), byteLength()); +} + +PassRefPtr ArrayBuffer::sliceImpl(unsigned begin, unsigned end) const +{ + unsigned size = begin <= end ? end - begin : 0; + return ArrayBuffer::create(static_cast(data()) + begin, size); +} + +unsigned ArrayBuffer::clampIndex(int index) const +{ + unsigned currentLength = byteLength(); + if (index < 0) + index = currentLength + index; + return clampValue(index, 0, currentLength); +} + +void ArrayBufferContents::tryAllocate(unsigned numElements, unsigned elementByteSize, ArrayBufferContents& result) +{ + // Do not allow 32-bit overflow of the total size. + // FIXME: Why not? The tryFastCalloc function already checks its arguments, + // and will fail if there is any overflow, so why should we include a + // redudant unnecessarily restrictive check here? + if (numElements) { + unsigned totalSize = numElements * elementByteSize; + if (totalSize / numElements != elementByteSize) { + result.m_data = 0; + return; + } + } + if (WTF::tryFastCalloc(numElements, elementByteSize).getValue(result.m_data)) { + result.m_sizeInBytes = numElements * elementByteSize; + return; + } + result.m_data = 0; +} + +ArrayBufferContents::~ArrayBufferContents() +{ + WTF::fastFree(m_data); +} + +} // namespace WTF + +using WTF::ArrayBuffer; + +#endif // ArrayBuffer_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ArrayBufferView.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ArrayBufferView.h new file mode 100644 index 000000000..24ce25a5e --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ArrayBufferView.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 ArrayBufferView_h +#define ArrayBufferView_h + +#include "ArrayBuffer.h" + +#include +#include +#include +#include +#include + +namespace WTF { + +class ArrayBufferView : public RefCounted { + public: + virtual bool isByteArray() const { return false; } + virtual bool isUnsignedByteArray() const { return false; } + virtual bool isUnsignedByteClampedArray() const { return false; } + virtual bool isShortArray() const { return false; } + virtual bool isUnsignedShortArray() const { return false; } + virtual bool isIntArray() const { return false; } + virtual bool isUnsignedIntArray() const { return false; } + virtual bool isFloatArray() const { return false; } + virtual bool isDoubleArray() const { return false; } + virtual bool isDataView() const { return false; } + + PassRefPtr buffer() const + { + return m_buffer; + } + + void* baseAddress() const + { + return m_baseAddress; + } + + unsigned byteOffset() const + { + return m_byteOffset; + } + + virtual unsigned byteLength() const = 0; + + WTF_EXPORT_PRIVATE virtual ~ArrayBufferView(); + + protected: + WTF_EXPORT_PRIVATE ArrayBufferView(PassRefPtr, unsigned byteOffset); + + inline bool setImpl(ArrayBufferView*, unsigned byteOffset); + + inline bool setRangeImpl(const char* data, size_t dataByteLength, unsigned byteOffset); + + inline bool zeroRangeImpl(unsigned byteOffset, size_t rangeByteLength); + + static inline void calculateOffsetAndLength(int start, int end, unsigned arraySize, + unsigned* offset, unsigned* length); + + // Helper to verify that a given sub-range of an ArrayBuffer is + // within range. + template + static bool verifySubRange(PassRefPtr buffer, + unsigned byteOffset, + unsigned numElements) + { + if (!buffer) + return false; + if (sizeof(T) > 1 && byteOffset % sizeof(T)) + return false; + if (byteOffset > buffer->byteLength()) + return false; + unsigned remainingElements = (buffer->byteLength() - byteOffset) / sizeof(T); + if (numElements > remainingElements) + return false; + return true; + } + + // Input offset is in number of elements from this array's view; + // output offset is in number of bytes from the underlying buffer's view. + template + static void clampOffsetAndNumElements(PassRefPtr buffer, + unsigned arrayByteOffset, + unsigned *offset, + unsigned *numElements) + { + unsigned maxOffset = (UINT_MAX - arrayByteOffset) / sizeof(T); + if (*offset > maxOffset) { + *offset = buffer->byteLength(); + *numElements = 0; + return; + } + *offset = arrayByteOffset + *offset * sizeof(T); + *offset = std::min(buffer->byteLength(), *offset); + unsigned remainingElements = (buffer->byteLength() - *offset) / sizeof(T); + *numElements = std::min(remainingElements, *numElements); + } + + WTF_EXPORT_PRIVATE virtual void neuter(); + + // This is the address of the ArrayBuffer's storage, plus the byte offset. + void* m_baseAddress; + + unsigned m_byteOffset; + + private: + friend class ArrayBuffer; + RefPtr m_buffer; + ArrayBufferView* m_prevView; + ArrayBufferView* m_nextView; +}; + +bool ArrayBufferView::setImpl(ArrayBufferView* array, unsigned byteOffset) +{ + if (byteOffset > byteLength() + || byteOffset + array->byteLength() > byteLength() + || byteOffset + array->byteLength() < byteOffset) { + // Out of range offset or overflow + return false; + } + + char* base = static_cast(baseAddress()); + memmove(base + byteOffset, array->baseAddress(), array->byteLength()); + return true; +} + +bool ArrayBufferView::setRangeImpl(const char* data, size_t dataByteLength, unsigned byteOffset) +{ + if (byteOffset > byteLength() + || byteOffset + dataByteLength > byteLength() + || byteOffset + dataByteLength < byteOffset) { + // Out of range offset or overflow + return false; + } + + char* base = static_cast(baseAddress()); + memmove(base + byteOffset, data, dataByteLength); + return true; +} + +bool ArrayBufferView::zeroRangeImpl(unsigned byteOffset, size_t rangeByteLength) +{ + if (byteOffset > byteLength() + || byteOffset + rangeByteLength > byteLength() + || byteOffset + rangeByteLength < byteOffset) { + // Out of range offset or overflow + return false; + } + + char* base = static_cast(baseAddress()); + memset(base + byteOffset, 0, rangeByteLength); + return true; +} + +void ArrayBufferView::calculateOffsetAndLength(int start, int end, unsigned arraySize, + unsigned* offset, unsigned* length) +{ + if (start < 0) + start += arraySize; + if (start < 0) + start = 0; + if (end < 0) + end += arraySize; + if (end < 0) + end = 0; + if (end < start) + end = start; + *offset = static_cast(start); + *length = static_cast(end - start); +} + +} // namespace WTF + +using WTF::ArrayBufferView; + +#endif // ArrayBufferView_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ArrayPrototype.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ArrayPrototype.h new file mode 100644 index 000000000..f49a9a667 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ArrayPrototype.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2007, 2011 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef ArrayPrototype_h +#define ArrayPrototype_h + +#include "JSArray.h" +#include "Lookup.h" + +namespace JSC { + + class ArrayPrototype : public JSArray { + private: + ArrayPrototype(JSGlobalObject*, Structure*); + + public: + typedef JSArray Base; + + static ArrayPrototype* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure) + { + ArrayPrototype* prototype = new (NotNull, allocateCell(*exec->heap())) ArrayPrototype(globalObject, structure); + prototype->finishCreation(globalObject); + return prototype; + } + + static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&); + static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); + + static const ClassInfo s_info; + + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + { + return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); + } + + protected: + void finishCreation(JSGlobalObject*); + }; + +} // namespace JSC + +#endif // ArrayPrototype_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Assertions.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Assertions.h new file mode 100644 index 000000000..42dc0bd35 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Assertions.h @@ -0,0 +1,398 @@ +/* + * Copyright (C) 2003, 2006, 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. + */ + +#ifndef WTF_Assertions_h +#define WTF_Assertions_h + +/* + no namespaces because this file has to be includable from C and Objective-C + + Note, this file uses many GCC extensions, but it should be compatible with + C, Objective C, C++, and Objective C++. + + For non-debug builds, everything is disabled by default. + Defining any of the symbols explicitly prevents this from having any effect. + + MSVC7 note: variadic macro support was added in MSVC8, so for now we disable + those macros in MSVC7. For more info, see the MSDN document on variadic + macros here: + + http://msdn2.microsoft.com/en-us/library/ms177415(VS.80).aspx +*/ + +#include "Platform.h" + +#include + +#if !COMPILER(MSVC) +#include +#endif + +#ifdef NDEBUG +/* Disable ASSERT* macros in release mode. */ +#define ASSERTIONS_DISABLED_DEFAULT 1 +#else +#define ASSERTIONS_DISABLED_DEFAULT 0 +#endif + +#if COMPILER(MSVC7_OR_LOWER) +#define HAVE_VARIADIC_MACRO 0 +#else +#define HAVE_VARIADIC_MACRO 1 +#endif + +#ifndef BACKTRACE_DISABLED +#define BACKTRACE_DISABLED ASSERTIONS_DISABLED_DEFAULT +#endif + +#ifndef ASSERT_DISABLED +#define ASSERT_DISABLED ASSERTIONS_DISABLED_DEFAULT +#endif + +#ifndef ASSERT_MSG_DISABLED +#if HAVE(VARIADIC_MACRO) +#define ASSERT_MSG_DISABLED ASSERTIONS_DISABLED_DEFAULT +#else +#define ASSERT_MSG_DISABLED 1 +#endif +#endif + +#ifndef ASSERT_ARG_DISABLED +#define ASSERT_ARG_DISABLED ASSERTIONS_DISABLED_DEFAULT +#endif + +#ifndef FATAL_DISABLED +#if HAVE(VARIADIC_MACRO) +#define FATAL_DISABLED ASSERTIONS_DISABLED_DEFAULT +#else +#define FATAL_DISABLED 1 +#endif +#endif + +#ifndef ERROR_DISABLED +#if HAVE(VARIADIC_MACRO) +#define ERROR_DISABLED ASSERTIONS_DISABLED_DEFAULT +#else +#define ERROR_DISABLED 1 +#endif +#endif + +#ifndef LOG_DISABLED +#if HAVE(VARIADIC_MACRO) +#define LOG_DISABLED ASSERTIONS_DISABLED_DEFAULT +#else +#define LOG_DISABLED 1 +#endif +#endif + +#if COMPILER(GCC) +#define WTF_PRETTY_FUNCTION __PRETTY_FUNCTION__ +#else +#define WTF_PRETTY_FUNCTION __FUNCTION__ +#endif + +/* WTF logging functions can process %@ in the format string to log a NSObject* but the printf format attribute + emits a warning when %@ is used in the format string. Until is resolved we can't include + the attribute when being used from Objective-C code in case it decides to use %@. */ +#if COMPILER(GCC) && !defined(__OBJC__) +#define WTF_ATTRIBUTE_PRINTF(formatStringArgument, extraArguments) __attribute__((__format__(printf, formatStringArgument, extraArguments))) +#else +#define WTF_ATTRIBUTE_PRINTF(formatStringArgument, extraArguments) +#endif + +/* These helper functions are always declared, but not necessarily always defined if the corresponding function is disabled. */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { WTFLogChannelOff, WTFLogChannelOn } WTFLogChannelState; + +typedef struct { + unsigned mask; + const char *defaultName; + WTFLogChannelState state; +} WTFLogChannel; + +WTF_EXPORT_PRIVATE void WTFReportAssertionFailure(const char* file, int line, const char* function, const char* assertion); +WTF_EXPORT_PRIVATE void WTFReportAssertionFailureWithMessage(const char* file, int line, const char* function, const char* assertion, const char* format, ...) WTF_ATTRIBUTE_PRINTF(5, 6); +WTF_EXPORT_PRIVATE void WTFReportArgumentAssertionFailure(const char* file, int line, const char* function, const char* argName, const char* assertion); +WTF_EXPORT_PRIVATE void WTFReportFatalError(const char* file, int line, const char* function, const char* format, ...) WTF_ATTRIBUTE_PRINTF(4, 5); +WTF_EXPORT_PRIVATE void WTFReportError(const char* file, int line, const char* function, const char* format, ...) WTF_ATTRIBUTE_PRINTF(4, 5); +WTF_EXPORT_PRIVATE void WTFLog(WTFLogChannel*, const char* format, ...) WTF_ATTRIBUTE_PRINTF(2, 3); +WTF_EXPORT_PRIVATE void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChannel*, const char* format, ...) WTF_ATTRIBUTE_PRINTF(5, 6); + +WTF_EXPORT_PRIVATE void WTFGetBacktrace(void** stack, int* size); +WTF_EXPORT_PRIVATE void WTFReportBacktrace(); + +typedef void (*WTFCrashHookFunction)(); +WTF_EXPORT_PRIVATE void WTFSetCrashHook(WTFCrashHookFunction); +WTF_EXPORT_PRIVATE void WTFInvokeCrashHook(); + +#ifdef __cplusplus +} +#endif + +/* CRASH() - Raises a fatal error resulting in program termination and triggering either the debugger or the crash reporter. + + Use CRASH() in response to known, unrecoverable errors like out-of-memory. + Macro is enabled in both debug and release mode. + To test for unknown errors and verify assumptions, use ASSERT instead, to avoid impacting performance in release builds. + + Signals are ignored by the crash reporter on OS X so we must do better. +*/ +#ifndef CRASH +#if COMPILER(CLANG) +#define CRASH() do { \ + WTFReportBacktrace(); \ + WTFInvokeCrashHook(); \ + *(int *)(uintptr_t)0xbbadbeef = 0; \ + __builtin_trap(); \ +} while (false) +#else +#define CRASH() do { \ + WTFReportBacktrace(); \ + WTFInvokeCrashHook(); \ + *(int *)(uintptr_t)0xbbadbeef = 0; \ + ((void(*)())0)(); /* More reliable, but doesn't say BBADBEEF */ \ +} while (false) +#endif +#endif + +#if COMPILER(CLANG) +#define NO_RETURN_DUE_TO_CRASH NO_RETURN +#else +#define NO_RETURN_DUE_TO_CRASH +#endif + + +/* BACKTRACE + + Print a backtrace to the same location as ASSERT messages. +*/ + +#if BACKTRACE_DISABLED + +#define BACKTRACE() ((void)0) + +#else + +#define BACKTRACE() do { \ + WTFReportBacktrace(); \ +} while(false) + +#endif + +/* ASSERT, ASSERT_NOT_REACHED, ASSERT_UNUSED + + These macros are compiled out of release builds. + Expressions inside them are evaluated in debug builds only. +*/ + +#if OS(WINCE) && !PLATFORM(TORCHMOBILE) +/* FIXME: We include this here only to avoid a conflict with the ASSERT macro. */ +#include +#undef min +#undef max +#undef ERROR +#endif + +#if OS(WINDOWS) +/* FIXME: Change to use something other than ASSERT to avoid this conflict with the underlying platform */ +#undef ASSERT +#endif + +#if ASSERT_DISABLED + +#define ASSERT(assertion) ((void)0) +#define ASSERT_AT(assertion, file, line, function) ((void)0) +#define ASSERT_NOT_REACHED() ((void)0) +#define NO_RETURN_DUE_TO_ASSERT + +#if COMPILER(INTEL) && !OS(WINDOWS) || COMPILER(RVCT) +template +inline void assertUnused(T& x) { (void)x; } +#define ASSERT_UNUSED(variable, assertion) (assertUnused(variable)) +#else +#define ASSERT_UNUSED(variable, assertion) ((void)variable) +#endif + +#else + +#define ASSERT(assertion) do \ + if (!(assertion)) { \ + WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion); \ + CRASH(); \ + } \ +while (0) + +#define ASSERT_AT(assertion, file, line, function) do \ + if (!(assertion)) { \ + WTFReportAssertionFailure(file, line, function, #assertion); \ + CRASH(); \ + } \ +while (0) + +#define ASSERT_NOT_REACHED() do { \ + WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, 0); \ + CRASH(); \ +} while (0) + +#define ASSERT_UNUSED(variable, assertion) ASSERT(assertion) + +#define NO_RETURN_DUE_TO_ASSERT NO_RETURN_DUE_TO_CRASH + +#endif + +/* ASSERT_WITH_MESSAGE */ + +#if COMPILER(MSVC7_OR_LOWER) +#define ASSERT_WITH_MESSAGE(assertion) ((void)0) +#elif ASSERT_MSG_DISABLED +#define ASSERT_WITH_MESSAGE(assertion, ...) ((void)0) +#else +#define ASSERT_WITH_MESSAGE(assertion, ...) do \ + if (!(assertion)) { \ + WTFReportAssertionFailureWithMessage(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion, __VA_ARGS__); \ + CRASH(); \ + } \ +while (0) +#endif + +/* ASSERT_WITH_MESSAGE_UNUSED */ + +#if COMPILER(MSVC7_OR_LOWER) +#define ASSERT_WITH_MESSAGE_UNUSED(variable, assertion) ((void)0) +#elif ASSERT_MSG_DISABLED +#if COMPILER(INTEL) && !OS(WINDOWS) || COMPILER(RVCT) +template +inline void assertWithMessageUnused(T& x) { (void)x; } +#define ASSERT_WITH_MESSAGE_UNUSED(variable, assertion, ...) (assertWithMessageUnused(variable)) +#else +#define ASSERT_WITH_MESSAGE_UNUSED(variable, assertion, ...) ((void)variable) +#endif +#else +#define ASSERT_WITH_MESSAGE_UNUSED(variable, assertion, ...) do \ + if (!(assertion)) { \ + WTFReportAssertionFailureWithMessage(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion, __VA_ARGS__); \ + CRASH(); \ + } \ +while (0) +#endif + + +/* ASSERT_ARG */ + +#if ASSERT_ARG_DISABLED + +#define ASSERT_ARG(argName, assertion) ((void)0) + +#else + +#define ASSERT_ARG(argName, assertion) do \ + if (!(assertion)) { \ + WTFReportArgumentAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #argName, #assertion); \ + CRASH(); \ + } \ +while (0) + +#endif + +/* COMPILE_ASSERT */ +#ifndef COMPILE_ASSERT +#define COMPILE_ASSERT(exp, name) typedef int dummy##name [(exp) ? 1 : -1] +#endif + +/* FATAL */ + +#if COMPILER(MSVC7_OR_LOWER) +#define FATAL() ((void)0) +#elif FATAL_DISABLED +#define FATAL(...) ((void)0) +#else +#define FATAL(...) do { \ + WTFReportFatalError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, __VA_ARGS__); \ + CRASH(); \ +} while (0) +#endif + +/* LOG_ERROR */ + +#if COMPILER(MSVC7_OR_LOWER) +#define LOG_ERROR() ((void)0) +#elif ERROR_DISABLED +#define LOG_ERROR(...) ((void)0) +#else +#define LOG_ERROR(...) WTFReportError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, __VA_ARGS__) +#endif + +/* LOG */ + +#if COMPILER(MSVC7_OR_LOWER) +#define LOG() ((void)0) +#elif LOG_DISABLED +#define LOG(channel, ...) ((void)0) +#else +#define LOG(channel, ...) WTFLog(&JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, channel), __VA_ARGS__) +#define JOIN_LOG_CHANNEL_WITH_PREFIX(prefix, channel) JOIN_LOG_CHANNEL_WITH_PREFIX_LEVEL_2(prefix, channel) +#define JOIN_LOG_CHANNEL_WITH_PREFIX_LEVEL_2(prefix, channel) prefix ## channel +#endif + +/* LOG_VERBOSE */ + +#if COMPILER(MSVC7_OR_LOWER) +#define LOG_VERBOSE(channel) ((void)0) +#elif LOG_DISABLED +#define LOG_VERBOSE(channel, ...) ((void)0) +#else +#define LOG_VERBOSE(channel, ...) WTFLogVerbose(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, &JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, channel), __VA_ARGS__) +#endif + +#if ENABLE(GC_VALIDATION) +#define ASSERT_GC_OBJECT_LOOKS_VALID(cell) do { \ + if (!(cell))\ + CRASH();\ + if (cell->unvalidatedStructure()->unvalidatedStructure() != cell->unvalidatedStructure()->unvalidatedStructure()->unvalidatedStructure())\ + CRASH();\ +} while (0) + +#define ASSERT_GC_OBJECT_INHERITS(object, classInfo) do {\ + ASSERT_GC_OBJECT_LOOKS_VALID(object); \ + if (!object->inherits(classInfo)) \ + CRASH();\ +} while (0) + +#else +#define ASSERT_GC_OBJECT_LOOKS_VALID(cell) do { (void)cell; } while (0) +#define ASSERT_GC_OBJECT_INHERITS(object, classInfo) do { (void)object; (void)classInfo; } while (0) +#endif + +#if COMPILER(CLANG) +#define ASSERT_HAS_TRIVIAL_DESTRUCTOR(klass) COMPILE_ASSERT(__has_trivial_destructor(klass), klass##_has_trivial_destructor_check) +#else +#define ASSERT_HAS_TRIVIAL_DESTRUCTOR(klass) +#endif + +#endif /* WTF_Assertions_h */ diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/AtomicString.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/AtomicString.h new file mode 100644 index 000000000..6c2606984 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/AtomicString.h @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef AtomicString_h +#define AtomicString_h + +#include "AtomicStringImpl.h" +#include "WTFString.h" + +// Define 'NO_IMPLICIT_ATOMICSTRING' before including this header, +// to disallow (expensive) implicit String-->AtomicString conversions. +#ifdef NO_IMPLICIT_ATOMICSTRING +#define ATOMICSTRING_CONVERSION explicit +#else +#define ATOMICSTRING_CONVERSION +#endif + +namespace WTF { + +struct AtomicStringHash; + +class AtomicString { +public: + WTF_EXPORT_PRIVATE static void init(); + + AtomicString() { } + AtomicString(const LChar* s) : m_string(add(s)) { } + AtomicString(const char* s) : m_string(add(s)) { } + AtomicString(const UChar* s, unsigned length) : m_string(add(s, length)) { } + AtomicString(const UChar* s, unsigned length, unsigned existingHash) : m_string(add(s, length, existingHash)) { } + AtomicString(const UChar* s) : m_string(add(s)) { } + ATOMICSTRING_CONVERSION AtomicString(StringImpl* imp) : m_string(add(imp)) { } + AtomicString(AtomicStringImpl* imp) : m_string(imp) { } + ATOMICSTRING_CONVERSION AtomicString(const String& s) : m_string(add(s.impl())) { } + AtomicString(StringImpl* baseString, unsigned start, unsigned length) : m_string(add(baseString, start, length)) { } + + // Hash table deleted values, which are only constructed and never copied or destroyed. + AtomicString(WTF::HashTableDeletedValueType) : m_string(WTF::HashTableDeletedValue) { } + bool isHashTableDeletedValue() const { return m_string.isHashTableDeletedValue(); } + + WTF_EXPORT_PRIVATE static AtomicStringImpl* find(const UChar* s, unsigned length, unsigned existingHash); + + operator const String&() const { return m_string; } + const String& string() const { return m_string; }; + + AtomicStringImpl* impl() const { return static_cast(m_string.impl()); } + + const UChar* characters() const { return m_string.characters(); } + unsigned length() const { return m_string.length(); } + + UChar operator[](unsigned int i) const { return m_string[i]; } + + bool contains(UChar c) const { return m_string.contains(c); } + bool contains(const LChar* s, bool caseSensitive = true) const + { return m_string.contains(s, caseSensitive); } + bool contains(const String& s, bool caseSensitive = true) const + { return m_string.contains(s, caseSensitive); } + + size_t find(UChar c, size_t start = 0) const { return m_string.find(c, start); } + size_t find(const LChar* s, size_t start = 0, bool caseSentitive = true) const + { return m_string.find(s, start, caseSentitive); } + size_t find(const String& s, size_t start = 0, bool caseSentitive = true) const + { return m_string.find(s, start, caseSentitive); } + + bool startsWith(const String& s, bool caseSensitive = true) const + { return m_string.startsWith(s, caseSensitive); } + bool endsWith(const String& s, bool caseSensitive = true) const + { return m_string.endsWith(s, caseSensitive); } + + WTF_EXPORT_PRIVATE AtomicString lower() const; + AtomicString upper() const { return AtomicString(impl()->upper()); } + + int toInt(bool* ok = 0) const { return m_string.toInt(ok); } + double toDouble(bool* ok = 0) const { return m_string.toDouble(ok); } + float toFloat(bool* ok = 0) const { return m_string.toFloat(ok); } + bool percentage(int& p) const { return m_string.percentage(p); } + + bool isNull() const { return m_string.isNull(); } + bool isEmpty() const { return m_string.isEmpty(); } + + static void remove(StringImpl*); + +#if USE(CF) + AtomicString(CFStringRef s) : m_string(add(String(s).impl())) { } + CFStringRef createCFString() const { return m_string.createCFString(); } +#endif +#ifdef __OBJC__ + AtomicString(NSString* s) : m_string(add(String(s).impl())) { } + operator NSString*() const { return m_string; } +#endif +#if PLATFORM(QT) + AtomicString(const QString& s) : m_string(add(String(s).impl())) { } + operator QString() const { return m_string; } +#endif + + // AtomicString::fromUTF8 will return a null string if + // the input data contains invalid UTF-8 sequences. + static AtomicString fromUTF8(const char*, size_t); + static AtomicString fromUTF8(const char*); + +#ifndef NDEBUG + void show() const; +#endif +private: + String m_string; + + WTF_EXPORT_PRIVATE static PassRefPtr add(const LChar*); + ALWAYS_INLINE static PassRefPtr add(const char* s) { return add(reinterpret_cast(s)); }; + WTF_EXPORT_PRIVATE static PassRefPtr add(const UChar*, unsigned length); + ALWAYS_INLINE static PassRefPtr add(const char* s, unsigned length) { return add(reinterpret_cast(s), length); }; + WTF_EXPORT_PRIVATE static PassRefPtr add(const UChar*, unsigned length, unsigned existingHash); + WTF_EXPORT_PRIVATE static PassRefPtr add(const UChar*); + static PassRefPtr add(StringImpl*, unsigned offset, unsigned length); + ALWAYS_INLINE static PassRefPtr add(StringImpl* r) + { + if (!r || r->isAtomic()) + return r; + return addSlowCase(r); + } + WTF_EXPORT_PRIVATE static PassRefPtr addSlowCase(StringImpl*); + WTF_EXPORT_PRIVATE static AtomicString fromUTF8Internal(const char*, const char*); +}; + +inline bool operator==(const AtomicString& a, const AtomicString& b) { return a.impl() == b.impl(); } +bool operator==(const AtomicString&, const LChar*); +inline bool operator==(const AtomicString& a, const char* b) { return WTF::equal(a.impl(), reinterpret_cast(b)); } +inline bool operator==(const AtomicString& a, const Vector& b) { return a.impl() && equal(a.impl(), b.data(), b.size()); } +inline bool operator==(const AtomicString& a, const String& b) { return equal(a.impl(), b.impl()); } +inline bool operator==(const LChar* a, const AtomicString& b) { return b == a; } +inline bool operator==(const String& a, const AtomicString& b) { return equal(a.impl(), b.impl()); } +inline bool operator==(const Vector& a, const AtomicString& b) { return b == a; } + +inline bool operator!=(const AtomicString& a, const AtomicString& b) { return a.impl() != b.impl(); } +inline bool operator!=(const AtomicString& a, const LChar* b) { return !(a == b); } +inline bool operator!=(const AtomicString& a, const char* b) { return !(a == b); } +inline bool operator!=(const AtomicString& a, const String& b) { return !equal(a.impl(), b.impl()); } +inline bool operator!=(const AtomicString& a, const Vector& b) { return !(a == b); } +inline bool operator!=(const LChar* a, const AtomicString& b) { return !(b == a); } +inline bool operator!=(const String& a, const AtomicString& b) { return !equal(a.impl(), b.impl()); } +inline bool operator!=(const Vector& a, const AtomicString& b) { return !(a == b); } + +inline bool equalIgnoringCase(const AtomicString& a, const AtomicString& b) { return equalIgnoringCase(a.impl(), b.impl()); } +inline bool equalIgnoringCase(const AtomicString& a, const LChar* b) { return equalIgnoringCase(a.impl(), b); } +inline bool equalIgnoringCase(const AtomicString& a, const char* b) { return equalIgnoringCase(a.impl(), reinterpret_cast(b)); } +inline bool equalIgnoringCase(const AtomicString& a, const String& b) { return equalIgnoringCase(a.impl(), b.impl()); } +inline bool equalIgnoringCase(const LChar* a, const AtomicString& b) { return equalIgnoringCase(a, b.impl()); } +inline bool equalIgnoringCase(const char* a, const AtomicString& b) { return equalIgnoringCase(reinterpret_cast(a), b.impl()); } +inline bool equalIgnoringCase(const String& a, const AtomicString& b) { return equalIgnoringCase(a.impl(), b.impl()); } + +// Define external global variables for the commonly used atomic strings. +// These are only usable from the main thread. +#ifndef ATOMICSTRING_HIDE_GLOBALS +extern const WTF_EXPORTDATA AtomicString nullAtom; +extern const WTF_EXPORTDATA AtomicString emptyAtom; +extern const WTF_EXPORTDATA AtomicString textAtom; +extern const WTF_EXPORTDATA AtomicString commentAtom; +extern const WTF_EXPORTDATA AtomicString starAtom; +extern const WTF_EXPORTDATA AtomicString xmlAtom; +extern const WTF_EXPORTDATA AtomicString xmlnsAtom; + +inline AtomicString AtomicString::fromUTF8(const char* characters, size_t length) +{ + if (!characters) + return nullAtom; + if (!length) + return emptyAtom; + return fromUTF8Internal(characters, characters + length); +} + +inline AtomicString AtomicString::fromUTF8(const char* characters) +{ + if (!characters) + return nullAtom; + if (!*characters) + return emptyAtom; + return fromUTF8Internal(characters, 0); +} +#endif + +// AtomicStringHash is the default hash for AtomicString +template struct DefaultHash; +template<> struct DefaultHash { + typedef AtomicStringHash Hash; +}; + +} // namespace WTF + +#ifndef ATOMICSTRING_HIDE_GLOBALS +using WTF::AtomicString; +using WTF::nullAtom; +using WTF::emptyAtom; +using WTF::textAtom; +using WTF::commentAtom; +using WTF::starAtom; +using WTF::xmlAtom; +using WTF::xmlnsAtom; +#endif + +#include "StringConcatenate.h" +#endif // AtomicString_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/AtomicStringHash.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/AtomicStringHash.h new file mode 100644 index 000000000..6130d9493 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/AtomicStringHash.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 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. + * 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 AtomicStringHash_h +#define AtomicStringHash_h + +#include +#include + +namespace WTF { + + struct AtomicStringHash { + static unsigned hash(const AtomicString& key) + { + return key.impl()->existingHash(); + } + + static bool equal(const AtomicString& a, const AtomicString& b) + { + return a == b; + } + + static const bool safeToCompareToEmptyOrDeleted = false; + }; + + // AtomicStringHash is the default hash for AtomicString + template<> struct HashTraits : GenericHashTraits { + static const bool emptyValueIsZero = true; + static void constructDeletedValue(WTF::AtomicString& slot) { new (NotNull, &slot) WTF::AtomicString(HashTableDeletedValue); } + static bool isDeletedValue(const WTF::AtomicString& slot) { return slot.isHashTableDeletedValue(); } + }; + +} + +using WTF::AtomicStringHash; + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/AtomicStringImpl.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/AtomicStringImpl.h new file mode 100644 index 000000000..3f0c37606 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/AtomicStringImpl.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef AtomicStringImpl_h +#define AtomicStringImpl_h + +#include "StringImpl.h" + +namespace WTF { + +class AtomicStringImpl : public StringImpl +{ +public: + AtomicStringImpl() : StringImpl(0) {} +}; + +} + +using WTF::AtomicStringImpl; + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Atomics.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Atomics.h new file mode 100644 index 000000000..5e10460c6 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Atomics.h @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2007, 2008, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com) + * + * 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. + * + * + * Note: The implementations of InterlockedIncrement and InterlockedDecrement are based + * on atomic_increment and atomic_exchange_and_add from the Boost C++ Library. The license + * is virtually identical to the Apple license above but is included here for completeness. + * + * Boost Software License - Version 1.0 - August 17th, 2003 + * + * Permission is hereby granted, free of charge, to any person or organization + * obtaining a copy of the software and accompanying documentation covered by + * this license (the "Software") to use, reproduce, display, distribute, + * execute, and transmit the Software, and to prepare derivative works of the + * Software, and to permit third-parties to whom the Software is furnished to + * do so, all subject to the following: + * + * The copyright notices in the Software and this entire statement, including + * the above license grant, this restriction and the following disclaimer, + * must be included in all copies of the Software, in whole or in part, and + * all derivative works of the Software, unless such copies or derivative + * works are solely in the form of machine-executable object code generated by + * a source language processor. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT + * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE + * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef Atomics_h +#define Atomics_h + +#include "Platform.h" +#include "StdLibExtras.h" +#include "UnusedParam.h" + +#if OS(WINDOWS) +#include +#elif OS(DARWIN) +#include +#elif OS(QNX) +#include +#elif OS(ANDROID) +#include +#elif COMPILER(GCC) +#if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2)) +#include +#else +#include +#endif +#endif + +namespace WTF { + +#if OS(WINDOWS) +#define WTF_USE_LOCKFREE_THREADSAFEREFCOUNTED 1 + +#if COMPILER(MINGW) || COMPILER(MSVC7_OR_LOWER) || OS(WINCE) +inline int atomicIncrement(int* addend) { return InterlockedIncrement(reinterpret_cast(addend)); } +inline int atomicDecrement(int* addend) { return InterlockedDecrement(reinterpret_cast(addend)); } +#else +inline int atomicIncrement(int volatile* addend) { return InterlockedIncrement(reinterpret_cast(addend)); } +inline int atomicDecrement(int volatile* addend) { return InterlockedDecrement(reinterpret_cast(addend)); } +#endif + +#elif OS(DARWIN) +#define WTF_USE_LOCKFREE_THREADSAFEREFCOUNTED 1 + +inline int atomicIncrement(int volatile* addend) { return OSAtomicIncrement32Barrier(const_cast(addend)); } +inline int atomicDecrement(int volatile* addend) { return OSAtomicDecrement32Barrier(const_cast(addend)); } + +#elif OS(QNX) +#define WTF_USE_LOCKFREE_THREADSAFEREFCOUNTED 1 + +// Note, atomic_{add, sub}_value() return the previous value of addend's content. +inline int atomicIncrement(int volatile* addend) { return static_cast(atomic_add_value(reinterpret_cast(addend), 1)) + 1; } +inline int atomicDecrement(int volatile* addend) { return static_cast(atomic_sub_value(reinterpret_cast(addend), 1)) - 1; } + +#elif OS(ANDROID) + +inline int atomicIncrement(int volatile* addend) { return __atomic_inc(addend); } +inline int atomicDecrement(int volatile* addend) { return __atomic_dec(addend); } + +#elif COMPILER(GCC) && !CPU(SPARC64) // sizeof(_Atomic_word) != sizeof(int) on sparc64 gcc +#define WTF_USE_LOCKFREE_THREADSAFEREFCOUNTED 1 + +inline int atomicIncrement(int volatile* addend) { return __gnu_cxx::__exchange_and_add(addend, 1) + 1; } +inline int atomicDecrement(int volatile* addend) { return __gnu_cxx::__exchange_and_add(addend, -1) - 1; } + +#endif + +inline bool weakCompareAndSwap(unsigned* location, unsigned expected, unsigned newValue) +{ +#if ENABLE(COMPARE_AND_SWAP) + bool result; +#if CPU(X86) || CPU(X86_64) + asm volatile( + "lock; cmpxchgl %3, %2\n\t" + "sete %1" + : "+a"(expected), "=q"(result), "+m"(*location) + : "r"(newValue) + : "memory" + ); +#elif CPU(ARM_THUMB2) + unsigned tmp; + asm volatile( + "movw %1, #1\n\t" + "ldrex %2, %0\n\t" + "cmp %3, %2\n\t" + "bne.n 0f\n\t" + "strex %1, %4, %0\n\t" + "0:" + : "+m"(*location), "=&r"(result), "=&r"(tmp) + : "r"(expected), "r"(newValue) + : "memory"); + result = !result; +#else +#error "Bad architecture for compare and swap." +#endif + return result; +#else + UNUSED_PARAM(location); + UNUSED_PARAM(expected); + UNUSED_PARAM(newValue); + CRASH(); + return 0; +#endif +} + +inline bool weakCompareAndSwap(void*volatile* location, void* expected, void* newValue) +{ +#if ENABLE(COMPARE_AND_SWAP) +#if CPU(X86_64) + bool result; + asm volatile( + "lock; cmpxchgq %3, %2\n\t" + "sete %1" + : "+a"(expected), "=q"(result), "+m"(*location) + : "r"(newValue) + : "memory" + ); + return result; +#else + return weakCompareAndSwap(bitwise_cast(location), bitwise_cast(expected), bitwise_cast(newValue)); +#endif +#else // ENABLE(COMPARE_AND_SWAP) + UNUSED_PARAM(location); + UNUSED_PARAM(expected); + UNUSED_PARAM(newValue); + CRASH(); + return 0; +#endif // ENABLE(COMPARE_AND_SWAP) +} + +inline bool weakCompareAndSwap(volatile uintptr_t* location, uintptr_t expected, uintptr_t newValue) +{ + return weakCompareAndSwap(reinterpret_cast(location), reinterpret_cast(expected), reinterpret_cast(newValue)); +} + +} // namespace WTF + +#if USE(LOCKFREE_THREADSAFEREFCOUNTED) +using WTF::atomicDecrement; +using WTF::atomicIncrement; +#endif + +#endif // Atomics_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/BitVector.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/BitVector.h new file mode 100644 index 000000000..109d3ffcf --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/BitVector.h @@ -0,0 +1,243 @@ +/* + * Copyright (C) 2011 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 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 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 BitVector_h +#define BitVector_h + +#include +#include + +#ifndef NDEBUG +#include +#endif + +namespace WTF { + +// This is a space-efficient, resizeable bitvector class. In the common case it +// occupies one word, but if necessary, it will inflate this one word to point +// to a single chunk of out-of-line allocated storage to store an arbitrary number +// of bits. +// +// - The bitvector remembers the bound of how many bits can be stored, but this +// may be slightly greater (by as much as some platform-specific constant) +// than the last argument passed to ensureSize(). +// +// - The bitvector can resize itself automatically (set, clear, get) or can be used +// in a manual mode, which is faster (quickSet, quickClear, quickGet, ensureSize). +// +// - Accesses ASSERT that you are within bounds. +// +// - Bits are automatically initialized to zero. +// +// On the other hand, this BitVector class may not be the fastest around, since +// it does conditionals on every get/set/clear. But it is great if you need to +// juggle a lot of variable-length BitVectors and you're worried about wasting +// space. + +class BitVector { +public: + BitVector() + : m_bitsOrPointer(makeInlineBits(0)) + { + } + + explicit BitVector(size_t numBits) + : m_bitsOrPointer(makeInlineBits(0)) + { + ensureSize(numBits); + } + + BitVector(const BitVector& other) + : m_bitsOrPointer(makeInlineBits(0)) + { + (*this) = other; + } + + + ~BitVector() + { + if (isInline()) + return; + OutOfLineBits::destroy(outOfLineBits()); + } + + BitVector& operator=(const BitVector& other) + { + if (isInline() && other.isInline()) + m_bitsOrPointer = other.m_bitsOrPointer; + else + setSlow(other); + return *this; + } + + size_t size() const + { + if (isInline()) + return maxInlineBits(); + return outOfLineBits()->numBits(); + } + + void ensureSize(size_t numBits) + { + if (numBits <= size()) + return; + resizeOutOfLine(numBits); + } + + // Like ensureSize(), but supports reducing the size of the bitvector. + void resize(size_t numBits); + + void clearAll(); + + bool quickGet(size_t bit) const + { + ASSERT(bit < size()); + return !!(bits()[bit / bitsInPointer()] & (static_cast(1) << (bit & (bitsInPointer() - 1)))); + } + + void quickSet(size_t bit) + { + ASSERT(bit < size()); + bits()[bit / bitsInPointer()] |= (static_cast(1) << (bit & (bitsInPointer() - 1))); + } + + void quickClear(size_t bit) + { + ASSERT(bit < size()); + bits()[bit / bitsInPointer()] &= ~(static_cast(1) << (bit & (bitsInPointer() - 1))); + } + + void quickSet(size_t bit, bool value) + { + if (value) + quickSet(bit); + else + quickClear(bit); + } + + bool get(size_t bit) const + { + if (bit >= size()) + return false; + return quickGet(bit); + } + + void set(size_t bit) + { + ensureSize(bit + 1); + quickSet(bit); + } + + void clear(size_t bit) + { + if (bit >= size()) + return; + quickClear(bit); + } + + void set(size_t bit, bool value) + { + if (value) + set(bit); + else + clear(bit); + } + +#ifndef NDEBUG + void dump(FILE* out); +#endif + +private: + static unsigned bitsInPointer() + { + return sizeof(void*) << 3; + } + + static unsigned maxInlineBits() + { + return bitsInPointer() - 1; + } + + static size_t byteCount(size_t bitCount) + { + return (bitCount + 7) >> 3; + } + + static uintptr_t makeInlineBits(uintptr_t bits) + { + ASSERT(!(bits & (static_cast(1) << maxInlineBits()))); + return bits | (static_cast(1) << maxInlineBits()); + } + + class OutOfLineBits { + public: + size_t numBits() const { return m_numBits; } + size_t numWords() const { return (m_numBits + bitsInPointer() - 1) / bitsInPointer(); } + uintptr_t* bits() { return bitwise_cast(this + 1); } + const uintptr_t* bits() const { return bitwise_cast(this + 1); } + + static OutOfLineBits* create(size_t numBits); + + static void destroy(OutOfLineBits*); + + private: + OutOfLineBits(size_t numBits) + : m_numBits(numBits) + { + } + + size_t m_numBits; + }; + + bool isInline() const { return m_bitsOrPointer >> maxInlineBits(); } + + const OutOfLineBits* outOfLineBits() const { return bitwise_cast(m_bitsOrPointer << 1); } + OutOfLineBits* outOfLineBits() { return bitwise_cast(m_bitsOrPointer << 1); } + + void resizeOutOfLine(size_t numBits); + void setSlow(const BitVector& other); + + uintptr_t* bits() + { + if (isInline()) + return &m_bitsOrPointer; + return outOfLineBits()->bits(); + } + + const uintptr_t* bits() const + { + if (isInline()) + return &m_bitsOrPointer; + return outOfLineBits()->bits(); + } + + uintptr_t m_bitsOrPointer; +}; + +} // namespace WTF + +using WTF::BitVector; + +#endif // BitVector_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Bitmap.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Bitmap.h new file mode 100644 index 000000000..d7e2528a3 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Bitmap.h @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ +#ifndef Bitmap_h +#define Bitmap_h + +#include "Atomics.h" +#include "FixedArray.h" +#include "StdLibExtras.h" +#include +#include + +namespace WTF { + +enum BitmapAtomicMode { + // This makes concurrentTestAndSet behave just like testAndSet. + BitmapNotAtomic, + + // This makes concurrentTestAndSet use compareAndSwap, so that it's + // atomic even when used concurrently. + BitmapAtomic +}; + +template +class Bitmap { +private: + typedef uint32_t WordType; + +public: + Bitmap(); + + bool get(size_t) const; + void set(size_t); + bool testAndSet(size_t); + bool testAndClear(size_t); + bool concurrentTestAndSet(size_t); + bool concurrentTestAndClear(size_t); + size_t nextPossiblyUnset(size_t) const; + void clear(size_t); + void clearAll(); + int64_t findRunOfZeros(size_t) const; + size_t count(size_t = 0) const; + size_t isEmpty() const; + size_t isFull() const; + +private: + static const WordType wordSize = sizeof(WordType) * 8; + static const WordType words = (size + wordSize - 1) / wordSize; + + // the literal '1' is of type signed int. We want to use an unsigned + // version of the correct size when doing the calculations because if + // WordType is larger than int, '1 << 31' will first be sign extended + // and then casted to unsigned, meaning that set(31) when WordType is + // a 64 bit unsigned int would give 0xffff8000 + static const WordType one = 1; + + FixedArray bits; +}; + +template +inline Bitmap::Bitmap() +{ + clearAll(); +} + +template +inline bool Bitmap::get(size_t n) const +{ + return !!(bits[n / wordSize] & (one << (n % wordSize))); +} + +template +inline void Bitmap::set(size_t n) +{ + bits[n / wordSize] |= (one << (n % wordSize)); +} + +template +inline bool Bitmap::testAndSet(size_t n) +{ + WordType mask = one << (n % wordSize); + size_t index = n / wordSize; + bool result = bits[index] & mask; + bits[index] |= mask; + return result; +} + +template +inline bool Bitmap::testAndClear(size_t n) +{ + WordType mask = one << (n % wordSize); + size_t index = n / wordSize; + bool result = bits[index] & mask; + bits[index] &= ~mask; + return result; +} + +template +inline bool Bitmap::concurrentTestAndSet(size_t n) +{ + if (atomicMode == BitmapNotAtomic) + return testAndSet(n); + + ASSERT(atomicMode == BitmapAtomic); + + WordType mask = one << (n % wordSize); + size_t index = n / wordSize; + WordType* wordPtr = bits.data() + index; + WordType oldValue; + do { + oldValue = *wordPtr; + if (oldValue & mask) + return true; + } while (!weakCompareAndSwap(wordPtr, oldValue, oldValue | mask)); + return false; +} + +template +inline bool Bitmap::concurrentTestAndClear(size_t n) +{ + if (atomicMode == BitmapNotAtomic) + return testAndClear(n); + + ASSERT(atomicMode == BitmapAtomic); + + WordType mask = one << (n % wordSize); + size_t index = n / wordSize; + WordType* wordPtr = bits.data() + index; + WordType oldValue; + do { + oldValue = *wordPtr; + if (!(oldValue & mask)) + return false; + } while (!weakCompareAndSwap(wordPtr, oldValue, oldValue & ~mask)); + return true; +} + +template +inline void Bitmap::clear(size_t n) +{ + bits[n / wordSize] &= ~(one << (n % wordSize)); +} + +template +inline void Bitmap::clearAll() +{ + memset(bits.data(), 0, sizeof(bits)); +} + +template +inline size_t Bitmap::nextPossiblyUnset(size_t start) const +{ + if (!~bits[start / wordSize]) + return ((start / wordSize) + 1) * wordSize; + return start + 1; +} + +template +inline int64_t Bitmap::findRunOfZeros(size_t runLength) const +{ + if (!runLength) + runLength = 1; + + for (size_t i = 0; i <= (size - runLength) ; i++) { + bool found = true; + for (size_t j = i; j <= (i + runLength - 1) ; j++) { + if (get(j)) { + found = false; + break; + } + } + if (found) + return i; + } + return -1; +} + +template +inline size_t Bitmap::count(size_t start) const +{ + size_t result = 0; + for ( ; (start % wordSize); ++start) { + if (get(start)) + ++result; + } + for (size_t i = start / wordSize; i < words; ++i) + result += WTF::bitCount(bits[i]); + return result; +} + +template +inline size_t Bitmap::isEmpty() const +{ + for (size_t i = 0; i < words; ++i) + if (bits[i]) + return false; + return true; +} + +template +inline size_t Bitmap::isFull() const +{ + for (size_t i = 0; i < words; ++i) + if (~bits[i]) + return false; + return true; +} + +} +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/BlockStack.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/BlockStack.h new file mode 100644 index 000000000..61e108db3 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/BlockStack.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2011 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 INC. 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 INC. 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 BlockStack_h +#define BlockStack_h + +#include +#include +#include + +namespace WTF { + +template class BlockStack { +public: + static const size_t blockSize = 4096; + static const size_t blockLength = blockSize / sizeof(T); + + BlockStack(); + ~BlockStack(); + + T* grow(); + void shrink(T*); + + const Vector& blocks(); + +private: + Vector m_blocks; + T* m_spareBlock; // Used to avoid thrash at block boundaries. +}; + +template BlockStack::BlockStack() + : m_spareBlock(0) +{ +} + +template BlockStack::~BlockStack() +{ + if (m_spareBlock) + fastFree(m_spareBlock); + for (size_t i = 0; i < m_blocks.size(); ++i) + fastFree(m_blocks[i]); +} + +template inline const Vector& BlockStack::blocks() +{ + return m_blocks; +} + +template T* BlockStack::grow() +{ + T* block = m_spareBlock ? m_spareBlock : static_cast(fastMalloc(blockSize)); + m_spareBlock = 0; + + m_blocks.append(block); + return block; +} + +template void BlockStack::shrink(T* newEnd) +{ + ASSERT(newEnd != m_blocks.last() + blockLength); + m_spareBlock = m_blocks.last(); + m_blocks.removeLast(); + + while (m_blocks.last() + blockLength != newEnd) { + fastFree(m_blocks.last()); + m_blocks.removeLast(); + } +} + +} + +using WTF::BlockStack; + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/BloomFilter.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/BloomFilter.h new file mode 100644 index 000000000..f81d83e21 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/BloomFilter.h @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2011 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 INC. 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 INC. 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 BloomFilter_h +#define BloomFilter_h + +#include +#include + +namespace WTF { + +// Counting bloom filter with k=2 and 8 bit counters. Uses 2^keyBits bytes of memory. +// False positive rate is approximately (1-e^(-2n/m))^2, where n is the number of unique +// keys and m is the table size (==2^keyBits). +template +class BloomFilter { +public: + COMPILE_ASSERT(keyBits <= 16, bloom_filter_key_size); + + static const size_t tableSize = 1 << keyBits; + static const unsigned keyMask = (1 << keyBits) - 1; + static uint8_t maximumCount() { return std::numeric_limits::max(); } + + BloomFilter() { clear(); } + + void add(unsigned hash); + void remove(unsigned hash); + + // The filter may give false positives (claim it may contain a key it doesn't) + // but never false negatives (claim it doesn't contain a key it does). + bool mayContain(unsigned hash) const { return firstSlot(hash) && secondSlot(hash); } + + // The filter must be cleared before reuse even if all keys are removed. + // Otherwise overflowed keys will stick around. + void clear(); + + void add(const AtomicString& string) { add(string.impl()->existingHash()); } + void add(const String& string) { add(string.impl()->hash()); } + void remove(const AtomicString& string) { remove(string.impl()->existingHash()); } + void remove(const String& string) { remove(string.impl()->hash()); } + + bool mayContain(const AtomicString& string) const { return mayContain(string.impl()->existingHash()); } + bool mayContain(const String& string) const { return mayContain(string.impl()->hash()); } + +#if !ASSERT_DISABLED + // Slow. + bool likelyEmpty() const; + bool isClear() const; +#endif + +private: + uint8_t& firstSlot(unsigned hash) { return m_table[hash & keyMask]; } + uint8_t& secondSlot(unsigned hash) { return m_table[(hash >> 16) & keyMask]; } + const uint8_t& firstSlot(unsigned hash) const { return m_table[hash & keyMask]; } + const uint8_t& secondSlot(unsigned hash) const { return m_table[(hash >> 16) & keyMask]; } + + uint8_t m_table[tableSize]; +}; + +template +inline void BloomFilter::add(unsigned hash) +{ + uint8_t& first = firstSlot(hash); + uint8_t& second = secondSlot(hash); + if (LIKELY(first < maximumCount())) + ++first; + if (LIKELY(second < maximumCount())) + ++second; +} + +template +inline void BloomFilter::remove(unsigned hash) +{ + uint8_t& first = firstSlot(hash); + uint8_t& second = secondSlot(hash); + ASSERT(first); + ASSERT(second); + // In case of an overflow, the slot sticks in the table until clear(). + if (LIKELY(first < maximumCount())) + --first; + if (LIKELY(second < maximumCount())) + --second; +} + +template +inline void BloomFilter::clear() +{ + memset(m_table, 0, tableSize); +} + +#if !ASSERT_DISABLED +template +bool BloomFilter::likelyEmpty() const +{ + for (size_t n = 0; n < tableSize; ++n) { + if (m_table[n] && m_table[n] != maximumCount()) + return false; + } + return true; +} + +template +bool BloomFilter::isClear() const +{ + for (size_t n = 0; n < tableSize; ++n) { + if (m_table[n]) + return false; + } + return true; +} +#endif + +} + +using WTF::BloomFilter; + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/BooleanObject.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/BooleanObject.h new file mode 100644 index 000000000..2704ff3cd --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/BooleanObject.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef BooleanObject_h +#define BooleanObject_h + +#include "JSWrapperObject.h" + +namespace JSC { + + class BooleanObject : public JSWrapperObject { + protected: + BooleanObject(JSGlobalData&, Structure*); + void finishCreation(JSGlobalData&); + + public: + typedef JSWrapperObject Base; + + static BooleanObject* create(JSGlobalData& globalData, Structure* structure) + { + BooleanObject* boolean = new (NotNull, allocateCell(globalData.heap)) BooleanObject(globalData, structure); + boolean->finishCreation(globalData); + return boolean; + } + + static const ClassInfo s_info; + + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + { + return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); + } + }; + + BooleanObject* asBooleanObject(JSValue); + + inline BooleanObject* asBooleanObject(JSValue value) + { + ASSERT(asObject(value)->inherits(&BooleanObject::s_info)); + return static_cast(asObject(value)); + } + +} // namespace JSC + +#endif // BooleanObject_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/BoundsCheckedPointer.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/BoundsCheckedPointer.h new file mode 100644 index 000000000..d5d42fc1c --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/BoundsCheckedPointer.h @@ -0,0 +1,287 @@ +/* + * Copyright (C) 2011 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 WTF_BoundsCheckedPointer_h +#define WTF_BoundsCheckedPointer_h + +#include "Assertions.h" +#include "UnusedParam.h" + +namespace WTF { + +// Useful for when you'd like to do pointer arithmetic on a buffer, but +// you'd also like to get some ASSERT()'s that prevent you from overflowing. +// This should be performance-neutral in release builds, while providing +// you with strong assertions in debug builds. Note that all of the +// asserting happens when you actually access the pointer. You are allowed +// to overflow or underflow with arithmetic so long as no accesses are +// performed. + +template +class BoundsCheckedPointer { +public: + BoundsCheckedPointer() + : m_pointer(0) +#if !ASSERT_DISABLED + , m_begin(0) + , m_end(0) +#endif + { + } + + BoundsCheckedPointer(T* pointer, size_t numElements) + : m_pointer(pointer) +#if !ASSERT_DISABLED + , m_begin(pointer) + , m_end(pointer + numElements) +#endif + { + UNUSED_PARAM(numElements); + } + + BoundsCheckedPointer(T* pointer, T* end) + : m_pointer(pointer) +#if !ASSERT_DISABLED + , m_begin(pointer) + , m_end(end) +#endif + { + UNUSED_PARAM(end); + } + + BoundsCheckedPointer(T* pointer, T* begin, size_t numElements) + : m_pointer(pointer) +#if !ASSERT_DISABLED + , m_begin(begin) + , m_end(begin + numElements) +#endif + { + UNUSED_PARAM(begin); + UNUSED_PARAM(numElements); + } + + BoundsCheckedPointer(T* pointer, T* begin, T* end) + : m_pointer(pointer) +#if !ASSERT_DISABLED + , m_begin(begin) + , m_end(end) +#endif + { + UNUSED_PARAM(begin); + UNUSED_PARAM(end); + } + + BoundsCheckedPointer& operator=(T* value) + { + m_pointer = value; + return *this; + } + + BoundsCheckedPointer& operator+=(ptrdiff_t amount) + { + m_pointer += amount; + return *this; + } + + BoundsCheckedPointer& operator-=(ptrdiff_t amount) + { + m_pointer -= amount; + return *this; + } + + BoundsCheckedPointer operator+(ptrdiff_t amount) const + { + BoundsCheckedPointer result = *this; + result.m_pointer += amount; + return result; + } + + BoundsCheckedPointer operator-(ptrdiff_t amount) const + { + BoundsCheckedPointer result = *this; + result.m_pointer -= amount; + return result; + } + + BoundsCheckedPointer operator++() // prefix + { + m_pointer++; + return *this; + } + + BoundsCheckedPointer operator--() // prefix + { + m_pointer--; + return *this; + } + + BoundsCheckedPointer operator++(int) // postfix + { + BoundsCheckedPointer result = *this; + m_pointer++; + return result; + } + + BoundsCheckedPointer operator--(int) // postfix + { + BoundsCheckedPointer result = *this; + m_pointer--; + return result; + } + + bool operator<(T* other) const + { + return m_pointer < other; + } + + bool operator<=(T* other) const + { + return m_pointer <= other; + } + + bool operator>(T* other) const + { + return m_pointer > other; + } + + bool operator>=(T* other) const + { + return m_pointer >= other; + } + + bool operator==(T* other) const + { + return m_pointer == other; + } + + bool operator!=(T* other) const + { + return m_pointer != other; + } + + bool operator<(BoundsCheckedPointer other) const + { + return m_pointer < other.m_pointer; + } + + bool operator<=(BoundsCheckedPointer other) const + { + return m_pointer <= other.m_pointer; + } + + bool operator>(BoundsCheckedPointer other) const + { + return m_pointer > other.m_pointer; + } + + bool operator>=(BoundsCheckedPointer other) const + { + return m_pointer >= other.m_pointer; + } + + bool operator==(BoundsCheckedPointer other) const + { + return m_pointer == other.m_pointer; + } + + bool operator!=(BoundsCheckedPointer other) const + { + return m_pointer != other.m_pointer; + } + + BoundsCheckedPointer operator!() + { + return !m_pointer; + } + + T* get() + { + return m_pointer; + } + + T& operator*() + { + validate(); + return *m_pointer; + } + + const T& operator*() const + { + validate(); + return *m_pointer; + } + + T& operator[](ptrdiff_t index) + { + validate(m_pointer + index); + return m_pointer[index]; + } + + const T& operator[](ptrdiff_t index) const + { + validate(m_pointer + index); + return m_pointer[index]; + } + + // The only thing this has in common with strcat() is that it + // keeps appending from the given pointer until reaching 0. + BoundsCheckedPointer& strcat(const T* source) + { + while (*source) + *(*this)++ = *source++; + return *this; + } + +private: + void validate(T* pointer) const + { + ASSERT_UNUSED(pointer, pointer >= m_begin); + + // This guard is designed to protect against the misaligned case. + // A simple pointer < m_end would miss the case if, for example, + // T = int16_t and pointer is 1 byte less than m_end. + ASSERT_UNUSED(pointer, pointer + 1 <= m_end); + } + + void validate() const + { + validate(m_pointer); + } + + T* m_pointer; +#if !ASSERT_DISABLED + T* m_begin; + T* m_end; +#endif +}; + +} // namespace WTF + +using WTF::BoundsCheckedPointer; + +#endif // WTF_BoundsCheckedPointer_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/BumpBlock.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/BumpBlock.h new file mode 100644 index 000000000..b9f271ca8 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/BumpBlock.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2011 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 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 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 BumpBlock_h +#define BumpBlock_h + +#include "HeapBlock.h" + +namespace JSC { + +class BumpSpace; + +class BumpBlock : public HeapBlock { + friend class BumpSpace; +public: + BumpBlock(PageAllocationAligned& allocation) + : HeapBlock(allocation) + , m_offset(m_payload) + , m_isPinned(false) + { + } + +private: + void* m_offset; + uintptr_t m_isPinned; + char m_payload[1]; +}; + +} // namespace JSC + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/BumpPointerAllocator.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/BumpPointerAllocator.h new file mode 100644 index 000000000..12911a4b0 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/BumpPointerAllocator.h @@ -0,0 +1,250 @@ +/* + * Copyright (C) 2010 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 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 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 BumpPointerAllocator_h +#define BumpPointerAllocator_h + +#include + +namespace WTF { + +#define MINIMUM_BUMP_POOL_SIZE 0x1000 + +class BumpPointerPool { +public: + // ensureCapacity will check whether the current pool has capacity to + // allocate 'size' bytes of memory If it does not, it will attempt to + // allocate a new pool (which will be added to this one in a chain). + // + // If allocation fails (out of memory) this method will return null. + // If the return value is non-null, then callers should update any + // references they have to this current (possibly full) BumpPointerPool + // to instead point to the newly returned BumpPointerPool. + BumpPointerPool* ensureCapacity(size_t size) + { + void* allocationEnd = static_cast(m_current) + size; + ASSERT(allocationEnd > m_current); // check for overflow + if (allocationEnd <= static_cast(this)) + return this; + return ensureCapacityCrossPool(this, size); + } + + // alloc should only be called after calling ensureCapacity; as such + // alloc will never fail. + void* alloc(size_t size) + { + void* current = m_current; + void* allocationEnd = static_cast(current) + size; + ASSERT(allocationEnd > current); // check for overflow + ASSERT(allocationEnd <= static_cast(this)); + m_current = allocationEnd; + return current; + } + + // The dealloc method releases memory allocated using alloc. Memory + // must be released in a LIFO fashion, e.g. if the client calls alloc + // four times, returning pointer A, B, C, D, then the only valid order + // in which these may be deallocaed is D, C, B, A. + // + // The client may optionally skip some deallocations. In the example + // above, it would be valid to only explicitly dealloc C, A (D being + // dealloced along with C, B along with A). + // + // If pointer was not allocated from this pool (or pools) then dealloc + // will CRASH(). Callers should update any references they have to + // this current BumpPointerPool to instead point to the returned + // BumpPointerPool. + BumpPointerPool* dealloc(void* position) + { + if ((position >= m_start) && (position <= static_cast(this))) { + ASSERT(position <= m_current); + m_current = position; + return this; + } + return deallocCrossPool(this, position); + } + +private: + // Placement operator new, returns the last 'size' bytes of allocation for use as this. + void* operator new(size_t size, const PageAllocation& allocation) + { + ASSERT(size < allocation.size()); + return reinterpret_cast(reinterpret_cast(allocation.base()) + allocation.size()) - size; + } + + BumpPointerPool(const PageAllocation& allocation) + : m_current(allocation.base()) + , m_start(allocation.base()) + , m_next(0) + , m_previous(0) + , m_allocation(allocation) + { + } + + static BumpPointerPool* create(size_t minimumCapacity = 0) + { + // Add size of BumpPointerPool object, check for overflow. + minimumCapacity += sizeof(BumpPointerPool); + if (minimumCapacity < sizeof(BumpPointerPool)) + return 0; + + size_t poolSize = MINIMUM_BUMP_POOL_SIZE; + while (poolSize < minimumCapacity) { + poolSize <<= 1; + // The following if check relies on MINIMUM_BUMP_POOL_SIZE being a power of 2! + ASSERT(!(MINIMUM_BUMP_POOL_SIZE & (MINIMUM_BUMP_POOL_SIZE - 1))); + if (!poolSize) + return 0; + } + + PageAllocation allocation = PageAllocation::allocate(poolSize); + if (!!allocation) + return new (allocation) BumpPointerPool(allocation); + return 0; + } + + void shrink() + { + ASSERT(!m_previous); + m_current = m_start; + while (m_next) { + BumpPointerPool* nextNext = m_next->m_next; + m_next->destroy(); + m_next = nextNext; + } + } + + void destroy() + { + m_allocation.deallocate(); + } + + static BumpPointerPool* ensureCapacityCrossPool(BumpPointerPool* previousPool, size_t size) + { + // The pool passed should not have capacity, so we'll start with the next one. + ASSERT(previousPool); + ASSERT((static_cast(previousPool->m_current) + size) > previousPool->m_current); // check for overflow + ASSERT((static_cast(previousPool->m_current) + size) > static_cast(previousPool)); + BumpPointerPool* pool = previousPool->m_next; + + while (true) { + if (!pool) { + // We've run to the end; allocate a new pool. + pool = BumpPointerPool::create(size); + previousPool->m_next = pool; + pool->m_previous = previousPool; + return pool; + } + + // + void* current = pool->m_current; + void* allocationEnd = static_cast(current) + size; + ASSERT(allocationEnd > current); // check for overflow + if (allocationEnd <= static_cast(pool)) + return pool; + } + } + + static BumpPointerPool* deallocCrossPool(BumpPointerPool* pool, void* position) + { + // Should only be called if position is not in the current pool. + ASSERT((position < pool->m_start) || (position > static_cast(pool))); + + while (true) { + // Unwind the current pool to the start, move back in the chain to the previous pool. + pool->m_current = pool->m_start; + pool = pool->m_previous; + + // position was nowhere in the chain! + if (!pool) + CRASH(); + + if ((position >= pool->m_start) && (position <= static_cast(pool))) { + ASSERT(position <= pool->m_current); + pool->m_current = position; + return pool; + } + } + } + + void* m_current; + void* m_start; + BumpPointerPool* m_next; + BumpPointerPool* m_previous; + PageAllocation m_allocation; + + friend class BumpPointerAllocator; +}; + +// A BumpPointerAllocator manages a set of BumpPointerPool objects, which +// can be used for LIFO (stack like) allocation. +// +// To begin allocating using this class call startAllocator(). The result +// of this method will be null if the initial pool allocation fails, or a +// pointer to a BumpPointerPool object that can be used to perform +// allocations. Whilst running no memory will be released until +// stopAllocator() is called. At this point all allocations made through +// this allocator will be reaped, and underlying memory may be freed. +// +// (In practice we will still hold on to the initial pool to allow allocation +// to be quickly restared, but aditional pools will be freed). +// +// This allocator is non-renetrant, it is encumbant on the clients to ensure +// startAllocator() is not called again until stopAllocator() has been called. +class BumpPointerAllocator { +public: + BumpPointerAllocator() + : m_head(0) + { + } + + ~BumpPointerAllocator() + { + if (m_head) + m_head->destroy(); + } + + BumpPointerPool* startAllocator() + { + if (!m_head) + m_head = BumpPointerPool::create(); + return m_head; + } + + void stopAllocator() + { + if (m_head) + m_head->shrink(); + } + +private: + BumpPointerPool* m_head; +}; + +} + +using WTF::BumpPointerAllocator; + +#endif // BumpPointerAllocator_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/BumpSpace.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/BumpSpace.h new file mode 100644 index 000000000..1ffcb4680 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/BumpSpace.h @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2011 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 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 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 BumpSpace_h +#define BumpSpace_h + +#include "TinyBloomFilter.h" +#include +#include +#include +#include +#include +#include +#include +#include + +namespace JSC { + +class Heap; +class BumpBlock; +class HeapBlock; + +class BumpSpace { + friend class SlotVisitor; +public: + BumpSpace(Heap*); + void init(); + + CheckedBoolean tryAllocate(size_t, void**); + CheckedBoolean tryReallocate(void**, size_t, size_t); + + void startedCopying(); + void doneCopying(); + bool isInCopyPhase() { return m_inCopyingPhase; } + + void pin(BumpBlock*); + bool isPinned(void*); + + bool contains(void*, BumpBlock*&); + + size_t totalMemoryAllocated() { return m_totalMemoryAllocated; } + size_t totalMemoryUtilized() { return m_totalMemoryUtilized; } + + static BumpBlock* blockFor(void*); + +private: + enum AllocationEffort { AllocationCanFail, AllocationMustSucceed }; + + CheckedBoolean tryAllocateSlowCase(size_t, void**); + CheckedBoolean addNewBlock(); + CheckedBoolean allocateNewBlock(BumpBlock**); + bool fitsInCurrentBlock(size_t); + + static void* allocateFromBlock(BumpBlock*, size_t); + CheckedBoolean tryAllocateOversize(size_t, void**); + CheckedBoolean tryReallocateOversize(void**, size_t, size_t); + + static bool isOversize(size_t); + + CheckedBoolean borrowBlock(BumpBlock**); + CheckedBoolean getFreshBlock(AllocationEffort, BumpBlock**); + void doneFillingBlock(BumpBlock*); + void recycleBlock(BumpBlock*); + static bool fitsInBlock(BumpBlock*, size_t); + static BumpBlock* oversizeBlockFor(void* ptr); + + Heap* m_heap; + + BumpBlock* m_currentBlock; + + TinyBloomFilter m_toSpaceFilter; + TinyBloomFilter m_oversizeFilter; + HashSet m_toSpaceSet; + + Mutex m_toSpaceLock; + Mutex m_memoryStatsLock; + + DoublyLinkedList* m_toSpace; + DoublyLinkedList* m_fromSpace; + + DoublyLinkedList m_blocks1; + DoublyLinkedList m_blocks2; + DoublyLinkedList m_oversizeBlocks; + + size_t m_totalMemoryAllocated; + size_t m_totalMemoryUtilized; + + bool m_inCopyingPhase; + + Mutex m_loanedBlocksLock; + ThreadCondition m_loanedBlocksCondition; + size_t m_numberOfLoanedBlocks; + + static const size_t s_blockSize = 64 * KB; + static const size_t s_maxAllocationSize = 32 * KB; + static const size_t s_pageSize = 4 * KB; + static const size_t s_pageMask = ~(s_pageSize - 1); + static const size_t s_initialBlockNum = 16; + static const size_t s_blockMask = ~(s_blockSize - 1); +}; + +} // namespace JSC + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/BumpSpaceInlineMethods.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/BumpSpaceInlineMethods.h new file mode 100644 index 000000000..3454631b0 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/BumpSpaceInlineMethods.h @@ -0,0 +1,400 @@ +/* + * Copyright (C) 2011 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 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 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 BumpSpaceInlineMethods_h +#define BumpSpaceInlineMethods_h + +#include "BumpBlock.h" +#include "BumpSpace.h" +#include "Heap.h" +#include "HeapBlock.h" +#include "JSGlobalData.h" +#include + +namespace JSC { + +inline BumpSpace::BumpSpace(Heap* heap) + : m_heap(heap) + , m_currentBlock(0) + , m_toSpace(0) + , m_fromSpace(0) + , m_totalMemoryAllocated(0) + , m_totalMemoryUtilized(0) + , m_inCopyingPhase(false) + , m_numberOfLoanedBlocks(0) +{ +} + +inline void BumpSpace::init() +{ + m_toSpace = &m_blocks1; + m_fromSpace = &m_blocks2; + + m_totalMemoryAllocated += s_blockSize * s_initialBlockNum; + + if (!addNewBlock()) + CRASH(); +} + +inline bool BumpSpace::contains(void* ptr, BumpBlock*& result) +{ + BumpBlock* block = blockFor(ptr); + result = block; + return !m_toSpaceFilter.ruleOut(reinterpret_cast(block)) && m_toSpaceSet.contains(block); +} + +inline void BumpSpace::pin(BumpBlock* block) +{ + block->m_isPinned = true; +} + +inline void BumpSpace::startedCopying() +{ + DoublyLinkedList* temp = m_fromSpace; + m_fromSpace = m_toSpace; + m_toSpace = temp; + + m_toSpaceFilter.reset(); + + m_totalMemoryUtilized = 0; + + ASSERT(!m_inCopyingPhase); + ASSERT(!m_numberOfLoanedBlocks); + m_inCopyingPhase = true; +} + +inline void BumpSpace::doneCopying() +{ + { + MutexLocker locker(m_loanedBlocksLock); + while (m_numberOfLoanedBlocks > 0) + m_loanedBlocksCondition.wait(m_loanedBlocksLock); + } + + ASSERT(m_inCopyingPhase); + m_inCopyingPhase = false; + while (!m_fromSpace->isEmpty()) { + BumpBlock* block = static_cast(m_fromSpace->removeHead()); + if (block->m_isPinned) { + block->m_isPinned = false; + m_toSpace->push(block); + continue; + } + + m_toSpaceSet.remove(block); + { + MutexLocker locker(m_heap->m_freeBlockLock); + m_heap->m_freeBlocks.push(block); + m_heap->m_numberOfFreeBlocks++; + } + } + + BumpBlock* curr = static_cast(m_oversizeBlocks.head()); + while (curr) { + BumpBlock* next = static_cast(curr->next()); + if (!curr->m_isPinned) { + m_oversizeBlocks.remove(curr); + m_totalMemoryAllocated -= curr->m_allocation.size(); + m_totalMemoryUtilized -= curr->m_allocation.size() - sizeof(BumpBlock); + curr->m_allocation.deallocate(); + } else + curr->m_isPinned = false; + curr = next; + } + + if (!(m_currentBlock = static_cast(m_toSpace->head()))) + if (!addNewBlock()) + CRASH(); +} + +inline void BumpSpace::doneFillingBlock(BumpBlock* block) +{ + ASSERT(block); + ASSERT(block->m_offset < reinterpret_cast(block) + s_blockSize); + ASSERT(m_inCopyingPhase); + + if (block->m_offset == block->m_payload) { + recycleBlock(block); + return; + } + + { + MutexLocker locker(m_toSpaceLock); + m_toSpace->push(block); + m_toSpaceSet.add(block); + m_toSpaceFilter.add(reinterpret_cast(block)); + } + + { + MutexLocker locker(m_memoryStatsLock); + m_totalMemoryUtilized += static_cast(static_cast(block->m_offset) - block->m_payload); + } + + { + MutexLocker locker(m_loanedBlocksLock); + ASSERT(m_numberOfLoanedBlocks > 0); + m_numberOfLoanedBlocks--; + if (!m_numberOfLoanedBlocks) + m_loanedBlocksCondition.signal(); + } +} + +inline void BumpSpace::recycleBlock(BumpBlock* block) +{ + { + MutexLocker locker(m_heap->m_freeBlockLock); + m_heap->m_freeBlocks.push(block); + m_heap->m_numberOfFreeBlocks++; + } + + { + MutexLocker locker(m_loanedBlocksLock); + ASSERT(m_numberOfLoanedBlocks > 0); + m_numberOfLoanedBlocks--; + if (!m_numberOfLoanedBlocks) + m_loanedBlocksCondition.signal(); + } +} + +inline CheckedBoolean BumpSpace::getFreshBlock(AllocationEffort allocationEffort, BumpBlock** outBlock) +{ + HeapBlock* heapBlock = 0; + BumpBlock* block = 0; + { + MutexLocker locker(m_heap->m_freeBlockLock); + if (!m_heap->m_freeBlocks.isEmpty()) { + heapBlock = m_heap->m_freeBlocks.removeHead(); + m_heap->m_numberOfFreeBlocks--; + } + } + if (heapBlock) + block = new (NotNull, heapBlock) BumpBlock(heapBlock->m_allocation); + else if (allocationEffort == AllocationMustSucceed) { + if (!allocateNewBlock(&block)) { + *outBlock = 0; + ASSERT_NOT_REACHED(); + return false; + } + } else { + ASSERT(allocationEffort == AllocationCanFail); + if (m_heap->waterMark() >= m_heap->highWaterMark() && m_heap->m_isSafeToCollect) + m_heap->collect(Heap::DoNotSweep); + + if (!getFreshBlock(AllocationMustSucceed, &block)) { + *outBlock = 0; + ASSERT_NOT_REACHED(); + return false; + } + } + ASSERT(block); + ASSERT(isPointerAligned(block->m_offset)); + *outBlock = block; + return true; +} + +inline CheckedBoolean BumpSpace::borrowBlock(BumpBlock** outBlock) +{ + BumpBlock* block = 0; + if (!getFreshBlock(AllocationMustSucceed, &block)) { + *outBlock = 0; + return false; + } + + ASSERT(m_inCopyingPhase); + MutexLocker locker(m_loanedBlocksLock); + m_numberOfLoanedBlocks++; + + ASSERT(block->m_offset == block->m_payload); + *outBlock = block; + return true; +} + +inline CheckedBoolean BumpSpace::addNewBlock() +{ + BumpBlock* block = 0; + if (!getFreshBlock(AllocationCanFail, &block)) + return false; + + m_toSpace->push(block); + m_currentBlock = block; + return true; +} + +inline CheckedBoolean BumpSpace::allocateNewBlock(BumpBlock** outBlock) +{ + PageAllocationAligned allocation = PageAllocationAligned::allocate(s_blockSize, s_blockSize, OSAllocator::JSGCHeapPages); + if (!static_cast(allocation)) { + *outBlock = 0; + return false; + } + + { + MutexLocker locker(m_memoryStatsLock); + m_totalMemoryAllocated += s_blockSize; + } + + *outBlock = new (NotNull, allocation.base()) BumpBlock(allocation); + return true; +} + +inline bool BumpSpace::fitsInBlock(BumpBlock* block, size_t bytes) +{ + return static_cast(block->m_offset) + bytes < reinterpret_cast(block) + s_blockSize && static_cast(block->m_offset) + bytes > block->m_offset; +} + +inline bool BumpSpace::fitsInCurrentBlock(size_t bytes) +{ + return fitsInBlock(m_currentBlock, bytes); +} + +inline CheckedBoolean BumpSpace::tryAllocate(size_t bytes, void** outPtr) +{ + ASSERT(!m_heap->globalData()->isInitializingObject()); + + if (isOversize(bytes) || !fitsInCurrentBlock(bytes)) + return tryAllocateSlowCase(bytes, outPtr); + + *outPtr = allocateFromBlock(m_currentBlock, bytes); + return true; +} + +inline CheckedBoolean BumpSpace::tryAllocateOversize(size_t bytes, void** outPtr) +{ + ASSERT(isOversize(bytes)); + + size_t blockSize = WTF::roundUpToMultipleOf(sizeof(BumpBlock) + bytes); + PageAllocationAligned allocation = PageAllocationAligned::allocate(blockSize, s_pageSize, OSAllocator::JSGCHeapPages); + if (!static_cast(allocation)) { + *outPtr = 0; + return false; + } + BumpBlock* block = new (NotNull, allocation.base()) BumpBlock(allocation); + m_oversizeBlocks.push(block); + ASSERT(isPointerAligned(block->m_offset)); + + m_oversizeFilter.add(reinterpret_cast(block)); + + m_totalMemoryAllocated += blockSize; + m_totalMemoryUtilized += bytes; + + *outPtr = block->m_offset; + return true; +} + +inline void* BumpSpace::allocateFromBlock(BumpBlock* block, size_t bytes) +{ + ASSERT(!isOversize(bytes)); + ASSERT(fitsInBlock(block, bytes)); + ASSERT(isPointerAligned(block->m_offset)); + + void* ptr = block->m_offset; + ASSERT(block->m_offset >= block->m_payload && block->m_offset < reinterpret_cast(block) + s_blockSize); + block->m_offset = static_cast((static_cast(ptr) + bytes)); + ASSERT(block->m_offset >= block->m_payload && block->m_offset < reinterpret_cast(block) + s_blockSize); + + ASSERT(isPointerAligned(ptr)); + return ptr; +} + +inline CheckedBoolean BumpSpace::tryReallocate(void** ptr, size_t oldSize, size_t newSize) +{ + if (oldSize >= newSize) + return true; + + void* oldPtr = *ptr; + ASSERT(!m_heap->globalData()->isInitializingObject()); + + if (isOversize(oldSize) || isOversize(newSize)) + return tryReallocateOversize(ptr, oldSize, newSize); + + if (static_cast(oldPtr) + oldSize == m_currentBlock->m_offset && oldPtr > m_currentBlock && oldPtr < reinterpret_cast(m_currentBlock) + s_blockSize) { + m_currentBlock->m_offset = oldPtr; + if (fitsInCurrentBlock(newSize)) { + m_totalMemoryUtilized += newSize - oldSize; + return allocateFromBlock(m_currentBlock, newSize); + } + } + m_totalMemoryUtilized -= oldSize; + + void* result = 0; + if (!tryAllocate(newSize, &result)) { + *ptr = 0; + return false; + } + memcpy(result, oldPtr, oldSize); + *ptr = result; + return true; +} + +inline CheckedBoolean BumpSpace::tryReallocateOversize(void** ptr, size_t oldSize, size_t newSize) +{ + ASSERT(isOversize(oldSize) || isOversize(newSize)); + ASSERT(newSize > oldSize); + + void* oldPtr = *ptr; + + void* newPtr = 0; + if (!tryAllocateOversize(newSize, &newPtr)) { + *ptr = 0; + return false; + } + memcpy(newPtr, oldPtr, oldSize); + + if (isOversize(oldSize)) { + BumpBlock* oldBlock = oversizeBlockFor(oldPtr); + m_oversizeBlocks.remove(oldBlock); + oldBlock->m_allocation.deallocate(); + m_totalMemoryAllocated -= oldSize + sizeof(BumpBlock); + } + + m_totalMemoryUtilized -= oldSize; + + *ptr = newPtr; + return true; +} + +inline bool BumpSpace::isOversize(size_t bytes) +{ + return bytes > s_maxAllocationSize; +} + +inline bool BumpSpace::isPinned(void* ptr) +{ + return blockFor(ptr)->m_isPinned; +} + +inline BumpBlock* BumpSpace::oversizeBlockFor(void* ptr) +{ + return reinterpret_cast(reinterpret_cast(ptr) & s_pageMask); +} + +inline BumpBlock* BumpSpace::blockFor(void* ptr) +{ + return reinterpret_cast(reinterpret_cast(ptr) & s_blockMask); +} + +} // namespace JSC + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ByteArray.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ByteArray.h new file mode 100644 index 000000000..f68d032fd --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ByteArray.h @@ -0,0 +1,110 @@ +/* + * 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 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 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 ByteArray_h +#define ByteArray_h + +#include +#include +#include +#include +#include + +namespace WTF { + class ByteArray : public RefCountedBase { + public: + unsigned length() const { return m_size; } + + void set(unsigned index, double value) + { + if (index >= m_size) + return; + if (!(value > 0)) // Clamp NaN to 0 + value = 0; + else if (value > 255) + value = 255; + m_data[index] = static_cast(value + 0.5); + } + + void set(unsigned index, unsigned char value) + { + if (index >= m_size) + return; + m_data[index] = value; + } + + bool get(unsigned index, unsigned char& result) const + { + if (index >= m_size) + return false; + result = m_data[index]; + return true; + } + + unsigned char get(unsigned index) const + { + ASSERT(index < m_size); + return m_data[index]; + } + + unsigned char* data() { return m_data; } + + void clear() { memset(m_data, 0, m_size); } + + void deref() + { + if (derefBase()) { + // We allocated with new unsigned char[] in create(), + // and then used placement new to construct the object. + this->~ByteArray(); + delete[] reinterpret_cast(this); + } + } + + WTF_EXPORT_PRIVATE static PassRefPtr create(size_t size); + + static size_t offsetOfSize() { return OBJECT_OFFSETOF(ByteArray, m_size); } + static size_t offsetOfData() { return OBJECT_OFFSETOF(ByteArray, m_data); } + + private: + ByteArray(size_t size) + : m_size(size) + { + } + size_t m_size; +// MSVC can't handle correctly unsized array. +// warning C4200: nonstandard extension used : zero-sized array in struct/union +// Cannot generate copy-ctor or copy-assignment operator when UDT contains a zero-sized array +#if (COMPILER(MSVC) || COMPILER(SUNCC)) && !COMPILER(INTEL) + unsigned char m_data[INT_MAX]; +#else + unsigned char m_data[]; +#endif + }; +} // namespace WTF + +using WTF::ByteArray; + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CString.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CString.h new file mode 100644 index 000000000..d43ad4bd7 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CString.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2003, 2006, 2008, 2009, 2010 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 CString_h +#define CString_h + +#include "PassRefPtr.h" +#include "RefCounted.h" +#include "Vector.h" + +namespace WTF { + +class CStringBuffer : public RefCounted { +public: + const char* data() { return m_vector.data(); } + size_t length() { return m_vector.size(); } + +private: + friend class CString; + + static PassRefPtr create(size_t length) { return adoptRef(new CStringBuffer(length)); } + CStringBuffer(size_t length) : m_vector(length) { } + char* mutableData() { return m_vector.data(); } + + Vector m_vector; +}; + +// A container for a null-terminated char array supporting copy-on-write +// assignment. The contained char array may be null. +class CString { +public: + CString() { } + WTF_EXPORT_PRIVATE CString(const char*); + WTF_EXPORT_PRIVATE CString(const char*, size_t length); + CString(CStringBuffer* buffer) : m_buffer(buffer) { } + WTF_EXPORT_PRIVATE static CString newUninitialized(size_t length, char*& characterBuffer); + + const char* data() const + { + return m_buffer ? m_buffer->data() : 0; + } + WTF_EXPORT_PRIVATE char* mutableData(); + size_t length() const + { + return m_buffer ? m_buffer->length() - 1 : 0; + } + + bool isNull() const { return !m_buffer; } + + CStringBuffer* buffer() const { return m_buffer.get(); } + +private: + void copyBufferIfNeeded(); + void init(const char*, size_t length); + RefPtr m_buffer; +}; + +WTF_EXPORT_PRIVATE bool operator==(const CString& a, const CString& b); +inline bool operator!=(const CString& a, const CString& b) { return !(a == b); } + +} // namespace WTF + +using WTF::CString; + +#endif // CString_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CachedTranscendentalFunction.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CachedTranscendentalFunction.h new file mode 100644 index 000000000..f31b4a07f --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CachedTranscendentalFunction.h @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2010 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 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 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 CachedTranscendentalFunction_h +#define CachedTranscendentalFunction_h + +#include "JSValue.h" + +namespace JSC { + +typedef double (*TranscendentalFunctionPtr)(double); + +// CachedTranscendentalFunction provides a generic mechanism to cache results +// for pure functions with the signature "double func(double)", and where NaN +// maps to NaN. +template +class CachedTranscendentalFunction { + struct CacheEntry { + double operand; + double result; + }; + +public: + CachedTranscendentalFunction() + : m_cache(0) + { + } + + ~CachedTranscendentalFunction() + { + if (m_cache) + fastFree(m_cache); + } + + JSValue operator() (double operand) + { + if (UNLIKELY(!m_cache)) + initialize(); + CacheEntry* entry = &m_cache[hash(operand)]; + + if (entry->operand == operand) + return jsDoubleNumber(entry->result); + double result = orignalFunction(operand); + entry->operand = operand; + entry->result = result; + return jsDoubleNumber(result); + } + +private: + void initialize() + { + // Lazily allocate the table, populate with NaN->NaN mapping. + m_cache = static_cast(fastMalloc(s_cacheSize * sizeof(CacheEntry))); + for (unsigned x = 0; x < s_cacheSize; ++x) { + m_cache[x].operand = std::numeric_limits::quiet_NaN(); + m_cache[x].result = std::numeric_limits::quiet_NaN(); + } + } + + static unsigned hash(double d) + { + union doubleAndUInt64 { + double d; + uint32_t is[2]; + } u; + u.d = d; + + unsigned x = u.is[0] ^ u.is[1]; + x = (x >> 20) ^ (x >> 8); + return x & (s_cacheSize - 1); + } + + static const unsigned s_cacheSize = 0x1000; + CacheEntry* m_cache; +}; + +} + +#endif // CachedTranscendentalFunction_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CallData.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CallData.h new file mode 100644 index 000000000..15a6a0a48 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CallData.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 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. + * 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 CallData_h +#define CallData_h + +#include "JSValue.h" + +namespace JSC { + + class ArgList; + class ExecState; + class FunctionExecutable; + class JSObject; + class ScopeChainNode; + + enum CallType { + CallTypeNone, + CallTypeHost, + CallTypeJS + }; + + typedef EncodedJSValue (JSC_HOST_CALL *NativeFunction)(ExecState*); + + union CallData { + struct { + NativeFunction function; + } native; + struct { + FunctionExecutable* functionExecutable; + ScopeChainNode* scopeChain; + } js; + }; + + JS_EXPORT_PRIVATE JSValue call(ExecState*, JSValue functionObject, CallType, const CallData&, JSValue thisValue, const ArgList&); + +} // namespace JSC + +#endif // CallData_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CallFrame.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CallFrame.h new file mode 100644 index 000000000..d5037b794 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CallFrame.h @@ -0,0 +1,214 @@ +/* + * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) + * Copyright (C) 2001 Peter Kelly (pmk@post.com) + * Copyright (C) 2003, 2007, 2008, 2011 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef CallFrame_h +#define CallFrame_h + +#include "JSGlobalData.h" +#include "MacroAssemblerCodeRef.h" +#include "RegisterFile.h" + +namespace JSC { + + class Arguments; + class JSActivation; + class Interpreter; + class ScopeChainNode; + + // Represents the current state of script execution. + // Passed as the first argument to most functions. + class ExecState : private Register { + public: + JSValue calleeAsValue() const { return this[RegisterFile::Callee].jsValue(); } + JSObject* callee() const { return this[RegisterFile::Callee].function(); } + CodeBlock* codeBlock() const { return this[RegisterFile::CodeBlock].Register::codeBlock(); } + ScopeChainNode* scopeChain() const + { + ASSERT(this[RegisterFile::ScopeChain].Register::scopeChain()); + return this[RegisterFile::ScopeChain].Register::scopeChain(); + } + + // Global object in which execution began. + JSGlobalObject* dynamicGlobalObject(); + + // Global object in which the currently executing code was defined. + // Differs from dynamicGlobalObject() during function calls across web browser frames. + inline JSGlobalObject* lexicalGlobalObject() const; + + // Differs from lexicalGlobalObject because this will have DOM window shell rather than + // the actual DOM window, which can't be "this" for security reasons. + inline JSObject* globalThisValue() const; + + inline JSGlobalData& globalData() const; + + // Convenience functions for access to global data. + // It takes a few memory references to get from a call frame to the global data + // pointer, so these are inefficient, and should be used sparingly in new code. + // But they're used in many places in legacy code, so they're not going away any time soon. + + void clearException() { globalData().exception = JSValue(); } + JSValue exception() const { return globalData().exception; } + bool hadException() const { return globalData().exception; } + + const CommonIdentifiers& propertyNames() const { return *globalData().propertyNames; } + const MarkedArgumentBuffer& emptyList() const { return *globalData().emptyList; } + Interpreter* interpreter() { return globalData().interpreter; } + Heap* heap() { return &globalData().heap; } +#ifndef NDEBUG + void dumpCaller(); +#endif + static const HashTable* arrayConstructorTable(CallFrame* callFrame) { return callFrame->globalData().arrayConstructorTable; } + static const HashTable* arrayPrototypeTable(CallFrame* callFrame) { return callFrame->globalData().arrayPrototypeTable; } + static const HashTable* booleanPrototypeTable(CallFrame* callFrame) { return callFrame->globalData().booleanPrototypeTable; } + static const HashTable* dateTable(CallFrame* callFrame) { return callFrame->globalData().dateTable; } + static const HashTable* dateConstructorTable(CallFrame* callFrame) { return callFrame->globalData().dateConstructorTable; } + static const HashTable* errorPrototypeTable(CallFrame* callFrame) { return callFrame->globalData().errorPrototypeTable; } + static const HashTable* globalObjectTable(CallFrame* callFrame) { return callFrame->globalData().globalObjectTable; } + static const HashTable* jsonTable(CallFrame* callFrame) { return callFrame->globalData().jsonTable; } + static const HashTable* mathTable(CallFrame* callFrame) { return callFrame->globalData().mathTable; } + static const HashTable* numberConstructorTable(CallFrame* callFrame) { return callFrame->globalData().numberConstructorTable; } + static const HashTable* numberPrototypeTable(CallFrame* callFrame) { return callFrame->globalData().numberPrototypeTable; } + static const HashTable* objectConstructorTable(CallFrame* callFrame) { return callFrame->globalData().objectConstructorTable; } + static const HashTable* objectPrototypeTable(CallFrame* callFrame) { return callFrame->globalData().objectPrototypeTable; } + static const HashTable* regExpTable(CallFrame* callFrame) { return callFrame->globalData().regExpTable; } + static const HashTable* regExpConstructorTable(CallFrame* callFrame) { return callFrame->globalData().regExpConstructorTable; } + static const HashTable* regExpPrototypeTable(CallFrame* callFrame) { return callFrame->globalData().regExpPrototypeTable; } + static const HashTable* stringTable(CallFrame* callFrame) { return callFrame->globalData().stringTable; } + static const HashTable* stringConstructorTable(CallFrame* callFrame) { return callFrame->globalData().stringConstructorTable; } + + static CallFrame* create(Register* callFrameBase) { return static_cast(callFrameBase); } + Register* registers() { return this; } + + CallFrame& operator=(const Register& r) { *static_cast(this) = r; return *this; } + + CallFrame* callerFrame() const { return this[RegisterFile::CallerFrame].callFrame(); } +#if ENABLE(JIT) + ReturnAddressPtr returnPC() const { return ReturnAddressPtr(this[RegisterFile::ReturnPC].vPC()); } +#endif +#if ENABLE(DFG_JIT) + InlineCallFrame* inlineCallFrame() const { return this[RegisterFile::ReturnPC].asInlineCallFrame(); } +#else + // This will never be called if !ENABLE(DFG_JIT) since all calls should be guarded by + // isInlineCallFrame(). But to make it easier to write code without having a bunch of + // #if's, we make a dummy implementation available anyway. + InlineCallFrame* inlineCallFrame() const + { + ASSERT_NOT_REACHED(); + return 0; + } +#endif +#if ENABLE(INTERPRETER) + Instruction* returnVPC() const { return this[RegisterFile::ReturnPC].vPC(); } +#endif + + void setCallerFrame(CallFrame* callerFrame) { static_cast(this)[RegisterFile::CallerFrame] = callerFrame; } + void setScopeChain(ScopeChainNode* scopeChain) { static_cast(this)[RegisterFile::ScopeChain] = scopeChain; } + + ALWAYS_INLINE void init(CodeBlock* codeBlock, Instruction* vPC, ScopeChainNode* scopeChain, + CallFrame* callerFrame, int argc, JSObject* callee) + { + ASSERT(callerFrame); // Use noCaller() rather than 0 for the outer host call frame caller. + ASSERT(callerFrame == noCaller() || callerFrame->removeHostCallFrameFlag()->registerFile()->end() >= this); + + setCodeBlock(codeBlock); + setScopeChain(scopeChain); + setCallerFrame(callerFrame); + setReturnPC(vPC); // This is either an Instruction* or a pointer into JIT generated code stored as an Instruction*. + setArgumentCountIncludingThis(argc); // original argument count (for the sake of the "arguments" object) + setCallee(callee); + } + + // Read a register from the codeframe (or constant from the CodeBlock). + inline Register& r(int); + // Read a register for a non-constant + inline Register& uncheckedR(int); + + // Access to arguments. + size_t argumentCount() const { return argumentCountIncludingThis() - 1; } + size_t argumentCountIncludingThis() const { return this[RegisterFile::ArgumentCount].payload(); } + static int argumentOffset(size_t argument) { return s_firstArgumentOffset - argument; } + static int argumentOffsetIncludingThis(size_t argument) { return s_thisArgumentOffset - argument; } + + JSValue argument(size_t argument) + { + if (argument >= argumentCount()) + return jsUndefined(); + return this[argumentOffset(argument)].jsValue(); + } + void setArgument(size_t argument, JSValue value) + { + this[argumentOffset(argument)] = value; + } + + static int thisArgumentOffset() { return argumentOffsetIncludingThis(0); } + JSValue thisValue() { return this[thisArgumentOffset()].jsValue(); } + void setThisValue(JSValue value) { this[thisArgumentOffset()] = value; } + + static int offsetFor(size_t argumentCountIncludingThis) { return argumentCountIncludingThis + RegisterFile::CallFrameHeaderSize; } + + // FIXME: Remove these. + int hostThisRegister() { return thisArgumentOffset(); } + JSValue hostThisValue() { return thisValue(); } + + static CallFrame* noCaller() { return reinterpret_cast(HostCallFrameFlag); } + + bool hasHostCallFrameFlag() const { return reinterpret_cast(this) & HostCallFrameFlag; } + CallFrame* addHostCallFrameFlag() const { return reinterpret_cast(reinterpret_cast(this) | HostCallFrameFlag); } + CallFrame* removeHostCallFrameFlag() { return reinterpret_cast(reinterpret_cast(this) & ~HostCallFrameFlag); } + + void setArgumentCountIncludingThis(int count) { static_cast(this)[RegisterFile::ArgumentCount].payload() = count; } + void setCallee(JSObject* callee) { static_cast(this)[RegisterFile::Callee] = Register::withCallee(callee); } + void setCodeBlock(CodeBlock* codeBlock) { static_cast(this)[RegisterFile::CodeBlock] = codeBlock; } + void setReturnPC(void* value) { static_cast(this)[RegisterFile::ReturnPC] = (Instruction*)value; } + +#if ENABLE(DFG_JIT) + bool isInlineCallFrame(); + + void setInlineCallFrame(InlineCallFrame* inlineCallFrame) { static_cast(this)[RegisterFile::ReturnPC] = inlineCallFrame; } + + // Call this to get the semantically correct JS CallFrame*. This resolves issues + // surrounding inlining and the HostCallFrameFlag stuff. + CallFrame* trueCallerFrame(); +#else + bool isInlineCallFrame() { return false; } + + CallFrame* trueCallerFrame() { return callerFrame()->removeHostCallFrameFlag(); } +#endif + + private: + static const intptr_t HostCallFrameFlag = 1; + static const int s_thisArgumentOffset = -1 - RegisterFile::CallFrameHeaderSize; + static const int s_firstArgumentOffset = s_thisArgumentOffset - 1; + +#ifndef NDEBUG + RegisterFile* registerFile(); +#endif +#if ENABLE(DFG_JIT) + bool isInlineCallFrameSlow(); +#endif + ExecState(); + ~ExecState(); + }; + +} // namespace JSC + +#endif // CallFrame_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CallIdentifier.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CallIdentifier.h new file mode 100644 index 000000000..2da8a2ff1 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CallIdentifier.h @@ -0,0 +1,101 @@ +/* + * Copyright (C) 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 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 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 CallIdentifier_h +#define CallIdentifier_h + +#include +#include +#include + +namespace JSC { + + struct CallIdentifier { + WTF_MAKE_FAST_ALLOCATED; + public: + UString m_name; + UString m_url; + unsigned m_lineNumber; + + CallIdentifier() + : m_lineNumber(0) + { + } + + CallIdentifier(const UString& name, const UString& url, int lineNumber) + : m_name(name) + , m_url(!url.isNull() ? url : "") + , m_lineNumber(lineNumber) + { + } + + inline bool operator==(const CallIdentifier& ci) const { return ci.m_lineNumber == m_lineNumber && ci.m_name == m_name && ci.m_url == m_url; } + inline bool operator!=(const CallIdentifier& ci) const { return !(*this == ci); } + + struct Hash { + static unsigned hash(const CallIdentifier& key) + { + unsigned hashCodes[3] = { + key.m_name.impl()->hash(), + key.m_url.impl()->hash(), + key.m_lineNumber + }; + return StringHasher::hashMemory(hashCodes); + } + + static bool equal(const CallIdentifier& a, const CallIdentifier& b) { return a == b; } + static const bool safeToCompareToEmptyOrDeleted = true; + }; + + unsigned hash() const { return Hash::hash(*this); } + +#ifndef NDEBUG + operator const char*() const { return c_str(); } + const char* c_str() const { return m_name.utf8().data(); } +#endif + }; + +} // namespace JSC + +namespace WTF { + + template<> struct DefaultHash { typedef JSC::CallIdentifier::Hash Hash; }; + + template<> struct HashTraits : GenericHashTraits { + static void constructDeletedValue(JSC::CallIdentifier& slot) + { + new (NotNull, &slot) JSC::CallIdentifier(JSC::UString(), JSC::UString(), std::numeric_limits::max()); + } + static bool isDeletedValue(const JSC::CallIdentifier& value) + { + return value.m_name.isNull() && value.m_url.isNull() && value.m_lineNumber == std::numeric_limits::max(); + } + }; + +} // namespace WTF + +#endif // CallIdentifier_h + diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CallLinkInfo.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CallLinkInfo.h new file mode 100644 index 000000000..8ec48e4e1 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CallLinkInfo.h @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2012 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 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 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 CallLinkInfo_h +#define CallLinkInfo_h + +#include "CodeLocation.h" +#include "JITWriteBarrier.h" +#include "JSFunction.h" +#include "Opcode.h" +#include "WriteBarrier.h" +#include +#include + +namespace JSC { + +#if ENABLE(JIT) + +class RepatchBuffer; + +struct CallLinkInfo : public BasicRawSentinelNode { + enum CallType { None, Call, CallVarargs, Construct }; + static CallType callTypeFor(OpcodeID opcodeID) + { + if (opcodeID == op_call || opcodeID == op_call_eval) + return Call; + if (opcodeID == op_construct) + return Construct; + ASSERT(opcodeID == op_call_varargs); + return CallVarargs; + } + + CallLinkInfo() + : hasSeenShouldRepatch(false) + , isDFG(false) + , callType(None) + { + } + + ~CallLinkInfo() + { + if (isOnList()) + remove(); + } + + CodeLocationLabel callReturnLocation; // it's a near call in the old JIT, or a normal call in DFG + CodeLocationDataLabelPtr hotPathBegin; + CodeLocationNearCall hotPathOther; + JITWriteBarrier callee; + WriteBarrier lastSeenCallee; + bool hasSeenShouldRepatch : 1; + bool isDFG : 1; + CallType callType : 2; + unsigned bytecodeIndex; + + bool isLinked() { return callee; } + void unlink(JSGlobalData&, RepatchBuffer&); + + bool seenOnce() + { + return hasSeenShouldRepatch; + } + + void setSeen() + { + hasSeenShouldRepatch = true; + } +}; + +inline void* getCallLinkInfoReturnLocation(CallLinkInfo* callLinkInfo) +{ + return callLinkInfo->callReturnLocation.executableAddress(); +} + +inline unsigned getCallLinkInfoBytecodeIndex(CallLinkInfo* callLinkInfo) +{ + return callLinkInfo->bytecodeIndex; +} +#endif // ENABLE(JIT) + +} // namespace JSC + +#endif // CallLinkInfo_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CallLinkStatus.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CallLinkStatus.h new file mode 100644 index 000000000..e1c741016 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CallLinkStatus.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2012 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 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 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 CallLinkStatus_h +#define CallLinkStatus_h + +namespace JSC { + +class JSFunction; +class CodeBlock; + +class CallLinkStatus { +public: + CallLinkStatus() + : m_callTarget(0) + , m_couldTakeSlowPath(false) + { + } + + CallLinkStatus(JSFunction* callTarget, bool couldTakeSlowPath) + : m_callTarget(callTarget) + , m_couldTakeSlowPath(couldTakeSlowPath) + { + } + + static CallLinkStatus computeFor(CodeBlock*, unsigned bytecodeIndex); + + bool isSet() const { return !!m_callTarget; } + + bool operator!() const { return !m_callTarget; } + + bool couldTakeSlowPath() const { return m_couldTakeSlowPath; } + + JSFunction* callTarget() const { return m_callTarget; } + +private: + JSFunction* m_callTarget; + bool m_couldTakeSlowPath; +}; + +} // namespace JSC + +#endif // CallLinkStatus_h + diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CallReturnOffsetToBytecodeOffset.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CallReturnOffsetToBytecodeOffset.h new file mode 100644 index 000000000..3a7448efd --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CallReturnOffsetToBytecodeOffset.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2012 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 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 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 CallReturnOffsetToBytecodeOffset_h +#define CallReturnOffsetToBytecodeOffset_h + +#include + +namespace JSC { + +#if ENABLE(JIT) +// This structure is used to map from a call return location +// (given as an offset in bytes into the JIT code) back to +// the bytecode index of the corresponding bytecode operation. +// This is then used to look up the corresponding handler. +// FIXME: This should be made inlining aware! Currently it isn't +// because we never inline code that has exception handlers. +struct CallReturnOffsetToBytecodeOffset { + CallReturnOffsetToBytecodeOffset(unsigned callReturnOffset, unsigned bytecodeOffset) + : callReturnOffset(callReturnOffset) + , bytecodeOffset(bytecodeOffset) + { + } + + unsigned callReturnOffset; + unsigned bytecodeOffset; +}; + +inline unsigned getCallReturnOffset(CallReturnOffsetToBytecodeOffset* pc) +{ + return pc->callReturnOffset; +} +#endif + +} // namespace JSC + +#endif // CallReturnOffsetToBytecodeOffset_h + diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CardSet.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CardSet.h new file mode 100644 index 000000000..dc44c024d --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CardSet.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2011 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 INC. 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 INC. 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 CardSet_h +#define CardSet_h + +#include +#include +#include + +namespace JSC { + +template class CardSet { + WTF_MAKE_NONCOPYABLE(CardSet); + +public: + static const size_t cardCount = (blockSize + cardSize - 1) / cardSize; + + CardSet() + { + memset(m_cards, 0, cardCount); + } + + bool isCardMarkedForAtom(const void*); + void markCardForAtom(const void*); + uint8_t& cardForAtom(const void*); + bool isCardMarked(size_t); + bool testAndClear(size_t); + +private: + uint8_t m_cards[cardCount]; + COMPILE_ASSERT(!(cardSize & (cardSize - 1)), cardSet_cardSize_is_power_of_two); + COMPILE_ASSERT(!(cardCount & (cardCount - 1)), cardSet_cardCount_is_power_of_two); +}; + +template uint8_t& CardSet::cardForAtom(const void* ptr) +{ + ASSERT(ptr > this && ptr < (reinterpret_cast(this) + cardCount * cardSize)); + uintptr_t card = (reinterpret_cast(ptr) / cardSize) % cardCount; + return m_cards[card]; +} + +template bool CardSet::isCardMarkedForAtom(const void* ptr) +{ + return cardForAtom(ptr); +} + +template void CardSet::markCardForAtom(const void* ptr) +{ + cardForAtom(ptr) = 1; +} + +template bool CardSet::isCardMarked(size_t i) +{ + ASSERT(i < cardCount); + return m_cards[i]; +} + +template bool CardSet::testAndClear(size_t i) +{ + ASSERT(i < cardCount); + bool result = m_cards[i]; + m_cards[i] = 0; + return result; +} + +} + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CharacterNames.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CharacterNames.h new file mode 100644 index 000000000..10fdbf0ef --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CharacterNames.h @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2007, 2009, 2010 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 CharacterNames_h +#define CharacterNames_h + +#include "Unicode.h" + +namespace WTF { +namespace Unicode { + +// Names here are taken from the Unicode standard. + +// Most of these are UChar constants, not UChar32, which makes them +// more convenient for WebCore code that mostly uses UTF-16. + +const UChar32 aegeanWordSeparatorLine = 0x10100; +const UChar32 aegeanWordSeparatorDot = 0x10101; +const UChar blackCircle = 0x25CF; +const UChar blackSquare = 0x25A0; +const UChar blackUpPointingTriangle = 0x25B2; +const UChar bullet = 0x2022; +const UChar bullseye = 0x25CE; +const UChar carriageReturn = 0x000D; +const UChar ethiopicPrefaceColon = 0x1366; +const UChar ethiopicWordspace = 0x1361; +const UChar fisheye = 0x25C9; +const UChar hebrewPunctuationGeresh = 0x05F3; +const UChar hebrewPunctuationGershayim = 0x05F4; +const UChar horizontalEllipsis = 0x2026; +const UChar hyphen = 0x2010; +const UChar hyphenMinus = 0x002D; +const UChar ideographicComma = 0x3001; +const UChar ideographicFullStop = 0x3002; +const UChar ideographicSpace = 0x3000; +const UChar leftDoubleQuotationMark = 0x201C; +const UChar leftSingleQuotationMark = 0x2018; +const UChar leftToRightEmbed = 0x202A; +const UChar leftToRightMark = 0x200E; +const UChar leftToRightOverride = 0x202D; +const UChar minusSign = 0x2212; +const UChar newlineCharacter = 0x000A; +const UChar noBreakSpace = 0x00A0; +const UChar objectReplacementCharacter = 0xFFFC; +const UChar popDirectionalFormatting = 0x202C; +const UChar replacementCharacter = 0xFFFD; +const UChar rightDoubleQuotationMark = 0x201D; +const UChar rightSingleQuotationMark = 0x2019; +const UChar rightToLeftEmbed = 0x202B; +const UChar rightToLeftMark = 0x200F; +const UChar rightToLeftOverride = 0x202E; +const UChar sesameDot = 0xFE45; +const UChar softHyphen = 0x00AD; +const UChar space = 0x0020; +const UChar tibetanMarkIntersyllabicTsheg = 0x0F0B; +const UChar tibetanMarkDelimiterTshegBstar = 0x0F0C; +const UChar32 ugariticWordDivider = 0x1039F; +const UChar whiteBullet = 0x25E6; +const UChar whiteCircle = 0x25CB; +const UChar whiteSesameDot = 0xFE46; +const UChar whiteUpPointingTriangle = 0x25B3; +const UChar yenSign = 0x00A5; +const UChar zeroWidthJoiner = 0x200D; +const UChar zeroWidthNonJoiner = 0x200C; +const UChar zeroWidthSpace = 0x200B; +const UChar zeroWidthNoBreakSpace = 0xFEFF; + +} // namespace Unicode +} // namespace WTF + +using WTF::Unicode::aegeanWordSeparatorLine; +using WTF::Unicode::aegeanWordSeparatorDot; +using WTF::Unicode::blackCircle; +using WTF::Unicode::blackSquare; +using WTF::Unicode::blackUpPointingTriangle; +using WTF::Unicode::bullet; +using WTF::Unicode::bullseye; +using WTF::Unicode::carriageReturn; +using WTF::Unicode::ethiopicPrefaceColon; +using WTF::Unicode::ethiopicWordspace; +using WTF::Unicode::fisheye; +using WTF::Unicode::hebrewPunctuationGeresh; +using WTF::Unicode::hebrewPunctuationGershayim; +using WTF::Unicode::horizontalEllipsis; +using WTF::Unicode::hyphen; +using WTF::Unicode::hyphenMinus; +using WTF::Unicode::ideographicComma; +using WTF::Unicode::ideographicFullStop; +using WTF::Unicode::ideographicSpace; +using WTF::Unicode::leftDoubleQuotationMark; +using WTF::Unicode::leftSingleQuotationMark; +using WTF::Unicode::leftToRightEmbed; +using WTF::Unicode::leftToRightMark; +using WTF::Unicode::leftToRightOverride; +using WTF::Unicode::minusSign; +using WTF::Unicode::newlineCharacter; +using WTF::Unicode::noBreakSpace; +using WTF::Unicode::objectReplacementCharacter; +using WTF::Unicode::popDirectionalFormatting; +using WTF::Unicode::replacementCharacter; +using WTF::Unicode::rightDoubleQuotationMark; +using WTF::Unicode::rightSingleQuotationMark; +using WTF::Unicode::rightToLeftEmbed; +using WTF::Unicode::rightToLeftMark; +using WTF::Unicode::rightToLeftOverride; +using WTF::Unicode::sesameDot; +using WTF::Unicode::softHyphen; +using WTF::Unicode::space; +using WTF::Unicode::tibetanMarkIntersyllabicTsheg; +using WTF::Unicode::tibetanMarkDelimiterTshegBstar; +using WTF::Unicode::ugariticWordDivider; +using WTF::Unicode::whiteBullet; +using WTF::Unicode::whiteCircle; +using WTF::Unicode::whiteSesameDot; +using WTF::Unicode::whiteUpPointingTriangle; +using WTF::Unicode::yenSign; +using WTF::Unicode::zeroWidthJoiner; +using WTF::Unicode::zeroWidthNonJoiner; +using WTF::Unicode::zeroWidthSpace; +using WTF::Unicode::zeroWidthNoBreakSpace; + +#endif // CharacterNames_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CheckedArithmetic.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CheckedArithmetic.h new file mode 100644 index 000000000..f90efae41 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CheckedArithmetic.h @@ -0,0 +1,693 @@ +/* + * Copyright (C) 2011 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 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 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 CheckedArithmetic_h +#define CheckedArithmetic_h + +#include "Assertions.h" +#include "TypeTraits.h" + +#include +#include + +/* Checked + * + * This class provides a mechanism to perform overflow-safe integer arithmetic + * without having to manually ensure that you have all the required bounds checks + * directly in your code. + * + * There are two modes of operation: + * - The default is Checked, and crashes at the point + * and overflow has occurred. + * - The alternative is Checked, which uses an additional + * byte of storage to track whether an overflow has occurred, subsequent + * unchecked operations will crash if an overflow has occured + * + * It is possible to provide a custom overflow handler, in which case you need + * to support these functions: + * - void overflowed(); + * This function is called when an operation has produced an overflow. + * - bool hasOverflowed(); + * This function must return true if overflowed() has been called on an + * instance and false if it has not. + * - void clearOverflow(); + * Used to reset overflow tracking when a value is being overwritten with + * a new value. + * + * Checked works for all integer types, with the following caveats: + * - Mixing signedness of operands is only supported for types narrower than + * 64bits. + * - It does have a performance impact, so tight loops may want to be careful + * when using it. + * + */ + +namespace WTF { + +class CrashOnOverflow { +protected: + NO_RETURN_DUE_TO_CRASH void overflowed() + { + CRASH(); + } + + void clearOverflow() { } + +public: + bool hasOverflowed() const { return false; } +}; + +class RecordOverflow { +protected: + RecordOverflow() + : m_overflowed(false) + { + } + + void overflowed() + { + m_overflowed = true; + } + + void clearOverflow() + { + m_overflowed = false; + } + +public: + bool hasOverflowed() const { return m_overflowed; } + +private: + unsigned char m_overflowed; +}; + +template class Checked; +template struct RemoveChecked; +template struct RemoveChecked >; + +template ::is_signed, bool sourceSigned = std::numeric_limits::is_signed> struct BoundsChecker; +template struct BoundsChecker { + static bool inBounds(Source value) + { + // Same signedness so implicit type conversion will always increase precision + // to widest type + return value <= std::numeric_limits::max(); + } +}; + +template struct BoundsChecker { + static bool inBounds(Source value) + { + // Same signedness so implicit type conversion will always increase precision + // to widest type + return std::numeric_limits::min() <= value && value <= std::numeric_limits::max(); + } +}; + +template struct BoundsChecker { + static bool inBounds(Source value) + { + // Target is unsigned so any value less than zero is clearly unsafe + if (value < 0) + return false; + // If our (unsigned) Target is the same or greater width we can + // convert value to type Target without losing precision + if (sizeof(Target) >= sizeof(Source)) + return static_cast(value) <= std::numeric_limits::max(); + // The signed Source type has greater precision than the target so + // max(Target) -> Source will widen. + return value <= static_cast(std::numeric_limits::max()); + } +}; + +template struct BoundsChecker { + static bool inBounds(Source value) + { + // Signed target with an unsigned source + if (sizeof(Target) <= sizeof(Source)) + return value <= static_cast(std::numeric_limits::max()); + // Target is Wider than Source so we're guaranteed to fit any value in + // unsigned Source + return true; + } +}; + +template ::value> struct BoundsCheckElider; +template struct BoundsCheckElider { + static bool inBounds(Source) { return true; } +}; +template struct BoundsCheckElider : public BoundsChecker { +}; + +template static inline bool isInBounds(Source value) +{ + return BoundsCheckElider::inBounds(value); +} + +template struct RemoveChecked { + typedef T CleanType; + static const CleanType DefaultValue = 0; +}; + +template struct RemoveChecked > { + typedef typename RemoveChecked::CleanType CleanType; + static const CleanType DefaultValue = 0; +}; + +template struct RemoveChecked > { + typedef typename RemoveChecked::CleanType CleanType; + static const CleanType DefaultValue = 0; +}; + +// The ResultBase and SignednessSelector are used to workaround typeof not being +// available in MSVC +template sizeof(V)), bool sameSize = (sizeof(U) == sizeof(V))> struct ResultBase; +template struct ResultBase { + typedef U ResultType; +}; + +template struct ResultBase { + typedef V ResultType; +}; + +template struct ResultBase { + typedef U ResultType; +}; + +template ::is_signed, bool vIsSigned = std::numeric_limits::is_signed> struct SignednessSelector; +template struct SignednessSelector { + typedef U ResultType; +}; + +template struct SignednessSelector { + typedef U ResultType; +}; + +template struct SignednessSelector { + typedef V ResultType; +}; + +template struct SignednessSelector { + typedef U ResultType; +}; + +template struct ResultBase { + typedef typename SignednessSelector::ResultType ResultType; +}; + +template struct Result : ResultBase::CleanType, typename RemoveChecked::CleanType> { +}; + +template ::ResultType, + bool lhsSigned = std::numeric_limits::is_signed, bool rhsSigned = std::numeric_limits::is_signed> struct ArithmeticOperations; + +template struct ArithmeticOperations { + // LHS and RHS are signed types + + // Helper function + static inline bool signsMatch(LHS lhs, RHS rhs) + { + return (lhs ^ rhs) >= 0; + } + + static inline bool add(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN + { + if (signsMatch(lhs, rhs)) { + if (lhs >= 0) { + if ((std::numeric_limits::max() - rhs) < lhs) + return false; + } else { + ResultType temp = lhs - std::numeric_limits::min(); + if (rhs < -temp) + return false; + } + } // if the signs do not match this operation can't overflow + result = lhs + rhs; + return true; + } + + static inline bool sub(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN + { + if (!signsMatch(lhs, rhs)) { + if (lhs >= 0) { + if (lhs > std::numeric_limits::max() + rhs) + return false; + } else { + if (rhs > std::numeric_limits::max() + lhs) + return false; + } + } // if the signs match this operation can't overflow + result = lhs - rhs; + return true; + } + + static inline bool multiply(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN + { + if (signsMatch(lhs, rhs)) { + if (lhs >= 0) { + if (lhs && (std::numeric_limits::max() / lhs) < rhs) + return false; + } else { + if (lhs == std::numeric_limits::min() || rhs == std::numeric_limits::min()) + return false; + if ((std::numeric_limits::max() / -lhs) < -rhs) + return false; + } + } else { + if (lhs < 0) { + if (rhs && lhs < (std::numeric_limits::min() / rhs)) + return false; + } else { + if (lhs && rhs < (std::numeric_limits::min() / lhs)) + return false; + } + } + result = lhs * rhs; + return true; + } + + static inline bool equals(LHS lhs, RHS rhs) { return lhs == rhs; } + +}; + +template struct ArithmeticOperations { + // LHS and RHS are unsigned types so bounds checks are nice and easy + static inline bool add(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN + { + ResultType temp = lhs + rhs; + if (temp < lhs) + return false; + result = temp; + return true; + } + + static inline bool sub(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN + { + ResultType temp = lhs - rhs; + if (temp > lhs) + return false; + result = temp; + return true; + } + + static inline bool multiply(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN + { + ResultType temp = lhs * rhs; + if (temp < lhs) + return false; + result = temp; + return true; + } + + static inline bool equals(LHS lhs, RHS rhs) { return lhs == rhs; } + +}; + +template struct ArithmeticOperations { + static inline bool add(int64_t lhs, int64_t rhs, ResultType& result) + { + int64_t temp = lhs + rhs; + if (temp < std::numeric_limits::min()) + return false; + if (temp > std::numeric_limits::max()) + return false; + result = static_cast(temp); + return true; + } + + static inline bool sub(int64_t lhs, int64_t rhs, ResultType& result) + { + int64_t temp = lhs - rhs; + if (temp < std::numeric_limits::min()) + return false; + if (temp > std::numeric_limits::max()) + return false; + result = static_cast(temp); + return true; + } + + static inline bool multiply(int64_t lhs, int64_t rhs, ResultType& result) + { + int64_t temp = lhs * rhs; + if (temp < std::numeric_limits::min()) + return false; + if (temp > std::numeric_limits::max()) + return false; + result = static_cast(temp); + return true; + } + + static inline bool equals(int lhs, unsigned rhs) + { + return static_cast(lhs) == static_cast(rhs); + } +}; + +template struct ArithmeticOperations { + static inline bool add(int64_t lhs, int64_t rhs, ResultType& result) + { + return ArithmeticOperations::add(rhs, lhs, result); + } + + static inline bool sub(int64_t lhs, int64_t rhs, ResultType& result) + { + return ArithmeticOperations::sub(lhs, rhs, result); + } + + static inline bool multiply(int64_t lhs, int64_t rhs, ResultType& result) + { + return ArithmeticOperations::multiply(rhs, lhs, result); + } + + static inline bool equals(unsigned lhs, int rhs) + { + return ArithmeticOperations::equals(rhs, lhs); + } +}; + +template static inline bool safeAdd(U lhs, V rhs, R& result) +{ + return ArithmeticOperations::add(lhs, rhs, result); +} + +template static inline bool safeSub(U lhs, V rhs, R& result) +{ + return ArithmeticOperations::sub(lhs, rhs, result); +} + +template static inline bool safeMultiply(U lhs, V rhs, R& result) +{ + return ArithmeticOperations::multiply(lhs, rhs, result); +} + +template static inline bool safeEquals(U lhs, V rhs) +{ + return ArithmeticOperations::equals(lhs, rhs); +} + +enum ResultOverflowedTag { ResultOverflowed }; + +// FIXME: Needed to workaround http://llvm.org/bugs/show_bug.cgi?id=10801 +static inline bool workAroundClangBug() { return true; } + +template class Checked : public OverflowHandler { +public: + template friend class Checked; + Checked() + : m_value(0) + { + } + + Checked(ResultOverflowedTag) + : m_value(0) + { + // FIXME: Remove this when clang fixes http://llvm.org/bugs/show_bug.cgi?id=10801 + if (workAroundClangBug()) + this->overflowed(); + } + + template Checked(U value) + { + if (!isInBounds(value)) + this->overflowed(); + m_value = static_cast(value); + } + + template Checked(const Checked& rhs) + : m_value(rhs.m_value) + { + if (rhs.hasOverflowed()) + this->overflowed(); + } + + template Checked(const Checked& rhs) + : OverflowHandler(rhs) + { + if (!isInBounds(rhs.m_value)) + this->overflowed(); + m_value = static_cast(rhs.m_value); + } + + template Checked(const Checked& rhs) + { + if (rhs.hasOverflowed()) + this->overflowed(); + if (!isInBounds(rhs.m_value)) + this->overflowed(); + m_value = static_cast(rhs.m_value); + } + + const Checked& operator=(Checked rhs) + { + this->clearOverflow(); + if (rhs.hasOverflowed()) + this->overflowed(); + m_value = static_cast(rhs.m_value); + return *this; + } + + template const Checked& operator=(U value) + { + return *this = Checked(value); + } + + template const Checked& operator=(const Checked& rhs) + { + return *this = Checked(rhs); + } + + // prefix + const Checked& operator++() + { + if (m_value == std::numeric_limits::max()) + this->overflowed(); + m_value++; + return *this; + } + + const Checked& operator--() + { + if (m_value == std::numeric_limits::min()) + this->overflowed(); + m_value--; + return *this; + } + + // postfix operators + const Checked operator++(int) + { + if (m_value == std::numeric_limits::max()) + this->overflowed(); + return Checked(m_value++); + } + + const Checked operator--(int) + { + if (m_value == std::numeric_limits::min()) + this->overflowed(); + return Checked(m_value--); + } + + // Boolean operators + bool operator!() const + { + if (this->hasOverflowed()) + CRASH(); + return !m_value; + } + + typedef void* (Checked::*UnspecifiedBoolType); + operator UnspecifiedBoolType*() const + { + if (this->hasOverflowed()) + CRASH(); + return (m_value) ? reinterpret_cast(1) : 0; + } + + // Value accessors. unsafeGet() will crash if there's been an overflow. + T unsafeGet() const + { + if (this->hasOverflowed()) + CRASH(); + return m_value; + } + + bool safeGet(T& value) const WARN_UNUSED_RETURN + { + value = m_value; + return this->hasOverflowed(); + } + + // Mutating assignment + template const Checked operator+=(U rhs) + { + if (!safeAdd(m_value, rhs, m_value)) + this->overflowed(); + return *this; + } + + template const Checked operator-=(U rhs) + { + if (!safeSub(m_value, rhs, m_value)) + this->overflowed(); + return *this; + } + + template const Checked operator*=(U rhs) + { + if (!safeMultiply(m_value, rhs, m_value)) + this->overflowed(); + return *this; + } + + template const Checked operator+=(Checked rhs) + { + if (rhs.hasOverflowed()) + this->overflowed(); + return *this += rhs.m_value; + } + + template const Checked operator-=(Checked rhs) + { + if (rhs.hasOverflowed()) + this->overflowed(); + return *this -= rhs.m_value; + } + + template const Checked operator*=(Checked rhs) + { + if (rhs.hasOverflowed()) + this->overflowed(); + return *this *= rhs.m_value; + } + + // Equality comparisons + template bool operator==(Checked rhs) + { + return unsafeGet() == rhs.unsafeGet(); + } + + template bool operator==(U rhs) + { + if (this->hasOverflowed()) + this->overflowed(); + return safeEquals(m_value, rhs); + } + + template const Checked operator==(Checked rhs) + { + return unsafeGet() == Checked(rhs.unsafeGet()); + } + + template bool operator!=(U rhs) + { + return !(*this == rhs); + } + +private: + // Disallow implicit conversion of floating point to integer types + Checked(float); + Checked(double); + void operator=(float); + void operator=(double); + void operator+=(float); + void operator+=(double); + void operator-=(float); + void operator-=(double); + T m_value; +}; + +template static inline Checked::ResultType, OverflowHandler> operator+(Checked lhs, Checked rhs) +{ + U x = 0; + V y = 0; + bool overflowed = lhs.safeGet(x) || rhs.safeGet(y); + typename Result::ResultType result = 0; + overflowed |= !safeAdd(x, y, result); + if (overflowed) + return ResultOverflowed; + return result; +} + +template static inline Checked::ResultType, OverflowHandler> operator-(Checked lhs, Checked rhs) +{ + U x = 0; + V y = 0; + bool overflowed = lhs.safeGet(x) || rhs.safeGet(y); + typename Result::ResultType result = 0; + overflowed |= !safeSub(x, y, result); + if (overflowed) + return ResultOverflowed; + return result; +} + +template static inline Checked::ResultType, OverflowHandler> operator*(Checked lhs, Checked rhs) +{ + U x = 0; + V y = 0; + bool overflowed = lhs.safeGet(x) || rhs.safeGet(y); + typename Result::ResultType result = 0; + overflowed |= !safeMultiply(x, y, result); + if (overflowed) + return ResultOverflowed; + return result; +} + +template static inline Checked::ResultType, OverflowHandler> operator+(Checked lhs, V rhs) +{ + return lhs + Checked(rhs); +} + +template static inline Checked::ResultType, OverflowHandler> operator-(Checked lhs, V rhs) +{ + return lhs - Checked(rhs); +} + +template static inline Checked::ResultType, OverflowHandler> operator*(Checked lhs, V rhs) +{ + return lhs * Checked(rhs); +} + +template static inline Checked::ResultType, OverflowHandler> operator+(U lhs, Checked rhs) +{ + return Checked(lhs) + rhs; +} + +template static inline Checked::ResultType, OverflowHandler> operator-(U lhs, Checked rhs) +{ + return Checked(lhs) - rhs; +} + +template static inline Checked::ResultType, OverflowHandler> operator*(U lhs, Checked rhs) +{ + return Checked(lhs) * rhs; +} + +} + +using WTF::Checked; +using WTF::RecordOverflow; + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CheckedBoolean.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CheckedBoolean.h new file mode 100644 index 000000000..c65c70ef8 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CheckedBoolean.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2011 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 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 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 CheckedBoolean_h +#define CheckedBoolean_h + +#include + +class CheckedBoolean { +public: + CheckedBoolean(bool value) + : m_value(value) +#if !ASSERT_DISABLED + , m_checked(false) +#endif + { + } + + ~CheckedBoolean() + { + ASSERT(m_checked); + } + + operator bool() + { +#if !ASSERT_DISABLED + m_checked = true; +#endif + return m_value; + } + +private: + bool m_value; +#if !ASSERT_DISABLED + bool m_checked; +#endif +}; + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ClassInfo.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ClassInfo.h new file mode 100644 index 000000000..3d556d88c --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ClassInfo.h @@ -0,0 +1,198 @@ +/* + * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) + * Copyright (C) 2001 Peter Kelly (pmk@post.com) + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef ClassInfo_h +#define ClassInfo_h + +#include "CallFrame.h" +#include "ConstructData.h" +#include "JSCell.h" + +namespace JSC { + + class HashEntry; + struct HashTable; + + struct MethodTable { + typedef void (*DestroyFunctionPtr)(JSCell*); + DestroyFunctionPtr destroy; + + typedef void (*VisitChildrenFunctionPtr)(JSCell*, SlotVisitor&); + VisitChildrenFunctionPtr visitChildren; + + typedef CallType (*GetCallDataFunctionPtr)(JSCell*, CallData&); + GetCallDataFunctionPtr getCallData; + + typedef ConstructType (*GetConstructDataFunctionPtr)(JSCell*, ConstructData&); + GetConstructDataFunctionPtr getConstructData; + + typedef void (*PutFunctionPtr)(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); + PutFunctionPtr put; + + typedef void (*PutByIndexFunctionPtr)(JSCell*, ExecState*, unsigned propertyName, JSValue); + PutByIndexFunctionPtr putByIndex; + + typedef bool (*DeletePropertyFunctionPtr)(JSCell*, ExecState*, const Identifier&); + DeletePropertyFunctionPtr deleteProperty; + + typedef bool (*DeletePropertyByIndexFunctionPtr)(JSCell*, ExecState*, unsigned); + DeletePropertyByIndexFunctionPtr deletePropertyByIndex; + + typedef bool (*GetOwnPropertySlotFunctionPtr)(JSCell*, ExecState*, const Identifier&, PropertySlot&); + GetOwnPropertySlotFunctionPtr getOwnPropertySlot; + + typedef bool (*GetOwnPropertySlotByIndexFunctionPtr)(JSCell*, ExecState*, unsigned, PropertySlot&); + GetOwnPropertySlotByIndexFunctionPtr getOwnPropertySlotByIndex; + + typedef JSObject* (*ToThisObjectFunctionPtr)(JSCell*, ExecState*); + ToThisObjectFunctionPtr toThisObject; + + typedef void (*DefineGetterFunctionPtr)(JSObject*, ExecState*, const Identifier&, JSObject*, unsigned); + DefineGetterFunctionPtr defineGetter; + + typedef void (*DefineSetterFunctionPtr)(JSObject*, ExecState*, const Identifier&, JSObject*, unsigned); + DefineSetterFunctionPtr defineSetter; + + typedef JSValue (*DefaultValueFunctionPtr)(const JSObject*, ExecState*, PreferredPrimitiveType); + DefaultValueFunctionPtr defaultValue; + + typedef void (*GetOwnPropertyNamesFunctionPtr)(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); + GetOwnPropertyNamesFunctionPtr getOwnPropertyNames; + + typedef void (*GetPropertyNamesFunctionPtr)(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); + GetPropertyNamesFunctionPtr getPropertyNames; + + typedef UString (*ClassNameFunctionPtr)(const JSObject*); + ClassNameFunctionPtr className; + + typedef bool (*HasInstanceFunctionPtr)(JSObject*, ExecState*, JSValue, JSValue); + HasInstanceFunctionPtr hasInstance; + + typedef void (*PutWithAttributesFunctionPtr)(JSObject*, ExecState*, const Identifier& propertyName, JSValue, unsigned attributes); + PutWithAttributesFunctionPtr putDirectVirtual; + + typedef bool (*DefineOwnPropertyFunctionPtr)(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&, bool); + DefineOwnPropertyFunctionPtr defineOwnProperty; + + typedef bool (*GetOwnPropertyDescriptorFunctionPtr)(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); + GetOwnPropertyDescriptorFunctionPtr getOwnPropertyDescriptor; + }; + +#define CREATE_MEMBER_CHECKER(member) \ +template \ +struct MemberCheck##member { \ + struct Fallback { \ + void member(...); \ + }; \ + struct Derived : T, Fallback { }; \ + template struct Check; \ + typedef char Yes[2]; \ + typedef char No[1]; \ + template \ + static No &func(Check*); \ + template \ + static Yes &func(...); \ + enum { has = sizeof(func(0)) == sizeof(Yes) }; \ +} + +#define HAS_MEMBER_NAMED(klass, name) (MemberCheck##name::has) + +#define CREATE_METHOD_TABLE(ClassName) { \ + &ClassName::destroy, \ + &ClassName::visitChildren, \ + &ClassName::getCallData, \ + &ClassName::getConstructData, \ + &ClassName::put, \ + &ClassName::putByIndex, \ + &ClassName::deleteProperty, \ + &ClassName::deletePropertyByIndex, \ + &ClassName::getOwnPropertySlot, \ + &ClassName::getOwnPropertySlotByIndex, \ + &ClassName::toThisObject, \ + &ClassName::defineGetter, \ + &ClassName::defineSetter, \ + &ClassName::defaultValue, \ + &ClassName::getOwnPropertyNames, \ + &ClassName::getPropertyNames, \ + &ClassName::className, \ + &ClassName::hasInstance, \ + &ClassName::putDirectVirtual, \ + &ClassName::defineOwnProperty, \ + &ClassName::getOwnPropertyDescriptor, \ + }, \ + sizeof(ClassName), \ + ClassName::TypedArrayStorageType + + struct ClassInfo { + /** + * A string denoting the class name. Example: "Window". + */ + const char* className; + + /** + * Pointer to the class information of the base class. + * 0L if there is none. + */ + const ClassInfo* parentClass; + /** + * Static hash-table of properties. + * For classes that can be used from multiple threads, it is accessed via a getter function that would typically return a pointer to thread-specific value. + */ + const HashTable* propHashTable(ExecState* exec) const + { + if (classPropHashTableGetterFunction) + return classPropHashTableGetterFunction(exec); + return staticPropHashTable; + } + + bool isSubClassOf(const ClassInfo* other) const + { + for (const ClassInfo* ci = this; ci; ci = ci->parentClass) { + if (ci == other) + return true; + } + return false; + } + + bool hasStaticProperties() const + { + for (const ClassInfo* ci = this; ci; ci = ci->parentClass) { + if (ci->staticPropHashTable || ci->classPropHashTableGetterFunction) + return true; + } + return false; + } + + const HashTable* staticPropHashTable; + typedef const HashTable* (*ClassPropHashTableGetterFunction)(ExecState*); + const ClassPropHashTableGetterFunction classPropHashTableGetterFunction; + + MethodTable methodTable; + + size_t cellSize; + + TypedArrayType typedArrayStorageType; + }; + +} // namespace JSC + +#endif // ClassInfo_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CodeOrigin.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CodeOrigin.h new file mode 100644 index 000000000..25a116c55 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CodeOrigin.h @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2011 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 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 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 CodeOrigin_h +#define CodeOrigin_h + +#include "ValueRecovery.h" +#include "WriteBarrier.h" +#include +#include + +namespace JSC { + +struct InlineCallFrame; +class ExecutableBase; +class JSFunction; + +struct CodeOrigin { + // Bytecode offset that you'd use to re-execute this instruction. + unsigned bytecodeIndex : 29; + // Bytecode offset corresponding to the opcode that gives the result (needed to handle + // op_call/op_call_put_result and op_method_check/op_get_by_id). + unsigned valueProfileOffset : 3; + + InlineCallFrame* inlineCallFrame; + + CodeOrigin() + : bytecodeIndex(std::numeric_limits::max()) + , valueProfileOffset(0) + , inlineCallFrame(0) + { + } + + explicit CodeOrigin(unsigned bytecodeIndex, InlineCallFrame* inlineCallFrame = 0, unsigned valueProfileOffset = 0) + : bytecodeIndex(bytecodeIndex) + , valueProfileOffset(valueProfileOffset) + , inlineCallFrame(inlineCallFrame) + { + ASSERT(bytecodeIndex < (1u << 29)); + ASSERT(valueProfileOffset < (1u << 3)); + } + + bool isSet() const { return bytecodeIndex != std::numeric_limits::max(); } + + unsigned bytecodeIndexForValueProfile() const + { + return bytecodeIndex + valueProfileOffset; + } + + // The inline depth is the depth of the inline stack, so 1 = not inlined, + // 2 = inlined one deep, etc. + unsigned inlineDepth() const; + + // If the code origin corresponds to inlined code, gives you the heap object that + // would have owned the code if it had not been inlined. Otherwise returns 0. + ExecutableBase* codeOriginOwner() const; + + static unsigned inlineDepthForCallFrame(InlineCallFrame*); + + bool operator==(const CodeOrigin& other) const; + + bool operator!=(const CodeOrigin& other) const { return !(*this == other); } + +#ifndef NDEBUG + // Get the inline stack. This is slow, and is intended for debugging only. + Vector inlineStack() const; +#endif +}; + +struct InlineCallFrame { + Vector arguments; + WriteBarrier executable; + WriteBarrier callee; + CodeOrigin caller; + unsigned stackOffset : 31; + bool isCall : 1; +}; + +struct CodeOriginAtCallReturnOffset { + CodeOrigin codeOrigin; + unsigned callReturnOffset; +}; + +inline unsigned CodeOrigin::inlineDepthForCallFrame(InlineCallFrame* inlineCallFrame) +{ + unsigned result = 1; + for (InlineCallFrame* current = inlineCallFrame; current; current = current->caller.inlineCallFrame) + result++; + return result; +} + +inline unsigned CodeOrigin::inlineDepth() const +{ + return inlineDepthForCallFrame(inlineCallFrame); +} + +inline bool CodeOrigin::operator==(const CodeOrigin& other) const +{ + return bytecodeIndex == other.bytecodeIndex + && inlineCallFrame == other.inlineCallFrame; +} + +#ifndef NDEBUG +// Get the inline stack. This is slow, and is intended for debugging only. +inline Vector CodeOrigin::inlineStack() const +{ + Vector result(inlineDepth()); + result.last() = *this; + unsigned index = result.size() - 2; + for (InlineCallFrame* current = inlineCallFrame; current; current = current->caller.inlineCallFrame) + result[index--] = current->caller; + return result; +} +#endif + +inline unsigned getCallReturnOffsetForCodeOrigin(CodeOriginAtCallReturnOffset* data) +{ + return data->callReturnOffset; +} + +inline ExecutableBase* CodeOrigin::codeOriginOwner() const +{ + if (!inlineCallFrame) + return 0; + return inlineCallFrame->executable.get(); +} + +} // namespace JSC + +#endif // CodeOrigin_h + diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CodeType.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CodeType.h new file mode 100644 index 000000000..03485e564 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CodeType.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2012 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 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 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 CodeType_h +#define CodeType_h + +namespace JSC { + +enum CodeType { GlobalCode, EvalCode, FunctionCode }; + +} + +#endif // CodeType_h + diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Collator.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Collator.h new file mode 100644 index 000000000..7994ff8e5 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Collator.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 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. + * 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 WTF_Collator_h +#define WTF_Collator_h + +#include +#include +#include +#include + +#if USE(ICU_UNICODE) && !UCONFIG_NO_COLLATION +struct UCollator; +#endif + +namespace WTF { + + class Collator { + WTF_MAKE_NONCOPYABLE(Collator); WTF_MAKE_FAST_ALLOCATED; + public: + enum Result { Equal = 0, Greater = 1, Less = -1 }; + + WTF_EXPORT_PRIVATE Collator(const char* locale); // Parsing is lenient; e.g. language identifiers (such as "en-US") are accepted, too. + WTF_EXPORT_PRIVATE ~Collator(); + WTF_EXPORT_PRIVATE void setOrderLowerFirst(bool); + + static PassOwnPtr userDefault(); + + WTF_EXPORT_PRIVATE Result collate(const ::UChar*, size_t, const ::UChar*, size_t) const; + + private: +#if USE(ICU_UNICODE) && !UCONFIG_NO_COLLATION + void createCollator() const; + void releaseCollator(); + mutable UCollator* m_collator; +#endif + char* m_locale; + bool m_lowerFirst; + }; +} + +using WTF::Collator; + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CommonIdentifiers.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CommonIdentifiers.h new file mode 100644 index 000000000..ce1173063 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CommonIdentifiers.h @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2003, 2007, 2009 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef CommonIdentifiers_h +#define CommonIdentifiers_h + +#include "Identifier.h" +#include + +// MarkedArgumentBuffer of property names, passed to a macro so we can do set them up various +// ways without repeating the list. +#define JSC_COMMON_IDENTIFIERS_EACH_PROPERTY_NAME(macro) \ + macro(__defineGetter__) \ + macro(__defineSetter__) \ + macro(__lookupGetter__) \ + macro(__lookupSetter__) \ + macro(apply) \ + macro(arguments) \ + macro(bind) \ + macro(call) \ + macro(callee) \ + macro(caller) \ + macro(compile) \ + macro(configurable) \ + macro(constructor) \ + macro(enumerable) \ + macro(eval) \ + macro(exec) \ + macro(fromCharCode) \ + macro(global) \ + macro(get) \ + macro(hasOwnProperty) \ + macro(ignoreCase) \ + macro(index) \ + macro(input) \ + macro(isArray) \ + macro(isPrototypeOf) \ + macro(stack) \ + macro(length) \ + macro(message) \ + macro(multiline) \ + macro(name) \ + macro(now) \ + macro(parse) \ + macro(propertyIsEnumerable) \ + macro(prototype) \ + macro(set) \ + macro(source) \ + macro(test) \ + macro(toExponential) \ + macro(toFixed) \ + macro(toISOString) \ + macro(toJSON) \ + macro(toLocaleString) \ + macro(toPrecision) \ + macro(toString) \ + macro(UTC) \ + macro(value) \ + macro(valueOf) \ + macro(writable) \ + macro(displayName) \ + macro(undefined) + +#define JSC_COMMON_IDENTIFIERS_EACH_KEYWORD(macro) \ + macro(null) \ + macro(true) \ + macro(false) \ + macro(break) \ + macro(case) \ + macro(catch) \ + macro(const) \ + macro(default) \ + macro(finally) \ + macro(for) \ + macro(instanceof) \ + macro(new) \ + macro(var) \ + macro(continue) \ + macro(function) \ + macro(return) \ + macro(void) \ + macro(delete) \ + macro(if) \ + macro(this) \ + macro(do) \ + macro(while) \ + macro(else) \ + macro(in) \ + macro(switch) \ + macro(throw) \ + macro(try) \ + macro(typeof) \ + macro(with) \ + macro(debugger) \ + macro(class) \ + macro(enum) \ + macro(export) \ + macro(extends) \ + macro(import) \ + macro(super) \ + macro(implements) \ + macro(interface) \ + macro(let) \ + macro(package) \ + macro(private) \ + macro(protected) \ + macro(public) \ + macro(static) \ + macro(yield) + +namespace JSC { + + class CommonIdentifiers { + WTF_MAKE_NONCOPYABLE(CommonIdentifiers); WTF_MAKE_FAST_ALLOCATED; + private: + CommonIdentifiers(JSGlobalData*); + friend class JSGlobalData; + + public: + const Identifier nullIdentifier; + const Identifier emptyIdentifier; + const Identifier underscoreProto; + const Identifier thisIdentifier; + const Identifier useStrictIdentifier; + + +#define JSC_IDENTIFIER_DECLARE_KEYWORD_NAME_GLOBAL(name) const Identifier name##Keyword; + JSC_COMMON_IDENTIFIERS_EACH_KEYWORD(JSC_IDENTIFIER_DECLARE_KEYWORD_NAME_GLOBAL) +#undef JSC_IDENTIFIER_DECLARE_KEYWORD_NAME_GLOBAL + +#define JSC_IDENTIFIER_DECLARE_PROPERTY_NAME_GLOBAL(name) const Identifier name; + JSC_COMMON_IDENTIFIERS_EACH_PROPERTY_NAME(JSC_IDENTIFIER_DECLARE_PROPERTY_NAME_GLOBAL) +#undef JSC_IDENTIFIER_DECLARE_PROPERTY_NAME_GLOBAL + }; + +} // namespace JSC + +#endif // CommonIdentifiers_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CommonSlowPaths.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CommonSlowPaths.h new file mode 100644 index 000000000..86c4bd5c2 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CommonSlowPaths.h @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2011, 2012 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 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 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 CommonSlowPaths_h +#define CommonSlowPaths_h + +#include "CodeBlock.h" +#include "ExceptionHelpers.h" +#include "JSArray.h" + +namespace JSC { + +// The purpose of this namespace is to include slow paths that are shared +// between the interpreter and baseline JIT. They are written to be agnostic +// with respect to the slow-path calling convention, but they do rely on the +// JS code being executed more-or-less directly from bytecode (so the call +// frame layout is unmodified, making it potentially awkward to use these +// from any optimizing JIT, like the DFG). + +namespace CommonSlowPaths { + +ALWAYS_INLINE bool opInstanceOfSlow(ExecState* exec, JSValue value, JSValue baseVal, JSValue proto) +{ + ASSERT(!value.isCell() || !baseVal.isCell() || !proto.isCell() + || !value.isObject() || !baseVal.isObject() || !proto.isObject() + || !asObject(baseVal)->structure()->typeInfo().implementsDefaultHasInstance()); + + + // ECMA-262 15.3.5.3: + // Throw an exception either if baseVal is not an object, or if it does not implement 'HasInstance' (i.e. is a function). + TypeInfo typeInfo(UnspecifiedType); + if (!baseVal.isObject() || !(typeInfo = asObject(baseVal)->structure()->typeInfo()).implementsHasInstance()) { + exec->globalData().exception = createInvalidParamError(exec, "instanceof", baseVal); + return false; + } + ASSERT(typeInfo.type() != UnspecifiedType); + + if (!typeInfo.overridesHasInstance() && !value.isObject()) + return false; + + return asObject(baseVal)->methodTable()->hasInstance(asObject(baseVal), exec, value, proto); +} + +inline bool opIn(ExecState* exec, JSValue propName, JSValue baseVal) +{ + if (!baseVal.isObject()) { + exec->globalData().exception = createInvalidParamError(exec, "in", baseVal); + return false; + } + + JSObject* baseObj = asObject(baseVal); + + uint32_t i; + if (propName.getUInt32(i)) + return baseObj->hasProperty(exec, i); + + Identifier property(exec, propName.toString(exec)->value(exec)); + if (exec->globalData().exception) + return false; + return baseObj->hasProperty(exec, property); +} + +ALWAYS_INLINE JSValue opResolve(ExecState* exec, Identifier& ident) +{ + ScopeChainNode* scopeChain = exec->scopeChain(); + + ScopeChainIterator iter = scopeChain->begin(); + ScopeChainIterator end = scopeChain->end(); + ASSERT(iter != end); + + do { + JSObject* o = iter->get(); + PropertySlot slot(o); + if (o->getPropertySlot(exec, ident, slot)) + return slot.getValue(exec, ident); + } while (++iter != end); + + exec->globalData().exception = createUndefinedVariableError(exec, ident); + return JSValue(); +} + +ALWAYS_INLINE JSValue opResolveSkip(ExecState* exec, Identifier& ident, int skip) +{ + ScopeChainNode* scopeChain = exec->scopeChain(); + + ScopeChainIterator iter = scopeChain->begin(); + ScopeChainIterator end = scopeChain->end(); + ASSERT(iter != end); + CodeBlock* codeBlock = exec->codeBlock(); + bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain(); + ASSERT(skip || !checkTopLevel); + if (checkTopLevel && skip--) { + if (exec->uncheckedR(codeBlock->activationRegister()).jsValue()) + ++iter; + } + while (skip--) { + ++iter; + ASSERT(iter != end); + } + do { + JSObject* o = iter->get(); + PropertySlot slot(o); + if (o->getPropertySlot(exec, ident, slot)) + return slot.getValue(exec, ident); + } while (++iter != end); + + exec->globalData().exception = createUndefinedVariableError(exec, ident); + return JSValue(); +} + +ALWAYS_INLINE JSValue opResolveWithBase(ExecState* exec, Identifier& ident, Register& baseSlot) +{ + ScopeChainNode* scopeChain = exec->scopeChain(); + + ScopeChainIterator iter = scopeChain->begin(); + ScopeChainIterator end = scopeChain->end(); + + // FIXME: add scopeDepthIsZero optimization + + ASSERT(iter != end); + + JSObject* base; + do { + base = iter->get(); + PropertySlot slot(base); + if (base->getPropertySlot(exec, ident, slot)) { + JSValue result = slot.getValue(exec, ident); + if (exec->globalData().exception) + return JSValue(); + + baseSlot = JSValue(base); + return result; + } + ++iter; + } while (iter != end); + + exec->globalData().exception = createUndefinedVariableError(exec, ident); + return JSValue(); +} + +ALWAYS_INLINE JSValue opResolveWithThis(ExecState* exec, Identifier& ident, Register& baseSlot) +{ + ScopeChainNode* scopeChain = exec->scopeChain(); + + ScopeChainIterator iter = scopeChain->begin(); + ScopeChainIterator end = scopeChain->end(); + + // FIXME: add scopeDepthIsZero optimization + + ASSERT(iter != end); + + JSObject* base; + do { + base = iter->get(); + ++iter; + PropertySlot slot(base); + if (base->getPropertySlot(exec, ident, slot)) { + JSValue result = slot.getValue(exec, ident); + if (exec->globalData().exception) + return JSValue(); + + // All entries on the scope chain should be EnvironmentRecords (activations etc), + // other then 'with' object, which are directly referenced from the scope chain, + // and the global object. If we hit either an EnvironmentRecord or a global + // object at the end of the scope chain, this is undefined. If we hit a non- + // EnvironmentRecord within the scope chain, pass the base as the this value. + if (iter == end || base->structure()->typeInfo().isEnvironmentRecord()) + baseSlot = jsUndefined(); + else + baseSlot = JSValue(base); + return result; + } + } while (iter != end); + + exec->globalData().exception = createUndefinedVariableError(exec, ident); + return JSValue(); +} + +} } // namespace JSC::CommonSlowPaths + +#endif // CommonSlowPaths_h + diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CompactJITCodeMap.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CompactJITCodeMap.h new file mode 100644 index 000000000..5b92a8961 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CompactJITCodeMap.h @@ -0,0 +1,298 @@ +/* + * Copyright (C) 2011 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 CompactJITCodeMap_h +#define CompactJITCodeMap_h + +#include +#include +#include +#include +#include +#include +#include + +namespace JSC { + +// Gives you a compressed map between between bytecode indices and machine code +// entry points. The compression simply tries to use either 1, 2, or 4 bytes for +// any given offset. The largest offset that can be stored is 2^30. + +// Example use: +// +// CompactJITCodeMap::Encoder encoder(map); +// encoder.append(a, b); +// encoder.append(c, d); // preconditions: c >= a, d >= b +// OwnPtr map = encoder.finish(); +// +// At some later time: +// +// Vector decoded; +// map->decode(decoded); + +struct BytecodeAndMachineOffset { + BytecodeAndMachineOffset() { } + + BytecodeAndMachineOffset(unsigned bytecodeIndex, unsigned machineCodeOffset) + : m_bytecodeIndex(bytecodeIndex) + , m_machineCodeOffset(machineCodeOffset) + { + } + + unsigned m_bytecodeIndex; + unsigned m_machineCodeOffset; + + static inline unsigned getBytecodeIndex(BytecodeAndMachineOffset* mapping) + { + return mapping->m_bytecodeIndex; + } + + static inline unsigned getMachineCodeOffset(BytecodeAndMachineOffset* mapping) + { + return mapping->m_machineCodeOffset; + } +}; + +class CompactJITCodeMap { + WTF_MAKE_FAST_ALLOCATED; +public: + ~CompactJITCodeMap() + { + if (m_buffer) + fastFree(m_buffer); + } + + unsigned numberOfEntries() const + { + return m_numberOfEntries; + } + + void decode(Vector& result) const; + +private: + CompactJITCodeMap(uint8_t* buffer, unsigned size, unsigned numberOfEntries) + : m_buffer(buffer) +#if !ASSERT_DISABLED + , m_size(size) +#endif + , m_numberOfEntries(numberOfEntries) + { + UNUSED_PARAM(size); + } + + uint8_t at(unsigned index) const + { + ASSERT(index < m_size); + return m_buffer[index]; + } + + unsigned decodeNumber(unsigned& index) const + { + uint8_t headValue = at(index++); + if (!(headValue & 128)) + return headValue; + if (!(headValue & 64)) + return (static_cast(headValue & ~128) << 8) | at(index++); + unsigned second = at(index++); + unsigned third = at(index++); + unsigned fourth = at(index++); + return (static_cast(headValue & ~(128 + 64)) << 24) | (second << 16) | (third << 8) | fourth; + } + + uint8_t* m_buffer; +#if !ASSERT_DISABLED + unsigned m_size; +#endif + unsigned m_numberOfEntries; + +public: + class Encoder { + WTF_MAKE_NONCOPYABLE(Encoder); + public: + Encoder(); + ~Encoder(); + + void ensureCapacityFor(unsigned numberOfEntriesToAdd); + void append(unsigned bytecodeIndex, unsigned machineCodeOffset); + PassOwnPtr finish(); + + private: + void appendByte(uint8_t value); + void encodeNumber(uint32_t value); + + uint8_t* m_buffer; + unsigned m_size; + unsigned m_capacity; + unsigned m_numberOfEntries; + + unsigned m_previousBytecodeIndex; + unsigned m_previousMachineCodeOffset; + }; + + class Decoder { + WTF_MAKE_NONCOPYABLE(Decoder); + public: + Decoder(const CompactJITCodeMap*); + + unsigned numberOfEntriesRemaining() const; + void read(unsigned& bytecodeIndex, unsigned& machineCodeOffset); + + private: + const CompactJITCodeMap* m_jitCodeMap; + unsigned m_previousBytecodeIndex; + unsigned m_previousMachineCodeOffset; + unsigned m_numberOfEntriesRemaining; + unsigned m_bufferIndex; + }; + +private: + friend class Encoder; + friend class Decoder; +}; + +inline void CompactJITCodeMap::decode(Vector& result) const +{ + Decoder decoder(this); + result.resize(decoder.numberOfEntriesRemaining()); + for (unsigned i = 0; i < result.size(); ++i) + decoder.read(result[i].m_bytecodeIndex, result[i].m_machineCodeOffset); + + ASSERT(!decoder.numberOfEntriesRemaining()); +} + +inline CompactJITCodeMap::Encoder::Encoder() + : m_buffer(0) + , m_size(0) + , m_capacity(0) + , m_numberOfEntries(0) + , m_previousBytecodeIndex(0) + , m_previousMachineCodeOffset(0) +{ +} + +inline CompactJITCodeMap::Encoder::~Encoder() +{ + if (m_buffer) + fastFree(m_buffer); +} + +inline void CompactJITCodeMap::Encoder::append(unsigned bytecodeIndex, unsigned machineCodeOffset) +{ + ASSERT(bytecodeIndex >= m_previousBytecodeIndex); + ASSERT(machineCodeOffset >= m_previousMachineCodeOffset); + ensureCapacityFor(1); + encodeNumber(bytecodeIndex - m_previousBytecodeIndex); + encodeNumber(machineCodeOffset - m_previousMachineCodeOffset); + m_previousBytecodeIndex = bytecodeIndex; + m_previousMachineCodeOffset = machineCodeOffset; + m_numberOfEntries++; +} + +inline PassOwnPtr CompactJITCodeMap::Encoder::finish() +{ + m_capacity = m_size; + m_buffer = static_cast(fastRealloc(m_buffer, m_capacity)); + OwnPtr result = adoptPtr(new CompactJITCodeMap(m_buffer, m_size, m_numberOfEntries)); + m_buffer = 0; + m_size = 0; + m_capacity = 0; + m_numberOfEntries = 0; + m_previousBytecodeIndex = 0; + m_previousMachineCodeOffset = 0; + return result.release(); +} + +inline void CompactJITCodeMap::Encoder::appendByte(uint8_t value) +{ + ASSERT(m_size + 1 <= m_capacity); + m_buffer[m_size++] = value; +} + +inline void CompactJITCodeMap::Encoder::encodeNumber(uint32_t value) +{ + ASSERT(m_size + 4 <= m_capacity); + ASSERT(value < (1 << 30)); + if (value <= 127) { + uint8_t headValue = static_cast(value); + ASSERT(!(headValue & 128)); + appendByte(headValue); + } else if (value <= 16383) { + uint8_t headValue = static_cast(value >> 8); + ASSERT(!(headValue & 128)); + ASSERT(!(headValue & 64)); + appendByte(headValue | 128); + appendByte(static_cast(value)); + } else { + uint8_t headValue = static_cast(value >> 24); + ASSERT(!(headValue & 128)); + ASSERT(!(headValue & 64)); + appendByte(headValue | 128 | 64); + appendByte(static_cast(value >> 16)); + appendByte(static_cast(value >> 8)); + appendByte(static_cast(value)); + } +} + +inline void CompactJITCodeMap::Encoder::ensureCapacityFor(unsigned numberOfEntriesToAdd) +{ + unsigned capacityNeeded = m_size + numberOfEntriesToAdd * 2 * 4; + if (capacityNeeded > m_capacity) { + m_capacity = capacityNeeded * 2; + m_buffer = static_cast(fastRealloc(m_buffer, m_capacity)); + } +} + +inline CompactJITCodeMap::Decoder::Decoder(const CompactJITCodeMap* jitCodeMap) + : m_jitCodeMap(jitCodeMap) + , m_previousBytecodeIndex(0) + , m_previousMachineCodeOffset(0) + , m_numberOfEntriesRemaining(jitCodeMap->m_numberOfEntries) + , m_bufferIndex(0) +{ +} + +inline unsigned CompactJITCodeMap::Decoder::numberOfEntriesRemaining() const +{ + ASSERT(m_numberOfEntriesRemaining || m_bufferIndex == m_jitCodeMap->m_size); + return m_numberOfEntriesRemaining; +} + +inline void CompactJITCodeMap::Decoder::read(unsigned& bytecodeIndex, unsigned& machineCodeOffset) +{ + ASSERT(numberOfEntriesRemaining()); + + m_previousBytecodeIndex += m_jitCodeMap->decodeNumber(m_bufferIndex); + m_previousMachineCodeOffset += m_jitCodeMap->decodeNumber(m_bufferIndex); + bytecodeIndex = m_previousBytecodeIndex; + machineCodeOffset = m_previousMachineCodeOffset; + m_numberOfEntriesRemaining--; +} + +} // namespace JSC + +#endif // CompactJITCodeMap_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Compiler.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Compiler.h new file mode 100644 index 000000000..96ad6e40e --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Compiler.h @@ -0,0 +1,252 @@ +/* + * Copyright (C) 2011, 2012 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 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 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 WTF_Compiler_h +#define WTF_Compiler_h + +/* COMPILER() - the compiler being used to build the project */ +#define COMPILER(WTF_FEATURE) (defined WTF_COMPILER_##WTF_FEATURE && WTF_COMPILER_##WTF_FEATURE) + +/* COMPILER_SUPPORTS() - whether the compiler being used to build the project supports the given feature. */ +#define COMPILER_SUPPORTS(WTF_COMPILER_FEATURE) (defined WTF_COMPILER_SUPPORTS_##WTF_COMPILER_FEATURE && WTF_COMPILER_SUPPORTS_##WTF_COMPILER_FEATURE) + +/* ==== COMPILER() - the compiler being used to build the project ==== */ + +/* COMPILER(CLANG) - Clang */ +#if defined(__clang__) +#define WTF_COMPILER_CLANG 1 + +#ifndef __has_extension +#define __has_extension __has_feature /* Compatibility with older versions of clang */ +#endif + +/* Specific compiler features */ +#define WTF_COMPILER_SUPPORTS_CXX_VARIADIC_TEMPLATES __has_feature(cxx_variadic_templates) +#define WTF_COMPILER_SUPPORTS_CXX_RVALUE_REFERENCES __has_feature(cxx_rvalue_references) +#define WTF_COMPILER_SUPPORTS_CXX_DELETED_FUNCTIONS __has_feature(cxx_deleted_functions) +#define WTF_COMPILER_SUPPORTS_CXX_NULLPTR __has_feature(cxx_nullptr) +#define WTF_COMPILER_SUPPORTS_BLOCKS __has_feature(blocks) + +#endif + +/* COMPILER(MSVC) - Microsoft Visual C++ */ +/* COMPILER(MSVC7_OR_LOWER) - Microsoft Visual C++ 2003 or lower*/ +/* COMPILER(MSVC9_OR_LOWER) - Microsoft Visual C++ 2008 or lower*/ +#if defined(_MSC_VER) +#define WTF_COMPILER_MSVC 1 +#if _MSC_VER < 1400 +#define WTF_COMPILER_MSVC7_OR_LOWER 1 +#elif _MSC_VER < 1600 +#define WTF_COMPILER_MSVC9_OR_LOWER 1 +#endif + +/* Specific compiler features */ +#if _MSC_VER >= 1600 +#define WTF_COMPILER_SUPPORTS_CXX_NULLPTR 1 +#endif + +#endif + +/* COMPILER(RVCT) - ARM RealView Compilation Tools */ +/* COMPILER(RVCT4_OR_GREATER) - ARM RealView Compilation Tools 4.0 or greater */ +#if defined(__CC_ARM) || defined(__ARMCC__) +#define WTF_COMPILER_RVCT 1 +#define RVCT_VERSION_AT_LEAST(major, minor, patch, build) (__ARMCC_VERSION >= (major * 100000 + minor * 10000 + patch * 1000 + build)) +#else +/* Define this for !RVCT compilers, just so we can write things like RVCT_VERSION_AT_LEAST(3, 0, 0, 0). */ +#define RVCT_VERSION_AT_LEAST(major, minor, patch, build) 0 +#endif + +/* COMPILER(GCCE) - GNU Compiler Collection for Embedded */ +#if defined(__GCCE__) +#define WTF_COMPILER_GCCE 1 +#define GCCE_VERSION (__GCCE__ * 10000 + __GCCE_MINOR__ * 100 + __GCCE_PATCHLEVEL__) +#define GCCE_VERSION_AT_LEAST(major, minor, patch) (GCCE_VERSION >= (major * 10000 + minor * 100 + patch)) +#endif + +/* COMPILER(GCC) - GNU Compiler Collection */ +/* --gnu option of the RVCT compiler also defines __GNUC__ */ +#if defined(__GNUC__) && !COMPILER(RVCT) +#define WTF_COMPILER_GCC 1 +#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) +#define GCC_VERSION_AT_LEAST(major, minor, patch) (GCC_VERSION >= (major * 10000 + minor * 100 + patch)) + +/* Specific compiler features */ +#if !COMPILER(CLANG) && GCC_VERSION_AT_LEAST(4, 6, 0) && defined(__GXX_EXPERIMENTAL_CXX0X__) +#define WTF_COMPILER_SUPPORTS_CXX_NULLPTR 1 +#endif + +#else +/* Define this for !GCC compilers, just so we can write things like GCC_VERSION_AT_LEAST(4, 1, 0). */ +#define GCC_VERSION_AT_LEAST(major, minor, patch) 0 +#endif + +/* COMPILER(MINGW) - MinGW GCC */ +/* COMPILER(MINGW64) - mingw-w64 GCC - only used as additional check to exclude mingw.org specific functions */ +#if defined(__MINGW32__) +#define WTF_COMPILER_MINGW 1 +#include <_mingw.h> /* private MinGW header */ + #if defined(__MINGW64_VERSION_MAJOR) /* best way to check for mingw-w64 vs mingw.org */ + #define WTF_COMPILER_MINGW64 1 + #endif /* __MINGW64_VERSION_MAJOR */ +#endif /* __MINGW32__ */ + +/* COMPILER(INTEL) - Intel C++ Compiler */ +#if defined(__INTEL_COMPILER) +#define WTF_COMPILER_INTEL 1 +#endif + +/* COMPILER(SUNCC) */ +#if defined(__SUNPRO_CC) || defined(__SUNPRO_C) +#define WTF_COMPILER_SUNCC 1 +#endif + +/* ==== Compiler features ==== */ + + +/* ALWAYS_INLINE */ + +#ifndef ALWAYS_INLINE +#if COMPILER(GCC) && defined(NDEBUG) && !COMPILER(MINGW) +#define ALWAYS_INLINE inline __attribute__((__always_inline__)) +#elif (COMPILER(MSVC) || COMPILER(RVCT)) && defined(NDEBUG) +#define ALWAYS_INLINE __forceinline +#else +#define ALWAYS_INLINE inline +#endif +#endif + + +/* NEVER_INLINE */ + +#ifndef NEVER_INLINE +#if COMPILER(GCC) +#define NEVER_INLINE __attribute__((__noinline__)) +#elif COMPILER(RVCT) +#define NEVER_INLINE __declspec(noinline) +#else +#define NEVER_INLINE +#endif +#endif + + +/* UNLIKELY */ + +#ifndef UNLIKELY +#if COMPILER(GCC) || (RVCT_VERSION_AT_LEAST(3, 0, 0, 0) && defined(__GNUC__)) +#define UNLIKELY(x) __builtin_expect((x), 0) +#else +#define UNLIKELY(x) (x) +#endif +#endif + + +/* LIKELY */ + +#ifndef LIKELY +#if COMPILER(GCC) || (RVCT_VERSION_AT_LEAST(3, 0, 0, 0) && defined(__GNUC__)) +#define LIKELY(x) __builtin_expect((x), 1) +#else +#define LIKELY(x) (x) +#endif +#endif + + +/* NO_RETURN */ + + +#ifndef NO_RETURN +#if COMPILER(GCC) +#define NO_RETURN __attribute((__noreturn__)) +#elif COMPILER(MSVC) || COMPILER(RVCT) +#define NO_RETURN __declspec(noreturn) +#else +#define NO_RETURN +#endif +#endif + + +/* NO_RETURN_WITH_VALUE */ + +#ifndef NO_RETURN_WITH_VALUE +#if !COMPILER(MSVC) +#define NO_RETURN_WITH_VALUE NO_RETURN +#else +#define NO_RETURN_WITH_VALUE +#endif +#endif + + +/* WARN_UNUSED_RETURN */ + +#if COMPILER(GCC) +#define WARN_UNUSED_RETURN __attribute__ ((warn_unused_result)) +#else +#define WARN_UNUSED_RETURN +#endif + +/* OVERRIDE */ + +#ifndef OVERRIDE +#if COMPILER(CLANG) +#if __has_extension(cxx_override_control) +#define OVERRIDE override +#endif +#elif COMPILER(MSVC) +#define OVERRIDE override +#endif +#endif + +#ifndef OVERRIDE +#define OVERRIDE +#endif + +/* FINAL */ + +#ifndef FINAL +#if COMPILER(CLANG) +#if __has_extension(cxx_override_control) +#define FINAL final +#endif +#elif COMPILER(MSVC) +#define FINAL sealed +#endif +#endif + +#ifndef FINAL +#define FINAL +#endif + +/* OBJC_CLASS */ + +#ifndef OBJC_CLASS +#ifdef __OBJC__ +#define OBJC_CLASS @class +#else +#define OBJC_CLASS class +#endif +#endif + +#endif /* WTF_Compiler_h */ diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Completion.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Completion.h new file mode 100644 index 000000000..3d3b86fe4 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Completion.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) + * Copyright (C) 2001 Peter Kelly (pmk@post.com) + * Copyright (C) 2003, 2007 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef Completion_h +#define Completion_h + +#include "JSValue.h" + +namespace JSC { + + class ExecState; + class ScopeChainNode; + class SourceCode; + + JS_EXPORT_PRIVATE bool checkSyntax(ExecState*, const SourceCode&, JSValue* exception = 0); + JS_EXPORT_PRIVATE JSValue evaluate(ExecState*, ScopeChainNode*, const SourceCode&, JSValue thisValue = JSValue(), JSValue* exception = 0); + +} // namespace JSC + +#endif // Completion_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Complex.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Complex.h new file mode 100644 index 000000000..40fe56a7b --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Complex.h @@ -0,0 +1,49 @@ +/* + * 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: + * + * 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 WTF_Complex_h +#define WTF_Complex_h + +#include +#include + +namespace WTF { + +typedef std::complex Complex; + +inline Complex complexFromMagnitudePhase(double magnitude, double phase) +{ + return Complex(magnitude * cos(phase), magnitude * sin(phase)); +} + +} // namespace WTF + +using WTF::Complex; +using WTF::complexFromMagnitudePhase; + +#endif // WTF_Complex_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ConservativeRoots.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ConservativeRoots.h new file mode 100644 index 000000000..40b0996d0 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ConservativeRoots.h @@ -0,0 +1,82 @@ +/* + * 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 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 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 ConservativeRoots_h +#define ConservativeRoots_h + +#include "Heap.h" +#include +#include + +namespace JSC { + +class JSCell; +class DFGCodeBlocks; +class Heap; + +class ConservativeRoots { +public: + ConservativeRoots(const MarkedBlockSet*, BumpSpace*); + ~ConservativeRoots(); + + void add(void* begin, void* end); + void add(void* begin, void* end, DFGCodeBlocks&); + + size_t size(); + JSCell** roots(); + +private: + static const size_t inlineCapacity = 128; + static const size_t nonInlineCapacity = 8192 / sizeof(JSCell*); + + template + void genericAddPointer(void*, TinyBloomFilter, MarkHook&); + + template + void genericAddSpan(void*, void* end, MarkHook&); + + void grow(); + + JSCell** m_roots; + size_t m_size; + size_t m_capacity; + const MarkedBlockSet* m_blocks; + BumpSpace* m_bumpSpace; + JSCell* m_inlineRoots[inlineCapacity]; +}; + +inline size_t ConservativeRoots::size() +{ + return m_size; +} + +inline JSCell** ConservativeRoots::roots() +{ + return m_roots; +} + +} // namespace JSC + +#endif // ConservativeRoots_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ConstructData.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ConstructData.h new file mode 100644 index 000000000..d7a3c73d3 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ConstructData.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 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. + * 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 ConstructData_h +#define ConstructData_h + +#include "CallData.h" +#include "JSValue.h" + +namespace JSC { + + class ArgList; + class ExecState; + class FunctionExecutable; + class JSObject; + class ScopeChainNode; + + enum ConstructType { + ConstructTypeNone, + ConstructTypeHost, + ConstructTypeJS + }; + + union ConstructData { + struct { + NativeFunction function; + } native; + struct { + FunctionExecutable* functionExecutable; + ScopeChainNode* scopeChain; + } js; + }; + + JS_EXPORT_PRIVATE JSObject* construct(ExecState*, JSValue constructor, ConstructType, const ConstructData&, const ArgList&); + +} // namespace JSC + +#endif // ConstructData_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CryptographicallyRandomNumber.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CryptographicallyRandomNumber.h new file mode 100644 index 000000000..2262b6c3b --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CryptographicallyRandomNumber.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * 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 WTF_CryptographicallyRandomNumber_h +#define WTF_CryptographicallyRandomNumber_h + +#include + +namespace WTF { + +#if USE(OS_RANDOMNESS) +WTF_EXPORT_PRIVATE uint32_t cryptographicallyRandomNumber(); +WTF_EXPORT_PRIVATE void cryptographicallyRandomValues(void* buffer, size_t length); +#endif + +} + +#if USE(OS_RANDOMNESS) +using WTF::cryptographicallyRandomNumber; +using WTF::cryptographicallyRandomValues; +#endif + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CurrentTime.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CurrentTime.h new file mode 100644 index 000000000..ee49f8d25 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/CurrentTime.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2008 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 CurrentTime_h +#define CurrentTime_h + +#include + +namespace WTF { + +// Returns the current UTC time in seconds, counted from January 1, 1970. +// Precision varies depending on platform but is usually as good or better +// than a millisecond. +WTF_EXPORT_PRIVATE double currentTime(); + +// Same thing, in milliseconds. +inline double currentTimeMS() +{ + return currentTime() * 1000.0; +} + +inline void getLocalTime(const time_t* localTime, struct tm* localTM) +{ +#if COMPILER(MSVC7_OR_LOWER) || COMPILER(MINGW) || OS(WINCE) + *localTM = *localtime(localTime); +#elif COMPILER(MSVC) + localtime_s(localTM, localTime); +#else + localtime_r(localTime, localTM); +#endif +} + +// Provides a monotonically increasing time in seconds since an arbitrary point in the past. +// On unsupported platforms, this function only guarantees the result will be non-decreasing. +WTF_EXPORT_PRIVATE double monotonicallyIncreasingTime(); + +} // namespace WTF + +using WTF::currentTime; +using WTF::currentTimeMS; +using WTF::getLocalTime; +using WTF::monotonicallyIncreasingTime; + +#endif // CurrentTime_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGAbstractState.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGAbstractState.h new file mode 100644 index 000000000..337a4d0b4 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGAbstractState.h @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2011 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 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 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 DFGAbstractState_h +#define DFGAbstractState_h + +#include + +#if ENABLE(DFG_JIT) + +#include "DFGAbstractValue.h" +#include "DFGGraph.h" +#include "DFGNode.h" +#include + +namespace JSC { + +class CodeBlock; + +namespace DFG { + +struct BasicBlock; + +// This implements the notion of an abstract state for flow-sensitive intraprocedural +// control flow analysis (CFA), with a focus on the elimination of redundant type checks. +// It also implements most of the mechanisms of abstract interpretation that such an +// analysis would use. This class should be used in two idioms: +// +// 1) Performing the CFA. In this case, AbstractState should be run over all basic +// blocks repeatedly until convergence is reached. Convergence is defined by +// endBasicBlock(AbstractState::MergeToSuccessors) returning false for all blocks. +// +// 2) Rematerializing the results of a previously executed CFA. In this case, +// AbstractState should be run over whatever basic block you're interested in up +// to the point of the node at which you'd like to interrogate the known type +// of all other nodes. At this point it's safe to discard the AbstractState entirely, +// call reset(), or to run it to the end of the basic block and call +// endBasicBlock(AbstractState::DontMerge). The latter option is safest because +// it performs some useful integrity checks. +// +// After the CFA is run, the inter-block state is saved at the heads and tails of all +// basic blocks. This allows the intra-block state to be rematerialized by just +// executing the CFA for that block. If you need to know inter-block state only, then +// you only need to examine the BasicBlock::m_valuesAtHead or m_valuesAtTail fields. +// +// Running this analysis involves the following, modulo the inter-block state +// merging and convergence fixpoint: +// +// AbstractState state(codeBlock, graph); +// state.beginBasicBlock(basicBlock); +// bool endReached = true; +// for (NodeIndex idx = basicBlock.begin; idx < basicBlock.end; ++idx) { +// if (!state.execute(idx)) +// break; +// } +// bool result = state.endBasicBlock(); + +class AbstractState { +public: + enum MergeMode { + // Don't merge the state in AbstractState with basic blocks. + DontMerge, + + // Merge the state in AbstractState with the tail of the basic + // block being analyzed. + MergeToTail, + + // Merge the state in AbstractState with the tail of the basic + // block, and with the heads of successor blocks. + MergeToSuccessors + }; + + AbstractState(CodeBlock*, Graph&); + + ~AbstractState(); + + AbstractValue& forNode(NodeIndex nodeIndex) + { + return m_nodes[nodeIndex - m_block->begin]; + } + + // Call this before beginning CFA to initialize the abstract values of + // arguments, and to indicate which blocks should be listed for CFA + // execution. + static void initialize(Graph&); + + // Start abstractly executing the given basic block. Initializes the + // notion of abstract state to what we believe it to be at the head + // of the basic block, according to the basic block's data structures. + // This method also sets cfaShouldRevisit to false. + void beginBasicBlock(BasicBlock*); + + // Finish abstractly executing a basic block. If MergeToTail or + // MergeToSuccessors is passed, then this merges everything we have + // learned about how the state changes during this block's execution into + // the block's data structures. There are three return modes, depending + // on the value of mergeMode: + // + // DontMerge: + // Always returns false. + // + // MergeToTail: + // Returns true if the state of the block at the tail was changed. + // This means that you must call mergeToSuccessors(), and if that + // returns true, then you must revisit (at least) the successor + // blocks. False will always be returned if the block is terminal + // (i.e. ends in Throw or Return, or has a ForceOSRExit inside it). + // + // MergeToSuccessors: + // Returns true if the state of the block at the tail was changed, + // and, if the state at the heads of successors was changed. + // A true return means that you must revisit (at least) the successor + // blocks. This also sets cfaShouldRevisit to true for basic blocks + // that must be visited next. + bool endBasicBlock(MergeMode); + + // Reset the AbstractState. This throws away any results, and at this point + // you can safely call beginBasicBlock() on any basic block. + void reset(); + + // Abstractly executes the given node. The new abstract state is stored into an + // abstract register file stored in *this. Loads of local variables (that span + // basic blocks) interrogate the basic block's notion of the state at the head. + // Stores to local variables are handled in endBasicBlock(). This returns true + // if execution should continue past this node. Notably, it will return true + // for block terminals, so long as those terminals are not Return or variants + // of Throw. + bool execute(NodeIndex); + + // Is the execution state still valid? This will be false if execute() has + // returned false previously. + bool isValid() const { return m_isValid; } + + // Merge the abstract state stored at the first block's tail into the second + // block's head. Returns true if the second block's state changed. If so, + // that block must be abstractly interpreted again. This also sets + // to->cfaShouldRevisit to true, if it returns true, or if to has not been + // visited yet. + static bool merge(BasicBlock* from, BasicBlock* to); + + // Merge the abstract state stored at the block's tail into all of its + // successors. Returns true if any of the successors' states changed. Note + // that this is automatically called in endBasicBlock() if MergeMode is + // MergeToSuccessors. + static bool mergeToSuccessors(Graph&, BasicBlock*); + +#ifndef NDEBUG + void dump(FILE* out); +#endif + +private: + void clobberStructures(NodeIndex); + + bool mergeStateAtTail(AbstractValue& destination, AbstractValue& inVariable, NodeIndex); + + static bool mergeVariableBetweenBlocks(AbstractValue& destination, AbstractValue& source, NodeIndex destinationNodeIndex, NodeIndex sourceNodeIndex); + + CodeBlock* m_codeBlock; + Graph& m_graph; + + Vector m_nodes; + Operands m_variables; + BasicBlock* m_block; + bool m_haveStructures; + + bool m_isValid; +}; + +} } // namespace JSC::DFG + +#endif // ENABLE(DFG_JIT) + +#endif // DFGAbstractState_h + diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGAbstractValue.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGAbstractValue.h new file mode 100644 index 000000000..15bc0d496 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGAbstractValue.h @@ -0,0 +1,488 @@ +/* + * Copyright (C) 2011 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 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 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 DFGAbstractValue_h +#define DFGAbstractValue_h + +#include + +#if ENABLE(DFG_JIT) + +#include "JSCell.h" +#include "PredictedType.h" +#include "StructureSet.h" + +namespace JSC { namespace DFG { + +class StructureAbstractValue { +public: + StructureAbstractValue() + : m_structure(0) + { + } + + StructureAbstractValue(Structure* structure) + : m_structure(structure) + { + } + + StructureAbstractValue(const StructureSet& set) + { + switch (set.size()) { + case 0: + m_structure = 0; + break; + + case 1: + m_structure = set[0]; + break; + + default: + m_structure = topValue(); + break; + } + } + + void clear() + { + m_structure = 0; + } + + void makeTop() + { + m_structure = topValue(); + } + + static StructureAbstractValue top() + { + StructureAbstractValue value; + value.makeTop(); + return value; + } + + void add(Structure* structure) + { + ASSERT(!contains(structure) && !isTop()); + if (m_structure) + makeTop(); + else + m_structure = structure; + } + + bool addAll(const StructureSet& other) + { + if (isTop() || !other.size()) + return false; + if (other.size() > 1) { + makeTop(); + return true; + } + if (!m_structure) { + m_structure = other[0]; + return true; + } + if (m_structure == other[0]) + return false; + makeTop(); + return true; + } + + bool addAll(const StructureAbstractValue& other) + { + if (!other.m_structure) + return false; + if (isTop()) + return false; + if (other.isTop()) { + makeTop(); + return true; + } + if (m_structure) { + if (m_structure == other.m_structure) + return false; + makeTop(); + return true; + } + m_structure = other.m_structure; + return true; + } + + bool contains(Structure* structure) const + { + if (isTop()) + return true; + if (m_structure == structure) + return true; + return false; + } + + bool isSubsetOf(const StructureSet& other) const + { + if (isTop()) + return false; + if (!m_structure) + return true; + return other.contains(m_structure); + } + + bool doesNotContainAnyOtherThan(Structure* structure) const + { + if (isTop()) + return false; + if (!m_structure) + return true; + return m_structure == structure; + } + + bool isSupersetOf(const StructureSet& other) const + { + if (isTop()) + return true; + if (!other.size()) + return true; + if (other.size() > 1) + return false; + return m_structure == other[0]; + } + + bool isSubsetOf(const StructureAbstractValue& other) const + { + if (other.isTop()) + return true; + if (isTop()) + return false; + if (m_structure) { + if (other.m_structure) + return m_structure == other.m_structure; + return false; + } + return true; + } + + bool isSupersetOf(const StructureAbstractValue& other) const + { + return other.isSubsetOf(*this); + } + + void filter(const StructureSet& other) + { + if (!m_structure) + return; + + if (isTop()) { + switch (other.size()) { + case 0: + m_structure = 0; + return; + + case 1: + m_structure = other[0]; + return; + + default: + return; + } + } + + if (other.contains(m_structure)) + return; + + m_structure = 0; + } + + void filter(const StructureAbstractValue& other) + { + if (isTop()) { + m_structure = other.m_structure; + return; + } + if (m_structure == other.m_structure) + return; + if (other.isTop()) + return; + m_structure = 0; + } + + void filter(PredictedType other) + { + if (!(other & PredictCell)) { + clear(); + return; + } + + if (isClearOrTop()) + return; + + if (!(predictionFromStructure(m_structure) & other)) + m_structure = 0; + } + + bool isClear() const + { + return !m_structure; + } + + bool isTop() const { return m_structure == topValue(); } + + bool isClearOrTop() const { return m_structure <= topValue(); } + bool isNeitherClearNorTop() const { return !isClearOrTop(); } + + size_t size() const + { + ASSERT(!isTop()); + return !!m_structure; + } + + Structure* at(size_t i) const + { + ASSERT(!isTop()); + ASSERT(m_structure); + ASSERT_UNUSED(i, !i); + return m_structure; + } + + Structure* operator[](size_t i) const + { + return at(i); + } + + Structure* last() const + { + return at(0); + } + + PredictedType predictionFromStructures() const + { + if (isTop()) + return PredictCell; + if (isClear()) + return PredictNone; + return predictionFromStructure(m_structure); + } + + bool operator==(const StructureAbstractValue& other) const + { + return m_structure == other.m_structure; + } + +#ifndef NDEBUG + void dump(FILE* out) const + { + if (isTop()) { + fprintf(out, "TOP"); + return; + } + + fprintf(out, "["); + if (m_structure) + fprintf(out, "%p", m_structure); + fprintf(out, "]"); + } +#endif + +private: + static Structure* topValue() { return reinterpret_cast(1); } + + // This can only remember one structure at a time. + Structure* m_structure; +}; + +struct AbstractValue { + AbstractValue() + : m_type(PredictNone) + { + } + + void clear() + { + m_type = PredictNone; + m_structure.clear(); + checkConsistency(); + } + + bool isClear() + { + return m_type == PredictNone && m_structure.isClear(); + } + + void makeTop() + { + m_type = PredictTop; + m_structure.makeTop(); + checkConsistency(); + } + + void clobberStructures() + { + if (m_type & PredictCell) + m_structure.makeTop(); + else + ASSERT(m_structure.isClear()); + checkConsistency(); + } + + bool isTop() const + { + return m_type == PredictTop && m_structure.isTop(); + } + + static AbstractValue top() + { + AbstractValue result; + result.makeTop(); + return result; + } + + void set(JSValue value) + { + m_structure.clear(); + if (value.isCell()) + m_structure.add(value.asCell()->structure()); + + m_type = predictionFromValue(value); + + checkConsistency(); + } + + void set(Structure* structure) + { + m_structure.clear(); + m_structure.add(structure); + + m_type = predictionFromStructure(structure); + + checkConsistency(); + } + + void set(PredictedType type) + { + if (type & PredictCell) + m_structure.makeTop(); + else + m_structure.clear(); + m_type = type; + checkConsistency(); + } + + bool operator==(const AbstractValue& other) const + { + return m_type == other.m_type && m_structure == other.m_structure; + } + + bool merge(const AbstractValue& other) + { + bool result = mergePrediction(m_type, other.m_type) | m_structure.addAll(other.m_structure); + checkConsistency(); + return result; + } + + void merge(PredictedType type) + { + mergePrediction(m_type, type); + + if (type & PredictCell) + m_structure.makeTop(); + + checkConsistency(); + } + + void filter(const StructureSet& other) + { + m_type &= other.predictionFromStructures(); + m_structure.filter(other); + + // It's possible that prior to the above two statements we had (Foo, TOP), where + // Foo is a PredictedType that is disjoint with the passed StructureSet. In that + // case, we will now have (None, [someStructure]). In general, we need to make + // sure that new information gleaned from the PredictedType needs to be fed back + // into the information gleaned from the StructureSet. + m_structure.filter(m_type); + checkConsistency(); + } + + void filter(PredictedType type) + { + if (type == PredictTop) + return; + m_type &= type; + + // It's possible that prior to this filter() call we had, say, (Final, TOP), and + // the passed type is Array. At this point we'll have (None, TOP). The best way + // to ensure that the structure filtering does the right thing is to filter on + // the new type (None) rather than the one passed (Array). + m_structure.filter(m_type); + checkConsistency(); + } + + bool validate(JSValue value) const + { + if (isTop()) + return true; + + if (mergePredictions(m_type, predictionFromValue(value)) != m_type) + return false; + + if (m_structure.isTop()) + return true; + + if (value.isCell()) { + ASSERT(m_type & PredictCell); + return m_structure.contains(value.asCell()->structure()); + } + + return true; + } + + void checkConsistency() const + { + if (!(m_type & PredictCell)) + ASSERT(m_structure.isClear()); + + // Note that it's possible for a prediction like (Final, []). This really means that + // the value is bottom and that any code that uses the value is unreachable. But + // we don't want to get pedantic about this as it would only increase the computational + // complexity of the code. + } + +#ifndef NDEBUG + void dump(FILE* out) const + { + fprintf(out, "(%s, ", predictionToString(m_type)); + m_structure.dump(out); + fprintf(out, ")"); + } +#endif + + StructureAbstractValue m_structure; + PredictedType m_type; +}; + +} } // namespace JSC::DFG + +#endif // ENABLE(DFG_JIT) + +#endif // DFGAbstractValue_h + + diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGAssemblyHelpers.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGAssemblyHelpers.h new file mode 100644 index 000000000..e0d817c9f --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGAssemblyHelpers.h @@ -0,0 +1,331 @@ +/* + * Copyright (C) 2011 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 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 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 DFGAssemblyHelpers_h +#define DFGAssemblyHelpers_h + +#include + +#if ENABLE(DFG_JIT) + +#include "CodeBlock.h" +#include "DFGFPRInfo.h" +#include "DFGGPRInfo.h" +#include "DFGNode.h" +#include "JSGlobalData.h" +#include "MacroAssembler.h" + +namespace JSC { namespace DFG { + +#ifndef NDEBUG +typedef void (*V_DFGDebugOperation_EP)(ExecState*, void*); +#endif + +class AssemblyHelpers : public MacroAssembler { +public: + AssemblyHelpers(JSGlobalData* globalData, CodeBlock* codeBlock) + : m_globalData(globalData) + , m_codeBlock(codeBlock) + , m_baselineCodeBlock(codeBlock->baselineVersion()) + { + ASSERT(m_codeBlock); + ASSERT(m_baselineCodeBlock); + ASSERT(!m_baselineCodeBlock->alternative()); + ASSERT(m_baselineCodeBlock->getJITType() == JITCode::BaselineJIT); + } + + CodeBlock* codeBlock() { return m_codeBlock; } + JSGlobalData* globalData() { return m_globalData; } + AssemblerType_T& assembler() { return m_assembler; } + +#if CPU(X86_64) || CPU(X86) + void preserveReturnAddressAfterCall(GPRReg reg) + { + pop(reg); + } + + void restoreReturnAddressBeforeReturn(GPRReg reg) + { + push(reg); + } + + void restoreReturnAddressBeforeReturn(Address address) + { + push(address); + } +#endif // CPU(X86_64) || CPU(X86) + +#if CPU(ARM) + ALWAYS_INLINE void preserveReturnAddressAfterCall(RegisterID reg) + { + move(linkRegister, reg); + } + + ALWAYS_INLINE void restoreReturnAddressBeforeReturn(RegisterID reg) + { + move(reg, linkRegister); + } + + ALWAYS_INLINE void restoreReturnAddressBeforeReturn(Address address) + { + loadPtr(address, linkRegister); + } +#endif + + void emitGetFromCallFrameHeaderPtr(RegisterFile::CallFrameHeaderEntry entry, GPRReg to) + { + loadPtr(Address(GPRInfo::callFrameRegister, entry * sizeof(Register)), to); + } + void emitPutToCallFrameHeader(GPRReg from, RegisterFile::CallFrameHeaderEntry entry) + { + storePtr(from, Address(GPRInfo::callFrameRegister, entry * sizeof(Register))); + } + + void emitPutImmediateToCallFrameHeader(void* value, RegisterFile::CallFrameHeaderEntry entry) + { + storePtr(TrustedImmPtr(value), Address(GPRInfo::callFrameRegister, entry * sizeof(Register))); + } + + Jump branchIfNotCell(GPRReg reg) + { +#if USE(JSVALUE64) + return branchTestPtr(MacroAssembler::NonZero, reg, GPRInfo::tagMaskRegister); +#else + return branch32(MacroAssembler::NotEqual, reg, TrustedImm32(JSValue::CellTag)); +#endif + } + + static Address addressForGlobalVar(GPRReg global, int32_t varNumber) + { + return Address(global, varNumber * sizeof(Register)); + } + + static Address tagForGlobalVar(GPRReg global, int32_t varNumber) + { + return Address(global, varNumber * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)); + } + + static Address payloadForGlobalVar(GPRReg global, int32_t varNumber) + { + return Address(global, varNumber * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)); + } + + static Address addressFor(VirtualRegister virtualRegister) + { + return Address(GPRInfo::callFrameRegister, virtualRegister * sizeof(Register)); + } + + static Address tagFor(VirtualRegister virtualRegister) + { + return Address(GPRInfo::callFrameRegister, virtualRegister * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)); + } + + static Address payloadFor(VirtualRegister virtualRegister) + { + return Address(GPRInfo::callFrameRegister, virtualRegister * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)); + } + + Jump branchIfNotObject(GPRReg structureReg) + { + return branch8(Below, Address(structureReg, Structure::typeInfoTypeOffset()), TrustedImm32(ObjectType)); + } + +#ifndef NDEBUG + // Add a debug call. This call has no effect on JIT code execution state. + void debugCall(V_DFGDebugOperation_EP function, void* argument) + { + EncodedJSValue* buffer = static_cast(m_globalData->scratchBufferForSize(sizeof(EncodedJSValue) * (GPRInfo::numberOfRegisters + FPRInfo::numberOfRegisters))); + + for (unsigned i = 0; i < GPRInfo::numberOfRegisters; ++i) + storePtr(GPRInfo::toRegister(i), buffer + i); + for (unsigned i = 0; i < FPRInfo::numberOfRegisters; ++i) { + move(TrustedImmPtr(buffer + GPRInfo::numberOfRegisters + i), GPRInfo::regT0); + storeDouble(FPRInfo::toRegister(i), GPRInfo::regT0); + } +#if CPU(X86_64) || CPU(ARM_THUMB2) + move(TrustedImmPtr(argument), GPRInfo::argumentGPR1); + move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); +#elif CPU(X86) + poke(GPRInfo::callFrameRegister, 0); + poke(TrustedImmPtr(argument), 1); +#else +#error "DFG JIT not supported on this platform." +#endif + move(TrustedImmPtr(reinterpret_cast(function)), GPRInfo::regT0); + call(GPRInfo::regT0); + for (unsigned i = 0; i < FPRInfo::numberOfRegisters; ++i) { + move(TrustedImmPtr(buffer + GPRInfo::numberOfRegisters + i), GPRInfo::regT0); + loadDouble(GPRInfo::regT0, FPRInfo::toRegister(i)); + } + for (unsigned i = 0; i < GPRInfo::numberOfRegisters; ++i) + loadPtr(buffer + i, GPRInfo::toRegister(i)); + } +#endif + + // These methods JIT generate dynamic, debug-only checks - akin to ASSERTs. +#if DFG_ENABLE(JIT_ASSERT) + void jitAssertIsInt32(GPRReg); + void jitAssertIsJSInt32(GPRReg); + void jitAssertIsJSNumber(GPRReg); + void jitAssertIsJSDouble(GPRReg); + void jitAssertIsCell(GPRReg); +#else + void jitAssertIsInt32(GPRReg) { } + void jitAssertIsJSInt32(GPRReg) { } + void jitAssertIsJSNumber(GPRReg) { } + void jitAssertIsJSDouble(GPRReg) { } + void jitAssertIsCell(GPRReg) { } +#endif + + // These methods convert between doubles, and doubles boxed and JSValues. +#if USE(JSVALUE64) + GPRReg boxDouble(FPRReg fpr, GPRReg gpr) + { + moveDoubleToPtr(fpr, gpr); + subPtr(GPRInfo::tagTypeNumberRegister, gpr); + jitAssertIsJSDouble(gpr); + return gpr; + } + FPRReg unboxDouble(GPRReg gpr, FPRReg fpr) + { + jitAssertIsJSDouble(gpr); + addPtr(GPRInfo::tagTypeNumberRegister, gpr); + movePtrToDouble(gpr, fpr); + return fpr; + } +#endif + +#if USE(JSVALUE32_64) && CPU(X86) + void boxDouble(FPRReg fpr, GPRReg tagGPR, GPRReg payloadGPR) + { + movePackedToInt32(fpr, payloadGPR); + rshiftPacked(TrustedImm32(32), fpr); + movePackedToInt32(fpr, tagGPR); + } + void unboxDouble(GPRReg tagGPR, GPRReg payloadGPR, FPRReg fpr, FPRReg scratchFPR) + { + jitAssertIsJSDouble(tagGPR); + moveInt32ToPacked(payloadGPR, fpr); + moveInt32ToPacked(tagGPR, scratchFPR); + lshiftPacked(TrustedImm32(32), scratchFPR); + orPacked(scratchFPR, fpr); + } +#endif + +#if USE(JSVALUE32_64) && CPU(ARM) + void boxDouble(FPRReg fpr, GPRReg tagGPR, GPRReg payloadGPR) + { + m_assembler.vmov(payloadGPR, tagGPR, fpr); + } + void unboxDouble(GPRReg tagGPR, GPRReg payloadGPR, FPRReg fpr, FPRReg scratchFPR) + { + jitAssertIsJSDouble(tagGPR); + UNUSED_PARAM(scratchFPR); + m_assembler.vmov(fpr, payloadGPR, tagGPR); + } +#endif + + enum ExceptionCheckKind { NormalExceptionCheck, InvertedExceptionCheck }; + Jump emitExceptionCheck(ExceptionCheckKind kind = NormalExceptionCheck) + { +#if USE(JSVALUE64) + return branchTestPtr(kind == NormalExceptionCheck ? NonZero : Zero, AbsoluteAddress(&globalData()->exception)); +#elif USE(JSVALUE32_64) + return branch32(kind == NormalExceptionCheck ? NotEqual : Equal, AbsoluteAddress(reinterpret_cast(&globalData()->exception) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag)); +#endif + } + +#if ENABLE(SAMPLING_COUNTERS) + static void emitCount(MacroAssembler& jit, AbstractSamplingCounter& counter, int32_t increment = 1) + { + jit.add64(TrustedImm32(increment), AbsoluteAddress(counter.addressOfCounter())); + } + void emitCount(AbstractSamplingCounter& counter, int32_t increment = 1) + { + add64(TrustedImm32(increment), AbsoluteAddress(counter.addressOfCounter())); + } +#endif + +#if ENABLE(SAMPLING_FLAGS) + void setSamplingFlag(int32_t); + void clearSamplingFlag(int32_t flag); +#endif + + JSGlobalObject* globalObjectFor(CodeOrigin codeOrigin) + { + return codeBlock()->globalObjectFor(codeOrigin); + } + + JSObject* globalThisObjectFor(CodeOrigin codeOrigin) + { + JSGlobalObject* object = globalObjectFor(codeOrigin); + return object->methodTable()->toThisObject(object, 0); + } + + bool strictModeFor(CodeOrigin codeOrigin) + { + if (!codeOrigin.inlineCallFrame) + return codeBlock()->isStrictMode(); + return codeOrigin.inlineCallFrame->callee->jsExecutable()->isStrictMode(); + } + + static CodeBlock* baselineCodeBlockForOriginAndBaselineCodeBlock(const CodeOrigin& codeOrigin, CodeBlock* baselineCodeBlock) + { + if (codeOrigin.inlineCallFrame) { + ExecutableBase* executable = codeOrigin.inlineCallFrame->executable.get(); + ASSERT(executable->structure()->classInfo() == &FunctionExecutable::s_info); + return static_cast(executable)->baselineCodeBlockFor(codeOrigin.inlineCallFrame->isCall ? CodeForCall : CodeForConstruct); + } + return baselineCodeBlock; + } + + CodeBlock* baselineCodeBlockFor(const CodeOrigin& codeOrigin) + { + return baselineCodeBlockForOriginAndBaselineCodeBlock(codeOrigin, baselineCodeBlock()); + } + + CodeBlock* baselineCodeBlock() + { + return m_baselineCodeBlock; + } + + Vector& decodedCodeMapFor(CodeBlock*); + + static const double twoToThe32; + +protected: + JSGlobalData* m_globalData; + CodeBlock* m_codeBlock; + CodeBlock* m_baselineCodeBlock; + + HashMap > m_decodedCodeMaps; +}; + +} } // namespace JSC::DFG + +#endif // ENABLE(DFG_JIT) + +#endif // DFGAssemblyHelpers_h + diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGBasicBlock.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGBasicBlock.h new file mode 100644 index 000000000..9d464bdc2 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGBasicBlock.h @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2011 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 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 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 DFGBasicBlock_h +#define DFGBasicBlock_h + +#if ENABLE(DFG_JIT) + +#include "DFGAbstractValue.h" +#include "DFGNode.h" +#include "DFGOperands.h" +#include +#include + +namespace JSC { namespace DFG { + +typedef Vector PredecessorList; + +struct BasicBlock { + BasicBlock(unsigned bytecodeBegin, NodeIndex begin, unsigned numArguments, unsigned numLocals) + : bytecodeBegin(bytecodeBegin) + , begin(begin) + , end(NoNode) + , isOSRTarget(false) + , cfaHasVisited(false) + , cfaShouldRevisit(false) +#if !ASSERT_DISABLED + , isLinked(false) +#endif + , isReachable(false) + , variablesAtHead(numArguments, numLocals) + , variablesAtTail(numArguments, numLocals) + , valuesAtHead(numArguments, numLocals) + , valuesAtTail(numArguments, numLocals) + { + } + + void ensureLocals(unsigned newNumLocals) + { + variablesAtHead.ensureLocals(newNumLocals); + variablesAtTail.ensureLocals(newNumLocals); + valuesAtHead.ensureLocals(newNumLocals); + valuesAtTail.ensureLocals(newNumLocals); + } + + // This value is used internally for block linking and OSR entry. It is mostly meaningless + // for other purposes due to inlining. + unsigned bytecodeBegin; + + NodeIndex begin; + NodeIndex end; + bool isOSRTarget; + bool cfaHasVisited; + bool cfaShouldRevisit; +#if !ASSERT_DISABLED + bool isLinked; +#endif + bool isReachable; + + PredecessorList m_predecessors; + + Operands variablesAtHead; + Operands variablesAtTail; + + Operands valuesAtHead; + Operands valuesAtTail; +}; + +struct UnlinkedBlock { + BlockIndex m_blockIndex; + bool m_needsNormalLinking; + bool m_needsEarlyReturnLinking; + + UnlinkedBlock() { } + + explicit UnlinkedBlock(BlockIndex blockIndex) + : m_blockIndex(blockIndex) + , m_needsNormalLinking(true) + , m_needsEarlyReturnLinking(false) + { + } +}; + +} } // namespace JSC::DFG + +#endif // ENABLE(DFG_JIT) + +#endif // DFGBasicBlock_h + diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGByteCodeCache.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGByteCodeCache.h new file mode 100644 index 000000000..fd3b5147f --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGByteCodeCache.h @@ -0,0 +1,194 @@ +/* + * Copyright (C) 2011 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 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 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 DFGByteCodeCache_h +#define DFGByteCodeCache_h + +#include + +#if ENABLE(DFG_JIT) + +#include "CodeBlock.h" +#include "Executable.h" +#include "JSFunction.h" +#include + +namespace JSC { namespace DFG { + +class CodeBlockKey { +public: + CodeBlockKey() + : m_executable(0) + , m_kind(CodeForCall) // CodeForCall = empty value + { + } + + CodeBlockKey(WTF::HashTableDeletedValueType) + : m_executable(0) + , m_kind(CodeForConstruct) // CodeForConstruct = deleted value + { + } + + CodeBlockKey(FunctionExecutable* executable, CodeSpecializationKind kind) + : m_executable(executable) + , m_kind(kind) + { + } + + bool operator==(const CodeBlockKey& other) const + { + return m_executable == other.m_executable + && m_kind == other.m_kind; + } + + unsigned hash() const + { + return WTF::PtrHash::hash(m_executable) ^ static_cast(m_kind); + } + + FunctionExecutable* executable() const { return m_executable; } + CodeSpecializationKind kind() const { return m_kind; } + + bool isHashTableDeletedValue() const + { + return !m_executable && m_kind == CodeForConstruct; + } + +private: + FunctionExecutable* m_executable; + CodeSpecializationKind m_kind; +}; + +struct CodeBlockKeyHash { + static unsigned hash(const CodeBlockKey& key) { return key.hash(); } + static bool equal(const CodeBlockKey& a, const CodeBlockKey& b) { return a == b; } + + static const bool safeToCompareToEmptyOrDeleted = true; +}; + +} } // namespace JSC::DFG + +namespace WTF { + +template struct DefaultHash; +template<> struct DefaultHash { + typedef JSC::DFG::CodeBlockKeyHash Hash; +}; + +template struct HashTraits; +template<> struct HashTraits : SimpleClassHashTraits { }; + +} // namespace WTF + +namespace JSC { namespace DFG { + +struct ByteCodeCacheValue { + FunctionCodeBlock* codeBlock; + bool owned; + bool oldValueOfShouldDiscardBytecode; + + // All uses of this struct initialize everything manually. But gcc isn't + // smart enough to see that, so this constructor is just here to make the + // compiler happy. + ByteCodeCacheValue() + : codeBlock(0) + , owned(false) + , oldValueOfShouldDiscardBytecode(false) + { + } +}; + +template +class ByteCodeCache { +public: + typedef HashMap Map; + + ByteCodeCache() { } + + ~ByteCodeCache() + { + Map::iterator begin = m_map.begin(); + Map::iterator end = m_map.end(); + for (Map::iterator iter = begin; iter != end; ++iter) { + if (!iter->second.codeBlock) + continue; + if (iter->second.owned) { + delete iter->second.codeBlock; + continue; + } + iter->second.codeBlock->m_shouldDiscardBytecode = iter->second.oldValueOfShouldDiscardBytecode; + } + } + + CodeBlock* get(const CodeBlockKey& key, ScopeChainNode* scope) + { + Map::iterator iter = m_map.find(key); + if (iter != m_map.end()) + return iter->second.codeBlock; + + ByteCodeCacheValue value; + + // First see if there is already a parsed code block that still has some + // bytecode in it. + value.codeBlock = key.executable()->codeBlockWithBytecodeFor(key.kind()); + if (value.codeBlock) { + value.owned = false; + value.oldValueOfShouldDiscardBytecode = value.codeBlock->m_shouldDiscardBytecode; + } else { + // Nope, so try to parse one. + JSObject* exception; + value.owned = true; + value.codeBlock = key.executable()->produceCodeBlockFor(scope, OptimizingCompilation, key.kind(), exception).leakPtr(); + } + + // Check if there is any reason to reject this from our cache. If so, then + // poison it. + if (!!value.codeBlock && !filterFunction(value.codeBlock, key.kind())) { + if (value.owned) + delete value.codeBlock; + value.codeBlock = 0; + } + + // If we're about to return a code block, make sure that we're not going + // to be discarding its bytecode if a GC were to happen during DFG + // compilation. That's unlikely, but it's good to thoroughly enjoy this + // kind of paranoia. + if (!!value.codeBlock) + value.codeBlock->m_shouldDiscardBytecode = false; + + m_map.add(key, value); + + return value.codeBlock; + } + +private: + Map m_map; +}; + +} } // namespace JSC::DFG + +#endif // ENABLE(DFG_JIT) + +#endif // DFGByteCodeCache_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGCCallHelpers.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGCCallHelpers.h new file mode 100644 index 000000000..3481f99e8 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGCCallHelpers.h @@ -0,0 +1,548 @@ +/* + * Copyright (C) 2011 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 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 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 DFGCCallHelpers_h +#define DFGCCallHelpers_h + +#include + +#if ENABLE(DFG_JIT) + +#include "DFGAssemblyHelpers.h" +#include "DFGGPRInfo.h" + +namespace JSC { namespace DFG { + +class CCallHelpers : public AssemblyHelpers { +public: + CCallHelpers(JSGlobalData* globalData, CodeBlock* codeBlock) + : AssemblyHelpers(globalData, codeBlock) + { + } + + // These methods used to sort arguments into the correct registers. + // On X86 we use cdecl calling conventions, which pass all arguments on the + // stack. On other architectures we may need to sort values into the + // correct registers. +#if !NUMBER_OF_ARGUMENT_REGISTERS + unsigned m_callArgumentOffset; + void resetCallArguments() { m_callArgumentOffset = 0; } + + // These methods are using internally to implement the callOperation methods. + void addCallArgument(GPRReg value) + { + poke(value, m_callArgumentOffset++); + } + void addCallArgument(TrustedImm32 imm) + { + poke(imm, m_callArgumentOffset++); + } + void addCallArgument(TrustedImmPtr pointer) + { + poke(pointer, m_callArgumentOffset++); + } + void addCallArgument(FPRReg value) + { + storeDouble(value, Address(stackPointerRegister, m_callArgumentOffset * sizeof(void*))); + m_callArgumentOffset += sizeof(double) / sizeof(void*); + } + + ALWAYS_INLINE void setupArguments(FPRReg arg1) + { + resetCallArguments(); + addCallArgument(arg1); + } + + ALWAYS_INLINE void setupArguments(FPRReg arg1, FPRReg arg2) + { + resetCallArguments(); + addCallArgument(arg1); + addCallArgument(arg2); + } + + ALWAYS_INLINE void setupArguments(GPRReg arg1, GPRReg arg2) + { + resetCallArguments(); + addCallArgument(arg1); + addCallArgument(arg2); + } + + ALWAYS_INLINE void setupArgumentsExecState() + { + resetCallArguments(); + addCallArgument(GPRInfo::callFrameRegister); + } + + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1) + { + resetCallArguments(); + addCallArgument(GPRInfo::callFrameRegister); + addCallArgument(arg1); + } + + ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1) + { + resetCallArguments(); + addCallArgument(GPRInfo::callFrameRegister); + addCallArgument(arg1); + } + + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2) + { + resetCallArguments(); + addCallArgument(GPRInfo::callFrameRegister); + addCallArgument(arg1); + addCallArgument(arg2); + } + + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2) + { + resetCallArguments(); + addCallArgument(GPRInfo::callFrameRegister); + addCallArgument(arg1); + addCallArgument(arg2); + } + + ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2) + { + resetCallArguments(); + addCallArgument(GPRInfo::callFrameRegister); + addCallArgument(arg1); + addCallArgument(arg2); + } + + ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, TrustedImmPtr arg2) + { + resetCallArguments(); + addCallArgument(GPRInfo::callFrameRegister); + addCallArgument(arg1); + addCallArgument(arg2); + } + + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3) + { + resetCallArguments(); + addCallArgument(GPRInfo::callFrameRegister); + addCallArgument(arg1); + addCallArgument(arg2); + addCallArgument(arg3); + } + + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImmPtr arg3) + { + resetCallArguments(); + addCallArgument(GPRInfo::callFrameRegister); + addCallArgument(arg1); + addCallArgument(arg2); + addCallArgument(arg3); + } + + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImm32 arg2, TrustedImmPtr arg3) + { + resetCallArguments(); + addCallArgument(GPRInfo::callFrameRegister); + addCallArgument(arg1); + addCallArgument(arg2); + addCallArgument(arg3); + } + + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2, TrustedImmPtr arg3) + { + resetCallArguments(); + addCallArgument(GPRInfo::callFrameRegister); + addCallArgument(arg1); + addCallArgument(arg2); + addCallArgument(arg3); + } + + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4) + { + resetCallArguments(); + addCallArgument(GPRInfo::callFrameRegister); + addCallArgument(arg1); + addCallArgument(arg2); + addCallArgument(arg3); + addCallArgument(arg4); + } + + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, TrustedImmPtr arg4) + { + resetCallArguments(); + addCallArgument(GPRInfo::callFrameRegister); + addCallArgument(arg1); + addCallArgument(arg2); + addCallArgument(arg3); + addCallArgument(arg4); + } + + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImm32 arg3, TrustedImm32 arg4) + { + resetCallArguments(); + addCallArgument(GPRInfo::callFrameRegister); + addCallArgument(arg1); + addCallArgument(arg2); + addCallArgument(arg3); + addCallArgument(arg4); + } + + ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2, GPRReg arg3, GPRReg arg4) + { + resetCallArguments(); + addCallArgument(GPRInfo::callFrameRegister); + addCallArgument(arg1); + addCallArgument(arg2); + addCallArgument(arg3); + addCallArgument(arg4); + } + + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5) + { + resetCallArguments(); + addCallArgument(GPRInfo::callFrameRegister); + addCallArgument(arg1); + addCallArgument(arg2); + addCallArgument(arg3); + addCallArgument(arg4); + addCallArgument(arg5); + } +#endif // !NUMBER_OF_ARGUMENT_REGISTERS + // These methods are suitable for any calling convention that provides for + // at least 4 argument registers, e.g. X86_64, ARMv7. +#if NUMBER_OF_ARGUMENT_REGISTERS >= 4 + template + void setupTwoStubArgs(GPRReg srcA, GPRReg srcB) + { + // Assuming that srcA != srcB, there are 7 interesting states the registers may be in: + // (1) both are already in arg regs, the right way around. + // (2) both are already in arg regs, the wrong way around. + // (3) neither are currently in arg registers. + // (4) srcA in in its correct reg. + // (5) srcA in in the incorrect reg. + // (6) srcB in in its correct reg. + // (7) srcB in in the incorrect reg. + // + // The trivial approach is to simply emit two moves, to put srcA in place then srcB in + // place (the MacroAssembler will omit redundant moves). This apporach will be safe in + // cases 1, 3, 4, 5, 6, and in cases where srcA==srcB. The two problem cases are 2 + // (requires a swap) and 7 (must move srcB first, to avoid trampling.) + + if (srcB != destA) { + // Handle the easy cases - two simple moves. + move(srcA, destA); + move(srcB, destB); + } else if (srcA != destB) { + // Handle the non-swap case - just put srcB in place first. + move(srcB, destB); + move(srcA, destA); + } else + swap(destA, destB); + } +#if CPU(X86_64) + template + void setupTwoStubArgs(FPRReg srcA, FPRReg srcB) + { + // Assuming that srcA != srcB, there are 7 interesting states the registers may be in: + // (1) both are already in arg regs, the right way around. + // (2) both are already in arg regs, the wrong way around. + // (3) neither are currently in arg registers. + // (4) srcA in in its correct reg. + // (5) srcA in in the incorrect reg. + // (6) srcB in in its correct reg. + // (7) srcB in in the incorrect reg. + // + // The trivial approach is to simply emit two moves, to put srcA in place then srcB in + // place (the MacroAssembler will omit redundant moves). This apporach will be safe in + // cases 1, 3, 4, 5, 6, and in cases where srcA==srcB. The two problem cases are 2 + // (requires a swap) and 7 (must move srcB first, to avoid trampling.) + + if (srcB != destA) { + // Handle the easy cases - two simple moves. + moveDouble(srcA, destA); + moveDouble(srcB, destB); + return; + } + + if (srcA != destB) { + // Handle the non-swap case - just put srcB in place first. + moveDouble(srcB, destB); + moveDouble(srcA, destA); + return; + } + + ASSERT(srcB == destA && srcA == destB); + // Need to swap; pick a temporary register. + FPRReg temp; + if (destA != FPRInfo::argumentFPR3 && destA != FPRInfo::argumentFPR3) + temp = FPRInfo::argumentFPR3; + else if (destA != FPRInfo::argumentFPR2 && destA != FPRInfo::argumentFPR2) + temp = FPRInfo::argumentFPR2; + else { + ASSERT(destA != FPRInfo::argumentFPR1 && destA != FPRInfo::argumentFPR1); + temp = FPRInfo::argumentFPR1; + } + moveDouble(destA, temp); + moveDouble(destB, destA); + moveDouble(temp, destB); + } +#endif + void setupStubArguments(GPRReg arg1, GPRReg arg2) + { + setupTwoStubArgs(arg1, arg2); + } + void setupStubArguments(GPRReg arg1, GPRReg arg2, GPRReg arg3) + { + // If neither of arg2/arg3 are in our way, then we can move arg1 into place. + // Then we can use setupTwoStubArgs to fix arg2/arg3. + if (arg2 != GPRInfo::argumentGPR1 && arg3 != GPRInfo::argumentGPR1) { + move(arg1, GPRInfo::argumentGPR1); + setupTwoStubArgs(arg2, arg3); + return; + } + + // If neither of arg1/arg3 are in our way, then we can move arg2 into place. + // Then we can use setupTwoStubArgs to fix arg1/arg3. + if (arg1 != GPRInfo::argumentGPR2 && arg3 != GPRInfo::argumentGPR2) { + move(arg2, GPRInfo::argumentGPR2); + setupTwoStubArgs(arg1, arg3); + return; + } + + // If neither of arg1/arg2 are in our way, then we can move arg3 into place. + // Then we can use setupTwoStubArgs to fix arg1/arg2. + if (arg1 != GPRInfo::argumentGPR3 && arg2 != GPRInfo::argumentGPR3) { + move(arg3, GPRInfo::argumentGPR3); + setupTwoStubArgs(arg1, arg2); + return; + } + + // If we get here, we haven't been able to move any of arg1/arg2/arg3. + // Since all three are blocked, then all three must already be in the argument register. + // But are they in the right ones? + + // First, ensure arg1 is in place. + if (arg1 != GPRInfo::argumentGPR1) { + swap(arg1, GPRInfo::argumentGPR1); + + // If arg1 wasn't in argumentGPR1, one of arg2/arg3 must be. + ASSERT(arg2 == GPRInfo::argumentGPR1 || arg3 == GPRInfo::argumentGPR1); + // If arg2 was in argumentGPR1 it no longer is (due to the swap). + // Otherwise arg3 must have been. Mark him as moved. + if (arg2 == GPRInfo::argumentGPR1) + arg2 = arg1; + else + arg3 = arg1; + } + + // Either arg2 & arg3 need swapping, or we're all done. + ASSERT((arg2 == GPRInfo::argumentGPR2 || arg3 == GPRInfo::argumentGPR3) + || (arg2 == GPRInfo::argumentGPR3 || arg3 == GPRInfo::argumentGPR2)); + + if (arg2 != GPRInfo::argumentGPR2) + swap(GPRInfo::argumentGPR2, GPRInfo::argumentGPR3); + } + +#if CPU(X86_64) + ALWAYS_INLINE void setupArguments(FPRReg arg1) + { + moveDouble(arg1, FPRInfo::argumentFPR0); + } + + ALWAYS_INLINE void setupArguments(FPRReg arg1, FPRReg arg2) + { + setupTwoStubArgs(arg1, arg2); + } +#else + ALWAYS_INLINE void setupArguments(FPRReg arg1) + { + assembler().vmov(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1, arg1); + } + + ALWAYS_INLINE void setupArguments(FPRReg arg1, FPRReg arg2) + { + assembler().vmov(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1, arg1); + assembler().vmov(GPRInfo::argumentGPR2, GPRInfo::argumentGPR3, arg2); + } +#endif + + ALWAYS_INLINE void setupArguments(GPRReg arg1, GPRReg arg2) + { + setupTwoStubArgs(arg1, arg2); + } + + ALWAYS_INLINE void setupArgumentsExecState() + { + move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); + } + + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1) + { + move(arg1, GPRInfo::argumentGPR1); + move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); + } + + ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1) + { + move(arg1, GPRInfo::argumentGPR1); + move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); + } + + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2) + { + setupStubArguments(arg1, arg2); + move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); + } + + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2) + { + move(arg1, GPRInfo::argumentGPR1); + move(arg2, GPRInfo::argumentGPR2); + move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); + } + + ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, GPRReg arg2) + { + move(arg2, GPRInfo::argumentGPR2); // Move this first, so setting arg1 does not trample! + move(arg1, GPRInfo::argumentGPR1); + move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); + } + + ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2) + { + move(arg1, GPRInfo::argumentGPR1); + move(arg2, GPRInfo::argumentGPR2); + move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); + } + + ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImmPtr arg1, TrustedImmPtr arg2) + { + move(arg1, GPRInfo::argumentGPR1); + move(arg2, GPRInfo::argumentGPR2); + move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); + } + + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3) + { + setupStubArguments(arg1, arg2, arg3); + move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); + } + + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImm32 arg3) + { + setupStubArguments(arg1, arg2); + move(arg3, GPRInfo::argumentGPR3); + move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); + } + + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImm32 arg2, TrustedImmPtr arg3) + { + move(arg1, GPRInfo::argumentGPR1); + move(arg2, GPRInfo::argumentGPR2); + move(arg3, GPRInfo::argumentGPR3); + move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); + } + + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2, TrustedImmPtr arg3) + { + move(arg1, GPRInfo::argumentGPR1); + move(arg2, GPRInfo::argumentGPR2); + move(arg3, GPRInfo::argumentGPR3); + move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); + } + + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImmPtr arg3) + { + setupStubArguments(arg1, arg2); + move(arg3, GPRInfo::argumentGPR3); + move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); + } + + ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2, GPRReg arg3) + { + move(arg1, GPRInfo::argumentGPR1); + move(arg2, GPRInfo::argumentGPR2); + move(arg3, GPRInfo::argumentGPR3); + move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); + } + +#endif // NUMBER_OF_ARGUMENT_REGISTERS >= 4 + // These methods are suitable for any calling convention that provides for + // exactly 4 argument registers, e.g. ARMv7. +#if NUMBER_OF_ARGUMENT_REGISTERS == 4 + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4) + { + poke(arg4); + setupArgumentsWithExecState(arg1, arg2, arg3); + } + + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImm32 arg3, TrustedImm32 arg4) + { + poke(arg4); + setupArgumentsWithExecState(arg1, arg2, arg3); + } + + ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImm32 arg2, GPRReg arg3, GPRReg arg4) + { + poke(arg4); + setupArgumentsWithExecState(arg1, arg2, arg3); + } + + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, TrustedImmPtr arg4) + { + poke(arg4); + setupArgumentsWithExecState(arg1, arg2, arg3); + } + + ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, GPRReg arg4, GPRReg arg5) + { + poke(arg5, 1); + poke(arg4); + setupArgumentsWithExecState(arg1, arg2, arg3); + } +#endif // NUMBER_OF_ARGUMENT_REGISTERS == 4 + + void setupResults(GPRReg destA, GPRReg destB) + { + GPRReg srcA = GPRInfo::returnValueGPR; + GPRReg srcB = GPRInfo::returnValueGPR2; + + if (srcB != destA) { + // Handle the easy cases - two simple moves. + move(srcA, destA); + move(srcB, destB); + } else if (srcA != destB) { + // Handle the non-swap case - just put srcB in place first. + move(srcB, destB); + move(srcA, destA); + } else + swap(destA, destB); + } +}; + +} } // namespace JSC::DFG + +#endif // ENABLE(DFG_JIT) + +#endif // DFGCCallHelpers_h + diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGCapabilities.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGCapabilities.h new file mode 100644 index 000000000..2653c73b0 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGCapabilities.h @@ -0,0 +1,262 @@ +/* + * Copyright (C) 2011 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 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 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 DFGCapabilities_h +#define DFGCapabilities_h + +#include "Intrinsic.h" +#include "DFGNode.h" +#include "Executable.h" +#include "Options.h" +#include "Interpreter.h" +#include + +namespace JSC { namespace DFG { + +#if ENABLE(DFG_JIT) +// Fast check functions; if they return true it is still necessary to +// check opcodes. +inline bool mightCompileEval(CodeBlock* codeBlock) +{ + return codeBlock->instructionCount() <= Options::maximumOptimizationCandidateInstructionCount; +} +inline bool mightCompileProgram(CodeBlock* codeBlock) +{ + return codeBlock->instructionCount() <= Options::maximumOptimizationCandidateInstructionCount; +} +inline bool mightCompileFunctionForCall(CodeBlock* codeBlock) +{ + return codeBlock->instructionCount() <= Options::maximumOptimizationCandidateInstructionCount; +} +inline bool mightCompileFunctionForConstruct(CodeBlock* codeBlock) +{ + return codeBlock->instructionCount() <= Options::maximumOptimizationCandidateInstructionCount; +} + +inline bool mightInlineFunctionForCall(CodeBlock* codeBlock) +{ + return codeBlock->instructionCount() <= Options::maximumFunctionForCallInlineCandidateInstructionCount; +} +inline bool mightInlineFunctionForConstruct(CodeBlock* codeBlock) +{ + return codeBlock->instructionCount() <= Options::maximumFunctionForConstructInlineCandidateInstructionCount; +} + +// Opcode checking. +inline bool canCompileOpcode(OpcodeID opcodeID) +{ + switch (opcodeID) { + case op_enter: + case op_convert_this: + case op_create_this: + case op_get_callee: + case op_bitand: + case op_bitor: + case op_bitxor: + case op_rshift: + case op_lshift: + case op_urshift: + case op_pre_inc: + case op_post_inc: + case op_pre_dec: + case op_post_dec: + case op_add: + case op_sub: + case op_mul: + case op_mod: + case op_div: +#if ENABLE(DEBUG_WITH_BREAKPOINT) + case op_debug: +#endif + case op_mov: + case op_check_has_instance: + case op_instanceof: + case op_not: + case op_less: + case op_lesseq: + case op_greater: + case op_greatereq: + case op_eq: + case op_eq_null: + case op_stricteq: + case op_neq: + case op_neq_null: + case op_nstricteq: + case op_get_by_val: + case op_put_by_val: + case op_method_check: + case op_get_scoped_var: + case op_put_scoped_var: + case op_get_by_id: + case op_put_by_id: + case op_get_global_var: + case op_put_global_var: + case op_jmp: + case op_loop: + case op_jtrue: + case op_jfalse: + case op_loop_if_true: + case op_loop_if_false: + case op_jeq_null: + case op_jneq_null: + case op_jless: + case op_jlesseq: + case op_jgreater: + case op_jgreatereq: + case op_jnless: + case op_jnlesseq: + case op_jngreater: + case op_jngreatereq: + case op_loop_hint: + case op_loop_if_less: + case op_loop_if_lesseq: + case op_loop_if_greater: + case op_loop_if_greatereq: + case op_ret: + case op_end: + case op_call_put_result: + case op_resolve: + case op_resolve_base: + case op_resolve_global: + case op_new_object: + case op_new_array: + case op_new_array_buffer: + case op_strcat: + case op_to_primitive: + case op_throw: + case op_throw_reference_error: + case op_call: + case op_construct: + return true; + + // Opcodes we support conditionally. Enabling these opcodes currently results in + // performance regressions. Each node that we disable under restrictions has a + // comment describing what we know about the regression so far. + + // Regresses string-validate-input, probably because it uses comparisons (< and >) + // on strings, which currently will cause speculation failures in some cases. + case op_new_regexp: +#if DFG_ENABLE(RESTRICTIONS) + return false; +#else + return true; +#endif + + default: + return false; + } +} + +inline bool canInlineOpcode(OpcodeID opcodeID) +{ + switch (opcodeID) { + + // These opcodes would be easy to support with inlining, but we currently don't do it. + // The issue is that the scope chain will not be set correctly. + case op_get_scoped_var: + case op_put_scoped_var: + case op_resolve: + case op_resolve_base: + case op_resolve_global: + + // Constant buffers aren't copied correctly. This is easy to fix, but for + // now we just disable inlining for functions that use them. + case op_new_array_buffer: + + // Inlining doesn't correctly remap regular expression operands. + case op_new_regexp: + return false; + + default: + return canCompileOpcode(opcodeID); + } +} + +bool canCompileOpcodes(CodeBlock*); +bool canInlineOpcodes(CodeBlock*); +#else // ENABLE(DFG_JIT) +inline bool mightCompileEval(CodeBlock*) { return false; } +inline bool mightCompileProgram(CodeBlock*) { return false; } +inline bool mightCompileFunctionForCall(CodeBlock*) { return false; } +inline bool mightCompileFunctionForConstruct(CodeBlock*) { return false; } +inline bool mightInlineFunctionForCall(CodeBlock*) { return false; } +inline bool mightInlineFunctionForConstruct(CodeBlock*) { return false; } + +inline bool canCompileOpcode(OpcodeID) { return false; } +inline bool canInlineOpcode(OpcodeID) { return false; } +inline bool canCompileOpcodes(CodeBlock*) { return false; } +inline bool canInlineOpcodes(CodeBlock*) { return false; } +#endif // ENABLE(DFG_JIT) + +inline bool canCompileEval(CodeBlock* codeBlock) +{ + return mightCompileEval(codeBlock) && canCompileOpcodes(codeBlock); +} + +inline bool canCompileProgram(CodeBlock* codeBlock) +{ + return mightCompileProgram(codeBlock) && canCompileOpcodes(codeBlock); +} + +inline bool canCompileFunctionForCall(CodeBlock* codeBlock) +{ + return mightCompileFunctionForCall(codeBlock) && canCompileOpcodes(codeBlock); +} + +inline bool canCompileFunctionForConstruct(CodeBlock* codeBlock) +{ + return mightCompileFunctionForConstruct(codeBlock) && canCompileOpcodes(codeBlock); +} + +inline bool canInlineFunctionForCall(CodeBlock* codeBlock) +{ + return mightInlineFunctionForCall(codeBlock) && canInlineOpcodes(codeBlock); +} + +inline bool canInlineFunctionForConstruct(CodeBlock* codeBlock) +{ + return mightInlineFunctionForConstruct(codeBlock) && canInlineOpcodes(codeBlock); +} + +inline bool mightInlineFunctionFor(CodeBlock* codeBlock, CodeSpecializationKind kind) +{ + if (kind == CodeForCall) + return mightInlineFunctionForCall(codeBlock); + ASSERT(kind == CodeForConstruct); + return mightInlineFunctionForConstruct(codeBlock); +} + +inline bool canInlineFunctionFor(CodeBlock* codeBlock, CodeSpecializationKind kind) +{ + if (kind == CodeForCall) + return canInlineFunctionForCall(codeBlock); + ASSERT(kind == CodeForConstruct); + return canInlineFunctionForConstruct(codeBlock); +} + +} } // namespace JSC::DFG + +#endif // DFGCapabilities_h + diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGCodeBlocks.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGCodeBlocks.h new file mode 100644 index 000000000..06fd5ed3d --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGCodeBlocks.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2011 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 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 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 DFGCodeBlocks_h +#define DFGCodeBlocks_h + +#include +#include +#include + +namespace JSC { + +class CodeBlock; +class SlotVisitor; + +// DFGCodeBlocks notifies the garbage collector about optimized code blocks that +// have different marking behavior depending on whether or not they are on the +// stack, and that may be jettisoned. Jettisoning is the process of discarding +// a code block after all calls to it have been unlinked. This class takes special +// care to ensure that if there are still call frames that are using the code +// block, then it should not be immediately deleted, but rather, it should be +// deleted once we know that there are no longer any references to it from any +// call frames. This class takes its name from the DFG compiler; only code blocks +// compiled by the DFG need special marking behavior if they are on the stack, and +// only those code blocks may be jettisoned. + +#if ENABLE(DFG_JIT) +class DFGCodeBlocks { + WTF_MAKE_FAST_ALLOCATED; + +public: + DFGCodeBlocks(); + ~DFGCodeBlocks(); + + // Inform the collector that a code block has been jettisoned form its + // executable and should only be kept alive if there are call frames that use + // it. This is typically called either from a recompilation trigger, or from + // an unconditional finalizer associated with a CodeBlock that had weak + // references, where some subset of those references were dead. + void jettison(PassOwnPtr); + + // Clear all mark bits associated with DFG code blocks. + void clearMarks(); + + // Mark a pointer that may be a CodeBlock that belongs to the set of DFG code + // blocks. This is defined inline in CodeBlock.h + void mark(void* candidateCodeBlock); + + // Delete all jettisoned code blocks that have not been marked (i.e. are not referenced + // from call frames). + void deleteUnmarkedJettisonedCodeBlocks(); + + // Trace all marked code blocks (i.e. are referenced from call frames). The CodeBlock + // is free to make use of m_dfgData->isMarked and m_dfgData->isJettisoned. + void traceMarkedCodeBlocks(SlotVisitor&); + +private: + friend class CodeBlock; + + HashSet m_set; +}; +#else +class DFGCodeBlocks { + WTF_MAKE_FAST_ALLOCATED; + +public: + void jettison(PassOwnPtr); + void clearMarks() { } + void mark(void*) { } + void deleteUnmarkedJettisonedCodeBlocks() { } + void traceMarkedCodeBlocks(SlotVisitor&) { } +}; +#endif + +} // namespace JSC + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGCommon.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGCommon.h new file mode 100644 index 000000000..469dbd33e --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGCommon.h @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2011 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 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 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 DFGCommon_h +#define DFGCommon_h + +#include + +#if ENABLE(DFG_JIT) + +#include "CodeOrigin.h" +#include "VirtualRegister.h" + +/* DFG_ENABLE() - turn on a specific features in the DFG JIT */ +#define DFG_ENABLE(DFG_FEATURE) (defined DFG_ENABLE_##DFG_FEATURE && DFG_ENABLE_##DFG_FEATURE) + +// Emit various logging information for debugging, including dumping the dataflow graphs. +#define DFG_ENABLE_DEBUG_VERBOSE 0 +// Emit dumps during propagation, in addition to just after. +#define DFG_ENABLE_DEBUG_PROPAGATION_VERBOSE 0 +// Emit logging for OSR exit value recoveries at every node, not just nodes that +// actually has speculation checks. +#define DFG_ENABLE_VERBOSE_VALUE_RECOVERIES 0 +// Enable generation of dynamic checks into the instruction stream. +#if !ASSERT_DISABLED +#define DFG_ENABLE_JIT_ASSERT 1 +#else +#define DFG_ENABLE_JIT_ASSERT 0 +#endif +// Consistency check contents compiler data structures. +#define DFG_ENABLE_CONSISTENCY_CHECK 0 +// Emit a breakpoint into the head of every generated function, to aid debugging in GDB. +#define DFG_ENABLE_JIT_BREAK_ON_EVERY_FUNCTION 0 +// Emit a breakpoint into the head of every generated node, to aid debugging in GDB. +#define DFG_ENABLE_JIT_BREAK_ON_EVERY_BLOCK 0 +// Emit a breakpoint into the head of every generated node, to aid debugging in GDB. +#define DFG_ENABLE_JIT_BREAK_ON_EVERY_NODE 0 +// Emit a pair of xorPtr()'s on regT0 with the node index to make it easy to spot node boundaries in disassembled code. +#define DFG_ENABLE_XOR_DEBUG_AID 0 +// Emit a breakpoint into the speculation failure code. +#define DFG_ENABLE_JIT_BREAK_ON_SPECULATION_FAILURE 0 +// Log every speculation failure. +#define DFG_ENABLE_VERBOSE_SPECULATION_FAILURE 0 +// Disable the DFG JIT without having to touch Platform.h +#define DFG_DEBUG_LOCAL_DISBALE 0 +// Enable OSR entry from baseline JIT. +#define DFG_ENABLE_OSR_ENTRY ENABLE(DFG_JIT) +// Generate stats on how successful we were in making use of the DFG jit, and remaining on the hot path. +#define DFG_ENABLE_SUCCESS_STATS 0 +// Used to enable conditionally supported opcodes that currently result in performance regressions. +#define DFG_ENABLE_RESTRICTIONS 1 + +namespace JSC { namespace DFG { + +// Type for a reference to another node in the graph. +typedef uint32_t NodeIndex; +static const NodeIndex NoNode = UINT_MAX; + +typedef uint32_t BlockIndex; +static const BlockIndex NoBlock = UINT_MAX; + +struct NodeIndexTraits { + static NodeIndex defaultValue() { return NoNode; } + static void dump(NodeIndex value, FILE* out) + { + if (value == NoNode) + fprintf(out, "-"); + else + fprintf(out, "@%u", value); + } +}; + +} } // namespace JSC::DFG + +#endif // ENABLE(DFG_JIT) + +#endif // DFGCommon_h + diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGCorrectableJumpPoint.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGCorrectableJumpPoint.h new file mode 100644 index 000000000..983f479c2 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGCorrectableJumpPoint.h @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2011 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 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 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 DFGCorrectableJumpPoint_h +#define DFGCorrectableJumpPoint_h + +#if ENABLE(DFG_JIT) + +#include "LinkBuffer.h" +#include "MacroAssembler.h" + +namespace JSC { namespace DFG { + +// This is a type-safe union of MacroAssembler::Jump and CodeLocationJump. +// Furthermore, it supports the notion of branching (possibly conditionally, but +// also possibly jumping unconditionally) to an out-of-line patchable jump. +// Thus it goes through three states: +// +// 1) Label of unpatchable branch or jump (i.e. MacroAssembler::Jump). +// 2) Label of patchable jump (i.e. MacroAssembler::Jump). +// 3) Corrected post-linking label of patchable jump (i.e. CodeLocationJump). +// +// The setting of state (1) corresponds to planting the in-line unpatchable +// branch or jump. The state transition (1)->(2) corresponds to linking the +// in-line branch or jump to the out-of-line patchable jump, and recording +// the latter's label. The state transition (2)->(3) corresponds to recording +// the out-of-line patchable jump's location after branch compaction has +// completed. +// +// You can also go directly from the first state to the third state, if you +// wish to use this class for in-line patchable jumps. + +class CorrectableJumpPoint { +public: + CorrectableJumpPoint(MacroAssembler::Jump check) + : m_codeOffset(check.m_label.m_offset) +#ifndef NDEBUG + , m_mode(InitialJump) +#endif + { +#if CPU(ARM_THUMB2) + m_type = check.m_type; + m_condition = check.m_condition; +#endif + } + + void switchToLateJump(MacroAssembler::Jump check) + { +#ifndef NDEBUG + ASSERT(m_mode == InitialJump); + m_mode = LateJump; +#endif + // Late jumps should only ever be real jumps. +#if CPU(ARM_THUMB2) + ASSERT(check.m_type == ARMv7Assembler::JumpNoConditionFixedSize); + ASSERT(check.m_condition == ARMv7Assembler::ConditionInvalid); + m_type = ARMv7Assembler::JumpNoConditionFixedSize; + m_condition = ARMv7Assembler::ConditionInvalid; +#endif + m_codeOffset = check.m_label.m_offset; + } + + void correctInitialJump(LinkBuffer& linkBuffer) + { + ASSERT(m_mode == InitialJump); +#if CPU(ARM_THUMB2) + ASSERT(m_type == ARMv7Assembler::JumpNoConditionFixedSize); + ASSERT(m_condition == ARMv7Assembler::ConditionInvalid); +#endif + correctJump(linkBuffer); + } + + void correctLateJump(LinkBuffer& linkBuffer) + { + ASSERT(m_mode == LateJump); + correctJump(linkBuffer); + } + + MacroAssembler::Jump initialJump() const + { + ASSERT(m_mode == InitialJump); + return getJump(); + } + + MacroAssembler::Jump lateJump() const + { + ASSERT(m_mode == LateJump); + return getJump(); + } + + CodeLocationJump codeLocationForRepatch(CodeBlock*) const; + +private: + void correctJump(LinkBuffer& linkBuffer) + { +#ifndef NDEBUG + m_mode = CorrectedJump; +#endif + MacroAssembler::Label label; + label.m_label.m_offset = m_codeOffset; + m_codeOffset = linkBuffer.offsetOf(label); + } + + MacroAssembler::Jump getJump() const + { + MacroAssembler::Jump jump; + jump.m_label.m_offset = m_codeOffset; +#if CPU(ARM_THUMB2) + jump.m_type = m_type; + jump.m_condition = m_condition; +#endif + return jump; + } + + unsigned m_codeOffset; + +#if CPU(ARM_THUMB2) + ARMv7Assembler::JumpType m_type : 8; + ARMv7Assembler::Condition m_condition : 8; +#endif + +#ifndef NDEBUG + enum Mode { + InitialJump, + LateJump, + CorrectedJump + }; + + Mode m_mode; +#endif +}; + +} } // namespace JSC::DFG + +#endif // ENABLE(DFG_JIT) + +#endif // DFGCorrectableJumpPoint_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGExitProfile.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGExitProfile.h new file mode 100644 index 000000000..f18b69a54 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGExitProfile.h @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2011 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 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 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 DFGExitProfile_h +#define DFGExitProfile_h + +#include +#include +#include + +namespace JSC { namespace DFG { + +enum ExitKind { + ExitKindUnset, + BadType, // We exited because a type prediction was wrong. + BadCache, // We exited because an inline cache was wrong. + Overflow, // We exited because of overflow. + NegativeZero, // We exited because we encountered negative zero. + Uncountable, // We exited for none of the above reasons, and we should not count it. Most uses of this should be viewed as a FIXME. +}; + +#ifndef NDEBUG +inline const char* exitKindToString(ExitKind kind) +{ + switch (kind) { + case ExitKindUnset: + return "Unset"; + case BadType: + return "BadType"; + case BadCache: + return "BadCache"; + case Overflow: + return "Overflow"; + case NegativeZero: + return "NegativeZero"; + default: + return "Unknown"; + } +} +#endif + +inline bool exitKindIsCountable(ExitKind kind) +{ + switch (kind) { + case ExitKindUnset: + ASSERT_NOT_REACHED(); + case BadType: + case Uncountable: + return false; + default: + return true; + } +} + +class FrequentExitSite { +public: + FrequentExitSite() + : m_bytecodeOffset(0) // 0 = empty value + , m_kind(ExitKindUnset) + { + } + + FrequentExitSite(WTF::HashTableDeletedValueType) + : m_bytecodeOffset(1) // 1 = deleted value + , m_kind(ExitKindUnset) + { + } + + explicit FrequentExitSite(unsigned bytecodeOffset, ExitKind kind) + : m_bytecodeOffset(bytecodeOffset) + , m_kind(kind) + { + ASSERT(exitKindIsCountable(kind)); + } + + bool operator!() const + { + return m_kind == ExitKindUnset; + } + + bool operator==(const FrequentExitSite& other) const + { + return m_bytecodeOffset == other.m_bytecodeOffset + && m_kind == other.m_kind; + } + + unsigned hash() const + { + return WTF::intHash(m_bytecodeOffset) + m_kind; + } + + unsigned bytecodeOffset() const { return m_bytecodeOffset; } + ExitKind kind() const { return m_kind; } + + bool isHashTableDeletedValue() const + { + return m_kind == ExitKindUnset && m_bytecodeOffset; + } + +private: + unsigned m_bytecodeOffset; + ExitKind m_kind; +}; + +struct FrequentExitSiteHash { + static unsigned hash(const FrequentExitSite& key) { return key.hash(); } + static bool equal(const FrequentExitSite& a, const FrequentExitSite& b) { return a == b; } + static const bool safeToCompareToEmptyOrDeleted = true; +}; + +} } // namespace JSC::DFG + +namespace WTF { + +template struct DefaultHash; +template<> struct DefaultHash { + typedef JSC::DFG::FrequentExitSiteHash Hash; +}; + +template struct HashTraits; +template<> struct HashTraits : SimpleClassHashTraits { }; + +} // namespace WTF + +namespace JSC { namespace DFG { + +class QueryableExitProfile; + +class ExitProfile { +public: + ExitProfile(); + ~ExitProfile(); + + // Add a new frequent exit site. Return true if this is a new one, or false + // if we already knew about it. This is an O(n) operation, because it errs + // on the side of keeping the data structure compact. Also, this will only + // be called a fixed number of times per recompilation. Recompilation is + // rare to begin with, and implies doing O(n) operations on the CodeBlock + // anyway. + bool add(const FrequentExitSite&); + +private: + friend class QueryableExitProfile; + + OwnPtr > m_frequentExitSites; +}; + +class QueryableExitProfile { +public: + explicit QueryableExitProfile(const ExitProfile&); + ~QueryableExitProfile(); + + bool hasExitSite(const FrequentExitSite& site) const + { + return m_frequentExitSites.find(site) != m_frequentExitSites.end(); + } + + bool hasExitSite(unsigned bytecodeIndex, ExitKind kind) const + { + return hasExitSite(FrequentExitSite(bytecodeIndex, kind)); + } +private: + HashSet m_frequentExitSites; +}; + +} } // namespace JSC::DFG + +#endif // DFGExitProfile_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGOSREntry.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGOSREntry.h new file mode 100644 index 000000000..e38a6ceb9 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGOSREntry.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2011 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 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 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 DFGOSREntry_h +#define DFGOSREntry_h + +#include "DFGAbstractValue.h" +#include "DFGOperands.h" +#include + +namespace JSC { + +class ExecState; +class CodeBlock; + +namespace DFG { + +#if ENABLE(DFG_JIT) +struct OSREntryData { + unsigned m_bytecodeIndex; + unsigned m_machineCodeOffset; + Operands m_expectedValues; + BitVector m_localsForcedDouble; +}; + +inline unsigned getOSREntryDataBytecodeIndex(OSREntryData* osrEntryData) +{ + return osrEntryData->m_bytecodeIndex; +} + +void* prepareOSREntry(ExecState*, CodeBlock*, unsigned bytecodeIndex); +#else +inline void* prepareOSREntry(ExecState*, CodeBlock*, unsigned) { return 0; } +#endif + +} } // namespace JSC::DFG + +#endif // DFGOSREntry_h + diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGOSRExit.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGOSRExit.h new file mode 100644 index 000000000..cf96f4f3a --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGOSRExit.h @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2011 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 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 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 DFGOSRExit_h +#define DFGOSRExit_h + +#include + +#if ENABLE(DFG_JIT) + +#include "CodeOrigin.h" +#include "DFGCommon.h" +#include "DFGCorrectableJumpPoint.h" +#include "DFGExitProfile.h" +#include "DFGGPRInfo.h" +#include "DFGOperands.h" +#include "MacroAssembler.h" +#include "ValueProfile.h" +#include "ValueRecovery.h" +#include + +namespace JSC { namespace DFG { + +class SpeculativeJIT; + +// This enum describes the types of additional recovery that +// may need be performed should a speculation check fail. +enum SpeculationRecoveryType { + SpeculativeAdd, + BooleanSpeculationCheck +}; + +// === SpeculationRecovery === +// +// This class provides additional information that may be associated with a +// speculation check - for example +class SpeculationRecovery { +public: + SpeculationRecovery(SpeculationRecoveryType type, GPRReg dest, GPRReg src) + : m_type(type) + , m_dest(dest) + , m_src(src) + { + } + + SpeculationRecoveryType type() { return m_type; } + GPRReg dest() { return m_dest; } + GPRReg src() { return m_src; } + +private: + // Indicates the type of additional recovery to be performed. + SpeculationRecoveryType m_type; + // different recovery types may required different additional information here. + GPRReg m_dest; + GPRReg m_src; +}; + +// === OSRExit === +// +// This structure describes how to exit the speculative path by +// going into baseline code. +struct OSRExit { + OSRExit(ExitKind, JSValueSource, ValueProfile*, MacroAssembler::Jump, SpeculativeJIT*, unsigned recoveryIndex = 0); + + MacroAssemblerCodeRef m_code; + + JSValueSource m_jsValueSource; + ValueProfile* m_valueProfile; + + CorrectableJumpPoint m_check; + NodeIndex m_nodeIndex; + CodeOrigin m_codeOrigin; + + unsigned m_recoveryIndex; + + ExitKind m_kind; + uint32_t m_count; + + // Convenient way of iterating over ValueRecoveries while being + // generic over argument versus variable. + int numberOfRecoveries() const { return m_arguments.size() + m_variables.size(); } + const ValueRecovery& valueRecovery(int index) const + { + if (index < (int)m_arguments.size()) + return m_arguments[index]; + return m_variables[index - m_arguments.size()]; + } + ValueRecovery& valueRecoveryForOperand(int operand) + { + if (operandIsArgument(operand)) + return m_arguments[operandToArgument(operand)]; + return m_variables[operand]; + } + bool isArgument(int index) const { return index < (int)m_arguments.size(); } + bool isVariable(int index) const { return !isArgument(index); } + int argumentForIndex(int index) const + { + return index; + } + int variableForIndex(int index) const + { + return index - m_arguments.size(); + } + int operandForIndex(int index) const + { + if (index < (int)m_arguments.size()) + return operandToArgument(index); + return index - m_arguments.size(); + } + + bool considerAddingAsFrequentExitSite(CodeBlock* dfgCodeBlock, CodeBlock* profiledCodeBlock) + { + if (!m_count || !exitKindIsCountable(m_kind)) + return false; + return considerAddingAsFrequentExitSiteSlow(dfgCodeBlock, profiledCodeBlock); + } + +#ifndef NDEBUG + void dump(FILE* out) const; +#endif + + Vector m_arguments; + Vector m_variables; + int m_lastSetOperand; + +private: + bool considerAddingAsFrequentExitSiteSlow(CodeBlock* dfgCodeBlock, CodeBlock* profiledCodeBlock); +}; + +#if DFG_ENABLE(VERBOSE_SPECULATION_FAILURE) +struct SpeculationFailureDebugInfo { + CodeBlock* codeBlock; + NodeIndex nodeIndex; +}; +#endif + +} } // namespace JSC::DFG + +#endif // ENABLE(DFG_JIT) + +#endif // DFGOSRExit_h + diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGOSRExitCompiler.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGOSRExitCompiler.h new file mode 100644 index 000000000..e08362f22 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGOSRExitCompiler.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2011 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 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 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 DFGOSRExitCompiler_h +#define DFGOSRExitCompiler_h + +#include + +#if ENABLE(DFG_JIT) + +#include "DFGAssemblyHelpers.h" +#include "DFGOSRExit.h" +#include "DFGOperations.h" + +namespace JSC { + +class ExecState; + +namespace DFG { + +class OSRExitCompiler { +public: + OSRExitCompiler(AssemblyHelpers& jit) + : m_jit(jit) + { + } + + void compileExit(const OSRExit&, SpeculationRecovery*); + +private: +#if !ASSERT_DISABLED + static unsigned badIndex() { return static_cast(-1); }; +#endif + + void initializePoisoned(unsigned size) + { +#if ASSERT_DISABLED + m_poisonScratchIndices.resize(size); +#else + m_poisonScratchIndices.fill(badIndex(), size); +#endif + } + + unsigned poisonIndex(unsigned index) + { + unsigned result = m_poisonScratchIndices[index]; + ASSERT(result != badIndex()); + return result; + } + + AssemblyHelpers& m_jit; + Vector m_poisonScratchIndices; +}; + +extern "C" { +void DFG_OPERATION compileOSRExit(ExecState*); +} + +} } // namespace JSC::DFG + +#endif // ENABLE(DFG_JIT) + +#endif // DFGOSRExitCompiler_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGOperands.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGOperands.h new file mode 100644 index 000000000..9ce43119c --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGOperands.h @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2011 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 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 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 DFGOperands_h +#define DFGOperands_h + +#include + +#if ENABLE(DFG_JIT) + +#include "CallFrame.h" +#include + +namespace JSC { namespace DFG { + +// argument 0 is 'this'. +inline bool operandIsArgument(int operand) { return operand < 0; } +inline int operandToArgument(int operand) { return -operand + CallFrame::thisArgumentOffset(); } +inline int argumentToOperand(int argument) { return -argument + CallFrame::thisArgumentOffset(); } + +template struct OperandValueTraits; + +template +struct OperandValueTraits { + static T defaultValue() { return T(); } + static void dump(const T& value, FILE* out) { value.dump(out); } +}; + +template > +class Operands { +public: + Operands() { } + + explicit Operands(size_t numArguments, size_t numLocals) + { + m_arguments.fill(Traits::defaultValue(), numArguments); + m_locals.fill(Traits::defaultValue(), numLocals); + } + + size_t numberOfArguments() const { return m_arguments.size(); } + size_t numberOfLocals() const { return m_locals.size(); } + + T& argument(size_t idx) { return m_arguments[idx]; } + const T& argument(size_t idx) const { return m_arguments[idx]; } + + T& local(size_t idx) { return m_locals[idx]; } + const T& local(size_t idx) const { return m_locals[idx]; } + + void ensureLocals(size_t size) + { + if (size <= m_locals.size()) + return; + + size_t oldSize = m_locals.size(); + m_locals.resize(size); + for (size_t i = oldSize; i < m_locals.size(); ++i) + m_locals[i] = Traits::defaultValue(); + } + + void setLocal(size_t idx, const T& value) + { + ensureLocals(idx + 1); + + m_locals[idx] = value; + } + + T getLocal(size_t idx) + { + if (idx >= m_locals.size()) + return Traits::defaultValue(); + return m_locals[idx]; + } + + void setArgumentFirstTime(size_t idx, const T& value) + { + ASSERT(m_arguments[idx] == Traits::defaultValue()); + argument(idx) = value; + } + + void setLocalFirstTime(size_t idx, const T& value) + { + ASSERT(idx >= m_locals.size() || m_locals[idx] == Traits::defaultValue()); + setLocal(idx, value); + } + + T& operand(int operand) + { + if (operandIsArgument(operand)) { + int argument = operandToArgument(operand); + return m_arguments[argument]; + } + + return m_locals[operand]; + } + + const T& operand(int operand) const { return const_cast(const_cast(this)->operand(operand)); } + + void setOperand(int operand, const T& value) + { + if (operandIsArgument(operand)) { + int argument = operandToArgument(operand); + m_arguments[argument] = value; + return; + } + + setLocal(operand, value); + } + + void clear() + { + for (size_t i = 0; i < m_arguments.size(); ++i) + m_arguments[i] = Traits::defaultValue(); + for (size_t i = 0; i < m_locals.size(); ++i) + m_locals[i] = Traits::defaultValue(); + } + +private: + Vector m_arguments; + Vector m_locals; +}; + +template +void dumpOperands(Operands& operands, FILE* out) +{ + for (size_t argument = 0; argument < operands.numberOfArguments(); ++argument) { + if (argument) + fprintf(out, " "); + Traits::dump(operands.argument(argument), out); + } + fprintf(out, " : "); + for (size_t local = 0; local < operands.numberOfLocals(); ++local) { + if (local) + fprintf(out, " "); + Traits::dump(operands.local(local), out); + } +} + +} } // namespace JSC::DFG + +#endif // ENABLE(DFG_JIT) + +#endif // DFGOperands_h + diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGThunks.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGThunks.h new file mode 100644 index 000000000..3db62442a --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGThunks.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2011 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 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 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 DFGThunks_h +#define DFGThunks_h + +#include + +#if ENABLE(DFG_JIT) + +#include "MacroAssemblerCodeRef.h" + +namespace JSC { + +class JSGlobalData; + +namespace DFG { + +MacroAssemblerCodeRef osrExitGenerationThunkGenerator(JSGlobalData*); + +} } // namespace JSC::DFG + +#endif // ENABLE(DFG_JIT) + +#endif // DFGThunks_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGVariableAccessData.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGVariableAccessData.h new file mode 100644 index 000000000..3cc53748a --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DFGVariableAccessData.h @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2011 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 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 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 DFGVariableAccessData_h +#define DFGVariableAccessData_h + +#include "DFGOperands.h" +#include "PredictedType.h" +#include "VirtualRegister.h" +#include +#include + +namespace JSC { namespace DFG { + +class VariableAccessData : public UnionFind { +public: + enum Ballot { VoteValue, VoteDouble }; + + VariableAccessData() + : m_local(static_cast(std::numeric_limits::min())) + , m_prediction(PredictNone) + , m_shouldUseDoubleFormat(false) + { + clearVotes(); + } + + VariableAccessData(VirtualRegister local) + : m_local(local) + , m_prediction(PredictNone) + , m_shouldUseDoubleFormat(false) + { + clearVotes(); + } + + VirtualRegister local() + { + ASSERT(m_local == find()->m_local); + return m_local; + } + + int operand() + { + return static_cast(local()); + } + + bool predict(PredictedType prediction) + { + return mergePrediction(find()->m_prediction, prediction); + } + + PredictedType prediction() + { + return find()->m_prediction; + } + + void clearVotes() + { + ASSERT(find() == this); + m_votes[VoteValue] = 0; + m_votes[VoteDouble] = 0; + } + + void vote(Ballot ballot) + { + ASSERT(static_cast(ballot) < 2); + m_votes[ballot]++; + } + + double doubleVoteRatio() + { + ASSERT(find() == this); + return static_cast(m_votes[VoteDouble]) / m_votes[VoteValue]; + } + + bool shouldUseDoubleFormatAccordingToVote() + { + // FIXME: make this work for arguments. + return !operandIsArgument(operand()) && ((isNumberPrediction(prediction()) && doubleVoteRatio() >= Options::doubleVoteRatioForDoubleFormat) || isDoublePrediction(prediction())); + } + + bool shouldUseDoubleFormat() + { + ASSERT(find() == this); + return m_shouldUseDoubleFormat; + } + + bool tallyVotesForShouldUseDoubleFormat() + { + ASSERT(find() == this); + + bool newValueOfShouldUseDoubleFormat = shouldUseDoubleFormatAccordingToVote(); + if (!newValueOfShouldUseDoubleFormat) { + // We monotonically convert to double. Hence, if the fixpoint leads us to conclude that we should + // switch back to int, we instead ignore this and stick with double. + return false; + } + + if (m_shouldUseDoubleFormat) + return false; + + m_shouldUseDoubleFormat = true; + mergePrediction(m_prediction, PredictDouble); + return true; + } + +private: + // This is slightly space-inefficient, since anything we're unified with + // will have the same operand and should have the same prediction. But + // putting them here simplifies the code, and we don't expect DFG space + // usage for variable access nodes do be significant. + + VirtualRegister m_local; + PredictedType m_prediction; + + float m_votes[2]; + bool m_shouldUseDoubleFormat; +}; + +} } // namespace JSC::DFG + +#endif // DFGVariableAccessData_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DataFormat.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DataFormat.h new file mode 100644 index 000000000..b78a6e8e6 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DataFormat.h @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2011 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 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 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 DataFormat_h +#define DataFormat_h + +#include + +namespace JSC { + +// === DataFormat === +// +// This enum tracks the current representation in which a value is being held. +// Values may be unboxed primitives (int32, double, or cell), or boxed as a JSValue. +// For boxed values, we may know the type of boxing that has taken place. +// (May also need bool, array, object, string types!) +enum DataFormat { + DataFormatNone = 0, + DataFormatInteger = 1, + DataFormatDouble = 2, + DataFormatBoolean = 3, + DataFormatCell = 4, + DataFormatStorage = 5, + DataFormatJS = 8, + DataFormatJSInteger = DataFormatJS | DataFormatInteger, + DataFormatJSDouble = DataFormatJS | DataFormatDouble, + DataFormatJSCell = DataFormatJS | DataFormatCell, + DataFormatJSBoolean = DataFormatJS | DataFormatBoolean +}; + +#ifndef NDEBUG +inline const char* dataFormatToString(DataFormat dataFormat) +{ + switch (dataFormat) { + case DataFormatNone: + return "None"; + case DataFormatInteger: + return "Integer"; + case DataFormatDouble: + return "Double"; + case DataFormatCell: + return "Cell"; + case DataFormatBoolean: + return "Boolean"; + case DataFormatStorage: + return "Storage"; + case DataFormatJS: + return "JS"; + case DataFormatJSInteger: + return "JSInteger"; + case DataFormatJSDouble: + return "JSDouble"; + case DataFormatJSCell: + return "JSCell"; + case DataFormatJSBoolean: + return "JSBoolean"; + default: + return "Unknown"; + } +} +#endif + +#if USE(JSVALUE64) +inline bool needDataFormatConversion(DataFormat from, DataFormat to) +{ + ASSERT(from != DataFormatNone); + ASSERT(to != DataFormatNone); + switch (from) { + case DataFormatInteger: + case DataFormatDouble: + return to != from; + case DataFormatCell: + case DataFormatJS: + case DataFormatJSInteger: + case DataFormatJSDouble: + case DataFormatJSCell: + case DataFormatJSBoolean: + switch (to) { + case DataFormatInteger: + case DataFormatDouble: + return true; + case DataFormatCell: + case DataFormatJS: + case DataFormatJSInteger: + case DataFormatJSDouble: + case DataFormatJSCell: + case DataFormatJSBoolean: + return false; + default: + // This captures DataFormatBoolean, which is currently unused. + ASSERT_NOT_REACHED(); + } + case DataFormatStorage: + ASSERT(to == DataFormatStorage); + return false; + default: + // This captures DataFormatBoolean, which is currently unused. + ASSERT_NOT_REACHED(); + } + return true; +} + +#elif USE(JSVALUE32_64) +inline bool needDataFormatConversion(DataFormat from, DataFormat to) +{ + ASSERT(from != DataFormatNone); + ASSERT(to != DataFormatNone); + switch (from) { + case DataFormatInteger: + case DataFormatCell: + case DataFormatBoolean: + return ((to & DataFormatJS) || to == DataFormatDouble); + case DataFormatDouble: + case DataFormatJSDouble: + return (to != DataFormatDouble && to != DataFormatJSDouble); + case DataFormatJS: + case DataFormatJSInteger: + case DataFormatJSCell: + case DataFormatJSBoolean: + return (!(to & DataFormatJS) || to == DataFormatJSDouble); + case DataFormatStorage: + ASSERT(to == DataFormatStorage); + return false; + default: + ASSERT_NOT_REACHED(); + } + return true; +} +#endif + +inline bool isJSFormat(DataFormat format, DataFormat expectedFormat) +{ + ASSERT(expectedFormat & DataFormatJS); + return (format | DataFormatJS) == expectedFormat; +} + +inline bool isJSInteger(DataFormat format) +{ + return isJSFormat(format, DataFormatJSInteger); +} + +inline bool isJSDouble(DataFormat format) +{ + return isJSFormat(format, DataFormatJSDouble); +} + +inline bool isJSCell(DataFormat format) +{ + return isJSFormat(format, DataFormatJSCell); +} + +inline bool isJSBoolean(DataFormat format) +{ + return isJSFormat(format, DataFormatJSBoolean); +} + +} + +#endif // DataFormat_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DateInstance.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DateInstance.h new file mode 100644 index 000000000..7c976a514 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DateInstance.h @@ -0,0 +1,97 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef DateInstance_h +#define DateInstance_h + +#include "JSWrapperObject.h" + +namespace WTF { + struct GregorianDateTime; +} + +namespace JSC { + + class DateInstance : public JSWrapperObject { + protected: + JS_EXPORT_PRIVATE DateInstance(ExecState*, Structure*); + void finishCreation(JSGlobalData&); + JS_EXPORT_PRIVATE void finishCreation(JSGlobalData&, double); + + static void destroy(JSCell*); + + public: + typedef JSWrapperObject Base; + + static DateInstance* create(ExecState* exec, Structure* structure, double date) + { + DateInstance* instance = new (NotNull, allocateCell(*exec->heap())) DateInstance(exec, structure); + instance->finishCreation(exec->globalData(), date); + return instance; + } + + static DateInstance* create(ExecState* exec, Structure* structure) + { + DateInstance* instance = new (NotNull, allocateCell(*exec->heap())) DateInstance(exec, structure); + instance->finishCreation(exec->globalData()); + return instance; + } + + double internalNumber() const { return internalValue().asNumber(); } + + static JS_EXPORTDATA const ClassInfo s_info; + + const GregorianDateTime* gregorianDateTime(ExecState* exec) const + { + if (m_data && m_data->m_gregorianDateTimeCachedForMS == internalNumber()) + return &m_data->m_cachedGregorianDateTime; + return calculateGregorianDateTime(exec); + } + + const GregorianDateTime* gregorianDateTimeUTC(ExecState* exec) const + { + if (m_data && m_data->m_gregorianDateTimeUTCCachedForMS == internalNumber()) + return &m_data->m_cachedGregorianDateTimeUTC; + return calculateGregorianDateTimeUTC(exec); + } + + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + { + return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); + } + + private: + const GregorianDateTime* calculateGregorianDateTime(ExecState*) const; + const GregorianDateTime* calculateGregorianDateTimeUTC(ExecState*) const; + + mutable RefPtr m_data; + }; + + DateInstance* asDateInstance(JSValue); + + inline DateInstance* asDateInstance(JSValue value) + { + ASSERT(asObject(value)->inherits(&DateInstance::s_info)); + return static_cast(asObject(value)); + } + +} // namespace JSC + +#endif // DateInstance_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DateInstanceCache.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DateInstanceCache.h new file mode 100644 index 000000000..153582f67 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DateInstanceCache.h @@ -0,0 +1,93 @@ +/* + * 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 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 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 DateInstanceCache_h +#define DateInstanceCache_h + +#include "JSDateMath.h" +#include +#include +#include +#include + +namespace JSC { + + class DateInstanceData : public RefCounted { + public: + static PassRefPtr create() { return adoptRef(new DateInstanceData); } + + double m_gregorianDateTimeCachedForMS; + GregorianDateTime m_cachedGregorianDateTime; + double m_gregorianDateTimeUTCCachedForMS; + GregorianDateTime m_cachedGregorianDateTimeUTC; + + private: + DateInstanceData() + : m_gregorianDateTimeCachedForMS(std::numeric_limits::quiet_NaN()) + , m_gregorianDateTimeUTCCachedForMS(std::numeric_limits::quiet_NaN()) + { + } + }; + + class DateInstanceCache { + public: + DateInstanceCache() + { + reset(); + } + + void reset() + { + for (size_t i = 0; i < cacheSize; ++i) + m_cache[i].key = std::numeric_limits::quiet_NaN(); + } + + DateInstanceData* add(double d) + { + CacheEntry& entry = lookup(d); + if (d == entry.key) + return entry.value.get(); + + entry.key = d; + entry.value = DateInstanceData::create(); + return entry.value.get(); + } + + private: + static const size_t cacheSize = 16; + + struct CacheEntry { + double key; + RefPtr value; + }; + + CacheEntry& lookup(double d) { return m_cache[WTF::FloatHash::hash(d) & (cacheSize - 1)]; } + + FixedArray m_cache; + }; + +} // namespace JSC + +#endif // DateInstanceCache_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DateMath.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DateMath.h new file mode 100644 index 000000000..fc1a8d8e4 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DateMath.h @@ -0,0 +1,126 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright (C) 2010 Research In Motion Limited. All rights reserved. + * + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + */ + +#ifndef DateMath_h +#define DateMath_h + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace WTF { + +void initializeDates(); +int equivalentYearForDST(int year); + +// Not really math related, but this is currently the only shared place to put these. +double parseES5DateFromNullTerminatedCharacters(const char* dateString); +WTF_EXPORT_PRIVATE double parseDateFromNullTerminatedCharacters(const char* dateString); +double parseDateFromNullTerminatedCharacters(const char* dateString, bool& haveTZ, int& offset); +double timeClip(double); +// dayOfWeek: [0, 6] 0 being Monday, day: [1, 31], month: [0, 11], year: ex: 2011, hours: [0, 23], minutes: [0, 59], seconds: [0, 59], utcOffset: [-720,720]. +String makeRFC2822DateString(unsigned dayOfWeek, unsigned day, unsigned month, unsigned year, unsigned hours, unsigned minutes, unsigned seconds, int utcOffset); + +inline double jsCurrentTime() +{ + // JavaScript doesn't recognize fractions of a millisecond. + return floor(WTF::currentTimeMS()); +} + +const char* const weekdayName[7] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" }; +const char* const monthName[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + +const double hoursPerDay = 24.0; +const double minutesPerHour = 60.0; +const double secondsPerHour = 60.0 * 60.0; +const double secondsPerMinute = 60.0; +const double msPerSecond = 1000.0; +const double msPerMinute = 60.0 * 1000.0; +const double msPerHour = 60.0 * 60.0 * 1000.0; +const double msPerDay = 24.0 * 60.0 * 60.0 * 1000.0; +const double msPerMonth = 2592000000.0; + +bool isLeapYear(int year); + +// Returns the number of days from 1970-01-01 to the specified date. +WTF_EXPORT_PRIVATE double dateToDaysFrom1970(int year, int month, int day); +WTF_EXPORT_PRIVATE int msToYear(double ms); +double msToDays(double ms); +int msToMinutes(double ms); +int msToHours(double ms); +WTF_EXPORT_PRIVATE int dayInYear(double ms, int year); +WTF_EXPORT_PRIVATE int monthFromDayInYear(int dayInYear, bool leapYear); +WTF_EXPORT_PRIVATE int dayInMonthFromDayInYear(int dayInYear, bool leapYear); + +// Returns offset milliseconds for UTC and DST. +WTF_EXPORT_PRIVATE int32_t calculateUTCOffset(); +WTF_EXPORT_PRIVATE double calculateDSTOffset(double ms, double utcOffset); + +} // namespace WTF + +using WTF::isLeapYear; +using WTF::dateToDaysFrom1970; +using WTF::dayInMonthFromDayInYear; +using WTF::dayInYear; +using WTF::minutesPerHour; +using WTF::monthFromDayInYear; +using WTF::msPerDay; +using WTF::msPerMinute; +using WTF::msPerSecond; +using WTF::msToYear; +using WTF::msToDays; +using WTF::msToMinutes; +using WTF::msToHours; +using WTF::secondsPerMinute; +using WTF::parseDateFromNullTerminatedCharacters; +using WTF::makeRFC2822DateString; +using WTF::calculateUTCOffset; +using WTF::calculateDSTOffset; + +#endif // DateMath_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Debugger.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Debugger.h new file mode 100644 index 000000000..a23732918 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Debugger.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) + * Copyright (C) 2001 Peter Kelly (pmk@post.com) + * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef Debugger_h +#define Debugger_h + +#include + +namespace JSC { + + class DebuggerCallFrame; + class ExecState; + class JSGlobalData; + class JSGlobalObject; + class JSValue; + class SourceProvider; + class UString; + + class JS_EXPORT_PRIVATE Debugger { + public: + virtual ~Debugger(); + + void attach(JSGlobalObject*); + virtual void detach(JSGlobalObject*); + + virtual void sourceParsed(ExecState*, SourceProvider*, int errorLineNumber, const UString& errorMessage) = 0; + virtual void exception(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber, bool hasHandler) = 0; + virtual void atStatement(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber) = 0; + virtual void callEvent(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber) = 0; + virtual void returnEvent(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber) = 0; + + virtual void willExecuteProgram(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber) = 0; + virtual void didExecuteProgram(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber) = 0; + virtual void didReachBreakpoint(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber) = 0; + + void recompileAllJSFunctions(JSGlobalData*); + + private: + HashSet m_globalObjects; + }; + + // This function exists only for backwards compatibility with existing WebScriptDebugger clients. + JS_EXPORT_PRIVATE JSValue evaluateInGlobalCallFrame(const UString&, JSValue& exception, JSGlobalObject*); + +} // namespace JSC + +#endif // Debugger_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DebuggerActivation.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DebuggerActivation.h new file mode 100644 index 000000000..8dba70b80 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DebuggerActivation.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 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 DebuggerActivation_h +#define DebuggerActivation_h + +#include "JSObject.h" + +namespace JSC { + + class DebuggerActivation : public JSNonFinalObject { + public: + typedef JSNonFinalObject Base; + + static DebuggerActivation* create(JSGlobalData& globalData, JSObject* object) + { + DebuggerActivation* activation = new (NotNull, allocateCell(globalData.heap)) DebuggerActivation(globalData); + activation->finishCreation(globalData, object); + return activation; + } + + static void visitChildren(JSCell*, SlotVisitor&); + static UString className(const JSObject*); + static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier& propertyName, PropertySlot&); + static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); + static void putDirectVirtual(JSObject*, ExecState*, const Identifier& propertyName, JSValue, unsigned attributes); + static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName); + static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); + static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); + static void defineGetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes); + static void defineSetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes); + + JS_EXPORTDATA static const ClassInfo s_info; + + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + { + return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); + } + + protected: + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | JSObject::StructureFlags; + + JS_EXPORT_PRIVATE void finishCreation(JSGlobalData&, JSObject* activation); + + private: + JS_EXPORT_PRIVATE DebuggerActivation(JSGlobalData&); + WriteBarrier m_activation; + }; + +} // namespace JSC + +#endif // DebuggerActivation_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DebuggerCallFrame.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DebuggerCallFrame.h new file mode 100644 index 000000000..8605af54d --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DebuggerCallFrame.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 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. + * 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 DebuggerCallFrame_h +#define DebuggerCallFrame_h + +#include "CallFrame.h" + +namespace JSC { + + class DebuggerCallFrame { + public: + enum Type { ProgramType, FunctionType }; + + DebuggerCallFrame(CallFrame* callFrame) + : m_callFrame(callFrame) + { + } + + DebuggerCallFrame(CallFrame* callFrame, JSValue exception) + : m_callFrame(callFrame) + , m_exception(exception) + { + } + + JSGlobalObject* dynamicGlobalObject() const { return m_callFrame->dynamicGlobalObject(); } + ScopeChainNode* scopeChain() const { return m_callFrame->scopeChain(); } + JS_EXPORT_PRIVATE const UString* functionName() const; + JS_EXPORT_PRIVATE UString calculatedFunctionName() const; + JS_EXPORT_PRIVATE Type type() const; + JS_EXPORT_PRIVATE JSObject* thisObject() const; + JS_EXPORT_PRIVATE JSValue evaluate(const UString&, JSValue& exception) const; + JSValue exception() const { return m_exception; } + + private: + CallFrame* m_callFrame; + JSValue m_exception; + }; + +} // namespace JSC + +#endif // DebuggerCallFrame_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DecimalNumber.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DecimalNumber.h new file mode 100644 index 000000000..61effcdd3 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DecimalNumber.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2010 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 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 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 DecimalNumber_h +#define DecimalNumber_h + +#include +#include +#include +#include + +namespace WTF { + +enum RoundingSignificantFiguresType { RoundingSignificantFigures }; +enum RoundingDecimalPlacesType { RoundingDecimalPlaces }; + +class DecimalNumber { +public: + DecimalNumber(double d) + { + ASSERT(isfinite(d)); + dtoa(m_significand, d, m_sign, m_exponent, m_precision); + + ASSERT(m_precision); + // Zero should always have exponent 0. + ASSERT(m_significand[0] != '0' || !m_exponent); + // No values other than zero should have a leading zero. + ASSERT(m_significand[0] != '0' || m_precision == 1); + // No values other than zero should have trailing zeros. + ASSERT(m_significand[0] == '0' || m_significand[m_precision - 1] != '0'); + } + + DecimalNumber(double d, RoundingSignificantFiguresType, unsigned significantFigures) + { + ASSERT(isfinite(d)); + dtoaRoundSF(m_significand, d, significantFigures, m_sign, m_exponent, m_precision); + + ASSERT(significantFigures && significantFigures <= sizeof(DtoaBuffer)); + while (m_precision < significantFigures) + m_significand[m_precision++] = '0'; + + ASSERT(m_precision); + // Zero should always have exponent 0. + ASSERT(m_significand[0] != '0' || !m_exponent); + } + + DecimalNumber(double d, RoundingDecimalPlacesType, unsigned decimalPlaces) + { + ASSERT(isfinite(d)); + dtoaRoundDP(m_significand, d, decimalPlaces, m_sign, m_exponent, m_precision); + + unsigned significantFigures = 1 + m_exponent + decimalPlaces; + ASSERT(significantFigures && significantFigures <= sizeof(DtoaBuffer)); + while (m_precision < significantFigures) + m_significand[m_precision++] = '0'; + + ASSERT(m_precision); + // Zero should always have exponent 0. + ASSERT(m_significand[0] != '0' || !m_exponent); + } + + WTF_EXPORT_PRIVATE unsigned bufferLengthForStringDecimal() const; + WTF_EXPORT_PRIVATE unsigned bufferLengthForStringExponential() const; + + WTF_EXPORT_PRIVATE unsigned toStringDecimal(UChar* buffer, unsigned bufferLength) const; + WTF_EXPORT_PRIVATE unsigned toStringExponential(UChar* buffer, unsigned bufferLength) const; + + bool sign() const { return m_sign; } + int exponent() const { return m_exponent; } + const char* significand() const { return m_significand; } // significand contains precision characters, is not null-terminated. + unsigned precision() const { return m_precision; } + +private: + bool m_sign; + int m_exponent; + DtoaBuffer m_significand; + unsigned m_precision; +}; + +} // namespace WTF + +using WTF::DecimalNumber; +using WTF::RoundingSignificantFigures; +using WTF::RoundingDecimalPlaces; + +#endif // DecimalNumber_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Decoder.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Decoder.h new file mode 100644 index 000000000..341d58d73 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Decoder.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2011 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 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 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 Decoder_h +#define Decoder_h + +#include + +namespace WTF { + +class String; + +class Decoder { +protected: + Decoder() { } + virtual ~Decoder() { } + +public: + virtual bool decodeBytes(Vector&) = 0; + + virtual bool decodeBool(bool&) = 0; + virtual bool decodeUInt32(uint32_t&) = 0; + virtual bool decodeUInt64(uint64_t&) = 0; + virtual bool decodeInt32(int32_t&) = 0; + virtual bool decodeInt64(int64_t&) = 0; + virtual bool decodeFloat(float&) = 0; + virtual bool decodeDouble(double&) = 0; + virtual bool decodeString(String&) = 0; +}; + +} // namespace WTF + +using WTF::Decoder; + +#endif // Decoder_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Deque.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Deque.h new file mode 100644 index 000000000..18eb10582 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Deque.h @@ -0,0 +1,690 @@ +/* + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * 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: + * + * 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 WTF_Deque_h +#define WTF_Deque_h + +// FIXME: Could move what Vector and Deque share into a separate file. +// Deque doesn't actually use Vector. + +#include "PassTraits.h" +#include "Vector.h" + +namespace WTF { + + template class DequeIteratorBase; + template class DequeIterator; + template class DequeConstIterator; + template class DequeReverseIterator; + template class DequeConstReverseIterator; + + template + class Deque { + WTF_MAKE_FAST_ALLOCATED; + public: + typedef DequeIterator iterator; + typedef DequeConstIterator const_iterator; + typedef DequeReverseIterator reverse_iterator; + typedef DequeConstReverseIterator const_reverse_iterator; + typedef PassTraits Pass; + typedef typename PassTraits::PassType PassType; + + Deque(); + Deque(const Deque&); + Deque& operator=(const Deque&); + ~Deque(); + + void swap(Deque&); + + size_t size() const { return m_start <= m_end ? m_end - m_start : m_end + m_buffer.capacity() - m_start; } + bool isEmpty() const { return m_start == m_end; } + + iterator begin() { return iterator(this, m_start); } + iterator end() { return iterator(this, m_end); } + const_iterator begin() const { return const_iterator(this, m_start); } + const_iterator end() const { return const_iterator(this, m_end); } + reverse_iterator rbegin() { return reverse_iterator(this, m_end); } + reverse_iterator rend() { return reverse_iterator(this, m_start); } + const_reverse_iterator rbegin() const { return const_reverse_iterator(this, m_end); } + const_reverse_iterator rend() const { return const_reverse_iterator(this, m_start); } + + T& first() { ASSERT(m_start != m_end); return m_buffer.buffer()[m_start]; } + const T& first() const { ASSERT(m_start != m_end); return m_buffer.buffer()[m_start]; } + PassType takeFirst(); + + T& last() { ASSERT(m_start != m_end); return *(--end()); } + const T& last() const { ASSERT(m_start != m_end); return *(--end()); } + + template void append(const U&); + template void prepend(const U&); + void removeFirst(); + void remove(iterator&); + void remove(const_iterator&); + + void clear(); + + template + iterator findIf(Predicate&); + + private: + friend class DequeIteratorBase; + + typedef VectorBuffer Buffer; + typedef VectorTypeOperations TypeOperations; + typedef DequeIteratorBase IteratorBase; + + void remove(size_t position); + void invalidateIterators(); + void destroyAll(); + void checkValidity() const; + void checkIndexValidity(size_t) const; + void expandCapacityIfNeeded(); + void expandCapacity(); + + size_t m_start; + size_t m_end; + Buffer m_buffer; +#ifndef NDEBUG + mutable IteratorBase* m_iterators; +#endif + }; + + template + class DequeIteratorBase { + private: + typedef DequeIteratorBase Base; + + protected: + DequeIteratorBase(); + DequeIteratorBase(const Deque*, size_t); + DequeIteratorBase(const Base&); + Base& operator=(const Base&); + ~DequeIteratorBase(); + + void assign(const Base& other) { *this = other; } + + void increment(); + void decrement(); + + T* before() const; + T* after() const; + + bool isEqual(const Base&) const; + + private: + void addToIteratorsList(); + void removeFromIteratorsList(); + void checkValidity() const; + void checkValidity(const Base&) const; + + Deque* m_deque; + size_t m_index; + + friend class Deque; + +#ifndef NDEBUG + mutable DequeIteratorBase* m_next; + mutable DequeIteratorBase* m_previous; +#endif + }; + + template + class DequeIterator : public DequeIteratorBase { + private: + typedef DequeIteratorBase Base; + typedef DequeIterator Iterator; + + public: + DequeIterator(Deque* deque, size_t index) : Base(deque, index) { } + + DequeIterator(const Iterator& other) : Base(other) { } + DequeIterator& operator=(const Iterator& other) { Base::assign(other); return *this; } + + T& operator*() const { return *Base::after(); } + T* operator->() const { return Base::after(); } + + bool operator==(const Iterator& other) const { return Base::isEqual(other); } + bool operator!=(const Iterator& other) const { return !Base::isEqual(other); } + + Iterator& operator++() { Base::increment(); return *this; } + // postfix ++ intentionally omitted + Iterator& operator--() { Base::decrement(); return *this; } + // postfix -- intentionally omitted + }; + + template + class DequeConstIterator : public DequeIteratorBase { + private: + typedef DequeIteratorBase Base; + typedef DequeConstIterator Iterator; + typedef DequeIterator NonConstIterator; + + public: + DequeConstIterator(const Deque* deque, size_t index) : Base(deque, index) { } + + DequeConstIterator(const Iterator& other) : Base(other) { } + DequeConstIterator(const NonConstIterator& other) : Base(other) { } + DequeConstIterator& operator=(const Iterator& other) { Base::assign(other); return *this; } + DequeConstIterator& operator=(const NonConstIterator& other) { Base::assign(other); return *this; } + + const T& operator*() const { return *Base::after(); } + const T* operator->() const { return Base::after(); } + + bool operator==(const Iterator& other) const { return Base::isEqual(other); } + bool operator!=(const Iterator& other) const { return !Base::isEqual(other); } + + Iterator& operator++() { Base::increment(); return *this; } + // postfix ++ intentionally omitted + Iterator& operator--() { Base::decrement(); return *this; } + // postfix -- intentionally omitted + }; + + template + class DequeReverseIterator : public DequeIteratorBase { + private: + typedef DequeIteratorBase Base; + typedef DequeReverseIterator Iterator; + + public: + DequeReverseIterator(const Deque* deque, size_t index) : Base(deque, index) { } + + DequeReverseIterator(const Iterator& other) : Base(other) { } + DequeReverseIterator& operator=(const Iterator& other) { Base::assign(other); return *this; } + + T& operator*() const { return *Base::before(); } + T* operator->() const { return Base::before(); } + + bool operator==(const Iterator& other) const { return Base::isEqual(other); } + bool operator!=(const Iterator& other) const { return !Base::isEqual(other); } + + Iterator& operator++() { Base::decrement(); return *this; } + // postfix ++ intentionally omitted + Iterator& operator--() { Base::increment(); return *this; } + // postfix -- intentionally omitted + }; + + template + class DequeConstReverseIterator : public DequeIteratorBase { + private: + typedef DequeIteratorBase Base; + typedef DequeConstReverseIterator Iterator; + typedef DequeReverseIterator NonConstIterator; + + public: + DequeConstReverseIterator(const Deque* deque, size_t index) : Base(deque, index) { } + + DequeConstReverseIterator(const Iterator& other) : Base(other) { } + DequeConstReverseIterator(const NonConstIterator& other) : Base(other) { } + DequeConstReverseIterator& operator=(const Iterator& other) { Base::assign(other); return *this; } + DequeConstReverseIterator& operator=(const NonConstIterator& other) { Base::assign(other); return *this; } + + const T& operator*() const { return *Base::before(); } + const T* operator->() const { return Base::before(); } + + bool operator==(const Iterator& other) const { return Base::isEqual(other); } + bool operator!=(const Iterator& other) const { return !Base::isEqual(other); } + + Iterator& operator++() { Base::decrement(); return *this; } + // postfix ++ intentionally omitted + Iterator& operator--() { Base::increment(); return *this; } + // postfix -- intentionally omitted + }; + +#ifdef NDEBUG + template inline void Deque::checkValidity() const { } + template inline void Deque::checkIndexValidity(size_t) const { } + template inline void Deque::invalidateIterators() { } +#else + template + void Deque::checkValidity() const + { + // In this implementation a capacity of 1 would confuse append() and + // other places that assume the index after capacity - 1 is 0. + ASSERT(m_buffer.capacity() != 1); + + if (!m_buffer.capacity()) { + ASSERT(!m_start); + ASSERT(!m_end); + } else { + ASSERT(m_start < m_buffer.capacity()); + ASSERT(m_end < m_buffer.capacity()); + } + } + + template + void Deque::checkIndexValidity(size_t index) const + { + ASSERT_UNUSED(index, index <= m_buffer.capacity()); + if (m_start <= m_end) { + ASSERT(index >= m_start); + ASSERT(index <= m_end); + } else { + ASSERT(index >= m_start || index <= m_end); + } + } + + template + void Deque::invalidateIterators() + { + IteratorBase* next; + for (IteratorBase* p = m_iterators; p; p = next) { + next = p->m_next; + p->m_deque = 0; + p->m_next = 0; + p->m_previous = 0; + } + m_iterators = 0; + } +#endif + + template + inline Deque::Deque() + : m_start(0) + , m_end(0) +#ifndef NDEBUG + , m_iterators(0) +#endif + { + checkValidity(); + } + + template + inline Deque::Deque(const Deque& other) + : m_start(other.m_start) + , m_end(other.m_end) + , m_buffer(other.m_buffer.capacity()) +#ifndef NDEBUG + , m_iterators(0) +#endif + { + const T* otherBuffer = other.m_buffer.buffer(); + if (m_start <= m_end) + TypeOperations::uninitializedCopy(otherBuffer + m_start, otherBuffer + m_end, m_buffer.buffer() + m_start); + else { + TypeOperations::uninitializedCopy(otherBuffer, otherBuffer + m_end, m_buffer.buffer()); + TypeOperations::uninitializedCopy(otherBuffer + m_start, otherBuffer + m_buffer.capacity(), m_buffer.buffer() + m_start); + } + } + + template + void deleteAllValues(const Deque& collection) + { + typedef typename Deque::const_iterator iterator; + iterator end = collection.end(); + for (iterator it = collection.begin(); it != end; ++it) + delete *it; + } + + template + inline Deque& Deque::operator=(const Deque& other) + { + // FIXME: This is inefficient if we're using an inline buffer and T is + // expensive to copy since it will copy the buffer twice instead of once. + Deque copy(other); + swap(copy); + return *this; + } + + template + inline void Deque::destroyAll() + { + if (m_start <= m_end) + TypeOperations::destruct(m_buffer.buffer() + m_start, m_buffer.buffer() + m_end); + else { + TypeOperations::destruct(m_buffer.buffer(), m_buffer.buffer() + m_end); + TypeOperations::destruct(m_buffer.buffer() + m_start, m_buffer.buffer() + m_buffer.capacity()); + } + } + + template + inline Deque::~Deque() + { + checkValidity(); + invalidateIterators(); + destroyAll(); + } + + template + inline void Deque::swap(Deque& other) + { + checkValidity(); + other.checkValidity(); + invalidateIterators(); + std::swap(m_start, other.m_start); + std::swap(m_end, other.m_end); + m_buffer.swap(other.m_buffer); + checkValidity(); + other.checkValidity(); + } + + template + inline void Deque::clear() + { + checkValidity(); + invalidateIterators(); + destroyAll(); + m_start = 0; + m_end = 0; + checkValidity(); + } + + template + template + inline DequeIterator Deque::findIf(Predicate& predicate) + { + iterator end_iterator = end(); + for (iterator it = begin(); it != end_iterator; ++it) { + if (predicate(*it)) + return it; + } + return end_iterator; + } + + template + inline void Deque::expandCapacityIfNeeded() + { + if (m_start) { + if (m_end + 1 != m_start) + return; + } else if (m_end) { + if (m_end != m_buffer.capacity() - 1) + return; + } else if (m_buffer.capacity()) + return; + + expandCapacity(); + } + + template + void Deque::expandCapacity() + { + checkValidity(); + size_t oldCapacity = m_buffer.capacity(); + size_t newCapacity = max(static_cast(16), oldCapacity + oldCapacity / 4 + 1); + T* oldBuffer = m_buffer.buffer(); + m_buffer.allocateBuffer(newCapacity); + if (m_start <= m_end) + TypeOperations::move(oldBuffer + m_start, oldBuffer + m_end, m_buffer.buffer() + m_start); + else { + TypeOperations::move(oldBuffer, oldBuffer + m_end, m_buffer.buffer()); + size_t newStart = newCapacity - (oldCapacity - m_start); + TypeOperations::move(oldBuffer + m_start, oldBuffer + oldCapacity, m_buffer.buffer() + newStart); + m_start = newStart; + } + m_buffer.deallocateBuffer(oldBuffer); + checkValidity(); + } + + template + inline typename Deque::PassType Deque::takeFirst() + { + T oldFirst = Pass::transfer(first()); + removeFirst(); + return Pass::transfer(oldFirst); + } + + template template + inline void Deque::append(const U& value) + { + checkValidity(); + expandCapacityIfNeeded(); + new (NotNull, &m_buffer.buffer()[m_end]) T(value); + if (m_end == m_buffer.capacity() - 1) + m_end = 0; + else + ++m_end; + checkValidity(); + } + + template template + inline void Deque::prepend(const U& value) + { + checkValidity(); + expandCapacityIfNeeded(); + if (!m_start) + m_start = m_buffer.capacity() - 1; + else + --m_start; + new (NotNull, &m_buffer.buffer()[m_start]) T(value); + checkValidity(); + } + + template + inline void Deque::removeFirst() + { + checkValidity(); + invalidateIterators(); + ASSERT(!isEmpty()); + TypeOperations::destruct(&m_buffer.buffer()[m_start], &m_buffer.buffer()[m_start + 1]); + if (m_start == m_buffer.capacity() - 1) + m_start = 0; + else + ++m_start; + checkValidity(); + } + + template + inline void Deque::remove(iterator& it) + { + it.checkValidity(); + remove(it.m_index); + } + + template + inline void Deque::remove(const_iterator& it) + { + it.checkValidity(); + remove(it.m_index); + } + + template + inline void Deque::remove(size_t position) + { + if (position == m_end) + return; + + checkValidity(); + invalidateIterators(); + + T* buffer = m_buffer.buffer(); + TypeOperations::destruct(&buffer[position], &buffer[position + 1]); + + // Find which segment of the circular buffer contained the remove element, and only move elements in that part. + if (position >= m_start) { + TypeOperations::moveOverlapping(buffer + m_start, buffer + position, buffer + m_start + 1); + m_start = (m_start + 1) % m_buffer.capacity(); + } else { + TypeOperations::moveOverlapping(buffer + position + 1, buffer + m_end, buffer + position); + m_end = (m_end - 1 + m_buffer.capacity()) % m_buffer.capacity(); + } + checkValidity(); + } + +#ifdef NDEBUG + template inline void DequeIteratorBase::checkValidity() const { } + template inline void DequeIteratorBase::checkValidity(const DequeIteratorBase&) const { } + template inline void DequeIteratorBase::addToIteratorsList() { } + template inline void DequeIteratorBase::removeFromIteratorsList() { } +#else + template + void DequeIteratorBase::checkValidity() const + { + ASSERT(m_deque); + m_deque->checkIndexValidity(m_index); + } + + template + void DequeIteratorBase::checkValidity(const Base& other) const + { + checkValidity(); + other.checkValidity(); + ASSERT(m_deque == other.m_deque); + } + + template + void DequeIteratorBase::addToIteratorsList() + { + if (!m_deque) + m_next = 0; + else { + m_next = m_deque->m_iterators; + m_deque->m_iterators = this; + if (m_next) + m_next->m_previous = this; + } + m_previous = 0; + } + + template + void DequeIteratorBase::removeFromIteratorsList() + { + if (!m_deque) { + ASSERT(!m_next); + ASSERT(!m_previous); + } else { + if (m_next) { + ASSERT(m_next->m_previous == this); + m_next->m_previous = m_previous; + } + if (m_previous) { + ASSERT(m_deque->m_iterators != this); + ASSERT(m_previous->m_next == this); + m_previous->m_next = m_next; + } else { + ASSERT(m_deque->m_iterators == this); + m_deque->m_iterators = m_next; + } + } + m_next = 0; + m_previous = 0; + } +#endif + + template + inline DequeIteratorBase::DequeIteratorBase() + : m_deque(0) + { + } + + template + inline DequeIteratorBase::DequeIteratorBase(const Deque* deque, size_t index) + : m_deque(const_cast*>(deque)) + , m_index(index) + { + addToIteratorsList(); + checkValidity(); + } + + template + inline DequeIteratorBase::DequeIteratorBase(const Base& other) + : m_deque(other.m_deque) + , m_index(other.m_index) + { + addToIteratorsList(); + checkValidity(); + } + + template + inline DequeIteratorBase& DequeIteratorBase::operator=(const Base& other) + { + other.checkValidity(); + removeFromIteratorsList(); + + m_deque = other.m_deque; + m_index = other.m_index; + addToIteratorsList(); + checkValidity(); + return *this; + } + + template + inline DequeIteratorBase::~DequeIteratorBase() + { +#ifndef NDEBUG + removeFromIteratorsList(); + m_deque = 0; +#endif + } + + template + inline bool DequeIteratorBase::isEqual(const Base& other) const + { + checkValidity(other); + return m_index == other.m_index; + } + + template + inline void DequeIteratorBase::increment() + { + checkValidity(); + ASSERT(m_index != m_deque->m_end); + ASSERT(m_deque->m_buffer.capacity()); + if (m_index == m_deque->m_buffer.capacity() - 1) + m_index = 0; + else + ++m_index; + checkValidity(); + } + + template + inline void DequeIteratorBase::decrement() + { + checkValidity(); + ASSERT(m_index != m_deque->m_start); + ASSERT(m_deque->m_buffer.capacity()); + if (!m_index) + m_index = m_deque->m_buffer.capacity() - 1; + else + --m_index; + checkValidity(); + } + + template + inline T* DequeIteratorBase::after() const + { + checkValidity(); + ASSERT(m_index != m_deque->m_end); + return &m_deque->m_buffer.buffer()[m_index]; + } + + template + inline T* DequeIteratorBase::before() const + { + checkValidity(); + ASSERT(m_index != m_deque->m_start); + if (!m_index) + return &m_deque->m_buffer.buffer()[m_deque->m_buffer.capacity() - 1]; + return &m_deque->m_buffer.buffer()[m_index - 1]; + } + +} // namespace WTF + +using WTF::Deque; + +#endif // WTF_Deque_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DisallowCType.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DisallowCType.h new file mode 100644 index 000000000..436f7f214 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DisallowCType.h @@ -0,0 +1,74 @@ +/* + * 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. + * 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 WTF_DisallowCType_h +#define WTF_DisallowCType_h + +// The behavior of many of the functions in the header is dependent +// on the current locale. But almost all uses of these functions are for +// locale-independent, ASCII-specific purposes. In WebKit code we use our own +// ASCII-specific functions instead. This header makes sure we get a compile-time +// error if we use one of the functions by accident. + +#include + +#undef isalnum +#undef isalpha +#undef isascii +#undef isblank +#undef iscntrl +#undef isdigit +#undef isgraph +#undef islower +#undef isprint +#undef ispunct +#undef isspace +#undef isupper +#undef isxdigit +#undef toascii +#undef tolower +#undef toupper + +#define isalnum isalnum_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h +#define isalpha isalpha_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h +#define isascii isascii_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h +#define isblank isblank_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h +#define iscntrl iscntrl_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h +#define isdigit isdigit_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h +#define isgraph isgraph_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h +#define islower islower_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h +#define isprint isprint_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h +#define ispunct ispunct_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h +#define isspace isspace_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h +#define isupper isupper_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h +#define isxdigit isxdigit_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h +#define toascii toascii_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h +#define tolower tolower_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h +#define toupper toupper_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DoublyLinkedList.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DoublyLinkedList.h new file mode 100644 index 000000000..361d71d7b --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DoublyLinkedList.h @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2011 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 INC. 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 INC. 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 DoublyLinkedList_h +#define DoublyLinkedList_h + +namespace WTF { + +// This class allows nodes to share code without dictating data member layout. +template class DoublyLinkedListNode { +public: + DoublyLinkedListNode(); + + void setPrev(T*); + void setNext(T*); + + T* prev() const; + T* next() const; +}; + +template inline DoublyLinkedListNode::DoublyLinkedListNode() +{ + setPrev(0); + setNext(0); +} + +template inline void DoublyLinkedListNode::setPrev(T* prev) +{ + static_cast(this)->m_prev = prev; +} + +template inline void DoublyLinkedListNode::setNext(T* next) +{ + static_cast(this)->m_next = next; +} + +template inline T* DoublyLinkedListNode::prev() const +{ + return static_cast(this)->m_prev; +} + +template inline T* DoublyLinkedListNode::next() const +{ + return static_cast(this)->m_next; +} + +template class DoublyLinkedList { +public: + DoublyLinkedList(); + + bool isEmpty() const; + size_t size() const; // This is O(n). + void clear(); + + T* head() const; + T* removeHead(); + + void push(T*); + void append(T*); + void remove(T*); + +private: + T* m_head; + T* m_tail; +}; + +template inline DoublyLinkedList::DoublyLinkedList() + : m_head(0) + , m_tail(0) +{ +} + +template inline bool DoublyLinkedList::isEmpty() const +{ + return !m_head; +} + +template inline size_t DoublyLinkedList::size() const +{ + size_t size = 0; + for (T* node = m_head; node; node = node->next()) + ++size; + return size; +} + +template inline void DoublyLinkedList::clear() +{ + m_head = 0; + m_tail = 0; +} + +template inline T* DoublyLinkedList::head() const +{ + return m_head; +} + +template inline void DoublyLinkedList::push(T* node) +{ + if (!m_head) { + ASSERT(!m_tail); + m_head = node; + m_tail = node; + node->setPrev(0); + node->setNext(0); + return; + } + + ASSERT(m_tail); + m_head->setPrev(node); + node->setNext(m_head); + node->setPrev(0); + m_head = node; +} + +template inline void DoublyLinkedList::append(T* node) +{ + if (!m_tail) { + ASSERT(!m_head); + m_head = node; + m_tail = node; + node->setPrev(0); + node->setNext(0); + return; + } + + ASSERT(m_head); + m_tail->setNext(node); + node->setPrev(m_tail); + node->setNext(0); + m_tail = node; +} + +template inline void DoublyLinkedList::remove(T* node) +{ + if (node->prev()) { + ASSERT(node != m_head); + node->prev()->setNext(node->next()); + } else { + ASSERT(node == m_head); + m_head = node->next(); + } + + if (node->next()) { + ASSERT(node != m_tail); + node->next()->setPrev(node->prev()); + } else { + ASSERT(node == m_tail); + m_tail = node->prev(); + } +} + +template inline T* DoublyLinkedList::removeHead() +{ + T* node = head(); + if (node) + remove(node); + return node; +} + +} // namespace WTF + +using WTF::DoublyLinkedListNode; +using WTF::DoublyLinkedList; + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DynamicAnnotations.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DynamicAnnotations.h new file mode 100644 index 000000000..38acce35e --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/DynamicAnnotations.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2011 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. + * * 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 WTF_DynamicAnnotations_h +#define WTF_DynamicAnnotations_h + +/* This file defines dynamic annotations for use with dynamic analysis + * tool such as ThreadSanitizer, Valgrind, etc. + * + * Dynamic annotation is a source code annotation that affects + * the generated code (that is, the annotation is not a comment). + * Each such annotation is attached to a particular + * instruction and/or to a particular object (address) in the program. + * + * By using dynamic annotations a developer can give more details to the dynamic + * analysis tool to improve its precision. + * + * In C/C++ program the annotations are represented as C macros. + * With the default build flags, these macros are empty, hence don't affect + * performance of a compiled binary. + * If dynamic annotations are enabled, they just call no-op functions. + * The dynamic analysis tools can intercept these functions and replace them + * with their own implementations. + * + * See http://code.google.com/p/data-race-test/wiki/DynamicAnnotations for more information. + */ + +#if USE(DYNAMIC_ANNOTATIONS) +/* Tell data race detector that we're not interested in reports on the given address range. */ +#define WTF_ANNOTATE_BENIGN_RACE_SIZED(address, size, description) WTFAnnotateBenignRaceSized(__FILE__, __LINE__, address, size, description) +#define WTF_ANNOTATE_BENIGN_RACE(pointer, description) WTFAnnotateBenignRaceSized(__FILE__, __LINE__, pointer, sizeof(*(pointer)), description) + +/* Annotations for user-defined synchronization mechanisms. + * These annotations can be used to define happens-before arcs in user-defined + * synchronization mechanisms: the race detector will infer an arc from + * the former to the latter when they share the same argument pointer. + * + * The most common case requiring annotations is atomic reference counting: + * bool deref() { + * ANNOTATE_HAPPENS_BEFORE(&m_refCount); + * if (!atomicDecrement(&m_refCount)) { + * // m_refCount is now 0 + * ANNOTATE_HAPPENS_AFTER(&m_refCount); + * // "return true; happens-after each atomicDecrement of m_refCount" + * return true; + * } + * return false; + * } + */ +#define WTF_ANNOTATE_HAPPENS_BEFORE(address) WTFAnnotateHappensBefore(__FILE__, __LINE__, address) +#define WTF_ANNOTATE_HAPPENS_AFTER(address) WTFAnnotateHappensAfter(__FILE__, __LINE__, address) + +#ifdef __cplusplus +extern "C" { +#endif +/* Don't use these directly, use the above macros instead. */ +void WTFAnnotateBenignRaceSized(const char* file, int line, const volatile void* memory, long size, const char* description); +void WTFAnnotateHappensBefore(const char* file, int line, const volatile void* address); +void WTFAnnotateHappensAfter(const char* file, int line, const volatile void* address); +#ifdef __cplusplus +} // extern "C" +#endif + +#else // USE(DYNAMIC_ANNOTATIONS) +/* These macros are empty when dynamic annotations are not enabled so you can + * use them without affecting the performance of release binaries. */ +#define WTF_ANNOTATE_BENIGN_RACE_SIZED(address, size, description) +#define WTF_ANNOTATE_BENIGN_RACE(pointer, description) +#define WTF_ANNOTATE_HAPPENS_BEFORE(address) +#define WTF_ANNOTATE_HAPPENS_AFTER(address) +#endif // USE(DYNAMIC_ANNOTATIONS) + +#endif // WTF_DynamicAnnotations_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Encoder.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Encoder.h new file mode 100644 index 000000000..109b0db8d --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Encoder.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2011 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 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 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 Encoder_h +#define Encoder_h + +#include + +namespace WTF { + +class String; + +class Encoder { +protected: + Encoder() { } + virtual ~Encoder() { } + +public: + virtual void encodeBytes(const uint8_t*, size_t) = 0; + + virtual void encodeBool(bool) = 0; + virtual void encodeUInt32(uint32_t) = 0; + virtual void encodeUInt64(uint64_t) = 0; + virtual void encodeInt32(int32_t) = 0; + virtual void encodeInt64(int64_t) = 0; + virtual void encodeFloat(float) = 0; + virtual void encodeDouble(double) = 0; + virtual void encodeString(const String&) = 0; +}; + +} // namespace WTF + +using WTF::Encoder; + +#endif // Encoder_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Error.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Error.h new file mode 100644 index 000000000..59b39495f --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Error.h @@ -0,0 +1,133 @@ +/* + * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) + * Copyright (C) 2001 Peter Kelly (pmk@post.com) + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef Error_h +#define Error_h + +#include "InternalFunction.h" +#include "Interpreter.h" +#include "JSObject.h" +#include + +namespace JSC { + + class ExecState; + class JSGlobalData; + class JSGlobalObject; + class JSObject; + class SourceCode; + class Structure; + class UString; + + // Methods to create a range of internal errors. + JSObject* createError(JSGlobalObject*, const UString&); + JSObject* createEvalError(JSGlobalObject*, const UString&); + JSObject* createRangeError(JSGlobalObject*, const UString&); + JSObject* createReferenceError(JSGlobalObject*, const UString&); + JSObject* createSyntaxError(JSGlobalObject*, const UString&); + JSObject* createTypeError(JSGlobalObject*, const UString&); + JSObject* createURIError(JSGlobalObject*, const UString&); + // ExecState wrappers. + JS_EXPORT_PRIVATE JSObject* createError(ExecState*, const UString&); + JSObject* createEvalError(ExecState*, const UString&); + JS_EXPORT_PRIVATE JSObject* createRangeError(ExecState*, const UString&); + JS_EXPORT_PRIVATE JSObject* createReferenceError(ExecState*, const UString&); + JS_EXPORT_PRIVATE JSObject* createSyntaxError(ExecState*, const UString&); + JS_EXPORT_PRIVATE JSObject* createTypeError(ExecState*, const UString&); + JSObject* createURIError(ExecState*, const UString&); + + // Methods to add + bool hasErrorInfo(ExecState*, JSObject* error); + JSObject* addErrorInfo(JSGlobalData*, JSObject* error, int line, const SourceCode&, const Vector&); + // ExecState wrappers. + JSObject* addErrorInfo(ExecState*, JSObject* error, int line, const SourceCode&, const Vector&); + + // Methods to throw Errors. + JS_EXPORT_PRIVATE JSValue throwError(ExecState*, JSValue); + JS_EXPORT_PRIVATE JSObject* throwError(ExecState*, JSObject*); + + // Convenience wrappers, create an throw an exception with a default message. + JS_EXPORT_PRIVATE JSObject* throwTypeError(ExecState*); + JS_EXPORT_PRIVATE JSObject* throwSyntaxError(ExecState*); + + // Convenience wrappers, wrap result as an EncodedJSValue. + inline EncodedJSValue throwVMError(ExecState* exec, JSValue error) { return JSValue::encode(throwError(exec, error)); } + inline EncodedJSValue throwVMTypeError(ExecState* exec) { return JSValue::encode(throwTypeError(exec)); } + + class StrictModeTypeErrorFunction : public InternalFunction { + private: + StrictModeTypeErrorFunction(JSGlobalObject* globalObject, Structure* structure, const UString& message) + : InternalFunction(globalObject, structure) + , m_message(message) + { + } + + static void destroy(JSCell*); + + public: + typedef InternalFunction Base; + + static StrictModeTypeErrorFunction* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, const UString& message) + { + StrictModeTypeErrorFunction* function = new (NotNull, allocateCell(*exec->heap())) StrictModeTypeErrorFunction(globalObject, structure, message); + function->finishCreation(exec->globalData(), exec->globalData().propertyNames->emptyIdentifier); + return function; + } + + static EncodedJSValue JSC_HOST_CALL constructThrowTypeError(ExecState* exec) + { + throwTypeError(exec, static_cast(exec->callee())->m_message); + return JSValue::encode(jsNull()); + } + + static ConstructType getConstructData(JSCell*, ConstructData& constructData) + { + constructData.native.function = constructThrowTypeError; + return ConstructTypeHost; + } + + static EncodedJSValue JSC_HOST_CALL callThrowTypeError(ExecState* exec) + { + throwTypeError(exec, static_cast(exec->callee())->m_message); + return JSValue::encode(jsNull()); + } + + static CallType getCallData(JSCell*, CallData& callData) + { + callData.native.function = callThrowTypeError; + return CallTypeHost; + } + + static const ClassInfo s_info; + + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + { + return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); + } + + private: + UString m_message; + }; + +} // namespace JSC + +#endif // Error_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ExceptionHelpers.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ExceptionHelpers.h new file mode 100644 index 000000000..388235b0d --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ExceptionHelpers.h @@ -0,0 +1,114 @@ +/* + * Copyright (C) 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. + * 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 ExceptionHelpers_h +#define ExceptionHelpers_h + +#include "JSObject.h" + +namespace JSC { + +JS_EXPORT_PRIVATE JSObject* createInterruptedExecutionException(JSGlobalData*); +bool isInterruptedExecutionException(JSObject*); +bool isInterruptedExecutionException(JSValue); + +JSObject* createTerminatedExecutionException(JSGlobalData*); +bool isTerminatedExecutionException(JSObject*); +JS_EXPORT_PRIVATE bool isTerminatedExecutionException(JSValue); + +JS_EXPORT_PRIVATE JSObject* createStackOverflowError(ExecState*); +JSObject* createStackOverflowError(JSGlobalObject*); +JSObject* createOutOfMemoryError(JSGlobalObject*); +JSObject* createUndefinedVariableError(ExecState*, const Identifier&); +JSObject* createNotAnObjectError(ExecState*, JSValue); +JSObject* createInvalidParamError(ExecState*, const char* op, JSValue); +JSObject* createNotAConstructorError(ExecState*, JSValue); +JSObject* createNotAFunctionError(ExecState*, JSValue); +JSObject* createErrorForInvalidGlobalAssignment(ExecState*, const UString&); + +JSObject* throwOutOfMemoryError(ExecState*); +JSObject* throwStackOverflowError(ExecState*); + + +class InterruptedExecutionError : public JSNonFinalObject { +private: + InterruptedExecutionError(JSGlobalData& globalData) + : JSNonFinalObject(globalData, globalData.interruptedExecutionErrorStructure.get()) + { + } + + static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType); + +public: + typedef JSNonFinalObject Base; + + static InterruptedExecutionError* create(JSGlobalData& globalData) + { + InterruptedExecutionError* error = new (NotNull, allocateCell(globalData.heap)) InterruptedExecutionError(globalData); + error->finishCreation(globalData); + return error; + } + + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + { + return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); + } + + static JS_EXPORTDATA const ClassInfo s_info; +}; + +class TerminatedExecutionError : public JSNonFinalObject { +private: + TerminatedExecutionError(JSGlobalData& globalData) + : JSNonFinalObject(globalData, globalData.terminatedExecutionErrorStructure.get()) + { + } + + static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType); + +public: + typedef JSNonFinalObject Base; + + static TerminatedExecutionError* create(JSGlobalData& globalData) + { + TerminatedExecutionError* error = new (NotNull, allocateCell(globalData.heap)) TerminatedExecutionError(globalData); + error->finishCreation(globalData); + return error; + } + + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + { + return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); + } + + static JS_EXPORTDATA const ClassInfo s_info; +}; + +} // namespace JSC + +#endif // ExceptionHelpers_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Executable.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Executable.h new file mode 100644 index 000000000..86080fe68 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Executable.h @@ -0,0 +1,716 @@ +/* + * Copyright (C) 2009, 2010 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 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 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 Executable_h +#define Executable_h + +#include "CallData.h" +#include "JSFunction.h" +#include "Interpreter.h" +#include "Nodes.h" +#include "SamplingTool.h" +#include + +namespace JSC { + + class CodeBlock; + class Debugger; + class EvalCodeBlock; + class FunctionCodeBlock; + class ProgramCodeBlock; + class ScopeChainNode; + + struct ExceptionInfo; + + enum CodeSpecializationKind { CodeForCall, CodeForConstruct }; + enum CompilationKind { FirstCompilation, OptimizingCompilation }; + + inline bool isCall(CodeSpecializationKind kind) + { + if (kind == CodeForCall) + return true; + ASSERT(kind == CodeForConstruct); + return false; + } + + class ExecutableBase : public JSCell { + friend class JIT; + + protected: + static const int NUM_PARAMETERS_IS_HOST = 0; + static const int NUM_PARAMETERS_NOT_COMPILED = -1; + + ExecutableBase(JSGlobalData& globalData, Structure* structure, int numParameters) + : JSCell(globalData, structure) + , m_numParametersForCall(numParameters) + , m_numParametersForConstruct(numParameters) + { + } + + void finishCreation(JSGlobalData& globalData) + { + Base::finishCreation(globalData); + } + + public: + typedef JSCell Base; + + static void destroy(JSCell*); + + bool isHostFunction() const + { + ASSERT((m_numParametersForCall == NUM_PARAMETERS_IS_HOST) == (m_numParametersForConstruct == NUM_PARAMETERS_IS_HOST)); + return m_numParametersForCall == NUM_PARAMETERS_IS_HOST; + } + + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(globalData, globalObject, proto, TypeInfo(CompoundType, StructureFlags), &s_info); } + + static JS_EXPORTDATA const ClassInfo s_info; + + protected: + static const unsigned StructureFlags = 0; + int m_numParametersForCall; + int m_numParametersForConstruct; + +#if ENABLE(JIT) + public: + JITCode& generatedJITCodeForCall() + { + ASSERT(m_jitCodeForCall); + return m_jitCodeForCall; + } + + JITCode& generatedJITCodeForConstruct() + { + ASSERT(m_jitCodeForConstruct); + return m_jitCodeForConstruct; + } + + JITCode& generatedJITCodeFor(CodeSpecializationKind kind) + { + if (kind == CodeForCall) + return generatedJITCodeForCall(); + ASSERT(kind == CodeForConstruct); + return generatedJITCodeForConstruct(); + } + + MacroAssemblerCodePtr generatedJITCodeForCallWithArityCheck() + { + ASSERT(m_jitCodeForCall); + ASSERT(m_jitCodeForCallWithArityCheck); + return m_jitCodeForCallWithArityCheck; + } + + MacroAssemblerCodePtr generatedJITCodeForConstructWithArityCheck() + { + ASSERT(m_jitCodeForConstruct); + ASSERT(m_jitCodeForConstructWithArityCheck); + return m_jitCodeForConstructWithArityCheck; + } + + MacroAssemblerCodePtr generatedJITCodeWithArityCheckFor(CodeSpecializationKind kind) + { + if (kind == CodeForCall) + return generatedJITCodeForCallWithArityCheck(); + ASSERT(kind == CodeForConstruct); + return generatedJITCodeForConstructWithArityCheck(); + } + + bool hasJITCodeForCall() const + { + return m_numParametersForCall >= 0; + } + + bool hasJITCodeForConstruct() const + { + return m_numParametersForConstruct >= 0; + } + + bool hasJITCodeFor(CodeSpecializationKind kind) const + { + if (kind == CodeForCall) + return hasJITCodeForCall(); + ASSERT(kind == CodeForConstruct); + return hasJITCodeForConstruct(); + } + + // Intrinsics are only for calls, currently. + Intrinsic intrinsic() const; + + Intrinsic intrinsicFor(CodeSpecializationKind kind) const + { + if (isCall(kind)) + return intrinsic(); + return NoIntrinsic; + } + + protected: + JITCode m_jitCodeForCall; + JITCode m_jitCodeForConstruct; + MacroAssemblerCodePtr m_jitCodeForCallWithArityCheck; + MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheck; +#endif + void clearCode(); + }; + + class NativeExecutable : public ExecutableBase { + friend class JIT; + public: + typedef ExecutableBase Base; + +#if ENABLE(JIT) + static NativeExecutable* create(JSGlobalData& globalData, MacroAssemblerCodeRef callThunk, NativeFunction function, MacroAssemblerCodeRef constructThunk, NativeFunction constructor, Intrinsic intrinsic) + { + ASSERT(globalData.canUseJIT()); + NativeExecutable* executable; + if (!callThunk) { + executable = new (NotNull, allocateCell(globalData.heap)) NativeExecutable(globalData, function, constructor); + executable->finishCreation(globalData, JITCode(), JITCode(), intrinsic); + } else { + executable = new (NotNull, allocateCell(globalData.heap)) NativeExecutable(globalData, function, constructor); + executable->finishCreation(globalData, JITCode::HostFunction(callThunk), JITCode::HostFunction(constructThunk), intrinsic); + } + globalData.heap.addFinalizer(executable, &finalize); + return executable; + } +#endif + +#if ENABLE(INTERPRETER) + static NativeExecutable* create(JSGlobalData& globalData, NativeFunction function, NativeFunction constructor) + { + ASSERT(!globalData.canUseJIT()); + NativeExecutable* executable = new (NotNull, allocateCell(globalData.heap)) NativeExecutable(globalData, function, constructor); + executable->finishCreation(globalData); + globalData.heap.addFinalizer(executable, &finalize); + return executable; + } +#endif + + static void destroy(JSCell*); + + NativeFunction function() { return m_function; } + NativeFunction constructor() { return m_constructor; } + + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(globalData, globalObject, proto, TypeInfo(LeafType, StructureFlags), &s_info); } + + static const ClassInfo s_info; + + Intrinsic intrinsic() const; + + protected: +#if ENABLE(JIT) + void finishCreation(JSGlobalData& globalData, JITCode callThunk, JITCode constructThunk, Intrinsic intrinsic) + { + ASSERT(globalData.canUseJIT()); + Base::finishCreation(globalData); + m_jitCodeForCall = callThunk; + m_jitCodeForConstruct = constructThunk; + m_jitCodeForCallWithArityCheck = callThunk.addressForCall(); + m_jitCodeForConstructWithArityCheck = constructThunk.addressForCall(); + m_intrinsic = intrinsic; + } +#endif + +#if ENABLE(INTERPRETER) + void finishCreation(JSGlobalData& globalData) + { + ASSERT(!globalData.canUseJIT()); + Base::finishCreation(globalData); + m_intrinsic = NoIntrinsic; + } +#endif + + static void finalize(JSCell*); + + private: + NativeExecutable(JSGlobalData& globalData, NativeFunction function, NativeFunction constructor) + : ExecutableBase(globalData, globalData.nativeExecutableStructure.get(), NUM_PARAMETERS_IS_HOST) + , m_function(function) + , m_constructor(constructor) + { + } + + NativeFunction m_function; + NativeFunction m_constructor; + + Intrinsic m_intrinsic; + }; + + class ScriptExecutable : public ExecutableBase { + public: + typedef ExecutableBase Base; + + ScriptExecutable(Structure* structure, JSGlobalData& globalData, const SourceCode& source, bool isInStrictContext) + : ExecutableBase(globalData, structure, NUM_PARAMETERS_NOT_COMPILED) + , m_source(source) + , m_features(isInStrictContext ? StrictModeFeature : 0) + { + } + + ScriptExecutable(Structure* structure, ExecState* exec, const SourceCode& source, bool isInStrictContext) + : ExecutableBase(exec->globalData(), structure, NUM_PARAMETERS_NOT_COMPILED) + , m_source(source) + , m_features(isInStrictContext ? StrictModeFeature : 0) + { + } + + static void destroy(JSCell*); + + const SourceCode& source() { return m_source; } + intptr_t sourceID() const { return m_source.provider()->asID(); } + const UString& sourceURL() const { return m_source.provider()->url(); } + int lineNo() const { return m_firstLine; } + int lastLine() const { return m_lastLine; } + + bool usesEval() const { return m_features & EvalFeature; } + bool usesArguments() const { return m_features & ArgumentsFeature; } + bool needsActivation() const { return m_hasCapturedVariables || m_features & (EvalFeature | WithFeature | CatchFeature); } + bool isStrictMode() const { return m_features & StrictModeFeature; } + + void unlinkCalls(); + + static const ClassInfo s_info; + + protected: + void finishCreation(JSGlobalData& globalData) + { + Base::finishCreation(globalData); +#if ENABLE(CODEBLOCK_SAMPLING) + if (SamplingTool* sampler = globalData.interpreter->sampler()) + sampler->notifyOfScope(globalData, this); +#endif + } + + void recordParse(CodeFeatures features, bool hasCapturedVariables, int firstLine, int lastLine) + { + m_features = features; + m_hasCapturedVariables = hasCapturedVariables; + m_firstLine = firstLine; + m_lastLine = lastLine; + } + + SourceCode m_source; + CodeFeatures m_features; + bool m_hasCapturedVariables; + int m_firstLine; + int m_lastLine; + }; + + class EvalExecutable : public ScriptExecutable { + public: + typedef ScriptExecutable Base; + + static void destroy(JSCell*); + + JSObject* compile(ExecState* exec, ScopeChainNode* scopeChainNode) + { + ASSERT(exec->globalData().dynamicGlobalObject); + JSObject* error = 0; + if (!m_evalCodeBlock) + error = compileInternal(exec, scopeChainNode, JITCode::bottomTierJIT()); + ASSERT(!error == !!m_evalCodeBlock); + return error; + } + + JSObject* compileOptimized(ExecState*, ScopeChainNode*); + +#if ENABLE(JIT) + void jettisonOptimizedCode(JSGlobalData&); +#endif + + EvalCodeBlock& generatedBytecode() + { + ASSERT(m_evalCodeBlock); + return *m_evalCodeBlock; + } + + static EvalExecutable* create(ExecState* exec, const SourceCode& source, bool isInStrictContext) + { + EvalExecutable* executable = new (NotNull, allocateCell(*exec->heap())) EvalExecutable(exec, source, isInStrictContext); + executable->finishCreation(exec->globalData()); + exec->globalData().heap.addFinalizer(executable, &finalize); + return executable; + } + +#if ENABLE(JIT) + JITCode& generatedJITCode() + { + return generatedJITCodeForCall(); + } +#endif + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) + { + return Structure::create(globalData, globalObject, proto, TypeInfo(EvalExecutableType, StructureFlags), &s_info); + } + + static const ClassInfo s_info; + + void unlinkCalls(); + + protected: + void clearCode(); + static void finalize(JSCell*); + + private: + static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags; + EvalExecutable(ExecState*, const SourceCode&, bool); + + JSObject* compileInternal(ExecState*, ScopeChainNode*, JITCode::JITType); + static void visitChildren(JSCell*, SlotVisitor&); + + OwnPtr m_evalCodeBlock; + }; + + class ProgramExecutable : public ScriptExecutable { + public: + typedef ScriptExecutable Base; + + static ProgramExecutable* create(ExecState* exec, const SourceCode& source) + { + ProgramExecutable* executable = new (NotNull, allocateCell(*exec->heap())) ProgramExecutable(exec, source); + executable->finishCreation(exec->globalData()); + exec->globalData().heap.addFinalizer(executable, &finalize); + return executable; + } + + static void destroy(JSCell*); + + JSObject* compile(ExecState* exec, ScopeChainNode* scopeChainNode) + { + ASSERT(exec->globalData().dynamicGlobalObject); + JSObject* error = 0; + if (!m_programCodeBlock) + error = compileInternal(exec, scopeChainNode, JITCode::bottomTierJIT()); + ASSERT(!error == !!m_programCodeBlock); + return error; + } + + JSObject* compileOptimized(ExecState*, ScopeChainNode*); + +#if ENABLE(JIT) + void jettisonOptimizedCode(JSGlobalData&); +#endif + + ProgramCodeBlock& generatedBytecode() + { + ASSERT(m_programCodeBlock); + return *m_programCodeBlock; + } + + JSObject* checkSyntax(ExecState*); + +#if ENABLE(JIT) + JITCode& generatedJITCode() + { + return generatedJITCodeForCall(); + } +#endif + + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) + { + return Structure::create(globalData, globalObject, proto, TypeInfo(ProgramExecutableType, StructureFlags), &s_info); + } + + static const ClassInfo s_info; + + void unlinkCalls(); + + protected: + void clearCode(); + static void finalize(JSCell*); + + private: + static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags; + ProgramExecutable(ExecState*, const SourceCode&); + + JSObject* compileInternal(ExecState*, ScopeChainNode*, JITCode::JITType); + static void visitChildren(JSCell*, SlotVisitor&); + + OwnPtr m_programCodeBlock; + }; + + class FunctionExecutable : public ScriptExecutable { + friend class JIT; + public: + typedef ScriptExecutable Base; + + static FunctionExecutable* create(ExecState* exec, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine) + { + FunctionExecutable* executable = new (NotNull, allocateCell(*exec->heap())) FunctionExecutable(exec, name, source, forceUsesArguments, parameters, isInStrictContext); + executable->finishCreation(exec->globalData(), name, firstLine, lastLine); + exec->globalData().heap.addFinalizer(executable, &finalize); + return executable; + } + + static FunctionExecutable* create(JSGlobalData& globalData, const Identifier& name, const SourceCode& source, bool forceUsesArguments, FunctionParameters* parameters, bool isInStrictContext, int firstLine, int lastLine) + { + FunctionExecutable* executable = new (NotNull, allocateCell(globalData.heap)) FunctionExecutable(globalData, name, source, forceUsesArguments, parameters, isInStrictContext); + executable->finishCreation(globalData, name, firstLine, lastLine); + globalData.heap.addFinalizer(executable, &finalize); + return executable; + } + + static void destroy(JSCell*); + + JSFunction* make(ExecState* exec, ScopeChainNode* scopeChain) + { + return JSFunction::create(exec, this, scopeChain); + } + + // Returns either call or construct bytecode. This can be appropriate + // for answering questions that that don't vary between call and construct -- + // for example, argumentsRegister(). + FunctionCodeBlock& generatedBytecode() + { + if (m_codeBlockForCall) + return *m_codeBlockForCall; + ASSERT(m_codeBlockForConstruct); + return *m_codeBlockForConstruct; + } + + FunctionCodeBlock* codeBlockWithBytecodeFor(CodeSpecializationKind); + + PassOwnPtr produceCodeBlockFor(ScopeChainNode*, CompilationKind, CodeSpecializationKind, JSObject*& exception); + + JSObject* compileForCall(ExecState* exec, ScopeChainNode* scopeChainNode) + { + ASSERT(exec->globalData().dynamicGlobalObject); + JSObject* error = 0; + if (!m_codeBlockForCall) + error = compileForCallInternal(exec, scopeChainNode, JITCode::bottomTierJIT()); + ASSERT(!error == !!m_codeBlockForCall); + return error; + } + + JSObject* compileOptimizedForCall(ExecState*, ScopeChainNode*); + +#if ENABLE(JIT) + void jettisonOptimizedCodeForCall(JSGlobalData&); +#endif + + bool isGeneratedForCall() const + { + return m_codeBlockForCall; + } + + FunctionCodeBlock& generatedBytecodeForCall() + { + ASSERT(m_codeBlockForCall); + return *m_codeBlockForCall; + } + + JSObject* compileForConstruct(ExecState* exec, ScopeChainNode* scopeChainNode) + { + ASSERT(exec->globalData().dynamicGlobalObject); + JSObject* error = 0; + if (!m_codeBlockForConstruct) + error = compileForConstructInternal(exec, scopeChainNode, JITCode::bottomTierJIT()); + ASSERT(!error == !!m_codeBlockForConstruct); + return error; + } + + JSObject* compileOptimizedForConstruct(ExecState*, ScopeChainNode*); + +#if ENABLE(JIT) + void jettisonOptimizedCodeForConstruct(JSGlobalData&); +#endif + + bool isGeneratedForConstruct() const + { + return m_codeBlockForConstruct; + } + + FunctionCodeBlock& generatedBytecodeForConstruct() + { + ASSERT(m_codeBlockForConstruct); + return *m_codeBlockForConstruct; + } + + JSObject* compileFor(ExecState* exec, ScopeChainNode* scopeChainNode, CodeSpecializationKind kind) + { + ASSERT(exec->callee()); + ASSERT(exec->callee()->inherits(&JSFunction::s_info)); + ASSERT(asFunction(exec->callee())->jsExecutable() == this); + + if (kind == CodeForCall) + return compileForCall(exec, scopeChainNode); + ASSERT(kind == CodeForConstruct); + return compileForConstruct(exec, scopeChainNode); + } + + JSObject* compileOptimizedFor(ExecState* exec, ScopeChainNode* scopeChainNode, CodeSpecializationKind kind) + { + ASSERT(exec->callee()); + ASSERT(exec->callee()->inherits(&JSFunction::s_info)); + ASSERT(asFunction(exec->callee())->jsExecutable() == this); + + if (kind == CodeForCall) + return compileOptimizedForCall(exec, scopeChainNode); + ASSERT(kind == CodeForConstruct); + return compileOptimizedForConstruct(exec, scopeChainNode); + } + +#if ENABLE(JIT) + void jettisonOptimizedCodeFor(JSGlobalData& globalData, CodeSpecializationKind kind) + { + if (kind == CodeForCall) + jettisonOptimizedCodeForCall(globalData); + else { + ASSERT(kind == CodeForConstruct); + jettisonOptimizedCodeForConstruct(globalData); + } + } +#endif + + bool isGeneratedFor(CodeSpecializationKind kind) + { + if (kind == CodeForCall) + return isGeneratedForCall(); + ASSERT(kind == CodeForConstruct); + return isGeneratedForConstruct(); + } + + FunctionCodeBlock& generatedBytecodeFor(CodeSpecializationKind kind) + { + if (kind == CodeForCall) + return generatedBytecodeForCall(); + ASSERT(kind == CodeForConstruct); + return generatedBytecodeForConstruct(); + } + + FunctionCodeBlock* baselineCodeBlockFor(CodeSpecializationKind); + + FunctionCodeBlock* profiledCodeBlockFor(CodeSpecializationKind kind) + { + return baselineCodeBlockFor(kind); + } + + const Identifier& name() { return m_name; } + JSString* nameValue() const { return m_nameValue.get(); } + size_t parameterCount() const { return m_parameters->size(); } // Excluding 'this'! + unsigned capturedVariableCount() const { return m_numCapturedVariables; } + UString paramString() const; + SharedSymbolTable* symbolTable() const { return m_symbolTable; } + + void discardCode(); + static void visitChildren(JSCell*, SlotVisitor&); + static FunctionExecutable* fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, JSObject** exception); + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) + { + return Structure::create(globalData, globalObject, proto, TypeInfo(FunctionExecutableType, StructureFlags), &s_info); + } + + static const ClassInfo s_info; + + void unlinkCalls(); + + protected: + void clearCode(); + static void finalize(JSCell*); + + void finishCreation(JSGlobalData& globalData, const Identifier& name, int firstLine, int lastLine) + { + Base::finishCreation(globalData); + m_firstLine = firstLine; + m_lastLine = lastLine; + m_nameValue.set(globalData, this, jsString(&globalData, name.ustring())); + } + + private: + FunctionExecutable(JSGlobalData&, const Identifier& name, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool); + FunctionExecutable(ExecState*, const Identifier& name, const SourceCode&, bool forceUsesArguments, FunctionParameters*, bool); + + JSObject* compileForCallInternal(ExecState*, ScopeChainNode*, JITCode::JITType); + JSObject* compileForConstructInternal(ExecState*, ScopeChainNode*, JITCode::JITType); + + OwnPtr& codeBlockFor(CodeSpecializationKind kind) + { + if (kind == CodeForCall) + return m_codeBlockForCall; + ASSERT(kind == CodeForConstruct); + return m_codeBlockForConstruct; + } + + static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags; + unsigned m_numCapturedVariables : 31; + bool m_forceUsesArguments : 1; + + RefPtr m_parameters; + OwnPtr m_codeBlockForCall; + OwnPtr m_codeBlockForConstruct; + Identifier m_name; + WriteBarrier m_nameValue; + SharedSymbolTable* m_symbolTable; + }; + + inline FunctionExecutable* JSFunction::jsExecutable() const + { + ASSERT(!isHostFunctionNonInline()); + return static_cast(m_executable.get()); + } + + inline bool JSFunction::isHostFunction() const + { + ASSERT(m_executable); + return m_executable->isHostFunction(); + } + + inline NativeFunction JSFunction::nativeFunction() + { + ASSERT(isHostFunction()); + return static_cast(m_executable.get())->function(); + } + + inline NativeFunction JSFunction::nativeConstructor() + { + ASSERT(isHostFunction()); + return static_cast(m_executable.get())->constructor(); + } + + inline bool isHostFunction(JSValue value, NativeFunction nativeFunction) + { + JSFunction* function = static_cast(getJSFunction(value)); + if (!function || !function->isHostFunction()) + return false; + return function->nativeFunction() == nativeFunction; + } + + inline void ScriptExecutable::unlinkCalls() + { + switch (structure()->typeInfo().type()) { + case EvalExecutableType: + return jsCast(this)->unlinkCalls(); + case ProgramExecutableType: + return jsCast(this)->unlinkCalls(); + case FunctionExecutableType: + return jsCast(this)->unlinkCalls(); + default: + ASSERT_NOT_REACHED(); + } + } + +} + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ExecutableAllocator.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ExecutableAllocator.h new file mode 100644 index 000000000..bc8b816c8 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ExecutableAllocator.h @@ -0,0 +1,242 @@ +/* + * Copyright (C) 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 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 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 ExecutableAllocator_h +#define ExecutableAllocator_h +#include // for ptrdiff_t +#include +#include +#include +#include +#include +#include +#include +#include + +#if OS(IOS) +#include +#endif + +#if OS(IOS) || OS(QNX) +#include +#endif + +#if CPU(MIPS) && OS(LINUX) +#include +#endif + +#if CPU(SH4) && OS(LINUX) +#include +#include +#include +#include +#endif + +#if OS(WINCE) +// From pkfuncs.h (private header file from the Platform Builder) +#define CACHE_SYNC_ALL 0x07F +extern "C" __declspec(dllimport) void CacheRangeFlush(LPVOID pAddr, DWORD dwLength, DWORD dwFlags); +#endif + +#define JIT_ALLOCATOR_LARGE_ALLOC_SIZE (pageSize() * 4) + +#if ENABLE(ASSEMBLER_WX_EXCLUSIVE) +#define PROTECTION_FLAGS_RW (PROT_READ | PROT_WRITE) +#define PROTECTION_FLAGS_RX (PROT_READ | PROT_EXEC) +#define EXECUTABLE_POOL_WRITABLE false +#else +#define EXECUTABLE_POOL_WRITABLE true +#endif + +namespace JSC { + +class JSGlobalData; +void releaseExecutableMemory(JSGlobalData&); + +inline size_t roundUpAllocationSize(size_t request, size_t granularity) +{ + if ((std::numeric_limits::max() - granularity) <= request) + CRASH(); // Allocation is too large + + // Round up to next page boundary + size_t size = request + (granularity - 1); + size = size & ~(granularity - 1); + ASSERT(size >= request); + return size; +} + +} + +#if ENABLE(JIT) && ENABLE(ASSEMBLER) + +namespace JSC { + +typedef WTF::MetaAllocatorHandle ExecutableMemoryHandle; + +class ExecutableAllocator { + enum ProtectionSetting { Writable, Executable }; + +public: + ExecutableAllocator(JSGlobalData&); + + static void initializeAllocator(); + + bool isValid() const; + + static bool underMemoryPressure(); + +#if ENABLE(META_ALLOCATOR_PROFILE) + static void dumpProfile(); +#else + static void dumpProfile() { } +#endif + + PassRefPtr allocate(JSGlobalData&, size_t sizeInBytes, void* ownerUID); + +#if ENABLE(ASSEMBLER_WX_EXCLUSIVE) + static void makeWritable(void* start, size_t size) + { + reprotectRegion(start, size, Writable); + } + + static void makeExecutable(void* start, size_t size) + { + reprotectRegion(start, size, Executable); + } +#else + static void makeWritable(void*, size_t) {} + static void makeExecutable(void*, size_t) {} +#endif + +#if CPU(X86) || CPU(X86_64) + static void cacheFlush(void*, size_t) + { + } +#elif CPU(MIPS) + static void cacheFlush(void* code, size_t size) + { +#if GCC_VERSION_AT_LEAST(4, 3, 0) +#if WTF_MIPS_ISA_REV(2) && !GCC_VERSION_AT_LEAST(4, 4, 3) + int lineSize; + asm("rdhwr %0, $1" : "=r" (lineSize)); + // + // Modify "start" and "end" to avoid GCC 4.3.0-4.4.2 bug in + // mips_expand_synci_loop that may execute synci one more time. + // "start" points to the fisrt byte of the cache line. + // "end" points to the last byte of the line before the last cache line. + // Because size is always a multiple of 4, this is safe to set + // "end" to the last byte. + // + intptr_t start = reinterpret_cast(code) & (-lineSize); + intptr_t end = ((reinterpret_cast(code) + size - 1) & (-lineSize)) - 1; + __builtin___clear_cache(reinterpret_cast(start), reinterpret_cast(end)); +#else + intptr_t end = reinterpret_cast(code) + size; + __builtin___clear_cache(reinterpret_cast(code), reinterpret_cast(end)); +#endif +#else + _flush_cache(reinterpret_cast(code), size, BCACHE); +#endif + } +#elif CPU(ARM_THUMB2) && OS(IOS) + static void cacheFlush(void* code, size_t size) + { + sys_cache_control(kCacheFunctionPrepareForExecution, code, size); + } +#elif CPU(ARM_THUMB2) && OS(LINUX) + static void cacheFlush(void* code, size_t size) + { + asm volatile ( + "push {r7}\n" + "mov r0, %0\n" + "mov r1, %1\n" + "movw r7, #0x2\n" + "movt r7, #0xf\n" + "movs r2, #0x0\n" + "svc 0x0\n" + "pop {r7}\n" + : + : "r" (code), "r" (reinterpret_cast(code) + size) + : "r0", "r1", "r2"); + } +#elif CPU(ARM_TRADITIONAL) && OS(LINUX) && COMPILER(RVCT) + static __asm void cacheFlush(void* code, size_t size); +#elif CPU(ARM_TRADITIONAL) && OS(LINUX) && COMPILER(GCC) + static void cacheFlush(void* code, size_t size) + { + asm volatile ( + "push {r7}\n" + "mov r0, %0\n" + "mov r1, %1\n" + "mov r7, #0xf0000\n" + "add r7, r7, #0x2\n" + "mov r2, #0x0\n" + "svc 0x0\n" + "pop {r7}\n" + : + : "r" (code), "r" (reinterpret_cast(code) + size) + : "r0", "r1", "r2"); + } +#elif OS(WINCE) + static void cacheFlush(void* code, size_t size) + { + CacheRangeFlush(code, size, CACHE_SYNC_ALL); + } +#elif CPU(SH4) && OS(LINUX) + static void cacheFlush(void* code, size_t size) + { +#ifdef CACHEFLUSH_D_L2 + syscall(__NR_cacheflush, reinterpret_cast(code), size, CACHEFLUSH_D_WB | CACHEFLUSH_I | CACHEFLUSH_D_L2); +#else + syscall(__NR_cacheflush, reinterpret_cast(code), size, CACHEFLUSH_D_WB | CACHEFLUSH_I); +#endif + } +#elif OS(QNX) + static void cacheFlush(void* code, size_t size) + { +#if !ENABLE(ASSEMBLER_WX_EXCLUSIVE) + msync(code, size, MS_INVALIDATE_ICACHE); +#else + UNUSED_PARAM(code); + UNUSED_PARAM(size); +#endif + } +#else + #error "The cacheFlush support is missing on this platform." +#endif + static size_t committedByteCount(); + +private: + +#if ENABLE(ASSEMBLER_WX_EXCLUSIVE) + static void reprotectRegion(void*, size_t, ProtectionSetting); +#endif +}; + +} // namespace JSC + +#endif // ENABLE(JIT) && ENABLE(ASSEMBLER) + +#endif // !defined(ExecutableAllocator) diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ExportMacros.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ExportMacros.h new file mode 100644 index 000000000..a6b3bce5a --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ExportMacros.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2011 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. + * + * This file handles shared library symbol export decorations. It is recommended + * that all WebKit projects use these definitions so that symbol exports work + * properly on all platforms and compilers that WebKit builds under. + */ + +#ifndef ExportMacros_h +#define ExportMacros_h + +#include "Platform.h" + +// See note in wtf/Platform.h for more info on EXPORT_MACROS. +#if USE(EXPORT_MACROS) + +#if !PLATFORM(CHROMIUM) && OS(WINDOWS) && !COMPILER(GCC) +#define WTF_EXPORT __declspec(dllexport) +#define WTF_IMPORT __declspec(dllimport) +#define WTF_HIDDEN +#elif defined(__GNUC__) && !defined(__CC_ARM) && !defined(__ARMCC__) +#define WTF_EXPORT __attribute__((visibility("default"))) +#define WTF_IMPORT WTF_EXPORT +#define WTF_HIDDEN __attribute__((visibility("hidden"))) +#else +#define WTF_EXPORT +#define WTF_IMPORT +#define WTF_HIDDEN +#endif + +// FIXME: When all ports are using the export macros, we should replace +// WTF_EXPORTDATA with WTF_EXPORT_PRIVATE macros. +#if defined(BUILDING_WTF) +#define WTF_EXPORTDATA WTF_EXPORT +#else +#define WTF_EXPORTDATA WTF_IMPORT +#endif + +#else // !USE(EXPORT_MACROS) + +#if !PLATFORM(CHROMIUM) && OS(WINDOWS) && !COMPILER(GCC) +#if defined(BUILDING_WTF) +#define WTF_EXPORTDATA __declspec(dllexport) +#else +#define WTF_EXPORTDATA __declspec(dllimport) +#endif +#else // PLATFORM(CHROMIUM) || !OS(WINDOWS) || COMPILER(GCC) +#define WTF_EXPORTDATA +#endif // !PLATFORM(CHROMIUM)... + +#define WTF_EXPORTCLASS WTF_EXPORTDATA + +#define WTF_EXPORT +#define WTF_IMPORT +#define WTF_HIDDEN + +#endif // USE(EXPORT_MACROS) + +#if defined(BUILDING_WTF) +#define WTF_EXPORT_PRIVATE WTF_EXPORT +#else +#define WTF_EXPORT_PRIVATE WTF_IMPORT +#endif + +#define WTF_EXPORT_HIDDEN WTF_HIDDEN + +#define HIDDEN_INLINE WTF_EXPORT_HIDDEN inline + +#endif // ExportMacros_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ExpressionRangeInfo.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ExpressionRangeInfo.h new file mode 100644 index 000000000..f4949a686 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ExpressionRangeInfo.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2012 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 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 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 ExpressionRangeInfo_h +#define ExpressionRangeInfo_h + +#include + +namespace JSC { + +struct ExpressionRangeInfo { + enum { + MaxOffset = (1 << 7) - 1, + MaxDivot = (1 << 25) - 1 + }; + uint32_t instructionOffset : 25; + uint32_t divotPoint : 25; + uint32_t startOffset : 7; + uint32_t endOffset : 7; +}; + +} // namespace JSC + +#endif // ExpressionRangeInfo_h + diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/FastAllocBase.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/FastAllocBase.h new file mode 100644 index 000000000..1edbed94d --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/FastAllocBase.h @@ -0,0 +1,427 @@ +/* + * Copyright (C) 2008, 2009 Paul Pedriana . 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 FastAllocBase_h +#define FastAllocBase_h + +// Provides customizable overrides of fastMalloc/fastFree and operator new/delete +// +// Provided functionality: +// Macro: WTF_MAKE_FAST_ALLOCATED +// namespace WTF { +// +// T* fastNew(); +// T* fastNew(arg); +// T* fastNew(arg, arg); +// T* fastNewArray(count); +// void fastDelete(T* p); +// void fastDeleteArray(T* p); +// void fastNonNullDelete(T* p); +// void fastNonNullDeleteArray(T* p); +// } +// +// FastDelete assumes that the underlying +// +// Example usage: +// class Widget { +// WTF_MAKE_FAST_ALLOCATED +// ... +// }; +// +// struct Data { +// WTF_MAKE_FAST_ALLOCATED +// public: +// ... +// }; +// +// char* charPtr = fastNew(); +// fastDelete(charPtr); +// +// char* charArrayPtr = fastNewArray(37); +// fastDeleteArray(charArrayPtr); +// +// void** voidPtrPtr = fastNew(); +// fastDelete(voidPtrPtr); +// +// void** voidPtrArrayPtr = fastNewArray(37); +// fastDeleteArray(voidPtrArrayPtr); +// +// POD* podPtr = fastNew(); +// fastDelete(podPtr); +// +// POD* podArrayPtr = fastNewArray(37); +// fastDeleteArray(podArrayPtr); +// +// Object* objectPtr = fastNew(); +// fastDelete(objectPtr); +// +// Object* objectArrayPtr = fastNewArray(37); +// fastDeleteArray(objectArrayPtr); +// + +#include +#include +#include +#include +#include "Assertions.h" +#include "FastMalloc.h" +#include "StdLibExtras.h" +#include "TypeTraits.h" + +#define WTF_MAKE_FAST_ALLOCATED \ +public: \ + void* operator new(size_t, void* p) { return p; } \ + void* operator new[](size_t, void* p) { return p; } \ + \ + void* operator new(size_t size) \ + { \ + void* p = ::WTF::fastMalloc(size); \ + ::WTF::fastMallocMatchValidateMalloc(p, ::WTF::Internal::AllocTypeClassNew); \ + return p; \ + } \ + \ + void operator delete(void* p) \ + { \ + ::WTF::fastMallocMatchValidateFree(p, ::WTF::Internal::AllocTypeClassNew); \ + ::WTF::fastFree(p); \ + } \ + \ + void* operator new[](size_t size) \ + { \ + void* p = ::WTF::fastMalloc(size); \ + ::WTF::fastMallocMatchValidateMalloc(p, ::WTF::Internal::AllocTypeClassNewArray); \ + return p; \ + } \ + \ + void operator delete[](void* p) \ + { \ + ::WTF::fastMallocMatchValidateFree(p, ::WTF::Internal::AllocTypeClassNewArray); \ + ::WTF::fastFree(p); \ + } \ + void* operator new(size_t, NotNullTag, void* location) \ + { \ + ASSERT(location); \ + return location; \ + } \ +private: \ +typedef int ThisIsHereToForceASemicolonAfterThisMacro + +namespace WTF { + + // fastNew / fastDelete + + template + inline T* fastNew() + { + void* p = fastMalloc(sizeof(T)); + + if (!p) + return 0; + + fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew); + return ::new (p) T; + } + + template + inline T* fastNew(Arg1 arg1) + { + void* p = fastMalloc(sizeof(T)); + + if (!p) + return 0; + + fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew); + return ::new (p) T(arg1); + } + + template + inline T* fastNew(Arg1 arg1, Arg2 arg2) + { + void* p = fastMalloc(sizeof(T)); + + if (!p) + return 0; + + fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew); + return ::new (p) T(arg1, arg2); + } + + template + inline T* fastNew(Arg1 arg1, Arg2 arg2, Arg3 arg3) + { + void* p = fastMalloc(sizeof(T)); + + if (!p) + return 0; + + fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew); + return ::new (p) T(arg1, arg2, arg3); + } + + template + inline T* fastNew(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) + { + void* p = fastMalloc(sizeof(T)); + + if (!p) + return 0; + + fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew); + return ::new (p) T(arg1, arg2, arg3, arg4); + } + + template + inline T* fastNew(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5) + { + void* p = fastMalloc(sizeof(T)); + + if (!p) + return 0; + + fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew); + return ::new (p) T(arg1, arg2, arg3, arg4, arg5); + } + + namespace Internal { + + // We define a union of pointer to an integer and pointer to T. + // When non-POD arrays are allocated we add a few leading bytes to tell what + // the size of the array is. We return to the user the pointer to T. + // The way to think of it is as if we allocate a struct like so: + // struct Array { + // AllocAlignmentInteger m_size; + // T m_T[array count]; + // }; + + template + union ArraySize { + AllocAlignmentInteger* size; + T* t; + }; + + // This is a support template for fastNewArray. + // This handles the case wherein T has a trivial ctor and a trivial dtor. + template + struct NewArrayImpl { + static T* fastNewArray(size_t count) + { + T* p = static_cast(fastMalloc(sizeof(T) * count)); + fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray); + return p; + } + }; + + // This is a support template for fastNewArray. + // This handles the case wherein T has a non-trivial ctor and a trivial dtor. + template + struct NewArrayImpl { + static T* fastNewArray(size_t count) + { + T* p = static_cast(fastMalloc(sizeof(T) * count)); + + if (!p) + return 0; + + fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray); + + for (T* pObject = p, *pObjectEnd = pObject + count; pObject != pObjectEnd; ++pObject) + ::new (pObject) T; + + return p; + } + }; + + // This is a support template for fastNewArray. + // This handles the case wherein T has a trivial ctor and a non-trivial dtor. + template + struct NewArrayImpl { + static T* fastNewArray(size_t count) + { + void* p = fastMalloc(sizeof(AllocAlignmentInteger) + (sizeof(T) * count)); + ArraySize a = { static_cast(p) }; + + if (!p) + return 0; + + fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray); + *a.size++ = count; + // No need to construct the objects in this case. + + return a.t; + } + }; + + // This is a support template for fastNewArray. + // This handles the case wherein T has a non-trivial ctor and a non-trivial dtor. + template + struct NewArrayImpl { + static T* fastNewArray(size_t count) + { + void* p = fastMalloc(sizeof(AllocAlignmentInteger) + (sizeof(T) * count)); + ArraySize a = { static_cast(p) }; + + if (!p) + return 0; + + fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray); + *a.size++ = count; + + for (T* pT = a.t, *pTEnd = pT + count; pT != pTEnd; ++pT) + ::new (pT) T; + + return a.t; + } + }; + } // namespace Internal + + template + inline T* fastNewArray(size_t count) + { + return Internal::NewArrayImpl::value, WTF::HasTrivialDestructor::value>::fastNewArray(count); + } + + template + inline void fastDelete(T* p) + { + if (!p) + return; + + fastMallocMatchValidateFree(p, Internal::AllocTypeFastNew); + p->~T(); + fastFree(p); + } + + template + inline void fastDeleteSkippingDestructor(T* p) + { + if (!p) + return; + + fastMallocMatchValidateFree(p, Internal::AllocTypeFastNew); + fastFree(p); + } + + namespace Internal { + // This is a support template for fastDeleteArray. + // This handles the case wherein T has a trivial dtor. + template + struct DeleteArrayImpl { + static void fastDeleteArray(void* p) + { + // No need to destruct the objects in this case. + // We expect that fastFree checks for null. + fastMallocMatchValidateFree(p, Internal::AllocTypeFastNewArray); + fastFree(p); + } + }; + + // This is a support template for fastDeleteArray. + // This handles the case wherein T has a non-trivial dtor. + template + struct DeleteArrayImpl { + static void fastDeleteArray(T* p) + { + if (!p) + return; + + ArraySize a; + a.t = p; + a.size--; // Decrement size pointer + + T* pEnd = p + *a.size; + while (pEnd-- != p) + pEnd->~T(); + + fastMallocMatchValidateFree(a.size, Internal::AllocTypeFastNewArray); + fastFree(a.size); + } + }; + + } // namespace Internal + + template + void fastDeleteArray(T* p) + { + Internal::DeleteArrayImpl::value>::fastDeleteArray(p); + } + + + template + inline void fastNonNullDelete(T* p) + { + fastMallocMatchValidateFree(p, Internal::AllocTypeFastNew); + p->~T(); + fastFree(p); + } + + namespace Internal { + // This is a support template for fastDeleteArray. + // This handles the case wherein T has a trivial dtor. + template + struct NonNullDeleteArrayImpl { + static void fastNonNullDeleteArray(void* p) + { + fastMallocMatchValidateFree(p, Internal::AllocTypeFastNewArray); + // No need to destruct the objects in this case. + fastFree(p); + } + }; + + // This is a support template for fastDeleteArray. + // This handles the case wherein T has a non-trivial dtor. + template + struct NonNullDeleteArrayImpl { + static void fastNonNullDeleteArray(T* p) + { + ArraySize a; + a.t = p; + a.size--; + + T* pEnd = p + *a.size; + while (pEnd-- != p) + pEnd->~T(); + + fastMallocMatchValidateFree(a.size, Internal::AllocTypeFastNewArray); + fastFree(a.size); + } + }; + + } // namespace Internal + + template + void fastNonNullDeleteArray(T* p) + { + Internal::NonNullDeleteArrayImpl::value>::fastNonNullDeleteArray(p); + } + + +} // namespace WTF + +using WTF::fastDeleteSkippingDestructor; + +#endif // FastAllocBase_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/FastMalloc.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/FastMalloc.h new file mode 100644 index 000000000..b115908ba --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/FastMalloc.h @@ -0,0 +1,281 @@ +/* + * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WTF_FastMalloc_h +#define WTF_FastMalloc_h + +#include "Platform.h" +#include "PossiblyNull.h" +#include +#include + +namespace WTF { + + // These functions call CRASH() if an allocation fails. + WTF_EXPORT_PRIVATE void* fastMalloc(size_t); + WTF_EXPORT_PRIVATE void* fastZeroedMalloc(size_t); + WTF_EXPORT_PRIVATE void* fastCalloc(size_t numElements, size_t elementSize); + WTF_EXPORT_PRIVATE void* fastRealloc(void*, size_t); + WTF_EXPORT_PRIVATE char* fastStrDup(const char*); + WTF_EXPORT_PRIVATE size_t fastMallocSize(const void*); + + struct TryMallocReturnValue { + TryMallocReturnValue(void* data) + : m_data(data) + { + } + TryMallocReturnValue(const TryMallocReturnValue& source) + : m_data(source.m_data) + { + source.m_data = 0; + } + ~TryMallocReturnValue() { ASSERT(!m_data); } + template bool getValue(T& data) WARN_UNUSED_RETURN; + template operator PossiblyNull() + { + T value; + getValue(value); + return PossiblyNull(value); + } + private: + mutable void* m_data; + }; + + template bool TryMallocReturnValue::getValue(T& data) + { + union u { void* data; T target; } res; + res.data = m_data; + data = res.target; + bool returnValue = !!m_data; + m_data = 0; + return returnValue; + } + + WTF_EXPORT_PRIVATE TryMallocReturnValue tryFastMalloc(size_t n); + TryMallocReturnValue tryFastZeroedMalloc(size_t n); + WTF_EXPORT_PRIVATE TryMallocReturnValue tryFastCalloc(size_t n_elements, size_t element_size); + WTF_EXPORT_PRIVATE TryMallocReturnValue tryFastRealloc(void* p, size_t n); + + WTF_EXPORT_PRIVATE void fastFree(void*); + +#ifndef NDEBUG + void fastMallocForbid(); + void fastMallocAllow(); +#endif + + WTF_EXPORT_PRIVATE void releaseFastMallocFreeMemory(); + + struct FastMallocStatistics { + size_t reservedVMBytes; + size_t committedVMBytes; + size_t freeListBytes; + }; + WTF_EXPORT_PRIVATE FastMallocStatistics fastMallocStatistics(); + + // This defines a type which holds an unsigned integer and is the same + // size as the minimally aligned memory allocation. + typedef unsigned long long AllocAlignmentInteger; + + namespace Internal { + enum AllocType { // Start with an unusual number instead of zero, because zero is common. + AllocTypeMalloc = 0x375d6750, // Encompasses fastMalloc, fastZeroedMalloc, fastCalloc, fastRealloc. + AllocTypeClassNew, // Encompasses class operator new from FastAllocBase. + AllocTypeClassNewArray, // Encompasses class operator new[] from FastAllocBase. + AllocTypeFastNew, // Encompasses fastNew. + AllocTypeFastNewArray, // Encompasses fastNewArray. + AllocTypeNew, // Encompasses global operator new. + AllocTypeNewArray // Encompasses global operator new[]. + }; + + enum { + ValidationPrefix = 0xf00df00d, + ValidationSuffix = 0x0badf00d + }; + + typedef unsigned ValidationTag; + + struct ValidationHeader { + AllocType m_type; + unsigned m_size; + ValidationTag m_prefix; + unsigned m_alignment; + }; + + static const int ValidationBufferSize = sizeof(ValidationHeader) + sizeof(ValidationTag); + } + +#if ENABLE(WTF_MALLOC_VALIDATION) + + // Malloc validation is a scheme whereby a tag is attached to an + // allocation which identifies how it was originally allocated. + // This allows us to verify that the freeing operation matches the + // allocation operation. If memory is allocated with operator new[] + // but freed with free or delete, this system would detect that. + // In the implementation here, the tag is an integer prepended to + // the allocation memory which is assigned one of the AllocType + // enumeration values. An alternative implementation of this + // scheme could store the tag somewhere else or ignore it. + // Users of FastMalloc don't need to know or care how this tagging + // is implemented. + + namespace Internal { + + // Handle a detected alloc/free mismatch. By default this calls CRASH(). + void fastMallocMatchFailed(void* p); + + inline ValidationHeader* fastMallocValidationHeader(void* p) + { + return reinterpret_cast(static_cast(p) - sizeof(ValidationHeader)); + } + + inline ValidationTag* fastMallocValidationSuffix(void* p) + { + ValidationHeader* header = fastMallocValidationHeader(p); + if (header->m_prefix != static_cast(ValidationPrefix)) + fastMallocMatchFailed(p); + + return reinterpret_cast(static_cast(p) + header->m_size); + } + + // Return the AllocType tag associated with the allocated block p. + inline AllocType fastMallocMatchValidationType(void* p) + { + return fastMallocValidationHeader(p)->m_type; + } + + // Set the AllocType tag to be associaged with the allocated block p. + inline void setFastMallocMatchValidationType(void* p, AllocType allocType) + { + fastMallocValidationHeader(p)->m_type = allocType; + } + + } // namespace Internal + + // This is a higher level function which is used by FastMalloc-using code. + inline void fastMallocMatchValidateMalloc(void* p, Internal::AllocType allocType) + { + if (!p) + return; + + Internal::setFastMallocMatchValidationType(p, allocType); + } + + // This is a higher level function which is used by FastMalloc-using code. + inline void fastMallocMatchValidateFree(void* p, Internal::AllocType) + { + if (!p) + return; + + Internal::ValidationHeader* header = Internal::fastMallocValidationHeader(p); + if (header->m_prefix != static_cast(Internal::ValidationPrefix)) + Internal::fastMallocMatchFailed(p); + + if (*Internal::fastMallocValidationSuffix(p) != Internal::ValidationSuffix) + Internal::fastMallocMatchFailed(p); + + Internal::setFastMallocMatchValidationType(p, Internal::AllocTypeMalloc); // Set it to this so that fastFree thinks it's OK. + } + + inline void fastMallocValidate(void* p) + { + if (!p) + return; + + Internal::ValidationHeader* header = Internal::fastMallocValidationHeader(p); + if (header->m_prefix != static_cast(Internal::ValidationPrefix)) + Internal::fastMallocMatchFailed(p); + + if (*Internal::fastMallocValidationSuffix(p) != Internal::ValidationSuffix) + Internal::fastMallocMatchFailed(p); + } + +#else + + inline void fastMallocMatchValidateMalloc(void*, Internal::AllocType) + { + } + + inline void fastMallocMatchValidateFree(void*, Internal::AllocType) + { + } + +#endif + +} // namespace WTF + +using WTF::fastCalloc; +using WTF::fastFree; +using WTF::fastMalloc; +using WTF::fastMallocSize; +using WTF::fastRealloc; +using WTF::fastStrDup; +using WTF::fastZeroedMalloc; +using WTF::tryFastCalloc; +using WTF::tryFastMalloc; +using WTF::tryFastRealloc; +using WTF::tryFastZeroedMalloc; + +#ifndef NDEBUG +using WTF::fastMallocForbid; +using WTF::fastMallocAllow; +#endif + +#if COMPILER(GCC) && OS(DARWIN) +#define WTF_PRIVATE_INLINE __private_extern__ inline __attribute__((always_inline)) +#elif COMPILER(GCC) +#define WTF_PRIVATE_INLINE inline __attribute__((always_inline)) +#elif COMPILER(MSVC) || COMPILER(RVCT) +#define WTF_PRIVATE_INLINE __forceinline +#else +#define WTF_PRIVATE_INLINE inline +#endif + +#if !defined(_CRTDBG_MAP_ALLOC) && !(defined(USE_SYSTEM_MALLOC) && USE_SYSTEM_MALLOC) + +// The nothrow functions here are actually not all that helpful, because fastMalloc will +// call CRASH() rather than returning 0, and returning 0 is what nothrow is all about. +// But since WebKit code never uses exceptions or nothrow at all, this is probably OK. +// Long term we will adopt FastAllocBase.h everywhere, and and replace this with +// debug-only code to make sure we don't use the system malloc via the default operator +// new by accident. + +#if ENABLE(GLOBAL_FASTMALLOC_NEW) + +#if COMPILER(MSVC) +#pragma warning(push) +#pragma warning(disable: 4290) // Disable the C++ exception specification ignored warning. +#endif +WTF_PRIVATE_INLINE void* operator new(size_t size) throw (std::bad_alloc) { return fastMalloc(size); } +WTF_PRIVATE_INLINE void* operator new(size_t size, const std::nothrow_t&) throw() { return fastMalloc(size); } +WTF_PRIVATE_INLINE void operator delete(void* p) throw() { fastFree(p); } +WTF_PRIVATE_INLINE void operator delete(void* p, const std::nothrow_t&) throw() { fastFree(p); } +WTF_PRIVATE_INLINE void* operator new[](size_t size) throw (std::bad_alloc) { return fastMalloc(size); } +WTF_PRIVATE_INLINE void* operator new[](size_t size, const std::nothrow_t&) throw() { return fastMalloc(size); } +WTF_PRIVATE_INLINE void operator delete[](void* p) throw() { fastFree(p); } +WTF_PRIVATE_INLINE void operator delete[](void* p, const std::nothrow_t&) throw() { fastFree(p); } +#if COMPILER(MSVC) +#pragma warning(pop) +#endif + +#endif + +#endif + +#endif /* WTF_FastMalloc_h */ diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/FixedArray.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/FixedArray.h new file mode 100644 index 000000000..c67d18cda --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/FixedArray.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2010 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 INC. 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 INC. 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 FixedArray_h +#define FixedArray_h + +#include + +namespace WTF { + +template class FixedArray { +public: + T& operator[](size_t i) + { + ASSERT(i < Size); + return m_data[i]; + } + + const T& operator[](size_t i) const + { + ASSERT(i < Size); + return m_data[i]; + } + + T* data() { return m_data; } + size_t size() const { return Size; } + +private: + T m_data[Size]; +}; + +} // namespace WTF + +using WTF::FixedArray; + +#endif // FixedArray_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Float32Array.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Float32Array.h new file mode 100644 index 000000000..230a768aa --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Float32Array.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * 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: + * 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 Float32Array_h +#define Float32Array_h + +#include "TypedArrayBase.h" +#include + +namespace WTF { + +class Float32Array : public TypedArrayBase { +public: + static inline PassRefPtr create(unsigned length); + static inline PassRefPtr create(const float* array, unsigned length); + static inline PassRefPtr create(PassRefPtr, unsigned byteOffset, unsigned length); + + // Can’t use "using" here due to a bug in the RVCT compiler. + bool set(TypedArrayBase* array, unsigned offset) { return TypedArrayBase::set(array, offset); } + + void set(unsigned index, double value) + { + if (index >= TypedArrayBase::m_length) + return; + TypedArrayBase::data()[index] = static_cast(value); + } + + // Invoked by the indexed getter. Does not perform range checks; caller + // is responsible for doing so and returning undefined as necessary. + float item(unsigned index) const + { + ASSERT(index < TypedArrayBase::m_length); + float result = TypedArrayBase::data()[index]; + return result; + } + + inline PassRefPtr subarray(int start) const; + inline PassRefPtr subarray(int start, int end) const; + +private: + inline Float32Array(PassRefPtr, + unsigned byteOffset, + unsigned length); + // Make constructor visible to superclass. + friend class TypedArrayBase; + + // Overridden from ArrayBufferView. + virtual bool isFloatArray() const { return true; } +}; + +PassRefPtr Float32Array::create(unsigned length) +{ + return TypedArrayBase::create(length); +} + +PassRefPtr Float32Array::create(const float* array, unsigned length) +{ + return TypedArrayBase::create(array, length); +} + +PassRefPtr Float32Array::create(PassRefPtr buffer, unsigned byteOffset, unsigned length) +{ + return TypedArrayBase::create(buffer, byteOffset, length); +} + +Float32Array::Float32Array(PassRefPtr buffer, unsigned byteOffset, unsigned length) + : TypedArrayBase(buffer, byteOffset, length) +{ +} + +PassRefPtr Float32Array::subarray(int start) const +{ + return subarray(start, length()); +} + +PassRefPtr Float32Array::subarray(int start, int end) const +{ + return subarrayImpl(start, end); +} + +} // namespace WTF + +using WTF::Float32Array; + +#endif // Float32Array_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Float64Array.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Float64Array.h new file mode 100644 index 000000000..46713556c --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Float64Array.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * Copyright (C) 2011 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: + * 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 Float64Array_h +#define Float64Array_h + +#include "TypedArrayBase.h" +#include + +namespace WTF { + +class Float64Array : public TypedArrayBase { +public: + static inline PassRefPtr create(unsigned length); + static inline PassRefPtr create(const double* array, unsigned length); + static inline PassRefPtr create(PassRefPtr, unsigned byteOffset, unsigned length); + + // Can’t use "using" here due to a bug in the RVCT compiler. + bool set(TypedArrayBase* array, unsigned offset) { return TypedArrayBase::set(array, offset); } + + void set(unsigned index, double value) + { + if (index >= TypedArrayBase::m_length) + return; + TypedArrayBase::data()[index] = static_cast(value); + } + + // Invoked by the indexed getter. Does not perform range checks; caller + // is responsible for doing so and returning undefined as necessary. + double item(unsigned index) const + { + ASSERT(index < TypedArrayBase::m_length); + double result = TypedArrayBase::data()[index]; + return result; + } + + inline PassRefPtr subarray(int start) const; + inline PassRefPtr subarray(int start, int end) const; + +private: + inline Float64Array(PassRefPtr, + unsigned byteOffset, + unsigned length); + // Make constructor visible to superclass. + friend class TypedArrayBase; + + // Overridden from ArrayBufferView. + virtual bool isDoubleArray() const { return true; } +}; + +PassRefPtr Float64Array::create(unsigned length) +{ + return TypedArrayBase::create(length); +} + +PassRefPtr Float64Array::create(const double* array, unsigned length) +{ + return TypedArrayBase::create(array, length); +} + +PassRefPtr Float64Array::create(PassRefPtr buffer, unsigned byteOffset, unsigned length) +{ + return TypedArrayBase::create(buffer, byteOffset, length); +} + +Float64Array::Float64Array(PassRefPtr buffer, unsigned byteOffset, unsigned length) + : TypedArrayBase(buffer, byteOffset, length) +{ +} + +PassRefPtr Float64Array::subarray(int start) const +{ + return subarray(start, length()); +} + +PassRefPtr Float64Array::subarray(int start, int end) const +{ + return subarrayImpl(start, end); +} + +} // namespace WTF + +using WTF::Float64Array; + +#endif // Float64Array_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Forward.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Forward.h new file mode 100644 index 000000000..b81ab2580 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Forward.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2006, 2009, 2011 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WTF_Forward_h +#define WTF_Forward_h + +#include + +namespace WTF { + template class Function; + template class ListRefPtr; + template class OwnArrayPtr; + template class OwnPtr; + template class PassOwnArrayPtr; + template class PassOwnPtr; + template class PassRefPtr; + template class RefPtr; + template class Vector; + + class ArrayBuffer; + class ArrayBufferView; + class AtomicString; + class AtomicStringImpl; + class CString; + class Decoder; + class Encoder; + class Float32Array; + class Float64Array; + class Int8Array; + class Int16Array; + class Int32Array; + class String; + template class StringBuffer; + class StringBuilder; + class StringImpl; + class Uint8Array; + class Uint8ClampedArray; + class Uint16Array; + class Uint32Array; +} + +using WTF::Function; +using WTF::ListRefPtr; +using WTF::OwnArrayPtr; +using WTF::OwnPtr; +using WTF::PassOwnArrayPtr; +using WTF::PassOwnPtr; +using WTF::PassRefPtr; +using WTF::RefPtr; +using WTF::Vector; + +using WTF::ArrayBuffer; +using WTF::ArrayBufferView; +using WTF::AtomicString; +using WTF::AtomicStringImpl; +using WTF::CString; +using WTF::Encoder; +using WTF::Decoder; +using WTF::Float32Array; +using WTF::Float64Array; +using WTF::Int8Array; +using WTF::Int16Array; +using WTF::Int32Array; +using WTF::String; +using WTF::StringBuffer; +using WTF::StringBuilder; +using WTF::StringImpl; +using WTF::Uint8Array; +using WTF::Uint8ClampedArray; +using WTF::Uint16Array; +using WTF::Uint32Array; + +#endif // WTF_Forward_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/FunctionConstructor.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/FunctionConstructor.h new file mode 100644 index 000000000..31986b70a --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/FunctionConstructor.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef FunctionConstructor_h +#define FunctionConstructor_h + +#include "InternalFunction.h" + +namespace WTF { +class TextPosition; +} + +namespace JSC { + + class FunctionPrototype; + + class FunctionConstructor : public InternalFunction { + public: + typedef InternalFunction Base; + + static FunctionConstructor* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, FunctionPrototype* functionPrototype) + { + FunctionConstructor* constructor = new (NotNull, allocateCell(*exec->heap())) FunctionConstructor(globalObject, structure); + constructor->finishCreation(exec, functionPrototype); + return constructor; + } + + static const ClassInfo s_info; + + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + { + return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); + } + + private: + FunctionConstructor(JSGlobalObject*, Structure*); + void finishCreation(ExecState*, FunctionPrototype*); + static ConstructType getConstructData(JSCell*, ConstructData&); + static CallType getCallData(JSCell*, CallData&); + }; + + JSObject* constructFunction(ExecState*, JSGlobalObject*, const ArgList&, const Identifier& functionName, const UString& sourceURL, const WTF::TextPosition&); + JSObject* constructFunction(ExecState*, JSGlobalObject*, const ArgList&); + + JS_EXPORT_PRIVATE JSObject* constructFunctionSkippingEvalEnabledCheck(ExecState*, JSGlobalObject*, const ArgList&, const Identifier&, const UString&, const WTF::TextPosition&); + +} // namespace JSC + +#endif // FunctionConstructor_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/FunctionPrototype.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/FunctionPrototype.h new file mode 100644 index 000000000..7dd1c2418 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/FunctionPrototype.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef FunctionPrototype_h +#define FunctionPrototype_h + +#include "InternalFunction.h" + +namespace JSC { + + class FunctionPrototype : public InternalFunction { + public: + typedef InternalFunction Base; + + static FunctionPrototype* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure) + { + FunctionPrototype* prototype = new (NotNull, allocateCell(*exec->heap())) FunctionPrototype(globalObject, structure); + prototype->finishCreation(exec, exec->propertyNames().nullIdentifier); + return prototype; + } + + void addFunctionProperties(ExecState*, JSGlobalObject*, JSFunction** callFunction, JSFunction** applyFunction); + + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) + { + return Structure::create(globalData, globalObject, proto, TypeInfo(ObjectType, StructureFlags), &s_info); + } + + static const ClassInfo s_info; + + protected: + void finishCreation(ExecState*, const Identifier& name); + + private: + FunctionPrototype(JSGlobalObject*, Structure*); + static CallType getCallData(JSCell*, CallData&); + }; + +} // namespace JSC + +#endif // FunctionPrototype_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Functional.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Functional.h new file mode 100644 index 000000000..bd0f3e282 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Functional.h @@ -0,0 +1,658 @@ +/* + * Copyright (C) 2011 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 INC. 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 INC. 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 WTF_Functional_h +#define WTF_Functional_h + +#include "Assertions.h" +#include "PassRefPtr.h" +#include "RefPtr.h" +#include "ThreadSafeRefCounted.h" + +#if PLATFORM(MAC) && COMPILER_SUPPORTS(BLOCKS) +#include +#endif + +namespace WTF { + +// Functional.h provides a very simple way to bind a function pointer and arguments together into a function object +// that can be stored, copied and invoked, similar to how boost::bind and std::bind in C++11. + +// Helper class template to determine whether a given type has ref and deref member functions +// with the right type signature. +template +class HasRefAndDeref { + typedef char YesType; + struct NoType { + char padding[8]; + }; + + struct BaseMixin { + void deref(); + void ref(); + }; + + struct Base : public T, public BaseMixin { }; + + template struct + TypeChecker { }; + + template + static NoType refCheck(U*, TypeChecker* = 0); + static YesType refCheck(...); + + template + static NoType derefCheck(U*, TypeChecker* = 0); + static YesType derefCheck(...); + +public: + static const bool value = sizeof(refCheck(static_cast(0))) == sizeof(YesType) && sizeof(derefCheck(static_cast(0))) == sizeof(YesType); +}; + +// A FunctionWrapper is a class template that can wrap a function pointer or a member function pointer and +// provide a unified interface for calling that function. +template +class FunctionWrapper; + +template +class FunctionWrapper { +public: + typedef R ResultType; + static const bool shouldRefFirstParameter = false; + + explicit FunctionWrapper(R (*function)()) + : m_function(function) + { + } + + R operator()() + { + return m_function(); + } + +private: + R (*m_function)(); +}; + +template +class FunctionWrapper { +public: + typedef R ResultType; + static const bool shouldRefFirstParameter = false; + + explicit FunctionWrapper(R (*function)(P1)) + : m_function(function) + { + } + + R operator()(P1 p1) + { + return m_function(p1); + } + +private: + R (*m_function)(P1); +}; + +template +class FunctionWrapper { +public: + typedef R ResultType; + static const bool shouldRefFirstParameter = false; + + explicit FunctionWrapper(R (*function)(P1, P2)) + : m_function(function) + { + } + + R operator()(P1 p1, P2 p2) + { + return m_function(p1, p2); + } + +private: + R (*m_function)(P1, P2); +}; + +template +class FunctionWrapper { +public: + typedef R ResultType; + static const bool shouldRefFirstParameter = false; + + explicit FunctionWrapper(R (*function)(P1, P2, P3)) + : m_function(function) + { + } + + R operator()(P1 p1, P2 p2, P3 p3) + { + return m_function(p1, p2, p3); + } + +private: + R (*m_function)(P1, P2, P3); +}; + +template +class FunctionWrapper { +public: + typedef R ResultType; + static const bool shouldRefFirstParameter = HasRefAndDeref::value; + + explicit FunctionWrapper(R (C::*function)()) + : m_function(function) + { + } + + R operator()(C* c) + { + return (c->*m_function)(); + } + +private: + R (C::*m_function)(); +}; + +template +class FunctionWrapper { +public: + typedef R ResultType; + static const bool shouldRefFirstParameter = HasRefAndDeref::value; + + explicit FunctionWrapper(R (C::*function)(P1)) + : m_function(function) + { + } + + R operator()(C* c, P1 p1) + { + return (c->*m_function)(p1); + } + +private: + R (C::*m_function)(P1); +}; + +template +class FunctionWrapper { +public: + typedef R ResultType; + static const bool shouldRefFirstParameter = HasRefAndDeref::value; + + explicit FunctionWrapper(R (C::*function)(P1, P2)) + : m_function(function) + { + } + + R operator()(C* c, P1 p1, P2 p2) + { + return (c->*m_function)(p1, p2); + } + +private: + R (C::*m_function)(P1, P2); +}; + +template +class FunctionWrapper { +public: + typedef R ResultType; + static const bool shouldRefFirstParameter = HasRefAndDeref::value; + + explicit FunctionWrapper(R (C::*function)(P1, P2, P3)) + : m_function(function) + { + } + + R operator()(C* c, P1 p1, P2 p2, P3 p3) + { + return (c->*m_function)(p1, p2, p3); + } + +private: + R (C::*m_function)(P1, P2, P3); +}; + +template +class FunctionWrapper { +public: + typedef R ResultType; + static const bool shouldRefFirstParameter = HasRefAndDeref::value; + + explicit FunctionWrapper(R (C::*function)(P1, P2, P3, P4)) + : m_function(function) + { + } + + R operator()(C* c, P1 p1, P2 p2, P3 p3, P4 p4) + { + return (c->*m_function)(p1, p2, p3, p4); + } + +private: + R (C::*m_function)(P1, P2, P3, P4); +}; + +template +class FunctionWrapper { +public: + typedef R ResultType; + static const bool shouldRefFirstParameter = HasRefAndDeref::value; + + explicit FunctionWrapper(R (C::*function)(P1, P2, P3, P4, P5)) + : m_function(function) + { + } + + R operator()(C* c, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + { + return (c->*m_function)(p1, p2, p3, p4, p5); + } + +private: + R (C::*m_function)(P1, P2, P3, P4, P5); +}; + +template struct RefAndDeref { + static void ref(T) { } + static void deref(T) { } +}; + +template struct RefAndDeref { + static void ref(T* t) { t->ref(); } + static void deref(T* t) { t->deref(); } +}; + +template struct ParamStorageTraits { + typedef T StorageType; + + static StorageType wrap(const T& value) { return value; } + static const T& unwrap(const StorageType& value) { return value; } +}; + +template struct ParamStorageTraits > { + typedef RefPtr StorageType; + + static StorageType wrap(PassRefPtr value) { return value; } + static T* unwrap(const StorageType& value) { return value.get(); } +}; + +template struct ParamStorageTraits > { + typedef RefPtr StorageType; + + static StorageType wrap(RefPtr value) { return value.release(); } + static T* unwrap(const StorageType& value) { return value.get(); } +}; + + +template class RetainPtr; + +template struct ParamStorageTraits > { + typedef RetainPtr StorageType; + + static StorageType wrap(const RetainPtr& value) { return value; } + static typename RetainPtr::PtrType unwrap(const StorageType& value) { return value.get(); } +}; + +class FunctionImplBase : public ThreadSafeRefCounted { +public: + virtual ~FunctionImplBase() { } +}; + +template +class FunctionImpl; + +template +class FunctionImpl : public FunctionImplBase { +public: + virtual R operator()() = 0; +}; + +template +class BoundFunctionImpl; + +template +class BoundFunctionImpl : public FunctionImpl { +public: + explicit BoundFunctionImpl(FunctionWrapper functionWrapper) + : m_functionWrapper(functionWrapper) + { + } + + virtual R operator()() + { + return m_functionWrapper(); + } + +private: + FunctionWrapper m_functionWrapper; +}; + +template +class BoundFunctionImpl : public FunctionImpl { + +public: + BoundFunctionImpl(FunctionWrapper functionWrapper, const P1& p1) + : m_functionWrapper(functionWrapper) + , m_p1(ParamStorageTraits::wrap(p1)) + { + RefAndDeref::ref(m_p1); + } + + ~BoundFunctionImpl() + { + RefAndDeref::deref(m_p1); + } + + virtual R operator()() + { + return m_functionWrapper(ParamStorageTraits::unwrap(m_p1)); + } + +private: + FunctionWrapper m_functionWrapper; + typename ParamStorageTraits::StorageType m_p1; +}; + +template +class BoundFunctionImpl : public FunctionImpl { +public: + BoundFunctionImpl(FunctionWrapper functionWrapper, const P1& p1, const P2& p2) + : m_functionWrapper(functionWrapper) + , m_p1(ParamStorageTraits::wrap(p1)) + , m_p2(ParamStorageTraits::wrap(p2)) + { + RefAndDeref::ref(m_p1); + } + + ~BoundFunctionImpl() + { + RefAndDeref::deref(m_p1); + } + + virtual typename FunctionWrapper::ResultType operator()() + { + return m_functionWrapper(ParamStorageTraits::unwrap(m_p1), ParamStorageTraits::unwrap(m_p2)); + } + +private: + FunctionWrapper m_functionWrapper; + typename ParamStorageTraits::StorageType m_p1; + typename ParamStorageTraits::StorageType m_p2; +}; + +template +class BoundFunctionImpl : public FunctionImpl { +public: + BoundFunctionImpl(FunctionWrapper functionWrapper, const P1& p1, const P2& p2, const P3& p3) + : m_functionWrapper(functionWrapper) + , m_p1(ParamStorageTraits::wrap(p1)) + , m_p2(ParamStorageTraits::wrap(p2)) + , m_p3(ParamStorageTraits::wrap(p3)) + { + RefAndDeref::ref(m_p1); + } + + ~BoundFunctionImpl() + { + RefAndDeref::deref(m_p1); + } + + virtual typename FunctionWrapper::ResultType operator()() + { + return m_functionWrapper(ParamStorageTraits::unwrap(m_p1), ParamStorageTraits::unwrap(m_p2), ParamStorageTraits::unwrap(m_p3)); + } + +private: + FunctionWrapper m_functionWrapper; + typename ParamStorageTraits::StorageType m_p1; + typename ParamStorageTraits::StorageType m_p2; + typename ParamStorageTraits::StorageType m_p3; +}; + +template +class BoundFunctionImpl : public FunctionImpl { +public: + BoundFunctionImpl(FunctionWrapper functionWrapper, const P1& p1, const P2& p2, const P3& p3, const P4& p4) + : m_functionWrapper(functionWrapper) + , m_p1(ParamStorageTraits::wrap(p1)) + , m_p2(ParamStorageTraits::wrap(p2)) + , m_p3(ParamStorageTraits::wrap(p3)) + , m_p4(ParamStorageTraits::wrap(p4)) + { + RefAndDeref::ref(m_p1); + } + + ~BoundFunctionImpl() + { + RefAndDeref::deref(m_p1); + } + + virtual typename FunctionWrapper::ResultType operator()() + { + return m_functionWrapper(ParamStorageTraits::unwrap(m_p1), ParamStorageTraits::unwrap(m_p2), ParamStorageTraits::unwrap(m_p3), ParamStorageTraits::unwrap(m_p4)); + } + +private: + FunctionWrapper m_functionWrapper; + typename ParamStorageTraits::StorageType m_p1; + typename ParamStorageTraits::StorageType m_p2; + typename ParamStorageTraits::StorageType m_p3; + typename ParamStorageTraits::StorageType m_p4; +}; + +template +class BoundFunctionImpl : public FunctionImpl { +public: + BoundFunctionImpl(FunctionWrapper functionWrapper, const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5) + : m_functionWrapper(functionWrapper) + , m_p1(ParamStorageTraits::wrap(p1)) + , m_p2(ParamStorageTraits::wrap(p2)) + , m_p3(ParamStorageTraits::wrap(p3)) + , m_p4(ParamStorageTraits::wrap(p4)) + , m_p5(ParamStorageTraits::wrap(p5)) + { + RefAndDeref::ref(m_p1); + } + + ~BoundFunctionImpl() + { + RefAndDeref::deref(m_p1); + } + + virtual typename FunctionWrapper::ResultType operator()() + { + return m_functionWrapper(ParamStorageTraits::unwrap(m_p1), ParamStorageTraits::unwrap(m_p2), ParamStorageTraits::unwrap(m_p3), ParamStorageTraits::unwrap(m_p4), ParamStorageTraits::unwrap(m_p5)); + } + +private: + FunctionWrapper m_functionWrapper; + typename ParamStorageTraits::StorageType m_p1; + typename ParamStorageTraits::StorageType m_p2; + typename ParamStorageTraits::StorageType m_p3; + typename ParamStorageTraits::StorageType m_p4; + typename ParamStorageTraits::StorageType m_p5; +}; + +template +class BoundFunctionImpl : public FunctionImpl { +public: + BoundFunctionImpl(FunctionWrapper functionWrapper, const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5, const P6& p6) + : m_functionWrapper(functionWrapper) + , m_p1(ParamStorageTraits::wrap(p1)) + , m_p2(ParamStorageTraits::wrap(p2)) + , m_p3(ParamStorageTraits::wrap(p3)) + , m_p4(ParamStorageTraits::wrap(p4)) + , m_p5(ParamStorageTraits::wrap(p5)) + , m_p6(ParamStorageTraits::wrap(p6)) + { + RefAndDeref::ref(m_p1); + } + + ~BoundFunctionImpl() + { + RefAndDeref::deref(m_p1); + } + + virtual typename FunctionWrapper::ResultType operator()() + { + return m_functionWrapper(ParamStorageTraits::unwrap(m_p1), ParamStorageTraits::unwrap(m_p2), ParamStorageTraits::unwrap(m_p3), ParamStorageTraits::unwrap(m_p4), ParamStorageTraits::unwrap(m_p5), ParamStorageTraits::unwrap(m_p6)); + } + +private: + FunctionWrapper m_functionWrapper; + typename ParamStorageTraits::StorageType m_p1; + typename ParamStorageTraits::StorageType m_p2; + typename ParamStorageTraits::StorageType m_p3; + typename ParamStorageTraits::StorageType m_p4; + typename ParamStorageTraits::StorageType m_p5; + typename ParamStorageTraits::StorageType m_p6; +}; + +class FunctionBase { +public: + bool isNull() const + { + return !m_impl; + } + +protected: + FunctionBase() + { + } + + explicit FunctionBase(PassRefPtr impl) + : m_impl(impl) + { + } + + template FunctionImpl* impl() const + { + return static_cast*>(m_impl.get()); + } + +private: + RefPtr m_impl; +}; + +template +class Function; + +template +class Function : public FunctionBase { +public: + Function() + { + } + + Function(PassRefPtr > impl) + : FunctionBase(impl) + { + } + + R operator()() const + { + ASSERT(!isNull()); + + return impl()->operator()(); + } + +#if PLATFORM(MAC) && COMPILER_SUPPORTS(BLOCKS) + typedef void (^BlockType)(); + operator BlockType() const + { + // Declare a RefPtr here so we'll be sure that the underlying FunctionImpl object's + // lifecycle is managed correctly. + RefPtr > functionImpl = impl(); + BlockType block = ^{ + functionImpl->operator()(); + }; + + // This is equivalent to: + // + // return [[block copy] autorelease]; + // + // We're using manual objc_msgSend calls here because we don't want to make the entire + // file Objective-C. It's useful to be able to implicitly convert a Function to + // a block even in C++ code, since that allows us to do things like: + // + // dispatch_async(queue, bind(...)); + // + id copiedBlock = objc_msgSend((id)block, sel_registerName("copy")); + id autoreleasedBlock = objc_msgSend(copiedBlock, sel_registerName("autorelease")); + return (BlockType)autoreleasedBlock; + } +#endif +}; + +template +Function::ResultType ()> bind(FunctionType function) +{ + return Function::ResultType ()>(adoptRef(new BoundFunctionImpl, typename FunctionWrapper::ResultType ()>(FunctionWrapper(function)))); +} + +template +Function::ResultType ()> bind(FunctionType function, const A1& a1) +{ + return Function::ResultType ()>(adoptRef(new BoundFunctionImpl, typename FunctionWrapper::ResultType (A1)>(FunctionWrapper(function), a1))); +} + +template +Function::ResultType ()> bind(FunctionType function, const A1& a1, const A2& a2) +{ + return Function::ResultType ()>(adoptRef(new BoundFunctionImpl, typename FunctionWrapper::ResultType (A1, A2)>(FunctionWrapper(function), a1, a2))); +} + +template +Function::ResultType ()> bind(FunctionType function, const A1& a1, const A2& a2, const A3& a3) +{ + return Function::ResultType ()>(adoptRef(new BoundFunctionImpl, typename FunctionWrapper::ResultType (A1, A2, A3)>(FunctionWrapper(function), a1, a2, a3))); +} + +template +Function::ResultType ()> bind(FunctionType function, const A1& a1, const A2& a2, const A3& a3, const A4& a4) +{ + return Function::ResultType ()>(adoptRef(new BoundFunctionImpl, typename FunctionWrapper::ResultType (A1, A2, A3, A4)>(FunctionWrapper(function), a1, a2, a3, a4))); +} + +template +Function::ResultType ()> bind(FunctionType function, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5) +{ + return Function::ResultType ()>(adoptRef(new BoundFunctionImpl, typename FunctionWrapper::ResultType (A1, A2, A3, A4, A5)>(FunctionWrapper(function), a1, a2, a3, a4, a5))); +} + +template +Function::ResultType ()> bind(FunctionType function, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6) +{ + return Function::ResultType ()>(adoptRef(new BoundFunctionImpl, typename FunctionWrapper::ResultType (A1, A2, A3, A4, A5, A6)>(FunctionWrapper(function), a1, a2, a3, a4, a5, a6))); +} + +} + +using WTF::Function; +using WTF::bind; + +#endif // WTF_Functional_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/GCActivityCallback.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/GCActivityCallback.h new file mode 100644 index 000000000..f40ebee5b --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/GCActivityCallback.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2010 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 GCActivityCallback_h +#define GCActivityCallback_h + +#include +#include + +#if USE(CF) +#include +#endif + +namespace JSC { + +class Heap; + +class GCActivityCallback { +public: + virtual ~GCActivityCallback() {} + virtual void operator()() {} + virtual void synchronize() {} + +protected: + GCActivityCallback() {} +}; + +struct DefaultGCActivityCallbackPlatformData; + +class DefaultGCActivityCallback : public GCActivityCallback { +public: + static PassOwnPtr create(Heap*); + + DefaultGCActivityCallback(Heap*); + ~DefaultGCActivityCallback(); + + void operator()(); + void synchronize(); + +#if USE(CF) +protected: + DefaultGCActivityCallback(Heap*, CFRunLoopRef); + void commonConstructor(Heap*, CFRunLoopRef); +#endif + +private: + OwnPtr d; +}; + +inline PassOwnPtr DefaultGCActivityCallback::create(Heap* heap) +{ + return adoptPtr(new DefaultGCActivityCallback(heap)); +} + +} + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/GetByIdStatus.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/GetByIdStatus.h new file mode 100644 index 000000000..00e50e76d --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/GetByIdStatus.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2012 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 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 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 GetByIdStatus_h +#define GetByIdStatus_h + +#include "StructureSet.h" +#include + +namespace JSC { + +class CodeBlock; +class Identifier; + +class GetByIdStatus { +public: + enum State { + NoInformation, // It's uncached so we have no information. + SimpleDirect, // It's cached for a direct access to a known object property. + TakesSlowPath, // It's known to often take slow path. + MakesCalls // It's known to take paths that make calls. + }; + + GetByIdStatus() + : m_state(NoInformation) + , m_offset(notFound) + { + } + + GetByIdStatus(State state, const StructureSet& structureSet, size_t offset) + : m_state(state) + , m_structureSet(structureSet) + , m_offset(offset) + { + ASSERT((state == SimpleDirect) == (offset != notFound)); + } + + static GetByIdStatus computeFor(CodeBlock*, unsigned bytecodeIndex, Identifier&); + + State state() const { return m_state; } + + bool isSet() const { return m_state != NoInformation; } + bool operator!() const { return !isSet(); } + bool isSimpleDirect() const { return m_state == SimpleDirect; } + bool takesSlowPath() const { return m_state == TakesSlowPath || m_state == MakesCalls; } + bool makesCalls() const { return m_state == MakesCalls; } + + const StructureSet& structureSet() const { return m_structureSet; } + size_t offset() const { return m_offset; } + +private: + State m_state; + StructureSet m_structureSet; + size_t m_offset; +}; + +} // namespace JSC + +#endif // PropertyAccessStatus_h + diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/GetPtr.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/GetPtr.h new file mode 100644 index 000000000..25a0e6d9b --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/GetPtr.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WTF_GetPtr_h +#define WTF_GetPtr_h + +namespace WTF { + + template inline T* getPtr(T* p) + { + return p; + } + +} // namespace WTF + +#endif // WTF_GetPtr_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/GlobalResolveInfo.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/GlobalResolveInfo.h new file mode 100644 index 000000000..5576cfacd --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/GlobalResolveInfo.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2012 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 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 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 GlobalResolveInfo_h +#define GlobalResolveInfo_h + +#include "WriteBarrier.h" + +namespace JSC { + +struct GlobalResolveInfo { + GlobalResolveInfo(unsigned bytecodeOffset) + : offset(0) + , bytecodeOffset(bytecodeOffset) + { + } + + WriteBarrier structure; + unsigned offset; + unsigned bytecodeOffset; +}; + +} // namespace JSC + +#endif // GlobalResolveInfo_h + diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Handle.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Handle.h new file mode 100644 index 000000000..6f467743c --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Handle.h @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2011 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 INC. 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 INC. 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 Handle_h +#define Handle_h + +#include "HandleTypes.h" + +namespace JSC { + +/* + A Handle is a smart pointer that updates automatically when the garbage + collector moves the object to which it points. + + The base Handle class represents a temporary reference to a pointer whose + lifetime is guaranteed by something else. +*/ + +template class Handle; + +// Creating a JSValue Handle is invalid +template <> class Handle; + +// Forward declare WeakGCMap +template class WeakGCMap; + +class HandleBase { + template friend class Weak; + friend class HandleHeap; + friend struct JSCallbackObjectData; + template friend class WeakGCMap; + +public: + bool operator!() const { return !m_slot || !*m_slot; } + + // This conversion operator allows implicit conversion to bool but not to other integer types. + typedef JSValue (HandleBase::*UnspecifiedBoolType); + operator UnspecifiedBoolType*() const { return (m_slot && *m_slot) ? reinterpret_cast(1) : 0; } + +protected: + HandleBase(HandleSlot slot) + : m_slot(slot) + { + } + + void swap(HandleBase& other) { std::swap(m_slot, other.m_slot); } + + HandleSlot slot() const { return m_slot; } + void setSlot(HandleSlot slot) + { + m_slot = slot; + } + +private: + HandleSlot m_slot; +}; + +template struct HandleConverter { + T* operator->() + { + return static_cast(this)->get(); + } + const T* operator->() const + { + return static_cast(this)->get(); + } + + T* operator*() + { + return static_cast(this)->get(); + } + const T* operator*() const + { + return static_cast(this)->get(); + } +}; + +template struct HandleConverter { + Handle asObject() const; + bool isObject() const { return jsValue().isObject(); } + bool getNumber(double number) const { return jsValue().getNumber(number); } + UString getString(ExecState*) const; + bool isUndefinedOrNull() const { return jsValue().isUndefinedOrNull(); } + +private: + JSValue jsValue() const + { + return static_cast(this)->get(); + } +}; + +template class Handle : public HandleBase, public HandleConverter, T> { +public: + template friend class HandleConverter; + typedef typename HandleTypes::ExternalType ExternalType; + template Handle(Handle o) + { + typename HandleTypes::template validateUpcast(); + setSlot(o.slot()); + } + + void swap(Handle& other) { HandleBase::swap(other); } + + ExternalType get() const { return HandleTypes::getFromSlot(this->slot()); } + +protected: + Handle(HandleSlot slot = 0) + : HandleBase(slot) + { + } + +private: + friend class HandleHeap; + + static Handle wrapSlot(HandleSlot slot) + { + return Handle(slot); + } +}; + +template Handle HandleConverter::asObject() const +{ + return Handle::wrapSlot(static_cast(this)->slot()); +} + +template inline bool operator==(const Handle& a, const Handle& b) +{ + return a.get() == b.get(); +} + +template inline bool operator==(const Handle& a, U* b) +{ + return a.get() == b; +} + +template inline bool operator==(T* a, const Handle& b) +{ + return a == b.get(); +} + +template inline bool operator!=(const Handle& a, const Handle& b) +{ + return a.get() != b.get(); +} + +template inline bool operator!=(const Handle& a, U* b) +{ + return a.get() != b; +} + +template inline bool operator!=(T* a, const Handle& b) +{ + return a != b.get(); +} + +template inline bool operator!=(const Handle& a, JSValue b) +{ + return a.get() != b; +} + +template inline bool operator!=(JSValue a, const Handle& b) +{ + return a != b.get(); +} + +} + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HandleHeap.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HandleHeap.h new file mode 100644 index 000000000..3b9db37a2 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HandleHeap.h @@ -0,0 +1,309 @@ +/* + * Copyright (C) 2011 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 INC. 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 INC. 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 HandleHeap_h +#define HandleHeap_h + +#include "BlockStack.h" +#include "Handle.h" +#include "HashCountedSet.h" +#include "SentinelLinkedList.h" +#include "SinglyLinkedList.h" + +namespace JSC { + +class HandleHeap; +class HeapRootVisitor; +class JSGlobalData; +class JSValue; +class SlotVisitor; + +class JS_EXPORT_PRIVATE WeakHandleOwner { +public: + virtual ~WeakHandleOwner(); + virtual bool isReachableFromOpaqueRoots(Handle, void* context, SlotVisitor&); + virtual void finalize(Handle, void* context); +}; + +class HandleHeap { +public: + static HandleHeap* heapFor(HandleSlot); + + HandleHeap(JSGlobalData*); + + JSGlobalData* globalData(); + + HandleSlot allocate(); + void deallocate(HandleSlot); + + void makeWeak(HandleSlot, WeakHandleOwner* = 0, void* context = 0); + HandleSlot copyWeak(HandleSlot); + + void visitStrongHandles(HeapRootVisitor&); + void visitWeakHandles(HeapRootVisitor&); + void finalizeWeakHandles(); + + JS_EXPORT_PRIVATE void writeBarrier(HandleSlot, const JSValue&); + +#if !ASSERT_DISABLED + bool hasWeakOwner(HandleSlot, WeakHandleOwner*); + bool hasFinalizer(HandleSlot); +#endif + + unsigned protectedGlobalObjectCount(); + + template void forEachStrongHandle(Functor&, const HashCountedSet& skipSet); + +private: + class Node { + public: + Node(WTF::SentinelTag); + Node(HandleHeap*); + + HandleSlot slot(); + HandleHeap* handleHeap(); + + void makeWeak(WeakHandleOwner*, void* context); + bool isWeak(); + + WeakHandleOwner* weakOwner(); + void* weakOwnerContext(); + + void setPrev(Node*); + Node* prev(); + + void setNext(Node*); + Node* next(); + + private: + WeakHandleOwner* emptyWeakOwner(); + + JSValue m_value; + HandleHeap* m_handleHeap; + WeakHandleOwner* m_weakOwner; + void* m_weakOwnerContext; + Node* m_prev; + Node* m_next; + }; + + static HandleSlot toHandle(Node*); + static Node* toNode(HandleSlot); + + JS_EXPORT_PRIVATE void grow(); + +#if ENABLE(GC_VALIDATION) || !ASSERT_DISABLED + bool isValidWeakNode(Node*); + bool isLiveNode(Node*); +#endif + + JSGlobalData* m_globalData; + BlockStack m_blockStack; + + SentinelLinkedList m_strongList; + SentinelLinkedList m_weakList; + SentinelLinkedList m_immediateList; + SinglyLinkedList m_freeList; + Node* m_nextToFinalize; +}; + +inline HandleHeap* HandleHeap::heapFor(HandleSlot handle) +{ + return toNode(handle)->handleHeap(); +} + +inline JSGlobalData* HandleHeap::globalData() +{ + return m_globalData; +} + +inline HandleSlot HandleHeap::toHandle(Node* node) +{ + return reinterpret_cast(node); +} + +inline HandleHeap::Node* HandleHeap::toNode(HandleSlot handle) +{ + return reinterpret_cast(handle); +} + +inline HandleSlot HandleHeap::allocate() +{ + // Forbid assignment to handles during the finalization phase, since it would violate many GC invariants. + // File a bug with stack trace if you hit this. + if (m_nextToFinalize) + CRASH(); + if (m_freeList.isEmpty()) + grow(); + + Node* node = m_freeList.pop(); + new (NotNull, node) Node(this); + m_immediateList.push(node); + return toHandle(node); +} + +inline void HandleHeap::deallocate(HandleSlot handle) +{ + Node* node = toNode(handle); + if (node == m_nextToFinalize) { + ASSERT(m_nextToFinalize->next()); + m_nextToFinalize = m_nextToFinalize->next(); + } + + SentinelLinkedList::remove(node); + m_freeList.push(node); +} + +inline HandleSlot HandleHeap::copyWeak(HandleSlot other) +{ + Node* node = toNode(allocate()); + node->makeWeak(toNode(other)->weakOwner(), toNode(other)->weakOwnerContext()); + writeBarrier(node->slot(), *other); + *node->slot() = *other; + return toHandle(node); +} + +inline void HandleHeap::makeWeak(HandleSlot handle, WeakHandleOwner* weakOwner, void* context) +{ + // Forbid assignment to handles during the finalization phase, since it would violate many GC invariants. + // File a bug with stack trace if you hit this. + if (m_nextToFinalize) + CRASH(); + Node* node = toNode(handle); + node->makeWeak(weakOwner, context); + + SentinelLinkedList::remove(node); + if (!*handle || !handle->isCell()) { + m_immediateList.push(node); + return; + } + + m_weakList.push(node); +} + +#if !ASSERT_DISABLED +inline bool HandleHeap::hasWeakOwner(HandleSlot handle, WeakHandleOwner* weakOwner) +{ + return toNode(handle)->weakOwner() == weakOwner; +} + +inline bool HandleHeap::hasFinalizer(HandleSlot handle) +{ + return toNode(handle)->weakOwner(); +} +#endif + +inline HandleHeap::Node::Node(HandleHeap* handleHeap) + : m_handleHeap(handleHeap) + , m_weakOwner(0) + , m_weakOwnerContext(0) + , m_prev(0) + , m_next(0) +{ +} + +inline HandleHeap::Node::Node(WTF::SentinelTag) + : m_handleHeap(0) + , m_weakOwner(0) + , m_weakOwnerContext(0) + , m_prev(0) + , m_next(0) +{ +} + +inline HandleSlot HandleHeap::Node::slot() +{ + return &m_value; +} + +inline HandleHeap* HandleHeap::Node::handleHeap() +{ + return m_handleHeap; +} + +inline void HandleHeap::Node::makeWeak(WeakHandleOwner* weakOwner, void* context) +{ + m_weakOwner = weakOwner ? weakOwner : emptyWeakOwner(); + m_weakOwnerContext = context; +} + +inline bool HandleHeap::Node::isWeak() +{ + return m_weakOwner; // True for emptyWeakOwner(). +} + +inline WeakHandleOwner* HandleHeap::Node::weakOwner() +{ + return m_weakOwner == emptyWeakOwner() ? 0 : m_weakOwner; // 0 for emptyWeakOwner(). +} + +inline void* HandleHeap::Node::weakOwnerContext() +{ + ASSERT(weakOwner()); + return m_weakOwnerContext; +} + +inline void HandleHeap::Node::setPrev(Node* prev) +{ + m_prev = prev; +} + +inline HandleHeap::Node* HandleHeap::Node::prev() +{ + return m_prev; +} + +inline void HandleHeap::Node::setNext(Node* next) +{ + m_next = next; +} + +inline HandleHeap::Node* HandleHeap::Node::next() +{ + return m_next; +} + +// Sentinel to indicate that a node is weak, but its owner has no meaningful +// callbacks. This allows us to optimize by skipping such nodes. +inline WeakHandleOwner* HandleHeap::Node::emptyWeakOwner() +{ + return reinterpret_cast(-1); +} + +template void HandleHeap::forEachStrongHandle(Functor& functor, const HashCountedSet& skipSet) +{ + Node* end = m_strongList.end(); + for (Node* node = m_strongList.begin(); node != end; node = node->next()) { + JSValue value = *node->slot(); + if (!value || !value.isCell()) + continue; + if (skipSet.contains(value.asCell())) + continue; + functor(value.asCell()); + } +} + +} + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HandleStack.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HandleStack.h new file mode 100644 index 000000000..a1e8a0b2a --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HandleStack.h @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2010 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 INC. 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 INC. 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 HandleStack_h +#define HandleStack_h + +#include "Assertions.h" +#include "BlockStack.h" +#include "Handle.h" + +#include + +namespace JSC { + +class LocalScope; +class HeapRootVisitor; + +class HandleStack { +public: + class Frame { + public: + HandleSlot m_next; + HandleSlot m_end; + }; + + HandleStack(); + + void enterScope(Frame&); + void leaveScope(Frame&); + + HandleSlot push(); + + void visit(HeapRootVisitor&); + +private: + void grow(); + void zapTo(Frame&); + HandleSlot findFirstAfter(HandleSlot); + +#ifndef NDEBUG + size_t m_scopeDepth; +#endif + BlockStack m_blockStack; + Frame m_frame; +}; + +inline void HandleStack::enterScope(Frame& lastFrame) +{ +#ifndef NDEBUG + ++m_scopeDepth; +#endif + + lastFrame = m_frame; +} + + + +inline void HandleStack::zapTo(Frame& lastFrame) +{ +#ifdef NDEBUG + UNUSED_PARAM(lastFrame); +#else + const Vector& blocks = m_blockStack.blocks(); + + if (lastFrame.m_end != m_frame.m_end) { // Zapping to a frame in a different block. + int i = blocks.size() - 1; + for ( ; blocks[i] + m_blockStack.blockLength != lastFrame.m_end; --i) { + for (int j = m_blockStack.blockLength - 1; j >= 0; --j) + blocks[i][j] = JSValue(); + } + + for (HandleSlot it = blocks[i] + m_blockStack.blockLength - 1; it != lastFrame.m_next - 1; --it) + *it = JSValue(); + + return; + } + + for (HandleSlot it = m_frame.m_next - 1; it != lastFrame.m_next - 1; --it) + *it = JSValue(); +#endif +} + +inline void HandleStack::leaveScope(Frame& lastFrame) +{ +#ifndef NDEBUG + --m_scopeDepth; +#endif + + zapTo(lastFrame); + + if (lastFrame.m_end != m_frame.m_end) // Popping to a frame in a different block. + m_blockStack.shrink(lastFrame.m_end); + + m_frame = lastFrame; +} + +inline HandleSlot HandleStack::push() +{ + ASSERT(m_scopeDepth); // Creating a Local outside of a LocalScope is a memory leak. + if (m_frame.m_next == m_frame.m_end) + grow(); + return m_frame.m_next++; +} + +} + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HandleTypes.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HandleTypes.h new file mode 100644 index 000000000..780ab85cd --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HandleTypes.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2011 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 INC. 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 INC. 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 HandleTypes_h +#define HandleTypes_h + +#include "JSValue.h" + +namespace JSC { + +typedef enum { } Unknown; +typedef JSValue* HandleSlot; + +template struct HandleTypes { + typedef T* ExternalType; + static ExternalType getFromSlot(HandleSlot slot) { return (slot && *slot) ? reinterpret_cast(slot->asCell()) : 0; } + static JSValue toJSValue(T* cell) { return reinterpret_cast(cell); } + template static void validateUpcast() { T* temp; temp = (U*)0; } +}; + +template<> struct HandleTypes { + typedef JSValue ExternalType; + static ExternalType getFromSlot(HandleSlot slot) { return slot ? *slot : JSValue(); } + static JSValue toJSValue(const JSValue& v) { return v; } + template static void validateUpcast() { } +}; + +} // namespace JSC + +#endif // HandleTypes_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HandlerInfo.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HandlerInfo.h new file mode 100644 index 000000000..8396c9607 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HandlerInfo.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2012 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 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 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 HandlerInfo_h +#define HandlerInfo_h + +#include "CodeLocation.h" +#include + +namespace JSC { + +struct HandlerInfo { + uint32_t start; + uint32_t end; + uint32_t target; + uint32_t scopeDepth; +#if ENABLE(JIT) + CodeLocationLabel nativeCode; +#endif +}; + +} // namespace JSC + +#endif // HandlerInfo_h + diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HashCountedSet.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HashCountedSet.h new file mode 100644 index 000000000..b97d8c8fd --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HashCountedSet.h @@ -0,0 +1,228 @@ +/* + * Copyright (C) 2005, 2006, 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WTF_HashCountedSet_h +#define WTF_HashCountedSet_h + +#include "Assertions.h" +#include "HashMap.h" +#include "Vector.h" + +namespace WTF { + + template::Hash, + typename Traits = HashTraits > class HashCountedSet { + WTF_MAKE_FAST_ALLOCATED; + private: + typedef HashMap ImplType; + public: + typedef Value ValueType; + typedef typename ImplType::iterator iterator; + typedef typename ImplType::const_iterator const_iterator; + + HashCountedSet() {} + + int size() const; + int capacity() const; + bool isEmpty() const; + + // Iterators iterate over pairs of values and counts. + iterator begin(); + iterator end(); + const_iterator begin() const; + const_iterator end() const; + + iterator find(const ValueType&); + const_iterator find(const ValueType&) const; + bool contains(const ValueType&) const; + unsigned count(const ValueType&) const; + + // Increases the count if an equal value is already present + // the return value is a pair of an interator to the new value's + // location, and a bool that is true if an new entry was added. + std::pair add(const ValueType&); + + // Reduces the count of the value, and removes it if count + // goes down to zero, returns true if the value is removed. + bool remove(const ValueType&); + bool remove(iterator); + + // Removes the value, regardless of its count. + void removeAll(iterator); + void removeAll(const ValueType&); + + // Clears the whole set. + void clear(); + + private: + ImplType m_impl; + }; + + template + inline int HashCountedSet::size() const + { + return m_impl.size(); + } + + template + inline int HashCountedSet::capacity() const + { + return m_impl.capacity(); + } + + template + inline bool HashCountedSet::isEmpty() const + { + return size() == 0; + } + + template + inline typename HashCountedSet::iterator HashCountedSet::begin() + { + return m_impl.begin(); + } + + template + inline typename HashCountedSet::iterator HashCountedSet::end() + { + return m_impl.end(); + } + + template + inline typename HashCountedSet::const_iterator HashCountedSet::begin() const + { + return m_impl.begin(); + } + + template + inline typename HashCountedSet::const_iterator HashCountedSet::end() const + { + return m_impl.end(); + } + + template + inline typename HashCountedSet::iterator HashCountedSet::find(const ValueType& value) + { + return m_impl.find(value); + } + + template + inline typename HashCountedSet::const_iterator HashCountedSet::find(const ValueType& value) const + { + return m_impl.find(value); + } + + template + inline bool HashCountedSet::contains(const ValueType& value) const + { + return m_impl.contains(value); + } + + template + inline unsigned HashCountedSet::count(const ValueType& value) const + { + return m_impl.get(value); + } + + template + inline std::pair::iterator, bool> HashCountedSet::add(const ValueType &value) + { + pair result = m_impl.add(value, 0); + ++result.first->second; + return result; + } + + template + inline bool HashCountedSet::remove(const ValueType& value) + { + return remove(find(value)); + } + + template + inline bool HashCountedSet::remove(iterator it) + { + if (it == end()) + return false; + + unsigned oldVal = it->second; + ASSERT(oldVal); + unsigned newVal = oldVal - 1; + if (newVal) { + it->second = newVal; + return false; + } + + m_impl.remove(it); + return true; + } + + template + inline void HashCountedSet::removeAll(const ValueType& value) + { + removeAll(find(value)); + } + + template + inline void HashCountedSet::removeAll(iterator it) + { + if (it == end()) + return; + + m_impl.remove(it); + } + + template + inline void HashCountedSet::clear() + { + m_impl.clear(); + } + + template + inline void copyToVector(const HashCountedSet& collection, VectorType& vector) + { + typedef typename HashCountedSet::const_iterator iterator; + + vector.resize(collection.size()); + + iterator it = collection.begin(); + iterator end = collection.end(); + for (unsigned i = 0; it != end; ++it, ++i) + vector[i] = *it; + } + + template + inline void copyToVector(const HashCountedSet& collection, Vector& vector) + { + typedef typename HashCountedSet::const_iterator iterator; + + vector.resize(collection.size()); + + iterator it = collection.begin(); + iterator end = collection.end(); + for (unsigned i = 0; it != end; ++it, ++i) + vector[i] = (*it).first; + } + + +} // namespace khtml + +using WTF::HashCountedSet; + +#endif /* WTF_HashCountedSet_h */ diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HashFunctions.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HashFunctions.h new file mode 100644 index 000000000..2c66a2d9f --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HashFunctions.h @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2005, 2006, 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WTF_HashFunctions_h +#define WTF_HashFunctions_h + +#include "RefPtr.h" +#include + +namespace WTF { + + template struct IntTypes; + template<> struct IntTypes<1> { typedef int8_t SignedType; typedef uint8_t UnsignedType; }; + template<> struct IntTypes<2> { typedef int16_t SignedType; typedef uint16_t UnsignedType; }; + template<> struct IntTypes<4> { typedef int32_t SignedType; typedef uint32_t UnsignedType; }; + template<> struct IntTypes<8> { typedef int64_t SignedType; typedef uint64_t UnsignedType; }; + + // integer hash function + + // Thomas Wang's 32 Bit Mix Function: http://www.cris.com/~Ttwang/tech/inthash.htm + inline unsigned intHash(uint8_t key8) + { + unsigned key = key8; + key += ~(key << 15); + key ^= (key >> 10); + key += (key << 3); + key ^= (key >> 6); + key += ~(key << 11); + key ^= (key >> 16); + return key; + } + + // Thomas Wang's 32 Bit Mix Function: http://www.cris.com/~Ttwang/tech/inthash.htm + inline unsigned intHash(uint16_t key16) + { + unsigned key = key16; + key += ~(key << 15); + key ^= (key >> 10); + key += (key << 3); + key ^= (key >> 6); + key += ~(key << 11); + key ^= (key >> 16); + return key; + } + + // Thomas Wang's 32 Bit Mix Function: http://www.cris.com/~Ttwang/tech/inthash.htm + inline unsigned intHash(uint32_t key) + { + key += ~(key << 15); + key ^= (key >> 10); + key += (key << 3); + key ^= (key >> 6); + key += ~(key << 11); + key ^= (key >> 16); + return key; + } + + // Thomas Wang's 64 bit Mix Function: http://www.cris.com/~Ttwang/tech/inthash.htm + inline unsigned intHash(uint64_t key) + { + key += ~(key << 32); + key ^= (key >> 22); + key += ~(key << 13); + key ^= (key >> 8); + key += (key << 3); + key ^= (key >> 15); + key += ~(key << 27); + key ^= (key >> 31); + return static_cast(key); + } + + template struct IntHash { + static unsigned hash(T key) { return intHash(static_cast::UnsignedType>(key)); } + static bool equal(T a, T b) { return a == b; } + static const bool safeToCompareToEmptyOrDeleted = true; + }; + + template struct FloatHash { + static unsigned hash(T key) + { + union { + T key; + typename IntTypes::UnsignedType bits; + } u; + u.key = key; + return intHash(u.bits); + } + static bool equal(T a, T b) { return a == b; } + static const bool safeToCompareToEmptyOrDeleted = true; + }; + + // pointer identity hash function + + template struct PtrHash { + static unsigned hash(T key) + { +#if COMPILER(MSVC) +#pragma warning(push) +#pragma warning(disable: 4244) // work around what seems to be a bug in MSVC's conversion warnings +#endif + return IntHash::hash(reinterpret_cast(key)); +#if COMPILER(MSVC) +#pragma warning(pop) +#endif + } + static bool equal(T a, T b) { return a == b; } + static const bool safeToCompareToEmptyOrDeleted = true; + }; + template struct PtrHash > : PtrHash { + using PtrHash::hash; + static unsigned hash(const RefPtr

& key) { return hash(key.get()); } + using PtrHash::equal; + static bool equal(const RefPtr

& a, const RefPtr

& b) { return a == b; } + static bool equal(P* a, const RefPtr

& b) { return a == b; } + static bool equal(const RefPtr

& a, P* b) { return a == b; } + }; + + // default hash function for each type + + template struct DefaultHash; + + template struct PairHash { + static unsigned hash(const std::pair& p) + { + return intHash((static_cast(DefaultHash::Hash::hash(p.first)) << 32 | DefaultHash::Hash::hash(p.second))); + } + static bool equal(const std::pair& a, const std::pair& b) + { + return DefaultHash::Hash::equal(a.first, b.first) && DefaultHash::Hash::equal(a.second, b.second); + } + static const bool safeToCompareToEmptyOrDeleted = DefaultHash::Hash::safeToCompareToEmptyOrDeleted + && DefaultHash::Hash::safeToCompareToEmptyOrDeleted; + }; + + // make IntHash the default hash function for many integer types + + template<> struct DefaultHash { typedef IntHash Hash; }; + template<> struct DefaultHash { typedef IntHash Hash; }; + template<> struct DefaultHash { typedef IntHash Hash; }; + template<> struct DefaultHash { typedef IntHash Hash; }; + template<> struct DefaultHash { typedef IntHash Hash; }; + template<> struct DefaultHash { typedef IntHash Hash; }; + template<> struct DefaultHash { typedef IntHash Hash; }; + template<> struct DefaultHash { typedef IntHash Hash; }; + +#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED) + template<> struct DefaultHash { typedef IntHash Hash; }; +#endif + + template<> struct DefaultHash { typedef FloatHash Hash; }; + template<> struct DefaultHash { typedef FloatHash Hash; }; + + // make PtrHash the default hash function for pointer types that don't specialize + + template struct DefaultHash { typedef PtrHash Hash; }; + template struct DefaultHash > { typedef PtrHash > Hash; }; + + template struct DefaultHash > { typedef PairHash Hash; }; + +} // namespace WTF + +using WTF::DefaultHash; +using WTF::IntHash; +using WTF::PtrHash; + +#endif // WTF_HashFunctions_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HashIterators.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HashIterators.h new file mode 100644 index 000000000..6afa2fa57 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HashIterators.h @@ -0,0 +1,218 @@ +/* + * 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. + */ + +#ifndef WTF_HashIterators_h +#define WTF_HashIterators_h + +namespace WTF { + + template struct HashTableConstKeysIterator; + template struct HashTableConstValuesIterator; + template struct HashTableKeysIterator; + template struct HashTableValuesIterator; + + template struct HashTableConstIteratorAdapter > { + private: + typedef std::pair ValueType; + public: + typedef HashTableConstKeysIterator Keys; + typedef HashTableConstValuesIterator Values; + + HashTableConstIteratorAdapter() {} + HashTableConstIteratorAdapter(const typename HashTableType::const_iterator& impl) : m_impl(impl) {} + + const ValueType* get() const { return (const ValueType*)m_impl.get(); } + const ValueType& operator*() const { return *get(); } + const ValueType* operator->() const { return get(); } + + HashTableConstIteratorAdapter& operator++() { ++m_impl; return *this; } + // postfix ++ intentionally omitted + + Keys keys() { return Keys(*this); } + Values values() { return Values(*this); } + + typename HashTableType::const_iterator m_impl; + }; + + template struct HashTableIteratorAdapter > { + private: + typedef std::pair ValueType; + public: + typedef HashTableKeysIterator Keys; + typedef HashTableValuesIterator Values; + + HashTableIteratorAdapter() {} + HashTableIteratorAdapter(const typename HashTableType::iterator& impl) : m_impl(impl) {} + + ValueType* get() const { return (ValueType*)m_impl.get(); } + ValueType& operator*() const { return *get(); } + ValueType* operator->() const { return get(); } + + HashTableIteratorAdapter& operator++() { ++m_impl; return *this; } + // postfix ++ intentionally omitted + + operator HashTableConstIteratorAdapter() { + typename HashTableType::const_iterator i = m_impl; + return i; + } + + Keys keys() { return Keys(*this); } + Values values() { return Values(*this); } + + typename HashTableType::iterator m_impl; + }; + + template struct HashTableConstKeysIterator { + private: + typedef HashTableConstIteratorAdapter > ConstIterator; + + public: + HashTableConstKeysIterator(const ConstIterator& impl) : m_impl(impl) {} + + const KeyType* get() const { return &(m_impl.get()->first); } + const KeyType& operator*() const { return *get(); } + const KeyType* operator->() const { return get(); } + + HashTableConstKeysIterator& operator++() { ++m_impl; return *this; } + // postfix ++ intentionally omitted + + ConstIterator m_impl; + }; + + template struct HashTableConstValuesIterator { + private: + typedef HashTableConstIteratorAdapter > ConstIterator; + + public: + HashTableConstValuesIterator(const ConstIterator& impl) : m_impl(impl) {} + + const MappedType* get() const { return &(m_impl.get()->second); } + const MappedType& operator*() const { return *get(); } + const MappedType* operator->() const { return get(); } + + HashTableConstValuesIterator& operator++() { ++m_impl; return *this; } + // postfix ++ intentionally omitted + + ConstIterator m_impl; + }; + + template struct HashTableKeysIterator { + private: + typedef HashTableIteratorAdapter > Iterator; + typedef HashTableConstIteratorAdapter > ConstIterator; + + public: + HashTableKeysIterator(const Iterator& impl) : m_impl(impl) {} + + KeyType* get() const { return &(m_impl.get()->first); } + KeyType& operator*() const { return *get(); } + KeyType* operator->() const { return get(); } + + HashTableKeysIterator& operator++() { ++m_impl; return *this; } + // postfix ++ intentionally omitted + + operator HashTableConstKeysIterator() { + ConstIterator i = m_impl; + return i; + } + + Iterator m_impl; + }; + + template struct HashTableValuesIterator { + private: + typedef HashTableIteratorAdapter > Iterator; + typedef HashTableConstIteratorAdapter > ConstIterator; + + public: + HashTableValuesIterator(const Iterator& impl) : m_impl(impl) {} + + MappedType* get() const { return &(m_impl.get()->second); } + MappedType& operator*() const { return *get(); } + MappedType* operator->() const { return get(); } + + HashTableValuesIterator& operator++() { ++m_impl; return *this; } + // postfix ++ intentionally omitted + + operator HashTableConstValuesIterator() { + ConstIterator i = m_impl; + return i; + } + + Iterator m_impl; + }; + + template + inline bool operator==(const HashTableConstKeysIterator& a, const HashTableConstKeysIterator& b) + { + return a.m_impl == b.m_impl; + } + + template + inline bool operator!=(const HashTableConstKeysIterator& a, const HashTableConstKeysIterator& b) + { + return a.m_impl != b.m_impl; + } + + template + inline bool operator==(const HashTableConstValuesIterator& a, const HashTableConstValuesIterator& b) + { + return a.m_impl == b.m_impl; + } + + template + inline bool operator!=(const HashTableConstValuesIterator& a, const HashTableConstValuesIterator& b) + { + return a.m_impl != b.m_impl; + } + + template + inline bool operator==(const HashTableKeysIterator& a, const HashTableKeysIterator& b) + { + return a.m_impl == b.m_impl; + } + + template + inline bool operator!=(const HashTableKeysIterator& a, const HashTableKeysIterator& b) + { + return a.m_impl != b.m_impl; + } + + template + inline bool operator==(const HashTableValuesIterator& a, const HashTableValuesIterator& b) + { + return a.m_impl == b.m_impl; + } + + template + inline bool operator!=(const HashTableValuesIterator& a, const HashTableValuesIterator& b) + { + return a.m_impl != b.m_impl; + } + + +} // namespace WTF + +#endif // WTF_HashIterators_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HashMap.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HashMap.h new file mode 100644 index 000000000..13e6d496d --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HashMap.h @@ -0,0 +1,491 @@ +/* + * Copyright (C) 2005, 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WTF_HashMap_h +#define WTF_HashMap_h + +#include "HashTable.h" + +namespace WTF { + + template struct PairFirstExtractor; + + template struct ReferenceTypeMaker { + typedef T& ReferenceType; + }; + template struct ReferenceTypeMaker { + typedef T& ReferenceType; + }; + + template::Hash, + typename KeyTraitsArg = HashTraits, typename MappedTraitsArg = HashTraits > + class HashMap { + WTF_MAKE_FAST_ALLOCATED; + private: + typedef KeyTraitsArg KeyTraits; + typedef MappedTraitsArg MappedTraits; + typedef PairHashTraits ValueTraits; + + public: + typedef typename KeyTraits::TraitType KeyType; + typedef typename MappedTraits::TraitType MappedType; + typedef typename ValueTraits::TraitType ValueType; + + private: + typedef typename MappedTraits::PassInType MappedPassInType; + typedef typename MappedTraits::PassOutType MappedPassOutType; + typedef typename MappedTraits::PeekType MappedPeekType; + + typedef typename ReferenceTypeMaker::ReferenceType MappedPassInReferenceType; + + typedef HashArg HashFunctions; + + typedef HashTable, + HashFunctions, ValueTraits, KeyTraits> HashTableType; + + class HashMapKeysProxy; + class HashMapValuesProxy; + + public: + typedef HashTableIteratorAdapter iterator; + typedef HashTableConstIteratorAdapter const_iterator; + + public: + void swap(HashMap&); + + int size() const; + int capacity() const; + bool isEmpty() const; + + // iterators iterate over pairs of keys and values + iterator begin(); + iterator end(); + const_iterator begin() const; + const_iterator end() const; + + HashMapKeysProxy& keys() { return static_cast(*this); } + const HashMapKeysProxy& keys() const { return static_cast(*this); } + + HashMapValuesProxy& values() { return static_cast(*this); } + const HashMapValuesProxy& values() const { return static_cast(*this); } + + iterator find(const KeyType&); + const_iterator find(const KeyType&) const; + bool contains(const KeyType&) const; + MappedPeekType get(const KeyType&) const; + + // replaces value but not key if key is already present + // return value is a pair of the iterator to the key location, + // and a boolean that's true if a new value was actually added + pair set(const KeyType&, MappedPassInType); + + // does nothing if key is already present + // return value is a pair of the iterator to the key location, + // and a boolean that's true if a new value was actually added + pair add(const KeyType&, MappedPassInType); + + void remove(const KeyType&); + void remove(iterator); + void clear(); + + MappedPassOutType take(const KeyType&); // efficient combination of get with remove + + // An alternate version of find() that finds the object by hashing and comparing + // with some other type, to avoid the cost of type conversion. HashTranslator + // must have the following function members: + // static unsigned hash(const T&); + // static bool equal(const ValueType&, const T&); + template iterator find(const T&); + template const_iterator find(const T&) const; + template bool contains(const T&) const; + + // An alternate version of add() that finds the object by hashing and comparing + // with some other type, to avoid the cost of type conversion if the object is already + // in the table. HashTranslator must have the following function members: + // static unsigned hash(const T&); + // static bool equal(const ValueType&, const T&); + // static translate(ValueType&, const T&, unsigned hashCode); + template pair add(const T&, MappedPassInType); + + void checkConsistency() const; + + private: + pair inlineAdd(const KeyType&, MappedPassInReferenceType); + + class HashMapKeysProxy : private HashMap { + public: + typedef typename HashMap::iterator::Keys iterator; + typedef typename HashMap::const_iterator::Keys const_iterator; + + iterator begin() + { + return HashMap::begin().keys(); + } + + iterator end() + { + return HashMap::end().keys(); + } + + const_iterator begin() const + { + return HashMap::begin().keys(); + } + + const_iterator end() const + { + return HashMap::end().keys(); + } + + private: + friend class HashMap; + + // These are intentionally not implemented. + HashMapKeysProxy(); + HashMapKeysProxy(const HashMapKeysProxy&); + HashMapKeysProxy& operator=(const HashMapKeysProxy&); + ~HashMapKeysProxy(); + }; + + class HashMapValuesProxy : private HashMap { + public: + typedef typename HashMap::iterator::Values iterator; + typedef typename HashMap::const_iterator::Values const_iterator; + + iterator begin() + { + return HashMap::begin().values(); + } + + iterator end() + { + return HashMap::end().values(); + } + + const_iterator begin() const + { + return HashMap::begin().values(); + } + + const_iterator end() const + { + return HashMap::end().values(); + } + + private: + friend class HashMap; + + // These are intentionally not implemented. + HashMapValuesProxy(); + HashMapValuesProxy(const HashMapValuesProxy&); + HashMapValuesProxy& operator=(const HashMapValuesProxy&); + ~HashMapValuesProxy(); + }; + + HashTableType m_impl; + }; + + template struct PairFirstExtractor { + static const typename PairType::first_type& extract(const PairType& p) { return p.first; } + }; + + template + struct HashMapTranslator { + template static unsigned hash(const T& key) { return HashFunctions::hash(key); } + template static bool equal(const T& a, const U& b) { return HashFunctions::equal(a, b); } + template static void translate(T& location, const U& key, const V& mapped) + { + location.first = key; + ValueTraits::SecondTraits::store(mapped, location.second); + } + }; + + template + struct HashMapTranslatorAdapter { + template static unsigned hash(const T& key) { return Translator::hash(key); } + template static bool equal(const T& a, const U& b) { return Translator::equal(a, b); } + template static void translate(T& location, const U& key, const V& mapped, unsigned hashCode) + { + Translator::translate(location.first, key, hashCode); + ValueTraits::SecondTraits::store(mapped, location.second); + } + }; + + template + inline void HashMap::swap(HashMap& other) + { + m_impl.swap(other.m_impl); + } + + template + inline int HashMap::size() const + { + return m_impl.size(); + } + + template + inline int HashMap::capacity() const + { + return m_impl.capacity(); + } + + template + inline bool HashMap::isEmpty() const + { + return m_impl.isEmpty(); + } + + template + inline typename HashMap::iterator HashMap::begin() + { + return m_impl.begin(); + } + + template + inline typename HashMap::iterator HashMap::end() + { + return m_impl.end(); + } + + template + inline typename HashMap::const_iterator HashMap::begin() const + { + return m_impl.begin(); + } + + template + inline typename HashMap::const_iterator HashMap::end() const + { + return m_impl.end(); + } + + template + inline typename HashMap::iterator HashMap::find(const KeyType& key) + { + return m_impl.find(key); + } + + template + inline typename HashMap::const_iterator HashMap::find(const KeyType& key) const + { + return m_impl.find(key); + } + + template + inline bool HashMap::contains(const KeyType& key) const + { + return m_impl.contains(key); + } + + template + template + inline typename HashMap::iterator + HashMap::find(const TYPE& value) + { + return m_impl.template find >(value); + } + + template + template + inline typename HashMap::const_iterator + HashMap::find(const TYPE& value) const + { + return m_impl.template find >(value); + } + + template + template + inline bool + HashMap::contains(const TYPE& value) const + { + return m_impl.template contains >(value); + } + + template + inline pair::iterator, bool> + HashMap::inlineAdd(const KeyType& key, MappedPassInReferenceType mapped) + { + return m_impl.template add >(key, mapped); + } + + template + pair::iterator, bool> + HashMap::set(const KeyType& key, MappedPassInType mapped) + { + pair result = inlineAdd(key, mapped); + if (!result.second) { + // The inlineAdd call above found an existing hash table entry; we need to set the mapped value. + MappedTraits::store(mapped, result.first->second); + } + return result; + } + + template + template + pair::iterator, bool> + HashMap::add(const TYPE& key, MappedPassInType value) + { + return m_impl.template addPassingHashCode >(key, value); + } + + template + pair::iterator, bool> + HashMap::add(const KeyType& key, MappedPassInType mapped) + { + return inlineAdd(key, mapped); + } + + template + typename HashMap::MappedPeekType + HashMap::get(const KeyType& key) const + { + ValueType* entry = const_cast(m_impl).lookup(key); + if (!entry) + return MappedTraits::peek(MappedTraits::emptyValue()); + return MappedTraits::peek(entry->second); + } + + template + inline void HashMap::remove(iterator it) + { + if (it.m_impl == m_impl.end()) + return; + m_impl.internalCheckTableConsistency(); + m_impl.removeWithoutEntryConsistencyCheck(it.m_impl); + } + + template + inline void HashMap::remove(const KeyType& key) + { + remove(find(key)); + } + + template + inline void HashMap::clear() + { + m_impl.clear(); + } + + template + typename HashMap::MappedPassOutType + HashMap::take(const KeyType& key) + { + iterator it = find(key); + if (it == end()) + return MappedTraits::passOut(MappedTraits::emptyValue()); + MappedPassOutType result = MappedTraits::passOut(it->second); + remove(it); + return result; + } + + template + inline void HashMap::checkConsistency() const + { + m_impl.checkTableConsistency(); + } + + template + bool operator==(const HashMap& a, const HashMap& b) + { + if (a.size() != b.size()) + return false; + + typedef typename HashMap::const_iterator const_iterator; + + const_iterator end = a.end(); + const_iterator notFound = b.end(); + for (const_iterator it = a.begin(); it != end; ++it) { + const_iterator bPos = b.find(it->first); + if (bPos == notFound || it->second != bPos->second) + return false; + } + + return true; + } + + template + inline bool operator!=(const HashMap& a, const HashMap& b) + { + return !(a == b); + } + + template + void deleteAllPairSeconds(HashTableType& collection) + { + typedef typename HashTableType::const_iterator iterator; + iterator end = collection.end(); + for (iterator it = collection.begin(); it != end; ++it) + delete it->second; + } + + template + inline void deleteAllValues(const HashMap& collection) + { + deleteAllPairSeconds(collection); + } + + template + void deleteAllPairFirsts(HashTableType& collection) + { + typedef typename HashTableType::const_iterator iterator; + iterator end = collection.end(); + for (iterator it = collection.begin(); it != end; ++it) + delete it->first; + } + + template + inline void deleteAllKeys(const HashMap& collection) + { + deleteAllPairFirsts(collection); + } + + template + inline void copyKeysToVector(const HashMap& collection, Y& vector) + { + typedef typename HashMap::const_iterator::Keys iterator; + + vector.resize(collection.size()); + + iterator it = collection.begin().keys(); + iterator end = collection.end().keys(); + for (unsigned i = 0; it != end; ++it, ++i) + vector[i] = *it; + } + + template + inline void copyValuesToVector(const HashMap& collection, Y& vector) + { + typedef typename HashMap::const_iterator::Values iterator; + + vector.resize(collection.size()); + + iterator it = collection.begin().values(); + iterator end = collection.end().values(); + for (unsigned i = 0; it != end; ++it, ++i) + vector[i] = *it; + } + +} // namespace WTF + +using WTF::HashMap; + +#include "RefPtrHashMap.h" + +#endif /* WTF_HashMap_h */ diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HashSet.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HashSet.h new file mode 100644 index 000000000..7fce19348 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HashSet.h @@ -0,0 +1,261 @@ +/* + * Copyright (C) 2005, 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WTF_HashSet_h +#define WTF_HashSet_h + +#include "FastAllocBase.h" +#include "HashTable.h" + +namespace WTF { + + struct IdentityExtractor; + + template class HashSet; + template + void deleteAllValues(const HashSet&); + template + void fastDeleteAllValues(const HashSet&); + + template::Hash, + typename TraitsArg = HashTraits > class HashSet { + WTF_MAKE_FAST_ALLOCATED; + private: + typedef HashArg HashFunctions; + typedef TraitsArg ValueTraits; + + public: + typedef typename ValueTraits::TraitType ValueType; + + private: + typedef HashTable HashTableType; + + public: + typedef HashTableConstIteratorAdapter iterator; + typedef HashTableConstIteratorAdapter const_iterator; + + void swap(HashSet&); + + int size() const; + int capacity() const; + bool isEmpty() const; + + iterator begin() const; + iterator end() const; + + iterator find(const ValueType&) const; + bool contains(const ValueType&) const; + + // An alternate version of find() that finds the object by hashing and comparing + // with some other type, to avoid the cost of type conversion. HashTranslator + // must have the following function members: + // static unsigned hash(const T&); + // static bool equal(const ValueType&, const T&); + // FIXME: We should reverse the order of the template arguments so that callers + // can just pass the translator and let the compiler deduce T. + template iterator find(const T&) const; + template bool contains(const T&) const; + + // The return value is a pair of an interator to the new value's location, + // and a bool that is true if an new entry was added. + pair add(const ValueType&); + + // An alternate version of add() that finds the object by hashing and comparing + // with some other type, to avoid the cost of type conversion if the object is already + // in the table. HashTranslator must have the following function members: + // static unsigned hash(const T&); + // static bool equal(const ValueType&, const T&); + // static translate(ValueType&, const T&, unsigned hashCode); + // FIXME: We should reverse the order of the template arguments so that callers + // can just pass the translator and let the compiler deduce T. + template pair add(const T&); + + void remove(const ValueType&); + void remove(iterator); + void clear(); + + private: + friend void deleteAllValues<>(const HashSet&); + friend void fastDeleteAllValues<>(const HashSet&); + + HashTableType m_impl; + }; + + struct IdentityExtractor { + template static const T& extract(const T& t) { return t; } + }; + + template + struct HashSetTranslatorAdapter { + template static unsigned hash(const T& key) { return Translator::hash(key); } + template static bool equal(const T& a, const U& b) { return Translator::equal(a, b); } + template static void translate(T& location, const U& key, const U&, unsigned hashCode) + { + Translator::translate(location, key, hashCode); + } + }; + + template + inline void HashSet::swap(HashSet& other) + { + m_impl.swap(other.m_impl); + } + + template + inline int HashSet::size() const + { + return m_impl.size(); + } + + template + inline int HashSet::capacity() const + { + return m_impl.capacity(); + } + + template + inline bool HashSet::isEmpty() const + { + return m_impl.isEmpty(); + } + + template + inline typename HashSet::iterator HashSet::begin() const + { + return m_impl.begin(); + } + + template + inline typename HashSet::iterator HashSet::end() const + { + return m_impl.end(); + } + + template + inline typename HashSet::iterator HashSet::find(const ValueType& value) const + { + return m_impl.find(value); + } + + template + inline bool HashSet::contains(const ValueType& value) const + { + return m_impl.contains(value); + } + + template + template + typename HashSet::iterator + inline HashSet::find(const T& value) const + { + return m_impl.template find >(value); + } + + template + template + inline bool HashSet::contains(const T& value) const + { + return m_impl.template contains >(value); + } + + template + inline pair::iterator, bool> HashSet::add(const ValueType& value) + { + return m_impl.add(value); + } + + template + template + inline pair::iterator, bool> + HashSet::add(const T& value) + { + return m_impl.template addPassingHashCode >(value, value); + } + + template + inline void HashSet::remove(iterator it) + { + if (it.m_impl == m_impl.end()) + return; + m_impl.internalCheckTableConsistency(); + m_impl.removeWithoutEntryConsistencyCheck(it.m_impl); + } + + template + inline void HashSet::remove(const ValueType& value) + { + remove(find(value)); + } + + template + inline void HashSet::clear() + { + m_impl.clear(); + } + + template + void deleteAllValues(HashTableType& collection) + { + typedef typename HashTableType::const_iterator iterator; + iterator end = collection.end(); + for (iterator it = collection.begin(); it != end; ++it) + delete *it; + } + + template + inline void deleteAllValues(const HashSet& collection) + { + deleteAllValues::ValueType>(collection.m_impl); + } + + template + void fastDeleteAllValues(HashTableType& collection) + { + typedef typename HashTableType::const_iterator iterator; + iterator end = collection.end(); + for (iterator it = collection.begin(); it != end; ++it) + fastDelete(*it); + } + + template + inline void fastDeleteAllValues(const HashSet& collection) + { + fastDeleteAllValues::ValueType>(collection.m_impl); + } + + template + inline void copyToVector(const HashSet& collection, W& vector) + { + typedef typename HashSet::const_iterator iterator; + + vector.resize(collection.size()); + + iterator it = collection.begin(); + iterator end = collection.end(); + for (unsigned i = 0; it != end; ++it, ++i) + vector[i] = *it; + } + +} // namespace WTF + +using WTF::HashSet; + +#endif /* WTF_HashSet_h */ diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HashTable.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HashTable.h new file mode 100644 index 000000000..44f914330 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HashTable.h @@ -0,0 +1,1244 @@ +/* + * Copyright (C) 2005, 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. + * Copyright (C) 2008 David Levin + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WTF_HashTable_h +#define WTF_HashTable_h + +#include "Alignment.h" +#include "Assertions.h" +#include "FastMalloc.h" +#include "HashTraits.h" +#include "StdLibExtras.h" +#include "Threading.h" +#include "ValueCheck.h" + +namespace WTF { + +#define DUMP_HASHTABLE_STATS 0 + +// Enables internal WTF consistency checks that are invoked automatically. Non-WTF callers can call checkTableConsistency() even if internal checks are disabled. +#define CHECK_HASHTABLE_CONSISTENCY 0 + +#ifdef NDEBUG +#define CHECK_HASHTABLE_ITERATORS 0 +#define CHECK_HASHTABLE_USE_AFTER_DESTRUCTION 0 +#else +#define CHECK_HASHTABLE_ITERATORS 1 +#define CHECK_HASHTABLE_USE_AFTER_DESTRUCTION 1 +#endif + +#if DUMP_HASHTABLE_STATS + + struct HashTableStats { + ~HashTableStats(); + // All of the variables are accessed in ~HashTableStats when the static struct is destroyed. + + // The following variables are all atomically incremented when modified. + static int numAccesses; + static int numRehashes; + static int numRemoves; + static int numReinserts; + + // The following variables are only modified in the recordCollisionAtCount method within a mutex. + static int maxCollisions; + static int numCollisions; + static int collisionGraph[4096]; + + static void recordCollisionAtCount(int count); + }; + +#endif + + template + class HashTable; + template + class HashTableIterator; + template + class HashTableConstIterator; + + template + void addIterator(const HashTable*, + HashTableConstIterator*); + + template + void removeIterator(HashTableConstIterator*); + +#if !CHECK_HASHTABLE_ITERATORS + + template + inline void addIterator(const HashTable*, + HashTableConstIterator*) { } + + template + inline void removeIterator(HashTableConstIterator*) { } + +#endif + + typedef enum { HashItemKnownGood } HashItemKnownGoodTag; + + template + class HashTableConstIterator { + private: + typedef HashTable HashTableType; + typedef HashTableIterator iterator; + typedef HashTableConstIterator const_iterator; + typedef Value ValueType; + typedef const ValueType& ReferenceType; + typedef const ValueType* PointerType; + + friend class HashTable; + friend class HashTableIterator; + + void skipEmptyBuckets() + { + while (m_position != m_endPosition && HashTableType::isEmptyOrDeletedBucket(*m_position)) + ++m_position; + } + + HashTableConstIterator(const HashTableType* table, PointerType position, PointerType endPosition) + : m_position(position), m_endPosition(endPosition) + { + addIterator(table, this); + skipEmptyBuckets(); + } + + HashTableConstIterator(const HashTableType* table, PointerType position, PointerType endPosition, HashItemKnownGoodTag) + : m_position(position), m_endPosition(endPosition) + { + addIterator(table, this); + } + + public: + HashTableConstIterator() + { + addIterator(static_cast(0), this); + } + + // default copy, assignment and destructor are OK if CHECK_HASHTABLE_ITERATORS is 0 + +#if CHECK_HASHTABLE_ITERATORS + ~HashTableConstIterator() + { + removeIterator(this); + } + + HashTableConstIterator(const const_iterator& other) + : m_position(other.m_position), m_endPosition(other.m_endPosition) + { + addIterator(other.m_table, this); + } + + const_iterator& operator=(const const_iterator& other) + { + m_position = other.m_position; + m_endPosition = other.m_endPosition; + + removeIterator(this); + addIterator(other.m_table, this); + + return *this; + } +#endif + + PointerType get() const + { + checkValidity(); + return m_position; + } + ReferenceType operator*() const { return *get(); } + PointerType operator->() const { return get(); } + + const_iterator& operator++() + { + checkValidity(); + ASSERT(m_position != m_endPosition); + ++m_position; + skipEmptyBuckets(); + return *this; + } + + // postfix ++ intentionally omitted + + // Comparison. + bool operator==(const const_iterator& other) const + { + checkValidity(other); + return m_position == other.m_position; + } + bool operator!=(const const_iterator& other) const + { + checkValidity(other); + return m_position != other.m_position; + } + bool operator==(const iterator& other) const + { + return *this == static_cast(other); + } + bool operator!=(const iterator& other) const + { + return *this != static_cast(other); + } + + private: + void checkValidity() const + { +#if CHECK_HASHTABLE_ITERATORS + ASSERT(m_table); +#endif + } + + +#if CHECK_HASHTABLE_ITERATORS + void checkValidity(const const_iterator& other) const + { + ASSERT(m_table); + ASSERT_UNUSED(other, other.m_table); + ASSERT(m_table == other.m_table); + } +#else + void checkValidity(const const_iterator&) const { } +#endif + + PointerType m_position; + PointerType m_endPosition; + +#if CHECK_HASHTABLE_ITERATORS + public: + // Any modifications of the m_next or m_previous of an iterator that is in a linked list of a HashTable::m_iterator, + // should be guarded with m_table->m_mutex. + mutable const HashTableType* m_table; + mutable const_iterator* m_next; + mutable const_iterator* m_previous; +#endif + }; + + template + class HashTableIterator { + private: + typedef HashTable HashTableType; + typedef HashTableIterator iterator; + typedef HashTableConstIterator const_iterator; + typedef Value ValueType; + typedef ValueType& ReferenceType; + typedef ValueType* PointerType; + + friend class HashTable; + + HashTableIterator(HashTableType* table, PointerType pos, PointerType end) : m_iterator(table, pos, end) { } + HashTableIterator(HashTableType* table, PointerType pos, PointerType end, HashItemKnownGoodTag tag) : m_iterator(table, pos, end, tag) { } + + public: + HashTableIterator() { } + + // default copy, assignment and destructor are OK + + PointerType get() const { return const_cast(m_iterator.get()); } + ReferenceType operator*() const { return *get(); } + PointerType operator->() const { return get(); } + + iterator& operator++() { ++m_iterator; return *this; } + + // postfix ++ intentionally omitted + + // Comparison. + bool operator==(const iterator& other) const { return m_iterator == other.m_iterator; } + bool operator!=(const iterator& other) const { return m_iterator != other.m_iterator; } + bool operator==(const const_iterator& other) const { return m_iterator == other; } + bool operator!=(const const_iterator& other) const { return m_iterator != other; } + + operator const_iterator() const { return m_iterator; } + + private: + const_iterator m_iterator; + }; + + using std::swap; + + // Work around MSVC's standard library, whose swap for pairs does not swap by component. + template inline void hashTableSwap(T& a, T& b) + { + swap(a, b); + } + + // Swap pairs by component, in case of pair members that specialize swap. + template inline void hashTableSwap(pair& a, pair& b) + { + swap(a.first, b.first); + swap(a.second, b.second); + } + + template struct Mover; + template struct Mover { static void move(T& from, T& to) { hashTableSwap(from, to); } }; + template struct Mover { static void move(T& from, T& to) { to = from; } }; + + template class IdentityHashTranslator { + public: + template static unsigned hash(const T& key) { return HashFunctions::hash(key); } + template static bool equal(const T& a, const T& b) { return HashFunctions::equal(a, b); } + template static void translate(T& location, const U&, const T& value) { location = value; } + }; + + template + class HashTable { + public: + typedef HashTableIterator iterator; + typedef HashTableConstIterator const_iterator; + typedef Traits ValueTraits; + typedef Key KeyType; + typedef Value ValueType; + typedef IdentityHashTranslator IdentityTranslatorType; + + HashTable(); + ~HashTable() + { + invalidateIterators(); + deallocateTable(m_table, m_tableSize); +#if CHECK_HASHTABLE_USE_AFTER_DESTRUCTION + m_table = (ValueType*)(uintptr_t)0xbbadbeef; +#endif + } + + HashTable(const HashTable&); + void swap(HashTable&); + HashTable& operator=(const HashTable&); + + iterator begin() { return makeIterator(m_table); } + iterator end() { return makeKnownGoodIterator(m_table + m_tableSize); } + const_iterator begin() const { return makeConstIterator(m_table); } + const_iterator end() const { return makeKnownGoodConstIterator(m_table + m_tableSize); } + + int size() const { return m_keyCount; } + int capacity() const { return m_tableSize; } + bool isEmpty() const { return !m_keyCount; } + + pair add(const ValueType& value) { return add(Extractor::extract(value), value); } + + // A special version of add() that finds the object by hashing and comparing + // with some other type, to avoid the cost of type conversion if the object is already + // in the table. + template pair add(const T& key, const Extra&); + template pair addPassingHashCode(const T& key, const Extra&); + + iterator find(const KeyType& key) { return find(key); } + const_iterator find(const KeyType& key) const { return find(key); } + bool contains(const KeyType& key) const { return contains(key); } + + template iterator find(const T&); + template const_iterator find(const T&) const; + template bool contains(const T&) const; + + void remove(const KeyType&); + void remove(iterator); + void removeWithoutEntryConsistencyCheck(iterator); + void removeWithoutEntryConsistencyCheck(const_iterator); + void clear(); + + static bool isEmptyBucket(const ValueType& value) { return Extractor::extract(value) == KeyTraits::emptyValue(); } + static bool isDeletedBucket(const ValueType& value) { return KeyTraits::isDeletedValue(Extractor::extract(value)); } + static bool isEmptyOrDeletedBucket(const ValueType& value) { return isEmptyBucket(value) || isDeletedBucket(value); } + + ValueType* lookup(const Key& key) { return lookup(key); } + template ValueType* lookup(const T&); + +#if !ASSERT_DISABLED + void checkTableConsistency() const; +#else + static void checkTableConsistency() { } +#endif +#if CHECK_HASHTABLE_CONSISTENCY + void internalCheckTableConsistency() const { checkTableConsistency(); } + void internalCheckTableConsistencyExceptSize() const { checkTableConsistencyExceptSize(); } +#else + static void internalCheckTableConsistencyExceptSize() { } + static void internalCheckTableConsistency() { } +#endif + + private: + static ValueType* allocateTable(int size); + static void deallocateTable(ValueType* table, int size); + + typedef pair LookupType; + typedef pair FullLookupType; + + LookupType lookupForWriting(const Key& key) { return lookupForWriting(key); }; + template FullLookupType fullLookupForWriting(const T&); + template LookupType lookupForWriting(const T&); + + template void checkKey(const T&); + + void removeAndInvalidateWithoutEntryConsistencyCheck(ValueType*); + void removeAndInvalidate(ValueType*); + void remove(ValueType*); + + bool shouldExpand() const { return (m_keyCount + m_deletedCount) * m_maxLoad >= m_tableSize; } + bool mustRehashInPlace() const { return m_keyCount * m_minLoad < m_tableSize * 2; } + bool shouldShrink() const { return m_keyCount * m_minLoad < m_tableSize && m_tableSize > KeyTraits::minimumTableSize; } + void expand(); + void shrink() { rehash(m_tableSize / 2); } + + void rehash(int newTableSize); + void reinsert(ValueType&); + + static void initializeBucket(ValueType& bucket); + static void deleteBucket(ValueType& bucket) { bucket.~ValueType(); Traits::constructDeletedValue(bucket); } + + FullLookupType makeLookupResult(ValueType* position, bool found, unsigned hash) + { return FullLookupType(LookupType(position, found), hash); } + + iterator makeIterator(ValueType* pos) { return iterator(this, pos, m_table + m_tableSize); } + const_iterator makeConstIterator(ValueType* pos) const { return const_iterator(this, pos, m_table + m_tableSize); } + iterator makeKnownGoodIterator(ValueType* pos) { return iterator(this, pos, m_table + m_tableSize, HashItemKnownGood); } + const_iterator makeKnownGoodConstIterator(ValueType* pos) const { return const_iterator(this, pos, m_table + m_tableSize, HashItemKnownGood); } + +#if !ASSERT_DISABLED + void checkTableConsistencyExceptSize() const; +#else + static void checkTableConsistencyExceptSize() { } +#endif + +#if CHECK_HASHTABLE_ITERATORS + void invalidateIterators(); +#else + static void invalidateIterators() { } +#endif + + static const int m_maxLoad = 2; + static const int m_minLoad = 6; + + ValueType* m_table; + int m_tableSize; + int m_tableSizeMask; + int m_keyCount; + int m_deletedCount; + +#if CHECK_HASHTABLE_ITERATORS + public: + // All access to m_iterators should be guarded with m_mutex. + mutable const_iterator* m_iterators; + mutable Mutex m_mutex; +#endif + }; + + template + inline HashTable::HashTable() + : m_table(0) + , m_tableSize(0) + , m_tableSizeMask(0) + , m_keyCount(0) + , m_deletedCount(0) +#if CHECK_HASHTABLE_ITERATORS + , m_iterators(0) +#endif + { + } + + inline unsigned doubleHash(unsigned key) + { + key = ~key + (key >> 23); + key ^= (key << 12); + key ^= (key >> 7); + key ^= (key << 2); + key ^= (key >> 20); + return key; + } + +#if ASSERT_DISABLED + + template + template + inline void HashTable::checkKey(const T&) + { + } + +#else + + template + template + void HashTable::checkKey(const T& key) + { + if (!HashFunctions::safeToCompareToEmptyOrDeleted) + return; + ASSERT(!HashTranslator::equal(KeyTraits::emptyValue(), key)); + AlignedBuffer deletedValueBuffer; + ValueType& deletedValue = *reinterpret_cast_ptr(deletedValueBuffer.buffer); + Traits::constructDeletedValue(deletedValue); + ASSERT(!HashTranslator::equal(Extractor::extract(deletedValue), key)); + } + +#endif + + template + template + inline Value* HashTable::lookup(const T& key) + { + checkKey(key); + + int k = 0; + int sizeMask = m_tableSizeMask; + ValueType* table = m_table; + unsigned h = HashTranslator::hash(key); + int i = h & sizeMask; + + if (!table) + return 0; + +#if DUMP_HASHTABLE_STATS + atomicIncrement(&HashTableStats::numAccesses); + int probeCount = 0; +#endif + + while (1) { + ValueType* entry = table + i; + + // we count on the compiler to optimize out this branch + if (HashFunctions::safeToCompareToEmptyOrDeleted) { + if (HashTranslator::equal(Extractor::extract(*entry), key)) + return entry; + + if (isEmptyBucket(*entry)) + return 0; + } else { + if (isEmptyBucket(*entry)) + return 0; + + if (!isDeletedBucket(*entry) && HashTranslator::equal(Extractor::extract(*entry), key)) + return entry; + } +#if DUMP_HASHTABLE_STATS + ++probeCount; + HashTableStats::recordCollisionAtCount(probeCount); +#endif + if (k == 0) + k = 1 | doubleHash(h); + i = (i + k) & sizeMask; + } + } + + template + template + inline typename HashTable::LookupType HashTable::lookupForWriting(const T& key) + { + ASSERT(m_table); + checkKey(key); + + int k = 0; + ValueType* table = m_table; + int sizeMask = m_tableSizeMask; + unsigned h = HashTranslator::hash(key); + int i = h & sizeMask; + +#if DUMP_HASHTABLE_STATS + atomicIncrement(&HashTableStats::numAccesses); + int probeCount = 0; +#endif + + ValueType* deletedEntry = 0; + + while (1) { + ValueType* entry = table + i; + + // we count on the compiler to optimize out this branch + if (HashFunctions::safeToCompareToEmptyOrDeleted) { + if (isEmptyBucket(*entry)) + return LookupType(deletedEntry ? deletedEntry : entry, false); + + if (HashTranslator::equal(Extractor::extract(*entry), key)) + return LookupType(entry, true); + + if (isDeletedBucket(*entry)) + deletedEntry = entry; + } else { + if (isEmptyBucket(*entry)) + return LookupType(deletedEntry ? deletedEntry : entry, false); + + if (isDeletedBucket(*entry)) + deletedEntry = entry; + else if (HashTranslator::equal(Extractor::extract(*entry), key)) + return LookupType(entry, true); + } +#if DUMP_HASHTABLE_STATS + ++probeCount; + HashTableStats::recordCollisionAtCount(probeCount); +#endif + if (k == 0) + k = 1 | doubleHash(h); + i = (i + k) & sizeMask; + } + } + + template + template + inline typename HashTable::FullLookupType HashTable::fullLookupForWriting(const T& key) + { + ASSERT(m_table); + checkKey(key); + + int k = 0; + ValueType* table = m_table; + int sizeMask = m_tableSizeMask; + unsigned h = HashTranslator::hash(key); + int i = h & sizeMask; + +#if DUMP_HASHTABLE_STATS + atomicIncrement(&HashTableStats::numAccesses); + int probeCount = 0; +#endif + + ValueType* deletedEntry = 0; + + while (1) { + ValueType* entry = table + i; + + // we count on the compiler to optimize out this branch + if (HashFunctions::safeToCompareToEmptyOrDeleted) { + if (isEmptyBucket(*entry)) + return makeLookupResult(deletedEntry ? deletedEntry : entry, false, h); + + if (HashTranslator::equal(Extractor::extract(*entry), key)) + return makeLookupResult(entry, true, h); + + if (isDeletedBucket(*entry)) + deletedEntry = entry; + } else { + if (isEmptyBucket(*entry)) + return makeLookupResult(deletedEntry ? deletedEntry : entry, false, h); + + if (isDeletedBucket(*entry)) + deletedEntry = entry; + else if (HashTranslator::equal(Extractor::extract(*entry), key)) + return makeLookupResult(entry, true, h); + } +#if DUMP_HASHTABLE_STATS + ++probeCount; + HashTableStats::recordCollisionAtCount(probeCount); +#endif + if (k == 0) + k = 1 | doubleHash(h); + i = (i + k) & sizeMask; + } + } + + template struct HashTableBucketInitializer; + + template<> struct HashTableBucketInitializer { + template static void initialize(Value& bucket) + { + new (NotNull, &bucket) Value(Traits::emptyValue()); + } + }; + + template<> struct HashTableBucketInitializer { + template static void initialize(Value& bucket) + { + // This initializes the bucket without copying the empty value. + // That makes it possible to use this with types that don't support copying. + // The memset to 0 looks like a slow operation but is optimized by the compilers. + memset(&bucket, 0, sizeof(bucket)); + } + }; + + template + inline void HashTable::initializeBucket(ValueType& bucket) + { + HashTableBucketInitializer::template initialize(bucket); + } + + template + template + inline pair::iterator, bool> HashTable::add(const T& key, const Extra& extra) + { + checkKey(key); + + invalidateIterators(); + + if (!m_table) + expand(); + + internalCheckTableConsistency(); + + ASSERT(m_table); + + int k = 0; + ValueType* table = m_table; + int sizeMask = m_tableSizeMask; + unsigned h = HashTranslator::hash(key); + int i = h & sizeMask; + +#if DUMP_HASHTABLE_STATS + atomicIncrement(&HashTableStats::numAccesses); + int probeCount = 0; +#endif + + ValueType* deletedEntry = 0; + ValueType* entry; + while (1) { + entry = table + i; + + // we count on the compiler to optimize out this branch + if (HashFunctions::safeToCompareToEmptyOrDeleted) { + if (isEmptyBucket(*entry)) + break; + + if (HashTranslator::equal(Extractor::extract(*entry), key)) + return std::make_pair(makeKnownGoodIterator(entry), false); + + if (isDeletedBucket(*entry)) + deletedEntry = entry; + } else { + if (isEmptyBucket(*entry)) + break; + + if (isDeletedBucket(*entry)) + deletedEntry = entry; + else if (HashTranslator::equal(Extractor::extract(*entry), key)) + return std::make_pair(makeKnownGoodIterator(entry), false); + } +#if DUMP_HASHTABLE_STATS + ++probeCount; + HashTableStats::recordCollisionAtCount(probeCount); +#endif + if (k == 0) + k = 1 | doubleHash(h); + i = (i + k) & sizeMask; + } + + if (deletedEntry) { + initializeBucket(*deletedEntry); + entry = deletedEntry; + --m_deletedCount; + } + + HashTranslator::translate(*entry, key, extra); + + ++m_keyCount; + + if (shouldExpand()) { + // FIXME: This makes an extra copy on expand. Probably not that bad since + // expand is rare, but would be better to have a version of expand that can + // follow a pivot entry and return the new position. + KeyType enteredKey = Extractor::extract(*entry); + expand(); + pair p = std::make_pair(find(enteredKey), true); + ASSERT(p.first != end()); + return p; + } + + internalCheckTableConsistency(); + + return std::make_pair(makeKnownGoodIterator(entry), true); + } + + template + template + inline pair::iterator, bool> HashTable::addPassingHashCode(const T& key, const Extra& extra) + { + checkKey(key); + + invalidateIterators(); + + if (!m_table) + expand(); + + internalCheckTableConsistency(); + + FullLookupType lookupResult = fullLookupForWriting(key); + + ValueType* entry = lookupResult.first.first; + bool found = lookupResult.first.second; + unsigned h = lookupResult.second; + + if (found) + return std::make_pair(makeKnownGoodIterator(entry), false); + + if (isDeletedBucket(*entry)) { + initializeBucket(*entry); + --m_deletedCount; + } + + HashTranslator::translate(*entry, key, extra, h); + ++m_keyCount; + if (shouldExpand()) { + // FIXME: This makes an extra copy on expand. Probably not that bad since + // expand is rare, but would be better to have a version of expand that can + // follow a pivot entry and return the new position. + KeyType enteredKey = Extractor::extract(*entry); + expand(); + pair p = std::make_pair(find(enteredKey), true); + ASSERT(p.first != end()); + return p; + } + + internalCheckTableConsistency(); + + return std::make_pair(makeKnownGoodIterator(entry), true); + } + + template + inline void HashTable::reinsert(ValueType& entry) + { + ASSERT(m_table); + ASSERT(!lookupForWriting(Extractor::extract(entry)).second); + ASSERT(!isDeletedBucket(*(lookupForWriting(Extractor::extract(entry)).first))); +#if DUMP_HASHTABLE_STATS + atomicIncrement(&HashTableStats::numReinserts); +#endif + + Mover::move(entry, *lookupForWriting(Extractor::extract(entry)).first); + } + + template + template + typename HashTable::iterator HashTable::find(const T& key) + { + if (!m_table) + return end(); + + ValueType* entry = lookup(key); + if (!entry) + return end(); + + return makeKnownGoodIterator(entry); + } + + template + template + typename HashTable::const_iterator HashTable::find(const T& key) const + { + if (!m_table) + return end(); + + ValueType* entry = const_cast(this)->lookup(key); + if (!entry) + return end(); + + return makeKnownGoodConstIterator(entry); + } + + template + template + bool HashTable::contains(const T& key) const + { + if (!m_table) + return false; + + return const_cast(this)->lookup(key); + } + + template + void HashTable::removeAndInvalidateWithoutEntryConsistencyCheck(ValueType* pos) + { + invalidateIterators(); + remove(pos); + } + + template + void HashTable::removeAndInvalidate(ValueType* pos) + { + invalidateIterators(); + internalCheckTableConsistency(); + remove(pos); + } + + template + void HashTable::remove(ValueType* pos) + { +#if DUMP_HASHTABLE_STATS + atomicIncrement(&HashTableStats::numRemoves); +#endif + + deleteBucket(*pos); + ++m_deletedCount; + --m_keyCount; + + if (shouldShrink()) + shrink(); + + internalCheckTableConsistency(); + } + + template + inline void HashTable::remove(iterator it) + { + if (it == end()) + return; + + removeAndInvalidate(const_cast(it.m_iterator.m_position)); + } + + template + inline void HashTable::removeWithoutEntryConsistencyCheck(iterator it) + { + if (it == end()) + return; + + removeAndInvalidateWithoutEntryConsistencyCheck(const_cast(it.m_iterator.m_position)); + } + + template + inline void HashTable::removeWithoutEntryConsistencyCheck(const_iterator it) + { + if (it == end()) + return; + + removeAndInvalidateWithoutEntryConsistencyCheck(const_cast(it.m_position)); + } + + template + inline void HashTable::remove(const KeyType& key) + { + remove(find(key)); + } + + template + Value* HashTable::allocateTable(int size) + { + // would use a template member function with explicit specializations here, but + // gcc doesn't appear to support that + if (Traits::emptyValueIsZero) + return static_cast(fastZeroedMalloc(size * sizeof(ValueType))); + ValueType* result = static_cast(fastMalloc(size * sizeof(ValueType))); + for (int i = 0; i < size; i++) + initializeBucket(result[i]); + return result; + } + + template + void HashTable::deallocateTable(ValueType* table, int size) + { + if (Traits::needsDestruction) { + for (int i = 0; i < size; ++i) { + if (!isDeletedBucket(table[i])) + table[i].~ValueType(); + } + } + fastFree(table); + } + + template + void HashTable::expand() + { + int newSize; + if (m_tableSize == 0) + newSize = KeyTraits::minimumTableSize; + else if (mustRehashInPlace()) + newSize = m_tableSize; + else + newSize = m_tableSize * 2; + + rehash(newSize); + } + + template + void HashTable::rehash(int newTableSize) + { + internalCheckTableConsistencyExceptSize(); + + int oldTableSize = m_tableSize; + ValueType* oldTable = m_table; + +#if DUMP_HASHTABLE_STATS + if (oldTableSize != 0) + atomicIncrement(&HashTableStats::numRehashes); +#endif + + m_tableSize = newTableSize; + m_tableSizeMask = newTableSize - 1; + m_table = allocateTable(newTableSize); + + for (int i = 0; i != oldTableSize; ++i) + if (!isEmptyOrDeletedBucket(oldTable[i])) + reinsert(oldTable[i]); + + m_deletedCount = 0; + + deallocateTable(oldTable, oldTableSize); + + internalCheckTableConsistency(); + } + + template + void HashTable::clear() + { + invalidateIterators(); + deallocateTable(m_table, m_tableSize); + m_table = 0; + m_tableSize = 0; + m_tableSizeMask = 0; + m_keyCount = 0; + } + + template + HashTable::HashTable(const HashTable& other) + : m_table(0) + , m_tableSize(0) + , m_tableSizeMask(0) + , m_keyCount(0) + , m_deletedCount(0) +#if CHECK_HASHTABLE_ITERATORS + , m_iterators(0) +#endif + { + // Copy the hash table the dumb way, by adding each element to the new table. + // It might be more efficient to copy the table slots, but it's not clear that efficiency is needed. + const_iterator end = other.end(); + for (const_iterator it = other.begin(); it != end; ++it) + add(*it); + } + + template + void HashTable::swap(HashTable& other) + { + invalidateIterators(); + other.invalidateIterators(); + + ValueType* tmp_table = m_table; + m_table = other.m_table; + other.m_table = tmp_table; + + int tmp_tableSize = m_tableSize; + m_tableSize = other.m_tableSize; + other.m_tableSize = tmp_tableSize; + + int tmp_tableSizeMask = m_tableSizeMask; + m_tableSizeMask = other.m_tableSizeMask; + other.m_tableSizeMask = tmp_tableSizeMask; + + int tmp_keyCount = m_keyCount; + m_keyCount = other.m_keyCount; + other.m_keyCount = tmp_keyCount; + + int tmp_deletedCount = m_deletedCount; + m_deletedCount = other.m_deletedCount; + other.m_deletedCount = tmp_deletedCount; + } + + template + HashTable& HashTable::operator=(const HashTable& other) + { + HashTable tmp(other); + swap(tmp); + return *this; + } + +#if !ASSERT_DISABLED + + template + void HashTable::checkTableConsistency() const + { + checkTableConsistencyExceptSize(); + ASSERT(!m_table || !shouldExpand()); + ASSERT(!shouldShrink()); + } + + template + void HashTable::checkTableConsistencyExceptSize() const + { + if (!m_table) + return; + + int count = 0; + int deletedCount = 0; + for (int j = 0; j < m_tableSize; ++j) { + ValueType* entry = m_table + j; + if (isEmptyBucket(*entry)) + continue; + + if (isDeletedBucket(*entry)) { + ++deletedCount; + continue; + } + + const_iterator it = find(Extractor::extract(*entry)); + ASSERT(entry == it.m_position); + ++count; + + ValueCheck::checkConsistency(it->first); + } + + ASSERT(count == m_keyCount); + ASSERT(deletedCount == m_deletedCount); + ASSERT(m_tableSize >= KeyTraits::minimumTableSize); + ASSERT(m_tableSizeMask); + ASSERT(m_tableSize == m_tableSizeMask + 1); + } + +#endif // ASSERT_DISABLED + +#if CHECK_HASHTABLE_ITERATORS + + template + void HashTable::invalidateIterators() + { + MutexLocker lock(m_mutex); + const_iterator* next; + for (const_iterator* p = m_iterators; p; p = next) { + next = p->m_next; + p->m_table = 0; + p->m_next = 0; + p->m_previous = 0; + } + m_iterators = 0; + } + + template + void addIterator(const HashTable* table, + HashTableConstIterator* it) + { + it->m_table = table; + it->m_previous = 0; + + // Insert iterator at head of doubly-linked list of iterators. + if (!table) { + it->m_next = 0; + } else { + MutexLocker lock(table->m_mutex); + ASSERT(table->m_iterators != it); + it->m_next = table->m_iterators; + table->m_iterators = it; + if (it->m_next) { + ASSERT(!it->m_next->m_previous); + it->m_next->m_previous = it; + } + } + } + + template + void removeIterator(HashTableConstIterator* it) + { + typedef HashTable HashTableType; + typedef HashTableConstIterator const_iterator; + + // Delete iterator from doubly-linked list of iterators. + if (!it->m_table) { + ASSERT(!it->m_next); + ASSERT(!it->m_previous); + } else { + MutexLocker lock(it->m_table->m_mutex); + if (it->m_next) { + ASSERT(it->m_next->m_previous == it); + it->m_next->m_previous = it->m_previous; + } + if (it->m_previous) { + ASSERT(it->m_table->m_iterators != it); + ASSERT(it->m_previous->m_next == it); + it->m_previous->m_next = it->m_next; + } else { + ASSERT(it->m_table->m_iterators == it); + it->m_table->m_iterators = it->m_next; + } + } + + it->m_table = 0; + it->m_next = 0; + it->m_previous = 0; + } + +#endif // CHECK_HASHTABLE_ITERATORS + + // iterator adapters + + template struct HashTableConstIteratorAdapter { + HashTableConstIteratorAdapter() {} + HashTableConstIteratorAdapter(const typename HashTableType::const_iterator& impl) : m_impl(impl) {} + + const ValueType* get() const { return (const ValueType*)m_impl.get(); } + const ValueType& operator*() const { return *get(); } + const ValueType* operator->() const { return get(); } + + HashTableConstIteratorAdapter& operator++() { ++m_impl; return *this; } + // postfix ++ intentionally omitted + + typename HashTableType::const_iterator m_impl; + }; + + template struct HashTableIteratorAdapter { + HashTableIteratorAdapter() {} + HashTableIteratorAdapter(const typename HashTableType::iterator& impl) : m_impl(impl) {} + + ValueType* get() const { return (ValueType*)m_impl.get(); } + ValueType& operator*() const { return *get(); } + ValueType* operator->() const { return get(); } + + HashTableIteratorAdapter& operator++() { ++m_impl; return *this; } + // postfix ++ intentionally omitted + + operator HashTableConstIteratorAdapter() { + typename HashTableType::const_iterator i = m_impl; + return i; + } + + typename HashTableType::iterator m_impl; + }; + + template + inline bool operator==(const HashTableConstIteratorAdapter& a, const HashTableConstIteratorAdapter& b) + { + return a.m_impl == b.m_impl; + } + + template + inline bool operator!=(const HashTableConstIteratorAdapter& a, const HashTableConstIteratorAdapter& b) + { + return a.m_impl != b.m_impl; + } + + template + inline bool operator==(const HashTableIteratorAdapter& a, const HashTableIteratorAdapter& b) + { + return a.m_impl == b.m_impl; + } + + template + inline bool operator!=(const HashTableIteratorAdapter& a, const HashTableIteratorAdapter& b) + { + return a.m_impl != b.m_impl; + } + + // All 4 combinations of ==, != and Const,non const. + template + inline bool operator==(const HashTableConstIteratorAdapter& a, const HashTableIteratorAdapter& b) + { + return a.m_impl == b.m_impl; + } + + template + inline bool operator!=(const HashTableConstIteratorAdapter& a, const HashTableIteratorAdapter& b) + { + return a.m_impl != b.m_impl; + } + + template + inline bool operator==(const HashTableIteratorAdapter& a, const HashTableConstIteratorAdapter& b) + { + return a.m_impl == b.m_impl; + } + + template + inline bool operator!=(const HashTableIteratorAdapter& a, const HashTableConstIteratorAdapter& b) + { + return a.m_impl != b.m_impl; + } + +} // namespace WTF + +#include "HashIterators.h" + +#endif // WTF_HashTable_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HashTraits.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HashTraits.h new file mode 100644 index 000000000..12e6b0699 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HashTraits.h @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2005, 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WTF_HashTraits_h +#define WTF_HashTraits_h + +#include "HashFunctions.h" +#include "StdLibExtras.h" +#include "TypeTraits.h" +#include +#include + +namespace WTF { + + class String; + + template class OwnPtr; + template class PassOwnPtr; + + using std::pair; + using std::make_pair; + + template struct HashTraits; + + template struct GenericHashTraitsBase; + + template struct GenericHashTraitsBase { + static const bool emptyValueIsZero = false; + static const bool needsDestruction = true; + static const int minimumTableSize = 64; + }; + + // Default integer traits disallow both 0 and -1 as keys (max value instead of -1 for unsigned). + template struct GenericHashTraitsBase : GenericHashTraitsBase { + static const bool emptyValueIsZero = true; + static const bool needsDestruction = false; + static void constructDeletedValue(T& slot) { slot = static_cast(-1); } + static bool isDeletedValue(T value) { return value == static_cast(-1); } + }; + + template struct GenericHashTraits : GenericHashTraitsBase::value, T> { + typedef T TraitType; + + static T emptyValue() { return T(); } + + // Type for functions that take ownership, such as add. + // The store function either not be called or called once to store something passed in. + // The value passed to the store function will be either PassInType or PassInType&. + typedef const T& PassInType; + static void store(const T& value, T& storage) { storage = value; } + + // Type for return value of functions that transfer ownership, such as take. + typedef T PassOutType; + static PassOutType passOut(const T& value) { return value; } + + // Type for return value of functions that do not transfer ownership, such as get. + // FIXME: We could change this type to const T& for better performance if we figured out + // a way to handle the return value from emptyValue, which is a temporary. + typedef T PeekType; + static PeekType peek(const T& value) { return value; } + }; + + template struct HashTraits : GenericHashTraits { }; + + template struct FloatHashTraits : GenericHashTraits { + static const bool needsDestruction = false; + static T emptyValue() { return std::numeric_limits::infinity(); } + static void constructDeletedValue(T& slot) { slot = -std::numeric_limits::infinity(); } + static bool isDeletedValue(T value) { return value == -std::numeric_limits::infinity(); } + }; + + template<> struct HashTraits : FloatHashTraits { }; + template<> struct HashTraits : FloatHashTraits { }; + + // Default unsigned traits disallow both 0 and max as keys -- use these traits to allow zero and disallow max - 1. + template struct UnsignedWithZeroKeyHashTraits : GenericHashTraits { + static const bool emptyValueIsZero = false; + static const bool needsDestruction = false; + static T emptyValue() { return std::numeric_limits::max(); } + static void constructDeletedValue(T& slot) { slot = std::numeric_limits::max() - 1; } + static bool isDeletedValue(T value) { return value == std::numeric_limits::max() - 1; } + }; + + template struct HashTraits : GenericHashTraits { + static const bool emptyValueIsZero = true; + static const bool needsDestruction = false; + static void constructDeletedValue(P*& slot) { slot = reinterpret_cast(-1); } + static bool isDeletedValue(P* value) { return value == reinterpret_cast(-1); } + }; + + template struct SimpleClassHashTraits : GenericHashTraits { + static const bool emptyValueIsZero = true; + static void constructDeletedValue(T& slot) { new (NotNull, &slot) T(HashTableDeletedValue); } + static bool isDeletedValue(const T& value) { return value.isHashTableDeletedValue(); } + }; + + template struct HashTraits > : SimpleClassHashTraits > { + static std::nullptr_t emptyValue() { return nullptr; } + + typedef PassOwnPtr

PassInType; + static void store(PassOwnPtr

value, OwnPtr

& storage) { storage = value; } + + typedef PassOwnPtr

PassOutType; + static PassOwnPtr

passOut(OwnPtr

& value) { return value.release(); } + static PassOwnPtr

passOut(std::nullptr_t) { return nullptr; } + + typedef typename OwnPtr

::PtrType PeekType; + static PeekType peek(const OwnPtr

& value) { return value.get(); } + static PeekType peek(std::nullptr_t) { return 0; } + }; + + template struct HashTraits > : SimpleClassHashTraits > { + typedef PassRefPtr

PassInType; + static void store(PassRefPtr

value, RefPtr

& storage) { storage = value; } + + // FIXME: We should change PassOutType to PassRefPtr for better performance. + // FIXME: We should consider changing PeekType to a raw pointer for better performance, + // but then callers won't need to call get; doing so will require updating many call sites. + }; + + template<> struct HashTraits : SimpleClassHashTraits { }; + + // special traits for pairs, helpful for their use in HashMap implementation + + template + struct PairHashTraits : GenericHashTraits > { + typedef FirstTraitsArg FirstTraits; + typedef SecondTraitsArg SecondTraits; + typedef pair TraitType; + + static const bool emptyValueIsZero = FirstTraits::emptyValueIsZero && SecondTraits::emptyValueIsZero; + static TraitType emptyValue() { return make_pair(FirstTraits::emptyValue(), SecondTraits::emptyValue()); } + + static const bool needsDestruction = FirstTraits::needsDestruction || SecondTraits::needsDestruction; + + static const int minimumTableSize = FirstTraits::minimumTableSize; + + static void constructDeletedValue(TraitType& slot) { FirstTraits::constructDeletedValue(slot.first); } + static bool isDeletedValue(const TraitType& value) { return FirstTraits::isDeletedValue(value.first); } + }; + + template + struct HashTraits > : public PairHashTraits, HashTraits > { }; + +} // namespace WTF + +using WTF::HashTraits; +using WTF::PairHashTraits; + +#endif // WTF_HashTraits_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Heap.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Heap.h new file mode 100644 index 000000000..44a6f8638 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Heap.h @@ -0,0 +1,354 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2001 Peter Kelly (pmk@post.com) + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef Heap_h +#define Heap_h + +#include "AllocationSpace.h" +#include "DFGCodeBlocks.h" +#include "HandleHeap.h" +#include "HandleStack.h" +#include "MarkedBlock.h" +#include "MarkedBlockSet.h" +#include "MarkedSpace.h" +#include "SlotVisitor.h" +#include "WriteBarrierSupport.h" +#include +#include +#include +#include + +#define COLLECT_ON_EVERY_ALLOCATION 0 + +namespace JSC { + + class BumpSpace; + class CodeBlock; + class GCActivityCallback; + class GlobalCodeBlock; + class Heap; + class HeapRootVisitor; + class JSCell; + class JSGlobalData; + class JSValue; + class LiveObjectIterator; + class MarkedArgumentBuffer; + class RegisterFile; + class UString; + class WeakGCHandlePool; + class SlotVisitor; + + typedef std::pair ValueStringPair; + typedef HashCountedSet ProtectCountSet; + typedef HashCountedSet TypeCountSet; + + enum OperationInProgress { NoOperation, Allocation, Collection }; + + // Heap size hint. + enum HeapSize { SmallHeap, LargeHeap }; + + class Heap { + WTF_MAKE_NONCOPYABLE(Heap); + public: + friend class JIT; + friend class MarkStackThreadSharedData; + static Heap* heap(JSValue); // 0 for immediate values + static Heap* heap(JSCell*); + + static bool isMarked(const void*); + static bool testAndSetMarked(const void*); + static void setMarked(const void*); + + static void writeBarrier(const JSCell*, JSValue); + static void writeBarrier(const JSCell*, JSCell*); + static uint8_t* addressOfCardFor(JSCell*); + + Heap(JSGlobalData*, HeapSize); + ~Heap(); + JS_EXPORT_PRIVATE void destroy(); // JSGlobalData must call destroy() before ~Heap(). + + JSGlobalData* globalData() const { return m_globalData; } + AllocationSpace& objectSpace() { return m_objectSpace; } + MachineThreads& machineThreads() { return m_machineThreads; } + + JS_EXPORT_PRIVATE GCActivityCallback* activityCallback(); + JS_EXPORT_PRIVATE void setActivityCallback(PassOwnPtr); + + // true if an allocation or collection is in progress + inline bool isBusy(); + + MarkedSpace::SizeClass& sizeClassForObject(size_t bytes) { return m_objectSpace.sizeClassFor(bytes); } + void* allocate(size_t); + CheckedBoolean tryAllocateStorage(size_t, void**); + CheckedBoolean tryReallocateStorage(void**, size_t, size_t); + + typedef void (*Finalizer)(JSCell*); + JS_EXPORT_PRIVATE void addFinalizer(JSCell*, Finalizer); + + void notifyIsSafeToCollect() { m_isSafeToCollect = true; } + JS_EXPORT_PRIVATE void collectAllGarbage(); + + void reportExtraMemoryCost(size_t cost); + + JS_EXPORT_PRIVATE void protect(JSValue); + JS_EXPORT_PRIVATE bool unprotect(JSValue); // True when the protect count drops to 0. + + void jettisonDFGCodeBlock(PassOwnPtr); + + JS_EXPORT_PRIVATE size_t size(); + JS_EXPORT_PRIVATE size_t capacity(); + JS_EXPORT_PRIVATE size_t objectCount(); + JS_EXPORT_PRIVATE size_t globalObjectCount(); + JS_EXPORT_PRIVATE size_t protectedObjectCount(); + JS_EXPORT_PRIVATE size_t protectedGlobalObjectCount(); + JS_EXPORT_PRIVATE PassOwnPtr protectedObjectTypeCounts(); + JS_EXPORT_PRIVATE PassOwnPtr objectTypeCounts(); + + void pushTempSortVector(Vector*); + void popTempSortVector(Vector*); + + HashSet& markListSet() { if (!m_markListSet) m_markListSet = new HashSet; return *m_markListSet; } + + template typename Functor::ReturnType forEachProtectedCell(Functor&); + template typename Functor::ReturnType forEachProtectedCell(); + + HandleHeap* handleHeap() { return &m_handleHeap; } + HandleStack* handleStack() { return &m_handleStack; } + + void getConservativeRegisterRoots(HashSet& roots); + + private: + friend class MarkedBlock; + friend class AllocationSpace; + friend class BumpSpace; + friend class SlotVisitor; + friend class CodeBlock; + + size_t waterMark(); + size_t highWaterMark(); + void setHighWaterMark(size_t); + + static const size_t minExtraCost = 256; + static const size_t maxExtraCost = 1024 * 1024; + + class FinalizerOwner : public WeakHandleOwner { + virtual void finalize(Handle, void* context); + }; + + JS_EXPORT_PRIVATE bool isValidAllocation(size_t); + JS_EXPORT_PRIVATE void reportExtraMemoryCostSlowCase(size_t); + + // Call this function before any operation that needs to know which cells + // in the heap are live. (For example, call this function before + // conservative marking, eager sweeping, or iterating the cells in a MarkedBlock.) + void canonicalizeCellLivenessData(); + + void resetAllocator(); + void freeBlocks(MarkedBlock*); + + void clearMarks(); + void markRoots(bool fullGC); + void markProtectedObjects(HeapRootVisitor&); + void markTempSortVectors(HeapRootVisitor&); + void harvestWeakReferences(); + void finalizeUnconditionalFinalizers(); + + enum SweepToggle { DoNotSweep, DoSweep }; + void collect(SweepToggle); + void shrink(); + void releaseFreeBlocks(); + void sweep(); + + RegisterFile& registerFile(); + + void waitForRelativeTimeWhileHoldingLock(double relative); + void waitForRelativeTime(double relative); + void blockFreeingThreadMain(); + static void* blockFreeingThreadStartFunc(void* heap); + + const HeapSize m_heapSize; + const size_t m_minBytesPerCycle; + size_t m_lastFullGCSize; + size_t m_waterMark; + size_t m_highWaterMark; + + OperationInProgress m_operationInProgress; + AllocationSpace m_objectSpace; + BumpSpace m_storageSpace; + + DoublyLinkedList m_freeBlocks; + size_t m_numberOfFreeBlocks; + + ThreadIdentifier m_blockFreeingThread; + Mutex m_freeBlockLock; + ThreadCondition m_freeBlockCondition; + bool m_blockFreeingThreadShouldQuit; + +#if ENABLE(SIMPLE_HEAP_PROFILING) + VTableSpectrum m_destroyedTypeCounts; +#endif + + size_t m_extraCost; + + ProtectCountSet m_protectedValues; + Vector* > m_tempSortingVectors; + HashSet* m_markListSet; + + OwnPtr m_activityCallback; + + MachineThreads m_machineThreads; + + MarkStackThreadSharedData m_sharedData; + SlotVisitor m_slotVisitor; + + HandleHeap m_handleHeap; + HandleStack m_handleStack; + DFGCodeBlocks m_dfgCodeBlocks; + FinalizerOwner m_finalizerOwner; + + bool m_isSafeToCollect; + + JSGlobalData* m_globalData; + }; + + bool Heap::isBusy() + { + return m_operationInProgress != NoOperation; + } + + inline Heap* Heap::heap(JSCell* cell) + { + return MarkedBlock::blockFor(cell)->heap(); + } + + inline Heap* Heap::heap(JSValue v) + { + if (!v.isCell()) + return 0; + return heap(v.asCell()); + } + + inline bool Heap::isMarked(const void* cell) + { + return MarkedBlock::blockFor(cell)->isMarked(cell); + } + + inline bool Heap::testAndSetMarked(const void* cell) + { + return MarkedBlock::blockFor(cell)->testAndSetMarked(cell); + } + + inline void Heap::setMarked(const void* cell) + { + MarkedBlock::blockFor(cell)->setMarked(cell); + } + + inline size_t Heap::waterMark() + { + return m_objectSpace.waterMark() + m_storageSpace.totalMemoryUtilized(); + } + + inline size_t Heap::highWaterMark() + { + return m_highWaterMark; + } + + inline void Heap::setHighWaterMark(size_t newHighWaterMark) + { + m_highWaterMark = newHighWaterMark; + } + +#if ENABLE(GGC) + inline uint8_t* Heap::addressOfCardFor(JSCell* cell) + { + return MarkedBlock::blockFor(cell)->addressOfCardFor(cell); + } + + inline void Heap::writeBarrier(const JSCell* owner, JSCell*) + { + WriteBarrierCounters::countWriteBarrier(); + MarkedBlock* block = MarkedBlock::blockFor(owner); + if (block->isMarked(owner)) + block->setDirtyObject(owner); + } + + inline void Heap::writeBarrier(const JSCell* owner, JSValue value) + { + if (!value) + return; + if (!value.isCell()) + return; + writeBarrier(owner, value.asCell()); + } +#else + + inline void Heap::writeBarrier(const JSCell*, JSCell*) + { + WriteBarrierCounters::countWriteBarrier(); + } + + inline void Heap::writeBarrier(const JSCell*, JSValue) + { + WriteBarrierCounters::countWriteBarrier(); + } +#endif + + inline void Heap::reportExtraMemoryCost(size_t cost) + { + if (cost > minExtraCost) + reportExtraMemoryCostSlowCase(cost); + } + + template inline typename Functor::ReturnType Heap::forEachProtectedCell(Functor& functor) + { + ProtectCountSet::iterator end = m_protectedValues.end(); + for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it) + functor(it->first); + m_handleHeap.forEachStrongHandle(functor, m_protectedValues); + + return functor.returnValue(); + } + + template inline typename Functor::ReturnType Heap::forEachProtectedCell() + { + Functor functor; + return forEachProtectedCell(functor); + } + + inline void* Heap::allocate(size_t bytes) + { + ASSERT(isValidAllocation(bytes)); + return m_objectSpace.allocate(bytes); + } + + inline CheckedBoolean Heap::tryAllocateStorage(size_t bytes, void** outPtr) + { + return m_storageSpace.tryAllocate(bytes, outPtr); + } + + inline CheckedBoolean Heap::tryReallocateStorage(void** ptr, size_t oldSize, size_t newSize) + { + return m_storageSpace.tryReallocate(ptr, oldSize, newSize); + } + +} // namespace JSC + +#endif // Heap_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HeapBlock.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HeapBlock.h new file mode 100644 index 000000000..1d66aade9 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HeapBlock.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2011 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 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 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 HeapBlock_h +#define HeapBlock_h + +#include +#include + +namespace JSC { + +class HeapBlock : public DoublyLinkedListNode { +public: + HeapBlock(PageAllocationAligned& allocation) + : DoublyLinkedListNode() + , m_prev(0) + , m_next(0) + , m_allocation(allocation) + { + ASSERT(allocation); + } + + HeapBlock* m_prev; + HeapBlock* m_next; + PageAllocationAligned m_allocation; +}; + +} // namespace JSC + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HeapRootVisitor.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HeapRootVisitor.h new file mode 100644 index 000000000..76c97290a --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HeapRootVisitor.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2009, 2011 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 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 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 HeapRootVisitor_h +#define HeapRootVisitor_h + +#include "SlotVisitor.h" + +namespace JSC { + + // Privileged class for marking JSValues directly. It is only safe to use + // this class to mark direct heap roots that are marked during every GC pass. + // All other references should be wrapped in WriteBarriers. + class HeapRootVisitor { + private: + friend class Heap; + HeapRootVisitor(SlotVisitor&); + + public: + void visit(JSValue*); + void visit(JSValue*, size_t); + void visit(JSString**); + void visit(JSCell**); + + SlotVisitor& visitor(); + + private: + SlotVisitor& m_visitor; + }; + + inline HeapRootVisitor::HeapRootVisitor(SlotVisitor& visitor) + : m_visitor(visitor) + { + } + + inline void HeapRootVisitor::visit(JSValue* slot) + { + m_visitor.append(slot); + } + + inline void HeapRootVisitor::visit(JSValue* slot, size_t count) + { + m_visitor.append(slot, count); + } + + inline void HeapRootVisitor::visit(JSString** slot) + { + m_visitor.append(reinterpret_cast(slot)); + } + + inline void HeapRootVisitor::visit(JSCell** slot) + { + m_visitor.append(slot); + } + + inline SlotVisitor& HeapRootVisitor::visitor() + { + return m_visitor; + } + +} // namespace JSC + +#endif // HeapRootVisitor_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HexNumber.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HexNumber.h new file mode 100644 index 000000000..8fd60323b --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/HexNumber.h @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2011 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef HexNumber_h +#define HexNumber_h + +#include + +namespace WTF { + +enum HexConversionMode { + Lowercase, + Uppercase +}; + +namespace Internal { + +static const char* hexDigitsForMode(HexConversionMode mode) +{ + static const char lowerHexDigits[17] = "0123456789abcdef"; + static const char upperHexDigits[17] = "0123456789ABCDEF"; + return mode == Lowercase ? lowerHexDigits : upperHexDigits; +} + +}; // namespace Internal + +template +inline void appendByteAsHex(unsigned char byte, T& destination, HexConversionMode mode = Uppercase) +{ + const char* hexDigits = Internal::hexDigitsForMode(mode); + destination.append(hexDigits[byte >> 4]); + destination.append(hexDigits[byte & 0xF]); +} + +template +inline void placeByteAsHexCompressIfPossible(unsigned char byte, T& destination, unsigned& index, HexConversionMode mode = Uppercase) +{ + const char* hexDigits = Internal::hexDigitsForMode(mode); + if (byte >= 0x10) + destination[index++] = hexDigits[byte >> 4]; + destination[index++] = hexDigits[byte & 0xF]; +} + +template +inline void placeByteAsHex(unsigned char byte, T& destination, HexConversionMode mode = Uppercase) +{ + const char* hexDigits = Internal::hexDigitsForMode(mode); + *destination++ = hexDigits[byte >> 4]; + *destination++ = hexDigits[byte & 0xF]; +} + +template +inline void appendUnsignedAsHex(unsigned number, T& destination, HexConversionMode mode = Uppercase) +{ + const char* hexDigits = Internal::hexDigitsForMode(mode); + Vector result; + do { + result.prepend(hexDigits[number % 16]); + number >>= 4; + } while (number > 0); + + destination.append(result.data(), result.size()); +} + +// Same as appendUnsignedAsHex, but using exactly 'desiredDigits' for the conversion. +template +inline void appendUnsignedAsHexFixedSize(unsigned number, T& destination, unsigned desiredDigits, HexConversionMode mode = Uppercase) +{ + ASSERT(desiredDigits); + + const char* hexDigits = Internal::hexDigitsForMode(mode); + Vector result; + do { + result.prepend(hexDigits[number % 16]); + number >>= 4; + } while (result.size() < desiredDigits); + + ASSERT(result.size() == desiredDigits); + destination.append(result.data(), result.size()); +} + +} // namespace WTF + +using WTF::appendByteAsHex; +using WTF::appendUnsignedAsHex; +using WTF::appendUnsignedAsHexFixedSize; +using WTF::placeByteAsHex; +using WTF::placeByteAsHexCompressIfPossible; +using WTF::Lowercase; + +#endif // HexNumber_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Identifier.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Identifier.h new file mode 100644 index 000000000..947c95b33 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Identifier.h @@ -0,0 +1,258 @@ +/* + * Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef Identifier_h +#define Identifier_h + +#include "JSGlobalData.h" +#include "ThreadSpecific.h" +#include "UString.h" +#include +#include + +namespace JSC { + + class ExecState; + + class Identifier { + friend class Structure; + public: + Identifier() { } + + Identifier(ExecState* exec, const char* s) : m_string(add(exec, s)) { } // Only to be used with string literals. + Identifier(ExecState* exec, StringImpl* rep) : m_string(add(exec, rep)) { } + Identifier(ExecState* exec, const UString& s) : m_string(add(exec, s.impl())) { } + + Identifier(JSGlobalData* globalData, const char* s) : m_string(add(globalData, s)) { } // Only to be used with string literals. + Identifier(JSGlobalData* globalData, const LChar* s, int length) : m_string(add(globalData, s, length)) { } + Identifier(JSGlobalData* globalData, const UChar* s, int length) : m_string(add(globalData, s, length)) { } + Identifier(JSGlobalData* globalData, StringImpl* rep) : m_string(add(globalData, rep)) { } + Identifier(JSGlobalData* globalData, const UString& s) : m_string(add(globalData, s.impl())) { } + + const UString& ustring() const { return m_string; } + StringImpl* impl() const { return m_string.impl(); } + + const UChar* characters() const { return m_string.characters(); } + int length() const { return m_string.length(); } + + CString ascii() const { return m_string.ascii(); } + + static Identifier createLCharFromUChar(JSGlobalData* globalData, const UChar* s, int length) { return Identifier(globalData, add8(globalData, s, length)); } + + JS_EXPORT_PRIVATE static Identifier from(ExecState* exec, unsigned y); + JS_EXPORT_PRIVATE static Identifier from(ExecState* exec, int y); + static Identifier from(ExecState* exec, double y); + static Identifier from(JSGlobalData*, unsigned y); + static Identifier from(JSGlobalData*, int y); + static Identifier from(JSGlobalData*, double y); + + JS_EXPORT_PRIVATE static uint32_t toUInt32(const UString&, bool& ok); + uint32_t toUInt32(bool& ok) const { return toUInt32(m_string, ok); } + unsigned toArrayIndex(bool& ok) const; + + bool isNull() const { return m_string.isNull(); } + bool isEmpty() const { return m_string.isEmpty(); } + + friend bool operator==(const Identifier&, const Identifier&); + friend bool operator!=(const Identifier&, const Identifier&); + + friend bool operator==(const Identifier&, const LChar*); + friend bool operator==(const Identifier&, const char*); + friend bool operator!=(const Identifier&, const LChar*); + friend bool operator!=(const Identifier&, const char*); + + static bool equal(const StringImpl*, const LChar*); + static inline bool equal(const StringImpl*a, const char*b) { return Identifier::equal(a, reinterpret_cast(b)); }; + static bool equal(const StringImpl*, const LChar*, unsigned length); + static bool equal(const StringImpl*, const UChar*, unsigned length); + static bool equal(const StringImpl* a, const StringImpl* b) { return ::equal(a, b); } + + JS_EXPORT_PRIVATE static PassRefPtr add(ExecState*, const char*); // Only to be used with string literals. + static PassRefPtr add(JSGlobalData*, const char*); // Only to be used with string literals. + + private: + UString m_string; + + template + ALWAYS_INLINE static uint32_t toUInt32FromCharacters(const CharType* characters, unsigned length, bool& ok); + + static bool equal(const Identifier& a, const Identifier& b) { return a.m_string.impl() == b.m_string.impl(); } + static bool equal(const Identifier& a, const LChar* b) { return equal(a.m_string.impl(), b); } + + template static PassRefPtr add(JSGlobalData*, const T*, int length); + static PassRefPtr add8(JSGlobalData*, const UChar*, int length); + template ALWAYS_INLINE static bool canUseSingleCharacterString(T); + + static PassRefPtr add(ExecState* exec, StringImpl* r) + { +#ifndef NDEBUG + checkCurrentIdentifierTable(exec); +#endif + if (r->isIdentifier()) + return r; + return addSlowCase(exec, r); + } + static PassRefPtr add(JSGlobalData* globalData, StringImpl* r) + { +#ifndef NDEBUG + checkCurrentIdentifierTable(globalData); +#endif + if (r->isIdentifier()) + return r; + return addSlowCase(globalData, r); + } + + JS_EXPORT_PRIVATE static PassRefPtr addSlowCase(ExecState*, StringImpl* r); + JS_EXPORT_PRIVATE static PassRefPtr addSlowCase(JSGlobalData*, StringImpl* r); + + JS_EXPORT_PRIVATE static void checkCurrentIdentifierTable(ExecState*); + JS_EXPORT_PRIVATE static void checkCurrentIdentifierTable(JSGlobalData*); + }; + + template <> ALWAYS_INLINE bool Identifier::canUseSingleCharacterString(LChar) + { + ASSERT(maxSingleCharacterString == 0xff); + return true; + } + + template <> ALWAYS_INLINE bool Identifier::canUseSingleCharacterString(UChar c) + { + return (c <= maxSingleCharacterString); + } + + template + struct CharBuffer { + const T* s; + unsigned int length; + }; + + template + struct IdentifierCharBufferTranslator { + static unsigned hash(const CharBuffer& buf) + { + return StringHasher::computeHash(buf.s, buf.length); + } + + static bool equal(StringImpl* str, const CharBuffer& buf) + { + return Identifier::equal(str, buf.s, buf.length); + } + + static void translate(StringImpl*& location, const CharBuffer& buf, unsigned hash) + { + T* d; + StringImpl* r = StringImpl::createUninitialized(buf.length, d).leakRef(); + for (unsigned i = 0; i != buf.length; i++) + d[i] = buf.s[i]; + r->setHash(hash); + location = r; + } + }; + + template + PassRefPtr Identifier::add(JSGlobalData* globalData, const T* s, int length) + { + if (length == 1) { + T c = s[0]; + if (canUseSingleCharacterString(c)) + return add(globalData, globalData->smallStrings.singleCharacterStringRep(c)); + } + + if (!length) + return StringImpl::empty(); + CharBuffer buf = {s, length}; + pair::iterator, bool> addResult = globalData->identifierTable->add, IdentifierCharBufferTranslator >(buf); + + // If the string is newly-translated, then we need to adopt it. + // The boolean in the pair tells us if that is so. + return addResult.second ? adoptRef(*addResult.first) : *addResult.first; + } + + inline bool operator==(const Identifier& a, const Identifier& b) + { + return Identifier::equal(a, b); + } + + inline bool operator!=(const Identifier& a, const Identifier& b) + { + return !Identifier::equal(a, b); + } + + inline bool operator==(const Identifier& a, const LChar* b) + { + return Identifier::equal(a, b); + } + + inline bool operator==(const Identifier& a, const char* b) + { + return Identifier::equal(a, reinterpret_cast(b)); + } + + inline bool operator!=(const Identifier& a, const LChar* b) + { + return !Identifier::equal(a, b); + } + + inline bool operator!=(const Identifier& a, const char* b) + { + return !Identifier::equal(a, reinterpret_cast(b)); + } + + inline bool Identifier::equal(const StringImpl* r, const LChar* s) + { + return WTF::equal(r, s); + } + + inline bool Identifier::equal(const StringImpl* r, const LChar* s, unsigned length) + { + return WTF::equal(r, s, length); + } + + inline bool Identifier::equal(const StringImpl* r, const UChar* s, unsigned length) + { + return WTF::equal(r, s, length); + } + + IdentifierTable* createIdentifierTable(); + void deleteIdentifierTable(IdentifierTable*); + + struct IdentifierRepHash : PtrHash > { + static unsigned hash(const RefPtr& key) { return key->existingHash(); } + static unsigned hash(StringImpl* key) { return key->existingHash(); } + }; + + struct IdentifierMapIndexHashTraits : HashTraits { + static int emptyValue() { return std::numeric_limits::max(); } + static const bool emptyValueIsZero = false; + }; + + typedef HashMap, int, IdentifierRepHash, HashTraits >, IdentifierMapIndexHashTraits> IdentifierMap; + + template + std::pair::iterator, bool> IdentifierTable::add(U value) + { + std::pair::iterator, bool> result = m_table.add(value); + (*result.first)->setIsIdentifier(true); + return result; + } + +} // namespace JSC + +#endif // Identifier_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/InitializeThreading.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/InitializeThreading.h new file mode 100644 index 000000000..91301a0d8 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/InitializeThreading.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 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. + * 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 InitializeThreading_h +#define InitializeThreading_h + +namespace JSC { + + // 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. + JS_EXPORT_PRIVATE void initializeThreading(); + +} + +#endif // InitializeThreading_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Int16Array.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Int16Array.h new file mode 100644 index 000000000..34a52de90 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Int16Array.h @@ -0,0 +1,93 @@ +/* + * 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 Int16Array_h +#define Int16Array_h + +#include "IntegralTypedArrayBase.h" + +namespace WTF { + +class ArrayBuffer; + +class Int16Array : public IntegralTypedArrayBase { +public: + static inline PassRefPtr create(unsigned length); + static inline PassRefPtr create(short* array, unsigned length); + static inline PassRefPtr create(PassRefPtr, unsigned byteOffset, unsigned length); + + // Can’t use "using" here due to a bug in the RVCT compiler. + bool set(TypedArrayBase* array, unsigned offset) { return TypedArrayBase::set(array, offset); } + void set(unsigned index, double value) { IntegralTypedArrayBase::set(index, value); } + + inline PassRefPtr subarray(int start) const; + inline PassRefPtr subarray(int start, int end) const; + +private: + inline Int16Array(PassRefPtr, + unsigned byteOffset, + unsigned length); + // Make constructor visible to superclass. + friend class TypedArrayBase; + + // Overridden from ArrayBufferView. + virtual bool isShortArray() const { return true; } +}; + +PassRefPtr Int16Array::create(unsigned length) +{ + return TypedArrayBase::create(length); +} + +PassRefPtr Int16Array::create(short* array, unsigned length) +{ + return TypedArrayBase::create(array, length); +} + +PassRefPtr Int16Array::create(PassRefPtr buffer, unsigned byteOffset, unsigned length) +{ + return TypedArrayBase::create(buffer, byteOffset, length); +} + +Int16Array::Int16Array(PassRefPtr buffer, unsigned byteOffset, unsigned length) + : IntegralTypedArrayBase(buffer, byteOffset, length) +{ +} + +PassRefPtr Int16Array::subarray(int start) const +{ + return subarray(start, length()); +} + +PassRefPtr Int16Array::subarray(int start, int end) const +{ + return subarrayImpl(start, end); +} + +} // namespace WTF + +using WTF::Int16Array; + +#endif // Int16Array_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Int32Array.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Int32Array.h new file mode 100644 index 000000000..0b61457b3 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Int32Array.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * 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: + * 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 Int32Array_h +#define Int32Array_h + +#include "IntegralTypedArrayBase.h" + +namespace WTF { + +class Int32Array : public IntegralTypedArrayBase { +public: + static inline PassRefPtr create(unsigned length); + static inline PassRefPtr create(int* array, unsigned length); + static inline PassRefPtr create(PassRefPtr, unsigned byteOffset, unsigned length); + + // Can’t use "using" here due to a bug in the RVCT compiler. + bool set(TypedArrayBase* array, unsigned offset) { return TypedArrayBase::set(array, offset); } + void set(unsigned index, double value) { IntegralTypedArrayBase::set(index, value); } + + inline PassRefPtr subarray(int start) const; + inline PassRefPtr subarray(int start, int end) const; + +private: + inline Int32Array(PassRefPtr, + unsigned byteOffset, + unsigned length); + // Make constructor visible to superclass. + friend class TypedArrayBase; + + // Overridden from ArrayBufferView. + virtual bool isIntArray() const { return true; } +}; + +PassRefPtr Int32Array::create(unsigned length) +{ + return TypedArrayBase::create(length); +} + +PassRefPtr Int32Array::create(int* array, unsigned length) +{ + return TypedArrayBase::create(array, length); +} + +PassRefPtr Int32Array::create(PassRefPtr buffer, unsigned byteOffset, unsigned length) +{ + return TypedArrayBase::create(buffer, byteOffset, length); +} + +Int32Array::Int32Array(PassRefPtr buffer, unsigned byteOffset, unsigned length) + : IntegralTypedArrayBase(buffer, byteOffset, length) +{ +} + +PassRefPtr Int32Array::subarray(int start) const +{ + return subarray(start, length()); +} + +PassRefPtr Int32Array::subarray(int start, int end) const +{ + return subarrayImpl(start, end); +} + +} // namespace WTF + +using WTF::Int32Array; + +#endif // Int32Array_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Int8Array.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Int8Array.h new file mode 100644 index 000000000..6db7b6899 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Int8Array.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * 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: + * 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 Int8Array_h +#define Int8Array_h + +#include "IntegralTypedArrayBase.h" + +namespace WTF { + +class ArrayBuffer; + +class Int8Array : public IntegralTypedArrayBase { +public: + static inline PassRefPtr create(unsigned length); + static inline PassRefPtr create(signed char* array, unsigned length); + static inline PassRefPtr create(PassRefPtr, unsigned byteOffset, unsigned length); + + // Can’t use "using" here due to a bug in the RVCT compiler. + bool set(TypedArrayBase* array, unsigned offset) { return TypedArrayBase::set(array, offset); } + void set(unsigned index, double value) { IntegralTypedArrayBase::set(index, value); } + + inline PassRefPtr subarray(int start) const; + inline PassRefPtr subarray(int start, int end) const; + +private: + inline Int8Array(PassRefPtr, + unsigned byteOffset, + unsigned length); + // Make constructor visible to superclass. + friend class TypedArrayBase; + + // Overridden from ArrayBufferView. + virtual bool isByteArray() const { return true; } +}; + +PassRefPtr Int8Array::create(unsigned length) +{ + return TypedArrayBase::create(length); +} + +PassRefPtr Int8Array::create(signed char* array, unsigned length) +{ + return TypedArrayBase::create(array, length); +} + +PassRefPtr Int8Array::create(PassRefPtr buffer, unsigned byteOffset, unsigned length) +{ + return TypedArrayBase::create(buffer, byteOffset, length); +} + +Int8Array::Int8Array(PassRefPtr buffer, unsigned byteOffset, unsigned length) + : IntegralTypedArrayBase(buffer, byteOffset, length) +{ +} + +PassRefPtr Int8Array::subarray(int start) const +{ + return subarray(start, length()); +} + +PassRefPtr Int8Array::subarray(int start, int end) const +{ + return subarrayImpl(start, end); +} + +} // namespace WTF + +using WTF::Int8Array; + +#endif // Int8Array_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/IntegralTypedArrayBase.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/IntegralTypedArrayBase.h new file mode 100644 index 000000000..48f82a361 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/IntegralTypedArrayBase.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * 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: + * 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 IntegralTypedArrayBase_h +#define IntegralTypedArrayBase_h + +#include "TypedArrayBase.h" +#include +#include + +// Base class for all WebGLArray types holding integral +// (non-floating-point) values. + +namespace WTF { + +template +class IntegralTypedArrayBase : public TypedArrayBase { + public: + void set(unsigned index, double value) + { + if (index >= TypedArrayBase::m_length) + return; + if (isnan(value)) // Clamp NaN to 0 + value = 0; + // The double cast is necessary to get the correct wrapping + // for out-of-range values with Int32Array and Uint32Array. + TypedArrayBase::data()[index] = static_cast(static_cast(value)); + } + + // Invoked by the indexed getter. Does not perform range checks; caller + // is responsible for doing so and returning undefined as necessary. + T item(unsigned index) const + { + ASSERT(index < TypedArrayBase::m_length); + return TypedArrayBase::data()[index]; + } + + protected: + IntegralTypedArrayBase(PassRefPtr buffer, unsigned byteOffset, unsigned length) + : TypedArrayBase(buffer, byteOffset, length) + { + } +}; + +} // namespace WTF + +using WTF::IntegralTypedArrayBase; + +#endif // IntegralTypedArrayBase_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/InternalFunction.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/InternalFunction.h new file mode 100644 index 000000000..532bd0c8d --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/InternalFunction.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) + * Copyright (C) 2007 Maks Orlovich + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef InternalFunction_h +#define InternalFunction_h + +#include "JSObject.h" +#include "Identifier.h" + +namespace JSC { + + class FunctionPrototype; + + class InternalFunction : public JSNonFinalObject { + public: + typedef JSNonFinalObject Base; + + static JS_EXPORTDATA const ClassInfo s_info; + + JS_EXPORT_PRIVATE const UString& name(ExecState*); + const UString displayName(ExecState*); + const UString calculatedDisplayName(ExecState*); + + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) + { + return Structure::create(globalData, globalObject, proto, TypeInfo(ObjectType, StructureFlags), &s_info); + } + + protected: + static const unsigned StructureFlags = ImplementsHasInstance | JSObject::StructureFlags; + + JS_EXPORT_PRIVATE InternalFunction(JSGlobalObject*, Structure*); + + JS_EXPORT_PRIVATE void finishCreation(JSGlobalData&, const Identifier& name); + + static CallType getCallData(JSCell*, CallData&); + }; + + InternalFunction* asInternalFunction(JSValue); + + inline InternalFunction* asInternalFunction(JSValue value) + { + ASSERT(asObject(value)->inherits(&InternalFunction::s_info)); + return static_cast(asObject(value)); + } + +} // namespace JSC + +#endif // InternalFunction_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Interpreter.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Interpreter.h new file mode 100644 index 000000000..6d1a4a9a5 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Interpreter.h @@ -0,0 +1,286 @@ +/* + * Copyright (C) 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. + * 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 Interpreter_h +#define Interpreter_h + +#include "ArgList.h" +#include "JSCell.h" +#include "JSFunction.h" +#include "JSValue.h" +#include "JSObject.h" +#include "Opcode.h" +#include "RegisterFile.h" +#include "StrongInlines.h" + +#include + +namespace JSC { + + class CodeBlock; + class EvalExecutable; + class ExecutableBase; + class FunctionExecutable; + class JSGlobalObject; + class ProgramExecutable; + class Register; + class ScopeChainNode; + class SamplingTool; + struct CallFrameClosure; + struct HandlerInfo; + struct Instruction; + + enum DebugHookID { + WillExecuteProgram, + DidExecuteProgram, + DidEnterCallFrame, + DidReachBreakpoint, + WillLeaveCallFrame, + WillExecuteStatement + }; + + enum StackFrameCodeType { + StackFrameGlobalCode, + StackFrameEvalCode, + StackFrameFunctionCode, + StackFrameNativeCode + }; + + struct StackFrame { + Strong callee; + Strong callFrame; + StackFrameCodeType codeType; + Strong executable; + int line; + UString sourceURL; + UString toString() const + { + bool hasSourceURLInfo = sourceURL != NULL && !sourceURL.isNull() && !sourceURL.isEmpty(); + bool hasLineInfo = line > -1; + String traceLine; + String sourceInfo; + JSObject* stackFrameCallee = callee.get(); + UString functionName = ""; + + if (hasSourceURLInfo) + sourceInfo = hasLineInfo ? String::format("%s:%d", sourceURL.ascii().data(), line) + : String::format("%s", sourceURL.ascii().data()); + + if (stackFrameCallee && stackFrameCallee->inherits(&JSFunction::s_info)) + functionName = asFunction(stackFrameCallee)->name(callFrame.get()); + + switch (codeType) { + case StackFrameEvalCode: + if (hasSourceURLInfo && !functionName.isEmpty()) + traceLine = String::format("at eval at %s (%s)", functionName.ascii().data(), sourceInfo.ascii().data()); + else if (hasSourceURLInfo) + traceLine = String::format("at eval at (%s)", sourceInfo.ascii().data()); + else if (!functionName.isEmpty()) + traceLine = String::format("at eval at %s", functionName.ascii().data()); + else + traceLine = String::format("at eval"); + break; + case StackFrameNativeCode: + if (!functionName.isEmpty()) + traceLine = String::format("at %s (native)", functionName.ascii().data()); + else + traceLine = "at (native)"; + break; + case StackFrameFunctionCode: + case StackFrameGlobalCode: + if (hasSourceURLInfo && !functionName.isEmpty()) + traceLine = String::format("at %s (%s)", functionName.ascii().data(), sourceInfo.ascii().data()); + else if (hasSourceURLInfo) + traceLine = String::format("at %s", sourceInfo.ascii().data()); + else if (!functionName.isEmpty()) + traceLine = String::format("at %s", functionName.ascii().data()); + else + traceLine = String::format("at unknown source"); + break; + } + return traceLine.impl(); + } + }; + + class TopCallFrameSetter { + public: + TopCallFrameSetter(JSGlobalData& global, CallFrame* callFrame) + : globalData(global) + , oldCallFrame(global.topCallFrame) + { + global.topCallFrame = callFrame; + } + + ~TopCallFrameSetter() + { + globalData.topCallFrame = oldCallFrame; + } + private: + JSGlobalData& globalData; + CallFrame* oldCallFrame; + }; + +#if PLATFORM(IOS) + // We use a smaller reentrancy limit on iPhone because of the high amount of + // stack space required on the web thread. + enum { MaxLargeThreadReentryDepth = 93, MaxSmallThreadReentryDepth = 16 }; +#else + enum { MaxLargeThreadReentryDepth = 256, MaxSmallThreadReentryDepth = 16 }; +#endif // PLATFORM(IOS) + + class Interpreter { + WTF_MAKE_FAST_ALLOCATED; + friend class JIT; + friend class CachedCall; + public: + Interpreter(); + + void initialize(bool canUseJIT); + + RegisterFile& registerFile() { return m_registerFile; } + + Opcode getOpcode(OpcodeID id) + { + ASSERT(m_initialized); +#if ENABLE(COMPUTED_GOTO_INTERPRETER) + return m_opcodeTable[id]; +#else + return id; +#endif + } + + OpcodeID getOpcodeID(Opcode opcode) + { + ASSERT(m_initialized); +#if ENABLE(COMPUTED_GOTO_INTERPRETER) + ASSERT(isOpcode(opcode)); + if (!m_enabled) + return static_cast(bitwise_cast(opcode)); + + return m_opcodeIDTable.get(opcode); +#else + return opcode; +#endif + } + + bool isOpcode(Opcode); + + JSValue execute(ProgramExecutable*, CallFrame*, ScopeChainNode*, JSObject* thisObj); + JSValue executeCall(CallFrame*, JSObject* function, CallType, const CallData&, JSValue thisValue, const ArgList&); + JSObject* executeConstruct(CallFrame*, JSObject* function, ConstructType, const ConstructData&, const ArgList&); + JSValue execute(EvalExecutable*, CallFrame*, JSValue thisValue, ScopeChainNode*); + JSValue execute(EvalExecutable*, CallFrame*, JSValue thisValue, ScopeChainNode*, int globalRegisterOffset); + + JSValue retrieveArguments(CallFrame*, JSFunction*) const; + JS_EXPORT_PRIVATE JSValue retrieveCaller(CallFrame*, JSFunction*) const; + JS_EXPORT_PRIVATE void retrieveLastCaller(CallFrame*, int& lineNumber, intptr_t& sourceID, UString& sourceURL, JSValue& function) const; + + void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc); + + SamplingTool* sampler() { return m_sampler.get(); } + + NEVER_INLINE HandlerInfo* throwException(CallFrame*&, JSValue&, unsigned bytecodeOffset); + NEVER_INLINE void debug(CallFrame*, DebugHookID, int firstLine, int lastLine); + static const UString getTraceLine(CallFrame*, StackFrameCodeType, const UString&, int); + static void getStackTrace(JSGlobalData*, int line, Vector& results); + + void dumpSampleData(ExecState* exec); + void startSampling(); + void stopSampling(); + private: + enum ExecutionFlag { Normal, InitializeAndReturn }; + + CallFrameClosure prepareForRepeatCall(FunctionExecutable*, CallFrame*, JSFunction*, int argumentCountIncludingThis, ScopeChainNode*); + void endRepeatCall(CallFrameClosure&); + JSValue execute(CallFrameClosure&); + +#if ENABLE(INTERPRETER) + NEVER_INLINE bool resolve(CallFrame*, Instruction*, JSValue& exceptionValue); + NEVER_INLINE bool resolveSkip(CallFrame*, Instruction*, JSValue& exceptionValue); + NEVER_INLINE bool resolveGlobal(CallFrame*, Instruction*, JSValue& exceptionValue); + NEVER_INLINE bool resolveGlobalDynamic(CallFrame*, Instruction*, JSValue& exceptionValue); + NEVER_INLINE void resolveBase(CallFrame*, Instruction* vPC); + NEVER_INLINE bool resolveBaseAndProperty(CallFrame*, Instruction*, JSValue& exceptionValue); + NEVER_INLINE bool resolveThisAndProperty(CallFrame*, Instruction*, JSValue& exceptionValue); + NEVER_INLINE ScopeChainNode* createExceptionScope(CallFrame*, const Instruction* vPC); + + void tryCacheGetByID(CallFrame*, CodeBlock*, Instruction*, JSValue baseValue, const Identifier& propertyName, const PropertySlot&); + void uncacheGetByID(CodeBlock*, Instruction* vPC); + void tryCachePutByID(CallFrame*, CodeBlock*, Instruction*, JSValue baseValue, const PutPropertySlot&); + void uncachePutByID(CodeBlock*, Instruction* vPC); +#endif // ENABLE(INTERPRETER) + + NEVER_INLINE bool unwindCallFrame(CallFrame*&, JSValue, unsigned& bytecodeOffset, CodeBlock*&); + + static ALWAYS_INLINE CallFrame* slideRegisterWindowForCall(CodeBlock*, RegisterFile*, CallFrame*, size_t registerOffset, int argc); + + static CallFrame* findFunctionCallFrame(CallFrame*, JSFunction*); + + JSValue privateExecute(ExecutionFlag, RegisterFile*, CallFrame*); + + void dumpCallFrame(CallFrame*); + void dumpRegisters(CallFrame*); + + bool isCallBytecode(Opcode opcode) { return opcode == getOpcode(op_call) || opcode == getOpcode(op_construct) || opcode == getOpcode(op_call_eval); } + + void enableSampler(); + int m_sampleEntryDepth; + OwnPtr m_sampler; + + int m_reentryDepth; + + RegisterFile m_registerFile; + +#if ENABLE(COMPUTED_GOTO_INTERPRETER) + Opcode m_opcodeTable[numOpcodeIDs]; // Maps OpcodeID => Opcode for compiling + HashMap m_opcodeIDTable; // Maps Opcode => OpcodeID for decompiling +#endif + +#if !ASSERT_DISABLED + bool m_initialized; +#endif + bool m_enabled; + }; + + // This value must not be an object that would require this conversion (WebCore's global object). + inline bool isValidThisObject(JSValue thisValue, ExecState* exec) + { + return !thisValue.isObject() || thisValue.toThisObject(exec) == thisValue; + } + + inline JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue thisValue, ScopeChainNode* scopeChain) + { + return execute(eval, callFrame, thisValue, scopeChain, m_registerFile.size() + 1 + RegisterFile::CallFrameHeaderSize); + } + + JSValue eval(CallFrame*); + CallFrame* loadVarargs(CallFrame*, RegisterFile*, JSValue thisValue, JSValue arguments, int firstFreeRegister); + +} // namespace JSC + +#endif // Interpreter_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Intrinsic.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Intrinsic.h new file mode 100644 index 000000000..5cc00685f --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Intrinsic.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2011 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 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 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 Intrinsic_h +#define Intrinsic_h + +namespace JSC { + +enum Intrinsic { + NoIntrinsic, + AbsIntrinsic, + MinIntrinsic, + MaxIntrinsic, + SqrtIntrinsic, + ArrayPushIntrinsic, + ArrayPopIntrinsic, + CharCodeAtIntrinsic, + CharAtIntrinsic, + FromCharCodeIntrinsic, + PowIntrinsic, + FloorIntrinsic, + CeilIntrinsic, + RoundIntrinsic, + ExpIntrinsic, + LogIntrinsic, +}; + +} // namespace JSC + +#endif // Intrinsic_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JITCode.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JITCode.h new file mode 100644 index 000000000..f63c4a1a8 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JITCode.h @@ -0,0 +1,167 @@ +/* + * Copyright (C) 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 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 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 JITCode_h +#define JITCode_h + +#if ENABLE(JIT) +#include "CallFrame.h" +#include "JSValue.h" +#include "MacroAssemblerCodeRef.h" +#include "Profiler.h" +#endif + +namespace JSC { + +#if ENABLE(JIT) + class JSGlobalData; + class RegisterFile; +#endif + + class JITCode { +#if ENABLE(JIT) + typedef MacroAssemblerCodeRef CodeRef; + typedef MacroAssemblerCodePtr CodePtr; +#else + JITCode() { } +#endif + public: + enum JITType { HostCallThunk, BaselineJIT, DFGJIT }; + + static JITType bottomTierJIT() + { + return BaselineJIT; + } + + static JITType topTierJIT() + { + return DFGJIT; + } + + static JITType nextTierJIT(JITType jitType) + { + ASSERT_UNUSED(jitType, jitType == BaselineJIT || jitType == DFGJIT); + return DFGJIT; + } + +#if ENABLE(JIT) + JITCode() + { + } + + JITCode(const CodeRef ref, JITType jitType) + : m_ref(ref) + , m_jitType(jitType) + { + } + + bool operator !() const + { + return !m_ref; + } + + CodePtr addressForCall() + { + return m_ref.code(); + } + + void* executableAddressAtOffset(size_t offset) const + { + ASSERT(offset < size()); + return reinterpret_cast(m_ref.code().executableAddress()) + offset; + } + + void* dataAddressAtOffset(size_t offset) const + { + ASSERT(offset < size()); + return reinterpret_cast(m_ref.code().dataLocation()) + offset; + } + + // This function returns the offset in bytes of 'pointerIntoCode' into + // this block of code. The pointer provided must be a pointer into this + // block of code. It is ASSERTed that no codeblock >4gb in size. + unsigned offsetOf(void* pointerIntoCode) + { + intptr_t result = reinterpret_cast(pointerIntoCode) - reinterpret_cast(m_ref.code().executableAddress()); + ASSERT(static_cast(static_cast(result)) == result); + return static_cast(result); + } + + // Execute the code! + inline JSValue execute(RegisterFile* registerFile, CallFrame* callFrame, JSGlobalData* globalData) + { + JSValue result = JSValue::decode(ctiTrampoline(m_ref.code().executableAddress(), registerFile, callFrame, 0, Profiler::enabledProfilerReference(), globalData)); + return globalData->exception ? jsNull() : result; + } + + void* start() const + { + return m_ref.code().dataLocation(); + } + + size_t size() const + { + ASSERT(m_ref.code().executableAddress()); + return m_ref.size(); + } + + ExecutableMemoryHandle* getExecutableMemory() + { + return m_ref.executableMemory(); + } + + JITType jitType() + { + return m_jitType; + } + + // Host functions are a bit special; they have a m_code pointer but they + // do not individully ref the executable pool containing the trampoline. + static JITCode HostFunction(CodeRef code) + { + return JITCode(code, HostCallThunk); + } + + void clear() + { + m_ref.~CodeRef(); + new (NotNull, &m_ref) CodeRef(); + } + + private: + JITCode(PassRefPtr executableMemory, JITType jitType) + : m_ref(executableMemory) + , m_jitType(jitType) + { + } + + CodeRef m_ref; + JITType m_jitType; +#endif // ENABLE(JIT) + }; + +}; + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JITDriver.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JITDriver.h new file mode 100644 index 000000000..7e010cdfe --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JITDriver.h @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2012 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 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 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 JITDriver_h +#define JITDriver_h + +#include + +#if ENABLE(JIT) + +#include "BytecodeGenerator.h" +#include "DFGDriver.h" +#include "JIT.h" + +namespace JSC { + +template +inline bool jitCompileIfAppropriate(JSGlobalData& globalData, OwnPtr& codeBlock, JITCode& jitCode, JITCode::JITType jitType) +{ + if (!globalData.canUseJIT()) + return true; + + bool dfgCompiled = false; + if (jitType == JITCode::DFGJIT) + dfgCompiled = DFG::tryCompile(globalData, codeBlock.get(), jitCode); + if (dfgCompiled) { + if (codeBlock->alternative()) + codeBlock->alternative()->unlinkIncomingCalls(); + } else { + if (codeBlock->alternative()) { + codeBlock = static_pointer_cast(codeBlock->releaseAlternative()); + return false; + } + jitCode = JIT::compile(&globalData, codeBlock.get()); + } +#if !ENABLE(OPCODE_SAMPLING) + if (!BytecodeGenerator::dumpsGeneratedCode()) + codeBlock->handleBytecodeDiscardingOpportunity(); +#endif + codeBlock->setJITCode(jitCode, MacroAssemblerCodePtr()); + + return true; +} + +inline bool jitCompileFunctionIfAppropriate(JSGlobalData& globalData, OwnPtr& codeBlock, JITCode& jitCode, MacroAssemblerCodePtr& jitCodeWithArityCheck, SharedSymbolTable*& symbolTable, JITCode::JITType jitType) +{ + if (!globalData.canUseJIT()) + return true; + + bool dfgCompiled = false; + if (jitType == JITCode::DFGJIT) + dfgCompiled = DFG::tryCompileFunction(globalData, codeBlock.get(), jitCode, jitCodeWithArityCheck); + if (dfgCompiled) { + if (codeBlock->alternative()) + codeBlock->alternative()->unlinkIncomingCalls(); + } else { + if (codeBlock->alternative()) { + codeBlock = static_pointer_cast(codeBlock->releaseAlternative()); + symbolTable = codeBlock->sharedSymbolTable(); + return false; + } + jitCode = JIT::compile(&globalData, codeBlock.get(), &jitCodeWithArityCheck); + } +#if !ENABLE(OPCODE_SAMPLING) + if (!BytecodeGenerator::dumpsGeneratedCode()) + codeBlock->handleBytecodeDiscardingOpportunity(); +#endif + + codeBlock->setJITCode(jitCode, jitCodeWithArityCheck); + + return true; +} + +} // namespace JSC + +#endif // ENABLE(JIT) + +#endif // JITDriver_h + diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JITExceptions.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JITExceptions.h new file mode 100644 index 000000000..59ded187d --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JITExceptions.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2012 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 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 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 JITExceptions_h +#define JITExceptions_h + +#include "JSValue.h" +#include "MacroAssemblerCodeRef.h" + +#if ENABLE(ASSEMBLER) + +namespace JSC { + +class ExecState; +class JSGlobalData; + +// This header gives other parts of the system access to the JIT's prototocol +// for the throwing and handling exceptions. + +struct ExceptionHandler { + void* catchRoutine; + ExecState* callFrame; +}; + +ExceptionHandler genericThrow(JSGlobalData*, ExecState*, JSValue exceptionValue, unsigned vPCIndex); + +ExceptionHandler jitThrow(JSGlobalData*, ExecState*, JSValue exceptionValue, ReturnAddressPtr faultLocation); + +} // namespace JSC + +#endif + +#endif // JITExceptions_h + diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JITStubs.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JITStubs.h new file mode 100644 index 000000000..241ace968 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JITStubs.h @@ -0,0 +1,453 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) Research In Motion Limited 2010. 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 JITStubs_h +#define JITStubs_h + +#include "CallData.h" +#include "Intrinsic.h" +#include "MacroAssemblerCodeRef.h" +#include "Register.h" +#include "ThunkGenerators.h" +#include + +#if ENABLE(JIT) + +namespace JSC { + + struct StructureStubInfo; + + class CodeBlock; + class ExecutablePool; + class FunctionExecutable; + class Identifier; + class JSGlobalData; + class JSGlobalObject; + class JSObject; + class JSPropertyNameIterator; + class JSValue; + class JSValueEncodedAsPointer; + class NativeExecutable; + class Profiler; + class PropertySlot; + class PutPropertySlot; + class RegisterFile; + class RegExp; + + template class Weak; + + union JITStubArg { + void* asPointer; + EncodedJSValue asEncodedJSValue; + int32_t asInt32; + + JSValue jsValue() { return JSValue::decode(asEncodedJSValue); } + JSObject* jsObject() { return static_cast(asPointer); } + Register* reg() { return static_cast(asPointer); } + Identifier& identifier() { return *static_cast(asPointer); } + int32_t int32() { return asInt32; } + CodeBlock* codeBlock() { return static_cast(asPointer); } + FunctionExecutable* function() { return static_cast(asPointer); } + RegExp* regExp() { return static_cast(asPointer); } + JSPropertyNameIterator* propertyNameIterator() { return static_cast(asPointer); } + JSGlobalObject* globalObject() { return static_cast(asPointer); } + JSString* jsString() { return static_cast(asPointer); } + ReturnAddressPtr returnAddress() { return ReturnAddressPtr(asPointer); } + }; + + struct TrampolineStructure { + MacroAssemblerCodePtr ctiStringLengthTrampoline; + MacroAssemblerCodePtr ctiVirtualCallLink; + MacroAssemblerCodePtr ctiVirtualConstructLink; + MacroAssemblerCodePtr ctiVirtualCall; + MacroAssemblerCodePtr ctiVirtualConstruct; + MacroAssemblerCodePtr ctiNativeCall; + MacroAssemblerCodePtr ctiNativeConstruct; + MacroAssemblerCodePtr ctiSoftModulo; + }; + +#if CPU(X86_64) + struct JITStackFrame { + void* reserved; // Unused + JITStubArg args[6]; + void* padding[2]; // Maintain 32-byte stack alignment (possibly overkill). + + void* code; + RegisterFile* registerFile; + CallFrame* callFrame; + void* unused1; + Profiler** enabledProfilerReference; + JSGlobalData* globalData; + + void* savedRBX; + void* savedR15; + void* savedR14; + void* savedR13; + void* savedR12; + void* savedRBP; + void* savedRIP; + + // When JIT code makes a call, it pushes its return address just below the rest of the stack. + ReturnAddressPtr* returnAddressSlot() { return reinterpret_cast(this) - 1; } + }; +#elif CPU(X86) +#if COMPILER(MSVC) || (OS(WINDOWS) && COMPILER(GCC)) +#pragma pack(push) +#pragma pack(4) +#endif // COMPILER(MSVC) || (OS(WINDOWS) && COMPILER(GCC)) + struct JITStackFrame { + void* reserved; // Unused + JITStubArg args[6]; +#if USE(JSVALUE32_64) + void* padding[2]; // Maintain 16-byte stack alignment. +#endif + + void* savedEBX; + void* savedEDI; + void* savedESI; + void* savedEBP; + void* savedEIP; + + void* code; + RegisterFile* registerFile; + CallFrame* callFrame; + void* unused1; + Profiler** enabledProfilerReference; + JSGlobalData* globalData; + + // When JIT code makes a call, it pushes its return address just below the rest of the stack. + ReturnAddressPtr* returnAddressSlot() { return reinterpret_cast(this) - 1; } + }; +#if COMPILER(MSVC) || (OS(WINDOWS) && COMPILER(GCC)) +#pragma pack(pop) +#endif // COMPILER(MSVC) || (OS(WINDOWS) && COMPILER(GCC)) +#elif CPU(ARM_THUMB2) + struct JITStackFrame { + JITStubArg reserved; // Unused + JITStubArg args[6]; + + ReturnAddressPtr thunkReturnAddress; + + void* preservedReturnAddress; + void* preservedR4; + void* preservedR5; + void* preservedR6; + void* preservedR7; + void* preservedR8; + void* preservedR9; + void* preservedR10; + void* preservedR11; + + // These arguments passed in r1..r3 (r0 contained the entry code pointed, which is not preserved) + RegisterFile* registerFile; + CallFrame* callFrame; + + // These arguments passed on the stack. + Profiler** enabledProfilerReference; + JSGlobalData* globalData; + + ReturnAddressPtr* returnAddressSlot() { return &thunkReturnAddress; } + }; +#elif CPU(ARM_TRADITIONAL) +#if COMPILER(MSVC) +#pragma pack(push) +#pragma pack(4) +#endif // COMPILER(MSVC) + struct JITStackFrame { + JITStubArg padding; // Unused + JITStubArg args[7]; + + ReturnAddressPtr thunkReturnAddress; + + void* preservedR4; + void* preservedR5; + void* preservedR6; + void* preservedR7; + void* preservedR8; + void* preservedLink; + + RegisterFile* registerFile; + CallFrame* callFrame; + void* unused1; + + // These arguments passed on the stack. + Profiler** enabledProfilerReference; + JSGlobalData* globalData; + + // When JIT code makes a call, it pushes its return address just below the rest of the stack. + ReturnAddressPtr* returnAddressSlot() { return &thunkReturnAddress; } + }; +#if COMPILER(MSVC) +#pragma pack(pop) +#endif // COMPILER(MSVC) +#elif CPU(MIPS) + struct JITStackFrame { + JITStubArg reserved; // Unused + JITStubArg args[6]; + +#if USE(JSVALUE32_64) + void* padding; // Make the overall stack length 8-byte aligned. +#endif + + void* preservedGP; // store GP when using PIC code + void* preservedS0; + void* preservedS1; + void* preservedS2; + void* preservedReturnAddress; + + ReturnAddressPtr thunkReturnAddress; + + // These arguments passed in a1..a3 (a0 contained the entry code pointed, which is not preserved) + RegisterFile* registerFile; + CallFrame* callFrame; + void* unused1; + + // These arguments passed on the stack. + Profiler** enabledProfilerReference; + JSGlobalData* globalData; + + ReturnAddressPtr* returnAddressSlot() { return &thunkReturnAddress; } + }; +#elif CPU(SH4) + struct JITStackFrame { + JITStubArg padding; // Unused + JITStubArg args[6]; + + ReturnAddressPtr thunkReturnAddress; + void* savedR10; + void* savedR11; + void* savedR13; + void* savedRPR; + void* savedR14; + void* savedTimeoutReg; + + RegisterFile* registerFile; + CallFrame* callFrame; + JSValue* exception; + Profiler** enabledProfilerReference; + JSGlobalData* globalData; + + ReturnAddressPtr* returnAddressSlot() { return &thunkReturnAddress; } + }; +#else +#error "JITStackFrame not defined for this platform." +#endif + +#define JITSTACKFRAME_ARGS_INDEX (OBJECT_OFFSETOF(JITStackFrame, args) / sizeof(void*)) + +#define STUB_ARGS_DECLARATION void** args +#define STUB_ARGS (args) + +#if CPU(X86) + #if COMPILER(MSVC) + #define JIT_STUB __fastcall + #elif COMPILER(GCC) + #define JIT_STUB __attribute__ ((fastcall)) + #elif COMPILER(SUNCC) + #define JIT_STUB + #else + #error "JIT_STUB function calls require fastcall conventions on x86, add appropriate directive/attribute here for your compiler!" + #endif +#else + #define JIT_STUB +#endif + + extern "C" void ctiVMThrowTrampoline(); + extern "C" void ctiOpThrowNotCaught(); + extern "C" EncodedJSValue ctiTrampoline(void* code, RegisterFile*, CallFrame*, void* /*unused1*/, Profiler**, JSGlobalData*); + + class JITThunks { + public: + JITThunks(JSGlobalData*); + ~JITThunks(); + + static void tryCacheGetByID(CallFrame*, CodeBlock*, ReturnAddressPtr returnAddress, JSValue baseValue, const Identifier& propertyName, const PropertySlot&, StructureStubInfo* stubInfo); + static void tryCachePutByID(CallFrame*, CodeBlock*, ReturnAddressPtr returnAddress, JSValue baseValue, const PutPropertySlot&, StructureStubInfo* stubInfo, bool direct); + + MacroAssemblerCodePtr ctiStringLengthTrampoline() { return m_trampolineStructure.ctiStringLengthTrampoline; } + MacroAssemblerCodePtr ctiVirtualCallLink() { return m_trampolineStructure.ctiVirtualCallLink; } + MacroAssemblerCodePtr ctiVirtualConstructLink() { return m_trampolineStructure.ctiVirtualConstructLink; } + MacroAssemblerCodePtr ctiVirtualCall() { return m_trampolineStructure.ctiVirtualCall; } + MacroAssemblerCodePtr ctiVirtualConstruct() { return m_trampolineStructure.ctiVirtualConstruct; } + MacroAssemblerCodePtr ctiNativeCall() { return m_trampolineStructure.ctiNativeCall; } + MacroAssemblerCodePtr ctiNativeConstruct() { return m_trampolineStructure.ctiNativeConstruct; } + MacroAssemblerCodePtr ctiSoftModulo() { return m_trampolineStructure.ctiSoftModulo; } + + MacroAssemblerCodeRef ctiStub(JSGlobalData*, ThunkGenerator); + + NativeExecutable* hostFunctionStub(JSGlobalData*, NativeFunction, NativeFunction constructor); + NativeExecutable* hostFunctionStub(JSGlobalData*, NativeFunction, ThunkGenerator, Intrinsic); + + void clearHostFunctionStubs(); + + private: + typedef HashMap CTIStubMap; + CTIStubMap m_ctiStubMap; + typedef HashMap > HostFunctionStubMap; + OwnPtr m_hostFunctionStubMap; + RefPtr m_executableMemory; + + TrampolineStructure m_trampolineStructure; + }; + +extern "C" { + EncodedJSValue JIT_STUB cti_op_add(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_bitand(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_bitnot(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_bitor(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_bitxor(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_call_NotJSFunction(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_call_eval(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_construct_NotJSConstruct(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_create_this(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_convert_this(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_create_arguments(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_del_by_id(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_del_by_val(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_div(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_get_by_id(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_get_by_id_array_fail(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_get_by_id_custom_stub(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_get_by_id_generic(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_get_by_id_getter_stub(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_get_by_id_method_check(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_get_by_id_method_check_update(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_get_by_id_proto_fail(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_get_by_id_proto_list(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_get_by_id_proto_list_full(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_get_by_id_self_fail(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_get_by_id_string_fail(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_get_by_val(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_get_by_val_byte_array(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_get_by_val_string(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_in(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_instanceof(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_is_boolean(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_is_function(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_is_number(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_is_object(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_is_string(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_is_undefined(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_less(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_lesseq(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_greater(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_greatereq(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_lshift(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_mod(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_mul(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_negate(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_not(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_nstricteq(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_post_dec(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_post_inc(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_pre_dec(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_pre_inc(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_resolve(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_resolve_base(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_resolve_base_strict_put(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_ensure_property_exists(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_resolve_global(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_resolve_global_dynamic(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_resolve_skip(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_resolve_with_base(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_resolve_with_this(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_rshift(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_strcat(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_stricteq(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_sub(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_to_jsnumber(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_to_primitive(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_typeof(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_urshift(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_to_object(STUB_ARGS_DECLARATION); + JSObject* JIT_STUB cti_op_new_array(STUB_ARGS_DECLARATION); + JSObject* JIT_STUB cti_op_new_array_buffer(STUB_ARGS_DECLARATION); + JSObject* JIT_STUB cti_op_new_func(STUB_ARGS_DECLARATION); + JSObject* JIT_STUB cti_op_new_func_exp(STUB_ARGS_DECLARATION); + JSObject* JIT_STUB cti_op_new_object(STUB_ARGS_DECLARATION); + JSObject* JIT_STUB cti_op_new_regexp(STUB_ARGS_DECLARATION); + JSObject* JIT_STUB cti_op_push_activation(STUB_ARGS_DECLARATION); + JSObject* JIT_STUB cti_op_push_new_scope(STUB_ARGS_DECLARATION); + JSObject* JIT_STUB cti_op_push_scope(STUB_ARGS_DECLARATION); + JSObject* JIT_STUB cti_op_put_by_id_transition_realloc(STUB_ARGS_DECLARATION); + JSPropertyNameIterator* JIT_STUB cti_op_get_pnames(STUB_ARGS_DECLARATION); + int JIT_STUB cti_op_eq(STUB_ARGS_DECLARATION); + int JIT_STUB cti_op_eq_strings(STUB_ARGS_DECLARATION); + int JIT_STUB cti_op_jless(STUB_ARGS_DECLARATION); + int JIT_STUB cti_op_jlesseq(STUB_ARGS_DECLARATION); + int JIT_STUB cti_op_jgreater(STUB_ARGS_DECLARATION); + int JIT_STUB cti_op_jgreatereq(STUB_ARGS_DECLARATION); + int JIT_STUB cti_op_jtrue(STUB_ARGS_DECLARATION); + void* JIT_STUB cti_op_load_varargs(STUB_ARGS_DECLARATION); + int JIT_STUB cti_timeout_check(STUB_ARGS_DECLARATION); + int JIT_STUB cti_has_property(STUB_ARGS_DECLARATION); + void JIT_STUB cti_op_check_has_instance(STUB_ARGS_DECLARATION); + void JIT_STUB cti_op_debug(STUB_ARGS_DECLARATION); + void JIT_STUB cti_op_end(STUB_ARGS_DECLARATION); + void JIT_STUB cti_op_jmp_scopes(STUB_ARGS_DECLARATION); + void JIT_STUB cti_op_pop_scope(STUB_ARGS_DECLARATION); + void JIT_STUB cti_op_profile_did_call(STUB_ARGS_DECLARATION); + void JIT_STUB cti_op_profile_will_call(STUB_ARGS_DECLARATION); + void JIT_STUB cti_op_put_by_id(STUB_ARGS_DECLARATION); + void JIT_STUB cti_op_put_by_id_fail(STUB_ARGS_DECLARATION); + void JIT_STUB cti_op_put_by_id_generic(STUB_ARGS_DECLARATION); + void JIT_STUB cti_op_put_by_id_direct(STUB_ARGS_DECLARATION); + void JIT_STUB cti_op_put_by_id_direct_fail(STUB_ARGS_DECLARATION); + void JIT_STUB cti_op_put_by_id_direct_generic(STUB_ARGS_DECLARATION); + void JIT_STUB cti_op_put_by_index(STUB_ARGS_DECLARATION); + void JIT_STUB cti_op_put_by_val(STUB_ARGS_DECLARATION); + void JIT_STUB cti_op_put_by_val_byte_array(STUB_ARGS_DECLARATION); + void JIT_STUB cti_op_put_getter(STUB_ARGS_DECLARATION); + void JIT_STUB cti_op_put_setter(STUB_ARGS_DECLARATION); + void JIT_STUB cti_op_tear_off_activation(STUB_ARGS_DECLARATION); + void JIT_STUB cti_op_tear_off_arguments(STUB_ARGS_DECLARATION); + void JIT_STUB cti_op_throw_reference_error(STUB_ARGS_DECLARATION); +#if ENABLE(DFG_JIT) + void JIT_STUB cti_optimize_from_loop(STUB_ARGS_DECLARATION); + void JIT_STUB cti_optimize_from_ret(STUB_ARGS_DECLARATION); +#endif + void* JIT_STUB cti_op_call_arityCheck(STUB_ARGS_DECLARATION); + void* JIT_STUB cti_op_construct_arityCheck(STUB_ARGS_DECLARATION); + void* JIT_STUB cti_op_call_jitCompile(STUB_ARGS_DECLARATION); + void* JIT_STUB cti_op_construct_jitCompile(STUB_ARGS_DECLARATION); + void* JIT_STUB cti_op_switch_char(STUB_ARGS_DECLARATION); + void* JIT_STUB cti_op_switch_imm(STUB_ARGS_DECLARATION); + void* JIT_STUB cti_op_switch_string(STUB_ARGS_DECLARATION); + void* JIT_STUB cti_op_throw(STUB_ARGS_DECLARATION); + void* JIT_STUB cti_register_file_check(STUB_ARGS_DECLARATION); + void* JIT_STUB cti_vm_lazyLinkCall(STUB_ARGS_DECLARATION); + void* JIT_STUB cti_vm_lazyLinkConstruct(STUB_ARGS_DECLARATION); + void* JIT_STUB cti_vm_throw(STUB_ARGS_DECLARATION); +} // extern "C" + +} // namespace JSC + +#endif // ENABLE(JIT) + +#endif // JITStubs_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSAPIValueWrapper.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSAPIValueWrapper.h new file mode 100644 index 000000000..21d7b215c --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSAPIValueWrapper.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) + * Copyright (C) 2001 Peter Kelly (pmk@post.com) + * Copyright (C) 2003, 2004, 2005, 2007, 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef JSAPIValueWrapper_h +#define JSAPIValueWrapper_h + +#include "JSCell.h" +#include "JSValue.h" +#include "CallFrame.h" +#include "Structure.h" + +namespace JSC { + + class JSAPIValueWrapper : public JSCell { + friend JSValue jsAPIValueWrapper(ExecState*, JSValue); + public: + typedef JSCell Base; + + JSValue value() const { return m_value.get(); } + + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + { + return Structure::create(globalData, globalObject, prototype, TypeInfo(APIValueWrapperType, OverridesVisitChildren | OverridesGetPropertyNames), &s_info); + } + + static JS_EXPORTDATA const ClassInfo s_info; + + static JSAPIValueWrapper* create(ExecState* exec, JSValue value) + { + JSAPIValueWrapper* wrapper = new (NotNull, allocateCell(*exec->heap())) JSAPIValueWrapper(exec); + wrapper->finishCreation(exec, value); + return wrapper; + } + + protected: + void finishCreation(ExecState* exec, JSValue value) + { + Base::finishCreation(exec->globalData()); + m_value.set(exec->globalData(), this, value); + ASSERT(!value.isCell()); + } + + private: + JSAPIValueWrapper(ExecState* exec) + : JSCell(exec->globalData(), exec->globalData().apiWrapperStructure.get()) + { + } + + WriteBarrier m_value; + }; + + inline JSValue jsAPIValueWrapper(ExecState* exec, JSValue value) + { + return JSAPIValueWrapper::create(exec, value); + } + +} // namespace JSC + +#endif // JSAPIValueWrapper_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSArray.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSArray.h new file mode 100644 index 000000000..5e47977a9 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSArray.h @@ -0,0 +1,329 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2003, 2007, 2008, 2009 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef JSArray_h +#define JSArray_h + +#include "JSObject.h" + +#define CHECK_ARRAY_CONSISTENCY 0 + +namespace JSC { + + class JSArray; + + struct SparseArrayEntry : public WriteBarrier { + typedef WriteBarrier Base; + + SparseArrayEntry() : attributes(0) {} + + JSValue get(ExecState*, JSArray*) const; + void get(PropertySlot&) const; + void get(PropertyDescriptor&) const; + JSValue getNonSparseMode() const; + + unsigned attributes; + }; + + class SparseArrayValueMap { + typedef HashMap, WTF::UnsignedWithZeroKeyHashTraits > Map; + + enum Flags { + Normal = 0, + SparseMode = 1, + LengthIsReadOnly = 2, + }; + + public: + typedef Map::iterator iterator; + typedef Map::const_iterator const_iterator; + + SparseArrayValueMap() + : m_flags(Normal) + , m_reportedCapacity(0) + { + } + + void visitChildren(SlotVisitor&); + + bool sparseMode() + { + return m_flags & SparseMode; + } + + void setSparseMode() + { + m_flags = static_cast(m_flags | SparseMode); + } + + bool lengthIsReadOnly() + { + return m_flags & LengthIsReadOnly; + } + + void setLengthIsReadOnly() + { + m_flags = static_cast(m_flags | LengthIsReadOnly); + } + + // These methods may mutate the contents of the map + void put(ExecState*, JSArray*, unsigned, JSValue); + std::pair add(JSArray*, unsigned); + iterator find(unsigned i) { return m_map.find(i); } + // This should ASSERT the remove is valid (check the result of the find). + void remove(iterator it) { m_map.remove(it); } + void remove(unsigned i) { m_map.remove(i); } + + // These methods do not mutate the contents of the map. + iterator notFound() { return m_map.end(); } + bool isEmpty() const { return m_map.isEmpty(); } + bool contains(unsigned i) const { return m_map.contains(i); } + size_t size() const { return m_map.size(); } + // Only allow const begin/end iteration. + const_iterator begin() const { return m_map.begin(); } + const_iterator end() const { return m_map.end(); } + + private: + Map m_map; + Flags m_flags; + size_t m_reportedCapacity; + }; + + // This struct holds the actual data values of an array. A JSArray object points to it's contained ArrayStorage + // struct by pointing to m_vector. To access the contained ArrayStorage struct, use the getStorage() and + // setStorage() methods. It is important to note that there may be space before the ArrayStorage that + // is used to quick unshift / shift operation. The actual allocated pointer is available by using: + // getStorage() - m_indexBias * sizeof(JSValue) + struct ArrayStorage { + unsigned m_length; // The "length" property on the array + unsigned m_numValuesInVector; + void* m_allocBase; // Pointer to base address returned by malloc(). Keeping this pointer does eliminate false positives from the leak detector. +#if CHECK_ARRAY_CONSISTENCY + bool m_inCompactInitialization; +#endif + WriteBarrier m_vector[1]; + }; + + class JSArray : public JSNonFinalObject { + friend class Walker; + + protected: + JS_EXPORT_PRIVATE explicit JSArray(JSGlobalData&, Structure*); + + JS_EXPORT_PRIVATE void finishCreation(JSGlobalData&, unsigned initialLength = 0); + JS_EXPORT_PRIVATE JSArray* tryFinishCreationUninitialized(JSGlobalData&, unsigned initialLength); + + public: + typedef JSNonFinalObject Base; + + JS_EXPORT_PRIVATE ~JSArray(); + JS_EXPORT_PRIVATE static void destroy(JSCell*); + + static JSArray* create(JSGlobalData& globalData, Structure* structure, unsigned initialLength = 0) + { + JSArray* array = new (NotNull, allocateCell(globalData.heap)) JSArray(globalData, structure); + array->finishCreation(globalData, initialLength); + return array; + } + + // tryCreateUninitialized is used for fast construction of arrays whose size and + // contents are known at time of creation. Clients of this interface must: + // - null-check the result (indicating out of memory, or otherwise unable to allocate vector). + // - call 'initializeIndex' for all properties in sequence, for 0 <= i < initialLength. + // - called 'completeInitialization' after all properties have been initialized. + static JSArray* tryCreateUninitialized(JSGlobalData& globalData, Structure* structure, unsigned initialLength) + { + JSArray* array = new (NotNull, allocateCell(globalData.heap)) JSArray(globalData, structure); + return array->tryFinishCreationUninitialized(globalData, initialLength); + } + + JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&, bool throwException); + + static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&); + JS_EXPORT_PRIVATE static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&); + static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); + static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue); + + static JS_EXPORTDATA const ClassInfo s_info; + + unsigned length() const { return m_storage->m_length; } + // OK to use on new arrays, but not if it might be a RegExpMatchArray. + bool setLength(ExecState*, unsigned, bool throwException = false); + + void sort(ExecState*); + void sort(ExecState*, JSValue compareFunction, CallType, const CallData&); + void sortNumeric(ExecState*, JSValue compareFunction, CallType, const CallData&); + + void push(ExecState*, JSValue); + JSValue pop(ExecState*); + + void shiftCount(ExecState*, unsigned count); + void unshiftCount(ExecState*, unsigned count); + + bool canGetIndex(unsigned i) { return i < m_vectorLength && m_storage->m_vector[i]; } + JSValue getIndex(unsigned i) + { + ASSERT(canGetIndex(i)); + return m_storage->m_vector[i].get(); + } + + bool canSetIndex(unsigned i) { return i < m_vectorLength; } + void setIndex(JSGlobalData& globalData, unsigned i, JSValue v) + { + ASSERT(canSetIndex(i)); + + WriteBarrier& x = m_storage->m_vector[i]; + if (!x) { + ArrayStorage *storage = m_storage; + ++storage->m_numValuesInVector; + if (i >= storage->m_length) + storage->m_length = i + 1; + } + x.set(globalData, this, v); + } + + inline void initializeIndex(JSGlobalData& globalData, unsigned i, JSValue v) + { + ASSERT(canSetIndex(i)); + ArrayStorage *storage = m_storage; +#if CHECK_ARRAY_CONSISTENCY + ASSERT(storage->m_inCompactInitialization); +#endif + // Check that we are initializing the next index in sequence. + ASSERT_UNUSED(i, i == storage->m_length); + // tryCreateUninitialized set m_numValuesInVector to the initialLength, + // check we do not try to initialize more than this number of properties. + ASSERT(storage->m_length < storage->m_numValuesInVector); + // It is improtant that we increment length here, so that all newly added + // values in the array still get marked during the initialization phase. + storage->m_vector[storage->m_length++].set(globalData, this, v); + } + + inline void completeInitialization(unsigned newLength) + { + // Check that we have initialized as meny properties as we think we have. + ASSERT_UNUSED(newLength, newLength == m_storage->m_length); + // Check that the number of propreties initialized matches the initialLength. + ASSERT(m_storage->m_length == m_storage->m_numValuesInVector); +#if CHECK_ARRAY_CONSISTENCY + ASSERT(m_storage->m_inCompactInitialization); + m_storage->m_inCompactInitialization = false; +#endif + } + + bool inSparseMode() + { + SparseArrayValueMap* map = m_sparseValueMap; + return map && map->sparseMode(); + } + + void fillArgList(ExecState*, MarkedArgumentBuffer&); + void copyToArguments(ExecState*, CallFrame*, uint32_t length); + + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + { + return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); + } + + static ptrdiff_t storageOffset() + { + return OBJECT_OFFSETOF(JSArray, m_storage); + } + + static ptrdiff_t vectorLengthOffset() + { + return OBJECT_OFFSETOF(JSArray, m_vectorLength); + } + + JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&); + + protected: + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags; + static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); + + static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName); + static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName); + static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); + + JS_EXPORT_PRIVATE void* subclassData() const; + JS_EXPORT_PRIVATE void setSubclassData(void*); + + private: + bool isLengthWritable() + { + SparseArrayValueMap* map = m_sparseValueMap; + return !map || !map->lengthIsReadOnly(); + } + + void setLengthWritable(ExecState*, bool writable); + void putDescriptor(ExecState*, SparseArrayEntry*, PropertyDescriptor&, PropertyDescriptor& old); + bool defineOwnNumericProperty(ExecState*, unsigned, PropertyDescriptor&, bool throwException); + void enterSparseMode(JSGlobalData&); + + bool getOwnPropertySlotSlowCase(ExecState*, unsigned propertyName, PropertySlot&); + void putByIndexBeyondVectorLength(ExecState*, unsigned propertyName, JSValue); + + unsigned getNewVectorLength(unsigned desiredLength); + bool increaseVectorLength(JSGlobalData&, unsigned newLength); + bool unshiftCountSlowCase(JSGlobalData&, unsigned count); + + unsigned compactForSorting(JSGlobalData&); + + enum ConsistencyCheckType { NormalConsistencyCheck, DestructorConsistencyCheck, SortConsistencyCheck }; + void checkConsistency(ConsistencyCheckType = NormalConsistencyCheck); + + unsigned m_vectorLength; // The valid length of m_vector + unsigned m_indexBias; // The number of JSValue sized blocks before ArrayStorage. + ArrayStorage *m_storage; + + // FIXME: Maybe SparseArrayValueMap should be put into its own JSCell? + SparseArrayValueMap* m_sparseValueMap; + void* m_subclassData; // A JSArray subclass can use this to fill the vector lazily. + }; + + JSArray* asArray(JSValue); + + inline JSArray* asArray(JSCell* cell) + { + ASSERT(cell->inherits(&JSArray::s_info)); + return static_cast(cell); + } + + inline JSArray* asArray(JSValue value) + { + return asArray(value.asCell()); + } + + inline bool isJSArray(JSCell* cell) { return cell->classInfo() == &JSArray::s_info; } + inline bool isJSArray(JSValue v) { return v.isCell() && isJSArray(v.asCell()); } + + // Rule from ECMA 15.2 about what an array index is. + // Must exactly match string form of an unsigned integer, and be less than 2^32 - 1. + inline unsigned Identifier::toArrayIndex(bool& ok) const + { + unsigned i = toUInt32(ok); + if (ok && i >= 0xFFFFFFFFU) + ok = false; + return i; + } + +} // namespace JSC + +#endif // JSArray_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSBasePrivate.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSBasePrivate.h new file mode 100644 index 000000000..befa31643 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSBasePrivate.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2008 Apple Computer, 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 JSBasePrivate_h +#define JSBasePrivate_h + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*! +@function +@abstract Reports an object's non-GC memory payload to the garbage collector. +@param ctx The execution context to use. +@param size The payload's size, in bytes. +@discussion Use this function to notify the garbage collector that a GC object +owns a large non-GC memory region. Calling this function will encourage the +garbage collector to collect soon, hoping to reclaim that large non-GC memory +region. +*/ +JS_EXPORT void JSReportExtraMemoryCost(JSContextRef ctx, size_t size) AVAILABLE_IN_WEBKIT_VERSION_4_0; + +#ifdef __cplusplus +} +#endif + +#endif /* JSBasePrivate_h */ diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSByteArray.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSByteArray.h new file mode 100644 index 000000000..d1f4ad630 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSByteArray.h @@ -0,0 +1,133 @@ +/* + * 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 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 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 JSByteArray_h +#define JSByteArray_h + +#include "JSObject.h" + +#include + +namespace JSC { + + class JSByteArray : public JSNonFinalObject { + friend class JSGlobalData; + public: + typedef JSNonFinalObject Base; + + bool canAccessIndex(unsigned i) { return i < m_storage->length(); } + JSValue getIndex(ExecState*, unsigned i) + { + ASSERT(canAccessIndex(i)); + return jsNumber(m_storage->data()[i]); + } + + void setIndex(unsigned i, int value) + { + ASSERT(canAccessIndex(i)); + if (value & ~0xFF) { + if (value < 0) + value = 0; + else + value = 255; + } + m_storage->data()[i] = static_cast(value); + } + + void setIndex(unsigned i, double value) + { + ASSERT(canAccessIndex(i)); + if (!(value > 0)) // Clamp NaN to 0 + value = 0; + else if (value > 255) + value = 255; + m_storage->data()[i] = static_cast(value + 0.5); + } + + void setIndex(ExecState* exec, unsigned i, JSValue value) + { + double byteValue = value.toNumber(exec); + if (exec->hadException()) + return; + if (canAccessIndex(i)) + setIndex(i, byteValue); + } + + private: + JS_EXPORT_PRIVATE JSByteArray(ExecState*, Structure*, ByteArray* storage); + + public: + static JSByteArray* create(ExecState* exec, Structure* structure, ByteArray* storage) + { + JSByteArray* array = new (NotNull, allocateCell(*exec->heap())) JSByteArray(exec, structure, storage); + array->finishCreation(exec); + return array; + } + + JS_EXPORT_PRIVATE static Structure* createStructure(JSGlobalData&, JSGlobalObject*, JSValue prototype, const JSC::ClassInfo* = &s_info); + + JS_EXPORT_PRIVATE static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&); + JS_EXPORT_PRIVATE static bool getOwnPropertySlotByIndex(JSC::JSCell*, JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&); + JS_EXPORT_PRIVATE static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); + JS_EXPORT_PRIVATE static void put(JSC::JSCell*, JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&); + JS_EXPORT_PRIVATE static void putByIndex(JSC::JSCell*, JSC::ExecState*, unsigned propertyName, JSC::JSValue); + + JS_EXPORT_PRIVATE static void getOwnPropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&, EnumerationMode); + + static JS_EXPORTDATA const ClassInfo s_info; + + size_t length() const { return m_storage->length(); } + + WTF::ByteArray* storage() const { return m_storage.get(); } + + ~JSByteArray(); + JS_EXPORT_PRIVATE static void destroy(JSCell*); + + static size_t offsetOfStorage() { return OBJECT_OFFSETOF(JSByteArray, m_storage); } + + protected: + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | JSObject::StructureFlags; + + void finishCreation(ExecState* exec) + { + Base::finishCreation(exec->globalData()); + putDirect(exec->globalData(), exec->globalData().propertyNames->length, jsNumber(m_storage->length()), ReadOnly | DontDelete); + } + + private: + RefPtr m_storage; + }; + + JSByteArray* asByteArray(JSValue value); + inline JSByteArray* asByteArray(JSValue value) + { + return static_cast(value.asCell()); + } + + inline bool isJSByteArray(JSValue v) { return v.isCell() && v.asCell()->classInfo() == &JSByteArray::s_info; } + +} // namespace JSC + +#endif // JSByteArray_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSCell.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSCell.h new file mode 100644 index 000000000..a36bb7d58 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSCell.h @@ -0,0 +1,344 @@ +/* + * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) + * Copyright (C) 2001 Peter Kelly (pmk@post.com) + * Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef JSCell_h +#define JSCell_h + +#include "CallData.h" +#include "CallFrame.h" +#include "ConstructData.h" +#include "Heap.h" +#include "JSLock.h" +#include "JSValueInlineMethods.h" +#include "SlotVisitor.h" +#include "WriteBarrier.h" +#include + +namespace JSC { + + class JSGlobalObject; + class Structure; + class PropertyDescriptor; + class PropertyNameArray; + + enum EnumerationMode { + ExcludeDontEnumProperties, + IncludeDontEnumProperties + }; + + enum TypedArrayType { + TypedArrayNone, + TypedArrayInt8, + TypedArrayInt16, + TypedArrayInt32, + TypedArrayUint8, + TypedArrayUint8Clamped, + TypedArrayUint16, + TypedArrayUint32, + TypedArrayFloat32, + TypedArrayFloat64 + }; + + class JSCell { + friend class JSValue; + friend class MarkedBlock; + + public: + enum CreatingEarlyCellTag { CreatingEarlyCell }; + JSCell(CreatingEarlyCellTag); + + protected: + JSCell(JSGlobalData&, Structure*); + JS_EXPORT_PRIVATE static void destroy(JSCell*); + + public: + // Querying the type. + bool isString() const; + bool isObject() const; + bool isGetterSetter() const; + bool inherits(const ClassInfo*) const; + bool isAPIValueWrapper() const; + + Structure* structure() const; + void setStructure(JSGlobalData&, Structure*); + void clearStructure() { m_structure.clear(); } + + // Extracting the value. + JS_EXPORT_PRIVATE bool getString(ExecState* exec, UString&) const; + JS_EXPORT_PRIVATE UString getString(ExecState* exec) const; // null string if not a string + JS_EXPORT_PRIVATE JSObject* getObject(); // NULL if not an object + const JSObject* getObject() const; // NULL if not an object + + JS_EXPORT_PRIVATE static CallType getCallData(JSCell*, CallData&); + JS_EXPORT_PRIVATE static ConstructType getConstructData(JSCell*, ConstructData&); + + // Basic conversions. + JS_EXPORT_PRIVATE JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const; + bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const; + bool toBoolean(ExecState*) const; + JS_EXPORT_PRIVATE double toNumber(ExecState*) const; + JS_EXPORT_PRIVATE JSObject* toObject(ExecState*, JSGlobalObject*) const; + + static void visitChildren(JSCell*, SlotVisitor&); + + // Object operations, with the toObject operation included. + const ClassInfo* classInfo() const; + const ClassInfo* validatedClassInfo() const; + const MethodTable* methodTable() const; + static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); + static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue); + + static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName); + static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName); + + static JSObject* toThisObject(JSCell*, ExecState*); + + void zap() { *reinterpret_cast(this) = 0; } + bool isZapped() const { return !*reinterpret_cast(this); } + + // FIXME: Rename getOwnPropertySlot to virtualGetOwnPropertySlot, and + // fastGetOwnPropertySlot to getOwnPropertySlot. Callers should always + // call this function, not its slower virtual counterpart. (For integer + // property names, we want a similar interface with appropriate optimizations.) + bool fastGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); + JSValue fastGetOwnProperty(ExecState*, const UString&); + + static ptrdiff_t structureOffset() + { + return OBJECT_OFFSETOF(JSCell, m_structure); + } + + static ptrdiff_t classInfoOffset() + { + return OBJECT_OFFSETOF(JSCell, m_classInfo); + } + + void* structureAddress() + { + return &m_structure; + } + +#if ENABLE(GC_VALIDATION) + Structure* unvalidatedStructure() { return m_structure.unvalidatedGet(); } +#endif + + static const TypedArrayType TypedArrayStorageType = TypedArrayNone; + protected: + + void finishCreation(JSGlobalData&); + void finishCreation(JSGlobalData&, Structure*, CreatingEarlyCellTag); + + // Base implementation; for non-object classes implements getPropertySlot. + static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier& propertyName, PropertySlot&); + static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&); + + // Dummy implementations of override-able static functions for classes to put in their MethodTable + static NO_RETURN_DUE_TO_ASSERT void defineGetter(JSObject*, ExecState*, const Identifier&, JSObject*, unsigned); + static NO_RETURN_DUE_TO_ASSERT void defineSetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes = 0); + static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType); + static NO_RETURN_DUE_TO_ASSERT void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); + static NO_RETURN_DUE_TO_ASSERT void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); + static UString className(const JSObject*); + static bool hasInstance(JSObject*, ExecState*, JSValue, JSValue prototypeProperty); + static NO_RETURN_DUE_TO_ASSERT void putDirectVirtual(JSObject*, ExecState*, const Identifier& propertyName, JSValue, unsigned attributes); + static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow); + static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); + + private: + const ClassInfo* m_classInfo; + WriteBarrier m_structure; + }; + + inline JSCell::JSCell(CreatingEarlyCellTag) + { + } + + inline void JSCell::finishCreation(JSGlobalData& globalData) + { +#if ENABLE(GC_VALIDATION) + ASSERT(globalData.isInitializingObject()); + globalData.setInitializingObject(false); +#else + UNUSED_PARAM(globalData); +#endif + ASSERT(m_structure); + } + + inline Structure* JSCell::structure() const + { + return m_structure.get(); + } + + inline const ClassInfo* JSCell::classInfo() const + { + return m_classInfo; + } + + inline void JSCell::visitChildren(JSCell* cell, SlotVisitor& visitor) + { + visitor.append(&cell->m_structure); + } + + // --- JSValue inlines ---------------------------- + + inline bool JSValue::isString() const + { + return isCell() && asCell()->isString(); + } + + inline bool JSValue::isPrimitive() const + { + return !isCell() || asCell()->isString(); + } + + inline bool JSValue::isGetterSetter() const + { + return isCell() && asCell()->isGetterSetter(); + } + + inline bool JSValue::isObject() const + { + return isCell() && asCell()->isObject(); + } + + inline bool JSValue::getString(ExecState* exec, UString& s) const + { + return isCell() && asCell()->getString(exec, s); + } + + inline UString JSValue::getString(ExecState* exec) const + { + return isCell() ? asCell()->getString(exec) : UString(); + } + + template UString HandleConverter::getString(ExecState* exec) const + { + return jsValue().getString(exec); + } + + inline JSObject* JSValue::getObject() const + { + return isCell() ? asCell()->getObject() : 0; + } + + ALWAYS_INLINE bool JSValue::getUInt32(uint32_t& v) const + { + if (isInt32()) { + int32_t i = asInt32(); + v = static_cast(i); + return i >= 0; + } + if (isDouble()) { + double d = asDouble(); + v = static_cast(d); + return v == d; + } + return false; + } + + inline JSValue JSValue::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const + { + return isCell() ? asCell()->toPrimitive(exec, preferredType) : asValue(); + } + + inline bool JSValue::getPrimitiveNumber(ExecState* exec, double& number, JSValue& value) + { + if (isInt32()) { + number = asInt32(); + value = *this; + return true; + } + if (isDouble()) { + number = asDouble(); + value = *this; + return true; + } + if (isCell()) + return asCell()->getPrimitiveNumber(exec, number, value); + if (isTrue()) { + number = 1.0; + value = *this; + return true; + } + if (isFalse() || isNull()) { + number = 0.0; + value = *this; + return true; + } + ASSERT(isUndefined()); + number = std::numeric_limits::quiet_NaN(); + value = *this; + return true; + } + + ALWAYS_INLINE double JSValue::toNumber(ExecState* exec) const + { + if (isInt32()) + return asInt32(); + if (isDouble()) + return asDouble(); + return toNumberSlowCase(exec); + } + + inline JSObject* JSValue::toObject(ExecState* exec) const + { + return isCell() ? asCell()->toObject(exec, exec->lexicalGlobalObject()) : toObjectSlowCase(exec, exec->lexicalGlobalObject()); + } + + inline JSObject* JSValue::toObject(ExecState* exec, JSGlobalObject* globalObject) const + { + return isCell() ? asCell()->toObject(exec, globalObject) : toObjectSlowCase(exec, globalObject); + } + + template void* allocateCell(Heap& heap) + { +#if ENABLE(GC_VALIDATION) + ASSERT(sizeof(T) == T::s_info.cellSize); + ASSERT(!heap.globalData()->isInitializingObject()); + heap.globalData()->setInitializingObject(true); +#endif + JSCell* result = static_cast(heap.allocate(sizeof(T))); + result->clearStructure(); + return result; + } + + inline bool isZapped(const JSCell* cell) + { + return cell->isZapped(); + } + + template + inline To jsCast(From* from) + { + ASSERT(from->inherits(&WTF::RemovePointer::Type::s_info)); + return static_cast(from); + } + + template + inline To jsDynamicCast(From* from) + { + return from->inherits(&WTF::RemovePointer::Type::s_info) ? static_cast(from) : 0; + } + +} // namespace JSC + +#endif // JSCell_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSContextRefPrivate.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSContextRefPrivate.h new file mode 100644 index 000000000..4f77aeada --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSContextRefPrivate.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2009 Apple Computer, 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 JSContextRefPrivate_h +#define JSContextRefPrivate_h + +#include +#include +#include + +#ifndef __cplusplus +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/*! +@function +@abstract Gets the global context of a JavaScript execution context. +@param ctx The JSContext whose global context you want to get. +@result ctx's global context. +*/ +JS_EXPORT JSGlobalContextRef JSContextGetGlobalContext(JSContextRef ctx); + + +/*! +@function +@abstract Gets a Backtrace for the existing context +@param ctx The JSContext whose backtrace you want to get +@result A string containing the backtrace +*/ +JS_EXPORT JSStringRef JSContextCreateBacktrace(JSContextRef ctx, unsigned maxStackSize) AVAILABLE_IN_WEBKIT_VERSION_4_0; + +#ifdef __cplusplus +} +#endif + +#endif /* JSContextRefPrivate_h */ diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSDateMath.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSDateMath.h new file mode 100644 index 000000000..ba6d647dd --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSDateMath.h @@ -0,0 +1,169 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright (C) 2010 Research In Motion Limited. All rights reserved. + * + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + */ + +#ifndef JSDateMath_h +#define JSDateMath_h + +#include + +namespace JSC { + +class ExecState; +struct GregorianDateTime; + +void msToGregorianDateTime(ExecState*, double, bool outputIsUTC, GregorianDateTime&); +double gregorianDateTimeToMS(ExecState*, const GregorianDateTime&, double, bool inputIsUTC); +double getUTCOffset(ExecState*); +double parseDateFromNullTerminatedCharacters(ExecState*, const char* dateString); + +// Intentionally overridding the default tm of the system. +// The members of tm differ on various operating systems. +struct GregorianDateTime { + WTF_MAKE_NONCOPYABLE(GregorianDateTime); +public: + GregorianDateTime() + : second(0) + , minute(0) + , hour(0) + , weekDay(0) + , monthDay(0) + , yearDay(0) + , month(0) + , year(0) + , isDST(0) + , utcOffset(0) + { + } + + GregorianDateTime(ExecState* exec, const tm& inTm) + : second(inTm.tm_sec) + , minute(inTm.tm_min) + , hour(inTm.tm_hour) + , weekDay(inTm.tm_wday) + , monthDay(inTm.tm_mday) + , yearDay(inTm.tm_yday) + , month(inTm.tm_mon) + , year(inTm.tm_year) + , isDST(inTm.tm_isdst) + { + UNUSED_PARAM(exec); +#if HAVE(TM_GMTOFF) + utcOffset = static_cast(inTm.tm_gmtoff); +#else + utcOffset = static_cast(getUTCOffset(exec) / WTF::msPerSecond + (isDST ? WTF::secondsPerHour : 0)); +#endif + +#if HAVE(TM_ZONE) + int inZoneSize = strlen(inTm.tm_zone) + 1; + timeZone = adoptArrayPtr(new char[inZoneSize]); + strncpy(timeZone.get(), inTm.tm_zone, inZoneSize); +#else + timeZone = nullptr; +#endif + } + + operator tm() const + { + tm ret; + memset(&ret, 0, sizeof(ret)); + + ret.tm_sec = second; + ret.tm_min = minute; + ret.tm_hour = hour; + ret.tm_wday = weekDay; + ret.tm_mday = monthDay; + ret.tm_yday = yearDay; + ret.tm_mon = month; + ret.tm_year = year; + ret.tm_isdst = isDST; + +#if HAVE(TM_GMTOFF) + ret.tm_gmtoff = static_cast(utcOffset); +#endif +#if HAVE(TM_ZONE) + ret.tm_zone = timeZone.get(); +#endif + + return ret; + } + + void copyFrom(const GregorianDateTime& rhs) + { + second = rhs.second; + minute = rhs.minute; + hour = rhs.hour; + weekDay = rhs.weekDay; + monthDay = rhs.monthDay; + yearDay = rhs.yearDay; + month = rhs.month; + year = rhs.year; + isDST = rhs.isDST; + utcOffset = rhs.utcOffset; + if (rhs.timeZone) { + int inZoneSize = strlen(rhs.timeZone.get()) + 1; + timeZone = adoptArrayPtr(new char[inZoneSize]); + strncpy(timeZone.get(), rhs.timeZone.get(), inZoneSize); + } else + timeZone = nullptr; + } + + int second; + int minute; + int hour; + int weekDay; + int monthDay; + int yearDay; + int month; + int year; + int isDST; + int utcOffset; + OwnArrayPtr timeZone; +}; + +static inline int gmtoffset(const GregorianDateTime& t) +{ + return t.utcOffset; +} + +} // namespace JSC + +#endif // JSDateMath_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSExportMacros.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSExportMacros.h new file mode 100644 index 000000000..884805f86 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSExportMacros.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2011 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. + * + * This file handles shared library symbol export decorations. It is recommended + * that all WebKit projects use these definitions so that symbol exports work + * properly on all platforms and compilers that WebKit builds under. + */ + +#ifndef JSExportMacros_h +#define JSExportMacros_h + +#include +#include + +// See note in wtf/Platform.h for more info on EXPORT_MACROS. +#if USE(EXPORT_MACROS) + +#if defined(BUILDING_JavaScriptCore) +#define JS_EXPORT_PRIVATE WTF_EXPORT +#else +#define JS_EXPORT_PRIVATE WTF_IMPORT +#endif + +#define JS_EXPORT_HIDDEN WTF_HIDDEN +#define JS_EXPORTDATA JS_EXPORT_PRIVATE +#define JS_EXPORTCLASS JS_EXPORT_PRIVATE + +#else // !USE(EXPORT_MACROS) + +#if !PLATFORM(CHROMIUM) && OS(WINDOWS) && !defined(BUILDING_WX__) && !COMPILER(GCC) + +#if defined(BUILDING_JavaScriptCore) +#define JS_EXPORTDATA __declspec(dllexport) +#else +#define JS_EXPORTDATA __declspec(dllimport) +#endif + +#define JS_EXPORTCLASS JS_EXPORTDATA + +#else // !PLATFORM... + +#define JS_EXPORTDATA +#define JS_EXPORTCLASS + +#endif // !PLATFORM... + +#define JS_EXPORT_PRIVATE +#define JS_EXPORT_HIDDEN + +#endif // USE(EXPORT_MACROS) + +#endif // JSExportMacros_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSFunction.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSFunction.h new file mode 100644 index 000000000..b8cfd7157 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSFunction.h @@ -0,0 +1,163 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) + * Copyright (C) 2007 Maks Orlovich + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef JSFunction_h +#define JSFunction_h + +#include "JSObject.h" + +namespace JSC { + + class ExecutableBase; + class FunctionExecutable; + class FunctionPrototype; + class JSActivation; + class JSGlobalObject; + class NativeExecutable; + class SourceCode; + namespace DFG { + class SpeculativeJIT; + class JITCompiler; + } + + JS_EXPORT_PRIVATE EncodedJSValue JSC_HOST_CALL callHostFunctionAsConstructor(ExecState*); + + class JSFunction : public JSNonFinalObject { + friend class JIT; + friend class DFG::SpeculativeJIT; + friend class DFG::JITCompiler; + friend class JSGlobalData; + + public: + typedef JSNonFinalObject Base; + + JS_EXPORT_PRIVATE static JSFunction* create(ExecState*, JSGlobalObject*, int length, const Identifier& name, NativeFunction nativeFunction, NativeFunction nativeConstructor = callHostFunctionAsConstructor); + static JSFunction* create(ExecState*, JSGlobalObject*, int length, const Identifier& name, NativeExecutable* nativeExecutable); + + static JSFunction* create(ExecState* exec, FunctionExecutable* executable, ScopeChainNode* scopeChain) + { + JSFunction* function = new (NotNull, allocateCell(*exec->heap())) JSFunction(exec, executable, scopeChain); + ASSERT(function->structure()->globalObject()); + function->finishCreation(exec, executable, scopeChain); + return function; + } + + static void destroy(JSCell*); + + JS_EXPORT_PRIVATE const UString& name(ExecState*); + const UString displayName(ExecState*); + const UString calculatedDisplayName(ExecState*); + + ScopeChainNode* scope() + { + ASSERT(!isHostFunctionNonInline()); + return m_scopeChain.get(); + } + // This method may be called for host functins, in which case it + // will return an arbitrary value. This should only be used for + // optimized paths in which the return value does not matter for + // host functions, and checking whether the function is a host + // function is deemed too expensive. + ScopeChainNode* scopeUnchecked() + { + return m_scopeChain.get(); + } + void setScope(JSGlobalData& globalData, ScopeChainNode* scopeChain) + { + ASSERT(!isHostFunctionNonInline()); + m_scopeChain.set(globalData, this, scopeChain); + } + + ExecutableBase* executable() const { return m_executable.get(); } + + // To call either of these methods include Executable.h + inline bool isHostFunction() const; + FunctionExecutable* jsExecutable() const; + + JS_EXPORT_PRIVATE const SourceCode* sourceCode() const; + + static JS_EXPORTDATA const ClassInfo s_info; + + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + { + ASSERT(globalObject); + return Structure::create(globalData, globalObject, prototype, TypeInfo(JSFunctionType, StructureFlags), &s_info); + } + + NativeFunction nativeFunction(); + NativeFunction nativeConstructor(); + + static ConstructType getConstructData(JSCell*, ConstructData&); + static CallType getCallData(JSCell*, CallData&); + + static inline size_t offsetOfScopeChain() + { + return OBJECT_OFFSETOF(JSFunction, m_scopeChain); + } + + static inline size_t offsetOfExecutable() + { + return OBJECT_OFFSETOF(JSFunction, m_executable); + } + + protected: + const static unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags; + + JS_EXPORT_PRIVATE JSFunction(ExecState*, JSGlobalObject*, Structure*); + JSFunction(ExecState*, FunctionExecutable*, ScopeChainNode*); + + void finishCreation(ExecState*, NativeExecutable*, int length, const Identifier& name); + void finishCreation(ExecState*, FunctionExecutable*, ScopeChainNode*); + + static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&); + static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); + static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode = ExcludeDontEnumProperties); + + static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); + + static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName); + + static void visitChildren(JSCell*, SlotVisitor&); + + private: + JS_EXPORT_PRIVATE bool isHostFunctionNonInline() const; + + static JSValue argumentsGetter(ExecState*, JSValue, const Identifier&); + static JSValue callerGetter(ExecState*, JSValue, const Identifier&); + static JSValue lengthGetter(ExecState*, JSValue, const Identifier&); + + WriteBarrier m_executable; + WriteBarrier m_scopeChain; + }; + + JSFunction* asFunction(JSValue); + + inline JSFunction* asFunction(JSValue value) + { + ASSERT(asObject(value)->inherits(&JSFunction::s_info)); + return static_cast(asObject(value)); + } + +} // namespace JSC + +#endif // JSFunction_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSGlobalData.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSGlobalData.h new file mode 100644 index 000000000..92817f2a2 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSGlobalData.h @@ -0,0 +1,383 @@ +/* + * Copyright (C) 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 JSGlobalData_h +#define JSGlobalData_h + +#include "CachedTranscendentalFunction.h" +#include "Intrinsic.h" +#include "DateInstanceCache.h" +#include "ExecutableAllocator.h" +#include "Heap.h" +#include "Strong.h" +#include "JITStubs.h" +#include "JSValue.h" +#include "NumericStrings.h" +#include "SmallStrings.h" +#include "Terminator.h" +#include "TimeoutChecker.h" +#include "WeakRandom.h" +#include +#include +#include +#include +#include +#include +#if ENABLE(REGEXP_TRACING) +#include +#endif + +struct OpaqueJSClass; +struct OpaqueJSClassContextData; + +namespace JSC { + + class CodeBlock; + class CommonIdentifiers; + class HandleStack; + class IdentifierTable; + class Interpreter; + class JSGlobalObject; + class JSObject; + class Keywords; + class NativeExecutable; + class ParserArena; + class RegExpCache; + class Stringifier; + class Structure; + class UString; +#if ENABLE(REGEXP_TRACING) + class RegExp; +#endif + + struct HashTable; + struct Instruction; + + struct DSTOffsetCache { + DSTOffsetCache() + { + reset(); + } + + void reset() + { + offset = 0.0; + start = 0.0; + end = -1.0; + increment = 0.0; + } + + double offset; + double start; + double end; + double increment; + }; + + enum ThreadStackType { + ThreadStackTypeLarge, + ThreadStackTypeSmall + }; + + struct TypedArrayDescriptor { + TypedArrayDescriptor() + : m_classInfo(0) + , m_storageOffset(0) + , m_lengthOffset(0) + { + } + TypedArrayDescriptor(const ClassInfo* classInfo, size_t storageOffset, size_t lengthOffset) + : m_classInfo(classInfo) + , m_storageOffset(storageOffset) + , m_lengthOffset(lengthOffset) + { + } + const ClassInfo* m_classInfo; + size_t m_storageOffset; + size_t m_lengthOffset; + }; + + class JSGlobalData : public RefCounted { + public: + // WebCore has a one-to-one mapping of threads to JSGlobalDatas; + // either create() or createLeaked() should only be called once + // on a thread, this is the 'default' JSGlobalData (it uses the + // thread's default string uniquing table from wtfThreadData). + // API contexts created using the new context group aware interface + // create APIContextGroup objects which require less locking of JSC + // than the old singleton APIShared JSGlobalData created for use by + // the original API. + enum GlobalDataType { Default, APIContextGroup, APIShared }; + + struct ClientData { + JS_EXPORT_PRIVATE virtual ~ClientData() = 0; + }; + + bool isSharedInstance() { return globalDataType == APIShared; } + bool usingAPI() { return globalDataType != Default; } + static bool sharedInstanceExists(); + JS_EXPORT_PRIVATE static JSGlobalData& sharedInstance(); + + JS_EXPORT_PRIVATE static PassRefPtr create(ThreadStackType, HeapSize = SmallHeap); + JS_EXPORT_PRIVATE static PassRefPtr createLeaked(ThreadStackType, HeapSize = SmallHeap); + static PassRefPtr createContextGroup(ThreadStackType, HeapSize = SmallHeap); + JS_EXPORT_PRIVATE ~JSGlobalData(); + + void makeUsableFromMultipleThreads() { heap.machineThreads().makeUsableFromMultipleThreads(); } + + GlobalDataType globalDataType; + ClientData* clientData; + CallFrame* topCallFrame; + + const HashTable* arrayConstructorTable; + const HashTable* arrayPrototypeTable; + const HashTable* booleanPrototypeTable; + const HashTable* dateTable; + const HashTable* dateConstructorTable; + const HashTable* errorPrototypeTable; + const HashTable* globalObjectTable; + const HashTable* jsonTable; + const HashTable* mathTable; + const HashTable* numberConstructorTable; + const HashTable* numberPrototypeTable; + const HashTable* objectConstructorTable; + const HashTable* objectPrototypeTable; + const HashTable* regExpTable; + const HashTable* regExpConstructorTable; + const HashTable* regExpPrototypeTable; + const HashTable* stringTable; + const HashTable* stringConstructorTable; + + Strong structureStructure; + Strong debuggerActivationStructure; + Strong activationStructure; + Strong interruptedExecutionErrorStructure; + Strong terminatedExecutionErrorStructure; + Strong staticScopeStructure; + Strong strictEvalActivationStructure; + Strong stringStructure; + Strong notAnObjectStructure; + Strong propertyNameIteratorStructure; + Strong getterSetterStructure; + Strong apiWrapperStructure; + Strong scopeChainNodeStructure; + Strong executableStructure; + Strong nativeExecutableStructure; + Strong evalExecutableStructure; + Strong programExecutableStructure; + Strong functionExecutableStructure; + Strong regExpStructure; + Strong structureChainStructure; + + IdentifierTable* identifierTable; + CommonIdentifiers* propertyNames; + const MarkedArgumentBuffer* emptyList; // Lists are supposed to be allocated on the stack to have their elements properly marked, which is not the case here - but this list has nothing to mark. + SmallStrings smallStrings; + NumericStrings numericStrings; + DateInstanceCache dateInstanceCache; + Vector codeBlocksBeingCompiled; + void startedCompiling(CodeBlock* codeBlock) + { + codeBlocksBeingCompiled.append(codeBlock); + } + + void finishedCompiling(CodeBlock* codeBlock) + { + ASSERT_UNUSED(codeBlock, codeBlock == codeBlocksBeingCompiled.last()); + codeBlocksBeingCompiled.removeLast(); + } + +#if ENABLE(ASSEMBLER) + ExecutableAllocator executableAllocator; +#endif + +#if !ENABLE(JIT) + bool canUseJIT() { return false; } // interpreter only +#elif !ENABLE(INTERPRETER) + bool canUseJIT() { return true; } // jit only +#else + bool canUseJIT() { return m_canUseJIT; } +#endif + + OwnPtr parserArena; + OwnPtr keywords; + Interpreter* interpreter; +#if ENABLE(JIT) + OwnPtr jitStubs; + MacroAssemblerCodeRef getCTIStub(ThunkGenerator generator) + { + return jitStubs->ctiStub(this, generator); + } + NativeExecutable* getHostFunction(NativeFunction, Intrinsic); +#endif + NativeExecutable* getHostFunction(NativeFunction, NativeFunction constructor); + + TimeoutChecker timeoutChecker; + Terminator terminator; + Heap heap; + + JSValue exception; +#if ENABLE(JIT) + ReturnAddressPtr exceptionLocation; + JSValue hostCallReturnValue; + CallFrame* callFrameForThrow; + void* targetMachinePCForThrow; + Instruction* targetInterpreterPCForThrow; +#if ENABLE(DFG_JIT) + uint32_t osrExitIndex; + void* osrExitJumpDestination; + Vector scratchBuffers; + size_t sizeOfLastScratchBuffer; + + void* scratchBufferForSize(size_t size) + { + if (!size) + return 0; + + if (size > sizeOfLastScratchBuffer) { + // Protect against a N^2 memory usage pathology by ensuring + // that at worst, we get a geometric series, meaning that the + // total memory usage is somewhere around + // max(scratch buffer size) * 4. + sizeOfLastScratchBuffer = size * 2; + + scratchBuffers.append(fastMalloc(sizeOfLastScratchBuffer)); + } + + return scratchBuffers.last(); + } +#endif +#endif + + HashMap > opaqueJSClassData; + + JSGlobalObject* dynamicGlobalObject; + + HashSet stringRecursionCheckVisitedObjects; + + double cachedUTCOffset; + DSTOffsetCache dstOffsetCache; + + UString cachedDateString; + double cachedDateStringValue; + + int maxReentryDepth; + + RegExpCache* m_regExpCache; + BumpPointerAllocator m_regExpAllocator; + +#if ENABLE(REGEXP_TRACING) + typedef ListHashSet > RTTraceList; + RTTraceList* m_rtTraceList; +#endif + +#ifndef NDEBUG + ThreadIdentifier exclusiveThread; +#endif + + CachedTranscendentalFunction cachedSin; + + JS_EXPORT_PRIVATE void resetDateCache(); + + JS_EXPORT_PRIVATE void startSampling(); + JS_EXPORT_PRIVATE void stopSampling(); + JS_EXPORT_PRIVATE void dumpSampleData(ExecState* exec); + void recompileAllJSFunctions(); + RegExpCache* regExpCache() { return m_regExpCache; } +#if ENABLE(REGEXP_TRACING) + void addRegExpToTrace(PassRefPtr regExp); +#endif + JS_EXPORT_PRIVATE void dumpRegExpTrace(); + JS_EXPORT_PRIVATE void clearBuiltinStructures(); + + bool isCollectorBusy() { return heap.isBusy(); } + JS_EXPORT_PRIVATE void releaseExecutableMemory(); + +#if ENABLE(GC_VALIDATION) + bool isInitializingObject() const; + void setInitializingObject(bool); +#endif + +#if CPU(X86) && ENABLE(JIT) + unsigned m_timeoutCount; +#endif + +#define registerTypedArrayFunction(type, capitalizedType) \ + void registerTypedArrayDescriptor(const capitalizedType##Array*, const TypedArrayDescriptor& descriptor) \ + { \ + ASSERT(!m_##type##ArrayDescriptor.m_classInfo || m_##type##ArrayDescriptor.m_classInfo == descriptor.m_classInfo); \ + m_##type##ArrayDescriptor = descriptor; \ + } \ + const TypedArrayDescriptor& type##ArrayDescriptor() const { return m_##type##ArrayDescriptor; } + + registerTypedArrayFunction(int8, Int8); + registerTypedArrayFunction(int16, Int16); + registerTypedArrayFunction(int32, Int32); + registerTypedArrayFunction(uint8, Uint8); + registerTypedArrayFunction(uint8Clamped, Uint8Clamped); + registerTypedArrayFunction(uint16, Uint16); + registerTypedArrayFunction(uint32, Uint32); + registerTypedArrayFunction(float32, Float32); + registerTypedArrayFunction(float64, Float64); +#undef registerTypedArrayFunction + + private: + JSGlobalData(GlobalDataType, ThreadStackType, HeapSize); + static JSGlobalData*& sharedInstanceInternal(); + void createNativeThunk(); +#if ENABLE(JIT) && ENABLE(INTERPRETER) + bool m_canUseJIT; +#endif +#if ENABLE(GC_VALIDATION) + bool m_isInitializingObject; +#endif + TypedArrayDescriptor m_int8ArrayDescriptor; + TypedArrayDescriptor m_int16ArrayDescriptor; + TypedArrayDescriptor m_int32ArrayDescriptor; + TypedArrayDescriptor m_uint8ArrayDescriptor; + TypedArrayDescriptor m_uint8ClampedArrayDescriptor; + TypedArrayDescriptor m_uint16ArrayDescriptor; + TypedArrayDescriptor m_uint32ArrayDescriptor; + TypedArrayDescriptor m_float32ArrayDescriptor; + TypedArrayDescriptor m_float64ArrayDescriptor; + }; + +#if ENABLE(GC_VALIDATION) + inline bool JSGlobalData::isInitializingObject() const + { + return m_isInitializingObject; + } + + inline void JSGlobalData::setInitializingObject(bool initializingObject) + { + m_isInitializingObject = initializingObject; + } +#endif + +} // namespace JSC + +#endif // JSGlobalData_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSGlobalObject.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSGlobalObject.h new file mode 100644 index 000000000..70368307d --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSGlobalObject.h @@ -0,0 +1,510 @@ +/* + * Copyright (C) 2007 Eric Seidel + * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef JSGlobalObject_h +#define JSGlobalObject_h + +#include "JSArray.h" +#include "JSGlobalData.h" +#include "JSGlobalThis.h" +#include "JSVariableObject.h" +#include "JSWeakObjectMapRefInternal.h" +#include "NumberPrototype.h" +#include "StringPrototype.h" +#include "StructureChain.h" +#include +#include +#include + +namespace JSC { + + class ArrayPrototype; + class BooleanPrototype; + class DatePrototype; + class Debugger; + class ErrorConstructor; + class FunctionPrototype; + class GetterSetter; + class GlobalCodeBlock; + class NativeErrorConstructor; + class ProgramCodeBlock; + class RegExpConstructor; + class RegExpPrototype; + class RegisterFile; + + struct ActivationStackNode; + struct HashTable; + + typedef Vector ExecStateStack; + + struct GlobalObjectMethodTable { + typedef bool (*SupportsProfilingFunctionPtr)(const JSGlobalObject*); + SupportsProfilingFunctionPtr supportsProfiling; + + typedef bool (*SupportsRichSourceInfoFunctionPtr)(const JSGlobalObject*); + SupportsRichSourceInfoFunctionPtr supportsRichSourceInfo; + + typedef bool (*ShouldInterruptScriptFunctionPtr)(const JSGlobalObject*); + ShouldInterruptScriptFunctionPtr shouldInterruptScript; + }; + + class JSGlobalObject : public JSVariableObject { + private: + typedef HashSet > WeakMapSet; + + struct JSGlobalObjectRareData { + JSGlobalObjectRareData() + : profileGroup(0) + { + } + + WeakMapSet weakMaps; + unsigned profileGroup; + }; + + protected: + + RefPtr m_globalData; + + size_t m_registerArraySize; + Register m_globalCallFrame[RegisterFile::CallFrameHeaderSize]; + + WriteBarrier m_globalScopeChain; + WriteBarrier m_methodCallDummy; + + WriteBarrier m_regExpConstructor; + WriteBarrier m_errorConstructor; + WriteBarrier m_evalErrorConstructor; + WriteBarrier m_rangeErrorConstructor; + WriteBarrier m_referenceErrorConstructor; + WriteBarrier m_syntaxErrorConstructor; + WriteBarrier m_typeErrorConstructor; + WriteBarrier m_URIErrorConstructor; + + WriteBarrier m_evalFunction; + WriteBarrier m_callFunction; + WriteBarrier m_applyFunction; + WriteBarrier m_throwTypeErrorGetterSetter; + + WriteBarrier m_objectPrototype; + WriteBarrier m_functionPrototype; + WriteBarrier m_arrayPrototype; + WriteBarrier m_booleanPrototype; + WriteBarrier m_stringPrototype; + WriteBarrier m_numberPrototype; + WriteBarrier m_datePrototype; + WriteBarrier m_regExpPrototype; + + WriteBarrier m_argumentsStructure; + WriteBarrier m_arrayStructure; + WriteBarrier m_booleanObjectStructure; + WriteBarrier m_callbackConstructorStructure; + WriteBarrier m_callbackFunctionStructure; + WriteBarrier m_callbackObjectStructure; + WriteBarrier m_dateStructure; + WriteBarrier m_emptyObjectStructure; + WriteBarrier m_nullPrototypeObjectStructure; + WriteBarrier m_errorStructure; + WriteBarrier m_functionStructure; + WriteBarrier m_boundFunctionStructure; + WriteBarrier m_namedFunctionStructure; + size_t m_functionNameOffset; + WriteBarrier m_numberObjectStructure; + WriteBarrier m_regExpMatchesArrayStructure; + WriteBarrier m_regExpStructure; + WriteBarrier m_stringObjectStructure; + WriteBarrier m_internalFunctionStructure; + + Debugger* m_debugger; + + OwnPtr m_rareData; + + WeakRandom m_weakRandom; + + SymbolTable m_symbolTable; + + bool m_evalEnabled; + + static JS_EXPORTDATA const GlobalObjectMethodTable s_globalObjectMethodTable; + const GlobalObjectMethodTable* m_globalObjectMethodTable; + + void createRareDataIfNeeded() + { + if (m_rareData) + return; + m_rareData = adoptPtr(new JSGlobalObjectRareData); + Heap::heap(this)->addFinalizer(this, clearRareData); + } + + public: + typedef JSVariableObject Base; + + static JSGlobalObject* create(JSGlobalData& globalData, Structure* structure) + { + JSGlobalObject* globalObject = new (NotNull, allocateCell(globalData.heap)) JSGlobalObject(globalData, structure); + globalObject->finishCreation(globalData); + return globalObject; + } + + static JS_EXPORTDATA const ClassInfo s_info; + + protected: + explicit JSGlobalObject(JSGlobalData& globalData, Structure* structure, const GlobalObjectMethodTable* globalObjectMethodTable = 0) + : JSVariableObject(globalData, structure, &m_symbolTable, 0) + , m_registerArraySize(0) + , m_globalScopeChain() + , m_weakRandom(static_cast(randomNumber() * (std::numeric_limits::max() + 1.0))) + , m_evalEnabled(true) + , m_globalObjectMethodTable(globalObjectMethodTable ? globalObjectMethodTable : &s_globalObjectMethodTable) + { + } + + void finishCreation(JSGlobalData& globalData) + { + Base::finishCreation(globalData); + structure()->setGlobalObject(globalData, this); + init(this); + } + + void finishCreation(JSGlobalData& globalData, JSGlobalThis* thisValue) + { + Base::finishCreation(globalData); + structure()->setGlobalObject(globalData, this); + init(thisValue); + } + + public: + JS_EXPORT_PRIVATE ~JSGlobalObject(); + JS_EXPORT_PRIVATE static void destroy(JSCell*); + + JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&); + + JS_EXPORT_PRIVATE static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&); + JS_EXPORT_PRIVATE static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); + bool hasOwnPropertyForWrite(ExecState*, const Identifier&); + JS_EXPORT_PRIVATE static void put(JSCell*, ExecState*, const Identifier&, JSValue, PutPropertySlot&); + + JS_EXPORT_PRIVATE static void putDirectVirtual(JSObject*, ExecState*, const Identifier& propertyName, JSValue, unsigned attributes); + + JS_EXPORT_PRIVATE static void defineGetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* getterFunc, unsigned attributes); + JS_EXPORT_PRIVATE static void defineSetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* setterFunc, unsigned attributes); + + // We use this in the code generator as we perform symbol table + // lookups prior to initializing the properties + bool symbolTableHasProperty(const Identifier& propertyName); + + // The following accessors return pristine values, even if a script + // replaces the global object's associated property. + + RegExpConstructor* regExpConstructor() const { return m_regExpConstructor.get(); } + + ErrorConstructor* errorConstructor() const { return m_errorConstructor.get(); } + NativeErrorConstructor* evalErrorConstructor() const { return m_evalErrorConstructor.get(); } + NativeErrorConstructor* rangeErrorConstructor() const { return m_rangeErrorConstructor.get(); } + NativeErrorConstructor* referenceErrorConstructor() const { return m_referenceErrorConstructor.get(); } + NativeErrorConstructor* syntaxErrorConstructor() const { return m_syntaxErrorConstructor.get(); } + NativeErrorConstructor* typeErrorConstructor() const { return m_typeErrorConstructor.get(); } + NativeErrorConstructor* URIErrorConstructor() const { return m_URIErrorConstructor.get(); } + + JSFunction* evalFunction() const { return m_evalFunction.get(); } + JSFunction* callFunction() const { return m_callFunction.get(); } + JSFunction* applyFunction() const { return m_applyFunction.get(); } + GetterSetter* throwTypeErrorGetterSetter(ExecState* exec) + { + if (!m_throwTypeErrorGetterSetter) + createThrowTypeError(exec); + return m_throwTypeErrorGetterSetter.get(); + } + + ObjectPrototype* objectPrototype() const { return m_objectPrototype.get(); } + FunctionPrototype* functionPrototype() const { return m_functionPrototype.get(); } + ArrayPrototype* arrayPrototype() const { return m_arrayPrototype.get(); } + BooleanPrototype* booleanPrototype() const { return m_booleanPrototype.get(); } + StringPrototype* stringPrototype() const { return m_stringPrototype.get(); } + NumberPrototype* numberPrototype() const { return m_numberPrototype.get(); } + DatePrototype* datePrototype() const { return m_datePrototype.get(); } + RegExpPrototype* regExpPrototype() const { return m_regExpPrototype.get(); } + + JSObject* methodCallDummy() const { return m_methodCallDummy.get(); } + + Structure* argumentsStructure() const { return m_argumentsStructure.get(); } + Structure* arrayStructure() const { return m_arrayStructure.get(); } + Structure* booleanObjectStructure() const { return m_booleanObjectStructure.get(); } + Structure* callbackConstructorStructure() const { return m_callbackConstructorStructure.get(); } + Structure* callbackFunctionStructure() const { return m_callbackFunctionStructure.get(); } + Structure* callbackObjectStructure() const { return m_callbackObjectStructure.get(); } + Structure* dateStructure() const { return m_dateStructure.get(); } + Structure* emptyObjectStructure() const { return m_emptyObjectStructure.get(); } + Structure* nullPrototypeObjectStructure() const { return m_nullPrototypeObjectStructure.get(); } + Structure* errorStructure() const { return m_errorStructure.get(); } + Structure* functionStructure() const { return m_functionStructure.get(); } + Structure* boundFunctionStructure() const { return m_boundFunctionStructure.get(); } + Structure* namedFunctionStructure() const { return m_namedFunctionStructure.get(); } + size_t functionNameOffset() const { return m_functionNameOffset; } + Structure* numberObjectStructure() const { return m_numberObjectStructure.get(); } + Structure* internalFunctionStructure() const { return m_internalFunctionStructure.get(); } + Structure* regExpMatchesArrayStructure() const { return m_regExpMatchesArrayStructure.get(); } + Structure* regExpStructure() const { return m_regExpStructure.get(); } + Structure* stringObjectStructure() const { return m_stringObjectStructure.get(); } + + void setProfileGroup(unsigned value) { createRareDataIfNeeded(); m_rareData->profileGroup = value; } + unsigned profileGroup() const + { + if (!m_rareData) + return 0; + return m_rareData->profileGroup; + } + + Debugger* debugger() const { return m_debugger; } + void setDebugger(Debugger* debugger) { m_debugger = debugger; } + + const GlobalObjectMethodTable* globalObjectMethodTable() const { return m_globalObjectMethodTable; } + + static bool supportsProfiling(const JSGlobalObject*) { return false; } + static bool supportsRichSourceInfo(const JSGlobalObject*) { return true; } + + ScopeChainNode* globalScopeChain() { return m_globalScopeChain.get(); } + + JS_EXPORT_PRIVATE ExecState* globalExec(); + + static bool shouldInterruptScript(const JSGlobalObject*) { return true; } + + bool isDynamicScope(bool& requiresDynamicChecks) const; + + void setEvalEnabled(bool enabled) { m_evalEnabled = enabled; } + bool evalEnabled() { return m_evalEnabled; } + + void resizeRegisters(size_t newSize); + + void resetPrototype(JSGlobalData&, JSValue prototype); + + JSGlobalData& globalData() const { return *m_globalData.get(); } + + static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) + { + return Structure::create(globalData, 0, prototype, TypeInfo(GlobalObjectType, StructureFlags), &s_info); + } + + void registerWeakMap(OpaqueJSWeakObjectMap* map) + { + createRareDataIfNeeded(); + m_rareData->weakMaps.add(map); + } + + void unregisterWeakMap(OpaqueJSWeakObjectMap* map) + { + if (m_rareData) + m_rareData->weakMaps.remove(map); + } + + double weakRandomNumber() { return m_weakRandom.get(); } + protected: + + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags; + + struct GlobalPropertyInfo { + GlobalPropertyInfo(const Identifier& i, JSValue v, unsigned a) + : identifier(i) + , value(v) + , attributes(a) + { + } + + const Identifier identifier; + JSValue value; + unsigned attributes; + }; + JS_EXPORT_PRIVATE void addStaticGlobals(GlobalPropertyInfo*, int count); + + private: + // FIXME: Fold reset into init. + JS_EXPORT_PRIVATE void init(JSObject* thisValue); + void reset(JSValue prototype); + + void createThrowTypeError(ExecState*); + + void setRegisters(WriteBarrier* registers, PassOwnArrayPtr > registerArray, size_t count); + JS_EXPORT_PRIVATE static void clearRareData(JSCell*); + }; + + JSGlobalObject* asGlobalObject(JSValue); + + inline JSGlobalObject* asGlobalObject(JSValue value) + { + ASSERT(asObject(value)->isGlobalObject()); + return static_cast(asObject(value)); + } + + inline void JSGlobalObject::setRegisters(WriteBarrier* registers, PassOwnArrayPtr > registerArray, size_t count) + { + JSVariableObject::setRegisters(registers, registerArray); + m_registerArraySize = count; + } + + inline bool JSGlobalObject::hasOwnPropertyForWrite(ExecState* exec, const Identifier& propertyName) + { + PropertySlot slot; + if (JSVariableObject::getOwnPropertySlot(this, exec, propertyName, slot)) + return true; + bool slotIsWriteable; + return symbolTableGet(propertyName, slot, slotIsWriteable); + } + + inline bool JSGlobalObject::symbolTableHasProperty(const Identifier& propertyName) + { + SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl()); + return !entry.isNull(); + } + + inline JSValue Structure::prototypeForLookup(ExecState* exec) const + { + if (isObject()) + return m_prototype.get(); + + ASSERT(typeInfo().type() == StringType); + return exec->lexicalGlobalObject()->stringPrototype(); + } + + inline StructureChain* Structure::prototypeChain(ExecState* exec) const + { + // We cache our prototype chain so our clients can share it. + if (!isValid(exec, m_cachedPrototypeChain.get())) { + JSValue prototype = prototypeForLookup(exec); + m_cachedPrototypeChain.set(exec->globalData(), this, StructureChain::create(exec->globalData(), prototype.isNull() ? 0 : asObject(prototype)->structure())); + } + return m_cachedPrototypeChain.get(); + } + + inline bool Structure::isValid(ExecState* exec, StructureChain* cachedPrototypeChain) const + { + if (!cachedPrototypeChain) + return false; + + JSValue prototype = prototypeForLookup(exec); + WriteBarrier* cachedStructure = cachedPrototypeChain->head(); + while(*cachedStructure && !prototype.isNull()) { + if (asObject(prototype)->structure() != cachedStructure->get()) + return false; + ++cachedStructure; + prototype = asObject(prototype)->prototype(); + } + return prototype.isNull() && !*cachedStructure; + } + + inline JSGlobalObject* ExecState::dynamicGlobalObject() + { + if (this == lexicalGlobalObject()->globalExec()) + return lexicalGlobalObject(); + + // For any ExecState that's not a globalExec, the + // dynamic global object must be set since code is running + ASSERT(globalData().dynamicGlobalObject); + return globalData().dynamicGlobalObject; + } + + inline JSObject* constructEmptyObject(ExecState* exec, JSGlobalObject* globalObject) + { + return constructEmptyObject(exec, globalObject->emptyObjectStructure()); + } + + inline JSObject* constructEmptyObject(ExecState* exec) + { + return constructEmptyObject(exec, exec->lexicalGlobalObject()); + } + + inline JSArray* constructEmptyArray(ExecState* exec, JSGlobalObject* globalObject, unsigned initialLength = 0) + { + return JSArray::create(exec->globalData(), globalObject->arrayStructure(), initialLength); + } + + inline JSArray* constructEmptyArray(ExecState* exec, unsigned initialLength = 0) + { + return constructEmptyArray(exec, exec->lexicalGlobalObject(), initialLength); + } + + inline JSArray* constructArray(ExecState* exec, JSGlobalObject* globalObject, const ArgList& values) + { + JSGlobalData& globalData = exec->globalData(); + unsigned length = values.size(); + JSArray* array = JSArray::tryCreateUninitialized(globalData, globalObject->arrayStructure(), length); + + // FIXME: we should probably throw an out of memory error here, but + // when making this change we should check that all clients of this + // function will correctly handle an exception being thrown from here. + if (!array) + CRASH(); + + for (unsigned i = 0; i < length; ++i) + array->initializeIndex(globalData, i, values.at(i)); + array->completeInitialization(length); + return array; + } + + inline JSArray* constructArray(ExecState* exec, const ArgList& values) + { + return constructArray(exec, exec->lexicalGlobalObject(), values); + } + + inline JSArray* constructArray(ExecState* exec, JSGlobalObject* globalObject, const JSValue* values, unsigned length) + { + JSGlobalData& globalData = exec->globalData(); + JSArray* array = JSArray::tryCreateUninitialized(globalData, globalObject->arrayStructure(), length); + + // FIXME: we should probably throw an out of memory error here, but + // when making this change we should check that all clients of this + // function will correctly handle an exception being thrown from here. + if (!array) + CRASH(); + + for (unsigned i = 0; i < length; ++i) + array->initializeIndex(globalData, i, values[i]); + array->completeInitialization(length); + return array; + } + + inline JSArray* constructArray(ExecState* exec, const JSValue* values, unsigned length) + { + return constructArray(exec, exec->lexicalGlobalObject(), values, length); + } + + class DynamicGlobalObjectScope { + WTF_MAKE_NONCOPYABLE(DynamicGlobalObjectScope); + public: + JS_EXPORT_PRIVATE DynamicGlobalObjectScope(JSGlobalData&, JSGlobalObject*); + + ~DynamicGlobalObjectScope() + { + m_dynamicGlobalObjectSlot = m_savedDynamicGlobalObject; + } + + private: + JSGlobalObject*& m_dynamicGlobalObjectSlot; + JSGlobalObject* m_savedDynamicGlobalObject; + }; + + inline bool JSGlobalObject::isDynamicScope(bool&) const + { + return true; + } + +} // namespace JSC + +#endif // JSGlobalObject_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSGlobalThis.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSGlobalThis.h new file mode 100644 index 000000000..fa5c2eb34 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSGlobalThis.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2011 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 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 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 JSGlobalThis_h +#define JSGlobalThis_h + +#include "JSObject.h" + +namespace JSC { + +class JSGlobalThis : public JSNonFinalObject { +public: + typedef JSNonFinalObject Base; + + static JSGlobalThis* create(JSGlobalData& globalData, Structure* structure) + { + JSGlobalThis* globalThis = new (NotNull, allocateCell(globalData.heap)) JSGlobalThis(globalData, structure); + globalThis->finishCreation(globalData); + return globalThis; + } + + static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) + { + return Structure::create(globalData, 0, prototype, TypeInfo(GlobalThisType, StructureFlags), &s_info); + } + + static JS_EXPORTDATA const JSC::ClassInfo s_info; + + JSGlobalObject* unwrappedObject(); + +protected: + JSGlobalThis(JSGlobalData& globalData, Structure* structure) + : JSNonFinalObject(globalData, structure) + { + } + + void finishCreation(JSGlobalData& globalData) + { + Base::finishCreation(globalData); + } + + static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags; + + JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&); + + WriteBarrier m_unwrappedObject; +}; + +} // namespace JSC + +#endif // JSGlobalThis_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSLock.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSLock.h new file mode 100644 index 000000000..a0eb96975 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSLock.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2005, 2008, 2009 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef JSLock_h +#define JSLock_h + +#include +#include + +namespace JSC { + + // To make it safe to use JavaScript on multiple threads, it is + // important to lock before doing anything that allocates a + // JavaScript data structure or that interacts with shared state + // such as the protect count hash table. The simplest way to lock + // is to create a local JSLock object in the scope where the lock + // must be held. The lock is recursive so nesting is ok. The JSLock + // object also acts as a convenience short-hand for running important + // initialization routines. + + // To avoid deadlock, sometimes it is necessary to temporarily + // release the lock. Since it is recursive you actually have to + // release all locks held by your thread. This is safe to do if + // you are executing code that doesn't require the lock, and you + // reacquire the right number of locks at the end. You can do this + // by constructing a locally scoped JSLock::DropAllLocks object. The + // DropAllLocks object takes care to release the JSLock only if your + // thread acquired it to begin with. + + // For contexts other than the single shared one, implicit locking is not done, + // but we still need to perform all the counting in order to keep debug + // assertions working, so that clients that use the shared context don't break. + + class ExecState; + class JSGlobalData; + + enum JSLockBehavior { SilenceAssertionsOnly, LockForReal }; + + class JSLock { + WTF_MAKE_NONCOPYABLE(JSLock); + public: + JS_EXPORT_PRIVATE JSLock(ExecState*); + JSLock(JSGlobalData*); + + JSLock(JSLockBehavior lockBehavior) + : m_lockBehavior(lockBehavior) + { +#ifdef NDEBUG + // Locking "not for real" is a debug-only feature. + if (lockBehavior == SilenceAssertionsOnly) + return; +#endif + lock(lockBehavior); + } + + ~JSLock() + { +#ifdef NDEBUG + // Locking "not for real" is a debug-only feature. + if (m_lockBehavior == SilenceAssertionsOnly) + return; +#endif + unlock(m_lockBehavior); + } + + JS_EXPORT_PRIVATE static void lock(JSLockBehavior); + JS_EXPORT_PRIVATE static void unlock(JSLockBehavior); + static void lock(ExecState*); + static void unlock(ExecState*); + + JS_EXPORT_PRIVATE static intptr_t lockCount(); + JS_EXPORT_PRIVATE static bool currentThreadIsHoldingLock(); + + JSLockBehavior m_lockBehavior; + + class DropAllLocks { + WTF_MAKE_NONCOPYABLE(DropAllLocks); + public: + JS_EXPORT_PRIVATE DropAllLocks(ExecState* exec); + JS_EXPORT_PRIVATE DropAllLocks(JSLockBehavior); + JS_EXPORT_PRIVATE ~DropAllLocks(); + + private: + intptr_t m_lockCount; + JSLockBehavior m_lockBehavior; + }; + }; + +} // namespace + +#endif // JSLock_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSObject.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSObject.h new file mode 100644 index 000000000..356135d04 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSObject.h @@ -0,0 +1,884 @@ +/* + * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) + * Copyright (C) 2001 Peter Kelly (pmk@post.com) + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef JSObject_h +#define JSObject_h + +#include "ArgList.h" +#include "ClassInfo.h" +#include "CommonIdentifiers.h" +#include "CallFrame.h" +#include "JSCell.h" +#include "PropertySlot.h" +#include "PutPropertySlot.h" +#include "ScopeChain.h" +#include "StorageBarrier.h" +#include "Structure.h" +#include "JSGlobalData.h" +#include "JSString.h" +#include + +namespace JSC { + + inline JSCell* getJSFunction(JSValue value) + { + if (value.isCell() && (value.asCell()->structure()->typeInfo().type() == JSFunctionType)) + return value.asCell(); + return 0; + } + + class GetterSetter; + class HashEntry; + class InternalFunction; + class MarkedBlock; + class PropertyDescriptor; + class PropertyNameArray; + class Structure; + struct HashTable; + + JS_EXPORT_PRIVATE JSObject* throwTypeError(ExecState*, const UString&); + extern JS_EXPORTDATA const char* StrictModeReadonlyPropertyWriteError; + + // ECMA 262-3 8.6.1 + // Property attributes + enum Attribute { + None = 0, + ReadOnly = 1 << 1, // property can be only read, not written + DontEnum = 1 << 2, // property doesn't appear in (for .. in ..) + DontDelete = 1 << 3, // property can't be deleted + Function = 1 << 4, // property is a function - only used by static hashtables + Accessor = 1 << 5, // property is a getter/setter + }; + + class JSObject : public JSCell { + friend class BatchedTransitionOptimizer; + friend class JIT; + friend class JSCell; + friend class MarkedBlock; + JS_EXPORT_PRIVATE friend bool setUpStaticFunctionSlot(ExecState* exec, const HashEntry* entry, JSObject* thisObj, const Identifier& propertyName, PropertySlot& slot); + + enum PutMode { + PutModePut, + PutModeDefineOwnProperty, + }; + + public: + typedef JSCell Base; + + JS_EXPORT_PRIVATE static void destroy(JSCell*); + + JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&); + + JS_EXPORT_PRIVATE static UString className(const JSObject*); + + JSValue prototype() const; + void setPrototype(JSGlobalData&, JSValue prototype); + bool setPrototypeWithCycleCheck(JSGlobalData&, JSValue prototype); + + Structure* inheritorID(JSGlobalData&); + + JSValue get(ExecState*, const Identifier& propertyName) const; + JSValue get(ExecState*, unsigned propertyName) const; + + bool getPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); + bool getPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); + JS_EXPORT_PRIVATE bool getPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor&); + + static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier& propertyName, PropertySlot&); + JS_EXPORT_PRIVATE static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&); + JS_EXPORT_PRIVATE static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); + + JS_EXPORT_PRIVATE static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); + JS_EXPORT_PRIVATE static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue); + + // putDirect is effectively an unchecked vesion of 'defineOwnProperty': + // - the prototype chain is not consulted + // - accessors are not called. + // - attributes will be respected (after the call the property will exist with the given attributes) + JS_EXPORT_PRIVATE static void putDirectVirtual(JSObject*, ExecState*, const Identifier& propertyName, JSValue, unsigned attributes); + void putDirect(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attributes = 0); + void putDirect(JSGlobalData&, const Identifier& propertyName, JSValue, PutPropertySlot&); + void putDirectWithoutTransition(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attributes = 0); + + bool propertyIsEnumerable(ExecState*, const Identifier& propertyName) const; + + JS_EXPORT_PRIVATE bool hasProperty(ExecState*, const Identifier& propertyName) const; + JS_EXPORT_PRIVATE bool hasProperty(ExecState*, unsigned propertyName) const; + bool hasOwnProperty(ExecState*, const Identifier& propertyName) const; + + JS_EXPORT_PRIVATE static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName); + JS_EXPORT_PRIVATE static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName); + + JS_EXPORT_PRIVATE static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType); + + JS_EXPORT_PRIVATE static bool hasInstance(JSObject*, ExecState*, JSValue, JSValue prototypeProperty); + + JS_EXPORT_PRIVATE static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); + JS_EXPORT_PRIVATE static void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); + + JSValue toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const; + JS_EXPORT_PRIVATE bool toBoolean(ExecState*) const; + bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const; + JS_EXPORT_PRIVATE double toNumber(ExecState*) const; + JS_EXPORT_PRIVATE JSString* toString(ExecState*) const; + + // NOTE: JSObject and its subclasses must be able to gracefully handle ExecState* = 0, + // because this call may come from inside the compiler. + JS_EXPORT_PRIVATE static JSObject* toThisObject(JSCell*, ExecState*); + JSObject* unwrappedObject(); + + bool getPropertySpecificValue(ExecState* exec, const Identifier& propertyName, JSCell*& specificFunction) const; + + // This get function only looks at the property map. + JSValue getDirect(JSGlobalData& globalData, const Identifier& propertyName) const + { + size_t offset = structure()->get(globalData, propertyName); + return offset != WTF::notFound ? getDirectOffset(offset) : JSValue(); + } + + WriteBarrierBase* getDirectLocation(JSGlobalData& globalData, const Identifier& propertyName) + { + size_t offset = structure()->get(globalData, propertyName); + return offset != WTF::notFound ? locationForOffset(offset) : 0; + } + + WriteBarrierBase* getDirectLocation(JSGlobalData& globalData, const Identifier& propertyName, unsigned& attributes) + { + JSCell* specificFunction; + size_t offset = structure()->get(globalData, propertyName, attributes, specificFunction); + return offset != WTF::notFound ? locationForOffset(offset) : 0; + } + + size_t offsetForLocation(WriteBarrierBase* location) const + { + return location - propertyStorage(); + } + + void transitionTo(JSGlobalData&, Structure*); + + void removeDirect(JSGlobalData&, const Identifier& propertyName); + bool hasCustomProperties() { return structure()->didTransition(); } + bool hasGetterSetterProperties() { return structure()->hasGetterSetterProperties(); } + + // putOwnDataProperty has 'put' like semantics, however this method: + // - assumes the object contains no own getter/setter properties. + // - provides no special handling for __proto__ + // - does not walk the prototype chain (to check for accessors or non-writable properties). + // This is used by JSActivation. + bool putOwnDataProperty(JSGlobalData&, const Identifier& propertyName, JSValue, PutPropertySlot&); + + // Fast access to known property offsets. + JSValue getDirectOffset(size_t offset) const { return propertyStorage()[offset].get(); } + void putDirectOffset(JSGlobalData& globalData, size_t offset, JSValue value) { propertyStorage()[offset].set(globalData, this, value); } + void putUndefinedAtDirectOffset(size_t offset) { propertyStorage()[offset].setUndefined(); } + + JS_EXPORT_PRIVATE void fillGetterPropertySlot(PropertySlot&, WriteBarrierBase* location); + void initializeGetterSetterProperty(ExecState*, const Identifier&, GetterSetter*, unsigned attributes); + + JS_EXPORT_PRIVATE static void defineGetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes = 0); + JS_EXPORT_PRIVATE static void defineSetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes = 0); + JS_EXPORT_PRIVATE JSValue lookupGetter(ExecState*, const Identifier& propertyName); + JS_EXPORT_PRIVATE JSValue lookupSetter(ExecState*, const Identifier& propertyName); + JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow); + + bool isGlobalObject() const; + bool isVariableObject() const; + bool isActivationObject() const; + bool isErrorInstance() const; + bool isGlobalThis() const; + + void seal(JSGlobalData&); + void freeze(JSGlobalData&); + JS_EXPORT_PRIVATE void preventExtensions(JSGlobalData&); + bool isSealed(JSGlobalData& globalData) { return structure()->isSealed(globalData); } + bool isFrozen(JSGlobalData& globalData) { return structure()->isFrozen(globalData); } + bool isExtensible() { return structure()->isExtensible(); } + + bool staticFunctionsReified() { return structure()->staticFunctionsReified(); } + void reifyStaticFunctionsForDelete(ExecState* exec); + + JS_EXPORT_PRIVATE void allocatePropertyStorage(JSGlobalData&, size_t oldSize, size_t newSize); + bool isUsingInlineStorage() const { return static_cast(m_propertyStorage.get()) == static_cast(this + 1); } + + void* addressOfPropertyStorage() + { + return &m_propertyStorage; + } + + static const unsigned baseExternalStorageCapacity = 16; + + void flattenDictionaryObject(JSGlobalData& globalData) + { + structure()->flattenDictionaryStructure(globalData, this); + } + + JSGlobalObject* globalObject() const + { + ASSERT(structure()->globalObject()); + ASSERT(!isGlobalObject() || ((JSObject*)structure()->globalObject()) == this); + return structure()->globalObject(); + } + + static size_t offsetOfInlineStorage(); + static size_t offsetOfPropertyStorage(); + static size_t offsetOfInheritorID(); + + static JS_EXPORTDATA const ClassInfo s_info; + + protected: + void finishCreation(JSGlobalData& globalData, PropertyStorage inlineStorage) + { + Base::finishCreation(globalData); + ASSERT(inherits(&s_info)); + ASSERT(structure()->propertyStorageCapacity() < baseExternalStorageCapacity); + ASSERT(structure()->isEmpty()); + ASSERT(prototype().isNull() || Heap::heap(this) == Heap::heap(prototype())); + ASSERT_UNUSED(inlineStorage, static_cast(inlineStorage) == static_cast(this + 1)); + ASSERT(structure()->isObject()); + ASSERT(classInfo()); + } + + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + { + return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); + } + + static const unsigned StructureFlags = 0; + + // To instantiate objects you likely want JSFinalObject, below. + // To create derived types you likely want JSNonFinalObject, below. + JSObject(JSGlobalData&, Structure*, PropertyStorage inlineStorage); + + private: + // Nobody should ever ask any of these questions on something already known to be a JSObject. + using JSCell::isAPIValueWrapper; + using JSCell::isGetterSetter; + void getObject(); + void getString(ExecState* exec); + void isObject(); + void isString(); + + ConstPropertyStorage propertyStorage() const { return m_propertyStorage.get(); } + PropertyStorage propertyStorage() { return m_propertyStorage.get(); } + + const WriteBarrierBase* locationForOffset(size_t offset) const + { + return &propertyStorage()[offset]; + } + + WriteBarrierBase* locationForOffset(size_t offset) + { + return &propertyStorage()[offset]; + } + + template + bool putDirectInternal(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attr, PutPropertySlot&, JSCell*); + + bool inlineGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); + + const HashEntry* findPropertyHashEntry(ExecState*, const Identifier& propertyName) const; + Structure* createInheritorID(JSGlobalData&); + + StorageBarrier m_propertyStorage; + WriteBarrier m_inheritorID; + }; + + +#if USE(JSVALUE32_64) +#define JSNonFinalObject_inlineStorageCapacity 4 +#define JSFinalObject_inlineStorageCapacity 6 +#else +#define JSNonFinalObject_inlineStorageCapacity 2 +#define JSFinalObject_inlineStorageCapacity 4 +#endif + +COMPILE_ASSERT((JSFinalObject_inlineStorageCapacity >= JSNonFinalObject_inlineStorageCapacity), final_storage_is_at_least_as_large_as_non_final); + + // JSNonFinalObject is a type of JSObject that has some internal storage, + // but also preserves some space in the collector cell for additional + // data members in derived types. + class JSNonFinalObject : public JSObject { + friend class JSObject; + + public: + typedef JSObject Base; + + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + { + return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); + } + + JS_EXPORT_PRIVATE static void destroy(JSCell*); + + protected: + explicit JSNonFinalObject(JSGlobalData& globalData, Structure* structure) + : JSObject(globalData, structure, m_inlineStorage) + { + } + + void finishCreation(JSGlobalData& globalData) + { + Base::finishCreation(globalData, m_inlineStorage); + ASSERT(!(OBJECT_OFFSETOF(JSNonFinalObject, m_inlineStorage) % sizeof(double))); + ASSERT(this->structure()->propertyStorageCapacity() == JSNonFinalObject_inlineStorageCapacity); + ASSERT(classInfo()); + } + + private: + WriteBarrier m_inlineStorage[JSNonFinalObject_inlineStorageCapacity]; + }; + + // JSFinalObject is a type of JSObject that contains sufficent internal + // storage to fully make use of the colloctor cell containing it. + class JSFinalObject : public JSObject { + friend class JSObject; + + public: + typedef JSObject Base; + + static JSFinalObject* create(ExecState* exec, Structure* structure) + { + JSFinalObject* finalObject = new (NotNull, allocateCell(*exec->heap())) JSFinalObject(exec->globalData(), structure); + finalObject->finishCreation(exec->globalData()); + return finalObject; + } + + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + { + return Structure::create(globalData, globalObject, prototype, TypeInfo(FinalObjectType, StructureFlags), &s_info); + } + + static JS_EXPORTDATA const ClassInfo s_info; + + protected: + void finishCreation(JSGlobalData& globalData) + { + Base::finishCreation(globalData, m_inlineStorage); + ASSERT(!(OBJECT_OFFSETOF(JSFinalObject, m_inlineStorage) % sizeof(double))); + ASSERT(this->structure()->propertyStorageCapacity() == JSFinalObject_inlineStorageCapacity); + ASSERT(classInfo()); + } + + static void destroy(JSCell*); + + private: + explicit JSFinalObject(JSGlobalData& globalData, Structure* structure) + : JSObject(globalData, structure, m_inlineStorage) + { + } + + static const unsigned StructureFlags = JSObject::StructureFlags; + + WriteBarrierBase m_inlineStorage[JSFinalObject_inlineStorageCapacity]; + }; + +inline bool isJSFinalObject(JSCell* cell) +{ + return cell->classInfo() == &JSFinalObject::s_info; +} + +inline bool isJSFinalObject(JSValue value) +{ + return value.isCell() && isJSFinalObject(value.asCell()); +} + +inline size_t JSObject::offsetOfInlineStorage() +{ + ASSERT(OBJECT_OFFSETOF(JSFinalObject, m_inlineStorage) == OBJECT_OFFSETOF(JSNonFinalObject, m_inlineStorage)); + return OBJECT_OFFSETOF(JSFinalObject, m_inlineStorage); +} + +inline size_t JSObject::offsetOfPropertyStorage() +{ + return OBJECT_OFFSETOF(JSObject, m_propertyStorage); +} + +inline size_t JSObject::offsetOfInheritorID() +{ + return OBJECT_OFFSETOF(JSObject, m_inheritorID); +} + +inline bool JSObject::isGlobalObject() const +{ + return structure()->typeInfo().type() == GlobalObjectType; +} + +inline bool JSObject::isVariableObject() const +{ + return structure()->typeInfo().type() >= VariableObjectType; +} + +inline bool JSObject::isActivationObject() const +{ + return structure()->typeInfo().type() == ActivationObjectType; +} + +inline bool JSObject::isErrorInstance() const +{ + return structure()->typeInfo().type() == ErrorInstanceType; +} + +inline bool JSObject::isGlobalThis() const +{ + return structure()->typeInfo().type() == GlobalThisType; +} + +inline JSObject* constructEmptyObject(ExecState* exec, Structure* structure) +{ + return JSFinalObject::create(exec, structure); +} + +inline CallType getCallData(JSValue value, CallData& callData) +{ + CallType result = value.isCell() ? value.asCell()->methodTable()->getCallData(value.asCell(), callData) : CallTypeNone; + ASSERT(result == CallTypeNone || value.isValidCallee()); + return result; +} + +inline ConstructType getConstructData(JSValue value, ConstructData& constructData) +{ + ConstructType result = value.isCell() ? value.asCell()->methodTable()->getConstructData(value.asCell(), constructData) : ConstructTypeNone; + ASSERT(result == ConstructTypeNone || value.isValidCallee()); + return result; +} + +inline Structure* createEmptyObjectStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) +{ + return JSFinalObject::createStructure(globalData, globalObject, prototype); +} + +inline JSObject* asObject(JSCell* cell) +{ + ASSERT(cell->isObject()); + return static_cast(cell); +} + +inline JSObject* asObject(JSValue value) +{ + return asObject(value.asCell()); +} + +inline JSObject::JSObject(JSGlobalData& globalData, Structure* structure, PropertyStorage inlineStorage) + : JSCell(globalData, structure) + , m_propertyStorage(globalData, this, inlineStorage) +{ +} + +inline JSValue JSObject::prototype() const +{ + return structure()->storedPrototype(); +} + +inline bool JSObject::setPrototypeWithCycleCheck(JSGlobalData& globalData, JSValue prototype) +{ + JSValue nextPrototypeValue = prototype; + while (nextPrototypeValue && nextPrototypeValue.isObject()) { + JSObject* nextPrototype = asObject(nextPrototypeValue)->unwrappedObject(); + if (nextPrototype == this) + return false; + nextPrototypeValue = nextPrototype->prototype(); + } + setPrototype(globalData, prototype); + return true; +} + +inline void JSObject::setPrototype(JSGlobalData& globalData, JSValue prototype) +{ + ASSERT(prototype); + setStructure(globalData, Structure::changePrototypeTransition(globalData, structure(), prototype)); +} + +inline Structure* JSObject::inheritorID(JSGlobalData& globalData) +{ + if (m_inheritorID) { + ASSERT(m_inheritorID->isEmpty()); + return m_inheritorID.get(); + } + return createInheritorID(globalData); +} + +inline bool Structure::isUsingInlineStorage() const +{ + return propertyStorageCapacity() < JSObject::baseExternalStorageCapacity; +} + +inline bool JSCell::inherits(const ClassInfo* info) const +{ + return classInfo()->isSubClassOf(info); +} + +inline const MethodTable* JSCell::methodTable() const +{ + return &classInfo()->methodTable; +} + +// this method is here to be after the inline declaration of JSCell::inherits +inline bool JSValue::inherits(const ClassInfo* classInfo) const +{ + return isCell() && asCell()->inherits(classInfo); +} + +inline JSObject* JSValue::toThisObject(ExecState* exec) const +{ + return isCell() ? asCell()->methodTable()->toThisObject(asCell(), exec) : toThisObjectSlowCase(exec); +} + +ALWAYS_INLINE bool JSObject::inlineGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) +{ + if (WriteBarrierBase* location = getDirectLocation(exec->globalData(), propertyName)) { + if (structure()->hasGetterSetterProperties() && location->isGetterSetter()) + fillGetterPropertySlot(slot, location); + else + slot.setValue(this, location->get(), offsetForLocation(location)); + return true; + } + + // non-standard Netscape extension + if (propertyName == exec->propertyNames().underscoreProto) { + slot.setValue(prototype()); + return true; + } + + return false; +} + +// It may seem crazy to inline a function this large, especially a virtual function, +// but it makes a big difference to property lookup that derived classes can inline their +// base class call to this. +ALWAYS_INLINE bool JSObject::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot) +{ + return jsCast(cell)->inlineGetOwnPropertySlot(exec, propertyName, slot); +} + +ALWAYS_INLINE bool JSCell::fastGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) +{ + if (!structure()->typeInfo().overridesGetOwnPropertySlot()) + return asObject(this)->inlineGetOwnPropertySlot(exec, propertyName, slot); + return methodTable()->getOwnPropertySlot(this, exec, propertyName, slot); +} + +// Fast call to get a property where we may not yet have converted the string to an +// identifier. The first time we perform a property access with a given string, try +// performing the property map lookup without forming an identifier. We detect this +// case by checking whether the hash has yet been set for this string. +ALWAYS_INLINE JSValue JSCell::fastGetOwnProperty(ExecState* exec, const UString& name) +{ + if (!structure()->typeInfo().overridesGetOwnPropertySlot() && !structure()->hasGetterSetterProperties()) { + size_t offset = name.impl()->hasHash() + ? structure()->get(exec->globalData(), Identifier(exec, name)) + : structure()->get(exec->globalData(), name); + if (offset != WTF::notFound) + return asObject(this)->locationForOffset(offset)->get(); + } + return JSValue(); +} + +// It may seem crazy to inline a function this large but it makes a big difference +// since this is function very hot in variable lookup +ALWAYS_INLINE bool JSObject::getPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) +{ + JSObject* object = this; + while (true) { + if (object->fastGetOwnPropertySlot(exec, propertyName, slot)) + return true; + JSValue prototype = object->prototype(); + if (!prototype.isObject()) + return false; + object = asObject(prototype); + } +} + +ALWAYS_INLINE bool JSObject::getPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot) +{ + JSObject* object = this; + while (true) { + if (object->methodTable()->getOwnPropertySlotByIndex(object, exec, propertyName, slot)) + return true; + JSValue prototype = object->prototype(); + if (!prototype.isObject()) + return false; + object = asObject(prototype); + } +} + +inline JSValue JSObject::get(ExecState* exec, const Identifier& propertyName) const +{ + PropertySlot slot(this); + if (const_cast(this)->getPropertySlot(exec, propertyName, slot)) + return slot.getValue(exec, propertyName); + + return jsUndefined(); +} + +inline JSValue JSObject::get(ExecState* exec, unsigned propertyName) const +{ + PropertySlot slot(this); + if (const_cast(this)->getPropertySlot(exec, propertyName, slot)) + return slot.getValue(exec, propertyName); + + return jsUndefined(); +} + +template +inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes, PutPropertySlot& slot, JSCell* specificFunction) +{ + ASSERT(value); + ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); + + if (structure()->isDictionary()) { + unsigned currentAttributes; + JSCell* currentSpecificFunction; + size_t offset = structure()->get(globalData, propertyName, currentAttributes, currentSpecificFunction); + if (offset != WTF::notFound) { + // If there is currently a specific function, and there now either isn't, + // or the new value is different, then despecify. + if (currentSpecificFunction && (specificFunction != currentSpecificFunction)) + structure()->despecifyDictionaryFunction(globalData, propertyName); + if ((mode == PutModePut) && currentAttributes & ReadOnly) + return false; + + putDirectOffset(globalData, offset, value); + // At this point, the objects structure only has a specific value set if previously there + // had been one set, and if the new value being specified is the same (otherwise we would + // have despecified, above). So, if currentSpecificFunction is not set, or if the new + // value is different (or there is no new value), then the slot now has no value - and + // as such it is cachable. + // If there was previously a value, and the new value is the same, then we cannot cache. + if (!currentSpecificFunction || (specificFunction != currentSpecificFunction)) + slot.setExistingProperty(this, offset); + return true; + } + + if ((mode == PutModePut) && !isExtensible()) + return false; + + size_t currentCapacity = structure()->propertyStorageCapacity(); + offset = structure()->addPropertyWithoutTransition(globalData, propertyName, attributes, specificFunction); + if (currentCapacity != structure()->propertyStorageCapacity()) + allocatePropertyStorage(globalData, currentCapacity, structure()->propertyStorageCapacity()); + + ASSERT(offset < structure()->propertyStorageCapacity()); + putDirectOffset(globalData, offset, value); + // See comment on setNewProperty call below. + if (!specificFunction) + slot.setNewProperty(this, offset); + return true; + } + + size_t offset; + size_t currentCapacity = structure()->propertyStorageCapacity(); + if (Structure* structure = Structure::addPropertyTransitionToExistingStructure(this->structure(), propertyName, attributes, specificFunction, offset)) { + if (currentCapacity != structure->propertyStorageCapacity()) + allocatePropertyStorage(globalData, currentCapacity, structure->propertyStorageCapacity()); + + ASSERT(offset < structure->propertyStorageCapacity()); + setStructure(globalData, structure); + putDirectOffset(globalData, offset, value); + // This is a new property; transitions with specific values are not currently cachable, + // so leave the slot in an uncachable state. + if (!specificFunction) + slot.setNewProperty(this, offset); + return true; + } + + unsigned currentAttributes; + JSCell* currentSpecificFunction; + offset = structure()->get(globalData, propertyName, currentAttributes, currentSpecificFunction); + if (offset != WTF::notFound) { + if ((mode == PutModePut) && currentAttributes & ReadOnly) + return false; + + // There are three possibilities here: + // (1) There is an existing specific value set, and we're overwriting with *the same value*. + // * Do nothing - no need to despecify, but that means we can't cache (a cached + // put could write a different value). Leave the slot in an uncachable state. + // (2) There is a specific value currently set, but we're writing a different value. + // * First, we have to despecify. Having done so, this is now a regular slot + // with no specific value, so go ahead & cache like normal. + // (3) Normal case, there is no specific value set. + // * Go ahead & cache like normal. + if (currentSpecificFunction) { + // case (1) Do the put, then return leaving the slot uncachable. + if (specificFunction == currentSpecificFunction) { + putDirectOffset(globalData, offset, value); + return true; + } + // case (2) Despecify, fall through to (3). + setStructure(globalData, Structure::despecifyFunctionTransition(globalData, structure(), propertyName)); + } + + // case (3) set the slot, do the put, return. + slot.setExistingProperty(this, offset); + putDirectOffset(globalData, offset, value); + return true; + } + + if ((mode == PutModePut) && !isExtensible()) + return false; + + Structure* structure = Structure::addPropertyTransition(globalData, this->structure(), propertyName, attributes, specificFunction, offset); + + if (currentCapacity != structure->propertyStorageCapacity()) + allocatePropertyStorage(globalData, currentCapacity, structure->propertyStorageCapacity()); + + ASSERT(offset < structure->propertyStorageCapacity()); + setStructure(globalData, structure); + putDirectOffset(globalData, offset, value); + // This is a new property; transitions with specific values are not currently cachable, + // so leave the slot in an uncachable state. + if (!specificFunction) + slot.setNewProperty(this, offset); + return true; +} + +inline bool JSObject::putOwnDataProperty(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) +{ + ASSERT(value); + ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); + ASSERT(!structure()->hasGetterSetterProperties()); + + return putDirectInternal(globalData, propertyName, value, 0, slot, getJSFunction(value)); +} + +inline void JSObject::putDirect(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes) +{ + PutPropertySlot slot; + putDirectInternal(globalData, propertyName, value, attributes, slot, getJSFunction(value)); +} + +inline void JSObject::putDirect(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) +{ + putDirectInternal(globalData, propertyName, value, 0, slot, getJSFunction(value)); +} + +inline void JSObject::putDirectWithoutTransition(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes) +{ + size_t currentCapacity = structure()->propertyStorageCapacity(); + size_t offset = structure()->addPropertyWithoutTransition(globalData, propertyName, attributes, getJSFunction(value)); + if (currentCapacity != structure()->propertyStorageCapacity()) + allocatePropertyStorage(globalData, currentCapacity, structure()->propertyStorageCapacity()); + putDirectOffset(globalData, offset, value); +} + +inline void JSObject::transitionTo(JSGlobalData& globalData, Structure* newStructure) +{ + if (structure()->propertyStorageCapacity() != newStructure->propertyStorageCapacity()) + allocatePropertyStorage(globalData, structure()->propertyStorageCapacity(), newStructure->propertyStorageCapacity()); + setStructure(globalData, newStructure); +} + +inline JSValue JSObject::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const +{ + return methodTable()->defaultValue(this, exec, preferredType); +} + +inline JSValue JSValue::get(ExecState* exec, const Identifier& propertyName) const +{ + PropertySlot slot(asValue()); + return get(exec, propertyName, slot); +} + +inline JSValue JSValue::get(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) const +{ + if (UNLIKELY(!isCell())) { + JSObject* prototype = synthesizePrototype(exec); + if (propertyName == exec->propertyNames().underscoreProto) + return prototype; + if (!prototype->getPropertySlot(exec, propertyName, slot)) + return jsUndefined(); + return slot.getValue(exec, propertyName); + } + JSCell* cell = asCell(); + while (true) { + if (cell->fastGetOwnPropertySlot(exec, propertyName, slot)) + return slot.getValue(exec, propertyName); + JSValue prototype = asObject(cell)->prototype(); + if (!prototype.isObject()) + return jsUndefined(); + cell = asObject(prototype); + } +} + +inline JSValue JSValue::get(ExecState* exec, unsigned propertyName) const +{ + PropertySlot slot(asValue()); + return get(exec, propertyName, slot); +} + +inline JSValue JSValue::get(ExecState* exec, unsigned propertyName, PropertySlot& slot) const +{ + if (UNLIKELY(!isCell())) { + JSObject* prototype = synthesizePrototype(exec); + if (!prototype->getPropertySlot(exec, propertyName, slot)) + return jsUndefined(); + return slot.getValue(exec, propertyName); + } + JSCell* cell = const_cast(asCell()); + while (true) { + if (cell->methodTable()->getOwnPropertySlotByIndex(cell, exec, propertyName, slot)) + return slot.getValue(exec, propertyName); + JSValue prototype = asObject(cell)->prototype(); + if (!prototype.isObject()) + return jsUndefined(); + cell = prototype.asCell(); + } +} + +inline void JSValue::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) +{ + if (UNLIKELY(!isCell())) { + JSObject* thisObject = synthesizeObject(exec); + thisObject->methodTable()->put(thisObject, exec, propertyName, value, slot); + return; + } + asCell()->methodTable()->put(asCell(), exec, propertyName, value, slot); +} + +inline void JSValue::put(ExecState* exec, unsigned propertyName, JSValue value) +{ + if (UNLIKELY(!isCell())) { + JSObject* thisObject = synthesizeObject(exec); + thisObject->methodTable()->putByIndex(thisObject, exec, propertyName, value); + return; + } + asCell()->methodTable()->putByIndex(asCell(), exec, propertyName, value); +} + +// --- JSValue inlines ---------------------------- + +ALWAYS_INLINE JSObject* Register::function() const +{ + if (!jsValue()) + return 0; + return asObject(jsValue()); +} + +ALWAYS_INLINE Register Register::withCallee(JSObject* callee) +{ + Register r; + r = JSValue(callee); + return r; +} + +} // namespace JSC + +#endif // JSObject_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSObjectRefPrivate.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSObjectRefPrivate.h new file mode 100644 index 000000000..32e80ab26 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSObjectRefPrivate.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2010 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 INC. 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 INC. 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 JSObjectRefPrivate_h +#define JSObjectRefPrivate_h + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + @function + @abstract Sets a private property on an object. This private property cannot be accessed from within JavaScript. + @param ctx The execution context to use. + @param object The JSObject whose private property you want to set. + @param propertyName A JSString containing the property's name. + @param value A JSValue to use as the property's value. This may be NULL. + @result true if object can store private data, otherwise false. + @discussion This API allows you to store JS values directly an object in a way that will be ensure that they are kept alive without exposing them to JavaScript code and without introducing the reference cycles that may occur when using JSValueProtect. + + The default object class does not allocate storage for private data. Only objects created with a non-NULL JSClass can store private properties. + */ +JS_EXPORT bool JSObjectSetPrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value); + +/*! + @function + @abstract Gets a private property from an object. + @param ctx The execution context to use. + @param object The JSObject whose private property you want to get. + @param propertyName A JSString containing the property's name. + @result The property's value if object has the property, otherwise NULL. + */ +JS_EXPORT JSValueRef JSObjectGetPrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName); + +/*! + @function + @abstract Deletes a private property from an object. + @param ctx The execution context to use. + @param object The JSObject whose private property you want to delete. + @param propertyName A JSString containing the property's name. + @result true if object can store private data, otherwise false. + @discussion The default object class does not allocate storage for private data. Only objects created with a non-NULL JSClass can store private data. + */ +JS_EXPORT bool JSObjectDeletePrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName); + +#ifdef __cplusplus +} +#endif + +#endif // JSObjectRefPrivate_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSProfilerPrivate.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSProfilerPrivate.h new file mode 100644 index 000000000..b3fe533a3 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSProfilerPrivate.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 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. + */ + +#ifndef JSProfiler_h +#define JSProfiler_h + +#include + +#ifndef __cplusplus +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/*! +@function JSStartProfiling +@abstract Enables the profler. +@param ctx The execution context to use. +@param title The title of the profile. +@result The profiler is turned on. +*/ +JS_EXPORT void JSStartProfiling(JSContextRef ctx, JSStringRef title); + +/*! +@function JSEndProfiling +@abstract Disables the profler. +@param ctx The execution context to use. +@param title The title of the profile. +@result The profiler is turned off. If there is no name, the most recently started + profile is stopped. If the name does not match any profile then no profile + is stopped. +*/ +JS_EXPORT void JSEndProfiling(JSContextRef ctx, JSStringRef title); + +#ifdef __cplusplus +} +#endif + +#endif /* JSProfiler_h */ diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSRetainPtr.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSRetainPtr.h new file mode 100644 index 000000000..574f7aaf1 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSRetainPtr.h @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2005, 2006, 2007, 2010 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 JSRetainPtr_h +#define JSRetainPtr_h + +#include +#include +#include + +inline void JSRetain(JSStringRef string) { JSStringRetain(string); } +inline void JSRelease(JSStringRef string) { JSStringRelease(string); } +inline void JSRetain(JSGlobalContextRef context) { JSGlobalContextRetain(context); } +inline void JSRelease(JSGlobalContextRef context) { JSGlobalContextRelease(context); } + +enum AdoptTag { Adopt }; + +template class JSRetainPtr { +public: + JSRetainPtr() : m_ptr(0) { } + JSRetainPtr(T ptr) : m_ptr(ptr) { if (ptr) JSRetain(ptr); } + JSRetainPtr(AdoptTag, T ptr) : m_ptr(ptr) { } + JSRetainPtr(const JSRetainPtr&); + template JSRetainPtr(const JSRetainPtr&); + ~JSRetainPtr(); + + T get() const { return m_ptr; } + + void clear(); + T leakRef(); + + T operator->() const { return m_ptr; } + + bool operator!() const { return !m_ptr; } + + // This conversion operator allows implicit conversion to bool but not to other integer types. + typedef T JSRetainPtr::*UnspecifiedBoolType; + operator UnspecifiedBoolType() const { return m_ptr ? &JSRetainPtr::m_ptr : 0; } + + JSRetainPtr& operator=(const JSRetainPtr&); + template JSRetainPtr& operator=(const JSRetainPtr&); + JSRetainPtr& operator=(T); + template JSRetainPtr& operator=(U*); + + void adopt(T); + + void swap(JSRetainPtr&); + +private: + T m_ptr; +}; + +template inline JSRetainPtr::JSRetainPtr(const JSRetainPtr& o) + : m_ptr(o.m_ptr) +{ + if (m_ptr) + JSRetain(m_ptr); +} + +template template inline JSRetainPtr::JSRetainPtr(const JSRetainPtr& o) + : m_ptr(o.get()) +{ + if (m_ptr) + JSRetain(m_ptr); +} + +template inline JSRetainPtr::~JSRetainPtr() +{ + if (m_ptr) + JSRelease(m_ptr); +} + +template inline void JSRetainPtr::clear() +{ + if (T ptr = m_ptr) { + m_ptr = 0; + JSRelease(ptr); + } +} + +template inline T JSRetainPtr::leakRef() +{ + T ptr = m_ptr; + m_ptr = 0; + return ptr; +} + +template inline JSRetainPtr& JSRetainPtr::operator=(const JSRetainPtr& o) +{ + T optr = o.get(); + if (optr) + JSRetain(optr); + T ptr = m_ptr; + m_ptr = optr; + if (ptr) + JSRelease(ptr); + return *this; +} + +template template inline JSRetainPtr& JSRetainPtr::operator=(const JSRetainPtr& o) +{ + T optr = o.get(); + if (optr) + JSRetain(optr); + T ptr = m_ptr; + m_ptr = optr; + if (ptr) + JSRelease(ptr); + return *this; +} + +template inline JSRetainPtr& JSRetainPtr::operator=(T optr) +{ + if (optr) + JSRetain(optr); + T ptr = m_ptr; + m_ptr = optr; + if (ptr) + JSRelease(ptr); + return *this; +} + +template inline void JSRetainPtr::adopt(T optr) +{ + T ptr = m_ptr; + m_ptr = optr; + if (ptr) + JSRelease(ptr); +} + +template template inline JSRetainPtr& JSRetainPtr::operator=(U* optr) +{ + if (optr) + JSRetain(optr); + T ptr = m_ptr; + m_ptr = optr; + if (ptr) + JSRelease(ptr); + return *this; +} + +template inline void JSRetainPtr::swap(JSRetainPtr& o) +{ + std::swap(m_ptr, o.m_ptr); +} + +template inline void swap(JSRetainPtr& a, JSRetainPtr& b) +{ + a.swap(b); +} + +template inline bool operator==(const JSRetainPtr& a, const JSRetainPtr& b) +{ + return a.get() == b.get(); +} + +template inline bool operator==(const JSRetainPtr& a, U* b) +{ + return a.get() == b; +} + +template inline bool operator==(T* a, const JSRetainPtr& b) +{ + return a == b.get(); +} + +template inline bool operator!=(const JSRetainPtr& a, const JSRetainPtr& b) +{ + return a.get() != b.get(); +} + +template inline bool operator!=(const JSRetainPtr& a, U* b) +{ + return a.get() != b; +} + +template inline bool operator!=(T* a, const JSRetainPtr& b) +{ + return a != b.get(); +} + + +#endif // JSRetainPtr_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSString.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSString.h new file mode 100644 index 000000000..c0637a6e0 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSString.h @@ -0,0 +1,464 @@ +/* + * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) + * Copyright (C) 2001 Peter Kelly (pmk@post.com) + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef JSString_h +#define JSString_h +#include "CallFrame.h" +#include "CommonIdentifiers.h" +#include "Identifier.h" +#include "PropertyDescriptor.h" +#include "PropertySlot.h" +#include "Structure.h" + +namespace JSC { + + class JSString; + + JSString* jsEmptyString(JSGlobalData*); + JSString* jsEmptyString(ExecState*); + JSString* jsString(JSGlobalData*, const UString&); // returns empty string if passed null string + JSString* jsString(ExecState*, const UString&); // returns empty string if passed null string + + JSString* jsSingleCharacterString(JSGlobalData*, UChar); + JSString* jsSingleCharacterString(ExecState*, UChar); + JSString* jsSingleCharacterSubstring(ExecState*, const UString&, unsigned offset); + JSString* jsSubstring(JSGlobalData*, const UString&, unsigned offset, unsigned length); + JSString* jsSubstring(ExecState*, const UString&, unsigned offset, unsigned length); + + // Non-trivial strings are two or more characters long. + // These functions are faster than just calling jsString. + JSString* jsNontrivialString(JSGlobalData*, const UString&); + JSString* jsNontrivialString(ExecState*, const UString&); + JSString* jsNontrivialString(JSGlobalData*, const char*); + JSString* jsNontrivialString(ExecState*, const char*); + + // Should be used for strings that are owned by an object that will + // likely outlive the JSValue this makes, such as the parse tree or a + // DOM object that contains a UString + JSString* jsOwnedString(JSGlobalData*, const UString&); + JSString* jsOwnedString(ExecState*, const UString&); + + JSString* jsStringBuilder(JSGlobalData*); + + class JSString : public JSCell { + public: + friend class JIT; + friend class JSGlobalData; + friend class SpecializedThunkJIT; + friend struct ThunkHelpers; + friend JSString* jsStringBuilder(JSGlobalData*); + + typedef JSCell Base; + + static void destroy(JSCell*); + + class RopeBuilder { + public: + RopeBuilder(JSGlobalData& globalData) + : m_globalData(globalData) + , m_jsString(jsStringBuilder(&globalData)) + , m_index(0) + { + } + + void append(JSString* jsString) + { + if (m_index == JSString::s_maxInternalRopeLength) + expand(); + m_jsString->m_fibers[m_index++].set(m_globalData, m_jsString, jsString); + m_jsString->m_length += jsString->m_length; + m_jsString->m_is8Bit = m_jsString->m_is8Bit && jsString->m_is8Bit; + } + + JSString* release() + { + JSString* tmp = m_jsString; + m_jsString = 0; + return tmp; + } + + unsigned length() { return m_jsString->m_length; } + + private: + void expand(); + + JSGlobalData& m_globalData; + JSString* m_jsString; + size_t m_index; + }; + + private: + JSString(JSGlobalData& globalData, PassRefPtr value) + : JSCell(globalData, globalData.stringStructure.get()) + , m_value(value) + { + } + + JSString(JSGlobalData& globalData) + : JSCell(globalData, globalData.stringStructure.get()) + { + } + + void finishCreation(JSGlobalData& globalData) + { + Base::finishCreation(globalData); + m_length = 0; + m_is8Bit = true; + } + + void finishCreation(JSGlobalData& globalData, size_t length) + { + ASSERT(!m_value.isNull()); + Base::finishCreation(globalData); + m_length = length; + m_is8Bit = m_value.impl()->is8Bit(); + } + + void finishCreation(JSGlobalData& globalData, size_t length, size_t cost) + { + ASSERT(!m_value.isNull()); + Base::finishCreation(globalData); + m_length = length; + m_is8Bit = m_value.impl()->is8Bit(); + Heap::heap(this)->reportExtraMemoryCost(cost); + } + + void finishCreation(JSGlobalData& globalData, JSString* s1, JSString* s2) + { + Base::finishCreation(globalData); + m_length = s1->length() + s2->length(); + m_is8Bit = (s1->is8Bit() && s2->is8Bit()); + m_fibers[0].set(globalData, this, s1); + m_fibers[1].set(globalData, this, s2); + } + + void finishCreation(JSGlobalData& globalData, JSString* s1, JSString* s2, JSString* s3) + { + Base::finishCreation(globalData); + m_length = s1->length() + s2->length() + s3->length(); + m_is8Bit = (s1->is8Bit() && s2->is8Bit() && s3->is8Bit()); + m_fibers[0].set(globalData, this, s1); + m_fibers[1].set(globalData, this, s2); + m_fibers[2].set(globalData, this, s3); + } + + static JSString* createNull(JSGlobalData& globalData) + { + JSString* newString = new (NotNull, allocateCell(globalData.heap)) JSString(globalData); + newString->finishCreation(globalData); + return newString; + } + + public: + static JSString* create(JSGlobalData& globalData, PassRefPtr value) + { + ASSERT(value); + size_t length = value->length(); + size_t cost = value->cost(); + JSString* newString = new (NotNull, allocateCell(globalData.heap)) JSString(globalData, value); + newString->finishCreation(globalData, length, cost); + return newString; + } + static JSString* create(JSGlobalData& globalData, JSString* s1, JSString* s2) + { + JSString* newString = new (NotNull, allocateCell(globalData.heap)) JSString(globalData); + newString->finishCreation(globalData, s1, s2); + return newString; + } + static JSString* create(JSGlobalData& globalData, JSString* s1, JSString* s2, JSString* s3) + { + JSString* newString = new (NotNull, allocateCell(globalData.heap)) JSString(globalData); + newString->finishCreation(globalData, s1, s2, s3); + return newString; + } + static JSString* createHasOtherOwner(JSGlobalData& globalData, PassRefPtr value) + { + ASSERT(value); + size_t length = value->length(); + JSString* newString = new (NotNull, allocateCell(globalData.heap)) JSString(globalData, value); + newString->finishCreation(globalData, length); + return newString; + } + + const UString& value(ExecState* exec) const + { + if (isRope()) + resolveRope(exec); + return m_value; + } + const UString& tryGetValue() const + { + if (isRope()) + resolveRope(0); + return m_value; + } + unsigned length() { return m_length; } + + JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const; + JS_EXPORT_PRIVATE bool toBoolean(ExecState*) const; + bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const; + JSObject* toObject(ExecState*, JSGlobalObject*) const; + double toNumber(ExecState*) const; + + bool getStringPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); + bool getStringPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); + bool getStringPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor&); + + bool canGetIndex(unsigned i) { return i < m_length; } + JSString* getIndex(ExecState*, unsigned); + JSString* getIndexSlowCase(ExecState*, unsigned); + + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) + { + return Structure::create(globalData, globalObject, proto, TypeInfo(StringType, OverridesGetOwnPropertySlot), &s_info); + } + + static size_t offsetOfLength() { return OBJECT_OFFSETOF(JSString, m_length); } + static size_t offsetOfValue() { return OBJECT_OFFSETOF(JSString, m_value); } + + static JS_EXPORTDATA const ClassInfo s_info; + + static void visitChildren(JSCell*, SlotVisitor&); + + private: + JS_EXPORT_PRIVATE void resolveRope(ExecState*) const; + void resolveRopeSlowCase8(LChar*) const; + void resolveRopeSlowCase(UChar*) const; + void outOfMemory(ExecState*) const; + + static JSObject* toThisObject(JSCell*, ExecState*); + + // Actually getPropertySlot, not getOwnPropertySlot (see JSCell). + static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier& propertyName, PropertySlot&); + static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&); + + static const unsigned s_maxInternalRopeLength = 3; + + // A string is represented either by a UString or a rope of fibers. + bool m_is8Bit : 1; + unsigned m_length; + mutable UString m_value; + mutable FixedArray, s_maxInternalRopeLength> m_fibers; + + bool isRope() const { return m_value.isNull(); } + bool is8Bit() const { return m_is8Bit; } + UString& string() { ASSERT(!isRope()); return m_value; } + + friend JSValue jsString(ExecState*, JSString*, JSString*); + friend JSValue jsString(ExecState*, Register*, unsigned count); + friend JSValue jsStringFromArguments(ExecState*, JSValue thisValue); + friend JSString* jsSubstring(ExecState*, JSString*, unsigned offset, unsigned length); + }; + + JSString* asString(JSValue); + + inline JSString* asString(JSValue value) + { + ASSERT(value.asCell()->isString()); + return static_cast(value.asCell()); + } + + inline JSString* jsEmptyString(JSGlobalData* globalData) + { + return globalData->smallStrings.emptyString(globalData); + } + + inline JSString* jsSingleCharacterString(JSGlobalData* globalData, UChar c) + { + if (c <= maxSingleCharacterString) + return globalData->smallStrings.singleCharacterString(globalData, c); + return JSString::create(*globalData, UString(&c, 1).impl()); + } + + inline JSString* jsSingleCharacterSubstring(ExecState* exec, const UString& s, unsigned offset) + { + JSGlobalData* globalData = &exec->globalData(); + ASSERT(offset < static_cast(s.length())); + UChar c = s[offset]; + if (c <= maxSingleCharacterString) + return globalData->smallStrings.singleCharacterString(globalData, c); + return JSString::create(*globalData, StringImpl::create(s.impl(), offset, 1)); + } + + inline JSString* jsNontrivialString(JSGlobalData* globalData, const char* s) + { + ASSERT(s); + ASSERT(s[0]); + ASSERT(s[1]); + return JSString::create(*globalData, UString(s).impl()); + } + + inline JSString* jsNontrivialString(JSGlobalData* globalData, const UString& s) + { + ASSERT(s.length() > 1); + return JSString::create(*globalData, s.impl()); + } + + inline JSString* JSString::getIndex(ExecState* exec, unsigned i) + { + ASSERT(canGetIndex(i)); + if (isRope()) + return getIndexSlowCase(exec, i); + ASSERT(i < m_value.length()); + return jsSingleCharacterSubstring(exec, m_value, i); + } + + inline JSString* jsString(JSGlobalData* globalData, const UString& s) + { + int size = s.length(); + if (!size) + return globalData->smallStrings.emptyString(globalData); + if (size == 1) { + UChar c = s[0]; + if (c <= maxSingleCharacterString) + return globalData->smallStrings.singleCharacterString(globalData, c); + } + return JSString::create(*globalData, s.impl()); + } + + inline JSString* jsSubstring(ExecState* exec, JSString* s, unsigned offset, unsigned length) + { + ASSERT(offset <= static_cast(s->length())); + ASSERT(length <= static_cast(s->length())); + ASSERT(offset + length <= static_cast(s->length())); + JSGlobalData* globalData = &exec->globalData(); + if (!length) + return globalData->smallStrings.emptyString(globalData); + return jsSubstring(globalData, s->value(exec), offset, length); + } + + inline JSString* jsSubstring8(JSGlobalData* globalData, const UString& s, unsigned offset, unsigned length) + { + ASSERT(offset <= static_cast(s.length())); + ASSERT(length <= static_cast(s.length())); + ASSERT(offset + length <= static_cast(s.length())); + if (!length) + return globalData->smallStrings.emptyString(globalData); + if (length == 1) { + UChar c = s[offset]; + if (c <= maxSingleCharacterString) + return globalData->smallStrings.singleCharacterString(globalData, c); + } + return JSString::createHasOtherOwner(*globalData, StringImpl::create8(s.impl(), offset, length)); + } + + inline JSString* jsSubstring(JSGlobalData* globalData, const UString& s, unsigned offset, unsigned length) + { + ASSERT(offset <= static_cast(s.length())); + ASSERT(length <= static_cast(s.length())); + ASSERT(offset + length <= static_cast(s.length())); + if (!length) + return globalData->smallStrings.emptyString(globalData); + if (length == 1) { + UChar c = s[offset]; + if (c <= maxSingleCharacterString) + return globalData->smallStrings.singleCharacterString(globalData, c); + } + return JSString::createHasOtherOwner(*globalData, StringImpl::create(s.impl(), offset, length)); + } + + inline JSString* jsOwnedString(JSGlobalData* globalData, const UString& s) + { + int size = s.length(); + if (!size) + return globalData->smallStrings.emptyString(globalData); + if (size == 1) { + UChar c = s[0]; + if (c <= maxSingleCharacterString) + return globalData->smallStrings.singleCharacterString(globalData, c); + } + return JSString::createHasOtherOwner(*globalData, s.impl()); + } + + inline JSString* jsStringBuilder(JSGlobalData* globalData) + { + return JSString::createNull(*globalData); + } + + inline JSString* jsEmptyString(ExecState* exec) { return jsEmptyString(&exec->globalData()); } + inline JSString* jsString(ExecState* exec, const UString& s) { return jsString(&exec->globalData(), s); } + inline JSString* jsSingleCharacterString(ExecState* exec, UChar c) { return jsSingleCharacterString(&exec->globalData(), c); } + inline JSString* jsSubstring8(ExecState* exec, const UString& s, unsigned offset, unsigned length) { return jsSubstring8(&exec->globalData(), s, offset, length); } + inline JSString* jsSubstring(ExecState* exec, const UString& s, unsigned offset, unsigned length) { return jsSubstring(&exec->globalData(), s, offset, length); } + inline JSString* jsNontrivialString(ExecState* exec, const UString& s) { return jsNontrivialString(&exec->globalData(), s); } + inline JSString* jsNontrivialString(ExecState* exec, const char* s) { return jsNontrivialString(&exec->globalData(), s); } + inline JSString* jsOwnedString(ExecState* exec, const UString& s) { return jsOwnedString(&exec->globalData(), s); } + + ALWAYS_INLINE bool JSString::getStringPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) + { + if (propertyName == exec->propertyNames().length) { + slot.setValue(jsNumber(m_length)); + return true; + } + + bool isStrictUInt32; + unsigned i = propertyName.toUInt32(isStrictUInt32); + if (isStrictUInt32 && i < m_length) { + slot.setValue(getIndex(exec, i)); + return true; + } + + return false; + } + + ALWAYS_INLINE bool JSString::getStringPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot) + { + if (propertyName < m_length) { + slot.setValue(getIndex(exec, propertyName)); + return true; + } + + return false; + } + + inline bool isJSString(JSValue v) { return v.isCell() && v.asCell()->classInfo() == &JSString::s_info; } + + inline bool JSCell::toBoolean(ExecState* exec) const + { + if (isString()) + return static_cast(this)->toBoolean(exec); + return !structure()->typeInfo().masqueradesAsUndefined(); + } + + // --- JSValue inlines ---------------------------- + + inline bool JSValue::toBoolean(ExecState* exec) const + { + if (isInt32()) + return asInt32(); + if (isDouble()) + return asDouble() > 0.0 || asDouble() < 0.0; // false for NaN + if (isCell()) + return asCell()->toBoolean(exec); + return isTrue(); // false, null, and undefined all convert to false. + } + + inline JSString* JSValue::toString(ExecState* exec) const + { + if (isString()) + return static_cast(asCell()); + return toStringSlowCase(exec); + } + +} // namespace JSC + +#endif // JSString_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSType.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSType.h new file mode 100644 index 000000000..84a27a7ea --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSType.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef JSType_h +#define JSType_h + +namespace JSC { + +enum JSType { + UnspecifiedType, + UndefinedType, + BooleanType, + NumberType, + NullType, + StringType, + LeafType, + + // The CompoundType value must come before any JSType that may have children. + CompoundType, + GetterSetterType, + APIValueWrapperType, + + EvalExecutableType, + ProgramExecutableType, + FunctionExecutableType, + + // The ObjectType value must come before any JSType that is a subclass of JSObject. + ObjectType, + FinalObjectType, + JSFunctionType, + NumberObjectType, + ErrorInstanceType, + GlobalThisType, + + // VariableObjectType must come before all of the types of its subclasses and only its subclasses. + VariableObjectType, + GlobalObjectType, + ActivationObjectType, + StaticScopeObjectType, +}; + +} // namespace JSC + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSTypeInfo.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSTypeInfo.h new file mode 100644 index 000000000..3e23aa253 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSTypeInfo.h @@ -0,0 +1,100 @@ +// -*- mode: c++; c-basic-offset: 4 -*- +/* + * Copyright (C) 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. + */ + +#ifndef JSTypeInfo_h +#define JSTypeInfo_h + +// This file would be called TypeInfo.h, but that conflicts with +// in the STL on systems without case-sensitive file systems. + +#include "JSType.h" + +namespace JSC { + + static const unsigned MasqueradesAsUndefined = 1; // WebCore uses MasqueradesAsUndefined to make document.all undetectable. + static const unsigned ImplementsHasInstance = 1 << 1; + static const unsigned OverridesHasInstance = 1 << 2; + static const unsigned ImplementsDefaultHasInstance = 1 << 3; + static const unsigned IsEnvironmentRecord = 1 << 4; + static const unsigned OverridesGetOwnPropertySlot = 1 << 5; + static const unsigned OverridesVisitChildren = 1 << 6; + static const unsigned OverridesGetPropertyNames = 1 << 7; + static const unsigned ProhibitsPropertyCaching = 1 << 8; + + class TypeInfo { + public: + TypeInfo(JSType type, unsigned flags = 0) + : m_type(type) + , m_flags(flags & 0xff) + , m_flags2(flags >> 8) + { + ASSERT(flags <= 0x3ff); + ASSERT(type <= 0xff); + ASSERT(type >= CompoundType || !(flags & OverridesVisitChildren)); + // No object that doesn't ImplementsHasInstance should override it! + ASSERT((m_flags & (ImplementsHasInstance | OverridesHasInstance)) != OverridesHasInstance); + // ImplementsDefaultHasInstance means (ImplementsHasInstance & !OverridesHasInstance) + if ((m_flags & (ImplementsHasInstance | OverridesHasInstance)) == ImplementsHasInstance) + m_flags |= ImplementsDefaultHasInstance; + } + + JSType type() const { return static_cast(m_type); } + bool isObject() const { return type() >= ObjectType; } + bool isFinalObject() const { return type() == FinalObjectType; } + bool isNumberObject() const { return type() == NumberObjectType; } + + bool masqueradesAsUndefined() const { return isSetOnFlags1(MasqueradesAsUndefined); } + bool implementsHasInstance() const { return isSetOnFlags1(ImplementsHasInstance); } + bool isEnvironmentRecord() const { return isSetOnFlags1(IsEnvironmentRecord); } + bool overridesHasInstance() const { return isSetOnFlags1(OverridesHasInstance); } + bool implementsDefaultHasInstance() const { return isSetOnFlags1(ImplementsDefaultHasInstance); } + bool overridesGetOwnPropertySlot() const { return isSetOnFlags1(OverridesGetOwnPropertySlot); } + bool overridesVisitChildren() const { return isSetOnFlags1(OverridesVisitChildren); } + bool overridesGetPropertyNames() const { return isSetOnFlags1(OverridesGetPropertyNames); } + bool prohibitsPropertyCaching() const { return isSetOnFlags2(ProhibitsPropertyCaching); } + + static ptrdiff_t flagsOffset() + { + return OBJECT_OFFSETOF(TypeInfo, m_flags); + } + + static ptrdiff_t typeOffset() + { + return OBJECT_OFFSETOF(TypeInfo, m_type); + } + + private: + bool isSetOnFlags1(unsigned flag) const { ASSERT(flag <= (1 << 7)); return m_flags & flag; } + bool isSetOnFlags2(unsigned flag) const { ASSERT(flag >= (1 << 8)); return m_flags2 & (flag >> 8); } + + unsigned char m_type; + unsigned char m_flags; + unsigned char m_flags2; + }; + +} + +#endif // JSTypeInfo_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSValue.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSValue.h new file mode 100644 index 000000000..e3415eb1d --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSValue.h @@ -0,0 +1,477 @@ +/* + * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) + * Copyright (C) 2001 Peter Kelly (pmk@post.com) + * Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef JSValue_h +#define JSValue_h + +#include +#include // for size_t +#include +#include +#include +#include +#include +#include +#include + +namespace JSC { + + class ExecState; + class Identifier; + class JSCell; + class JSGlobalData; + class JSGlobalObject; + class JSObject; + class JSString; + class PropertySlot; + class PutPropertySlot; + class UString; +#if ENABLE(DFG_JIT) + namespace DFG { + class AssemblyHelpers; + class JITCompiler; + class JITCodeGenerator; + class JSValueSource; + class OSRExitCompiler; + class SpeculativeJIT; + } +#endif + + struct ClassInfo; + struct Instruction; + struct MethodTable; + + template class WriteBarrierBase; + + enum PreferredPrimitiveType { NoPreference, PreferNumber, PreferString }; + + +#if USE(JSVALUE32_64) + typedef int64_t EncodedJSValue; +#else + typedef void* EncodedJSValue; +#endif + + union EncodedValueDescriptor { + int64_t asInt64; +#if USE(JSVALUE32_64) + double asDouble; +#elif USE(JSVALUE64) + JSCell* ptr; +#endif + +#if CPU(BIG_ENDIAN) + struct { + int32_t tag; + int32_t payload; + } asBits; +#else + struct { + int32_t payload; + int32_t tag; + } asBits; +#endif + }; + + // This implements ToInt32, defined in ECMA-262 9.5. + JS_EXPORT_PRIVATE int32_t toInt32(double); + + // This implements ToUInt32, defined in ECMA-262 9.6. + inline uint32_t toUInt32(double number) + { + // As commented in the spec, the operation of ToInt32 and ToUint32 only differ + // in how the result is interpreted; see NOTEs in sections 9.5 and 9.6. + return toInt32(number); + } + + class JSValue { + friend struct EncodedJSValueHashTraits; + friend class JIT; + friend class JITStubs; + friend class JITStubCall; + friend class JSInterfaceJIT; + friend class SpecializedThunkJIT; +#if ENABLE(DFG_JIT) + friend class DFG::AssemblyHelpers; + friend class DFG::JITCompiler; + friend class DFG::JITCodeGenerator; + friend class DFG::JSValueSource; + friend class DFG::OSRExitCompiler; + friend class DFG::SpeculativeJIT; +#endif + + public: + static EncodedJSValue encode(JSValue); + static JSValue decode(EncodedJSValue); + + enum JSNullTag { JSNull }; + enum JSUndefinedTag { JSUndefined }; + enum JSTrueTag { JSTrue }; + enum JSFalseTag { JSFalse }; + enum EncodeAsDoubleTag { EncodeAsDouble }; + + JSValue(); + JSValue(JSNullTag); + JSValue(JSUndefinedTag); + JSValue(JSTrueTag); + JSValue(JSFalseTag); + JSValue(JSCell* ptr); + JSValue(const JSCell* ptr); + + // Numbers + JSValue(EncodeAsDoubleTag, double); + explicit JSValue(double); + explicit JSValue(char); + explicit JSValue(unsigned char); + explicit JSValue(short); + explicit JSValue(unsigned short); + explicit JSValue(int); + explicit JSValue(unsigned); + explicit JSValue(long); + explicit JSValue(unsigned long); + explicit JSValue(long long); + explicit JSValue(unsigned long long); + + operator bool() const; + bool operator==(const JSValue& other) const; + bool operator!=(const JSValue& other) const; + + bool isInt32() const; + bool isUInt32() const; + bool isDouble() const; + bool isTrue() const; + bool isFalse() const; + + int32_t asInt32() const; + uint32_t asUInt32() const; + double asDouble() const; + bool asBoolean() const; + double asNumber() const; + + // Querying the type. + bool isEmpty() const; + bool isUndefined() const; + bool isNull() const; + bool isUndefinedOrNull() const; + bool isBoolean() const; + bool isNumber() const; + bool isString() const; + bool isPrimitive() const; + bool isGetterSetter() const; + bool isObject() const; + bool inherits(const ClassInfo*) const; + + // Extracting the value. + bool getString(ExecState* exec, UString&) const; + UString getString(ExecState* exec) const; // null string if not a string + JSObject* getObject() const; // 0 if not an object + + // Extracting integer values. + bool getUInt32(uint32_t&) const; + + // Basic conversions. + JSValue toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const; + bool getPrimitiveNumber(ExecState*, double& number, JSValue&); + + bool toBoolean(ExecState*) const; + + // toNumber conversion is expected to be side effect free if an exception has + // been set in the ExecState already. + double toNumber(ExecState*) const; + JSString* toString(ExecState*) const; + JSObject* toObject(ExecState*) const; + JSObject* toObject(ExecState*, JSGlobalObject*) const; + + // Integer conversions. + JS_EXPORT_PRIVATE double toInteger(ExecState*) const; + double toIntegerPreserveNaN(ExecState*) const; + int32_t toInt32(ExecState*) const; + uint32_t toUInt32(ExecState*) const; + + // Floating point conversions (this is a convenience method for webcore; + // signle precision float is not a representation used in JS or JSC). + float toFloat(ExecState* exec) const { return static_cast(toNumber(exec)); } + + // Object operations, with the toObject operation included. + JSValue get(ExecState*, const Identifier& propertyName) const; + JSValue get(ExecState*, const Identifier& propertyName, PropertySlot&) const; + JSValue get(ExecState*, unsigned propertyName) const; + JSValue get(ExecState*, unsigned propertyName, PropertySlot&) const; + void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); + void put(ExecState*, unsigned propertyName, JSValue); + + JSObject* toThisObject(ExecState*) const; + + static bool equal(ExecState* exec, JSValue v1, JSValue v2); + static bool equalSlowCase(ExecState* exec, JSValue v1, JSValue v2); + static bool equalSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2); + static bool strictEqual(ExecState* exec, JSValue v1, JSValue v2); + static bool strictEqualSlowCase(ExecState* exec, JSValue v1, JSValue v2); + static bool strictEqualSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2); + + bool isCell() const; + JSCell* asCell() const; + JS_EXPORT_PRIVATE bool isValidCallee(); + +#ifndef NDEBUG + char* description(); +#endif + + private: + template JSValue(WriteBarrierBase); + + enum HashTableDeletedValueTag { HashTableDeletedValue }; + JSValue(HashTableDeletedValueTag); + + inline const JSValue asValue() const { return *this; } + JS_EXPORT_PRIVATE double toNumberSlowCase(ExecState*) const; + JSString* toStringSlowCase(ExecState*) const; + JS_EXPORT_PRIVATE JSObject* toObjectSlowCase(ExecState*, JSGlobalObject*) const; + JS_EXPORT_PRIVATE JSObject* toThisObjectSlowCase(ExecState*) const; + + JS_EXPORT_PRIVATE JSObject* synthesizePrototype(ExecState*) const; + JSObject* synthesizeObject(ExecState*) const; + +#if USE(JSVALUE32_64) + /* + * On 32-bit platforms USE(JSVALUE32_64) should be defined, and we use a NaN-encoded + * form for immediates. + * + * The encoding makes use of unused NaN space in the IEEE754 representation. Any value + * with the top 13 bits set represents a QNaN (with the sign bit set). QNaN values + * can encode a 51-bit payload. Hardware produced and C-library payloads typically + * have a payload of zero. We assume that non-zero payloads are available to encode + * pointer and integer values. Since any 64-bit bit pattern where the top 15 bits are + * all set represents a NaN with a non-zero payload, we can use this space in the NaN + * ranges to encode other values (however there are also other ranges of NaN space that + * could have been selected). + * + * For JSValues that do not contain a double value, the high 32 bits contain the tag + * values listed in the enums below, which all correspond to NaN-space. In the case of + * cell, integer and bool values the lower 32 bits (the 'payload') contain the pointer + * integer or boolean value; in the case of all other tags the payload is 0. + */ + enum { Int32Tag = 0xffffffff }; + enum { BooleanTag = 0xfffffffe }; + enum { NullTag = 0xfffffffd }; + enum { UndefinedTag = 0xfffffffc }; + enum { CellTag = 0xfffffffb }; + enum { EmptyValueTag = 0xfffffffa }; + enum { DeletedValueTag = 0xfffffff9 }; + + enum { LowestTag = DeletedValueTag }; + + uint32_t tag() const; + int32_t payload() const; +#elif USE(JSVALUE64) + /* + * On 64-bit platforms USE(JSVALUE64) should be defined, and we use a NaN-encoded + * form for immediates. + * + * The encoding makes use of unused NaN space in the IEEE754 representation. Any value + * with the top 13 bits set represents a QNaN (with the sign bit set). QNaN values + * can encode a 51-bit payload. Hardware produced and C-library payloads typically + * have a payload of zero. We assume that non-zero payloads are available to encode + * pointer and integer values. Since any 64-bit bit pattern where the top 15 bits are + * all set represents a NaN with a non-zero payload, we can use this space in the NaN + * ranges to encode other values (however there are also other ranges of NaN space that + * could have been selected). + * + * This range of NaN space is represented by 64-bit numbers begining with the 16-bit + * hex patterns 0xFFFE and 0xFFFF - we rely on the fact that no valid double-precision + * numbers will begin fall in these ranges. + * + * The top 16-bits denote the type of the encoded JSValue: + * + * Pointer { 0000:PPPP:PPPP:PPPP + * / 0001:****:****:**** + * Double { ... + * \ FFFE:****:****:**** + * Integer { FFFF:0000:IIII:IIII + * + * The scheme we have implemented encodes double precision values by performing a + * 64-bit integer addition of the value 2^48 to the number. After this manipulation + * no encoded double-precision value will begin with the pattern 0x0000 or 0xFFFF. + * Values must be decoded by reversing this operation before subsequent floating point + * operations my be peformed. + * + * 32-bit signed integers are marked with the 16-bit tag 0xFFFF. + * + * The tag 0x0000 denotes a pointer, or another form of tagged immediate. Boolean, + * null and undefined values are represented by specific, invalid pointer values: + * + * False: 0x06 + * True: 0x07 + * Undefined: 0x0a + * Null: 0x02 + * + * These values have the following properties: + * - Bit 1 (TagBitTypeOther) is set for all four values, allowing real pointers to be + * quickly distinguished from all immediate values, including these invalid pointers. + * - With bit 3 is masked out (TagBitUndefined) Undefined and Null share the + * same value, allowing null & undefined to be quickly detected. + * + * No valid JSValue will have the bit pattern 0x0, this is used to represent array + * holes, and as a C++ 'no value' result (e.g. JSValue() has an internal value of 0). + */ + + // These values are #defines since using static const integers here is a ~1% regression! + + // This value is 2^48, used to encode doubles such that the encoded value will begin + // with a 16-bit pattern within the range 0x0001..0xFFFE. + #define DoubleEncodeOffset 0x1000000000000ll + // If all bits in the mask are set, this indicates an integer number, + // if any but not all are set this value is a double precision number. + #define TagTypeNumber 0xffff000000000000ll + + // All non-numeric (bool, null, undefined) immediates have bit 2 set. + #define TagBitTypeOther 0x2ll + #define TagBitBool 0x4ll + #define TagBitUndefined 0x8ll + // Combined integer value for non-numeric immediates. + #define ValueFalse (TagBitTypeOther | TagBitBool | false) + #define ValueTrue (TagBitTypeOther | TagBitBool | true) + #define ValueUndefined (TagBitTypeOther | TagBitUndefined) + #define ValueNull (TagBitTypeOther) + + // TagMask is used to check for all types of immediate values (either number or 'other'). + #define TagMask (TagTypeNumber | TagBitTypeOther) + + // These special values are never visible to JavaScript code; Empty is used to represent + // Array holes, and for uninitialized JSValues. Deleted is used in hash table code. + // These values would map to cell types in the JSValue encoding, but not valid GC cell + // pointer should have either of these values (Empty is null, deleted is at an invalid + // alignment for a GC cell, and in the zero page). + #define ValueEmpty 0x0ll + #define ValueDeleted 0x4ll +#endif + + EncodedValueDescriptor u; + }; + +#if USE(JSVALUE32_64) + typedef IntHash EncodedJSValueHash; + + struct EncodedJSValueHashTraits : HashTraits { + static const bool emptyValueIsZero = false; + static EncodedJSValue emptyValue() { return JSValue::encode(JSValue()); } + static void constructDeletedValue(EncodedJSValue& slot) { slot = JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); } + static bool isDeletedValue(EncodedJSValue value) { return value == JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); } + }; +#else + typedef PtrHash EncodedJSValueHash; + + struct EncodedJSValueHashTraits : HashTraits { + static void constructDeletedValue(EncodedJSValue& slot) { slot = JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); } + static bool isDeletedValue(EncodedJSValue value) { return value == JSValue::encode(JSValue(JSValue::HashTableDeletedValue)); } + }; +#endif + + typedef HashMap JSValueMap; + + // Stand-alone helper functions. + inline JSValue jsNull() + { + return JSValue(JSValue::JSNull); + } + + inline JSValue jsUndefined() + { + return JSValue(JSValue::JSUndefined); + } + + inline JSValue jsBoolean(bool b) + { + return b ? JSValue(JSValue::JSTrue) : JSValue(JSValue::JSFalse); + } + + ALWAYS_INLINE JSValue jsDoubleNumber(double d) + { + ASSERT(JSValue(JSValue::EncodeAsDouble, d).isNumber()); + return JSValue(JSValue::EncodeAsDouble, d); + } + + ALWAYS_INLINE JSValue jsNumber(double d) + { + ASSERT(JSValue(d).isNumber()); + return JSValue(d); + } + + ALWAYS_INLINE JSValue jsNumber(char i) + { + return JSValue(i); + } + + ALWAYS_INLINE JSValue jsNumber(unsigned char i) + { + return JSValue(i); + } + + ALWAYS_INLINE JSValue jsNumber(short i) + { + return JSValue(i); + } + + ALWAYS_INLINE JSValue jsNumber(unsigned short i) + { + return JSValue(i); + } + + ALWAYS_INLINE JSValue jsNumber(int i) + { + return JSValue(i); + } + + ALWAYS_INLINE JSValue jsNumber(unsigned i) + { + return JSValue(i); + } + + ALWAYS_INLINE JSValue jsNumber(long i) + { + return JSValue(i); + } + + ALWAYS_INLINE JSValue jsNumber(unsigned long i) + { + return JSValue(i); + } + + ALWAYS_INLINE JSValue jsNumber(long long i) + { + return JSValue(i); + } + + ALWAYS_INLINE JSValue jsNumber(unsigned long long i) + { + return JSValue(i); + } + + inline bool operator==(const JSValue a, const JSCell* b) { return a == JSValue(b); } + inline bool operator==(const JSCell* a, const JSValue b) { return JSValue(a) == b; } + + inline bool operator!=(const JSValue a, const JSCell* b) { return a != JSValue(b); } + inline bool operator!=(const JSCell* a, const JSValue b) { return JSValue(a) != b; } + +} // namespace JSC + +#endif // JSValue_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSValueInlineMethods.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSValueInlineMethods.h new file mode 100644 index 000000000..e13d34745 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSValueInlineMethods.h @@ -0,0 +1,498 @@ +/* + * Copyright (C) 2011 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 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 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 JSValueInlineMethods_h +#define JSValueInlineMethods_h + +#include "JSValue.h" + +namespace JSC { + + ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const + { + if (isInt32()) + return asInt32(); + return JSC::toInt32(toNumber(exec)); + } + + inline uint32_t JSValue::toUInt32(ExecState* exec) const + { + // See comment on JSC::toUInt32, above. + return toInt32(exec); + } + + inline bool JSValue::isUInt32() const + { + return isInt32() && asInt32() >= 0; + } + + inline uint32_t JSValue::asUInt32() const + { + ASSERT(isUInt32()); + return asInt32(); + } + + inline double JSValue::asNumber() const + { + ASSERT(isNumber()); + return isInt32() ? asInt32() : asDouble(); + } + + inline JSValue jsNaN() + { + return JSValue(std::numeric_limits::quiet_NaN()); + } + + inline JSValue::JSValue(char i) + { + *this = JSValue(static_cast(i)); + } + + inline JSValue::JSValue(unsigned char i) + { + *this = JSValue(static_cast(i)); + } + + inline JSValue::JSValue(short i) + { + *this = JSValue(static_cast(i)); + } + + inline JSValue::JSValue(unsigned short i) + { + *this = JSValue(static_cast(i)); + } + + inline JSValue::JSValue(unsigned i) + { + if (static_cast(i) < 0) { + *this = JSValue(EncodeAsDouble, static_cast(i)); + return; + } + *this = JSValue(static_cast(i)); + } + + inline JSValue::JSValue(long i) + { + if (static_cast(i) != i) { + *this = JSValue(EncodeAsDouble, static_cast(i)); + return; + } + *this = JSValue(static_cast(i)); + } + + inline JSValue::JSValue(unsigned long i) + { + if (static_cast(i) != i) { + *this = JSValue(EncodeAsDouble, static_cast(i)); + return; + } + *this = JSValue(static_cast(i)); + } + + inline JSValue::JSValue(long long i) + { + if (static_cast(i) != i) { + *this = JSValue(EncodeAsDouble, static_cast(i)); + return; + } + *this = JSValue(static_cast(i)); + } + + inline JSValue::JSValue(unsigned long long i) + { + if (static_cast(i) != i) { + *this = JSValue(EncodeAsDouble, static_cast(i)); + return; + } + *this = JSValue(static_cast(i)); + } + + inline JSValue::JSValue(double d) + { + const int32_t asInt32 = static_cast(d); + if (asInt32 != d || (!asInt32 && signbit(d))) { // true for -0.0 + *this = JSValue(EncodeAsDouble, d); + return; + } + *this = JSValue(static_cast(d)); + } + +#if USE(JSVALUE32_64) + inline EncodedJSValue JSValue::encode(JSValue value) + { + return value.u.asInt64; + } + + inline JSValue JSValue::decode(EncodedJSValue encodedJSValue) + { + JSValue v; + v.u.asInt64 = encodedJSValue; + return v; + } + + inline JSValue::JSValue() + { + u.asBits.tag = EmptyValueTag; + u.asBits.payload = 0; + } + + inline JSValue::JSValue(JSNullTag) + { + u.asBits.tag = NullTag; + u.asBits.payload = 0; + } + + inline JSValue::JSValue(JSUndefinedTag) + { + u.asBits.tag = UndefinedTag; + u.asBits.payload = 0; + } + + inline JSValue::JSValue(JSTrueTag) + { + u.asBits.tag = BooleanTag; + u.asBits.payload = 1; + } + + inline JSValue::JSValue(JSFalseTag) + { + u.asBits.tag = BooleanTag; + u.asBits.payload = 0; + } + + inline JSValue::JSValue(HashTableDeletedValueTag) + { + u.asBits.tag = DeletedValueTag; + u.asBits.payload = 0; + } + + inline JSValue::JSValue(JSCell* ptr) + { + if (ptr) + u.asBits.tag = CellTag; + else + u.asBits.tag = EmptyValueTag; + u.asBits.payload = reinterpret_cast(ptr); + } + + inline JSValue::JSValue(const JSCell* ptr) + { + if (ptr) + u.asBits.tag = CellTag; + else + u.asBits.tag = EmptyValueTag; + u.asBits.payload = reinterpret_cast(const_cast(ptr)); + } + + inline JSValue::operator bool() const + { + ASSERT(tag() != DeletedValueTag); + return tag() != EmptyValueTag; + } + + inline bool JSValue::operator==(const JSValue& other) const + { + return u.asInt64 == other.u.asInt64; + } + + inline bool JSValue::operator!=(const JSValue& other) const + { + return u.asInt64 != other.u.asInt64; + } + + inline bool JSValue::isEmpty() const + { + return tag() == EmptyValueTag; + } + + inline bool JSValue::isUndefined() const + { + return tag() == UndefinedTag; + } + + inline bool JSValue::isNull() const + { + return tag() == NullTag; + } + + inline bool JSValue::isUndefinedOrNull() const + { + return isUndefined() || isNull(); + } + + inline bool JSValue::isCell() const + { + return tag() == CellTag; + } + + inline bool JSValue::isInt32() const + { + return tag() == Int32Tag; + } + + inline bool JSValue::isDouble() const + { + return tag() < LowestTag; + } + + inline bool JSValue::isTrue() const + { + return tag() == BooleanTag && payload(); + } + + inline bool JSValue::isFalse() const + { + return tag() == BooleanTag && !payload(); + } + + inline uint32_t JSValue::tag() const + { + return u.asBits.tag; + } + + inline int32_t JSValue::payload() const + { + return u.asBits.payload; + } + + inline int32_t JSValue::asInt32() const + { + ASSERT(isInt32()); + return u.asBits.payload; + } + + inline double JSValue::asDouble() const + { + ASSERT(isDouble()); + return u.asDouble; + } + + ALWAYS_INLINE JSCell* JSValue::asCell() const + { + ASSERT(isCell()); + return reinterpret_cast(u.asBits.payload); + } + + ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, double d) + { + u.asDouble = d; + } + + inline JSValue::JSValue(int i) + { + u.asBits.tag = Int32Tag; + u.asBits.payload = i; + } + + inline bool JSValue::isNumber() const + { + return isInt32() || isDouble(); + } + + inline bool JSValue::isBoolean() const + { + return isTrue() || isFalse(); + } + + inline bool JSValue::asBoolean() const + { + ASSERT(isBoolean()); + return payload(); + } + +#else // USE(JSVALUE32_64) + + // JSValue member functions. + inline EncodedJSValue JSValue::encode(JSValue value) + { + return value.u.ptr; + } + + inline JSValue JSValue::decode(EncodedJSValue ptr) + { + return JSValue(reinterpret_cast(ptr)); + } + + // 0x0 can never occur naturally because it has a tag of 00, indicating a pointer value, but a payload of 0x0, which is in the (invalid) zero page. + inline JSValue::JSValue() + { + u.asInt64 = ValueEmpty; + } + + // 0x4 can never occur naturally because it has a tag of 00, indicating a pointer value, but a payload of 0x4, which is in the (invalid) zero page. + inline JSValue::JSValue(HashTableDeletedValueTag) + { + u.asInt64 = ValueDeleted; + } + + inline JSValue::JSValue(JSCell* ptr) + { + u.ptr = ptr; + } + + inline JSValue::JSValue(const JSCell* ptr) + { + u.ptr = const_cast(ptr); + } + + inline JSValue::operator bool() const + { + return u.ptr; + } + + inline bool JSValue::operator==(const JSValue& other) const + { + return u.ptr == other.u.ptr; + } + + inline bool JSValue::operator!=(const JSValue& other) const + { + return u.ptr != other.u.ptr; + } + + inline bool JSValue::isEmpty() const + { + return u.asInt64 == ValueEmpty; + } + + inline bool JSValue::isUndefined() const + { + return asValue() == JSValue(JSUndefined); + } + + inline bool JSValue::isNull() const + { + return asValue() == JSValue(JSNull); + } + + inline bool JSValue::isTrue() const + { + return asValue() == JSValue(JSTrue); + } + + inline bool JSValue::isFalse() const + { + return asValue() == JSValue(JSFalse); + } + + inline bool JSValue::asBoolean() const + { + ASSERT(isBoolean()); + return asValue() == JSValue(JSTrue); + } + + inline int32_t JSValue::asInt32() const + { + ASSERT(isInt32()); + return static_cast(u.asInt64); + } + + inline bool JSValue::isDouble() const + { + return isNumber() && !isInt32(); + } + + inline JSValue::JSValue(JSNullTag) + { + u.asInt64 = ValueNull; + } + + inline JSValue::JSValue(JSUndefinedTag) + { + u.asInt64 = ValueUndefined; + } + + inline JSValue::JSValue(JSTrueTag) + { + u.asInt64 = ValueTrue; + } + + inline JSValue::JSValue(JSFalseTag) + { + u.asInt64 = ValueFalse; + } + + inline bool JSValue::isUndefinedOrNull() const + { + // Undefined and null share the same value, bar the 'undefined' bit in the extended tag. + return (u.asInt64 & ~TagBitUndefined) == ValueNull; + } + + inline bool JSValue::isBoolean() const + { + return (u.asInt64 & ~1) == ValueFalse; + } + + inline bool JSValue::isCell() const + { + return !(u.asInt64 & TagMask); + } + + inline bool JSValue::isInt32() const + { + return (u.asInt64 & TagTypeNumber) == TagTypeNumber; + } + + inline intptr_t reinterpretDoubleToIntptr(double value) + { + return bitwise_cast(value); + } + inline double reinterpretIntptrToDouble(intptr_t value) + { + return bitwise_cast(value); + } + + ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, double d) + { + u.asInt64 = reinterpretDoubleToIntptr(d) + DoubleEncodeOffset; + } + + inline JSValue::JSValue(int i) + { + u.asInt64 = TagTypeNumber | static_cast(i); + } + + inline double JSValue::asDouble() const + { + return reinterpretIntptrToDouble(u.asInt64 - DoubleEncodeOffset); + } + + inline bool JSValue::isNumber() const + { + return u.asInt64 & TagTypeNumber; + } + + ALWAYS_INLINE JSCell* JSValue::asCell() const + { + ASSERT(isCell()); + return u.ptr; + } + +#endif // USE(JSVALUE64) + +} // namespace JSC + +#endif // JSValueInlineMethods_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSVariableObject.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSVariableObject.h new file mode 100644 index 000000000..c1d05ff74 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSVariableObject.h @@ -0,0 +1,173 @@ +/* + * 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. + * 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 JSVariableObject_h +#define JSVariableObject_h + +#include "JSObject.h" +#include "Register.h" +#include "SymbolTable.h" +#include "UnusedParam.h" +#include +#include + +namespace JSC { + + class Register; + + class JSVariableObject : public JSNonFinalObject { + friend class JIT; + + public: + typedef JSNonFinalObject Base; + + SymbolTable& symbolTable() const { return *m_symbolTable; } + + JS_EXPORT_PRIVATE static void destroy(JSCell*); + + static NO_RETURN_DUE_TO_ASSERT void putDirectVirtual(JSObject*, ExecState*, const Identifier&, JSValue, unsigned attributes); + + JS_EXPORT_PRIVATE static bool deleteProperty(JSCell*, ExecState*, const Identifier&); + JS_EXPORT_PRIVATE static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); + + bool isDynamicScope(bool& requiresDynamicChecks) const; + + WriteBarrier& registerAt(int index) const { return m_registers[index]; } + + WriteBarrier* const * addressOfRegisters() const { return &m_registers; } + static size_t offsetOfRegisters() { return OBJECT_OFFSETOF(JSVariableObject, m_registers); } + + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + { + return Structure::create(globalData, globalObject, prototype, TypeInfo(VariableObjectType, StructureFlags), &s_info); + } + + protected: + static const unsigned StructureFlags = OverridesGetPropertyNames | JSNonFinalObject::StructureFlags; + + JSVariableObject(JSGlobalData& globalData, Structure* structure, SymbolTable* symbolTable, Register* registers) + : JSNonFinalObject(globalData, structure) + , m_symbolTable(symbolTable) + , m_registers(reinterpret_cast*>(registers)) + { + } + + void finishCreation(JSGlobalData& globalData) + { + Base::finishCreation(globalData); + ASSERT(m_symbolTable); + COMPILE_ASSERT(sizeof(WriteBarrier) == sizeof(Register), Register_should_be_same_size_as_WriteBarrier); + } + + PassOwnArrayPtr > copyRegisterArray(JSGlobalData&, WriteBarrier* src, size_t count, size_t callframeStarts); + void setRegisters(WriteBarrier* registers, PassOwnArrayPtr > registerArray); + + bool symbolTableGet(const Identifier&, PropertySlot&); + JS_EXPORT_PRIVATE bool symbolTableGet(const Identifier&, PropertyDescriptor&); + bool symbolTableGet(const Identifier&, PropertySlot&, bool& slotIsWriteable); + bool symbolTablePut(ExecState*, const Identifier&, JSValue, bool shouldThrow); + bool symbolTablePutWithAttributes(JSGlobalData&, const Identifier&, JSValue, unsigned attributes); + + SymbolTable* m_symbolTable; // Maps name -> offset from "r" in register file. + WriteBarrier* m_registers; // "r" in the register file. + OwnArrayPtr > m_registerArray; // Independent copy of registers, used when a variable object copies its registers out of the register file. + }; + + inline bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertySlot& slot) + { + SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl()); + if (!entry.isNull()) { + slot.setValue(registerAt(entry.getIndex()).get()); + return true; + } + return false; + } + + inline bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertySlot& slot, bool& slotIsWriteable) + { + SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl()); + if (!entry.isNull()) { + slot.setValue(registerAt(entry.getIndex()).get()); + slotIsWriteable = !entry.isReadOnly(); + return true; + } + return false; + } + + inline bool JSVariableObject::symbolTablePut(ExecState* exec, const Identifier& propertyName, JSValue value, bool shouldThrow) + { + JSGlobalData& globalData = exec->globalData(); + ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); + + SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl()); + if (entry.isNull()) + return false; + if (entry.isReadOnly()) { + if (shouldThrow) + throwTypeError(exec, StrictModeReadonlyPropertyWriteError); + return true; + } + registerAt(entry.getIndex()).set(globalData, this, value); + return true; + } + + inline bool JSVariableObject::symbolTablePutWithAttributes(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes) + { + ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); + + SymbolTable::iterator iter = symbolTable().find(propertyName.impl()); + if (iter == symbolTable().end()) + return false; + SymbolTableEntry& entry = iter->second; + ASSERT(!entry.isNull()); + entry.setAttributes(attributes); + registerAt(entry.getIndex()).set(globalData, this, value); + return true; + } + + inline PassOwnArrayPtr > JSVariableObject::copyRegisterArray(JSGlobalData& globalData, WriteBarrier* src, size_t count, size_t callframeStarts) + { + OwnArrayPtr > registerArray = adoptArrayPtr(new WriteBarrier[count]); + for (size_t i = 0; i < callframeStarts; i++) + registerArray[i].set(globalData, this, src[i].get()); + for (size_t i = callframeStarts + RegisterFile::CallFrameHeaderSize; i < count; i++) + registerArray[i].set(globalData, this, src[i].get()); + + return registerArray.release(); + } + + inline void JSVariableObject::setRegisters(WriteBarrier* registers, PassOwnArrayPtr > registerArray) + { + ASSERT(registerArray != m_registerArray); + m_registerArray = registerArray; + m_registers = registers; + } + +} // namespace JSC + +#endif // JSVariableObject_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSWeakObjectMapRefInternal.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSWeakObjectMapRefInternal.h new file mode 100644 index 000000000..f7b91da51 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSWeakObjectMapRefInternal.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2010 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 INC. 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 INC. 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 JSWeakObjectMapRefInternal_h +#define JSWeakObjectMapRefInternal_h + +#include "WeakGCMap.h" +#include + +namespace JSC { + +class JSObject; + +} + +typedef void (*JSWeakMapDestroyedCallback)(struct OpaqueJSWeakObjectMap*, void*); + +typedef JSC::WeakGCMap WeakMapType; + +struct OpaqueJSWeakObjectMap : public RefCounted { +public: + static PassRefPtr create(void* data, JSWeakMapDestroyedCallback callback) + { + return adoptRef(new OpaqueJSWeakObjectMap(data, callback)); + } + + WeakMapType& map() { return m_map; } + + ~OpaqueJSWeakObjectMap() + { + m_callback(this, m_data); + } + +private: + OpaqueJSWeakObjectMap(void* data, JSWeakMapDestroyedCallback callback) + : m_data(data) + , m_callback(callback) + { + } + WeakMapType m_map; + void* m_data; + JSWeakMapDestroyedCallback m_callback; +}; + + +#endif // JSWeakObjectMapInternal_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSWeakObjectMapRefPrivate.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSWeakObjectMapRefPrivate.h new file mode 100644 index 000000000..5a07cf7c4 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSWeakObjectMapRefPrivate.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2010 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 INC. 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 INC. 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 JSWeakObjectMapRefPrivate_h +#define JSWeakObjectMapRefPrivate_h + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*! @typedef JSWeakObjectMapRef A weak map for storing JSObjectRefs */ +typedef struct OpaqueJSWeakObjectMap* JSWeakObjectMapRef; + +/*! + @typedef JSWeakMapDestroyedCallback + @abstract The callback invoked when a JSWeakObjectMapRef is being destroyed. + @param map The map that is being destroyed. + @param data The private data (if any) that was associated with the map instance. + */ +typedef void (*JSWeakMapDestroyedCallback)(JSWeakObjectMapRef map, void* data); + +/*! + @function + @abstract Creates a weak value map that can be used to reference user defined objects without preventing them from being collected. + @param ctx The execution context to use. + @param data A void* to set as the map's private data. Pass NULL to specify no private data. + @param destructor A function to call when the weak map is destroyed. + @result A JSWeakObjectMapRef bound to the given context, data and destructor. + @discussion The JSWeakObjectMapRef can be used as a storage mechanism to hold custom JS objects without forcing those objects to + remain live as JSValueProtect would. + */ +JS_EXPORT JSWeakObjectMapRef JSWeakObjectMapCreate(JSContextRef ctx, void* data, JSWeakMapDestroyedCallback destructor); + +/*! + @function + @abstract Associates a JSObjectRef with the given key in a JSWeakObjectMap. + @param ctx The execution context to use. + @param map The map to operate on. + @param key The key to associate a weak reference with. + @param object The user defined object to associate with the key. + */ +JS_EXPORT void JSWeakObjectMapSet(JSContextRef ctx, JSWeakObjectMapRef map, void* key, JSObjectRef); + +/*! + @function + @abstract Retrieves the JSObjectRef associated with a key. + @param ctx The execution context to use. + @param map The map to query. + @param key The key to search for. + @result Either the live object associated with the provided key, or NULL. + */ +JS_EXPORT JSObjectRef JSWeakObjectMapGet(JSContextRef ctx, JSWeakObjectMapRef map, void* key); + +/*! + @function + @abstract Removes the entry for the given key if the key is present, otherwise it has no effect. + @param ctx The execution context to use. + @param map The map to use. + @param key The key to remove. + */ +JS_EXPORT void JSWeakObjectMapRemove(JSContextRef ctx, JSWeakObjectMapRef map, void* key); + +#ifdef __cplusplus +} +#endif + +#endif // JSWeakObjectMapPrivate_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSWrapperObject.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSWrapperObject.h new file mode 100644 index 000000000..65b4bdb7f --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/JSWrapperObject.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2006 Maks Orlovich + * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef JSWrapperObject_h +#define JSWrapperObject_h + +#include "JSObject.h" + +namespace JSC { + + // This class is used as a base for classes such as String, + // Number, Boolean and Date which are wrappers for primitive types. + class JSWrapperObject : public JSNonFinalObject { + public: + typedef JSNonFinalObject Base; + + JSValue internalValue() const; + void setInternalValue(JSGlobalData&, JSValue); + + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + { + return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); + } + + protected: + explicit JSWrapperObject(JSGlobalData&, Structure*); + static const unsigned StructureFlags = OverridesVisitChildren | JSNonFinalObject::StructureFlags; + + static void visitChildren(JSCell*, SlotVisitor&); + + private: + WriteBarrier m_internalValue; + }; + + inline JSWrapperObject::JSWrapperObject(JSGlobalData& globalData, Structure* structure) + : JSNonFinalObject(globalData, structure) + { + } + + inline JSValue JSWrapperObject::internalValue() const + { + return m_internalValue.get(); + } + + inline void JSWrapperObject::setInternalValue(JSGlobalData& globalData, JSValue value) + { + ASSERT(value); + ASSERT(!value.isObject()); + m_internalValue.set(globalData, this, value); + } + +} // namespace JSC + +#endif // JSWrapperObject_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/LineInfo.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/LineInfo.h new file mode 100644 index 000000000..e9e70138a --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/LineInfo.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2012 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 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 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 LineInfo_h +#define LineInfo_h + +#include + +namespace JSC { + +struct LineInfo { + uint32_t instructionOffset; + int32_t lineNumber; +}; + +} // namespace JSC + +#endif // LineInfo_h + diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ListHashSet.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ListHashSet.h new file mode 100644 index 000000000..32bd23832 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ListHashSet.h @@ -0,0 +1,853 @@ +/* + * Copyright (C) 2005, 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. + * Copyright (C) 2011, Benjamin Poulain + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WTF_ListHashSet_h +#define WTF_ListHashSet_h + +#include "HashSet.h" +#include "OwnPtr.h" +#include "PassOwnPtr.h" + +namespace WTF { + + // ListHashSet: Just like HashSet, this class provides a Set + // interface - a collection of unique objects with O(1) insertion, + // removal and test for containership. However, it also has an + // order - iterating it will always give back values in the order + // in which they are added. + + // In theory it would be possible to add prepend, insertAfter + // and an append that moves the element to the end even if already present, + // but unclear yet if these are needed. + + template class ListHashSet; + + template + void deleteAllValues(const ListHashSet&); + + template class ListHashSetIterator; + template class ListHashSetConstIterator; + template class ListHashSetReverseIterator; + template class ListHashSetConstReverseIterator; + + template struct ListHashSetNode; + template struct ListHashSetNodeAllocator; + + template struct ListHashSetNodeHashFunctions; + template struct ListHashSetTranslator; + + template::Hash> class ListHashSet { + WTF_MAKE_FAST_ALLOCATED; + private: + typedef ListHashSetNode Node; + typedef ListHashSetNodeAllocator NodeAllocator; + + typedef HashTraits NodeTraits; + typedef ListHashSetNodeHashFunctions NodeHash; + typedef ListHashSetTranslator BaseTranslator; + + typedef HashTable ImplType; + typedef HashTableIterator ImplTypeIterator; + typedef HashTableConstIterator ImplTypeConstIterator; + + typedef HashArg HashFunctions; + + public: + typedef ValueArg ValueType; + + typedef ListHashSetIterator iterator; + typedef ListHashSetConstIterator const_iterator; + friend class ListHashSetConstIterator; + + typedef ListHashSetReverseIterator reverse_iterator; + typedef ListHashSetConstReverseIterator const_reverse_iterator; + friend class ListHashSetConstReverseIterator; + + ListHashSet(); + ListHashSet(const ListHashSet&); + ListHashSet& operator=(const ListHashSet&); + ~ListHashSet(); + + void swap(ListHashSet&); + + int size() const; + int capacity() const; + bool isEmpty() const; + + iterator begin(); + iterator end(); + const_iterator begin() const; + const_iterator end() const; + + reverse_iterator rbegin(); + reverse_iterator rend(); + const_reverse_iterator rbegin() const; + const_reverse_iterator rend() const; + + ValueType& first(); + const ValueType& first() const; + + ValueType& last(); + const ValueType& last() const; + void removeLast(); + + iterator find(const ValueType&); + const_iterator find(const ValueType&) const; + bool contains(const ValueType&) const; + + // An alternate version of find() that finds the object by hashing and comparing + // with some other type, to avoid the cost of type conversion. + // The HashTranslator interface is defined in HashSet. + // FIXME: We should reverse the order of the template arguments so that callers + // can just pass the translator let the compiler deduce T. + template iterator find(const T&); + template const_iterator find(const T&) const; + template bool contains(const T&) const; + + // The return value of add is a pair of an iterator to the new value's location, + // and a bool that is true if an new entry was added. + pair add(const ValueType&); + + pair insertBefore(const ValueType& beforeValue, const ValueType& newValue); + pair insertBefore(iterator it, const ValueType&); + + void remove(const ValueType&); + void remove(iterator); + void clear(); + + private: + void unlinkAndDelete(Node*); + void appendNode(Node*); + void insertNodeBefore(Node* beforeNode, Node* newNode); + void deleteAllNodes(); + + iterator makeIterator(Node*); + const_iterator makeConstIterator(Node*) const; + reverse_iterator makeReverseIterator(Node*); + const_reverse_iterator makeConstReverseIterator(Node*) const; + + friend void deleteAllValues<>(const ListHashSet&); + + ImplType m_impl; + Node* m_head; + Node* m_tail; + OwnPtr m_allocator; + }; + + template struct ListHashSetNodeAllocator { + typedef ListHashSetNode Node; + typedef ListHashSetNodeAllocator NodeAllocator; + + ListHashSetNodeAllocator() + : m_freeList(pool()) + , m_isDoneWithInitialFreeList(false) + { + memset(m_pool.pool, 0, sizeof(m_pool.pool)); + } + + Node* allocate() + { + Node* result = m_freeList; + + if (!result) + return static_cast(fastMalloc(sizeof(Node))); + + ASSERT(!result->m_isAllocated); + + Node* next = result->m_next; + ASSERT(!next || !next->m_isAllocated); + if (!next && !m_isDoneWithInitialFreeList) { + next = result + 1; + if (next == pastPool()) { + m_isDoneWithInitialFreeList = true; + next = 0; + } else { + ASSERT(inPool(next)); + ASSERT(!next->m_isAllocated); + } + } + m_freeList = next; + + return result; + } + + void deallocate(Node* node) + { + if (inPool(node)) { +#ifndef NDEBUG + node->m_isAllocated = false; +#endif + node->m_next = m_freeList; + m_freeList = node; + return; + } + + fastFree(node); + } + + private: + Node* pool() { return reinterpret_cast_ptr(m_pool.pool); } + Node* pastPool() { return pool() + m_poolSize; } + + bool inPool(Node* node) + { + return node >= pool() && node < pastPool(); + } + + Node* m_freeList; + bool m_isDoneWithInitialFreeList; + static const size_t m_poolSize = inlineCapacity; + union { + char pool[sizeof(Node) * m_poolSize]; + double forAlignment; + } m_pool; + }; + + template struct ListHashSetNode { + typedef ListHashSetNodeAllocator NodeAllocator; + + ListHashSetNode(ValueArg value) + : m_value(value) + , m_prev(0) + , m_next(0) +#ifndef NDEBUG + , m_isAllocated(true) +#endif + { + } + + void* operator new(size_t, NodeAllocator* allocator) + { + return allocator->allocate(); + } + void destroy(NodeAllocator* allocator) + { + this->~ListHashSetNode(); + allocator->deallocate(this); + } + + ValueArg m_value; + ListHashSetNode* m_prev; + ListHashSetNode* m_next; + +#ifndef NDEBUG + bool m_isAllocated; +#endif + }; + + template struct ListHashSetNodeHashFunctions { + template static unsigned hash(const T& key) { return HashArg::hash(key->m_value); } + template static bool equal(const T& a, const T& b) { return HashArg::equal(a->m_value, b->m_value); } + static const bool safeToCompareToEmptyOrDeleted = false; + }; + + template class ListHashSetIterator { + private: + typedef ListHashSet ListHashSetType; + typedef ListHashSetIterator iterator; + typedef ListHashSetConstIterator const_iterator; + typedef ListHashSetNode Node; + typedef ValueArg ValueType; + typedef ValueType& ReferenceType; + typedef ValueType* PointerType; + + friend class ListHashSet; + + ListHashSetIterator(const ListHashSetType* set, Node* position) : m_iterator(set, position) { } + + public: + ListHashSetIterator() { } + + // default copy, assignment and destructor are OK + + PointerType get() const { return const_cast(m_iterator.get()); } + ReferenceType operator*() const { return *get(); } + PointerType operator->() const { return get(); } + + iterator& operator++() { ++m_iterator; return *this; } + + // postfix ++ intentionally omitted + + iterator& operator--() { --m_iterator; return *this; } + + // postfix -- intentionally omitted + + // Comparison. + bool operator==(const iterator& other) const { return m_iterator == other.m_iterator; } + bool operator!=(const iterator& other) const { return m_iterator != other.m_iterator; } + + operator const_iterator() const { return m_iterator; } + + private: + Node* node() { return m_iterator.node(); } + + const_iterator m_iterator; + }; + + template class ListHashSetConstIterator { + private: + typedef ListHashSet ListHashSetType; + typedef ListHashSetIterator iterator; + typedef ListHashSetConstIterator const_iterator; + typedef ListHashSetNode Node; + typedef ValueArg ValueType; + typedef const ValueType& ReferenceType; + typedef const ValueType* PointerType; + + friend class ListHashSet; + friend class ListHashSetIterator; + + ListHashSetConstIterator(const ListHashSetType* set, Node* position) + : m_set(set) + , m_position(position) + { + } + + public: + ListHashSetConstIterator() + { + } + + PointerType get() const + { + return &m_position->m_value; + } + ReferenceType operator*() const { return *get(); } + PointerType operator->() const { return get(); } + + const_iterator& operator++() + { + ASSERT(m_position != 0); + m_position = m_position->m_next; + return *this; + } + + // postfix ++ intentionally omitted + + const_iterator& operator--() + { + ASSERT(m_position != m_set->m_head); + if (!m_position) + m_position = m_set->m_tail; + else + m_position = m_position->m_prev; + return *this; + } + + // postfix -- intentionally omitted + + // Comparison. + bool operator==(const const_iterator& other) const + { + return m_position == other.m_position; + } + bool operator!=(const const_iterator& other) const + { + return m_position != other.m_position; + } + + private: + Node* node() { return m_position; } + + const ListHashSetType* m_set; + Node* m_position; + }; + + template class ListHashSetReverseIterator { + private: + typedef ListHashSet ListHashSetType; + typedef ListHashSetReverseIterator reverse_iterator; + typedef ListHashSetConstReverseIterator const_reverse_iterator; + typedef ListHashSetNode Node; + typedef ValueArg ValueType; + typedef ValueType& ReferenceType; + typedef ValueType* PointerType; + + friend class ListHashSet; + + ListHashSetReverseIterator(const ListHashSetType* set, Node* position) : m_iterator(set, position) { } + + public: + ListHashSetReverseIterator() { } + + // default copy, assignment and destructor are OK + + PointerType get() const { return const_cast(m_iterator.get()); } + ReferenceType operator*() const { return *get(); } + PointerType operator->() const { return get(); } + + reverse_iterator& operator++() { ++m_iterator; return *this; } + + // postfix ++ intentionally omitted + + reverse_iterator& operator--() { --m_iterator; return *this; } + + // postfix -- intentionally omitted + + // Comparison. + bool operator==(const reverse_iterator& other) const { return m_iterator == other.m_iterator; } + bool operator!=(const reverse_iterator& other) const { return m_iterator != other.m_iterator; } + + operator const_reverse_iterator() const { return m_iterator; } + + private: + Node* node() { return m_iterator.node(); } + + const_reverse_iterator m_iterator; + }; + + template class ListHashSetConstReverseIterator { + private: + typedef ListHashSet ListHashSetType; + typedef ListHashSetReverseIterator reverse_iterator; + typedef ListHashSetConstReverseIterator const_reverse_iterator; + typedef ListHashSetNode Node; + typedef ValueArg ValueType; + typedef const ValueType& ReferenceType; + typedef const ValueType* PointerType; + + friend class ListHashSet; + friend class ListHashSetReverseIterator; + + ListHashSetConstReverseIterator(const ListHashSetType* set, Node* position) + : m_set(set) + , m_position(position) + { + } + + public: + ListHashSetConstReverseIterator() + { + } + + PointerType get() const + { + return &m_position->m_value; + } + ReferenceType operator*() const { return *get(); } + PointerType operator->() const { return get(); } + + const_reverse_iterator& operator++() + { + ASSERT(m_position != 0); + m_position = m_position->m_prev; + return *this; + } + + // postfix ++ intentionally omitted + + const_reverse_iterator& operator--() + { + ASSERT(m_position != m_set->m_tail); + if (!m_position) + m_position = m_set->m_head; + else + m_position = m_position->m_next; + return *this; + } + + // postfix -- intentionally omitted + + // Comparison. + bool operator==(const const_reverse_iterator& other) const + { + return m_position == other.m_position; + } + bool operator!=(const const_reverse_iterator& other) const + { + return m_position != other.m_position; + } + + private: + Node* node() { return m_position; } + + const ListHashSetType* m_set; + Node* m_position; + }; + + template + struct ListHashSetTranslator { + template static unsigned hash(const T& key) { return HashFunctions::hash(key); } + template static bool equal(const T& a, const U& b) { return HashFunctions::equal(a->m_value, b); } + template static void translate(T*& location, const U& key, const V& allocator) + { + location = new (allocator) T(key); + } + }; + + template + inline ListHashSet::ListHashSet() + : m_head(0) + , m_tail(0) + , m_allocator(adoptPtr(new NodeAllocator)) + { + } + + template + inline ListHashSet::ListHashSet(const ListHashSet& other) + : m_head(0) + , m_tail(0) + , m_allocator(adoptPtr(new NodeAllocator)) + { + const_iterator end = other.end(); + for (const_iterator it = other.begin(); it != end; ++it) + add(*it); + } + + template + inline ListHashSet& ListHashSet::operator=(const ListHashSet& other) + { + ListHashSet tmp(other); + swap(tmp); + return *this; + } + + template + inline void ListHashSet::swap(ListHashSet& other) + { + m_impl.swap(other.m_impl); + std::swap(m_head, other.m_head); + std::swap(m_tail, other.m_tail); + m_allocator.swap(other.m_allocator); + } + + template + inline ListHashSet::~ListHashSet() + { + deleteAllNodes(); + } + + template + inline int ListHashSet::size() const + { + return m_impl.size(); + } + + template + inline int ListHashSet::capacity() const + { + return m_impl.capacity(); + } + + template + inline bool ListHashSet::isEmpty() const + { + return m_impl.isEmpty(); + } + + template + inline typename ListHashSet::iterator ListHashSet::begin() + { + return makeIterator(m_head); + } + + template + inline typename ListHashSet::iterator ListHashSet::end() + { + return makeIterator(0); + } + + template + inline typename ListHashSet::const_iterator ListHashSet::begin() const + { + return makeConstIterator(m_head); + } + + template + inline typename ListHashSet::const_iterator ListHashSet::end() const + { + return makeConstIterator(0); + } + + template + inline typename ListHashSet::reverse_iterator ListHashSet::rbegin() + { + return makeReverseIterator(m_tail); + } + + template + inline typename ListHashSet::reverse_iterator ListHashSet::rend() + { + return makeReverseIterator(0); + } + + template + inline typename ListHashSet::const_reverse_iterator ListHashSet::rbegin() const + { + return makeConstReverseIterator(m_tail); + } + + template + inline typename ListHashSet::const_reverse_iterator ListHashSet::rend() const + { + return makeConstReverseIterator(0); + } + + template + inline T& ListHashSet::first() + { + ASSERT(!isEmpty()); + return m_head->m_value; + } + + template + inline const T& ListHashSet::first() const + { + ASSERT(!isEmpty()); + return m_head->m_value; + } + + template + inline T& ListHashSet::last() + { + ASSERT(!isEmpty()); + return m_tail->m_value; + } + + template + inline const T& ListHashSet::last() const + { + ASSERT(!isEmpty()); + return m_tail->m_value; + } + + template + inline void ListHashSet::removeLast() + { + ASSERT(!isEmpty()); + m_impl.remove(m_tail); + unlinkAndDelete(m_tail); + } + + template + inline typename ListHashSet::iterator ListHashSet::find(const ValueType& value) + { + ImplTypeIterator it = m_impl.template find(value); + if (it == m_impl.end()) + return end(); + return makeIterator(*it); + } + + template + inline typename ListHashSet::const_iterator ListHashSet::find(const ValueType& value) const + { + ImplTypeConstIterator it = m_impl.template find(value); + if (it == m_impl.end()) + return end(); + return makeConstIterator(*it); + } + + template + struct ListHashSetTranslatorAdapter { + template static unsigned hash(const T& key) { return Translator::hash(key); } + template static bool equal(const T& a, const U& b) { return Translator::equal(a->m_value, b); } + }; + + template + template + inline typename ListHashSet::iterator ListHashSet::find(const T& value) + { + ImplTypeConstIterator it = m_impl.template find >(value); + if (it == m_impl.end()) + return end(); + return makeIterator(*it); + } + + template + template + inline typename ListHashSet::const_iterator ListHashSet::find(const T& value) const + { + ImplTypeConstIterator it = m_impl.template find >(value); + if (it == m_impl.end()) + return end(); + return makeConstIterator(*it); + } + + template + template + inline bool ListHashSet::contains(const T& value) const + { + return m_impl.template contains >(value); + } + + template + inline bool ListHashSet::contains(const ValueType& value) const + { + return m_impl.template contains(value); + } + + template + pair::iterator, bool> ListHashSet::add(const ValueType &value) + { + pair result = m_impl.template add(value, m_allocator.get()); + if (result.second) + appendNode(*result.first); + return std::make_pair(makeIterator(*result.first), result.second); + } + + template + pair::iterator, bool> ListHashSet::insertBefore(iterator it, const ValueType& newValue) + { + pair result = m_impl.template add(newValue, m_allocator.get()); + if (result.second) + insertNodeBefore(it.node(), *result.first); + return std::make_pair(makeIterator(*result.first), result.second); + + } + + template + pair::iterator, bool> ListHashSet::insertBefore(const ValueType& beforeValue, const ValueType& newValue) + { + return insertBefore(find(beforeValue), newValue); + } + + template + inline void ListHashSet::remove(iterator it) + { + if (it == end()) + return; + m_impl.remove(it.node()); + unlinkAndDelete(it.node()); + } + + template + inline void ListHashSet::remove(const ValueType& value) + { + remove(find(value)); + } + + template + inline void ListHashSet::clear() + { + deleteAllNodes(); + m_impl.clear(); + m_head = 0; + m_tail = 0; + } + + template + void ListHashSet::unlinkAndDelete(Node* node) + { + if (!node->m_prev) { + ASSERT(node == m_head); + m_head = node->m_next; + } else { + ASSERT(node != m_head); + node->m_prev->m_next = node->m_next; + } + + if (!node->m_next) { + ASSERT(node == m_tail); + m_tail = node->m_prev; + } else { + ASSERT(node != m_tail); + node->m_next->m_prev = node->m_prev; + } + + node->destroy(m_allocator.get()); + } + + template + void ListHashSet::appendNode(Node* node) + { + node->m_prev = m_tail; + node->m_next = 0; + + if (m_tail) { + ASSERT(m_head); + m_tail->m_next = node; + } else { + ASSERT(!m_head); + m_head = node; + } + + m_tail = node; + } + + template + void ListHashSet::insertNodeBefore(Node* beforeNode, Node* newNode) + { + if (!beforeNode) + return appendNode(newNode); + + newNode->m_next = beforeNode; + newNode->m_prev = beforeNode->m_prev; + if (beforeNode->m_prev) + beforeNode->m_prev->m_next = newNode; + beforeNode->m_prev = newNode; + + if (!newNode->m_prev) + m_head = newNode; + } + + template + void ListHashSet::deleteAllNodes() + { + if (!m_head) + return; + + for (Node* node = m_head, *next = m_head->m_next; node; node = next, next = node ? node->m_next : 0) + node->destroy(m_allocator.get()); + } + + template + inline ListHashSetReverseIterator ListHashSet::makeReverseIterator(Node* position) + { + return ListHashSetReverseIterator(this, position); + } + + template + inline ListHashSetConstReverseIterator ListHashSet::makeConstReverseIterator(Node* position) const + { + return ListHashSetConstReverseIterator(this, position); + } + + template + inline ListHashSetIterator ListHashSet::makeIterator(Node* position) + { + return ListHashSetIterator(this, position); + } + + template + inline ListHashSetConstIterator ListHashSet::makeConstIterator(Node* position) const + { + return ListHashSetConstIterator(this, position); + } + template + void deleteAllValues(HashTableType& collection) + { + typedef typename HashTableType::const_iterator iterator; + iterator end = collection.end(); + for (iterator it = collection.begin(); it != end; ++it) + delete (*it)->m_value; + } + + template + inline void deleteAllValues(const ListHashSet& collection) + { + deleteAllValues::ValueType>(collection.m_impl); + } + +} // namespace WTF + +using WTF::ListHashSet; + +#endif /* WTF_ListHashSet_h */ diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ListRefPtr.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ListRefPtr.h new file mode 100644 index 000000000..4ba0632d7 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ListRefPtr.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2005, 2006, 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WTF_ListRefPtr_h +#define WTF_ListRefPtr_h + +#include + +namespace WTF { + + // Specialized version of RefPtr desgined for use in singly-linked lists. + // Derefs the list iteratively to avoid recursive derefing that can overflow the stack. + template class ListRefPtr : public RefPtr { + public: + ListRefPtr() : RefPtr() {} + ListRefPtr(T* ptr) : RefPtr(ptr) {} + ListRefPtr(const RefPtr& o) : RefPtr(o) {} + // see comment in PassRefPtr.h for why this takes const reference + template ListRefPtr(const PassRefPtr& o) : RefPtr(o) {} + + ~ListRefPtr() + { + RefPtr reaper = this->release(); + while (reaper && reaper->hasOneRef()) + reaper = reaper->releaseNext(); // implicitly protects reaper->next, then derefs reaper + } + + ListRefPtr& operator=(T* optr) { RefPtr::operator=(optr); return *this; } + ListRefPtr& operator=(const RefPtr& o) { RefPtr::operator=(o); return *this; } + ListRefPtr& operator=(const PassRefPtr& o) { RefPtr::operator=(o); return *this; } + template ListRefPtr& operator=(const RefPtr& o) { RefPtr::operator=(o); return *this; } + template ListRefPtr& operator=(const PassRefPtr& o) { RefPtr::operator=(o); return *this; } + }; + + template inline T* getPtr(const ListRefPtr& p) + { + return p.get(); + } + +} // namespace WTF + +using WTF::ListRefPtr; + +#endif // WTF_ListRefPtr_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ListableHandler.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ListableHandler.h new file mode 100644 index 000000000..41f18fbce --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ListableHandler.h @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef ListableHandler_h +#define ListableHandler_h + +#include +#include +#include +#include + +namespace JSC { + +class MarkStack; +class MarkStackThreadSharedData; +class SlotVisitor; + +template +class ListableHandler { + WTF_MAKE_NONCOPYABLE(ListableHandler); + +protected: + ListableHandler() + : m_nextAndFlag(0) + { + } + + virtual ~ListableHandler() { } + + T* next() const + { + return reinterpret_cast(m_nextAndFlag & ~1); + } + +private: + // Allow these classes to use ListableHandler::List. + friend class MarkStack; + friend class MarkStackThreadSharedData; + friend class SlotVisitor; + + class List { + WTF_MAKE_NONCOPYABLE(List); + public: + List() + : m_first(0) + { + } + + void addThreadSafe(T* handler) + { + // NOTE: If we ever want this to be faster, we could turn it into + // a CAS loop, since this is a singly-linked-list that, in parallel + // tracing mode, can only grow. I.e. we don't have to worry about + // any ABA problems. + MutexLocker locker(m_lock); + addNotThreadSafe(handler); + } + + bool hasNext() + { + return !!m_first; + } + + T* head() + { + return m_first; + } + + T* removeNext() + { + T* current = m_first; + T* next = current->next(); + current->m_nextAndFlag = 0; + m_first = next; + return current; + } + + void removeAll() + { + while (hasNext()) + removeNext(); + } + + private: + void addNotThreadSafe(T* handler) + { + if (handler->m_nextAndFlag & 1) + return; + handler->m_nextAndFlag = reinterpret_cast(m_first) | 1; + m_first = handler; + } + + Mutex m_lock; + T* m_first; + }; + + uintptr_t m_nextAndFlag; +}; + +} // namespace JSC + +#endif // ListableHandler_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Locker.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Locker.h new file mode 100644 index 000000000..c465b99ea --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Locker.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 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. + * 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 Locker_h +#define Locker_h + +#include + +namespace WTF { + +template class Locker { + WTF_MAKE_NONCOPYABLE(Locker); +public: + Locker(T& lockable) : m_lockable(lockable) { m_lockable.lock(); } + ~Locker() { m_lockable.unlock(); } +private: + T& m_lockable; +}; + +} + +using WTF::Locker; + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Lookup.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Lookup.h new file mode 100644 index 000000000..64d06b503 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Lookup.h @@ -0,0 +1,384 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef Lookup_h +#define Lookup_h + +#include "CallFrame.h" +#include "Intrinsic.h" +#include "Identifier.h" +#include "JSGlobalObject.h" +#include "PropertySlot.h" +#include +#include + +namespace JSC { + // Hash table generated by the create_hash_table script. + struct HashTableValue { + const char* key; // property name + unsigned char attributes; // JSObject attributes + intptr_t value1; + intptr_t value2; + Intrinsic intrinsic; + }; + + // FIXME: There is no reason this get function can't be simpler. + // ie. typedef JSValue (*GetFunction)(ExecState*, JSObject* baseObject) + typedef PropertySlot::GetValueFunc GetFunction; + typedef void (*PutFunction)(ExecState*, JSObject* baseObject, JSValue value); + + class HashEntry { + WTF_MAKE_FAST_ALLOCATED; + public: + void initialize(StringImpl* key, unsigned char attributes, intptr_t v1, intptr_t v2, Intrinsic intrinsic) + { + m_key = key; + m_attributes = attributes; + m_u.store.value1 = v1; + m_u.store.value2 = v2; + m_u.function.intrinsic = intrinsic; + m_next = 0; + } + + void setKey(StringImpl* key) { m_key = key; } + StringImpl* key() const { return m_key; } + + unsigned char attributes() const { return m_attributes; } + + Intrinsic intrinsic() const + { + ASSERT(m_attributes & Function); + return m_u.function.intrinsic; + } + + NativeFunction function() const { ASSERT(m_attributes & Function); return m_u.function.functionValue; } + unsigned char functionLength() const { ASSERT(m_attributes & Function); return static_cast(m_u.function.length); } + + GetFunction propertyGetter() const { ASSERT(!(m_attributes & Function)); return m_u.property.get; } + PutFunction propertyPutter() const { ASSERT(!(m_attributes & Function)); return m_u.property.put; } + + intptr_t lexerValue() const { ASSERT(!m_attributes); return m_u.lexer.value; } + + void setNext(HashEntry *next) { m_next = next; } + HashEntry* next() const { return m_next; } + + private: + StringImpl* m_key; + unsigned char m_attributes; // JSObject attributes + + union { + struct { + intptr_t value1; + intptr_t value2; + } store; + struct { + NativeFunction functionValue; + intptr_t length; // number of arguments for function + Intrinsic intrinsic; + } function; + struct { + GetFunction get; + PutFunction put; + } property; + struct { + intptr_t value; + intptr_t unused; + } lexer; + } m_u; + + HashEntry* m_next; + }; + + struct HashTable { + + int compactSize; + int compactHashSizeMask; + + const HashTableValue* values; // Fixed values generated by script. + mutable const HashEntry* table; // Table allocated at runtime. + + ALWAYS_INLINE void initializeIfNeeded(JSGlobalData* globalData) const + { + if (!table) + createTable(globalData); + } + + ALWAYS_INLINE void initializeIfNeeded(ExecState* exec) const + { + if (!table) + createTable(&exec->globalData()); + } + + JS_EXPORT_PRIVATE void deleteTable() const; + + // Find an entry in the table, and return the entry. + ALWAYS_INLINE const HashEntry* entry(JSGlobalData* globalData, const Identifier& identifier) const + { + initializeIfNeeded(globalData); + return entry(identifier); + } + + ALWAYS_INLINE const HashEntry* entry(ExecState* exec, const Identifier& identifier) const + { + initializeIfNeeded(exec); + return entry(identifier); + } + + class ConstIterator { + public: + ConstIterator(const HashTable* table, int position) + : m_table(table) + , m_position(position) + { + skipInvalidKeys(); + } + + const HashEntry* operator->() + { + return &m_table->table[m_position]; + } + + const HashEntry* operator*() + { + return &m_table->table[m_position]; + } + + bool operator!=(const ConstIterator& other) + { + ASSERT(m_table == other.m_table); + return m_position != other.m_position; + } + + ConstIterator& operator++() + { + ASSERT(m_position < m_table->compactSize); + ++m_position; + skipInvalidKeys(); + return *this; + } + + private: + void skipInvalidKeys() + { + ASSERT(m_position <= m_table->compactSize); + while (m_position < m_table->compactSize && !m_table->table[m_position].key()) + ++m_position; + ASSERT(m_position <= m_table->compactSize); + } + + const HashTable* m_table; + int m_position; + }; + + ConstIterator begin(JSGlobalData& globalData) const + { + initializeIfNeeded(&globalData); + return ConstIterator(this, 0); + } + ConstIterator end(JSGlobalData& globalData) const + { + initializeIfNeeded(&globalData); + return ConstIterator(this, compactSize); + } + + private: + ALWAYS_INLINE const HashEntry* entry(const Identifier& identifier) const + { + ASSERT(table); + + const HashEntry* entry = &table[identifier.impl()->existingHash() & compactHashSizeMask]; + + if (!entry->key()) + return 0; + + do { + if (entry->key() == identifier.impl()) + return entry; + entry = entry->next(); + } while (entry); + + return 0; + } + + // Convert the hash table keys to identifiers. + JS_EXPORT_PRIVATE void createTable(JSGlobalData*) const; + }; + + JS_EXPORT_PRIVATE bool setUpStaticFunctionSlot(ExecState*, const HashEntry*, JSObject* thisObject, const Identifier& propertyName, PropertySlot&); + + /** + * This method does it all (looking in the hashtable, checking for function + * overrides, creating the function or retrieving from cache, calling + * getValueProperty in case of a non-function property, forwarding to parent if + * unknown property). + */ + template + inline bool getStaticPropertySlot(ExecState* exec, const HashTable* table, ThisImp* thisObj, const Identifier& propertyName, PropertySlot& slot) + { + const HashEntry* entry = table->entry(exec, propertyName); + + if (!entry) // not found, forward to parent + return ParentImp::getOwnPropertySlot(thisObj, exec, propertyName, slot); + + if (entry->attributes() & Function) + return setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot); + + slot.setCacheableCustom(thisObj, entry->propertyGetter()); + return true; + } + + template + inline bool getStaticPropertyDescriptor(ExecState* exec, const HashTable* table, ThisImp* thisObj, const Identifier& propertyName, PropertyDescriptor& descriptor) + { + const HashEntry* entry = table->entry(exec, propertyName); + + if (!entry) // not found, forward to parent + return ParentImp::getOwnPropertyDescriptor(thisObj, exec, propertyName, descriptor); + + PropertySlot slot; + if (entry->attributes() & Function) { + bool present = setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot); + if (present) + descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes()); + return present; + } + + slot.setCustom(thisObj, entry->propertyGetter()); + descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes()); + return true; + } + + /** + * Simplified version of getStaticPropertySlot in case there are only functions. + * Using this instead of getStaticPropertySlot allows 'this' to avoid implementing + * a dummy getValueProperty. + */ + template + inline bool getStaticFunctionSlot(ExecState* exec, const HashTable* table, JSObject* thisObj, const Identifier& propertyName, PropertySlot& slot) + { + if (ParentImp::getOwnPropertySlot(thisObj, exec, propertyName, slot)) + return true; + + const HashEntry* entry = table->entry(exec, propertyName); + if (!entry) + return false; + + return setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot); + } + + /** + * Simplified version of getStaticPropertyDescriptor in case there are only functions. + * Using this instead of getStaticPropertyDescriptor allows 'this' to avoid implementing + * a dummy getValueProperty. + */ + template + inline bool getStaticFunctionDescriptor(ExecState* exec, const HashTable* table, JSObject* thisObj, const Identifier& propertyName, PropertyDescriptor& descriptor) + { + if (ParentImp::getOwnPropertyDescriptor(static_cast(thisObj), exec, propertyName, descriptor)) + return true; + + const HashEntry* entry = table->entry(exec, propertyName); + if (!entry) + return false; + + PropertySlot slot; + bool present = setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot); + if (present) + descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes()); + return present; + } + + /** + * Simplified version of getStaticPropertySlot in case there are no functions, only "values". + * Using this instead of getStaticPropertySlot removes the need for a FuncImp class. + */ + template + inline bool getStaticValueSlot(ExecState* exec, const HashTable* table, ThisImp* thisObj, const Identifier& propertyName, PropertySlot& slot) + { + const HashEntry* entry = table->entry(exec, propertyName); + + if (!entry) // not found, forward to parent + return ParentImp::getOwnPropertySlot(thisObj, exec, propertyName, slot); + + ASSERT(!(entry->attributes() & Function)); + + slot.setCacheableCustom(thisObj, entry->propertyGetter()); + return true; + } + + /** + * Simplified version of getStaticPropertyDescriptor in case there are no functions, only "values". + * Using this instead of getStaticPropertyDescriptor removes the need for a FuncImp class. + */ + template + inline bool getStaticValueDescriptor(ExecState* exec, const HashTable* table, ThisImp* thisObj, const Identifier& propertyName, PropertyDescriptor& descriptor) + { + const HashEntry* entry = table->entry(exec, propertyName); + + if (!entry) // not found, forward to parent + return ParentImp::getOwnPropertyDescriptor(thisObj, exec, propertyName, descriptor); + + ASSERT(!(entry->attributes() & Function)); + PropertySlot slot; + slot.setCustom(thisObj, entry->propertyGetter()); + descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes()); + return true; + } + + /** + * This one is for "put". + * It looks up a hash entry for the property to be set. If an entry + * is found it sets the value and returns true, else it returns false. + */ + template + inline bool lookupPut(ExecState* exec, const Identifier& propertyName, JSValue value, const HashTable* table, ThisImp* thisObj, bool shouldThrow = false) + { + const HashEntry* entry = table->entry(exec, propertyName); + + if (!entry) + return false; + + // If this is a function put it as an override property. + if (entry->attributes() & Function) + thisObj->putDirect(exec->globalData(), propertyName, value); + else if (!(entry->attributes() & ReadOnly)) + entry->propertyPutter()(exec, thisObj, value); + else if (shouldThrow) + throwTypeError(exec, StrictModeReadonlyPropertyWriteError); + + return true; + } + + /** + * This one is for "put". + * It calls lookupPut() to set the value. If that call + * returns false (meaning no entry in the hash table was found), + * then it calls put() on the ParentImp class. + */ + template + inline void lookupPut(ExecState* exec, const Identifier& propertyName, JSValue value, const HashTable* table, ThisImp* thisObj, PutPropertySlot& slot) + { + if (!lookupPut(exec, propertyName, value, table, thisObj, slot.isStrictMode())) + ParentImp::put(thisObj, exec, propertyName, value, slot); // not found: forward to parent + } + +} // namespace JSC + +#endif // Lookup_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MD5.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MD5.h new file mode 100644 index 000000000..ef027ccad --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MD5.h @@ -0,0 +1,61 @@ +/* + * 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. + * * 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 WTF_MD5_h +#define WTF_MD5_h + +#include + +namespace WTF { + +class MD5 { +public: + WTF_EXPORT_PRIVATE MD5(); + + void addBytes(const Vector& input) + { + addBytes(input.data(), input.size()); + } + WTF_EXPORT_PRIVATE void addBytes(const uint8_t* input, size_t length); + + // checksum has a side effect of resetting the state of the object. + WTF_EXPORT_PRIVATE void checksum(Vector&); + +private: + uint32_t m_buf[4]; + uint32_t m_bits[2]; + uint8_t m_in[64]; +}; + +} // namespace WTF + +using WTF::MD5; + +#endif // WTF_MD5_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MachineStackMarker.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MachineStackMarker.h new file mode 100644 index 000000000..0f5a4c3aa --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MachineStackMarker.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2001 Peter Kelly (pmk@post.com) + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef MachineThreads_h +#define MachineThreads_h + +#include +#include +#include + +namespace JSC { + + class Heap; + class ConservativeRoots; + + class MachineThreads { + WTF_MAKE_NONCOPYABLE(MachineThreads); + public: + MachineThreads(Heap*); + ~MachineThreads(); + + void gatherConservativeRoots(ConservativeRoots&, void* stackCurrent); + + void makeUsableFromMultipleThreads(); + JS_EXPORT_PRIVATE void addCurrentThread(); // Only needs to be called by clients that can use the same heap from multiple threads. + + private: + void gatherFromCurrentThread(ConservativeRoots&, void* stackCurrent); + + class Thread; + + static void removeThread(void*); + void removeCurrentThread(); + + void gatherFromOtherThread(ConservativeRoots&, Thread*); + + Heap* m_heap; + Mutex m_registeredThreadsMutex; + Thread* m_registeredThreads; + pthread_key_t m_threadSpecific; + }; + +} // namespace JSC + +#endif // MachineThreads_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MacroAssemblerCodeRef.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MacroAssemblerCodeRef.h new file mode 100644 index 000000000..82e8c4151 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MacroAssemblerCodeRef.h @@ -0,0 +1,363 @@ +/* + * 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 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 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 MacroAssemblerCodeRef_h +#define MacroAssemblerCodeRef_h + +#include "ExecutableAllocator.h" +#include "PassRefPtr.h" +#include "RefPtr.h" +#include "UnusedParam.h" + +#if ENABLE(ASSEMBLER) + +// ASSERT_VALID_CODE_POINTER checks that ptr is a non-null pointer, and that it is a valid +// instruction address on the platform (for example, check any alignment requirements). +#if CPU(ARM_THUMB2) +// ARM/thumb instructions must be 16-bit aligned, but all code pointers to be loaded +// into the processor are decorated with the bottom bit set, indicating that this is +// thumb code (as oposed to 32-bit traditional ARM). The first test checks for both +// decorated and undectorated null, and the second test ensures that the pointer is +// decorated. +#define ASSERT_VALID_CODE_POINTER(ptr) \ + ASSERT(reinterpret_cast(ptr) & ~1); \ + ASSERT(reinterpret_cast(ptr) & 1) +#define ASSERT_VALID_CODE_OFFSET(offset) \ + ASSERT(!(offset & 1)) // Must be multiple of 2. +#else +#define ASSERT_VALID_CODE_POINTER(ptr) \ + ASSERT(ptr) +#define ASSERT_VALID_CODE_OFFSET(offset) // Anything goes! +#endif + +#if CPU(X86) && OS(WIN) +#define CALLING_CONVENTION_IS_STDCALL 1 +#ifndef CDECL +#if COMPILER(MSVC) +#define CDECL __cdecl +#else +#define CDECL __attribute__ ((__cdecl)) +#endif // COMPILER(MSVC) +#endif // CDECL +#else +#define CALLING_CONVENTION_IS_STDCALL 0 +#endif + +#if CPU(X86) +#define HAS_FASTCALL_CALLING_CONVENTION 1 +#ifndef FASTCALL +#if COMPILER(MSVC) +#define FASTCALL __fastcall +#else +#define FASTCALL __attribute__ ((fastcall)) +#endif // COMPILER(MSVC) +#endif // FASTCALL +#else +#define HAS_FASTCALL_CALLING_CONVENTION 0 +#endif // CPU(X86) + +namespace JSC { + +// FunctionPtr: +// +// FunctionPtr should be used to wrap pointers to C/C++ functions in JSC +// (particularly, the stub functions). +class FunctionPtr { +public: + FunctionPtr() + : m_value(0) + { + } + + template + FunctionPtr(returnType(*value)()) + : m_value((void*)value) + { + ASSERT_VALID_CODE_POINTER(m_value); + } + + template + FunctionPtr(returnType(*value)(argType1)) + : m_value((void*)value) + { + ASSERT_VALID_CODE_POINTER(m_value); + } + + template + FunctionPtr(returnType(*value)(argType1, argType2)) + : m_value((void*)value) + { + ASSERT_VALID_CODE_POINTER(m_value); + } + + template + FunctionPtr(returnType(*value)(argType1, argType2, argType3)) + : m_value((void*)value) + { + ASSERT_VALID_CODE_POINTER(m_value); + } + + template + FunctionPtr(returnType(*value)(argType1, argType2, argType3, argType4)) + : m_value((void*)value) + { + ASSERT_VALID_CODE_POINTER(m_value); + } + +#if CALLING_CONVENTION_IS_STDCALL + + template + FunctionPtr(returnType (CDECL *value)()) + : m_value((void*)value) + { + ASSERT_VALID_CODE_POINTER(m_value); + } + + template + FunctionPtr(returnType (CDECL *value)(argType1)) + : m_value((void*)value) + { + ASSERT_VALID_CODE_POINTER(m_value); + } + + template + FunctionPtr(returnType (CDECL *value)(argType1, argType2)) + : m_value((void*)value) + { + ASSERT_VALID_CODE_POINTER(m_value); + } + + template + FunctionPtr(returnType (CDECL *value)(argType1, argType2, argType3)) + : m_value((void*)value) + { + ASSERT_VALID_CODE_POINTER(m_value); + } + + template + FunctionPtr(returnType (CDECL *value)(argType1, argType2, argType3, argType4)) + : m_value((void*)value) + { + ASSERT_VALID_CODE_POINTER(m_value); + } +#endif + +#if HAS_FASTCALL_CALLING_CONVENTION + + template + FunctionPtr(returnType (FASTCALL *value)()) + : m_value((void*)value) + { + ASSERT_VALID_CODE_POINTER(m_value); + } + + template + FunctionPtr(returnType (FASTCALL *value)(argType1)) + : m_value((void*)value) + { + ASSERT_VALID_CODE_POINTER(m_value); + } + + template + FunctionPtr(returnType (FASTCALL *value)(argType1, argType2)) + : m_value((void*)value) + { + ASSERT_VALID_CODE_POINTER(m_value); + } + + template + FunctionPtr(returnType (FASTCALL *value)(argType1, argType2, argType3)) + : m_value((void*)value) + { + ASSERT_VALID_CODE_POINTER(m_value); + } + + template + FunctionPtr(returnType (FASTCALL *value)(argType1, argType2, argType3, argType4)) + : m_value((void*)value) + { + ASSERT_VALID_CODE_POINTER(m_value); + } +#endif + + template + explicit FunctionPtr(FunctionType* value) + // Using a C-ctyle cast here to avoid compiler error on RVTC: + // Error: #694: reinterpret_cast cannot cast away const or other type qualifiers + // (I guess on RVTC function pointers have a different constness to GCC/MSVC?) + : m_value((void*)value) + { + ASSERT_VALID_CODE_POINTER(m_value); + } + + void* value() const { return m_value; } + void* executableAddress() const { return m_value; } + + +private: + void* m_value; +}; + +// ReturnAddressPtr: +// +// ReturnAddressPtr should be used to wrap return addresses generated by processor +// 'call' instructions exectued in JIT code. We use return addresses to look up +// exception and optimization information, and to repatch the call instruction +// that is the source of the return address. +class ReturnAddressPtr { +public: + ReturnAddressPtr() + : m_value(0) + { + } + + explicit ReturnAddressPtr(void* value) + : m_value(value) + { + ASSERT_VALID_CODE_POINTER(m_value); + } + + explicit ReturnAddressPtr(FunctionPtr function) + : m_value(function.value()) + { + ASSERT_VALID_CODE_POINTER(m_value); + } + + void* value() const { return m_value; } + +private: + void* m_value; +}; + +// MacroAssemblerCodePtr: +// +// MacroAssemblerCodePtr should be used to wrap pointers to JIT generated code. +class MacroAssemblerCodePtr { +public: + MacroAssemblerCodePtr() + : m_value(0) + { + } + + explicit MacroAssemblerCodePtr(void* value) +#if CPU(ARM_THUMB2) + // Decorate the pointer as a thumb code pointer. + : m_value(reinterpret_cast(value) + 1) +#else + : m_value(value) +#endif + { + ASSERT_VALID_CODE_POINTER(m_value); + } + + explicit MacroAssemblerCodePtr(ReturnAddressPtr ra) + : m_value(ra.value()) + { + ASSERT_VALID_CODE_POINTER(m_value); + } + + void* executableAddress() const { return m_value; } +#if CPU(ARM_THUMB2) + // To use this pointer as a data address remove the decoration. + void* dataLocation() const { ASSERT_VALID_CODE_POINTER(m_value); return reinterpret_cast(m_value) - 1; } +#else + void* dataLocation() const { ASSERT_VALID_CODE_POINTER(m_value); return m_value; } +#endif + + bool operator!() const + { + return !m_value; + } + +private: + void* m_value; +}; + +// MacroAssemblerCodeRef: +// +// A reference to a section of JIT generated code. A CodeRef consists of a +// pointer to the code, and a ref pointer to the pool from within which it +// was allocated. +class MacroAssemblerCodeRef { +private: + // This is private because it's dangerous enough that we want uses of it + // to be easy to find - hence the static create method below. + explicit MacroAssemblerCodeRef(MacroAssemblerCodePtr codePtr) + : m_codePtr(codePtr) + { + ASSERT(m_codePtr); + } + +public: + MacroAssemblerCodeRef() + { + } + + MacroAssemblerCodeRef(PassRefPtr executableMemory) + : m_codePtr(executableMemory->start()) + , m_executableMemory(executableMemory) + { + ASSERT(m_executableMemory->isManaged()); + ASSERT(m_executableMemory->start()); + ASSERT(m_codePtr); + } + + // Use this only when you know that the codePtr refers to code that is + // already being kept alive through some other means. Typically this means + // that codePtr is immortal. + static MacroAssemblerCodeRef createSelfManagedCodeRef(MacroAssemblerCodePtr codePtr) + { + return MacroAssemblerCodeRef(codePtr); + } + + ExecutableMemoryHandle* executableMemory() const + { + return m_executableMemory.get(); + } + + MacroAssemblerCodePtr code() const + { + return m_codePtr; + } + + size_t size() const + { + if (!m_executableMemory) + return 0; + return m_executableMemory->sizeInBytes(); + } + + bool operator!() const { return !m_codePtr; } + +private: + MacroAssemblerCodePtr m_codePtr; + RefPtr m_executableMemory; +}; + +} // namespace JSC + +#endif // ENABLE(ASSEMBLER) + +#endif // MacroAssemblerCodeRef_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MainThread.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MainThread.h new file mode 100644 index 000000000..ff76a5fd3 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MainThread.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2007, 2008, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com) + * + * 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 MainThread_h +#define MainThread_h + +#include "Platform.h" + +#include + +namespace WTF { + +typedef uint32_t ThreadIdentifier; +typedef void MainThreadFunction(void*); + +// Must be called from the main thread. +WTF_EXPORT_PRIVATE void initializeMainThread(); + +WTF_EXPORT_PRIVATE void callOnMainThread(MainThreadFunction*, void* context); +WTF_EXPORT_PRIVATE void callOnMainThreadAndWait(MainThreadFunction*, void* context); +WTF_EXPORT_PRIVATE void cancelCallOnMainThread(MainThreadFunction*, void* context); + +template class Function; +WTF_EXPORT_PRIVATE void callOnMainThread(const Function&); + +WTF_EXPORT_PRIVATE void setMainThreadCallbacksPaused(bool paused); + +WTF_EXPORT_PRIVATE bool isMainThread(); +#if ENABLE(PARALLEL_GC) +void registerGCThread(); +WTF_EXPORT_PRIVATE bool isMainThreadOrGCThread(); +#elif PLATFORM(MAC) +bool isMainThreadOrGCThread(); +#else +inline bool isMainThreadOrGCThread() { return isMainThread(); } +#endif + +// NOTE: these functions are internal to the callOnMainThread implementation. +void initializeMainThreadPlatform(); +void scheduleDispatchFunctionsOnMainThread(); +void dispatchFunctionsFromMainThread(); + +#if PLATFORM(MAC) +// This version of initializeMainThread sets up the main thread as corresponding +// to the process's main thread, and not necessarily the thread that calls this +// function. It should only be used as a legacy aid for Mac WebKit. +WTF_EXPORT_PRIVATE void initializeMainThreadToProcessMainThread(); +void initializeMainThreadToProcessMainThreadPlatform(); +#endif + +} // namespace WTF + +using WTF::callOnMainThread; +using WTF::callOnMainThreadAndWait; +using WTF::cancelCallOnMainThread; +using WTF::setMainThreadCallbacksPaused; +using WTF::isMainThread; +using WTF::isMainThreadOrGCThread; +#endif // MainThread_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MarkStack.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MarkStack.h new file mode 100644 index 000000000..6923cdd8a --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MarkStack.h @@ -0,0 +1,453 @@ +/* + * Copyright (C) 2009, 2011 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 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 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 MarkStack_h +#define MarkStack_h + +#include "BumpSpace.h" +#include "HandleTypes.h" +#include "Options.h" +#include "JSValue.h" +#include "Register.h" +#include "UnconditionalFinalizer.h" +#include "VTableSpectrum.h" +#include "WeakReferenceHarvester.h" +#include +#include +#include +#include +#include +#include + +namespace JSC { + + class ConservativeRoots; + class JSGlobalData; + class MarkStack; + class ParallelModeEnabler; + class Register; + class SlotVisitor; + template class WriteBarrierBase; + template class JITWriteBarrier; + + struct MarkStackSegment { + MarkStackSegment* m_previous; +#if !ASSERT_DISABLED + size_t m_top; +#endif + + const JSCell** data() + { + return bitwise_cast(this + 1); + } + + static size_t capacityFromSize(size_t size) + { + return (size - sizeof(MarkStackSegment)) / sizeof(const JSCell*); + } + + static size_t sizeFromCapacity(size_t capacity) + { + return sizeof(MarkStackSegment) + capacity * sizeof(const JSCell*); + } + }; + + class MarkStackSegmentAllocator { + public: + MarkStackSegmentAllocator(); + ~MarkStackSegmentAllocator(); + + MarkStackSegment* allocate(); + void release(MarkStackSegment*); + + void shrinkReserve(); + + private: + Mutex m_lock; + MarkStackSegment* m_nextFreeSegment; + }; + + class MarkStackArray { + public: + MarkStackArray(MarkStackSegmentAllocator&); + ~MarkStackArray(); + + void append(const JSCell*); + + bool canRemoveLast(); + const JSCell* removeLast(); + bool refill(); + + bool isEmpty(); + + bool canDonateSomeCells(); // Returns false if you should definitely not call doanteSomeCellsTo(). + bool donateSomeCellsTo(MarkStackArray& other); // Returns true if some cells were donated. + + void stealSomeCellsFrom(MarkStackArray& other); + + size_t size(); + + private: + MarkStackSegment* m_topSegment; + + JS_EXPORT_PRIVATE void expand(); + + MarkStackSegmentAllocator& m_allocator; + + size_t m_segmentCapacity; + size_t m_top; + size_t m_numberOfPreviousSegments; + + size_t postIncTop() + { + size_t result = m_top++; + ASSERT(result == m_topSegment->m_top++); + return result; + } + + size_t preDecTop() + { + size_t result = --m_top; + ASSERT(result == --m_topSegment->m_top); + return result; + } + + void setTopForFullSegment() + { + ASSERT(m_topSegment->m_top == m_segmentCapacity); + m_top = m_segmentCapacity; + } + + void setTopForEmptySegment() + { + ASSERT(!m_topSegment->m_top); + m_top = 0; + } + + size_t top() + { + ASSERT(m_top == m_topSegment->m_top); + return m_top; + } + +#if ASSERT_DISABLED + void validatePrevious() { } +#else + void validatePrevious() + { + unsigned count = 0; + for (MarkStackSegment* current = m_topSegment->m_previous; current; current = current->m_previous) + count++; + ASSERT(count == m_numberOfPreviousSegments); + } +#endif + }; + + class MarkStackThreadSharedData { + public: + MarkStackThreadSharedData(JSGlobalData*); + ~MarkStackThreadSharedData(); + + void reset(); + + private: + friend class MarkStack; + friend class SlotVisitor; + +#if ENABLE(PARALLEL_GC) + void markingThreadMain(); + static void* markingThreadStartFunc(void* heap); +#endif + + JSGlobalData* m_globalData; + BumpSpace* m_bumpSpace; + + MarkStackSegmentAllocator m_segmentAllocator; + + Vector m_markingThreads; + + Mutex m_markingLock; + ThreadCondition m_markingCondition; + MarkStackArray m_sharedMarkStack; + unsigned m_numberOfActiveParallelMarkers; + bool m_parallelMarkersShouldExit; + + Mutex m_opaqueRootsLock; + HashSet m_opaqueRoots; + + ListableHandler::List m_weakReferenceHarvesters; + ListableHandler::List m_unconditionalFinalizers; + }; + + class MarkStack { + WTF_MAKE_NONCOPYABLE(MarkStack); + friend class HeapRootVisitor; // Allowed to mark a JSValue* or JSCell** directly. + + public: + MarkStack(MarkStackThreadSharedData&); + ~MarkStack(); + + void append(ConservativeRoots&); + + template void append(JITWriteBarrier*); + template void append(WriteBarrierBase*); + void appendValues(WriteBarrierBase*, size_t count); + + template + void appendUnbarrieredPointer(T**); + + void addOpaqueRoot(void*); + bool containsOpaqueRoot(void*); + int opaqueRootCount(); + + bool isEmpty() { return m_stack.isEmpty(); } + + void reset(); + + size_t visitCount() const { return m_visitCount; } + +#if ENABLE(SIMPLE_HEAP_PROFILING) + VTableSpectrum m_visitedTypeCounts; +#endif + + void addWeakReferenceHarvester(WeakReferenceHarvester* weakReferenceHarvester) + { + m_shared.m_weakReferenceHarvesters.addThreadSafe(weakReferenceHarvester); + } + + void addUnconditionalFinalizer(UnconditionalFinalizer* unconditionalFinalizer) + { + m_shared.m_unconditionalFinalizers.addThreadSafe(unconditionalFinalizer); + } + + protected: + JS_EXPORT_PRIVATE static void validate(JSCell*); + + void append(JSValue*); + void append(JSValue*, size_t count); + void append(JSCell**); + + void internalAppend(JSCell*); + void internalAppend(JSValue); + + JS_EXPORT_PRIVATE void mergeOpaqueRoots(); + + void mergeOpaqueRootsIfNecessary() + { + if (m_opaqueRoots.isEmpty()) + return; + mergeOpaqueRoots(); + } + + void mergeOpaqueRootsIfProfitable() + { + if (static_cast(m_opaqueRoots.size()) < Options::opaqueRootMergeThreshold) + return; + mergeOpaqueRoots(); + } + + MarkStackArray m_stack; + HashSet m_opaqueRoots; // Handle-owning data structures not visible to the garbage collector. + +#if !ASSERT_DISABLED + public: + bool m_isCheckingForDefaultMarkViolation; + bool m_isDraining; +#endif + protected: + friend class ParallelModeEnabler; + + size_t m_visitCount; + bool m_isInParallelMode; + + MarkStackThreadSharedData& m_shared; + }; + + inline MarkStack::MarkStack(MarkStackThreadSharedData& shared) + : m_stack(shared.m_segmentAllocator) +#if !ASSERT_DISABLED + , m_isCheckingForDefaultMarkViolation(false) + , m_isDraining(false) +#endif + , m_visitCount(0) + , m_isInParallelMode(false) + , m_shared(shared) + { + } + + inline MarkStack::~MarkStack() + { + ASSERT(m_stack.isEmpty()); + } + + inline void MarkStack::addOpaqueRoot(void* root) + { +#if ENABLE(PARALLEL_GC) + if (Options::numberOfGCMarkers == 1) { + // Put directly into the shared HashSet. + m_shared.m_opaqueRoots.add(root); + return; + } + // Put into the local set, but merge with the shared one every once in + // a while to make sure that the local sets don't grow too large. + mergeOpaqueRootsIfProfitable(); + m_opaqueRoots.add(root); +#else + m_opaqueRoots.add(root); +#endif + } + + inline bool MarkStack::containsOpaqueRoot(void* root) + { + ASSERT(!m_isInParallelMode); +#if ENABLE(PARALLEL_GC) + ASSERT(m_opaqueRoots.isEmpty()); + return m_shared.m_opaqueRoots.contains(root); +#else + return m_opaqueRoots.contains(root); +#endif + } + + inline int MarkStack::opaqueRootCount() + { + ASSERT(!m_isInParallelMode); +#if ENABLE(PARALLEL_GC) + ASSERT(m_opaqueRoots.isEmpty()); + return m_shared.m_opaqueRoots.size(); +#else + return m_opaqueRoots.size(); +#endif + } + + inline void MarkStackArray::append(const JSCell* cell) + { + if (m_top == m_segmentCapacity) + expand(); + m_topSegment->data()[postIncTop()] = cell; + } + + inline bool MarkStackArray::canRemoveLast() + { + return !!m_top; + } + + inline const JSCell* MarkStackArray::removeLast() + { + return m_topSegment->data()[preDecTop()]; + } + + inline bool MarkStackArray::isEmpty() + { + if (m_top) + return false; + if (m_topSegment->m_previous) { + ASSERT(m_topSegment->m_previous->m_top == m_segmentCapacity); + return false; + } + return true; + } + + inline bool MarkStackArray::canDonateSomeCells() + { + size_t numberOfCellsToKeep = Options::minimumNumberOfCellsToKeep; + // Another check: see if we have enough cells to warrant donation. + if (m_top <= numberOfCellsToKeep) { + // This indicates that we might not want to donate anything; check if we have + // another full segment. If not, then don't donate. + if (!m_topSegment->m_previous) + return false; + + ASSERT(m_topSegment->m_previous->m_top == m_segmentCapacity); + } + + return true; + } + + inline size_t MarkStackArray::size() + { + return m_top + m_segmentCapacity * m_numberOfPreviousSegments; + } + + ALWAYS_INLINE void MarkStack::append(JSValue* slot, size_t count) + { + for (size_t i = 0; i < count; ++i) { + JSValue& value = slot[i]; + if (!value) + continue; + internalAppend(value); + } + } + + template + inline void MarkStack::appendUnbarrieredPointer(T** slot) + { + ASSERT(slot); + JSCell* cell = *slot; + if (cell) + internalAppend(cell); + } + + ALWAYS_INLINE void MarkStack::append(JSValue* slot) + { + ASSERT(slot); + internalAppend(*slot); + } + + ALWAYS_INLINE void MarkStack::append(JSCell** slot) + { + ASSERT(slot); + internalAppend(*slot); + } + + ALWAYS_INLINE void MarkStack::internalAppend(JSValue value) + { + ASSERT(value); + if (!value.isCell()) + return; + internalAppend(value.asCell()); + } + + class ParallelModeEnabler { + public: + ParallelModeEnabler(MarkStack& stack) + : m_stack(stack) + { + ASSERT(!m_stack.m_isInParallelMode); + m_stack.m_isInParallelMode = true; + } + + ~ParallelModeEnabler() + { + ASSERT(m_stack.m_isInParallelMode); + m_stack.m_isInParallelMode = false; + } + + private: + MarkStack& m_stack; + }; + +} // namespace JSC + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MarkedBlock.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MarkedBlock.h new file mode 100644 index 000000000..00eb54b1f --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MarkedBlock.h @@ -0,0 +1,429 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2001 Peter Kelly (pmk@post.com) + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef MarkedBlock_h +#define MarkedBlock_h + +#include "CardSet.h" +#include "HeapBlock.h" + +#include +#include +#include +#include +#include +#include + +// Set to log state transitions of blocks. +#define HEAP_LOG_BLOCK_STATE_TRANSITIONS 0 + +#if HEAP_LOG_BLOCK_STATE_TRANSITIONS +#define HEAP_LOG_BLOCK_STATE_TRANSITION(block) do { \ + printf("%s:%d %s: block %s = %p, %d\n", \ + __FILE__, __LINE__, __FUNCTION__, #block, (block), (block)->m_state); \ + } while (false) +#else +#define HEAP_LOG_BLOCK_STATE_TRANSITION(block) ((void)0) +#endif + +namespace JSC { + + class Heap; + class JSCell; + + typedef uintptr_t Bits; + + static const size_t MB = 1024 * 1024; + + bool isZapped(const JSCell*); + + // A marked block is a page-aligned container for heap-allocated objects. + // Objects are allocated within cells of the marked block. For a given + // marked block, all cells have the same size. Objects smaller than the + // cell size may be allocated in the marked block, in which case the + // allocation suffers from internal fragmentation: wasted space whose + // size is equal to the difference between the cell size and the object + // size. + + class MarkedBlock : public HeapBlock { + friend class WTF::DoublyLinkedListNode; + public: + // Ensure natural alignment for native types whilst recognizing that the smallest + // object the heap will commonly allocate is four words. + static const size_t atomSize = 4 * sizeof(void*); + static const size_t atomShift = 5; + static const size_t blockSize = 64 * KB; + static const size_t blockMask = ~(blockSize - 1); // blockSize must be a power of two. + + static const size_t atomsPerBlock = blockSize / atomSize; // ~0.4% overhead + static const size_t atomMask = atomsPerBlock - 1; + static const int cardShift = 8; // This is log2 of bytes per card. + static const size_t bytesPerCard = 1 << cardShift; + static const int cardCount = blockSize / bytesPerCard; + static const int cardMask = cardCount - 1; + + struct FreeCell { + FreeCell* next; + }; + + struct VoidFunctor { + typedef void ReturnType; + void returnValue() { } + }; + + static MarkedBlock* create(Heap*, size_t cellSize); + static MarkedBlock* recycle(MarkedBlock*, Heap*, size_t cellSize); + static void destroy(MarkedBlock*); + + static bool isAtomAligned(const void*); + static MarkedBlock* blockFor(const void*); + static size_t firstAtom(); + + Heap* heap() const; + + void* allocate(); + + enum SweepMode { SweepOnly, SweepToFreeList }; + FreeCell* sweep(SweepMode = SweepOnly); + + // While allocating from a free list, MarkedBlock temporarily has bogus + // cell liveness data. To restore accurate cell liveness data, call one + // of these functions: + void didConsumeFreeList(); // Call this once you've allocated all the items in the free list. + void zapFreeList(FreeCell* firstFreeCell); // Call this to undo the free list. + + void clearMarks(); + size_t markCount(); + bool markCountIsZero(); // Faster than markCount(). + + size_t cellSize(); + + size_t size(); + size_t capacity(); + + bool isMarked(const void*); + bool testAndSetMarked(const void*); + bool isLive(const JSCell*); + bool isLiveCell(const void*); + void setMarked(const void*); + +#if ENABLE(GGC) + void setDirtyObject(const void* atom) + { + ASSERT(MarkedBlock::blockFor(atom) == this); + m_cards.markCardForAtom(atom); + } + + uint8_t* addressOfCardFor(const void* atom) + { + ASSERT(MarkedBlock::blockFor(atom) == this); + return &m_cards.cardForAtom(atom); + } + + static inline size_t offsetOfCards() + { + return OBJECT_OFFSETOF(MarkedBlock, m_cards); + } + + static inline size_t offsetOfMarks() + { + return OBJECT_OFFSETOF(MarkedBlock, m_marks); + } + + typedef Vector DirtyCellVector; + inline void gatherDirtyCells(DirtyCellVector&); + template inline void gatherDirtyCellsWithSize(DirtyCellVector&); +#endif + + template void forEachCell(Functor&); + + private: + static const size_t atomAlignmentMask = atomSize - 1; // atomSize must be a power of two. + + enum BlockState { New, FreeListed, Allocated, Marked, Zapped }; + + typedef char Atom[atomSize]; + + MarkedBlock(PageAllocationAligned&, Heap*, size_t cellSize); + Atom* atoms(); + size_t atomNumber(const void*); + void callDestructor(JSCell*); + template FreeCell* specializedSweep(); + +#if ENABLE(GGC) + CardSet m_cards; +#endif + + size_t m_atomsPerCell; + size_t m_endAtom; // This is a fuzzy end. Always test for < m_endAtom. +#if ENABLE(PARALLEL_GC) + WTF::Bitmap m_marks; +#else + WTF::Bitmap m_marks; +#endif + BlockState m_state; + Heap* m_heap; + }; + + inline size_t MarkedBlock::firstAtom() + { + return WTF::roundUpToMultipleOf(sizeof(MarkedBlock)) / atomSize; + } + + inline MarkedBlock::Atom* MarkedBlock::atoms() + { + return reinterpret_cast(this); + } + + inline bool MarkedBlock::isAtomAligned(const void* p) + { + return !(reinterpret_cast(p) & atomAlignmentMask); + } + + inline MarkedBlock* MarkedBlock::blockFor(const void* p) + { + return reinterpret_cast(reinterpret_cast(p) & blockMask); + } + + inline Heap* MarkedBlock::heap() const + { + return m_heap; + } + + inline void MarkedBlock::didConsumeFreeList() + { + HEAP_LOG_BLOCK_STATE_TRANSITION(this); + + ASSERT(m_state == FreeListed); + m_state = Allocated; + } + + inline void MarkedBlock::clearMarks() + { + HEAP_LOG_BLOCK_STATE_TRANSITION(this); + + ASSERT(m_state != New && m_state != FreeListed); + m_marks.clearAll(); + + // This will become true at the end of the mark phase. We set it now to + // avoid an extra pass to do so later. + m_state = Marked; + } + + inline size_t MarkedBlock::markCount() + { + return m_marks.count(); + } + + inline bool MarkedBlock::markCountIsZero() + { + return m_marks.isEmpty(); + } + + inline size_t MarkedBlock::cellSize() + { + return m_atomsPerCell * atomSize; + } + + inline size_t MarkedBlock::size() + { + return markCount() * cellSize(); + } + + inline size_t MarkedBlock::capacity() + { + return m_allocation.size(); + } + + inline size_t MarkedBlock::atomNumber(const void* p) + { + return (reinterpret_cast(p) - reinterpret_cast(this)) / atomSize; + } + + inline bool MarkedBlock::isMarked(const void* p) + { + return m_marks.get(atomNumber(p)); + } + + inline bool MarkedBlock::testAndSetMarked(const void* p) + { + return m_marks.concurrentTestAndSet(atomNumber(p)); + } + + inline void MarkedBlock::setMarked(const void* p) + { + m_marks.set(atomNumber(p)); + } + + inline bool MarkedBlock::isLive(const JSCell* cell) + { + switch (m_state) { + case Allocated: + return true; + case Zapped: + if (isZapped(cell)) { + // Object dead in previous collection, not allocated since previous collection: mark bit should not be set. + ASSERT(!m_marks.get(atomNumber(cell))); + return false; + } + + // Newly allocated objects: mark bit not set. + // Objects that survived prior collection: mark bit set. + return true; + case Marked: + return m_marks.get(atomNumber(cell)); + + case New: + case FreeListed: + ASSERT_NOT_REACHED(); + return false; + } + + ASSERT_NOT_REACHED(); + return false; + } + + inline bool MarkedBlock::isLiveCell(const void* p) + { + ASSERT(MarkedBlock::isAtomAligned(p)); + size_t atomNumber = this->atomNumber(p); + size_t firstAtom = this->firstAtom(); + if (atomNumber < firstAtom) // Filters pointers into MarkedBlock metadata. + return false; + if ((atomNumber - firstAtom) % m_atomsPerCell) // Filters pointers into cell middles. + return false; + + return isLive(static_cast(p)); + } + + template inline void MarkedBlock::forEachCell(Functor& functor) + { + for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) { + JSCell* cell = reinterpret_cast(&atoms()[i]); + if (!isLive(cell)) + continue; + + functor(cell); + } + } + +#if ENABLE(GGC) +template void MarkedBlock::gatherDirtyCellsWithSize(DirtyCellVector& dirtyCells) +{ + if (m_cards.testAndClear(0)) { + char* ptr = reinterpret_cast(&atoms()[firstAtom()]); + const char* end = reinterpret_cast(this) + bytesPerCard; + while (ptr < end) { + JSCell* cell = reinterpret_cast(ptr); + if (isMarked(cell)) + dirtyCells.append(cell); + ptr += _cellSize; + } + } + + const size_t cellOffset = firstAtom() * atomSize % _cellSize; + for (size_t i = 1; i < m_cards.cardCount; i++) { + if (!m_cards.testAndClear(i)) + continue; + char* ptr = reinterpret_cast(this) + i * bytesPerCard + cellOffset; + char* end = reinterpret_cast(this) + (i + 1) * bytesPerCard; + + while (ptr < end) { + JSCell* cell = reinterpret_cast(ptr); + if (isMarked(cell)) + dirtyCells.append(cell); + ptr += _cellSize; + } + } +} + +void MarkedBlock::gatherDirtyCells(DirtyCellVector& dirtyCells) +{ + COMPILE_ASSERT((int)m_cards.cardCount == (int)cardCount, MarkedBlockCardCountsMatch); + + ASSERT(m_state != New && m_state != FreeListed); + + // This is an optimisation to avoid having to walk the set of marked + // blocks twice during GC. + m_state = Marked; + + if (markCountIsZero()) + return; + + size_t cellSize = this->cellSize(); + if (cellSize == 32) { + gatherDirtyCellsWithSize<32>(dirtyCells); + return; + } + if (cellSize == 64) { + gatherDirtyCellsWithSize<64>(dirtyCells); + return; + } + + const size_t firstCellOffset = firstAtom() * atomSize % cellSize; + + if (m_cards.testAndClear(0)) { + char* ptr = reinterpret_cast(this) + firstAtom() * atomSize; + char* end = reinterpret_cast(this) + bytesPerCard; + while (ptr < end) { + JSCell* cell = reinterpret_cast(ptr); + if (isMarked(cell)) + dirtyCells.append(cell); + ptr += cellSize; + } + } + for (size_t i = 1; i < m_cards.cardCount; i++) { + if (!m_cards.testAndClear(i)) + continue; + char* ptr = reinterpret_cast(this) + firstCellOffset + cellSize * ((i * bytesPerCard + cellSize - 1 - firstCellOffset) / cellSize); + char* end = reinterpret_cast(this) + std::min((i + 1) * bytesPerCard, m_endAtom * atomSize); + + while (ptr < end) { + JSCell* cell = reinterpret_cast(ptr); + if (isMarked(cell)) + dirtyCells.append(cell); + ptr += cellSize; + } + } +} +#endif + +} // namespace JSC + +namespace WTF { + + struct MarkedBlockHash : PtrHash { + static unsigned hash(JSC::MarkedBlock* const& key) + { + // Aligned VM regions tend to be monotonically increasing integers, + // which is a great hash function, but we have to remove the low bits, + // since they're always zero, which is a terrible hash function! + return reinterpret_cast(key) / JSC::MarkedBlock::blockSize; + } + }; + + template<> struct DefaultHash { + typedef MarkedBlockHash Hash; + }; + +} // namespace WTF + +#endif // MarkedBlock_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MarkedBlockSet.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MarkedBlockSet.h new file mode 100644 index 000000000..022a17389 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MarkedBlockSet.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2011 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 INC. 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 INC. 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 MarkedBlockSet_h +#define MarkedBlockSet_h + +#include "MarkedBlock.h" +#include "TinyBloomFilter.h" +#include + +namespace JSC { + +class MarkedBlock; + +class MarkedBlockSet { +public: + void add(MarkedBlock*); + void remove(MarkedBlock*); + + TinyBloomFilter filter() const; + const HashSet& set() const; + +private: + void recomputeFilter(); + + TinyBloomFilter m_filter; + HashSet m_set; +}; + +inline void MarkedBlockSet::add(MarkedBlock* block) +{ + m_filter.add(reinterpret_cast(block)); + m_set.add(block); +} + +inline void MarkedBlockSet::remove(MarkedBlock* block) +{ + int oldCapacity = m_set.capacity(); + m_set.remove(block); + if (m_set.capacity() != oldCapacity) // Indicates we've removed a lot of blocks. + recomputeFilter(); +} + +inline void MarkedBlockSet::recomputeFilter() +{ + TinyBloomFilter filter; + for (HashSet::iterator it = m_set.begin(); it != m_set.end(); ++it) + filter.add(reinterpret_cast(*it)); + m_filter = filter; +} + +inline TinyBloomFilter MarkedBlockSet::filter() const +{ + return m_filter; +} + +inline const HashSet& MarkedBlockSet::set() const +{ + return m_set; +} + +} // namespace JSC + +#endif // MarkedBlockSet_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MarkedSpace.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MarkedSpace.h new file mode 100644 index 000000000..3b2c828f7 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MarkedSpace.h @@ -0,0 +1,192 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2001 Peter Kelly (pmk@post.com) + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef MarkedSpace_h +#define MarkedSpace_h + +#include "MachineStackMarker.h" +#include "MarkedBlock.h" +#include "PageAllocationAligned.h" +#include +#include +#include +#include +#include +#include + +#define ASSERT_CLASS_FITS_IN_CELL(class) COMPILE_ASSERT(sizeof(class) <= MarkedSpace::maxCellSize, class_fits_in_cell) + +namespace JSC { + +class Heap; +class JSCell; +class LiveObjectIterator; +class WeakGCHandle; +class SlotVisitor; + +class MarkedSpace { + WTF_MAKE_NONCOPYABLE(MarkedSpace); +public: + static const size_t maxCellSize = 2048; + + struct SizeClass { + SizeClass(); + void resetAllocator(); + void zapFreeList(); + + MarkedBlock::FreeCell* firstFreeCell; + MarkedBlock* currentBlock; + DoublyLinkedList blockList; + size_t cellSize; + }; + + MarkedSpace(Heap*); + + SizeClass& sizeClassFor(size_t); + void* allocate(SizeClass&); + + void resetAllocator(); + + void addBlock(SizeClass&, MarkedBlock*); + void removeBlock(MarkedBlock*); + + void canonicalizeCellLivenessData(); + + size_t waterMark(); + size_t nurseryWaterMark(); + + template typename Functor::ReturnType forEachBlock(Functor&); // Safe to remove the current item while iterating. + template typename Functor::ReturnType forEachBlock(); + +private: + // [ 32... 256 ] + static const size_t preciseStep = MarkedBlock::atomSize; + static const size_t preciseCutoff = 256; + static const size_t preciseCount = preciseCutoff / preciseStep; + + // [ 512... 2048 ] + static const size_t impreciseStep = preciseCutoff; + static const size_t impreciseCutoff = maxCellSize; + static const size_t impreciseCount = impreciseCutoff / impreciseStep; + + FixedArray m_preciseSizeClasses; + FixedArray m_impreciseSizeClasses; + size_t m_waterMark; + size_t m_nurseryWaterMark; + Heap* m_heap; +}; + +inline size_t MarkedSpace::waterMark() +{ + return m_waterMark; +} + +inline size_t MarkedSpace::nurseryWaterMark() +{ + return m_nurseryWaterMark; +} + +inline MarkedSpace::SizeClass& MarkedSpace::sizeClassFor(size_t bytes) +{ + ASSERT(bytes && bytes <= maxCellSize); + if (bytes <= preciseCutoff) + return m_preciseSizeClasses[(bytes - 1) / preciseStep]; + return m_impreciseSizeClasses[(bytes - 1) / impreciseStep]; +} + +inline void* MarkedSpace::allocate(SizeClass& sizeClass) +{ + MarkedBlock::FreeCell* firstFreeCell = sizeClass.firstFreeCell; + if (!firstFreeCell) { + for (MarkedBlock*& block = sizeClass.currentBlock; block; block = static_cast(block->next())) { + firstFreeCell = block->sweep(MarkedBlock::SweepToFreeList); + if (firstFreeCell) + break; + m_nurseryWaterMark += block->capacity() - block->size(); + m_waterMark += block->capacity(); + block->didConsumeFreeList(); + } + + if (!firstFreeCell) + return 0; + } + + ASSERT(firstFreeCell); + + sizeClass.firstFreeCell = firstFreeCell->next; + return firstFreeCell; +} + +template inline typename Functor::ReturnType MarkedSpace::forEachBlock(Functor& functor) +{ + for (size_t i = 0; i < preciseCount; ++i) { + SizeClass& sizeClass = m_preciseSizeClasses[i]; + HeapBlock* next; + for (HeapBlock* block = sizeClass.blockList.head(); block; block = next) { + next = block->next(); + functor(static_cast(block)); + } + } + + for (size_t i = 0; i < impreciseCount; ++i) { + SizeClass& sizeClass = m_impreciseSizeClasses[i]; + HeapBlock* next; + for (HeapBlock* block = sizeClass.blockList.head(); block; block = next) { + next = block->next(); + functor(static_cast(block)); + } + } + + return functor.returnValue(); +} + +template inline typename Functor::ReturnType MarkedSpace::forEachBlock() +{ + Functor functor; + return forEachBlock(functor); +} + +inline MarkedSpace::SizeClass::SizeClass() + : firstFreeCell(0) + , currentBlock(0) + , cellSize(0) +{ +} + +inline void MarkedSpace::SizeClass::resetAllocator() +{ + currentBlock = static_cast(blockList.head()); +} + +inline void MarkedSpace::SizeClass::zapFreeList() +{ + if (!currentBlock) { + ASSERT(!firstFreeCell); + return; + } + + currentBlock->zapFreeList(firstFreeCell); + firstFreeCell = 0; +} + +} // namespace JSC + +#endif // MarkedSpace_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MathExtras.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MathExtras.h new file mode 100644 index 000000000..e8ebd6ba1 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MathExtras.h @@ -0,0 +1,331 @@ +/* + * Copyright (C) 2006, 2007, 2008, 2009, 2010 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 WTF_MathExtras_h +#define WTF_MathExtras_h + +#include +#include +#include +#include +#include +#include +#include + +#if OS(SOLARIS) +#include +#endif + +#if OS(OPENBSD) +#include +#include +#endif + +#if COMPILER(MSVC) +#if OS(WINCE) +#include +#endif +#include +#endif + +#if OS(QNX) +// FIXME: Look into a way to have cmath import its functions into both the standard and global +// namespace. For now, we include math.h since the QNX cmath header only imports its functions +// into the standard namespace. +#include +#endif + +#ifndef M_PI +const double piDouble = 3.14159265358979323846; +const float piFloat = 3.14159265358979323846f; +#else +const double piDouble = M_PI; +const float piFloat = static_cast(M_PI); +#endif + +#ifndef M_PI_2 +const double piOverTwoDouble = 1.57079632679489661923; +const float piOverTwoFloat = 1.57079632679489661923f; +#else +const double piOverTwoDouble = M_PI_2; +const float piOverTwoFloat = static_cast(M_PI_2); +#endif + +#ifndef M_PI_4 +const double piOverFourDouble = 0.785398163397448309616; +const float piOverFourFloat = 0.785398163397448309616f; +#else +const double piOverFourDouble = M_PI_4; +const float piOverFourFloat = static_cast(M_PI_4); +#endif + +#if OS(DARWIN) + +// Work around a bug in the Mac OS X libc where ceil(-0.1) return +0. +inline double wtf_ceil(double x) { return copysign(ceil(x), x); } + +#define ceil(x) wtf_ceil(x) + +#endif + +#if OS(SOLARIS) + +#ifndef isfinite +inline bool isfinite(double x) { return finite(x) && !isnand(x); } +#endif +#ifndef isinf +inline bool isinf(double x) { return !finite(x) && !isnand(x); } +#endif +#ifndef signbit +inline bool signbit(double x) { return copysign(1.0, x) < 0; } +#endif + +#endif + +#if OS(OPENBSD) + +#ifndef isfinite +inline bool isfinite(double x) { return finite(x); } +#endif +#ifndef signbit +inline bool signbit(double x) { struct ieee_double *p = (struct ieee_double *)&x; return p->dbl_sign; } +#endif + +#endif + +#if COMPILER(MSVC) || (COMPILER(RVCT) && !(RVCT_VERSION_AT_LEAST(3, 0, 0, 0))) + +// We must not do 'num + 0.5' or 'num - 0.5' because they can cause precision loss. +static double round(double num) +{ + double integer = ceil(num); + if (num > 0) + return integer - num > 0.5 ? integer - 1.0 : integer; + return integer - num >= 0.5 ? integer - 1.0 : integer; +} +static float roundf(float num) +{ + float integer = ceilf(num); + if (num > 0) + return integer - num > 0.5f ? integer - 1.0f : integer; + return integer - num >= 0.5f ? integer - 1.0f : integer; +} +inline long long llround(double num) { return static_cast(round(num)); } +inline long long llroundf(float num) { return static_cast(roundf(num)); } +inline long lround(double num) { return static_cast(round(num)); } +inline long lroundf(float num) { return static_cast(roundf(num)); } +inline double trunc(double num) { return num > 0 ? floor(num) : ceil(num); } + +#endif + +#if COMPILER(GCC) && OS(QNX) +// The stdlib on QNX doesn't contain long abs(long). See PR #104666. +inline long long abs(long num) { return labs(num); } +#endif + +#if COMPILER(MSVC) +// The 64bit version of abs() is already defined in stdlib.h which comes with VC10 +#if COMPILER(MSVC9_OR_LOWER) +inline long long abs(long long num) { return _abs64(num); } +#endif + +inline bool isinf(double num) { return !_finite(num) && !_isnan(num); } +inline bool isnan(double num) { return !!_isnan(num); } +inline bool signbit(double num) { return _copysign(1.0, num) < 0; } + +inline double nextafter(double x, double y) { return _nextafter(x, y); } +inline float nextafterf(float x, float y) { return x > y ? x - FLT_EPSILON : x + FLT_EPSILON; } + +inline double copysign(double x, double y) { return _copysign(x, y); } +inline int isfinite(double x) { return _finite(x); } + +// MSVC's math.h does not currently supply log2 or log2f. +inline double log2(double num) +{ + // This constant is roughly M_LN2, which is not provided by default on Windows. + return log(num) / 0.693147180559945309417232121458176568; +} + +inline float log2f(float num) +{ + // This constant is roughly M_LN2, which is not provided by default on Windows. + return logf(num) / 0.693147180559945309417232121458176568f; +} + +// Work around a bug in Win, where atan2(+-infinity, +-infinity) yields NaN instead of specific values. +inline double wtf_atan2(double x, double y) +{ + double posInf = std::numeric_limits::infinity(); + double negInf = -std::numeric_limits::infinity(); + double nan = std::numeric_limits::quiet_NaN(); + + double result = nan; + + if (x == posInf && y == posInf) + result = piOverFourDouble; + else if (x == posInf && y == negInf) + result = 3 * piOverFourDouble; + else if (x == negInf && y == posInf) + result = -piOverFourDouble; + else if (x == negInf && y == negInf) + result = -3 * piOverFourDouble; + else + result = ::atan2(x, y); + + return result; +} + +// Work around a bug in the Microsoft CRT, where fmod(x, +-infinity) yields NaN instead of x. +inline double wtf_fmod(double x, double y) { return (!isinf(x) && isinf(y)) ? x : fmod(x, y); } + +// Work around a bug in the Microsoft CRT, where pow(NaN, 0) yields NaN instead of 1. +inline double wtf_pow(double x, double y) { return y == 0 ? 1 : pow(x, y); } + +#define atan2(x, y) wtf_atan2(x, y) +#define fmod(x, y) wtf_fmod(x, y) +#define pow(x, y) wtf_pow(x, y) + +#endif // COMPILER(MSVC) + +inline double deg2rad(double d) { return d * piDouble / 180.0; } +inline double rad2deg(double r) { return r * 180.0 / piDouble; } +inline double deg2grad(double d) { return d * 400.0 / 360.0; } +inline double grad2deg(double g) { return g * 360.0 / 400.0; } +inline double turn2deg(double t) { return t * 360.0; } +inline double deg2turn(double d) { return d / 360.0; } +inline double rad2grad(double r) { return r * 200.0 / piDouble; } +inline double grad2rad(double g) { return g * piDouble / 200.0; } + +inline float deg2rad(float d) { return d * piFloat / 180.0f; } +inline float rad2deg(float r) { return r * 180.0f / piFloat; } +inline float deg2grad(float d) { return d * 400.0f / 360.0f; } +inline float grad2deg(float g) { return g * 360.0f / 400.0f; } +inline float turn2deg(float t) { return t * 360.0f; } +inline float deg2turn(float d) { return d / 360.0f; } +inline float rad2grad(float r) { return r * 200.0f / piFloat; } +inline float grad2rad(float g) { return g * piFloat / 200.0f; } + +// std::numeric_limits::min() returns the smallest positive value for floating point types +template inline T defaultMinimumForClamp() { return std::numeric_limits::min(); } +template<> inline float defaultMinimumForClamp() { return -std::numeric_limits::max(); } +template<> inline double defaultMinimumForClamp() { return -std::numeric_limits::max(); } +template inline T defaultMaximumForClamp() { return std::numeric_limits::max(); } + +template inline T clampTo(double value, T min = defaultMinimumForClamp(), T max = defaultMaximumForClamp()) +{ + if (value >= static_cast(max)) + return max; + if (value <= static_cast(min)) + return min; + return static_cast(value); +} +template<> inline long long int clampTo(double, long long int, long long int); // clampTo does not support long long ints. + +inline int clampToInteger(double value) +{ + return clampTo(value); +} + +inline float clampToFloat(double value) +{ + return clampTo(value); +} + +inline int clampToPositiveInteger(double value) +{ + return clampTo(value, 0); +} + +inline int clampToInteger(float value) +{ + return clampTo(value); +} + +inline int clampToInteger(unsigned x) +{ + const unsigned intMax = static_cast(std::numeric_limits::max()); + + if (x >= intMax) + return std::numeric_limits::max(); + return static_cast(x); +} + +inline bool isWithinIntRange(float x) +{ + return x > static_cast(std::numeric_limits::min()) && x < static_cast(std::numeric_limits::max()); +} + +#if !COMPILER(MSVC) && !COMPILER(RVCT) && !OS(SOLARIS) +using std::isfinite; +using std::isinf; +using std::isnan; +using std::signbit; +#endif + +// decompose 'number' to its sign, exponent, and mantissa components. +// The result is interpreted as: +// (sign ? -1 : 1) * pow(2, exponent) * (mantissa / (1 << 52)) +inline void decomposeDouble(double number, bool& sign, int32_t& exponent, uint64_t& mantissa) +{ + ASSERT(isfinite(number)); + + sign = signbit(number); + + uint64_t bits = WTF::bitwise_cast(number); + exponent = (static_cast(bits >> 52) & 0x7ff) - 0x3ff; + mantissa = bits & 0xFFFFFFFFFFFFFull; + + // Check for zero/denormal values; if so, adjust the exponent, + // if not insert the implicit, omitted leading 1 bit. + if (exponent == -0x3ff) + exponent = mantissa ? -0x3fe : 0; + else + mantissa |= 0x10000000000000ull; +} + +// Calculate d % 2^{64}. +inline void doubleToInteger(double d, unsigned long long& value) +{ + if (isnan(d) || isinf(d)) + value = 0; + else { + // -2^{64} < fmodValue < 2^{64}. + double fmodValue = fmod(trunc(d), std::numeric_limits::max() + 1.0); + if (fmodValue >= 0) { + // 0 <= fmodValue < 2^{64}. + // 0 <= value < 2^{64}. This cast causes no loss. + value = static_cast(fmodValue); + } else { + // -2^{64} < fmodValue < 0. + // 0 < fmodValueInUnsignedLongLong < 2^{64}. This cast causes no loss. + unsigned long long fmodValueInUnsignedLongLong = static_cast(-fmodValue); + // -1 < (std::numeric_limits::max() - fmodValueInUnsignedLongLong) < 2^{64} - 1. + // 0 < value < 2^{64}. + value = std::numeric_limits::max() - fmodValueInUnsignedLongLong + 1; + } + } +} + +#endif // #ifndef WTF_MathExtras_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MathObject.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MathObject.h new file mode 100644 index 000000000..d8da039d8 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MathObject.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef MathObject_h +#define MathObject_h + +#include "JSObject.h" + +namespace JSC { + + class MathObject : public JSNonFinalObject { + private: + MathObject(JSGlobalObject*, Structure*); + + public: + typedef JSNonFinalObject Base; + + static MathObject* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure) + { + MathObject* object = new (NotNull, allocateCell(*exec->heap())) MathObject(globalObject, structure); + object->finishCreation(exec, globalObject); + return object; + } + static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&); + static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); + + static const ClassInfo s_info; + + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + { + return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); + } + + protected: + void finishCreation(ExecState*, JSGlobalObject*); + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | JSObject::StructureFlags; + }; + +} // namespace JSC + +#endif // MathObject_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MemoryStatistics.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MemoryStatistics.h new file mode 100644 index 000000000..9a86df296 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MemoryStatistics.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2010 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 INC. 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 INC. 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 MemoryStatistics_h +#define MemoryStatistics_h + +#include "Heap.h" + +class JSGlobalData; + +namespace JSC { + +struct GlobalMemoryStatistics { + size_t stackBytes; + size_t JITBytes; +}; + +JS_EXPORT_PRIVATE GlobalMemoryStatistics globalMemoryStatistics(); + +} + +#endif // MemoryStatistics_h + diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MessageQueue.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MessageQueue.h new file mode 100644 index 000000000..dda852fe1 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MessageQueue.h @@ -0,0 +1,226 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * 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: + * + * 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 MessageQueue_h +#define MessageQueue_h + +#include +#include +#include +#include +#include + +namespace WTF { + + enum MessageQueueWaitResult { + MessageQueueTerminated, // Queue was destroyed while waiting for message. + MessageQueueTimeout, // Timeout was specified and it expired. + MessageQueueMessageReceived // A message was successfully received and returned. + }; + + // The queue takes ownership of messages and transfer it to the new owner + // when messages are fetched from the queue. + // Essentially, MessageQueue acts as a queue of OwnPtr. + template + class MessageQueue { + WTF_MAKE_NONCOPYABLE(MessageQueue); + public: + MessageQueue() : m_killed(false) { } + ~MessageQueue(); + + void append(PassOwnPtr); + bool appendAndCheckEmpty(PassOwnPtr); + void prepend(PassOwnPtr); + + PassOwnPtr waitForMessage(); + PassOwnPtr tryGetMessage(); + PassOwnPtr tryGetMessageIgnoringKilled(); + template + PassOwnPtr waitForMessageFilteredWithTimeout(MessageQueueWaitResult&, Predicate&, double absoluteTime); + + template + void removeIf(Predicate&); + + void kill(); + bool killed() const; + + // The result of isEmpty() is only valid if no other thread is manipulating the queue at the same time. + bool isEmpty(); + + static double infiniteTime() { return std::numeric_limits::max(); } + + private: + static bool alwaysTruePredicate(DataType*) { return true; } + + mutable Mutex m_mutex; + ThreadCondition m_condition; + Deque m_queue; + bool m_killed; + }; + + template + MessageQueue::~MessageQueue() + { + deleteAllValues(m_queue); + } + + template + inline void MessageQueue::append(PassOwnPtr message) + { + MutexLocker lock(m_mutex); + m_queue.append(message.leakPtr()); + m_condition.signal(); + } + + // Returns true if the queue was empty before the item was added. + template + inline bool MessageQueue::appendAndCheckEmpty(PassOwnPtr message) + { + MutexLocker lock(m_mutex); + bool wasEmpty = m_queue.isEmpty(); + m_queue.append(message.leakPtr()); + m_condition.signal(); + return wasEmpty; + } + + template + inline void MessageQueue::prepend(PassOwnPtr message) + { + MutexLocker lock(m_mutex); + m_queue.prepend(message.leakPtr()); + m_condition.signal(); + } + + template + inline PassOwnPtr MessageQueue::waitForMessage() + { + MessageQueueWaitResult exitReason; + OwnPtr result = waitForMessageFilteredWithTimeout(exitReason, MessageQueue::alwaysTruePredicate, infiniteTime()); + ASSERT(exitReason == MessageQueueTerminated || exitReason == MessageQueueMessageReceived); + return result.release(); + } + + template + template + inline PassOwnPtr MessageQueue::waitForMessageFilteredWithTimeout(MessageQueueWaitResult& result, Predicate& predicate, double absoluteTime) + { + MutexLocker lock(m_mutex); + bool timedOut = false; + + DequeConstIterator found = m_queue.end(); + while (!m_killed && !timedOut && (found = m_queue.findIf(predicate)) == m_queue.end()) + timedOut = !m_condition.timedWait(m_mutex, absoluteTime); + + ASSERT(!timedOut || absoluteTime != infiniteTime()); + + if (m_killed) { + result = MessageQueueTerminated; + return nullptr; + } + + if (timedOut) { + result = MessageQueueTimeout; + return nullptr; + } + + ASSERT(found != m_queue.end()); + OwnPtr message = adoptPtr(*found); + m_queue.remove(found); + result = MessageQueueMessageReceived; + return message.release(); + } + + template + inline PassOwnPtr MessageQueue::tryGetMessage() + { + MutexLocker lock(m_mutex); + if (m_killed) + return nullptr; + if (m_queue.isEmpty()) + return nullptr; + + return adoptPtr(m_queue.takeFirst()); + } + + template + inline PassOwnPtr MessageQueue::tryGetMessageIgnoringKilled() + { + MutexLocker lock(m_mutex); + if (m_queue.isEmpty()) + return nullptr; + + return adoptPtr(m_queue.takeFirst()); + } + + template + template + inline void MessageQueue::removeIf(Predicate& predicate) + { + MutexLocker lock(m_mutex); + DequeConstIterator found = m_queue.end(); + while ((found = m_queue.findIf(predicate)) != m_queue.end()) { + DataType* message = *found; + m_queue.remove(found); + delete message; + } + } + + template + inline bool MessageQueue::isEmpty() + { + MutexLocker lock(m_mutex); + if (m_killed) + return true; + return m_queue.isEmpty(); + } + + template + inline void MessageQueue::kill() + { + MutexLocker lock(m_mutex); + m_killed = true; + m_condition.broadcast(); + } + + template + inline bool MessageQueue::killed() const + { + MutexLocker lock(m_mutex); + return m_killed; + } +} // namespace WTF + +using WTF::MessageQueue; +// MessageQueueWaitResult enum and all its values. +using WTF::MessageQueueWaitResult; +using WTF::MessageQueueTerminated; +using WTF::MessageQueueTimeout; +using WTF::MessageQueueMessageReceived; + +#endif // MessageQueue_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MetaAllocator.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MetaAllocator.h new file mode 100644 index 000000000..3ab96bc1c --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MetaAllocator.h @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2011 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 WTF_MetaAllocator_h +#define WTF_MetaAllocator_h + +#include "Assertions.h" +#include "HashMap.h" +#include "MetaAllocatorHandle.h" +#include "Noncopyable.h" +#include "PageBlock.h" +#include "RedBlackTree.h" +#include "RefCounted.h" +#include "RefPtr.h" +#include "TCSpinLock.h" + +namespace WTF { + +#define ENABLE_META_ALLOCATOR_PROFILE 0 + +class MetaAllocatorTracker { +public: + void notify(MetaAllocatorHandle*); + void release(MetaAllocatorHandle*); + + MetaAllocatorHandle* find(void* address) + { + MetaAllocatorHandle* handle = m_allocations.findGreatestLessThanOrEqual(address); + if (handle && address < handle->end()) + return handle; + return 0; + } + + RedBlackTree m_allocations; +}; + +class MetaAllocator { + WTF_MAKE_NONCOPYABLE(MetaAllocator); + +public: + WTF_EXPORT_PRIVATE MetaAllocator(size_t allocationGranule); + + virtual ~MetaAllocator(); + + WTF_EXPORT_PRIVATE PassRefPtr allocate(size_t sizeInBytes); + + void trackAllocations(MetaAllocatorTracker* tracker) + { + m_tracker = tracker; + } + + // Non-atomic methods for getting allocator statistics. + size_t bytesAllocated() { return m_bytesAllocated; } + size_t bytesReserved() { return m_bytesReserved; } + size_t bytesCommitted() { return m_bytesCommitted; } + + // Atomic method for getting allocator statistics. + struct Statistics { + size_t bytesAllocated; + size_t bytesReserved; + size_t bytesCommitted; + }; + Statistics currentStatistics(); + + // Add more free space to the allocator. Call this directly from + // the constructor if you wish to operate the allocator within a + // fixed pool. + WTF_EXPORT_PRIVATE void addFreshFreeSpace(void* start, size_t sizeInBytes); + + // This is meant only for implementing tests. Never call this in release + // builds. + WTF_EXPORT_PRIVATE size_t debugFreeSpaceSize(); + +#if ENABLE(META_ALLOCATOR_PROFILE) + void dumpProfile(); +#else + void dumpProfile() { } +#endif + +protected: + + // Allocate new virtual space, but don't commit. This may return more + // pages than we asked, in which case numPages is changed. + virtual void* allocateNewSpace(size_t& numPages) = 0; + + // Commit a page. + virtual void notifyNeedPage(void* page) = 0; + + // Uncommit a page. + virtual void notifyPageIsFree(void* page) = 0; + + // NOTE: none of the above methods are called during allocator + // destruction, in part because a MetaAllocator cannot die so long + // as there are Handles that refer to it. + +private: + + friend class MetaAllocatorHandle; + + class FreeSpaceNode : public RedBlackTree::Node { + public: + FreeSpaceNode(void* start, size_t sizeInBytes) + : m_start(start) + , m_sizeInBytes(sizeInBytes) + { + } + + size_t key() + { + return m_sizeInBytes; + } + + void* m_start; + size_t m_sizeInBytes; + }; + typedef RedBlackTree Tree; + + // Release a MetaAllocatorHandle. + void release(MetaAllocatorHandle*); + + // Remove free space from the allocator. This is effectively + // the allocate() function, except that it does not mark the + // returned space as being in-use. + void* findAndRemoveFreeSpace(size_t sizeInBytes); + + // This is called when memory from an allocation is freed. + void addFreeSpaceFromReleasedHandle(void* start, size_t sizeInBytes); + + // This is the low-level implementation of adding free space; it + // is called from both addFreeSpaceFromReleasedHandle and from + // addFreshFreeSpace. + void addFreeSpace(void* start, size_t sizeInBytes); + + // Management of used space. + + void incrementPageOccupancy(void* address, size_t sizeInBytes); + void decrementPageOccupancy(void* address, size_t sizeInBytes); + + // Utilities. + + size_t roundUp(size_t sizeInBytes); + + FreeSpaceNode* allocFreeSpaceNode(); + WTF_EXPORT_PRIVATE void freeFreeSpaceNode(FreeSpaceNode*); + + size_t m_allocationGranule; + unsigned m_logAllocationGranule; + size_t m_pageSize; + unsigned m_logPageSize; + + Tree m_freeSpaceSizeMap; + HashMap m_freeSpaceStartAddressMap; + HashMap m_freeSpaceEndAddressMap; + HashMap m_pageOccupancyMap; + + size_t m_bytesAllocated; + size_t m_bytesReserved; + size_t m_bytesCommitted; + + SpinLock m_lock; + + MetaAllocatorTracker* m_tracker; + +#ifndef NDEBUG + size_t m_mallocBalance; +#endif + +#if ENABLE(META_ALLOCATOR_PROFILE) + unsigned m_numAllocations; + unsigned m_numFrees; +#endif +}; + +inline MetaAllocator::~MetaAllocator() +{ + for (FreeSpaceNode* node = m_freeSpaceSizeMap.first(); node;) { + FreeSpaceNode* next = node->successor(); + m_freeSpaceSizeMap.remove(node); + freeFreeSpaceNode(node); + node = next; + } +#ifndef NDEBUG + ASSERT(!m_mallocBalance); +#endif +} + +} // namespace WTF + +#endif // WTF_MetaAllocator_h + diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MetaAllocatorHandle.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MetaAllocatorHandle.h new file mode 100644 index 000000000..bdd015db4 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MetaAllocatorHandle.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2011 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 WTF_MetaAllocatorHandle_h +#define WTF_MetaAllocatorHandle_h + +#include +#include +#include +#include + +namespace WTF { + +class MetaAllocator; + +class MetaAllocatorHandle : public RefCounted, public RedBlackTree::Node { +private: + MetaAllocatorHandle(MetaAllocator*, void* start, size_t sizeInBytes); + +public: + WTF_EXPORT_PRIVATE ~MetaAllocatorHandle(); + + void* start() + { + return m_start; + } + + void* end() + { + return reinterpret_cast(reinterpret_cast(m_start) + m_sizeInBytes); + } + + size_t sizeInBytes() + { + return m_sizeInBytes; + } + + WTF_EXPORT_PRIVATE void shrink(size_t newSizeInBytes); + + bool isManaged() + { + return !!m_allocator; + } + + MetaAllocator* allocator() + { + ASSERT(m_allocator); + return m_allocator; + } + + void* key() + { + return m_start; + } + +private: + friend class MetaAllocator; + + MetaAllocator* m_allocator; + void* m_start; + size_t m_sizeInBytes; +}; + +} + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MethodCallLinkInfo.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MethodCallLinkInfo.h new file mode 100644 index 000000000..2243bc24e --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MethodCallLinkInfo.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2012 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 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 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 MethodCallLinkInfo_h +#define MethodCallLinkInfo_h + +#include "CodeLocation.h" +#include "JITCode.h" +#include "JITWriteBarrier.h" +#include + +namespace JSC { + +#if ENABLE(JIT) + +class RepatchBuffer; + +struct MethodCallLinkInfo { + MethodCallLinkInfo() + : seen(false) + { + } + + bool seenOnce() + { + return seen; + } + + void setSeen() + { + seen = true; + } + + void reset(RepatchBuffer&, JITCode::JITType); + + unsigned bytecodeIndex; + CodeLocationCall callReturnLocation; + JITWriteBarrier cachedStructure; + JITWriteBarrier cachedPrototypeStructure; + // We'd like this to actually be JSFunction, but InternalFunction and JSFunction + // don't have a common parent class and we allow specialisation on both + JITWriteBarrier cachedFunction; + JITWriteBarrier cachedPrototype; + bool seen; +}; + +inline void* getMethodCallLinkInfoReturnLocation(MethodCallLinkInfo* methodCallLinkInfo) +{ + return methodCallLinkInfo->callReturnLocation.executableAddress(); +} + +inline unsigned getMethodCallLinkInfoBytecodeIndex(MethodCallLinkInfo* methodCallLinkInfo) +{ + return methodCallLinkInfo->bytecodeIndex; +} + +#endif // ENABLE(JIT) + +} // namespace JSC + +#endif // MethodCallLinkInfo_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MethodCallLinkStatus.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MethodCallLinkStatus.h new file mode 100644 index 000000000..c3d11a1d8 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/MethodCallLinkStatus.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2012 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 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 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 MethodCallLinkStatus_h +#define MethodCallLinkStatus_h + +namespace JSC { + +class CodeBlock; +class JSObject; +class Structure; + +class MethodCallLinkStatus { +public: + MethodCallLinkStatus() + : m_structure(0) + , m_prototypeStructure(0) + , m_function(0) + , m_prototype(0) + { + } + + MethodCallLinkStatus( + Structure* structure, + Structure* prototypeStructure, + JSObject* function, + JSObject* prototype) + : m_structure(structure) + , m_prototypeStructure(prototypeStructure) + , m_function(function) + , m_prototype(prototype) + { + if (!m_function) { + ASSERT(!m_structure); + ASSERT(!m_prototypeStructure); + ASSERT(!m_prototype); + } else + ASSERT(m_structure); + + ASSERT(!m_prototype == !m_prototypeStructure); + } + + static MethodCallLinkStatus computeFor(CodeBlock*, unsigned bytecodeIndex); + + bool isSet() const { return !!m_function; } + bool operator!() const { return !m_function; } + + bool needsPrototypeCheck() const { return !!m_prototype; } + + Structure* structure() { return m_structure; } + Structure* prototypeStructure() { return m_prototypeStructure; } + JSObject* function() const { return m_function; } + JSObject* prototype() const { return m_prototype; } + +private: + Structure* m_structure; + Structure* m_prototypeStructure; + JSObject* m_function; + JSObject* m_prototype; +}; + +} // namespace JSC + +#endif // MethodCallLinkStatus_h + diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Nodes.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Nodes.h new file mode 100644 index 000000000..5098dc76c --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Nodes.h @@ -0,0 +1,1616 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2001 Peter Kelly (pmk@post.com) + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) + * Copyright (C) 2007 Maks Orlovich + * Copyright (C) 2007 Eric Seidel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef Nodes_h +#define Nodes_h + +#include "Error.h" +#include "JITCode.h" +#include "Opcode.h" +#include "ParserArena.h" +#include "ResultType.h" +#include "SourceCode.h" +#include "SymbolTable.h" +#include + +namespace JSC { + + class ArgumentListNode; + class BytecodeGenerator; + class FunctionBodyNode; + class Label; + class PropertyListNode; + class ReadModifyResolveNode; + class RegisterID; + class ScopeChainNode; + class ScopeNode; + + typedef unsigned CodeFeatures; + + const CodeFeatures NoFeatures = 0; + const CodeFeatures EvalFeature = 1 << 0; + const CodeFeatures ClosureFeature = 1 << 1; + const CodeFeatures AssignFeature = 1 << 2; + const CodeFeatures ArgumentsFeature = 1 << 3; + const CodeFeatures WithFeature = 1 << 4; + const CodeFeatures CatchFeature = 1 << 5; + const CodeFeatures ThisFeature = 1 << 6; + const CodeFeatures StrictModeFeature = 1 << 7; + const CodeFeatures ShadowsArgumentsFeature = 1 << 8; + + + const CodeFeatures AllFeatures = EvalFeature | ClosureFeature | AssignFeature | ArgumentsFeature | WithFeature | CatchFeature | ThisFeature | StrictModeFeature | ShadowsArgumentsFeature; + + enum Operator { + OpEqual, + OpPlusEq, + OpMinusEq, + OpMultEq, + OpDivEq, + OpPlusPlus, + OpMinusMinus, + OpAndEq, + OpXOrEq, + OpOrEq, + OpModEq, + OpLShift, + OpRShift, + OpURShift + }; + + enum LogicalOperator { + OpLogicalAnd, + OpLogicalOr + }; + + typedef HashSet, IdentifierRepHash> IdentifierSet; + + namespace DeclarationStacks { + enum VarAttrs { IsConstant = 1, HasInitializer = 2 }; + typedef Vector > VarStack; + typedef Vector FunctionStack; + } + + struct SwitchInfo { + enum SwitchType { SwitchNone, SwitchImmediate, SwitchCharacter, SwitchString }; + uint32_t bytecodeOffset; + SwitchType switchType; + }; + + class ParserArenaFreeable { + public: + // ParserArenaFreeable objects are are freed when the arena is deleted. + // Destructors are not called. Clients must not call delete on such objects. + void* operator new(size_t, JSGlobalData*); + }; + + class ParserArenaDeletable { + public: + virtual ~ParserArenaDeletable() { } + + // ParserArenaDeletable objects are deleted when the arena is deleted. + // Clients must not call delete directly on such objects. + void* operator new(size_t, JSGlobalData*); + }; + + template + struct ParserArenaData : ParserArenaDeletable { + T data; + }; + + class ParserArenaRefCounted : public RefCounted { + protected: + ParserArenaRefCounted(JSGlobalData*); + + public: + virtual ~ParserArenaRefCounted() + { + ASSERT(deletionHasBegun()); + } + }; + + class Node : public ParserArenaFreeable { + protected: + Node(int); + + public: + virtual ~Node() { } + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* destination = 0) = 0; + + int lineNo() const { return m_lineNumber; } + + protected: + int m_lineNumber; + }; + + class ExpressionNode : public Node { + protected: + ExpressionNode(int, ResultType = ResultType::unknownType()); + + public: + virtual bool isNumber() const { return false; } + virtual bool isString() const { return false; } + virtual bool isNull() const { return false; } + virtual bool isPure(BytecodeGenerator&) const { return false; } + virtual bool isLocation() const { return false; } + virtual bool isResolveNode() const { return false; } + virtual bool isBracketAccessorNode() const { return false; } + virtual bool isDotAccessorNode() const { return false; } + virtual bool isFuncExprNode() const { return false; } + virtual bool isCommaNode() const { return false; } + virtual bool isSimpleArray() const { return false; } + virtual bool isAdd() const { return false; } + virtual bool isSubtract() const { return false; } + virtual bool hasConditionContextCodegen() const { return false; } + + virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label*, Label*, bool) { ASSERT_NOT_REACHED(); } + + virtual ExpressionNode* stripUnaryPlus() { return this; } + + ResultType resultDescriptor() const { return m_resultType; } + + private: + ResultType m_resultType; + }; + + class StatementNode : public Node { + protected: + StatementNode(int); + + public: + JS_EXPORT_PRIVATE void setLoc(int firstLine, int lastLine); + int firstLine() const { return lineNo(); } + int lastLine() const { return m_lastLine; } + + virtual bool isEmptyStatement() const { return false; } + virtual bool isReturnNode() const { return false; } + virtual bool isExprStatement() const { return false; } + + virtual bool isBlock() const { return false; } + + private: + int m_lastLine; + }; + + class NullNode : public ExpressionNode { + public: + NullNode(int); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + virtual bool isNull() const { return true; } + }; + + class BooleanNode : public ExpressionNode { + public: + BooleanNode(int, bool value); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + virtual bool isPure(BytecodeGenerator&) const { return true; } + + bool m_value; + }; + + class NumberNode : public ExpressionNode { + public: + NumberNode(int, double value); + + double value() const { return m_value; } + void setValue(double value) { m_value = value; } + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + virtual bool isNumber() const { return true; } + virtual bool isPure(BytecodeGenerator&) const { return true; } + + double m_value; + }; + + class StringNode : public ExpressionNode { + public: + StringNode(int, const Identifier&); + + const Identifier& value() { return m_value; } + + private: + virtual bool isPure(BytecodeGenerator&) const { return true; } + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + virtual bool isString() const { return true; } + + const Identifier& m_value; + }; + + class ThrowableExpressionData { + public: + ThrowableExpressionData() + : m_divot(static_cast(-1)) + , m_startOffset(static_cast(-1)) + , m_endOffset(static_cast(-1)) + { + } + + ThrowableExpressionData(unsigned divot, unsigned startOffset, unsigned endOffset) + : m_divot(divot) + , m_startOffset(startOffset) + , m_endOffset(endOffset) + { + } + + void setExceptionSourceCode(unsigned divot, unsigned startOffset, unsigned endOffset) + { + m_divot = divot; + m_startOffset = startOffset; + m_endOffset = endOffset; + } + + uint32_t divot() const { return m_divot; } + uint16_t startOffset() const { return m_startOffset; } + uint16_t endOffset() const { return m_endOffset; } + + protected: + RegisterID* emitThrowReferenceError(BytecodeGenerator&, const UString& message); + + private: + uint32_t m_divot; + uint16_t m_startOffset; + uint16_t m_endOffset; + }; + + class ThrowableSubExpressionData : public ThrowableExpressionData { + public: + ThrowableSubExpressionData() + : m_subexpressionDivotOffset(0) + , m_subexpressionEndOffset(0) + { + } + + ThrowableSubExpressionData(unsigned divot, unsigned startOffset, unsigned endOffset) + : ThrowableExpressionData(divot, startOffset, endOffset) + , m_subexpressionDivotOffset(0) + , m_subexpressionEndOffset(0) + { + } + + void setSubexpressionInfo(uint32_t subexpressionDivot, uint16_t subexpressionOffset) + { + ASSERT(subexpressionDivot <= divot()); + if ((divot() - subexpressionDivot) & ~0xFFFF) // Overflow means we can't do this safely, so just point at the primary divot + return; + m_subexpressionDivotOffset = divot() - subexpressionDivot; + m_subexpressionEndOffset = subexpressionOffset; + } + + protected: + uint16_t m_subexpressionDivotOffset; + uint16_t m_subexpressionEndOffset; + }; + + class ThrowablePrefixedSubExpressionData : public ThrowableExpressionData { + public: + ThrowablePrefixedSubExpressionData() + : m_subexpressionDivotOffset(0) + , m_subexpressionStartOffset(0) + { + } + + ThrowablePrefixedSubExpressionData(unsigned divot, unsigned startOffset, unsigned endOffset) + : ThrowableExpressionData(divot, startOffset, endOffset) + , m_subexpressionDivotOffset(0) + , m_subexpressionStartOffset(0) + { + } + + void setSubexpressionInfo(uint32_t subexpressionDivot, uint16_t subexpressionOffset) + { + ASSERT(subexpressionDivot >= divot()); + if ((subexpressionDivot - divot()) & ~0xFFFF) // Overflow means we can't do this safely, so just point at the primary divot + return; + m_subexpressionDivotOffset = subexpressionDivot - divot(); + m_subexpressionStartOffset = subexpressionOffset; + } + + protected: + uint16_t m_subexpressionDivotOffset; + uint16_t m_subexpressionStartOffset; + }; + + class RegExpNode : public ExpressionNode, public ThrowableExpressionData { + public: + RegExpNode(int, const Identifier& pattern, const Identifier& flags); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + const Identifier& m_pattern; + const Identifier& m_flags; + }; + + class ThisNode : public ExpressionNode { + public: + ThisNode(int); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + }; + + class ResolveNode : public ExpressionNode { + public: + ResolveNode(int, const Identifier&, int startOffset); + + const Identifier& identifier() const { return m_ident; } + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + virtual bool isPure(BytecodeGenerator&) const ; + virtual bool isLocation() const { return true; } + virtual bool isResolveNode() const { return true; } + + const Identifier& m_ident; + int32_t m_startOffset; + }; + + class ElementNode : public ParserArenaFreeable { + public: + ElementNode(int elision, ExpressionNode*); + ElementNode(ElementNode*, int elision, ExpressionNode*); + + int elision() const { return m_elision; } + ExpressionNode* value() { return m_node; } + ElementNode* next() { return m_next; } + + private: + ElementNode* m_next; + int m_elision; + ExpressionNode* m_node; + }; + + class ArrayNode : public ExpressionNode { + public: + ArrayNode(int, int elision); + ArrayNode(int, ElementNode*); + ArrayNode(int, int elision, ElementNode*); + + ArgumentListNode* toArgumentList(JSGlobalData*, int) const; + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + virtual bool isSimpleArray() const ; + + ElementNode* m_element; + int m_elision; + bool m_optional; + }; + + class PropertyNode : public ParserArenaFreeable { + public: + enum Type { Constant = 1, Getter = 2, Setter = 4 }; + + PropertyNode(JSGlobalData*, const Identifier&, ExpressionNode*, Type); + PropertyNode(JSGlobalData*, double, ExpressionNode*, Type); + + const Identifier& name() const { return m_name; } + Type type() const { return m_type; } + + private: + friend class PropertyListNode; + const Identifier& m_name; + ExpressionNode* m_assign; + Type m_type; + }; + + class PropertyListNode : public Node { + public: + PropertyListNode(int, PropertyNode*); + PropertyListNode(int, PropertyNode*, PropertyListNode*); + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + private: + PropertyNode* m_node; + PropertyListNode* m_next; + }; + + class ObjectLiteralNode : public ExpressionNode { + public: + ObjectLiteralNode(int); + ObjectLiteralNode(int, PropertyListNode*); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + PropertyListNode* m_list; + }; + + class BracketAccessorNode : public ExpressionNode, public ThrowableExpressionData { + public: + BracketAccessorNode(int, ExpressionNode* base, ExpressionNode* subscript, bool subscriptHasAssignments); + + ExpressionNode* base() const { return m_base; } + ExpressionNode* subscript() const { return m_subscript; } + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + virtual bool isLocation() const { return true; } + virtual bool isBracketAccessorNode() const { return true; } + + ExpressionNode* m_base; + ExpressionNode* m_subscript; + bool m_subscriptHasAssignments; + }; + + class DotAccessorNode : public ExpressionNode, public ThrowableExpressionData { + public: + DotAccessorNode(int, ExpressionNode* base, const Identifier&); + + ExpressionNode* base() const { return m_base; } + const Identifier& identifier() const { return m_ident; } + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + virtual bool isLocation() const { return true; } + virtual bool isDotAccessorNode() const { return true; } + + ExpressionNode* m_base; + const Identifier& m_ident; + }; + + class ArgumentListNode : public Node { + public: + ArgumentListNode(int, ExpressionNode*); + ArgumentListNode(int, ArgumentListNode*, ExpressionNode*); + + ArgumentListNode* m_next; + ExpressionNode* m_expr; + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + }; + + class ArgumentsNode : public ParserArenaFreeable { + public: + ArgumentsNode(); + ArgumentsNode(ArgumentListNode*); + + ArgumentListNode* m_listNode; + }; + + class NewExprNode : public ExpressionNode, public ThrowableExpressionData { + public: + NewExprNode(int, ExpressionNode*); + NewExprNode(int, ExpressionNode*, ArgumentsNode*); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; + ArgumentsNode* m_args; + }; + + class EvalFunctionCallNode : public ExpressionNode, public ThrowableExpressionData { + public: + EvalFunctionCallNode(int, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ArgumentsNode* m_args; + }; + + class FunctionCallValueNode : public ExpressionNode, public ThrowableExpressionData { + public: + FunctionCallValueNode(int, ExpressionNode*, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; + ArgumentsNode* m_args; + }; + + class FunctionCallResolveNode : public ExpressionNode, public ThrowableExpressionData { + public: + FunctionCallResolveNode(int, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + const Identifier& m_ident; + ArgumentsNode* m_args; + size_t m_index; // Used by LocalVarFunctionCallNode. + size_t m_scopeDepth; // Used by ScopedVarFunctionCallNode and NonLocalVarFunctionCallNode + }; + + class FunctionCallBracketNode : public ExpressionNode, public ThrowableSubExpressionData { + public: + FunctionCallBracketNode(int, ExpressionNode* base, ExpressionNode* subscript, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_base; + ExpressionNode* m_subscript; + ArgumentsNode* m_args; + }; + + class FunctionCallDotNode : public ExpressionNode, public ThrowableSubExpressionData { + public: + FunctionCallDotNode(int, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + protected: + ExpressionNode* m_base; + const Identifier& m_ident; + ArgumentsNode* m_args; + }; + + class CallFunctionCallDotNode : public FunctionCallDotNode { + public: + CallFunctionCallDotNode(int, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + }; + + class ApplyFunctionCallDotNode : public FunctionCallDotNode { + public: + ApplyFunctionCallDotNode(int, ExpressionNode* base, const Identifier&, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + }; + + class PrePostResolveNode : public ExpressionNode, public ThrowableExpressionData { + public: + PrePostResolveNode(int, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset); + + protected: + const Identifier& m_ident; + }; + + class PostfixResolveNode : public PrePostResolveNode { + public: + PostfixResolveNode(int, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + Operator m_operator; + }; + + class PostfixBracketNode : public ExpressionNode, public ThrowableSubExpressionData { + public: + PostfixBracketNode(int, ExpressionNode* base, ExpressionNode* subscript, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_base; + ExpressionNode* m_subscript; + Operator m_operator; + }; + + class PostfixDotNode : public ExpressionNode, public ThrowableSubExpressionData { + public: + PostfixDotNode(int, ExpressionNode* base, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_base; + const Identifier& m_ident; + Operator m_operator; + }; + + class PostfixErrorNode : public ExpressionNode, public ThrowableSubExpressionData { + public: + PostfixErrorNode(int, ExpressionNode*, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; + Operator m_operator; + }; + + class DeleteResolveNode : public ExpressionNode, public ThrowableExpressionData { + public: + DeleteResolveNode(int, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + const Identifier& m_ident; + }; + + class DeleteBracketNode : public ExpressionNode, public ThrowableExpressionData { + public: + DeleteBracketNode(int, ExpressionNode* base, ExpressionNode* subscript, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_base; + ExpressionNode* m_subscript; + }; + + class DeleteDotNode : public ExpressionNode, public ThrowableExpressionData { + public: + DeleteDotNode(int, ExpressionNode* base, const Identifier&, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_base; + const Identifier& m_ident; + }; + + class DeleteValueNode : public ExpressionNode { + public: + DeleteValueNode(int, ExpressionNode*); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; + }; + + class VoidNode : public ExpressionNode { + public: + VoidNode(int, ExpressionNode*); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; + }; + + class TypeOfResolveNode : public ExpressionNode { + public: + TypeOfResolveNode(int, const Identifier&); + + const Identifier& identifier() const { return m_ident; } + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + const Identifier& m_ident; + }; + + class TypeOfValueNode : public ExpressionNode { + public: + TypeOfValueNode(int, ExpressionNode*); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; + }; + + class PrefixResolveNode : public PrePostResolveNode { + public: + PrefixResolveNode(int, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + Operator m_operator; + }; + + class PrefixBracketNode : public ExpressionNode, public ThrowablePrefixedSubExpressionData { + public: + PrefixBracketNode(int, ExpressionNode* base, ExpressionNode* subscript, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_base; + ExpressionNode* m_subscript; + Operator m_operator; + }; + + class PrefixDotNode : public ExpressionNode, public ThrowablePrefixedSubExpressionData { + public: + PrefixDotNode(int, ExpressionNode* base, const Identifier&, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_base; + const Identifier& m_ident; + Operator m_operator; + }; + + class PrefixErrorNode : public ExpressionNode, public ThrowableExpressionData { + public: + PrefixErrorNode(int, ExpressionNode*, Operator, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; + Operator m_operator; + }; + + class UnaryOpNode : public ExpressionNode { + public: + UnaryOpNode(int, ResultType, ExpressionNode*, OpcodeID); + + protected: + ExpressionNode* expr() { return m_expr; } + const ExpressionNode* expr() const { return m_expr; } + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + OpcodeID opcodeID() const { return m_opcodeID; } + + ExpressionNode* m_expr; + OpcodeID m_opcodeID; + }; + + class UnaryPlusNode : public UnaryOpNode { + public: + UnaryPlusNode(int, ExpressionNode*); + + private: + virtual ExpressionNode* stripUnaryPlus() { return expr(); } + }; + + class NegateNode : public UnaryOpNode { + public: + NegateNode(int, ExpressionNode*); + }; + + class BitwiseNotNode : public UnaryOpNode { + public: + BitwiseNotNode(int, ExpressionNode*); + }; + + class LogicalNotNode : public UnaryOpNode { + public: + LogicalNotNode(int, ExpressionNode*); + private: + void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue); + virtual bool hasConditionContextCodegen() const { return expr()->hasConditionContextCodegen(); } + }; + + class BinaryOpNode : public ExpressionNode { + public: + BinaryOpNode(int, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); + BinaryOpNode(int, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); + + RegisterID* emitStrcat(BytecodeGenerator& generator, RegisterID* destination, RegisterID* lhs = 0, ReadModifyResolveNode* emitExpressionInfoForMe = 0); + + ExpressionNode* lhs() { return m_expr1; }; + ExpressionNode* rhs() { return m_expr2; }; + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + protected: + OpcodeID opcodeID() const { return m_opcodeID; } + + protected: + ExpressionNode* m_expr1; + ExpressionNode* m_expr2; + private: + OpcodeID m_opcodeID; + protected: + bool m_rightHasAssignments; + }; + + class MultNode : public BinaryOpNode { + public: + MultNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + }; + + class DivNode : public BinaryOpNode { + public: + DivNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + }; + + class ModNode : public BinaryOpNode { + public: + ModNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + }; + + class AddNode : public BinaryOpNode { + public: + AddNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + + virtual bool isAdd() const { return true; } + }; + + class SubNode : public BinaryOpNode { + public: + SubNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + + virtual bool isSubtract() const { return true; } + }; + + class LeftShiftNode : public BinaryOpNode { + public: + LeftShiftNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + }; + + class RightShiftNode : public BinaryOpNode { + public: + RightShiftNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + }; + + class UnsignedRightShiftNode : public BinaryOpNode { + public: + UnsignedRightShiftNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + }; + + class LessNode : public BinaryOpNode { + public: + LessNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + }; + + class GreaterNode : public BinaryOpNode { + public: + GreaterNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + }; + + class LessEqNode : public BinaryOpNode { + public: + LessEqNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + }; + + class GreaterEqNode : public BinaryOpNode { + public: + GreaterEqNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + }; + + class ThrowableBinaryOpNode : public BinaryOpNode, public ThrowableExpressionData { + public: + ThrowableBinaryOpNode(int, ResultType, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); + ThrowableBinaryOpNode(int, ExpressionNode* expr1, ExpressionNode* expr2, OpcodeID, bool rightHasAssignments); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + }; + + class InstanceOfNode : public ThrowableBinaryOpNode { + public: + InstanceOfNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + }; + + class InNode : public ThrowableBinaryOpNode { + public: + InNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + }; + + class EqualNode : public BinaryOpNode { + public: + EqualNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + }; + + class NotEqualNode : public BinaryOpNode { + public: + NotEqualNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + }; + + class StrictEqualNode : public BinaryOpNode { + public: + StrictEqualNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + }; + + class NotStrictEqualNode : public BinaryOpNode { + public: + NotStrictEqualNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + }; + + class BitAndNode : public BinaryOpNode { + public: + BitAndNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + }; + + class BitOrNode : public BinaryOpNode { + public: + BitOrNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + }; + + class BitXOrNode : public BinaryOpNode { + public: + BitXOrNode(int, ExpressionNode* expr1, ExpressionNode* expr2, bool rightHasAssignments); + }; + + // m_expr1 && m_expr2, m_expr1 || m_expr2 + class LogicalOpNode : public ExpressionNode { + public: + LogicalOpNode(int, ExpressionNode* expr1, ExpressionNode* expr2, LogicalOperator); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue); + virtual bool hasConditionContextCodegen() const { return true; } + + ExpressionNode* m_expr1; + ExpressionNode* m_expr2; + LogicalOperator m_operator; + }; + + // The ternary operator, "m_logical ? m_expr1 : m_expr2" + class ConditionalNode : public ExpressionNode { + public: + ConditionalNode(int, ExpressionNode* logical, ExpressionNode* expr1, ExpressionNode* expr2); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_logical; + ExpressionNode* m_expr1; + ExpressionNode* m_expr2; + }; + + class ReadModifyResolveNode : public ExpressionNode, public ThrowableExpressionData { + public: + ReadModifyResolveNode(int, const Identifier&, Operator, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + const Identifier& m_ident; + ExpressionNode* m_right; + size_t m_index; // Used by ReadModifyLocalVarNode. + Operator m_operator; + bool m_rightHasAssignments; + }; + + class AssignResolveNode : public ExpressionNode, public ThrowableExpressionData { + public: + AssignResolveNode(int, const Identifier&, ExpressionNode* right, bool rightHasAssignments); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + const Identifier& m_ident; + ExpressionNode* m_right; + size_t m_index; // Used by ReadModifyLocalVarNode. + bool m_rightHasAssignments; + }; + + class ReadModifyBracketNode : public ExpressionNode, public ThrowableSubExpressionData { + public: + ReadModifyBracketNode(int, ExpressionNode* base, ExpressionNode* subscript, Operator, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_base; + ExpressionNode* m_subscript; + ExpressionNode* m_right; + Operator m_operator : 30; + bool m_subscriptHasAssignments : 1; + bool m_rightHasAssignments : 1; + }; + + class AssignBracketNode : public ExpressionNode, public ThrowableExpressionData { + public: + AssignBracketNode(int, ExpressionNode* base, ExpressionNode* subscript, ExpressionNode* right, bool subscriptHasAssignments, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_base; + ExpressionNode* m_subscript; + ExpressionNode* m_right; + bool m_subscriptHasAssignments : 1; + bool m_rightHasAssignments : 1; + }; + + class AssignDotNode : public ExpressionNode, public ThrowableExpressionData { + public: + AssignDotNode(int, ExpressionNode* base, const Identifier&, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_base; + const Identifier& m_ident; + ExpressionNode* m_right; + bool m_rightHasAssignments; + }; + + class ReadModifyDotNode : public ExpressionNode, public ThrowableSubExpressionData { + public: + ReadModifyDotNode(int, ExpressionNode* base, const Identifier&, Operator, ExpressionNode* right, bool rightHasAssignments, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_base; + const Identifier& m_ident; + ExpressionNode* m_right; + Operator m_operator : 31; + bool m_rightHasAssignments : 1; + }; + + class AssignErrorNode : public ExpressionNode, public ThrowableExpressionData { + public: + AssignErrorNode(int, ExpressionNode* left, Operator, ExpressionNode* right, unsigned divot, unsigned startOffset, unsigned endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_left; + Operator m_operator; + ExpressionNode* m_right; + }; + + typedef Vector ExpressionVector; + + class CommaNode : public ExpressionNode, public ParserArenaDeletable { + public: + CommaNode(int, ExpressionNode* expr1, ExpressionNode* expr2); + + using ParserArenaDeletable::operator new; + + void append(ExpressionNode* expr) { m_expressions.append(expr); } + + private: + virtual bool isCommaNode() const { return true; } + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionVector m_expressions; + }; + + class ConstDeclNode : public ExpressionNode { + public: + ConstDeclNode(int, const Identifier&, ExpressionNode*); + + bool hasInitializer() const { return m_init; } + const Identifier& ident() { return m_ident; } + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + virtual RegisterID* emitCodeSingle(BytecodeGenerator&); + + const Identifier& m_ident; + + public: + ConstDeclNode* m_next; + + private: + ExpressionNode* m_init; + }; + + class ConstStatementNode : public StatementNode { + public: + ConstStatementNode(int, ConstDeclNode* next); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ConstDeclNode* m_next; + }; + + class SourceElements : public ParserArenaDeletable { + public: + SourceElements(); + + void append(StatementNode*); + + StatementNode* singleStatement() const; + StatementNode* lastStatement() const; + + void emitBytecode(BytecodeGenerator&, RegisterID* destination); + + private: + Vector m_statements; + }; + + class BlockNode : public StatementNode { + public: + BlockNode(int, SourceElements* = 0); + + StatementNode* singleStatement() const; + StatementNode* lastStatement() const; + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + virtual bool isBlock() const { return true; } + + SourceElements* m_statements; + }; + + class EmptyStatementNode : public StatementNode { + public: + EmptyStatementNode(int); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + virtual bool isEmptyStatement() const { return true; } + }; + + class DebuggerStatementNode : public StatementNode { + public: + DebuggerStatementNode(int); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + }; + + class ExprStatementNode : public StatementNode { + public: + ExprStatementNode(int, ExpressionNode*); + + ExpressionNode* expr() const { return m_expr; } + + private: + virtual bool isExprStatement() const { return true; } + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; + }; + + class VarStatementNode : public StatementNode { + public: + VarStatementNode(int, ExpressionNode*); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; + }; + + class IfNode : public StatementNode { + public: + IfNode(int, ExpressionNode* condition, StatementNode* ifBlock); + + protected: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_condition; + StatementNode* m_ifBlock; + }; + + class IfElseNode : public IfNode { + public: + IfElseNode(int, ExpressionNode* condition, StatementNode* ifBlock, StatementNode* elseBlock); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + StatementNode* m_elseBlock; + }; + + class DoWhileNode : public StatementNode { + public: + DoWhileNode(int, StatementNode*, ExpressionNode*); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + StatementNode* m_statement; + ExpressionNode* m_expr; + }; + + class WhileNode : public StatementNode { + public: + WhileNode(int, ExpressionNode*, StatementNode*); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; + StatementNode* m_statement; + }; + + class ForNode : public StatementNode { + public: + ForNode(int, ExpressionNode* expr1, ExpressionNode* expr2, ExpressionNode* expr3, StatementNode*, bool expr1WasVarDecl); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr1; + ExpressionNode* m_expr2; + ExpressionNode* m_expr3; + StatementNode* m_statement; + bool m_expr1WasVarDecl; + }; + + class ForInNode : public StatementNode, public ThrowableExpressionData { + public: + ForInNode(JSGlobalData*, int, ExpressionNode*, ExpressionNode*, StatementNode*); + ForInNode(JSGlobalData*, int, const Identifier&, ExpressionNode*, ExpressionNode*, StatementNode*, int divot, int startOffset, int endOffset); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + const Identifier& m_ident; + ExpressionNode* m_init; + ExpressionNode* m_lexpr; + ExpressionNode* m_expr; + StatementNode* m_statement; + bool m_identIsVarDecl; + }; + + class ContinueNode : public StatementNode, public ThrowableExpressionData { + public: + ContinueNode(JSGlobalData*, int); + ContinueNode(int, const Identifier&); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + const Identifier& m_ident; + }; + + class BreakNode : public StatementNode, public ThrowableExpressionData { + public: + BreakNode(JSGlobalData*, int); + BreakNode(int, const Identifier&); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + const Identifier& m_ident; + }; + + class ReturnNode : public StatementNode, public ThrowableExpressionData { + public: + ReturnNode(int, ExpressionNode* value); + + ExpressionNode* value() { return m_value; } + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + virtual bool isReturnNode() const { return true; } + + ExpressionNode* m_value; + }; + + class WithNode : public StatementNode { + public: + WithNode(int, ExpressionNode*, StatementNode*, uint32_t divot, uint32_t expressionLength); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; + StatementNode* m_statement; + uint32_t m_divot; + uint32_t m_expressionLength; + }; + + class LabelNode : public StatementNode, public ThrowableExpressionData { + public: + LabelNode(int, const Identifier& name, StatementNode*); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + const Identifier& m_name; + StatementNode* m_statement; + }; + + class ThrowNode : public StatementNode, public ThrowableExpressionData { + public: + ThrowNode(int, ExpressionNode*); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; + }; + + class TryNode : public StatementNode { + public: + TryNode(int, StatementNode* tryBlock, const Identifier& exceptionIdent, bool catchHasEval, StatementNode* catchBlock, StatementNode* finallyBlock); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + StatementNode* m_tryBlock; + const Identifier& m_exceptionIdent; + StatementNode* m_catchBlock; + StatementNode* m_finallyBlock; + bool m_catchHasEval; + }; + + class ParameterNode : public ParserArenaFreeable { + public: + ParameterNode(const Identifier&); + ParameterNode(ParameterNode*, const Identifier&); + + const Identifier& ident() const { return m_ident; } + ParameterNode* nextParam() const { return m_next; } + + private: + const Identifier& m_ident; + ParameterNode* m_next; + }; + + struct ScopeNodeData { + WTF_MAKE_FAST_ALLOCATED; + public: + typedef DeclarationStacks::VarStack VarStack; + typedef DeclarationStacks::FunctionStack FunctionStack; + + ScopeNodeData(ParserArena&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, int numConstants); + + ParserArena m_arena; + VarStack m_varStack; + FunctionStack m_functionStack; + int m_numConstants; + SourceElements* m_statements; + IdentifierSet m_capturedVariables; + }; + + class ScopeNode : public StatementNode, public ParserArenaRefCounted { + public: + typedef DeclarationStacks::VarStack VarStack; + typedef DeclarationStacks::FunctionStack FunctionStack; + + ScopeNode(JSGlobalData*, int, bool inStrictContext); + ScopeNode(JSGlobalData*, int, const SourceCode&, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, CodeFeatures, int numConstants); + + using ParserArenaRefCounted::operator new; + + ScopeNodeData* data() const { return m_data.get(); } + void destroyData() { m_data.clear(); } + + const SourceCode& source() const { return m_source; } + const UString& sourceURL() const { return m_source.provider()->url(); } + intptr_t sourceID() const { return m_source.provider()->asID(); } + + void setFeatures(CodeFeatures features) { m_features = features; } + CodeFeatures features() { return m_features; } + + bool usesEval() const { return m_features & EvalFeature; } + bool usesArguments() const { return (m_features & ArgumentsFeature) && !(m_features & ShadowsArgumentsFeature); } + bool isStrictMode() const { return m_features & StrictModeFeature; } + void setUsesArguments() { m_features |= ArgumentsFeature; } + bool usesThis() const { return m_features & ThisFeature; } + bool needsActivationForMoreThanVariables() const { ASSERT(m_data); return m_features & (EvalFeature | WithFeature | CatchFeature); } + bool needsActivation() const { ASSERT(m_data); return (hasCapturedVariables()) || (m_features & (EvalFeature | WithFeature | CatchFeature)); } + bool hasCapturedVariables() const { return !!m_data->m_capturedVariables.size(); } + size_t capturedVariableCount() const { return m_data->m_capturedVariables.size(); } + bool captures(const Identifier& ident) { return m_data->m_capturedVariables.contains(ident.impl()); } + + VarStack& varStack() { ASSERT(m_data); return m_data->m_varStack; } + FunctionStack& functionStack() { ASSERT(m_data); return m_data->m_functionStack; } + + int neededConstants() + { + ASSERT(m_data); + // We may need 2 more constants than the count given by the parser, + // because of the various uses of jsUndefined() and jsNull(). + return m_data->m_numConstants + 2; + } + + StatementNode* singleStatement() const; + + void emitStatementsBytecode(BytecodeGenerator&, RegisterID* destination); + + protected: + void setSource(const SourceCode& source) { m_source = source; } + + private: + OwnPtr m_data; + CodeFeatures m_features; + SourceCode m_source; + }; + + class ProgramNode : public ScopeNode { + public: + static const bool isFunctionNode = false; + static PassRefPtr create(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + + static const bool scopeIsFunction = false; + + private: + ProgramNode(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + }; + + class EvalNode : public ScopeNode { + public: + static const bool isFunctionNode = false; + static PassRefPtr create(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + + static const bool scopeIsFunction = false; + + private: + EvalNode(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + }; + + class FunctionParameters : public Vector, public RefCounted { + WTF_MAKE_FAST_ALLOCATED; + public: + static PassRefPtr create(ParameterNode* firstParameter) { return adoptRef(new FunctionParameters(firstParameter)); } + + private: + FunctionParameters(ParameterNode*); + }; + + class FunctionBodyNode : public ScopeNode { + public: + static const bool isFunctionNode = true; + static FunctionBodyNode* create(JSGlobalData*, int, bool isStrictMode); + static PassRefPtr create(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + + FunctionParameters* parameters() const { return m_parameters.get(); } + size_t parameterCount() const { return m_parameters->size(); } + + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + void finishParsing(const SourceCode&, ParameterNode*, const Identifier&); + void finishParsing(PassRefPtr, const Identifier&); + + const Identifier& ident() { return m_ident; } + + static const bool scopeIsFunction = true; + + private: + FunctionBodyNode(JSGlobalData*, int, bool inStrictContext); + FunctionBodyNode(JSGlobalData*, int, SourceElements*, VarStack*, FunctionStack*, IdentifierSet&, const SourceCode&, CodeFeatures, int numConstants); + + Identifier m_ident; + RefPtr m_parameters; + }; + + class FuncExprNode : public ExpressionNode { + public: + FuncExprNode(int, const Identifier&, FunctionBodyNode*, const SourceCode&, ParameterNode* = 0); + + FunctionBodyNode* body() { return m_body; } + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + virtual bool isFuncExprNode() const { return true; } + + FunctionBodyNode* m_body; + }; + + class FuncDeclNode : public StatementNode { + public: + FuncDeclNode(int, const Identifier&, FunctionBodyNode*, const SourceCode&, ParameterNode* = 0); + + FunctionBodyNode* body() { return m_body; } + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + FunctionBodyNode* m_body; + }; + + class CaseClauseNode : public ParserArenaFreeable { + public: + CaseClauseNode(ExpressionNode*, SourceElements* = 0); + + ExpressionNode* expr() const { return m_expr; } + + void emitBytecode(BytecodeGenerator&, RegisterID* destination); + + private: + ExpressionNode* m_expr; + SourceElements* m_statements; + }; + + class ClauseListNode : public ParserArenaFreeable { + public: + ClauseListNode(CaseClauseNode*); + ClauseListNode(ClauseListNode*, CaseClauseNode*); + + CaseClauseNode* getClause() const { return m_clause; } + ClauseListNode* getNext() const { return m_next; } + + private: + CaseClauseNode* m_clause; + ClauseListNode* m_next; + }; + + class CaseBlockNode : public ParserArenaFreeable { + public: + CaseBlockNode(ClauseListNode* list1, CaseClauseNode* defaultClause, ClauseListNode* list2); + + RegisterID* emitBytecodeForBlock(BytecodeGenerator&, RegisterID* input, RegisterID* destination); + + private: + SwitchInfo::SwitchType tryOptimizedSwitch(Vector& literalVector, int32_t& min_num, int32_t& max_num); + ClauseListNode* m_list1; + CaseClauseNode* m_defaultClause; + ClauseListNode* m_list2; + }; + + class SwitchNode : public StatementNode { + public: + SwitchNode(int, ExpressionNode*, CaseBlockNode*); + + private: + virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + + ExpressionNode* m_expr; + CaseBlockNode* m_block; + }; + + struct ElementList { + ElementNode* head; + ElementNode* tail; + }; + + struct PropertyList { + PropertyListNode* head; + PropertyListNode* tail; + }; + + struct ArgumentList { + ArgumentListNode* head; + ArgumentListNode* tail; + }; + + struct ConstDeclList { + ConstDeclNode* head; + ConstDeclNode* tail; + }; + + struct ParameterList { + ParameterNode* head; + ParameterNode* tail; + }; + + struct ClauseList { + ClauseListNode* head; + ClauseListNode* tail; + }; + +} // namespace JSC + +#endif // Nodes_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/NonCopyingSort.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/NonCopyingSort.h new file mode 100644 index 000000000..fd611bde7 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/NonCopyingSort.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2010 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 WTF_NonCopyingSort_h +#define WTF_NonCopyingSort_h + +namespace WTF { + +using std::swap; + +template +inline void siftDown(RandomAccessIterator array, ptrdiff_t start, ptrdiff_t end, Predicate compareLess) +{ + ptrdiff_t root = start; + + while (root * 2 + 1 <= end) { + ptrdiff_t child = root * 2 + 1; + if (child < end && compareLess(array[child], array[child + 1])) + child++; + + if (compareLess(array[root], array[child])) { + swap(array[root], array[child]); + root = child; + } else + return; + } +} + +template +inline void heapify(RandomAccessIterator array, ptrdiff_t count, Predicate compareLess) +{ + ptrdiff_t start = (count - 2) / 2; + + while (start >= 0) { + siftDown(array, start, count - 1, compareLess); + start--; + } +} + +template +void heapSort(RandomAccessIterator start, RandomAccessIterator end, Predicate compareLess) +{ + ptrdiff_t count = end - start; + heapify(start, count, compareLess); + + ptrdiff_t endIndex = count - 1; + while (endIndex > 0) { + swap(start[endIndex], start[0]); + siftDown(start, 0, endIndex - 1, compareLess); + endIndex--; + } +} + +template +inline void nonCopyingSort(RandomAccessIterator start, RandomAccessIterator end, Predicate compareLess) +{ + // heapsort happens to use only swaps, not copies, but the essential thing about + // this function is the fact that it does not copy, not the specific algorithm + heapSort(start, end, compareLess); +} + +} // namespace WTF + +using WTF::nonCopyingSort; + +#endif // WTF_NonCopyingSort_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Noncopyable.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Noncopyable.h new file mode 100644 index 000000000..9f93f173b --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Noncopyable.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2006, 2010 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WTF_Noncopyable_h +#define WTF_Noncopyable_h + +#include "Compiler.h" + +#if COMPILER_SUPPORTS(CXX_DELETED_FUNCTIONS) + #define WTF_MAKE_NONCOPYABLE(ClassName) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") \ + _Pragma("clang diagnostic ignored \"-Wc++0x-extensions\"") \ + private: \ + ClassName(const ClassName&) = delete; \ + ClassName& operator=(const ClassName&) = delete; \ + _Pragma("clang diagnostic pop") +#else + #define WTF_MAKE_NONCOPYABLE(ClassName) \ + private: \ + ClassName(const ClassName&); \ + ClassName& operator=(const ClassName&) +#endif + +#endif // WTF_Noncopyable_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/NotFound.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/NotFound.h new file mode 100644 index 000000000..4263bceca --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/NotFound.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 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 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 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 NotFound_h +#define NotFound_h + +namespace WTF { + + const size_t notFound = static_cast(-1); + +} // namespace WTF + +using WTF::notFound; + +#endif // NotFound_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/NullPtr.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/NullPtr.h new file mode 100644 index 000000000..b65f8fab5 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/NullPtr.h @@ -0,0 +1,48 @@ +/* + +Copyright (C) 2010 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 INC. 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 INC. 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 NullPtr_h +#define NullPtr_h + +// For compilers and standard libraries that do not yet include it, this adds the +// nullptr_t type and nullptr object. They are defined in the same namespaces they +// would be in compiler and library that had the support. + +#if COMPILER_SUPPORTS(CXX_NULLPTR) + +#include + +#else + +namespace std { + class nullptr_t { }; +} + +extern std::nullptr_t nullptr; + +#endif + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/NumberObject.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/NumberObject.h new file mode 100644 index 000000000..07334722b --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/NumberObject.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef NumberObject_h +#define NumberObject_h + +#include "JSWrapperObject.h" + +namespace JSC { + + class NumberObject : public JSWrapperObject { + protected: + NumberObject(JSGlobalData&, Structure*); + void finishCreation(JSGlobalData&); + + public: + typedef JSWrapperObject Base; + + static NumberObject* create(JSGlobalData& globalData, Structure* structure) + { + NumberObject* number = new (NotNull, allocateCell(globalData.heap)) NumberObject(globalData, structure); + number->finishCreation(globalData); + return number; + } + + static const ClassInfo s_info; + + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + { + return Structure::create(globalData, globalObject, prototype, TypeInfo(NumberObjectType, StructureFlags), &s_info); + } + }; + + NumberObject* constructNumber(ExecState*, JSGlobalObject*, JSValue); + +} // namespace JSC + +#endif // NumberObject_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/NumberPrototype.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/NumberPrototype.h new file mode 100644 index 000000000..d63cc3a6f --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/NumberPrototype.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2008, 2011 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef NumberPrototype_h +#define NumberPrototype_h + +#include "NumberObject.h" + +namespace JSC { + + class NumberPrototype : public NumberObject { + public: + typedef NumberObject Base; + + static NumberPrototype* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure) + { + NumberPrototype* prototype = new (NotNull, allocateCell(*exec->heap())) NumberPrototype(exec, structure); + prototype->finishCreation(exec, globalObject); + return prototype; + } + + static const ClassInfo s_info; + + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + { + return Structure::create(globalData, globalObject, prototype, TypeInfo(NumberObjectType, StructureFlags), &s_info); + } + + protected: + void finishCreation(ExecState*, JSGlobalObject*); + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | NumberObject::StructureFlags; + + private: + NumberPrototype(ExecState*, Structure*); + static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&); + static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); + }; + +} // namespace JSC + +#endif // NumberPrototype_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/NumericStrings.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/NumericStrings.h new file mode 100644 index 000000000..d65f14265 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/NumericStrings.h @@ -0,0 +1,98 @@ +/* + * 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 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 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 NumericStrings_h +#define NumericStrings_h + +#include "UString.h" +#include +#include + +namespace JSC { + + class NumericStrings { + public: + UString add(double d) + { + CacheEntry& entry = lookup(d); + if (d == entry.key && !entry.value.isNull()) + return entry.value; + entry.key = d; + entry.value = UString::number(d); + return entry.value; + } + + UString add(int i) + { + if (static_cast(i) < cacheSize) + return lookupSmallString(static_cast(i)); + CacheEntry& entry = lookup(i); + if (i == entry.key && !entry.value.isNull()) + return entry.value; + entry.key = i; + entry.value = UString::number(i); + return entry.value; + } + + UString add(unsigned i) + { + if (i < cacheSize) + return lookupSmallString(static_cast(i)); + CacheEntry& entry = lookup(i); + if (i == entry.key && !entry.value.isNull()) + return entry.value; + entry.key = i; + entry.value = UString::number(i); + return entry.value; + } + private: + static const size_t cacheSize = 64; + + template + struct CacheEntry { + T key; + UString value; + }; + + CacheEntry& lookup(double d) { return doubleCache[WTF::FloatHash::hash(d) & (cacheSize - 1)]; } + CacheEntry& lookup(int i) { return intCache[WTF::IntHash::hash(i) & (cacheSize - 1)]; } + CacheEntry& lookup(unsigned i) { return unsignedCache[WTF::IntHash::hash(i) & (cacheSize - 1)]; } + const UString& lookupSmallString(unsigned i) + { + ASSERT(i < cacheSize); + if (smallIntCache[i].isNull()) + smallIntCache[i] = UString::number(i); + return smallIntCache[i]; + } + + FixedArray, cacheSize> doubleCache; + FixedArray, cacheSize> intCache; + FixedArray, cacheSize> unsignedCache; + FixedArray smallIntCache; + }; + +} // namespace JSC + +#endif // NumericStrings_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/OSAllocator.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/OSAllocator.h new file mode 100644 index 000000000..be791a8c8 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/OSAllocator.h @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2010 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 INC. 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 INC. 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 OSAllocator_h +#define OSAllocator_h + +#include +#include +#include + +namespace WTF { + +class OSAllocator { +public: + enum Usage { + UnknownUsage = -1, + FastMallocPages = VM_TAG_FOR_TCMALLOC_MEMORY, + JSGCHeapPages = VM_TAG_FOR_COLLECTOR_MEMORY, + JSVMStackPages = VM_TAG_FOR_REGISTERFILE_MEMORY, + JSJITCodePages = VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY, + }; + + // These methods are symmetric; reserveUncommitted allocates VM in an uncommitted state, + // releaseDecommitted should be called on a region of VM allocated by a single reservation, + // the memory must all currently be in a decommitted state. + static void* reserveUncommitted(size_t, Usage = UnknownUsage, bool writable = true, bool executable = false, bool includesGuardPages = false); + WTF_EXPORT_PRIVATE static void releaseDecommitted(void*, size_t); + + // These methods are symmetric; they commit or decommit a region of VM (uncommitted VM should + // never be accessed, since the OS may not have attached physical memory for these regions). + // Clients should only call commit on uncommitted regions and decommit on committed regions. + static void commit(void*, size_t, bool writable, bool executable); + static void decommit(void*, size_t); + + // These methods are symmetric; reserveAndCommit allocates VM in an committed state, + // decommitAndRelease should be called on a region of VM allocated by a single reservation, + // the memory must all currently be in a committed state. + WTF_EXPORT_PRIVATE static void* reserveAndCommit(size_t, Usage = UnknownUsage, bool writable = true, bool executable = false, bool includesGuardPages = false); + static void decommitAndRelease(void* base, size_t size); + + // These methods are akin to reserveAndCommit/decommitAndRelease, above - however rather than + // committing/decommitting the entire region additional parameters allow a subregion to be + // specified. + static void* reserveAndCommit(size_t reserveSize, size_t commitSize, Usage = UnknownUsage, bool writable = true, bool executable = false); + static void decommitAndRelease(void* releaseBase, size_t releaseSize, void* decommitBase, size_t decommitSize); +}; + +inline void* OSAllocator::reserveAndCommit(size_t reserveSize, size_t commitSize, Usage usage, bool writable, bool executable) +{ + void* base = reserveUncommitted(reserveSize, usage, writable, executable); + commit(base, commitSize, writable, executable); + return base; +} + +inline void OSAllocator::decommitAndRelease(void* releaseBase, size_t releaseSize, void* decommitBase, size_t decommitSize) +{ + ASSERT(decommitBase >= releaseBase && (static_cast(decommitBase) + decommitSize) <= (static_cast(releaseBase) + releaseSize)); +#if OS(WINCE) + // On most platforms we can actually skip this final decommit; releasing the VM will + // implicitly decommit any physical memory in the region. This is not true on WINCE. + decommit(decommitBase, decommitSize); +#else + UNUSED_PARAM(decommitBase); + UNUSED_PARAM(decommitSize); +#endif + releaseDecommitted(releaseBase, releaseSize); +} + +inline void OSAllocator::decommitAndRelease(void* base, size_t size) +{ + decommitAndRelease(base, size, base, size); +} + +} // namespace WTF + +using WTF::OSAllocator; + +#endif // OSAllocator_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ObjectPrototype.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ObjectPrototype.h new file mode 100644 index 000000000..4c49e97a7 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ObjectPrototype.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2008, 2011 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef ObjectPrototype_h +#define ObjectPrototype_h + +#include "JSObject.h" + +namespace JSC { + + class ObjectPrototype : public JSNonFinalObject { + public: + typedef JSNonFinalObject Base; + + static ObjectPrototype* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure) + { + ObjectPrototype* prototype = new (NotNull, allocateCell(*exec->heap())) ObjectPrototype(exec, structure); + prototype->finishCreation(exec->globalData(), globalObject); + return prototype; + } + + static const ClassInfo s_info; + + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + { + return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); + } + + protected: + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | JSNonFinalObject::StructureFlags; + + void finishCreation(JSGlobalData&, JSGlobalObject*); + + private: + ObjectPrototype(ExecState*, Structure*); + static void put(JSCell*, ExecState*, const Identifier&, JSValue, PutPropertySlot&); + + static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&); + static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&); + static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); + + bool m_hasNoPropertiesWithUInt32Names; + }; + + JS_EXPORT_PRIVATE EncodedJSValue JSC_HOST_CALL objectProtoFuncToString(ExecState*); + +} // namespace JSC + +#endif // ObjectPrototype_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/OpaqueJSString.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/OpaqueJSString.h new file mode 100644 index 000000000..1c63150cf --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/OpaqueJSString.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 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. + */ + +#ifndef OpaqueJSString_h +#define OpaqueJSString_h + +#include +#include + +namespace JSC { + class Identifier; + class JSGlobalData; +} + +struct OpaqueJSString : public ThreadSafeRefCounted { + + static PassRefPtr create() // null + { + return adoptRef(new OpaqueJSString); + } + + static PassRefPtr create(const UChar* characters, unsigned length) + { + return adoptRef(new OpaqueJSString(characters, length)); + } + + JS_EXPORT_PRIVATE static PassRefPtr create(const JSC::UString&); + + UChar* characters() { return this ? m_characters : 0; } + unsigned length() { return this ? m_length : 0; } + + JSC::UString ustring() const; + JSC::Identifier identifier(JSC::JSGlobalData*) const; + +private: + friend class WTF::ThreadSafeRefCounted; + + OpaqueJSString() + : m_characters(0) + , m_length(0) + { + } + + OpaqueJSString(const UChar* characters, unsigned length) + : m_length(length) + { + m_characters = new UChar[length]; + memcpy(m_characters, characters, length * sizeof(UChar)); + } + + ~OpaqueJSString() + { + delete[] m_characters; + } + + UChar* m_characters; + unsigned m_length; +}; + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Opcode.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Opcode.h new file mode 100644 index 000000000..0f94176b8 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Opcode.h @@ -0,0 +1,278 @@ +/* + * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2008 Cameron Zwarich + * + * 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 Opcode_h +#define Opcode_h + +#include +#include + +#include + +namespace JSC { + + #define FOR_EACH_OPCODE_ID(macro) \ + macro(op_enter, 1) \ + macro(op_create_activation, 2) \ + macro(op_init_lazy_reg, 2) \ + macro(op_create_arguments, 2) \ + macro(op_create_this, 3) \ + macro(op_get_callee, 2) \ + macro(op_convert_this, 2) \ + \ + macro(op_new_object, 2) \ + macro(op_new_array, 4) \ + macro(op_new_array_buffer, 4) \ + macro(op_new_regexp, 3) \ + macro(op_mov, 3) \ + \ + macro(op_not, 3) \ + macro(op_eq, 4) \ + macro(op_eq_null, 3) \ + macro(op_neq, 4) \ + macro(op_neq_null, 3) \ + macro(op_stricteq, 4) \ + macro(op_nstricteq, 4) \ + macro(op_less, 4) \ + macro(op_lesseq, 4) \ + macro(op_greater, 4) \ + macro(op_greatereq, 4) \ + \ + macro(op_pre_inc, 2) \ + macro(op_pre_dec, 2) \ + macro(op_post_inc, 3) \ + macro(op_post_dec, 3) \ + macro(op_to_jsnumber, 3) \ + macro(op_negate, 3) \ + macro(op_add, 5) \ + macro(op_mul, 5) \ + macro(op_div, 5) \ + macro(op_mod, 4) \ + macro(op_sub, 5) \ + \ + macro(op_lshift, 4) \ + macro(op_rshift, 4) \ + macro(op_urshift, 4) \ + macro(op_bitand, 5) \ + macro(op_bitxor, 5) \ + macro(op_bitor, 5) \ + macro(op_bitnot, 3) \ + \ + macro(op_check_has_instance, 2) \ + macro(op_instanceof, 5) \ + macro(op_typeof, 3) \ + macro(op_is_undefined, 3) \ + macro(op_is_boolean, 3) \ + macro(op_is_number, 3) \ + macro(op_is_string, 3) \ + macro(op_is_object, 3) \ + macro(op_is_function, 3) \ + macro(op_in, 4) \ + \ + macro(op_resolve, 4) /* has value profiling */ \ + macro(op_resolve_skip, 5) /* has value profiling */ \ + macro(op_resolve_global, 6) /* has value profiling */ \ + macro(op_resolve_global_dynamic, 7) /* has value profiling */ \ + macro(op_get_scoped_var, 5) /* has value profiling */ \ + macro(op_put_scoped_var, 4) \ + macro(op_get_global_var, 4) /* has value profiling */ \ + macro(op_put_global_var, 3) \ + macro(op_resolve_base, 5) /* has value profiling */ \ + macro(op_ensure_property_exists, 3) \ + macro(op_resolve_with_base, 5) /* has value profiling */ \ + macro(op_resolve_with_this, 5) /* has value profiling */ \ + macro(op_get_by_id, 9) /* has value profiling */ \ + macro(op_get_by_id_self, 9) /* has value profiling */ \ + macro(op_get_by_id_proto, 9) /* has value profiling */ \ + macro(op_get_by_id_chain, 9) /* has value profiling */ \ + macro(op_get_by_id_getter_self, 9) /* has value profiling */ \ + macro(op_get_by_id_getter_proto, 9) /* has value profiling */ \ + macro(op_get_by_id_getter_chain, 9) /* has value profiling */ \ + macro(op_get_by_id_custom_self, 9) /* has value profiling */ \ + macro(op_get_by_id_custom_proto, 9) /* has value profiling */ \ + macro(op_get_by_id_custom_chain, 9) /* has value profiling */ \ + macro(op_get_by_id_generic, 9) /* has value profiling */ \ + macro(op_get_array_length, 9) /* has value profiling */ \ + macro(op_get_string_length, 9) /* has value profiling */ \ + macro(op_get_arguments_length, 4) \ + macro(op_put_by_id, 9) \ + macro(op_put_by_id_transition, 9) \ + macro(op_put_by_id_replace, 9) \ + macro(op_put_by_id_generic, 9) \ + macro(op_del_by_id, 4) \ + macro(op_get_by_val, 5) /* has value profiling */ \ + macro(op_get_argument_by_val, 4) \ + macro(op_get_by_pname, 7) \ + macro(op_put_by_val, 4) \ + macro(op_del_by_val, 4) \ + macro(op_put_by_index, 4) \ + macro(op_put_getter, 4) \ + macro(op_put_setter, 4) \ + \ + macro(op_jmp, 2) \ + macro(op_jtrue, 3) \ + macro(op_jfalse, 3) \ + macro(op_jeq_null, 3) \ + macro(op_jneq_null, 3) \ + macro(op_jneq_ptr, 4) \ + macro(op_jless, 4) \ + macro(op_jlesseq, 4) \ + macro(op_jgreater, 4) \ + macro(op_jgreatereq, 4) \ + macro(op_jnless, 4) \ + macro(op_jnlesseq, 4) \ + macro(op_jngreater, 4) \ + macro(op_jngreatereq, 4) \ + macro(op_jmp_scopes, 3) \ + macro(op_loop, 2) \ + macro(op_loop_if_true, 3) \ + macro(op_loop_if_false, 3) \ + macro(op_loop_if_less, 4) \ + macro(op_loop_if_lesseq, 4) \ + macro(op_loop_if_greater, 4) \ + macro(op_loop_if_greatereq, 4) \ + macro(op_loop_hint, 1) \ + macro(op_switch_imm, 4) \ + macro(op_switch_char, 4) \ + macro(op_switch_string, 4) \ + \ + macro(op_new_func, 4) \ + macro(op_new_func_exp, 3) \ + macro(op_call, 6) \ + macro(op_call_eval, 6) \ + macro(op_call_varargs, 5) \ + macro(op_tear_off_activation, 3) \ + macro(op_tear_off_arguments, 2) \ + macro(op_ret, 2) \ + macro(op_call_put_result, 3) /* has value profiling */ \ + macro(op_ret_object_or_this, 3) \ + macro(op_method_check, 1) \ + \ + macro(op_construct, 6) \ + macro(op_strcat, 4) \ + macro(op_to_primitive, 3) \ + \ + macro(op_get_pnames, 6) \ + macro(op_next_pname, 7) \ + \ + macro(op_push_scope, 2) \ + macro(op_pop_scope, 1) \ + macro(op_push_new_scope, 4) \ + \ + macro(op_catch, 2) \ + macro(op_throw, 2) \ + macro(op_throw_reference_error, 2) \ + \ + macro(op_jsr, 3) \ + macro(op_sret, 2) \ + \ + macro(op_debug, 4) \ + macro(op_profile_will_call, 2) \ + macro(op_profile_did_call, 2) \ + \ + macro(op_end, 2) // end must be the last opcode in the list + + #define OPCODE_ID_ENUM(opcode, length) opcode, + typedef enum { FOR_EACH_OPCODE_ID(OPCODE_ID_ENUM) } OpcodeID; + #undef OPCODE_ID_ENUM + + const int numOpcodeIDs = op_end + 1; + + #define OPCODE_ID_LENGTHS(id, length) const int id##_length = length; + FOR_EACH_OPCODE_ID(OPCODE_ID_LENGTHS); + #undef OPCODE_ID_LENGTHS + + #define OPCODE_LENGTH(opcode) opcode##_length + + #define OPCODE_ID_LENGTH_MAP(opcode, length) length, + const int opcodeLengths[numOpcodeIDs] = { FOR_EACH_OPCODE_ID(OPCODE_ID_LENGTH_MAP) }; + #undef OPCODE_ID_LENGTH_MAP + + #define VERIFY_OPCODE_ID(id, size) COMPILE_ASSERT(id <= op_end, ASSERT_THAT_JS_OPCODE_IDS_ARE_VALID); + FOR_EACH_OPCODE_ID(VERIFY_OPCODE_ID); + #undef VERIFY_OPCODE_ID + +#if ENABLE(COMPUTED_GOTO_INTERPRETER) +#if COMPILER(RVCT) || COMPILER(INTEL) + typedef void* Opcode; +#else + typedef const void* Opcode; +#endif +#else + typedef OpcodeID Opcode; +#endif + +#if !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING) || ENABLE(CODEBLOCK_SAMPLING) || ENABLE(OPCODE_STATS) + +#define PADDING_STRING " " +#define PADDING_STRING_LENGTH static_cast(strlen(PADDING_STRING)) + + extern const char* const opcodeNames[]; + + inline const char* padOpcodeName(OpcodeID op, unsigned width) + { + unsigned pad = width - strlen(opcodeNames[op]); + pad = std::min(pad, PADDING_STRING_LENGTH); + return PADDING_STRING + PADDING_STRING_LENGTH - pad; + } + +#undef PADDING_STRING_LENGTH +#undef PADDING_STRING + +#endif + +#if ENABLE(OPCODE_STATS) + + struct OpcodeStats { + OpcodeStats(); + ~OpcodeStats(); + static long long opcodeCounts[numOpcodeIDs]; + static long long opcodePairCounts[numOpcodeIDs][numOpcodeIDs]; + static int lastOpcode; + + static void recordInstruction(int opcode); + static void resetLastInstruction(); + }; + +#endif + + inline size_t opcodeLength(OpcodeID opcode) + { + switch (opcode) { +#define OPCODE_ID_LENGTHS(id, length) case id: return OPCODE_LENGTH(id); + FOR_EACH_OPCODE_ID(OPCODE_ID_LENGTHS) +#undef OPCODE_ID_LENGTHS + } + ASSERT_NOT_REACHED(); + return 0; + } + +} // namespace JSC + +#endif // Opcode_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Operations.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Operations.h new file mode 100644 index 000000000..945283899 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Operations.h @@ -0,0 +1,379 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2002, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef Operations_h +#define Operations_h + +#include "ExceptionHelpers.h" +#include "Interpreter.h" +#include "JSString.h" +#include "JSValueInlineMethods.h" + +namespace JSC { + + NEVER_INLINE JSValue jsAddSlowCase(CallFrame*, JSValue, JSValue); + JSValue jsTypeStringForValue(CallFrame*, JSValue); + bool jsIsObjectType(JSValue); + bool jsIsFunctionType(JSValue); + + ALWAYS_INLINE JSValue jsString(ExecState* exec, JSString* s1, JSString* s2) + { + JSGlobalData& globalData = exec->globalData(); + + unsigned length1 = s1->length(); + if (!length1) + return s2; + unsigned length2 = s2->length(); + if (!length2) + return s1; + if ((length1 + length2) < length1) + return throwOutOfMemoryError(exec); + + return JSString::create(globalData, s1, s2); + } + + ALWAYS_INLINE JSValue jsString(ExecState* exec, const UString& u1, const UString& u2, const UString& u3) + { + JSGlobalData* globalData = &exec->globalData(); + + unsigned length1 = u1.length(); + unsigned length2 = u2.length(); + unsigned length3 = u3.length(); + if (!length1) + return jsString(exec, jsString(globalData, u2), jsString(globalData, u3)); + if (!length2) + return jsString(exec, jsString(globalData, u1), jsString(globalData, u3)); + if (!length3) + return jsString(exec, jsString(globalData, u1), jsString(globalData, u2)); + + if ((length1 + length2) < length1) + return throwOutOfMemoryError(exec); + if ((length1 + length2 + length3) < length3) + return throwOutOfMemoryError(exec); + + return JSString::create(exec->globalData(), jsString(globalData, u1), jsString(globalData, u2), jsString(globalData, u3)); + } + + ALWAYS_INLINE JSValue jsString(ExecState* exec, Register* strings, unsigned count) + { + JSGlobalData* globalData = &exec->globalData(); + JSString::RopeBuilder ropeBuilder(*globalData); + + unsigned oldLength = 0; + + for (unsigned i = 0; i < count; ++i) { + JSValue v = strings[i].jsValue(); + ropeBuilder.append(v.toString(exec)); + + if (ropeBuilder.length() < oldLength) // True for overflow + return throwOutOfMemoryError(exec); + } + + return ropeBuilder.release(); + } + + ALWAYS_INLINE JSValue jsStringFromArguments(ExecState* exec, JSValue thisValue) + { + JSGlobalData* globalData = &exec->globalData(); + JSString::RopeBuilder ropeBuilder(*globalData); + ropeBuilder.append(thisValue.toString(exec)); + + unsigned oldLength = 0; + + for (unsigned i = 0; i < exec->argumentCount(); ++i) { + JSValue v = exec->argument(i); + ropeBuilder.append(v.toString(exec)); + + if (ropeBuilder.length() < oldLength) // True for overflow + return throwOutOfMemoryError(exec); + } + + return ropeBuilder.release(); + } + + // ECMA 11.9.3 + inline bool JSValue::equal(ExecState* exec, JSValue v1, JSValue v2) + { + if (v1.isInt32() && v2.isInt32()) + return v1 == v2; + + return equalSlowCase(exec, v1, v2); + } + + ALWAYS_INLINE bool JSValue::equalSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2) + { + do { + if (v1.isNumber() && v2.isNumber()) + return v1.asNumber() == v2.asNumber(); + + bool s1 = v1.isString(); + bool s2 = v2.isString(); + if (s1 && s2) + return asString(v1)->value(exec) == asString(v2)->value(exec); + + if (v1.isUndefinedOrNull()) { + if (v2.isUndefinedOrNull()) + return true; + if (!v2.isCell()) + return false; + return v2.asCell()->structure()->typeInfo().masqueradesAsUndefined(); + } + + if (v2.isUndefinedOrNull()) { + if (!v1.isCell()) + return false; + return v1.asCell()->structure()->typeInfo().masqueradesAsUndefined(); + } + + if (v1.isObject()) { + if (v2.isObject()) + return v1 == v2; + JSValue p1 = v1.toPrimitive(exec); + if (exec->hadException()) + return false; + v1 = p1; + if (v1.isInt32() && v2.isInt32()) + return v1 == v2; + continue; + } + + if (v2.isObject()) { + JSValue p2 = v2.toPrimitive(exec); + if (exec->hadException()) + return false; + v2 = p2; + if (v1.isInt32() && v2.isInt32()) + return v1 == v2; + continue; + } + + if (s1 || s2) { + double d1 = v1.toNumber(exec); + double d2 = v2.toNumber(exec); + return d1 == d2; + } + + if (v1.isBoolean()) { + if (v2.isNumber()) + return static_cast(v1.asBoolean()) == v2.asNumber(); + } else if (v2.isBoolean()) { + if (v1.isNumber()) + return v1.asNumber() == static_cast(v2.asBoolean()); + } + + return v1 == v2; + } while (true); + } + + // ECMA 11.9.3 + ALWAYS_INLINE bool JSValue::strictEqualSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2) + { + ASSERT(v1.isCell() && v2.isCell()); + + if (v1.asCell()->isString() && v2.asCell()->isString()) + return asString(v1)->value(exec) == asString(v2)->value(exec); + + return v1 == v2; + } + + inline bool JSValue::strictEqual(ExecState* exec, JSValue v1, JSValue v2) + { + if (v1.isInt32() && v2.isInt32()) + return v1 == v2; + + if (v1.isNumber() && v2.isNumber()) + return v1.asNumber() == v2.asNumber(); + + if (!v1.isCell() || !v2.isCell()) + return v1 == v2; + + return strictEqualSlowCaseInline(exec, v1, v2); + } + + // See ES5 11.8.1/11.8.2/11.8.5 for definition of leftFirst, this value ensures correct + // evaluation ordering for argument conversions for '<' and '>'. For '<' pass the value + // true, for leftFirst, for '>' pass the value false (and reverse operand order). + template + ALWAYS_INLINE bool jsLess(CallFrame* callFrame, JSValue v1, JSValue v2) + { + if (v1.isInt32() && v2.isInt32()) + return v1.asInt32() < v2.asInt32(); + + if (v1.isNumber() && v2.isNumber()) + return v1.asNumber() < v2.asNumber(); + + if (isJSString(v1) && isJSString(v2)) + return asString(v1)->value(callFrame) < asString(v2)->value(callFrame); + + double n1; + double n2; + JSValue p1; + JSValue p2; + bool wasNotString1; + bool wasNotString2; + if (leftFirst) { + wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1); + wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2); + } else { + wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2); + wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1); + } + + if (wasNotString1 | wasNotString2) + return n1 < n2; + return asString(p1)->value(callFrame) < asString(p2)->value(callFrame); + } + + // See ES5 11.8.3/11.8.4/11.8.5 for definition of leftFirst, this value ensures correct + // evaluation ordering for argument conversions for '<=' and '=>'. For '<=' pass the + // value true, for leftFirst, for '=>' pass the value false (and reverse operand order). + template + ALWAYS_INLINE bool jsLessEq(CallFrame* callFrame, JSValue v1, JSValue v2) + { + if (v1.isInt32() && v2.isInt32()) + return v1.asInt32() <= v2.asInt32(); + + if (v1.isNumber() && v2.isNumber()) + return v1.asNumber() <= v2.asNumber(); + + if (isJSString(v1) && isJSString(v2)) + return !(asString(v2)->value(callFrame) < asString(v1)->value(callFrame)); + + double n1; + double n2; + JSValue p1; + JSValue p2; + bool wasNotString1; + bool wasNotString2; + if (leftFirst) { + wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1); + wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2); + } else { + wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2); + wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1); + } + + if (wasNotString1 | wasNotString2) + return n1 <= n2; + return !(asString(p2)->value(callFrame) < asString(p1)->value(callFrame)); + } + + // Fast-path choices here are based on frequency data from SunSpider: + // Add case: + // --------------------------- + // 5626160 Add case: 3 3 (of these, 3637690 are for immediate values) + // 247412 Add case: 5 5 + // 20900 Add case: 5 6 + // 13962 Add case: 5 3 + // 4000 Add case: 3 5 + + ALWAYS_INLINE JSValue jsAdd(CallFrame* callFrame, JSValue v1, JSValue v2) + { + if (v1.isNumber() && v2.isNumber()) + return jsNumber(v1.asNumber() + v2.asNumber()); + + if (v1.isString() && !v2.isObject()) + return jsString(callFrame, asString(v1), v2.toString(callFrame)); + + // All other cases are pretty uncommon + return jsAddSlowCase(callFrame, v1, v2); + } + + inline size_t normalizePrototypeChain(CallFrame* callFrame, JSValue base, JSValue slotBase, const Identifier& propertyName, size_t& slotOffset) + { + JSCell* cell = base.asCell(); + size_t count = 0; + + while (slotBase != cell) { + JSValue v = cell->structure()->prototypeForLookup(callFrame); + + // If we didn't find slotBase in base's prototype chain, then base + // must be a proxy for another object. + + if (v.isNull()) + return 0; + + cell = v.asCell(); + + // Since we're accessing a prototype in a loop, it's a good bet that it + // should not be treated as a dictionary. + if (cell->structure()->isDictionary()) { + asObject(cell)->flattenDictionaryObject(callFrame->globalData()); + if (slotBase == cell) + slotOffset = cell->structure()->get(callFrame->globalData(), propertyName); + } + + ++count; + } + + ASSERT(count); + return count; + } + + inline size_t normalizePrototypeChain(CallFrame* callFrame, JSCell* base) + { + size_t count = 0; + while (1) { + JSValue v = base->structure()->prototypeForLookup(callFrame); + if (v.isNull()) + return count; + + base = v.asCell(); + + // Since we're accessing a prototype in a loop, it's a good bet that it + // should not be treated as a dictionary. + if (base->structure()->isDictionary()) + asObject(base)->flattenDictionaryObject(callFrame->globalData()); + + ++count; + } + } + + ALWAYS_INLINE JSValue resolveBase(CallFrame* callFrame, Identifier& property, ScopeChainNode* scopeChain, bool isStrictPut) + { + ScopeChainIterator iter = scopeChain->begin(); + ScopeChainIterator next = iter; + ++next; + ScopeChainIterator end = scopeChain->end(); + ASSERT(iter != end); + + PropertySlot slot; + JSObject* base; + while (true) { + base = iter->get(); + if (next == end) { + if (isStrictPut && !base->getPropertySlot(callFrame, property, slot)) + return JSValue(); + return base; + } + if (base->getPropertySlot(callFrame, property, slot)) + return base; + + iter = next; + ++next; + } + + ASSERT_NOT_REACHED(); + return JSValue(); + } +} // namespace JSC + +#endif // Operations_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Options.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Options.h new file mode 100644 index 000000000..feebd37bb --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Options.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2011 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 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 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 Options_h +#define Options_h + +#include + +namespace JSC { namespace Options { + +extern unsigned maximumOptimizationCandidateInstructionCount; + +extern unsigned maximumFunctionForCallInlineCandidateInstructionCount; +extern unsigned maximumFunctionForConstructInlineCandidateInstructionCount; + +extern unsigned maximumInliningDepth; // Depth of inline stack, so 1 = no inlining, 2 = one level, etc. + +extern int32_t executionCounterValueForOptimizeAfterWarmUp; +extern int32_t executionCounterValueForOptimizeAfterLongWarmUp; +extern int32_t executionCounterValueForDontOptimizeAnytimeSoon; +extern int32_t executionCounterValueForOptimizeSoon; +extern int32_t executionCounterValueForOptimizeNextInvocation; + +extern int32_t executionCounterIncrementForLoop; +extern int32_t executionCounterIncrementForReturn; + +extern unsigned desiredSpeculativeSuccessFailRatio; + +extern double likelyToTakeSlowCaseThreshold; +extern double couldTakeSlowCaseThreshold; +extern unsigned likelyToTakeSlowCaseMinimumCount; +extern unsigned couldTakeSlowCaseMinimumCount; + +extern double osrExitProminenceForFrequentExitSite; + +extern unsigned largeFailCountThresholdBase; +extern unsigned largeFailCountThresholdBaseForLoop; + +extern unsigned reoptimizationRetryCounterMax; +extern unsigned reoptimizationRetryCounterStep; + +extern unsigned minimumOptimizationDelay; +extern unsigned maximumOptimizationDelay; +extern double desiredProfileLivenessRate; +extern double desiredProfileFullnessRate; + +extern double doubleVoteRatioForDoubleFormat; + +extern unsigned minimumNumberOfScansBetweenRebalance; +extern unsigned gcMarkStackSegmentSize; +extern unsigned minimumNumberOfCellsToKeep; +extern unsigned maximumNumberOfSharedSegments; +extern unsigned sharedStackWakeupThreshold; +JS_EXPORTDATA extern unsigned numberOfGCMarkers; +JS_EXPORTDATA extern unsigned opaqueRootMergeThreshold; + +void initializeOptions(); + +} } // namespace JSC::Options + +#endif // Options_h + diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/OwnArrayPtr.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/OwnArrayPtr.h new file mode 100644 index 000000000..0fc8e71b3 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/OwnArrayPtr.h @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2006, 2010 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WTF_OwnArrayPtr_h +#define WTF_OwnArrayPtr_h + +#include "Assertions.h" +#include "Noncopyable.h" +#include "NullPtr.h" +#include "PassOwnArrayPtr.h" +#include + +namespace WTF { + +template class PassOwnArrayPtr; +template PassOwnArrayPtr adoptArrayPtr(T*); + +template class OwnArrayPtr { +public: + typedef T* PtrType; + + OwnArrayPtr() : m_ptr(0) { } + + // See comment in PassOwnArrayPtr.h for why this takes a const reference. + template OwnArrayPtr(const PassOwnArrayPtr& o); + + // This copy constructor is used implicitly by gcc when it generates + // transients for assigning a PassOwnArrayPtr object to a stack-allocated + // OwnArrayPtr object. It should never be called explicitly and gcc + // should optimize away the constructor when generating code. + OwnArrayPtr(const OwnArrayPtr&); + + ~OwnArrayPtr() { deleteOwnedArrayPtr(m_ptr); } + + PtrType get() const { return m_ptr; } + + void clear(); + PassOwnArrayPtr release(); + PtrType leakPtr() WARN_UNUSED_RETURN; + + T& operator*() const { ASSERT(m_ptr); return *m_ptr; } + PtrType operator->() const { ASSERT(m_ptr); return m_ptr; } + + T& operator[](std::ptrdiff_t i) const { ASSERT(m_ptr); ASSERT(i >= 0); return m_ptr[i]; } + + bool operator!() const { return !m_ptr; } + + // This conversion operator allows implicit conversion to bool but not to other integer types. + typedef T* OwnArrayPtr::*UnspecifiedBoolType; + operator UnspecifiedBoolType() const { return m_ptr ? &OwnArrayPtr::m_ptr : 0; } + + OwnArrayPtr& operator=(const PassOwnArrayPtr&); + OwnArrayPtr& operator=(std::nullptr_t) { clear(); return *this; } + template OwnArrayPtr& operator=(const PassOwnArrayPtr&); + + void swap(OwnArrayPtr& o) { std::swap(m_ptr, o.m_ptr); } + +private: + PtrType m_ptr; +}; + +template template inline OwnArrayPtr::OwnArrayPtr(const PassOwnArrayPtr& o) + : m_ptr(o.leakPtr()) +{ +} + +template inline void OwnArrayPtr::clear() +{ + PtrType ptr = m_ptr; + m_ptr = 0; + deleteOwnedArrayPtr(ptr); +} + +template inline PassOwnArrayPtr OwnArrayPtr::release() +{ + PtrType ptr = m_ptr; + m_ptr = 0; + return adoptArrayPtr(ptr); +} + +template inline typename OwnArrayPtr::PtrType OwnArrayPtr::leakPtr() +{ + PtrType ptr = m_ptr; + m_ptr = 0; + return ptr; +} + +template inline OwnArrayPtr& OwnArrayPtr::operator=(const PassOwnArrayPtr& o) +{ + PtrType ptr = m_ptr; + m_ptr = o.leakPtr(); + ASSERT(!ptr || m_ptr != ptr); + deleteOwnedArrayPtr(ptr); + return *this; +} + +template template inline OwnArrayPtr& OwnArrayPtr::operator=(const PassOwnArrayPtr& o) +{ + PtrType ptr = m_ptr; + m_ptr = o.leakPtr(); + ASSERT(!ptr || m_ptr != ptr); + deleteOwnedArrayPtr(ptr); + return *this; +} + +template inline void swap(OwnArrayPtr& a, OwnArrayPtr& b) +{ + a.swap(b); +} + +template inline bool operator==(const OwnArrayPtr& a, U* b) +{ + return a.get() == b; +} + +template inline bool operator==(T* a, const OwnArrayPtr& b) +{ + return a == b.get(); +} + +template inline bool operator!=(const OwnArrayPtr& a, U* b) +{ + return a.get() != b; +} + +template inline bool operator!=(T* a, const OwnArrayPtr& b) +{ + return a != b.get(); +} + +template inline T* getPtr(const OwnArrayPtr& p) +{ + return p.get(); +} + +} // namespace WTF + +using WTF::OwnArrayPtr; + +#endif // WTF_OwnArrayPtr_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/OwnPtr.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/OwnPtr.h new file mode 100644 index 000000000..097967964 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/OwnPtr.h @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WTF_OwnPtr_h +#define WTF_OwnPtr_h + +#include "Assertions.h" +#include "NullPtr.h" +#include "OwnPtrCommon.h" +#include "TypeTraits.h" +#include +#include + +namespace WTF { + + // Unlike most of our smart pointers, OwnPtr can take either the pointer type or the pointed-to type. + + template class PassOwnPtr; + template PassOwnPtr adoptPtr(T*); + + template class OwnPtr { + public: + typedef typename RemovePointer::Type ValueType; + typedef ValueType* PtrType; + + OwnPtr() : m_ptr(0) { } + OwnPtr(std::nullptr_t) : m_ptr(0) { } + + // See comment in PassOwnPtr.h for why this takes a const reference. + template OwnPtr(const PassOwnPtr& o); + + // This copy constructor is used implicitly by gcc when it generates + // transients for assigning a PassOwnPtr object to a stack-allocated + // OwnPtr object. It should never be called explicitly and gcc + // should optimize away the constructor when generating code. + OwnPtr(const OwnPtr&); + + ~OwnPtr() { deleteOwnedPtr(m_ptr); } + + PtrType get() const { return m_ptr; } + + void clear(); + PassOwnPtr release(); + PtrType leakPtr() WARN_UNUSED_RETURN; + + ValueType& operator*() const { ASSERT(m_ptr); return *m_ptr; } + PtrType operator->() const { ASSERT(m_ptr); return m_ptr; } + + bool operator!() const { return !m_ptr; } + + // This conversion operator allows implicit conversion to bool but not to other integer types. + typedef PtrType OwnPtr::*UnspecifiedBoolType; + operator UnspecifiedBoolType() const { return m_ptr ? &OwnPtr::m_ptr : 0; } + + OwnPtr& operator=(const PassOwnPtr&); + OwnPtr& operator=(std::nullptr_t) { clear(); return *this; } + template OwnPtr& operator=(const PassOwnPtr&); + + void swap(OwnPtr& o) { std::swap(m_ptr, o.m_ptr); } + + private: + OwnPtr& operator=(const OwnPtr&); + + // We should never have two OwnPtrs for the same underlying object (otherwise we'll get + // double-destruction), so these equality operators should never be needed. + template bool operator==(const OwnPtr&) { COMPILE_ASSERT(!sizeof(U*), OwnPtrs_should_never_be_equal); return false; } + template bool operator!=(const OwnPtr&) { COMPILE_ASSERT(!sizeof(U*), OwnPtrs_should_never_be_equal); return false; } + template bool operator==(const PassOwnPtr&) { COMPILE_ASSERT(!sizeof(U*), OwnPtrs_should_never_be_equal); return false; } + template bool operator!=(const PassOwnPtr&) { COMPILE_ASSERT(!sizeof(U*), OwnPtrs_should_never_be_equal); return false; } + + PtrType m_ptr; + }; + + template template inline OwnPtr::OwnPtr(const PassOwnPtr& o) + : m_ptr(o.leakPtr()) + { + } + + template inline void OwnPtr::clear() + { + PtrType ptr = m_ptr; + m_ptr = 0; + deleteOwnedPtr(ptr); + } + + template inline PassOwnPtr OwnPtr::release() + { + PtrType ptr = m_ptr; + m_ptr = 0; + return adoptPtr(ptr); + } + + template inline typename OwnPtr::PtrType OwnPtr::leakPtr() + { + PtrType ptr = m_ptr; + m_ptr = 0; + return ptr; + } + + template inline OwnPtr& OwnPtr::operator=(const PassOwnPtr& o) + { + PtrType ptr = m_ptr; + m_ptr = o.leakPtr(); + ASSERT(!ptr || m_ptr != ptr); + deleteOwnedPtr(ptr); + return *this; + } + + template template inline OwnPtr& OwnPtr::operator=(const PassOwnPtr& o) + { + PtrType ptr = m_ptr; + m_ptr = o.leakPtr(); + ASSERT(!ptr || m_ptr != ptr); + deleteOwnedPtr(ptr); + return *this; + } + + template inline void swap(OwnPtr& a, OwnPtr& b) + { + a.swap(b); + } + + template inline bool operator==(const OwnPtr& a, U* b) + { + return a.get() == b; + } + + template inline bool operator==(T* a, const OwnPtr& b) + { + return a == b.get(); + } + + template inline bool operator!=(const OwnPtr& a, U* b) + { + return a.get() != b; + } + + template inline bool operator!=(T* a, const OwnPtr& b) + { + return a != b.get(); + } + + template inline typename OwnPtr::PtrType getPtr(const OwnPtr& p) + { + return p.get(); + } + +} // namespace WTF + +using WTF::OwnPtr; + +#endif // WTF_OwnPtr_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/OwnPtrCommon.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/OwnPtrCommon.h new file mode 100644 index 000000000..b8b78a296 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/OwnPtrCommon.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2009 Torch Mobile, Inc. + * Copyright (C) 2010 Company 100 Inc. + * + * 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 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 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 WTF_OwnPtrCommon_h +#define WTF_OwnPtrCommon_h + +#if OS(WIN) +typedef struct HBITMAP__* HBITMAP; +typedef struct HBRUSH__* HBRUSH; +typedef struct HDC__* HDC; +typedef struct HFONT__* HFONT; +typedef struct HPALETTE__* HPALETTE; +typedef struct HPEN__* HPEN; +typedef struct HRGN__* HRGN; +#endif + +#if PLATFORM(EFL) +typedef struct _Ecore_Evas Ecore_Evas; +typedef struct _Ecore_Pipe Ecore_Pipe; +typedef struct _Eina_Module Eina_Module; +typedef struct _Evas_Object Evas_Object; +#endif + +namespace WTF { + + template inline void deleteOwnedPtr(T* ptr) + { + typedef char known[sizeof(T) ? 1 : -1]; + if (sizeof(known)) + delete ptr; + } + +#if OS(WIN) + void deleteOwnedPtr(HBITMAP); + void deleteOwnedPtr(HBRUSH); + void deleteOwnedPtr(HDC); + void deleteOwnedPtr(HFONT); + void deleteOwnedPtr(HPALETTE); + void deleteOwnedPtr(HPEN); + void deleteOwnedPtr(HRGN); +#endif + +#if PLATFORM(EFL) + void deleteOwnedPtr(Ecore_Evas*); + void deleteOwnedPtr(Ecore_Pipe*); + void deleteOwnedPtr(Eina_Module*); + void deleteOwnedPtr(Evas_Object*); +#endif + +} // namespace WTF + +#endif // WTF_OwnPtrCommon_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PageAllocation.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PageAllocation.h new file mode 100644 index 000000000..18d31880c --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PageAllocation.h @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2010 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 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 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 PageAllocation_h +#define PageAllocation_h + +#include +#include +#include +#include +#include +#include + +#if OS(DARWIN) +#include +#include +#endif + +#if OS(WINDOWS) +#include +#include +#endif + +#if HAVE(ERRNO_H) +#include +#endif + +#if HAVE(MMAP) +#include +#include +#endif + +namespace WTF { + +/* + PageAllocation + + The PageAllocation class provides a cross-platform memory allocation interface + with similar capabilities to posix mmap/munmap. Memory is allocated by calling + PageAllocation::allocate, and deallocated by calling deallocate on the + PageAllocation object. The PageAllocation holds the allocation's base pointer + and size. + + The allocate method is passed the size required (which must be a multiple of + the system page size, which can be accessed using PageAllocation::pageSize). + Callers may also optinally provide a flag indicating the usage (for use by + system memory usage tracking tools, where implemented), and boolean values + specifying the required protection (defaulting to writable, non-executable). +*/ + +class PageAllocation : private PageBlock { +public: + PageAllocation() + { + } + + using PageBlock::size; + using PageBlock::base; + +#ifndef __clang__ + using PageBlock::operator bool; +#else + // FIXME: This is a workaround for , wherein Clang incorrectly emits an access + // control warning when a client tries to use operator bool exposed above via "using PageBlock::operator bool". + operator bool() const { return PageBlock::operator bool(); } +#endif + + static PageAllocation allocate(size_t size, OSAllocator::Usage usage = OSAllocator::UnknownUsage, bool writable = true, bool executable = false) + { + ASSERT(isPageAligned(size)); + return PageAllocation(OSAllocator::reserveAndCommit(size, usage, writable, executable), size); + } + + void deallocate() + { + // Clear base & size before calling release; if this is *inside* allocation + // then we won't be able to clear then after deallocating the memory. + PageAllocation tmp; + std::swap(tmp, *this); + + ASSERT(tmp); + ASSERT(!*this); + + OSAllocator::decommitAndRelease(tmp.base(), tmp.size()); + } + +private: + PageAllocation(void* base, size_t size) + : PageBlock(base, size, false) + { + } +}; + +} // namespace WTF + +using WTF::PageAllocation; + +#endif // PageAllocation_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PageAllocationAligned.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PageAllocationAligned.h new file mode 100644 index 000000000..c018dabd8 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PageAllocationAligned.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2010 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 INC. 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 INC. 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 PageAllocationAligned_h +#define PageAllocationAligned_h + +#include +#include + +namespace WTF { + +class PageAllocationAligned : private PageBlock { +public: + PageAllocationAligned() + { + } + + using PageBlock::operator bool; + using PageBlock::size; + using PageBlock::base; + + static PageAllocationAligned allocate(size_t size, size_t alignment, OSAllocator::Usage usage = OSAllocator::UnknownUsage, bool writable = true, bool executable = false); + + void deallocate(); + +private: +#if OS(DARWIN) + PageAllocationAligned(void* base, size_t size) + : PageBlock(base, size, false) + { + } +#else + PageAllocationAligned(void* base, size_t size, void* reservationBase, size_t reservationSize) + : PageBlock(base, size, false) + , m_reservation(reservationBase, reservationSize, false) + { + } + + PageBlock m_reservation; +#endif +}; + + +} // namespace WTF + +using WTF::PageAllocationAligned; + +#endif // PageAllocationAligned_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PageBlock.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PageBlock.h new file mode 100644 index 000000000..3c348a0e3 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PageBlock.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2010 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 INC. 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 INC. 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 PageBlock_h +#define PageBlock_h + +namespace WTF { + +WTF_EXPORT_PRIVATE size_t pageSize(); +inline bool isPageAligned(void* address) { return !(reinterpret_cast(address) & (pageSize() - 1)); } +inline bool isPageAligned(size_t size) { return !(size & (pageSize() - 1)); } +inline bool isPowerOfTwo(size_t size) { return !(size & (size - 1)); } + +class PageBlock { +public: + PageBlock(); + PageBlock(const PageBlock&); + PageBlock(void*, size_t, bool hasGuardPages); + + void* base() const { return m_base; } + size_t size() const { return m_size; } + + operator bool() const { return !!m_realBase; } + + bool contains(void* containedBase, size_t containedSize) + { + return containedBase >= m_base + && (static_cast(containedBase) + containedSize) <= (static_cast(m_base) + m_size); + } + +private: + void* m_realBase; + void* m_base; + size_t m_size; +}; + +inline PageBlock::PageBlock() + : m_realBase(0) + , m_base(0) + , m_size(0) +{ +} + +inline PageBlock::PageBlock(const PageBlock& other) + : m_realBase(other.m_realBase) + , m_base(other.m_base) + , m_size(other.m_size) +{ +} + +inline PageBlock::PageBlock(void* base, size_t size, bool hasGuardPages) + : m_realBase(base) + , m_base(static_cast(base) + ((base && hasGuardPages) ? pageSize() : 0)) + , m_size(size) +{ +} + +} // namespace WTF + +using WTF::pageSize; +using WTF::isPageAligned; +using WTF::isPageAligned; +using WTF::isPowerOfTwo; + +#endif // PageBlock_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PageReservation.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PageReservation.h new file mode 100644 index 000000000..77783ebcc --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PageReservation.h @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2010 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 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 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 PageReservation_h +#define PageReservation_h + +#include + +namespace WTF { + +/* + PageReservation + + Like PageAllocation, the PageReservation class provides a cross-platform memory + allocation interface, but with a set of capabilities more similar to that of + VirtualAlloc than posix mmap. PageReservation can be used to allocate virtual + memory without committing physical memory pages using PageReservation::reserve. + Following a call to reserve all memory in the region is in a decommited state, + in which the memory should not be used (accessing the memory may cause a fault). + + Before using memory it must be committed by calling commit, which is passed start + and size values (both of which require system page size granularity). One the + committed memory is no longer needed 'decommit' may be called to return the + memory to its devommitted state. Commit should only be called on memory that is + currently decommitted, and decommit should only be called on memory regions that + are currently committed. All memory should be decommited before the reservation + is deallocated. Values in memory may not be retained accross a pair of calls if + the region of memory is decommitted and then committed again. + + Memory protection should not be changed on decommitted memory, and if protection + is changed on memory while it is committed it should be returned to the orignal + protection before decommit is called. +*/ + +class PageReservation : private PageBlock { +public: + PageReservation() + : m_committed(0) + , m_writable(false) + , m_executable(false) + { + } + + using PageBlock::base; + using PageBlock::size; + +#ifndef __clang__ + using PageBlock::operator bool; +#else + // FIXME: This is a workaround for , wherein Clang incorrectly emits an access + // control warning when a client tries to use operator bool exposed above via "using PageBlock::operator bool". + operator bool() const { return PageBlock::operator bool(); } +#endif + + void commit(void* start, size_t size) + { + ASSERT(*this); + ASSERT(isPageAligned(start)); + ASSERT(isPageAligned(size)); + ASSERT(contains(start, size)); + + m_committed += size; + OSAllocator::commit(start, size, m_writable, m_executable); + } + + void decommit(void* start, size_t size) + { + ASSERT(*this); + ASSERT(isPageAligned(start)); + ASSERT(isPageAligned(size)); + ASSERT(contains(start, size)); + + m_committed -= size; + OSAllocator::decommit(start, size); + } + + size_t committed() + { + return m_committed; + } + + static PageReservation reserve(size_t size, OSAllocator::Usage usage = OSAllocator::UnknownUsage, bool writable = true, bool executable = false) + { + ASSERT(isPageAligned(size)); + return PageReservation(OSAllocator::reserveUncommitted(size, usage, writable, executable), size, writable, executable, false); + } + + static PageReservation reserveWithGuardPages(size_t size, OSAllocator::Usage usage = OSAllocator::UnknownUsage, bool writable = true, bool executable = false) + { + ASSERT(isPageAligned(size)); + return PageReservation(OSAllocator::reserveUncommitted(size + pageSize() * 2, usage, writable, executable, true), size, writable, executable, true); + } + + void deallocate() + { + ASSERT(!m_committed); + + // Clear base & size before calling release; if this is *inside* allocation + // then we won't be able to clear then after deallocating the memory. + PageReservation tmp; + std::swap(tmp, *this); + + ASSERT(tmp); + ASSERT(!*this); + + OSAllocator::releaseDecommitted(tmp.base(), tmp.size()); + } + +private: + PageReservation(void* base, size_t size, bool writable, bool executable, bool hasGuardPages) + : PageBlock(base, size, hasGuardPages) + , m_committed(0) + , m_writable(writable) + , m_executable(executable) + { + } + + size_t m_committed; + bool m_writable; + bool m_executable; +}; + +} + +using WTF::PageReservation; + +#endif // PageReservation_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ParallelJobs.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ParallelJobs.h new file mode 100644 index 000000000..92b9c5b5b --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ParallelJobs.h @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2011 University of Szeged + * Copyright (C) 2011 Gabor Loki + * 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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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 ParallelJobs_h +#define ParallelJobs_h + +#include "Assertions.h" +#include "Noncopyable.h" +#include "RefPtr.h" +#include + +// Usage: +// +// // Initialize parallel jobs +// ParallelJobs parallelJobs(&worker [, requestedNumberOfJobs]); +// +// // Fill the parameter array +// for(i = 0; i < parallelJobs.numberOfJobs(); ++i) { +// TypeOfParameter& params = parallelJobs.parameter(i); +// params.attr1 = localVars ... +// ... +// } +// +// // Execute parallel jobs +// parallelJobs.execute(); +// + +#if ENABLE(THREADING_GENERIC) +#include "ParallelJobsGeneric.h" + +#elif ENABLE(THREADING_OPENMP) +#include "ParallelJobsOpenMP.h" + +#elif ENABLE(THREADING_LIBDISPATCH) +#include "ParallelJobsLibdispatch.h" + +#else +#error "No parallel processing API for ParallelJobs" + +#endif + +namespace WTF { + +template +class ParallelJobs { + WTF_MAKE_FAST_ALLOCATED; +public: + typedef void (*WorkerFunction)(Type*); + + ParallelJobs(WorkerFunction func, int requestedJobNumber) : + m_parallelEnvironment(reinterpret_cast(func), sizeof(Type), requestedJobNumber) + { + m_parameters.grow(m_parallelEnvironment.numberOfJobs()); + ASSERT(numberOfJobs() == m_parameters.size()); + } + + size_t numberOfJobs() + { + return m_parameters.size(); + } + + Type& parameter(size_t i) + { + return m_parameters[i]; + } + + void execute() + { + m_parallelEnvironment.execute(reinterpret_cast(m_parameters.data())); + } + +private: + ParallelEnvironment m_parallelEnvironment; + Vector m_parameters; +}; + +} // namespace WTF + +using WTF::ParallelJobs; + +#endif // ParallelJobs_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ParallelJobsGeneric.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ParallelJobsGeneric.h new file mode 100644 index 000000000..1c7d63c16 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ParallelJobsGeneric.h @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2011 University of Szeged + * Copyright (C) 2011 Gabor Loki + * 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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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 ParallelJobsGeneric_h +#define ParallelJobsGeneric_h + +#if ENABLE(THREADING_GENERIC) + +#include +#include + +namespace WTF { + +class ParallelEnvironment { + WTF_MAKE_FAST_ALLOCATED; +public: + typedef void (*ThreadFunction)(void*); + + ParallelEnvironment(ThreadFunction, size_t sizeOfParameter, int requestedJobNumber); + + int numberOfJobs() + { + return m_numberOfJobs; + } + + void execute(void* parameters); + + class ThreadPrivate : public RefCounted { + public: + ThreadPrivate() + : m_threadID(0) + , m_running(false) + , m_parent(0) + { + } + + bool tryLockFor(ParallelEnvironment*); + + void execute(ThreadFunction, void*); + + void waitForFinish(); + + static PassRefPtr create() + { + return adoptRef(new ThreadPrivate()); + } + + static void* workerThread(void*); + + private: + ThreadIdentifier m_threadID; + bool m_running; + ParallelEnvironment* m_parent; + + mutable Mutex m_mutex; + ThreadCondition m_threadCondition; + + ThreadFunction m_threadFunction; + void* m_parameters; + }; + +private: + ThreadFunction m_threadFunction; + size_t m_sizeOfParameter; + int m_numberOfJobs; + + Vector< RefPtr > m_threads; + static Vector< RefPtr >* s_threadPool; +}; + +} // namespace WTF + +#endif // ENABLE(THREADING_GENERIC) + + +#endif // ParallelJobsGeneric_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ParallelJobsLibdispatch.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ParallelJobsLibdispatch.h new file mode 100644 index 000000000..ca7d9a4e8 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ParallelJobsLibdispatch.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2011 University of Szeged + * Copyright (C) 2011 Gabor Loki + * 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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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 ParallelJobsLibdispatch_h +#define ParallelJobsLibdispatch_h + +#if ENABLE(THREADING_LIBDISPATCH) + +#include + +namespace WTF { + +class ParallelEnvironment { + WTF_MAKE_FAST_ALLOCATED; +public: + typedef void (*ThreadFunction)(void*); + + ParallelEnvironment(ThreadFunction threadFunction, size_t sizeOfParameter, int requestedJobNumber) + : m_threadFunction(threadFunction) + , m_sizeOfParameter(sizeOfParameter) + , m_numberOfJobs(requestedJobNumber) + { + // We go with the requested number of jobs. libdispatch will distribute the work optimally. + ASSERT_ARG(requestedJobNumber, requestedJobNumber > 0); + } + + int numberOfJobs() + { + return m_numberOfJobs; + } + + void execute(unsigned char* parameters) + { + static dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + + dispatch_apply(m_numberOfJobs, globalQueue, ^(size_t i) { (*m_threadFunction)(parameters + (m_sizeOfParameter * i)); }); + } + +private: + ThreadFunction m_threadFunction; + size_t m_sizeOfParameter; + int m_numberOfJobs; +}; + +} // namespace WTF + +#endif // ENABLE(THREADING_LIBDISPATCH) + +#endif // ParallelJobsLibdispatch_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ParallelJobsOpenMP.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ParallelJobsOpenMP.h new file mode 100644 index 000000000..706bd8065 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ParallelJobsOpenMP.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2011 University of Szeged + * Copyright (C) 2011 Gabor Loki + * 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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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 ParallelJobsOpenMP_h +#define ParallelJobsOpenMP_h + +#if ENABLE(THREADING_OPENMP) + +#include + +namespace WTF { + +class ParallelEnvironment { + WTF_MAKE_NONCOPYABLE(ParallelEnvironment); +public: + typedef void (*ThreadFunction)(void*); + + ParallelEnvironment(ThreadFunction threadFunction, size_t sizeOfParameter, int requestedJobNumber) : + m_threadFunction(threadFunction), + m_sizeOfParameter(sizeOfParameter) + { + int maxNumberOfThreads = omp_get_max_threads(); + + if (!requestedJobNumber || requestedJobNumber > maxNumberOfThreads) + requestedJobNumber = maxNumberOfThreads; + + ASSERT(requestedJobNumber > 0); + + m_numberOfJobs = requestedJobNumber; + + } + + int numberOfJobs() + { + return m_numberOfJobs; + } + + void execute(unsigned char* parameters) + { + omp_set_num_threads(m_numberOfJobs); + +#pragma omp parallel for + for (int i = 0; i < m_numberOfJobs; ++i) + (*m_threadFunction)(parameters + i * m_sizeOfParameter); + } + +private: + ThreadFunction m_threadFunction; + size_t m_sizeOfParameter; + int m_numberOfJobs; +}; + +} // namespace WTF + +#endif // ENABLE(THREADING_OPENMP) + +#endif // ParallelJobsOpenMP_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ParserArena.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ParserArena.h new file mode 100644 index 000000000..49f0ab6bf --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ParserArena.h @@ -0,0 +1,189 @@ +/* + * 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 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 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 ParserArena_h +#define ParserArena_h + +#include "Identifier.h" +#include + +namespace JSC { + + class ParserArenaDeletable; + class ParserArenaRefCounted; + + class IdentifierArena { + WTF_MAKE_FAST_ALLOCATED; + public: + IdentifierArena() + { + clear(); + } + + template + ALWAYS_INLINE const Identifier& makeIdentifier(JSGlobalData*, const T* characters, size_t length); + ALWAYS_INLINE const Identifier& makeIdentifierLCharFromUChar(JSGlobalData*, const UChar* characters, size_t length); + + const Identifier& makeNumericIdentifier(JSGlobalData*, double number); + + bool isEmpty() const { return m_identifiers.isEmpty(); } + + public: + static const int MaximumCachableCharacter = 128; + typedef SegmentedVector IdentifierVector; + void clear() + { + m_identifiers.clear(); + for (int i = 0; i < MaximumCachableCharacter; i++) + m_shortIdentifiers[i] = 0; + for (int i = 0; i < MaximumCachableCharacter; i++) + m_recentIdentifiers[i] = 0; + } + + private: + IdentifierVector m_identifiers; + FixedArray m_shortIdentifiers; + FixedArray m_recentIdentifiers; + }; + + template + ALWAYS_INLINE const Identifier& IdentifierArena::makeIdentifier(JSGlobalData* globalData, const T* characters, size_t length) + { + if (characters[0] >= MaximumCachableCharacter) { + m_identifiers.append(Identifier(globalData, characters, length)); + return m_identifiers.last(); + } + if (length == 1) { + if (Identifier* ident = m_shortIdentifiers[characters[0]]) + return *ident; + m_identifiers.append(Identifier(globalData, characters, length)); + m_shortIdentifiers[characters[0]] = &m_identifiers.last(); + return m_identifiers.last(); + } + Identifier* ident = m_recentIdentifiers[characters[0]]; + if (ident && Identifier::equal(ident->impl(), characters, length)) + return *ident; + m_identifiers.append(Identifier(globalData, characters, length)); + m_recentIdentifiers[characters[0]] = &m_identifiers.last(); + return m_identifiers.last(); + } + + ALWAYS_INLINE const Identifier& IdentifierArena::makeIdentifierLCharFromUChar(JSGlobalData* globalData, const UChar* characters, size_t length) + { + if (characters[0] >= MaximumCachableCharacter) { + m_identifiers.append(Identifier::createLCharFromUChar(globalData, characters, length)); + return m_identifiers.last(); + } + if (length == 1) { + if (Identifier* ident = m_shortIdentifiers[characters[0]]) + return *ident; + m_identifiers.append(Identifier(globalData, characters, length)); + m_shortIdentifiers[characters[0]] = &m_identifiers.last(); + return m_identifiers.last(); + } + Identifier* ident = m_recentIdentifiers[characters[0]]; + if (ident && Identifier::equal(ident->impl(), characters, length)) + return *ident; + m_identifiers.append(Identifier::createLCharFromUChar(globalData, characters, length)); + m_recentIdentifiers[characters[0]] = &m_identifiers.last(); + return m_identifiers.last(); + } + + inline const Identifier& IdentifierArena::makeNumericIdentifier(JSGlobalData* globalData, double number) + { + m_identifiers.append(Identifier(globalData, UString::number(number))); + return m_identifiers.last(); + } + + class ParserArena { + WTF_MAKE_NONCOPYABLE(ParserArena); + public: + ParserArena(); + ~ParserArena(); + + void swap(ParserArena& otherArena) + { + std::swap(m_freeableMemory, otherArena.m_freeableMemory); + std::swap(m_freeablePoolEnd, otherArena.m_freeablePoolEnd); + m_identifierArena.swap(otherArena.m_identifierArena); + m_freeablePools.swap(otherArena.m_freeablePools); + m_deletableObjects.swap(otherArena.m_deletableObjects); + m_refCountedObjects.swap(otherArena.m_refCountedObjects); + } + + void* allocateFreeable(size_t size) + { + ASSERT(size); + ASSERT(size <= freeablePoolSize); + size_t alignedSize = alignSize(size); + ASSERT(alignedSize <= freeablePoolSize); + if (UNLIKELY(static_cast(m_freeablePoolEnd - m_freeableMemory) < alignedSize)) + allocateFreeablePool(); + void* block = m_freeableMemory; + m_freeableMemory += alignedSize; + return block; + } + + void* allocateDeletable(size_t size) + { + ParserArenaDeletable* deletable = static_cast(allocateFreeable(size)); + m_deletableObjects.append(deletable); + return deletable; + } + + void derefWithArena(PassRefPtr); + bool contains(ParserArenaRefCounted*) const; + ParserArenaRefCounted* last() const; + void removeLast(); + + bool isEmpty() const; + JS_EXPORT_PRIVATE void reset(); + + IdentifierArena& identifierArena() { return *m_identifierArena; } + + private: + static const size_t freeablePoolSize = 8000; + + static size_t alignSize(size_t size) + { + return (size + sizeof(WTF::AllocAlignmentInteger) - 1) & ~(sizeof(WTF::AllocAlignmentInteger) - 1); + } + + void* freeablePool(); + void allocateFreeablePool(); + void deallocateObjects(); + + char* m_freeableMemory; + char* m_freeablePoolEnd; + + OwnPtr m_identifierArena; + Vector m_freeablePools; + Vector m_deletableObjects; + Vector > m_refCountedObjects; + }; + +} + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ParserTokens.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ParserTokens.h new file mode 100644 index 000000000..a1ea751ac --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ParserTokens.h @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2010 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 INC. 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 INC. 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 ParserTokens_h +#define ParserTokens_h + +namespace JSC { + +class Identifier; + +enum { + UnaryOpTokenFlag = 64, + KeywordTokenFlag = 128, + BinaryOpTokenPrecedenceShift = 8, + BinaryOpTokenAllowsInPrecedenceAdditionalShift = 4, + BinaryOpTokenPrecedenceMask = 15 << BinaryOpTokenPrecedenceShift, +}; + +#define BINARY_OP_PRECEDENCE(prec) (((prec) << BinaryOpTokenPrecedenceShift) | ((prec) << (BinaryOpTokenPrecedenceShift + BinaryOpTokenAllowsInPrecedenceAdditionalShift))) +#define IN_OP_PRECEDENCE(prec) ((prec) << (BinaryOpTokenPrecedenceShift + BinaryOpTokenAllowsInPrecedenceAdditionalShift)) + +enum JSTokenType { + NULLTOKEN = KeywordTokenFlag, + TRUETOKEN, + FALSETOKEN, + BREAK, + CASE, + DEFAULT, + FOR, + NEW, + VAR, + CONSTTOKEN, + CONTINUE, + FUNCTION, + RETURN, + IF, + THISTOKEN, + DO, + WHILE, + SWITCH, + WITH, + RESERVED, + RESERVED_IF_STRICT, + THROW, + TRY, + CATCH, + FINALLY, + DEBUGGER, + ELSE, + OPENBRACE = 0, + CLOSEBRACE, + OPENPAREN, + CLOSEPAREN, + OPENBRACKET, + CLOSEBRACKET, + COMMA, + QUESTION, + NUMBER, + IDENT, + STRING, + SEMICOLON, + COLON, + DOT, + ERRORTOK, + EOFTOK, + EQUAL, + PLUSEQUAL, + MINUSEQUAL, + MULTEQUAL, + DIVEQUAL, + LSHIFTEQUAL, + RSHIFTEQUAL, + URSHIFTEQUAL, + ANDEQUAL, + MODEQUAL, + XOREQUAL, + OREQUAL, + LastUntaggedToken, + + // Begin tagged tokens + PLUSPLUS = 0 | UnaryOpTokenFlag, + MINUSMINUS = 1 | UnaryOpTokenFlag, + EXCLAMATION = 2 | UnaryOpTokenFlag, + TILDE = 3 | UnaryOpTokenFlag, + AUTOPLUSPLUS = 4 | UnaryOpTokenFlag, + AUTOMINUSMINUS = 5 | UnaryOpTokenFlag, + TYPEOF = 6 | UnaryOpTokenFlag | KeywordTokenFlag, + VOIDTOKEN = 7 | UnaryOpTokenFlag | KeywordTokenFlag, + DELETETOKEN = 8 | UnaryOpTokenFlag | KeywordTokenFlag, + OR = 0 | BINARY_OP_PRECEDENCE(1), + AND = 1 | BINARY_OP_PRECEDENCE(2), + BITOR = 2 | BINARY_OP_PRECEDENCE(3), + BITXOR = 3 | BINARY_OP_PRECEDENCE(4), + BITAND = 4 | BINARY_OP_PRECEDENCE(5), + EQEQ = 5 | BINARY_OP_PRECEDENCE(6), + NE = 6 | BINARY_OP_PRECEDENCE(6), + STREQ = 7 | BINARY_OP_PRECEDENCE(6), + STRNEQ = 8 | BINARY_OP_PRECEDENCE(6), + LT = 9 | BINARY_OP_PRECEDENCE(7), + GT = 10 | BINARY_OP_PRECEDENCE(7), + LE = 11 | BINARY_OP_PRECEDENCE(7), + GE = 12 | BINARY_OP_PRECEDENCE(7), + INSTANCEOF = 13 | BINARY_OP_PRECEDENCE(7) | KeywordTokenFlag, + INTOKEN = 14 | IN_OP_PRECEDENCE(7) | KeywordTokenFlag, + LSHIFT = 15 | BINARY_OP_PRECEDENCE(8), + RSHIFT = 16 | BINARY_OP_PRECEDENCE(8), + URSHIFT = 17 | BINARY_OP_PRECEDENCE(8), + PLUS = 18 | BINARY_OP_PRECEDENCE(9) | UnaryOpTokenFlag, + MINUS = 19 | BINARY_OP_PRECEDENCE(9) | UnaryOpTokenFlag, + TIMES = 20 | BINARY_OP_PRECEDENCE(10), + DIVIDE = 21 | BINARY_OP_PRECEDENCE(10), + MOD = 22 | BINARY_OP_PRECEDENCE(10) +}; + +union JSTokenData { + int intValue; + double doubleValue; + const Identifier* ident; +}; + +struct JSTokenInfo { + JSTokenInfo() : line(0) { } + int line; + int startOffset; + int endOffset; +}; + +struct JSToken { + JSTokenType m_type; + JSTokenData m_data; + JSTokenInfo m_info; +}; + +enum JSParserStrictness { JSParseNormal, JSParseStrict }; +enum JSParserMode { JSParseProgramCode, JSParseFunctionCode }; + +} + + +#endif // ParserTokens_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PassOwnArrayPtr.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PassOwnArrayPtr.h new file mode 100644 index 000000000..3748f18c6 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PassOwnArrayPtr.h @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2010 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 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 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 WTF_PassOwnArrayPtr_h +#define WTF_PassOwnArrayPtr_h + +#include "Assertions.h" +#include "NullPtr.h" +#include "TypeTraits.h" + +namespace WTF { + +template class OwnArrayPtr; +template class PassOwnArrayPtr; +template PassOwnArrayPtr adoptArrayPtr(T*); +template void deleteOwnedArrayPtr(T* ptr); + +template class PassOwnArrayPtr { +public: + typedef T* PtrType; + + PassOwnArrayPtr() : m_ptr(0) { } + PassOwnArrayPtr(std::nullptr_t) : m_ptr(0) { } + + // It somewhat breaks the type system to allow transfer of ownership out of + // a const PassOwnArrayPtr. However, it makes it much easier to work with PassOwnArrayPtr + // temporaries, and we don't have a need to use real const PassOwnArrayPtrs anyway. + PassOwnArrayPtr(const PassOwnArrayPtr& o) : m_ptr(o.leakPtr()) { } + template PassOwnArrayPtr(const PassOwnArrayPtr& o) : m_ptr(o.leakPtr()) { } + + ~PassOwnArrayPtr() { deleteOwnedArrayPtr(m_ptr); } + + PtrType get() const { return m_ptr; } + + PtrType leakPtr() const WARN_UNUSED_RETURN; + + T& operator*() const { ASSERT(m_ptr); return *m_ptr; } + PtrType operator->() const { ASSERT(m_ptr); return m_ptr; } + + bool operator!() const { return !m_ptr; } + + // This conversion operator allows implicit conversion to bool but not to other integer types. + typedef PtrType PassOwnArrayPtr::*UnspecifiedBoolType; + operator UnspecifiedBoolType() const { return m_ptr ? &PassOwnArrayPtr::m_ptr : 0; } + + PassOwnArrayPtr& operator=(const PassOwnArrayPtr&) { COMPILE_ASSERT(!sizeof(T*), PassOwnArrayPtr_should_never_be_assigned_to); return *this; } + + template friend PassOwnArrayPtr adoptArrayPtr(U*); + +private: + explicit PassOwnArrayPtr(PtrType ptr) : m_ptr(ptr) { } + + mutable PtrType m_ptr; +}; + +template inline typename PassOwnArrayPtr::PtrType PassOwnArrayPtr::leakPtr() const +{ + PtrType ptr = m_ptr; + m_ptr = 0; + return ptr; +} + +template inline bool operator==(const PassOwnArrayPtr& a, const PassOwnArrayPtr& b) +{ + return a.get() == b.get(); +} + +template inline bool operator==(const PassOwnArrayPtr& a, const OwnArrayPtr& b) +{ + return a.get() == b.get(); +} + +template inline bool operator==(const OwnArrayPtr& a, const PassOwnArrayPtr& b) +{ + return a.get() == b.get(); +} + +template inline bool operator==(const PassOwnArrayPtr& a, U* b) +{ + return a.get() == b; +} + +template inline bool operator==(T* a, const PassOwnArrayPtr& b) +{ + return a == b.get(); +} + +template inline bool operator!=(const PassOwnArrayPtr& a, const PassOwnArrayPtr& b) +{ + return a.get() != b.get(); +} + +template inline bool operator!=(const PassOwnArrayPtr& a, const OwnArrayPtr& b) +{ + return a.get() != b.get(); +} + +template inline bool operator!=(const OwnArrayPtr& a, const PassOwnArrayPtr& b) +{ + return a.get() != b.get(); +} + +template inline bool operator!=(const PassOwnArrayPtr& a, U* b) +{ + return a.get() != b; +} + +template inline bool operator!=(T* a, const PassOwnArrayPtr& b) +{ + return a != b.get(); +} + +template inline PassOwnArrayPtr adoptArrayPtr(T* ptr) +{ + return PassOwnArrayPtr(ptr); +} + +template inline void deleteOwnedArrayPtr(T* ptr) +{ + typedef char known[sizeof(T) ? 1 : -1]; + if (sizeof(known)) + delete [] ptr; +} + +template inline PassOwnArrayPtr static_pointer_cast(const PassOwnArrayPtr& p) +{ + return adoptArrayPtr(static_cast(p.leakPtr())); +} + +template inline PassOwnArrayPtr const_pointer_cast(const PassOwnArrayPtr& p) +{ + return adoptArrayPtr(const_cast(p.leakPtr())); +} + +template inline T* getPtr(const PassOwnArrayPtr& p) +{ + return p.get(); +} + +} // namespace WTF + +using WTF::PassOwnArrayPtr; +using WTF::adoptArrayPtr; +using WTF::const_pointer_cast; +using WTF::static_pointer_cast; + +#endif // WTF_PassOwnArrayPtr_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PassOwnPtr.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PassOwnPtr.h new file mode 100644 index 000000000..262ac3bfe --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PassOwnPtr.h @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2009, 2010 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 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 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 WTF_PassOwnPtr_h +#define WTF_PassOwnPtr_h + +#include "Assertions.h" +#include "NullPtr.h" +#include "OwnPtrCommon.h" +#include "TypeTraits.h" + +namespace WTF { + + // Unlike most of our smart pointers, PassOwnPtr can take either the pointer type or the pointed-to type. + + template class OwnPtr; + template class PassOwnPtr; + template PassOwnPtr adoptPtr(T*); + + template class PassOwnPtr { + public: + typedef typename RemovePointer::Type ValueType; + typedef ValueType* PtrType; + + PassOwnPtr() : m_ptr(0) { } + PassOwnPtr(std::nullptr_t) : m_ptr(0) { } + + // It somewhat breaks the type system to allow transfer of ownership out of + // a const PassOwnPtr. However, it makes it much easier to work with PassOwnPtr + // temporaries, and we don't have a need to use real const PassOwnPtrs anyway. + PassOwnPtr(const PassOwnPtr& o) : m_ptr(o.leakPtr()) { } + template PassOwnPtr(const PassOwnPtr& o) : m_ptr(o.leakPtr()) { } + + ~PassOwnPtr() { deleteOwnedPtr(m_ptr); } + + PtrType get() const { return m_ptr; } + + PtrType leakPtr() const WARN_UNUSED_RETURN; + + ValueType& operator*() const { ASSERT(m_ptr); return *m_ptr; } + PtrType operator->() const { ASSERT(m_ptr); return m_ptr; } + + bool operator!() const { return !m_ptr; } + + // This conversion operator allows implicit conversion to bool but not to other integer types. + typedef PtrType PassOwnPtr::*UnspecifiedBoolType; + operator UnspecifiedBoolType() const { return m_ptr ? &PassOwnPtr::m_ptr : 0; } + + PassOwnPtr& operator=(const PassOwnPtr&) { COMPILE_ASSERT(!sizeof(T*), PassOwnPtr_should_never_be_assigned_to); return *this; } + + template friend PassOwnPtr adoptPtr(U*); + + private: + explicit PassOwnPtr(PtrType ptr) : m_ptr(ptr) { } + + // We should never have two OwnPtrs for the same underlying object (otherwise we'll get + // double-destruction), so these equality operators should never be needed. + template bool operator==(const PassOwnPtr&) { COMPILE_ASSERT(!sizeof(U*), OwnPtrs_should_never_be_equal); return false; } + template bool operator!=(const PassOwnPtr&) { COMPILE_ASSERT(!sizeof(U*), OwnPtrs_should_never_be_equal); return false; } + template bool operator==(const OwnPtr&) { COMPILE_ASSERT(!sizeof(U*), OwnPtrs_should_never_be_equal); return false; } + template bool operator!=(const OwnPtr&) { COMPILE_ASSERT(!sizeof(U*), OwnPtrs_should_never_be_equal); return false; } + + mutable PtrType m_ptr; + }; + + template inline typename PassOwnPtr::PtrType PassOwnPtr::leakPtr() const + { + PtrType ptr = m_ptr; + m_ptr = 0; + return ptr; + } + + template inline bool operator==(const PassOwnPtr& a, const PassOwnPtr& b) + { + return a.get() == b.get(); + } + + template inline bool operator==(const PassOwnPtr& a, const OwnPtr& b) + { + return a.get() == b.get(); + } + + template inline bool operator==(const OwnPtr& a, const PassOwnPtr& b) + { + return a.get() == b.get(); + } + + template inline bool operator==(const PassOwnPtr& a, U* b) + { + return a.get() == b; + } + + template inline bool operator==(T* a, const PassOwnPtr& b) + { + return a == b.get(); + } + + template inline bool operator!=(const PassOwnPtr& a, const PassOwnPtr& b) + { + return a.get() != b.get(); + } + + template inline bool operator!=(const PassOwnPtr& a, const OwnPtr& b) + { + return a.get() != b.get(); + } + + template inline bool operator!=(const OwnPtr& a, const PassOwnPtr& b) + { + return a.get() != b.get(); + } + + template inline bool operator!=(const PassOwnPtr& a, U* b) + { + return a.get() != b; + } + + template inline bool operator!=(T* a, const PassOwnPtr& b) + { + return a != b.get(); + } + + template inline PassOwnPtr adoptPtr(T* ptr) + { + return PassOwnPtr(ptr); + } + + template inline PassOwnPtr static_pointer_cast(const PassOwnPtr& p) + { + return adoptPtr(static_cast(p.leakPtr())); + } + + template inline PassOwnPtr const_pointer_cast(const PassOwnPtr& p) + { + return adoptPtr(const_cast(p.leakPtr())); + } + + template inline T* getPtr(const PassOwnPtr& p) + { + return p.get(); + } + +} // namespace WTF + +using WTF::PassOwnPtr; +using WTF::adoptPtr; +using WTF::const_pointer_cast; +using WTF::static_pointer_cast; + +#endif // WTF_PassOwnPtr_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PassRefPtr.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PassRefPtr.h new file mode 100644 index 000000000..a13dee794 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PassRefPtr.h @@ -0,0 +1,245 @@ +/* + * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WTF_PassRefPtr_h +#define WTF_PassRefPtr_h + +#include "AlwaysInline.h" +#include "NullPtr.h" + +namespace WTF { + + template class RefPtr; + template class PassRefPtr; + template PassRefPtr adoptRef(T*); + + inline void adopted(const void*) { } + +#if !PLATFORM(QT) + #define REF_DEREF_INLINE ALWAYS_INLINE +#else + // Using ALWAYS_INLINE broke the Qt build. This may be a GCC bug. + // See https://bugs.webkit.org/show_bug.cgi?id=37253 for details. + #define REF_DEREF_INLINE inline +#endif + + template REF_DEREF_INLINE void refIfNotNull(T* ptr) + { + if (LIKELY(ptr != 0)) + ptr->ref(); + } + + template REF_DEREF_INLINE void derefIfNotNull(T* ptr) + { + if (LIKELY(ptr != 0)) + ptr->deref(); + } + + #undef REF_DEREF_INLINE + + template class PassRefPtr { + public: + PassRefPtr() : m_ptr(0) { } + PassRefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); } + // It somewhat breaks the type system to allow transfer of ownership out of + // a const PassRefPtr. However, it makes it much easier to work with PassRefPtr + // temporaries, and we don't have a need to use real const PassRefPtrs anyway. + PassRefPtr(const PassRefPtr& o) : m_ptr(o.leakRef()) { } + template PassRefPtr(const PassRefPtr& o) : m_ptr(o.leakRef()) { } + + ALWAYS_INLINE ~PassRefPtr() { derefIfNotNull(m_ptr); } + + template PassRefPtr(const RefPtr&); + + T* get() const { return m_ptr; } + + T* leakRef() const WARN_UNUSED_RETURN; + + T& operator*() const { return *m_ptr; } + T* operator->() const { return m_ptr; } + + bool operator!() const { return !m_ptr; } + + // This conversion operator allows implicit conversion to bool but not to other integer types. + typedef T* (PassRefPtr::*UnspecifiedBoolType); + operator UnspecifiedBoolType() const { return m_ptr ? &PassRefPtr::m_ptr : 0; } + + PassRefPtr& operator=(const PassRefPtr&) { COMPILE_ASSERT(!sizeof(T*), PassRefPtr_should_never_be_assigned_to); return *this; } + + friend PassRefPtr adoptRef(T*); + + private: + // adopting constructor + PassRefPtr(T* ptr, bool) : m_ptr(ptr) { } + + mutable T* m_ptr; + }; + + // NonNullPassRefPtr: Optimized for passing non-null pointers. A NonNullPassRefPtr + // begins life non-null, and can only become null through a call to leakRef() + // or clear(). + + // FIXME: NonNullPassRefPtr could just inherit from PassRefPtr. However, + // if we use inheritance, GCC's optimizer fails to realize that destruction + // of a released NonNullPassRefPtr is a no-op. So, for now, just copy the + // most important code from PassRefPtr. + template class NonNullPassRefPtr { + public: + NonNullPassRefPtr(T* ptr) + : m_ptr(ptr) + { + ASSERT(m_ptr); + m_ptr->ref(); + } + + template NonNullPassRefPtr(const RefPtr& o) + : m_ptr(o.get()) + { + ASSERT(m_ptr); + m_ptr->ref(); + } + + NonNullPassRefPtr(const NonNullPassRefPtr& o) + : m_ptr(o.leakRef()) + { + ASSERT(m_ptr); + } + + template NonNullPassRefPtr(const NonNullPassRefPtr& o) + : m_ptr(o.leakRef()) + { + ASSERT(m_ptr); + } + + template NonNullPassRefPtr(const PassRefPtr& o) + : m_ptr(o.leakRef()) + { + ASSERT(m_ptr); + } + + ALWAYS_INLINE ~NonNullPassRefPtr() { derefIfNotNull(m_ptr); } + + T* get() const { return m_ptr; } + + T* leakRef() const WARN_UNUSED_RETURN { T* tmp = m_ptr; m_ptr = 0; return tmp; } + + T& operator*() const { return *m_ptr; } + T* operator->() const { return m_ptr; } + + NonNullPassRefPtr& operator=(const NonNullPassRefPtr&) { COMPILE_ASSERT(!sizeof(T*), NonNullPassRefPtr_should_never_be_assigned_to); return *this; } + + private: + mutable T* m_ptr; + }; + + template template inline PassRefPtr::PassRefPtr(const RefPtr& o) + : m_ptr(o.get()) + { + T* ptr = m_ptr; + refIfNotNull(ptr); + } + + template inline T* PassRefPtr::leakRef() const + { + T* ptr = m_ptr; + m_ptr = 0; + return ptr; + } + + template inline bool operator==(const PassRefPtr& a, const PassRefPtr& b) + { + return a.get() == b.get(); + } + + template inline bool operator==(const PassRefPtr& a, const RefPtr& b) + { + return a.get() == b.get(); + } + + template inline bool operator==(const RefPtr& a, const PassRefPtr& b) + { + return a.get() == b.get(); + } + + template inline bool operator==(const PassRefPtr& a, U* b) + { + return a.get() == b; + } + + template inline bool operator==(T* a, const PassRefPtr& b) + { + return a == b.get(); + } + + template inline bool operator!=(const PassRefPtr& a, const PassRefPtr& b) + { + return a.get() != b.get(); + } + + template inline bool operator!=(const PassRefPtr& a, const RefPtr& b) + { + return a.get() != b.get(); + } + + template inline bool operator!=(const RefPtr& a, const PassRefPtr& b) + { + return a.get() != b.get(); + } + + template inline bool operator!=(const PassRefPtr& a, U* b) + { + return a.get() != b; + } + + template inline bool operator!=(T* a, const PassRefPtr& b) + { + return a != b.get(); + } + + template inline PassRefPtr adoptRef(T* p) + { + adopted(p); + return PassRefPtr(p, true); + } + + template inline PassRefPtr static_pointer_cast(const PassRefPtr& p) + { + return adoptRef(static_cast(p.leakRef())); + } + + template inline PassRefPtr const_pointer_cast(const PassRefPtr& p) + { + return adoptRef(const_cast(p.leakRef())); + } + + template inline T* getPtr(const PassRefPtr& p) + { + return p.get(); + } + +} // namespace WTF + +using WTF::PassRefPtr; +using WTF::NonNullPassRefPtr; +using WTF::adoptRef; +using WTF::static_pointer_cast; +using WTF::const_pointer_cast; + +#endif // WTF_PassRefPtr_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PassTraits.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PassTraits.h new file mode 100644 index 000000000..346273486 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PassTraits.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2011 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 WTF_PassTraits_h +#define WTF_PassTraits_h + +#include "OwnPtr.h" +#include "RefPtr.h" + +// The PassTraits template exists to help optimize (or make possible) use +// of WTF data structures with WTF smart pointers that have a Pass +// variant for transfer of ownership + +namespace WTF { + +template struct PassTraits { + typedef T Type; + typedef T PassType; + static PassType transfer(Type& value) { return value; } +}; + +template struct PassTraits > { + typedef OwnPtr Type; + typedef PassOwnPtr PassType; + static PassType transfer(Type& value) { return value.release(); } +}; + +template struct PassTraits > { + typedef RefPtr Type; + typedef PassRefPtr PassType; + static PassType transfer(Type& value) { return value.release(); } +}; + +} // namespace WTF + +using WTF::PassTraits; + +#endif // WTF_PassTraits_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Platform.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Platform.h new file mode 100644 index 000000000..3e5c90f71 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Platform.h @@ -0,0 +1,1168 @@ +/* + * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2007-2009 Torch Mobile, Inc. + * Copyright (C) 2010, 2011 Research In Motion Limited. 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 WTF_Platform_h +#define WTF_Platform_h + +/* Include compiler specific macros */ +#include "Compiler.h" + +/* ==== PLATFORM handles OS, operating environment, graphics API, and + CPU. This macro will be phased out in favor of platform adaptation + macros, policy decision macros, and top-level port definitions. ==== */ +#define PLATFORM(WTF_FEATURE) (defined WTF_PLATFORM_##WTF_FEATURE && WTF_PLATFORM_##WTF_FEATURE) + + +/* ==== Platform adaptation macros: these describe properties of the target environment. ==== */ + +/* CPU() - the target CPU architecture */ +#define CPU(WTF_FEATURE) (defined WTF_CPU_##WTF_FEATURE && WTF_CPU_##WTF_FEATURE) +/* HAVE() - specific system features (headers, functions or similar) that are present or not */ +#define HAVE(WTF_FEATURE) (defined HAVE_##WTF_FEATURE && HAVE_##WTF_FEATURE) +/* OS() - underlying operating system; only to be used for mandated low-level services like + virtual memory, not to choose a GUI toolkit */ +#define OS(WTF_FEATURE) (defined WTF_OS_##WTF_FEATURE && WTF_OS_##WTF_FEATURE) + + +/* ==== Policy decision macros: these define policy choices for a particular port. ==== */ + +/* USE() - use a particular third-party library or optional OS service */ +#define USE(WTF_FEATURE) (defined WTF_USE_##WTF_FEATURE && WTF_USE_##WTF_FEATURE) +/* ENABLE() - turn on a specific feature of WebKit */ +#define ENABLE(WTF_FEATURE) (defined ENABLE_##WTF_FEATURE && ENABLE_##WTF_FEATURE) + + +/* ==== CPU() - the target CPU architecture ==== */ + +/* This also defines CPU(BIG_ENDIAN) or CPU(MIDDLE_ENDIAN) or neither, as appropriate. */ + +/* CPU(ALPHA) - DEC Alpha */ +#if defined(__alpha__) +#define WTF_CPU_ALPHA 1 +#endif + +/* CPU(IA64) - Itanium / IA-64 */ +#if defined(__ia64__) +#define WTF_CPU_IA64 1 +/* 32-bit mode on Itanium */ +#if !defined(__LP64__) +#define WTF_CPU_IA64_32 1 +#endif +#endif + +/* CPU(MIPS) - MIPS 32-bit */ +/* Note: Only O32 ABI is tested, so we enable it for O32 ABI for now. */ +#if (defined(mips) || defined(__mips__) || defined(MIPS) || defined(_MIPS_)) \ + && defined(_ABIO32) +#define WTF_CPU_MIPS 1 +#if defined(__MIPSEB__) +#define WTF_CPU_BIG_ENDIAN 1 +#endif +#define WTF_MIPS_PIC (defined __PIC__) +#define WTF_MIPS_ARCH __mips +#define WTF_MIPS_ISA(v) (defined WTF_MIPS_ARCH && WTF_MIPS_ARCH == v) +#define WTF_MIPS_ISA_AT_LEAST(v) (defined WTF_MIPS_ARCH && WTF_MIPS_ARCH >= v) +#define WTF_MIPS_ARCH_REV __mips_isa_rev +#define WTF_MIPS_ISA_REV(v) (defined WTF_MIPS_ARCH_REV && WTF_MIPS_ARCH_REV == v) +#define WTF_MIPS_DOUBLE_FLOAT (defined __mips_hard_float && !defined __mips_single_float) +#define WTF_MIPS_FP64 (defined __mips_fpr && __mips_fpr == 64) +/* MIPS requires allocators to use aligned memory */ +#define WTF_USE_ARENA_ALLOC_ALIGNMENT_INTEGER 1 +#endif /* MIPS */ + +/* CPU(PPC) - PowerPC 32-bit */ +#if defined(__ppc__) \ + || defined(__PPC__) \ + || defined(__powerpc__) \ + || defined(__powerpc) \ + || defined(__POWERPC__) \ + || defined(_M_PPC) \ + || defined(__PPC) +#define WTF_CPU_PPC 1 +#define WTF_CPU_BIG_ENDIAN 1 +#endif + +/* CPU(PPC64) - PowerPC 64-bit */ +#if defined(__ppc64__) \ + || defined(__PPC64__) +#define WTF_CPU_PPC64 1 +#define WTF_CPU_BIG_ENDIAN 1 +#endif + +/* CPU(SH4) - SuperH SH-4 */ +#if defined(__SH4__) +#define WTF_CPU_SH4 1 +#endif + +/* CPU(SPARC32) - SPARC 32-bit */ +#if defined(__sparc) && !defined(__arch64__) || defined(__sparcv8) +#define WTF_CPU_SPARC32 1 +#define WTF_CPU_BIG_ENDIAN 1 +#endif + +/* CPU(SPARC64) - SPARC 64-bit */ +#if defined(__sparc__) && defined(__arch64__) || defined (__sparcv9) +#define WTF_CPU_SPARC64 1 +#define WTF_CPU_BIG_ENDIAN 1 +#endif + +/* CPU(SPARC) - any SPARC, true for CPU(SPARC32) and CPU(SPARC64) */ +#if CPU(SPARC32) || CPU(SPARC64) +#define WTF_CPU_SPARC 1 +#endif + +/* CPU(S390X) - S390 64-bit */ +#if defined(__s390x__) +#define WTF_CPU_S390X 1 +#define WTF_CPU_BIG_ENDIAN 1 +#endif + +/* CPU(S390) - S390 32-bit */ +#if defined(__s390__) +#define WTF_CPU_S390 1 +#define WTF_CPU_BIG_ENDIAN 1 +#endif + +/* CPU(X86) - i386 / x86 32-bit */ +#if defined(__i386__) \ + || defined(i386) \ + || defined(_M_IX86) \ + || defined(_X86_) \ + || defined(__THW_INTEL) +#define WTF_CPU_X86 1 +#endif + +/* CPU(X86_64) - AMD64 / Intel64 / x86_64 64-bit */ +#if defined(__x86_64__) \ + || defined(_M_X64) +#define WTF_CPU_X86_64 1 +#endif + +/* CPU(ARM) - ARM, any version*/ +#if defined(arm) \ + || defined(__arm__) \ + || defined(ARM) \ + || defined(_ARM_) +#define WTF_CPU_ARM 1 + +#if defined(__ARMEB__) || (COMPILER(RVCT) && defined(__BIG_ENDIAN)) +#define WTF_CPU_BIG_ENDIAN 1 + +#elif !defined(__ARM_EABI__) \ + && !defined(__EABI__) \ + && !defined(__VFP_FP__) \ + && !defined(_WIN32_WCE) \ + && !defined(ANDROID) +#define WTF_CPU_MIDDLE_ENDIAN 1 + +#endif + +#define WTF_ARM_ARCH_AT_LEAST(N) (CPU(ARM) && WTF_ARM_ARCH_VERSION >= N) + +/* Set WTF_ARM_ARCH_VERSION */ +#if defined(__ARM_ARCH_4__) \ + || defined(__ARM_ARCH_4T__) \ + || defined(__MARM_ARMV4__) \ + || defined(_ARMV4I_) +#define WTF_ARM_ARCH_VERSION 4 + +#elif defined(__ARM_ARCH_5__) \ + || defined(__ARM_ARCH_5T__) \ + || defined(__MARM_ARMV5__) +#define WTF_ARM_ARCH_VERSION 5 + +#elif defined(__ARM_ARCH_5E__) \ + || defined(__ARM_ARCH_5TE__) \ + || defined(__ARM_ARCH_5TEJ__) +#define WTF_ARM_ARCH_VERSION 5 +/*ARMv5TE requires allocators to use aligned memory*/ +#define WTF_USE_ARENA_ALLOC_ALIGNMENT_INTEGER 1 + +#elif defined(__ARM_ARCH_6__) \ + || defined(__ARM_ARCH_6J__) \ + || defined(__ARM_ARCH_6K__) \ + || defined(__ARM_ARCH_6Z__) \ + || defined(__ARM_ARCH_6ZK__) \ + || defined(__ARM_ARCH_6T2__) \ + || defined(__ARMV6__) +#define WTF_ARM_ARCH_VERSION 6 + +#elif defined(__ARM_ARCH_7A__) \ + || defined(__ARM_ARCH_7R__) +#define WTF_ARM_ARCH_VERSION 7 + +/* RVCT sets _TARGET_ARCH_ARM */ +#elif defined(__TARGET_ARCH_ARM) +#define WTF_ARM_ARCH_VERSION __TARGET_ARCH_ARM + +#if defined(__TARGET_ARCH_5E) \ + || defined(__TARGET_ARCH_5TE) \ + || defined(__TARGET_ARCH_5TEJ) +/*ARMv5TE requires allocators to use aligned memory*/ +#define WTF_USE_ARENA_ALLOC_ALIGNMENT_INTEGER 1 +#endif + +#else +#define WTF_ARM_ARCH_VERSION 0 + +#endif + +/* Set WTF_THUMB_ARCH_VERSION */ +#if defined(__ARM_ARCH_4T__) +#define WTF_THUMB_ARCH_VERSION 1 + +#elif defined(__ARM_ARCH_5T__) \ + || defined(__ARM_ARCH_5TE__) \ + || defined(__ARM_ARCH_5TEJ__) +#define WTF_THUMB_ARCH_VERSION 2 + +#elif defined(__ARM_ARCH_6J__) \ + || defined(__ARM_ARCH_6K__) \ + || defined(__ARM_ARCH_6Z__) \ + || defined(__ARM_ARCH_6ZK__) \ + || defined(__ARM_ARCH_6M__) +#define WTF_THUMB_ARCH_VERSION 3 + +#elif defined(__ARM_ARCH_6T2__) \ + || defined(__ARM_ARCH_7__) \ + || defined(__ARM_ARCH_7A__) \ + || defined(__ARM_ARCH_7R__) \ + || defined(__ARM_ARCH_7M__) +#define WTF_THUMB_ARCH_VERSION 4 + +/* RVCT sets __TARGET_ARCH_THUMB */ +#elif defined(__TARGET_ARCH_THUMB) +#define WTF_THUMB_ARCH_VERSION __TARGET_ARCH_THUMB + +#else +#define WTF_THUMB_ARCH_VERSION 0 +#endif + + +/* CPU(ARMV5_OR_LOWER) - ARM instruction set v5 or earlier */ +/* On ARMv5 and below the natural alignment is required. + And there are some other differences for v5 or earlier. */ +#if !defined(ARMV5_OR_LOWER) && !WTF_ARM_ARCH_AT_LEAST(6) +#define WTF_CPU_ARMV5_OR_LOWER 1 +#endif + + +/* CPU(ARM_TRADITIONAL) - Thumb2 is not available, only traditional ARM (v4 or greater) */ +/* CPU(ARM_THUMB2) - Thumb2 instruction set is available */ +/* Only one of these will be defined. */ +#if !defined(WTF_CPU_ARM_TRADITIONAL) && !defined(WTF_CPU_ARM_THUMB2) +# if defined(thumb2) || defined(__thumb2__) \ + || ((defined(__thumb) || defined(__thumb__)) && WTF_THUMB_ARCH_VERSION == 4) +# define WTF_CPU_ARM_TRADITIONAL 0 +# define WTF_CPU_ARM_THUMB2 1 +# elif WTF_ARM_ARCH_AT_LEAST(4) +# define WTF_CPU_ARM_TRADITIONAL 1 +# define WTF_CPU_ARM_THUMB2 0 +# else +# error "Not supported ARM architecture" +# endif +#elif CPU(ARM_TRADITIONAL) && CPU(ARM_THUMB2) /* Sanity Check */ +# error "Cannot use both of WTF_CPU_ARM_TRADITIONAL and WTF_CPU_ARM_THUMB2 platforms" +#endif /* !defined(WTF_CPU_ARM_TRADITIONAL) && !defined(WTF_CPU_ARM_THUMB2) */ + +#if defined(__ARM_NEON__) && !defined(WTF_CPU_ARM_NEON) +#define WTF_CPU_ARM_NEON 1 +#endif + +#endif /* ARM */ + +#if CPU(ARM) || CPU(MIPS) || CPU(SH4) +#define WTF_CPU_NEEDS_ALIGNED_ACCESS 1 +#endif + +/* ==== OS() - underlying operating system; only to be used for mandated low-level services like + virtual memory, not to choose a GUI toolkit ==== */ + +/* OS(ANDROID) - Android */ +#ifdef ANDROID +#define WTF_OS_ANDROID 1 +#endif + +/* OS(AIX) - AIX */ +#ifdef _AIX +#define WTF_OS_AIX 1 +#endif + +/* OS(DARWIN) - Any Darwin-based OS, including Mac OS X and iPhone OS */ +#ifdef __APPLE__ +#define WTF_OS_DARWIN 1 + +#include +#include +#include +#endif + +/* OS(IOS) - iOS */ +/* OS(MAC_OS_X) - Mac OS X (not including iOS) */ +#if OS(DARWIN) && ((defined(TARGET_OS_EMBEDDED) && TARGET_OS_EMBEDDED) \ + || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) \ + || (defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR)) +#define WTF_OS_IOS 1 +#elif OS(DARWIN) && defined(TARGET_OS_MAC) && TARGET_OS_MAC +#define WTF_OS_MAC_OS_X 1 +/* FIXME: BUILDING_ON_.., and TARGETING... macros should be folded into the OS() system */ +#if !defined(MAC_OS_X_VERSION_10_6) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6 +#define BUILDING_ON_LEOPARD 1 +#elif !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 +#define BUILDING_ON_SNOW_LEOPARD 1 +#elif !defined(MAC_OS_X_VERSION_10_8) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_8 +#define BUILDING_ON_LION 1 +#endif +#if !defined(MAC_OS_X_VERSION_10_6) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6 +#define TARGETING_LEOPARD 1 +#elif !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7 +#define TARGETING_SNOW_LEOPARD 1 +#elif !defined(MAC_OS_X_VERSION_10_8) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_8 +#define TARGETING_LION 1 +#endif +#endif + +/* OS(FREEBSD) - FreeBSD */ +#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) +#define WTF_OS_FREEBSD 1 +#endif + +/* OS(LINUX) - Linux */ +#ifdef __linux__ +#define WTF_OS_LINUX 1 +#endif + +/* OS(NETBSD) - NetBSD */ +#if defined(__NetBSD__) +#define WTF_OS_NETBSD 1 +#endif + +/* OS(OPENBSD) - OpenBSD */ +#ifdef __OpenBSD__ +#define WTF_OS_OPENBSD 1 +#endif + +/* OS(QNX) - QNX */ +#if defined(__QNXNTO__) +#define WTF_OS_QNX 1 +#endif + +/* OS(SOLARIS) - Solaris */ +#if defined(sun) || defined(__sun) +#define WTF_OS_SOLARIS 1 +#endif + +/* OS(WINCE) - Windows CE; note that for this platform OS(WINDOWS) is also defined */ +#if defined(_WIN32_WCE) +#define WTF_OS_WINCE 1 +#endif + +/* OS(WINDOWS) - Any version of Windows */ +#if defined(WIN32) || defined(_WIN32) +#define WTF_OS_WINDOWS 1 +#endif + +/* OS(UNIX) - Any Unix-like system */ +#if OS(AIX) \ + || OS(ANDROID) \ + || OS(DARWIN) \ + || OS(FREEBSD) \ + || OS(LINUX) \ + || OS(NETBSD) \ + || OS(OPENBSD) \ + || OS(QNX) \ + || OS(SOLARIS) \ + || defined(unix) \ + || defined(__unix) \ + || defined(__unix__) +#define WTF_OS_UNIX 1 +#endif + +/* Operating environments */ + +/* FIXME: these are all mixes of OS, operating environment and policy choices. */ +/* PLATFORM(CHROMIUM) */ +/* PLATFORM(QT) */ +/* PLATFORM(WX) */ +/* PLATFORM(GTK) */ +/* PLATFORM(BLACKBERRY) */ +/* PLATFORM(MAC) */ +/* PLATFORM(WIN) */ +#if defined(BUILDING_CHROMIUM__) +#define WTF_PLATFORM_CHROMIUM 1 +#elif defined(BUILDING_QT__) +#define WTF_PLATFORM_QT 1 +#elif defined(BUILDING_WX__) +#define WTF_PLATFORM_WX 1 +#elif defined(BUILDING_GTK__) +#define WTF_PLATFORM_GTK 1 +#elif defined(BUILDING_BLACKBERRY__) +#define WTF_PLATFORM_BLACKBERRY 1 +#elif OS(DARWIN) +#define WTF_PLATFORM_MAC 1 +#elif OS(WINDOWS) +#define WTF_PLATFORM_WIN 1 +#endif + +/* PLATFORM(IOS) */ +/* FIXME: this is sometimes used as an OS switch and sometimes for higher-level things */ +#if (defined(TARGET_OS_EMBEDDED) && TARGET_OS_EMBEDDED) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) +#define WTF_PLATFORM_IOS 1 +#endif + +/* PLATFORM(IOS_SIMULATOR) */ +#if defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR +#define WTF_PLATFORM_IOS 1 +#define WTF_PLATFORM_IOS_SIMULATOR 1 +#else +#define WTF_PLATFORM_IOS_SIMULATOR 0 +#endif + +#if !defined(WTF_PLATFORM_IOS) +#define WTF_PLATFORM_IOS 0 +#endif + +/* Graphics engines */ + +/* USE(CG) and PLATFORM(CI) */ +#if PLATFORM(MAC) || PLATFORM(IOS) +#define WTF_USE_CG 1 +#endif +#if PLATFORM(MAC) || PLATFORM(IOS) || (PLATFORM(WIN) && USE(CG)) +#define WTF_USE_CA 1 +#endif + +/* USE(SKIA) for Win/Linux, CG for Mac, unless enabled */ +#if PLATFORM(CHROMIUM) +#if OS(DARWIN) +#if USE(SKIA_ON_MAC_CHROMIUM) +#define WTF_USE_SKIA 1 +#else +#define WTF_USE_CG 1 +#endif +#define WTF_USE_ATSUI 1 +#define WTF_USE_CORE_TEXT 1 +#define WTF_USE_ICCJPEG 1 +#else +#define WTF_USE_SKIA 1 +#define WTF_USE_CHROMIUM_NET 1 +#endif +#endif + +#if PLATFORM(BLACKBERRY) +#define ENABLE_DRAG_SUPPORT 0 +#define USE_SYSTEM_MALLOC 1 +#define WTF_USE_MERSENNE_TWISTER_19937 1 +#define WTF_USE_SKIA 1 +#endif + +#if PLATFORM(GTK) +#define WTF_USE_CAIRO 1 +#endif + + +#if OS(WINCE) +#include +#define WTF_USE_MERSENNE_TWISTER_19937 1 +#endif + +/* On Windows, use QueryPerformanceCounter by default */ +#if OS(WINDOWS) +#define WTF_USE_QUERY_PERFORMANCE_COUNTER 1 +#endif + +#if OS(WINCE) && !PLATFORM(QT) +#define NOMINMAX /* Windows min and max conflict with standard macros */ +#define NOSHLWAPI /* shlwapi.h not available on WinCe */ + +/* MSDN documentation says these functions are provided with uspce.lib. But we cannot find this file. */ +#define __usp10__ /* disable "usp10.h" */ + +#define _INC_ASSERT /* disable "assert.h" */ +#define assert(x) + +#endif /* OS(WINCE) && !PLATFORM(QT) */ + +#if PLATFORM(QT) +#ifndef WTF_USE_ICU_UNICODE +#define WTF_USE_QT4_UNICODE 1 +#endif +#elif OS(WINCE) +#define WTF_USE_WINCE_UNICODE 1 +#elif PLATFORM(GTK) +/* The GTK+ Unicode backend is configurable */ +#else +#define WTF_USE_ICU_UNICODE 1 +#endif + +#if PLATFORM(MAC) && !PLATFORM(IOS) +#if !defined(BUILDING_ON_LEOPARD) && CPU(X86_64) +#define WTF_USE_PLUGIN_HOST_PROCESS 1 +#endif +#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) +#define ENABLE_GESTURE_EVENTS 1 +#define ENABLE_RUBBER_BANDING 1 +#define WTF_USE_SCROLLBAR_PAINTER 1 +#endif +#if !defined(ENABLE_JAVA_BRIDGE) +#define ENABLE_JAVA_BRIDGE 1 +#endif +#if !defined(ENABLE_DASHBOARD_SUPPORT) +#define ENABLE_DASHBOARD_SUPPORT 1 +#endif +#define WTF_USE_CF 1 +#define WTF_USE_PTHREADS 1 +#define HAVE_PTHREAD_RWLOCK 1 +#define HAVE_READLINE 1 +#define HAVE_RUNLOOP_TIMER 1 +#define ENABLE_FULLSCREEN_API 1 +#define ENABLE_SMOOTH_SCROLLING 1 +#define ENABLE_WEB_ARCHIVE 1 +#define ENABLE_WEB_AUDIO 1 +#if defined(ENABLE_VIDEO) +#define ENABLE_VIDEO_TRACK 1 +#endif +#endif /* PLATFORM(MAC) && !PLATFORM(IOS) */ + +#if PLATFORM(CHROMIUM) && OS(DARWIN) +#define WTF_USE_CF 1 +#define WTF_USE_PTHREADS 1 +#define HAVE_PTHREAD_RWLOCK 1 + +#define WTF_USE_WK_SCROLLBAR_PAINTER 1 +#endif + +#if PLATFORM(IOS) +#define DONT_FINALIZE_ON_MAIN_THREAD 1 +#endif + +#if PLATFORM(QT) && OS(DARWIN) +#define WTF_USE_CF 1 +#define HAVE_DISPATCH_H 1 +#endif + +#if OS(DARWIN) && !PLATFORM(GTK) && !PLATFORM(QT) +#define ENABLE_PURGEABLE_MEMORY 1 +#endif + +#if PLATFORM(IOS) +#define ENABLE_CONTEXT_MENUS 0 +#define ENABLE_DRAG_SUPPORT 0 +#define ENABLE_DATA_TRANSFER_ITEMS 0 +#define ENABLE_FTPDIR 1 +#define ENABLE_GEOLOCATION 1 +#define ENABLE_ICONDATABASE 0 +#define ENABLE_INSPECTOR 1 +#define ENABLE_JAVA_BRIDGE 0 +#define ENABLE_NETSCAPE_PLUGIN_API 0 +#define ENABLE_ORIENTATION_EVENTS 1 +#define ENABLE_REPAINT_THROTTLING 1 +#define ENABLE_WEB_ARCHIVE 1 +#define HAVE_NETWORK_CFDATA_ARRAY_CALLBACK 1 +#define HAVE_PTHREAD_RWLOCK 1 +#define HAVE_READLINE 1 +#define HAVE_RUNLOOP_TIMER 0 +#define WTF_USE_CF 1 +#define WTF_USE_CFNETWORK 1 +#define WTF_USE_PTHREADS 1 + +#if PLATFORM(IOS_SIMULATOR) + #define ENABLE_INTERPRETER 1 + #define ENABLE_JIT 0 + #define ENABLE_YARR_JIT 0 +#else + #define ENABLE_INTERPRETER 1 + #define ENABLE_JIT 1 + #define ENABLE_YARR_JIT 1 +#endif + +#endif + +#if PLATFORM(WIN) && !OS(WINCE) +#define WTF_USE_CF 1 +#define WTF_USE_PTHREADS 0 +#endif + +#if PLATFORM(WIN) && !OS(WINCE) && !PLATFORM(CHROMIUM) && !PLATFORM(WIN_CAIRO) +#define WTF_USE_CFNETWORK 1 +#endif + +#if USE(CFNETWORK) || PLATFORM(MAC) || PLATFORM(IOS) +#define WTF_USE_CFURLCACHE 1 +#define WTF_USE_CFURLSTORAGESESSIONS 1 +#endif + +#if PLATFORM(WIN) && !OS(WINCE) && !PLATFORM(CHROMIUM) && !PLATFORM(QT) +#define ENABLE_WEB_ARCHIVE 1 +#endif + +#if PLATFORM(WIN) && !OS(WINCE) && !PLATFORM(CHROMIUM) && !PLATFORM(WIN_CAIRO) && !PLATFORM(QT) +#define ENABLE_FULLSCREEN_API 1 +#endif + +#if PLATFORM(WX) +#if !CPU(PPC) +#define ENABLE_ASSEMBLER 1 +#define ENABLE_JIT 1 +#endif +#define ENABLE_GLOBAL_FASTMALLOC_NEW 0 +#if OS(DARWIN) +#define WTF_USE_CF 1 +#define WTF_USE_CORE_TEXT 1 +#define ENABLE_WEB_ARCHIVE 1 +#endif +#endif + +#if PLATFORM(GTK) +#if HAVE(PTHREAD_H) +#define WTF_USE_PTHREADS 1 +#define HAVE_PTHREAD_RWLOCK 1 +#endif +#elif PLATFORM(QT) && OS(UNIX) +#define WTF_USE_PTHREADS 1 +#define HAVE_PTHREAD_RWLOCK 1 +#endif + +#if !defined(HAVE_ACCESSIBILITY) +#if PLATFORM(IOS) || PLATFORM(MAC) || PLATFORM(WIN) || PLATFORM(GTK) || PLATFORM(CHROMIUM) +#define HAVE_ACCESSIBILITY 1 +#endif +#endif /* !defined(HAVE_ACCESSIBILITY) */ + +#if OS(UNIX) +#define HAVE_SIGNAL_H 1 +#endif + +#if !defined(HAVE_VASPRINTF) +#if !COMPILER(MSVC) && !COMPILER(RVCT) && !COMPILER(MINGW) && !(COMPILER(GCC) && OS(QNX)) +#define HAVE_VASPRINTF 1 +#endif +#endif + +#if !defined(HAVE_STRNSTR) +#if OS(DARWIN) || (OS(FREEBSD) && !defined(__GLIBC__)) +#define HAVE_STRNSTR 1 +#endif +#endif + +#if !OS(WINDOWS) && !OS(SOLARIS) && !OS(QNX) \ + && !OS(RVCT) \ + && !OS(ANDROID) +#define HAVE_TM_GMTOFF 1 +#define HAVE_TM_ZONE 1 +#define HAVE_TIMEGM 1 +#endif + +#if OS(DARWIN) + +#define HAVE_ERRNO_H 1 +#define HAVE_LANGINFO_H 1 +#define HAVE_MMAP 1 +#define HAVE_MERGESORT 1 +#define HAVE_SBRK 1 +#define HAVE_STRINGS_H 1 +#define HAVE_SYS_PARAM_H 1 +#define HAVE_SYS_TIME_H 1 +#define HAVE_SYS_TIMEB_H 1 +#define WTF_USE_ACCELERATE 1 + +#ifndef TARGETING_LEOPARD + +#define HAVE_DISPATCH_H 1 +#define HAVE_HOSTED_CORE_ANIMATION 1 + +#if !PLATFORM(IOS) +#define HAVE_MADV_FREE_REUSE 1 +#define HAVE_MADV_FREE 1 +#define HAVE_PTHREAD_SETNAME_NP 1 +#endif + +#endif + +#if PLATFORM(IOS) +#define HAVE_MADV_FREE 1 +#define HAVE_PTHREAD_SETNAME_NP 1 +#endif + +#elif OS(WINDOWS) + +#if OS(WINCE) +#define HAVE_ERRNO_H 0 +#else +#define HAVE_SYS_TIMEB_H 1 +#define HAVE_ALIGNED_MALLOC 1 +#define HAVE_ISDEBUGGERPRESENT 1 +#endif +#define HAVE_VIRTUALALLOC 1 + +#elif OS(QNX) + +#define HAVE_ERRNO_H 1 +#define HAVE_MMAP 1 +#define HAVE_SBRK 1 +#define HAVE_STRINGS_H 1 +#define HAVE_SYS_PARAM_H 1 +#define HAVE_SYS_TIME_H 1 +#define WTF_USE_PTHREADS 1 + +#elif OS(ANDROID) + +#define HAVE_ERRNO_H 1 +#define HAVE_LANGINFO_H 0 +#define HAVE_NMAP 1 +#define HAVE_SBRK 1 +#define HAVE_STRINGS_H 1 +#define HAVE_SYS_PARAM_H 1 +#define HAVE_SYS_TIME_H 1 + +#else + +/* FIXME: is this actually used or do other platforms generate their own config.h? */ + +#define HAVE_ERRNO_H 1 +#define HAVE_LANGINFO_H 1 +#define HAVE_MMAP 1 +#define HAVE_SBRK 1 +#define HAVE_STRINGS_H 1 +#define HAVE_SYS_PARAM_H 1 +#define HAVE_SYS_TIME_H 1 + +#endif + +/* ENABLE macro defaults */ + +#if PLATFORM(QT) +/* We must not customize the global operator new and delete for the Qt port. */ +#define ENABLE_GLOBAL_FASTMALLOC_NEW 0 +#if !OS(UNIX) +#define USE_SYSTEM_MALLOC 1 +#endif +#endif + +/* fastMalloc match validation allows for runtime verification that + new is matched by delete, fastMalloc is matched by fastFree, etc. */ +#if !defined(ENABLE_FAST_MALLOC_MATCH_VALIDATION) +#define ENABLE_FAST_MALLOC_MATCH_VALIDATION 0 +#endif + +#if !defined(ENABLE_ICONDATABASE) +#define ENABLE_ICONDATABASE 1 +#endif + +#if !defined(ENABLE_SQL_DATABASE) +#define ENABLE_SQL_DATABASE 1 +#endif + +#if !defined(ENABLE_JAVASCRIPT_DEBUGGER) +#define ENABLE_JAVASCRIPT_DEBUGGER 1 +#endif + +#if !defined(ENABLE_FTPDIR) +#define ENABLE_FTPDIR 1 +#endif + +#if !defined(ENABLE_CONTEXT_MENUS) +#define ENABLE_CONTEXT_MENUS 1 +#endif + +#if !defined(ENABLE_DRAG_SUPPORT) +#define ENABLE_DRAG_SUPPORT 1 +#endif + +#if !defined(ENABLE_DATA_TRANSFER_ITEMS) +#define ENABLE_DATA_TRANSFER_ITEMS 0 +#endif + +#if !defined(ENABLE_DASHBOARD_SUPPORT) +#define ENABLE_DASHBOARD_SUPPORT 0 +#endif + +#if !defined(ENABLE_INSPECTOR) +#define ENABLE_INSPECTOR 1 +#endif + +#if !defined(ENABLE_JAVA_BRIDGE) +#define ENABLE_JAVA_BRIDGE 0 +#endif + +#if !defined(ENABLE_NETSCAPE_PLUGIN_API) +#define ENABLE_NETSCAPE_PLUGIN_API 1 +#endif + +#if !defined(ENABLE_NETSCAPE_PLUGIN_METADATA_CACHE) +#define ENABLE_NETSCAPE_PLUGIN_METADATA_CACHE 0 +#endif + +#if !defined(ENABLE_PURGEABLE_MEMORY) +#define ENABLE_PURGEABLE_MEMORY 0 +#endif + +#if !defined(WTF_USE_PLUGIN_HOST_PROCESS) +#define WTF_USE_PLUGIN_HOST_PROCESS 0 +#endif + +#if !defined(ENABLE_ORIENTATION_EVENTS) +#define ENABLE_ORIENTATION_EVENTS 0 +#endif + +#if !defined(ENABLE_OPCODE_STATS) +#define ENABLE_OPCODE_STATS 0 +#endif + +#if !defined(ENABLE_GLOBAL_FASTMALLOC_NEW) +#define ENABLE_GLOBAL_FASTMALLOC_NEW 1 +#endif + +#define ENABLE_DEBUG_WITH_BREAKPOINT 0 +#define ENABLE_SAMPLING_COUNTERS 0 +#define ENABLE_SAMPLING_FLAGS 0 +#define ENABLE_SAMPLING_REGIONS 0 +#define ENABLE_OPCODE_SAMPLING 0 +#define ENABLE_CODEBLOCK_SAMPLING 0 +#if ENABLE(CODEBLOCK_SAMPLING) && !ENABLE(OPCODE_SAMPLING) +#error "CODEBLOCK_SAMPLING requires OPCODE_SAMPLING" +#endif +#if ENABLE(OPCODE_SAMPLING) || ENABLE(SAMPLING_FLAGS) || ENABLE(SAMPLING_REGIONS) +#define ENABLE_SAMPLING_THREAD 1 +#endif + +#if !defined(ENABLE_GEOLOCATION) +#define ENABLE_GEOLOCATION 0 +#endif + +#if !defined(ENABLE_GESTURE_RECOGNIZER) +#define ENABLE_GESTURE_RECOGNIZER 0 +#endif + +#if !defined(ENABLE_VIEWPORT) +#define ENABLE_VIEWPORT 0 +#endif + +#if !defined(ENABLE_NOTIFICATIONS) +#define ENABLE_NOTIFICATIONS 0 +#endif + +#if PLATFORM(IOS) +#define ENABLE_TEXT_CARET 0 +#endif + +#if !defined(ENABLE_TEXT_CARET) +#define ENABLE_TEXT_CARET 1 +#endif + +#if !defined(ENABLE_FULLSCREEN_API) +#define ENABLE_FULLSCREEN_API 0 +#endif + +#if !defined(ENABLE_POINTER_LOCK) +#define ENABLE_POINTER_LOCK 0 +#endif + +#if !defined(WTF_USE_JSVALUE64) && !defined(WTF_USE_JSVALUE32_64) +#if (CPU(X86_64) && (OS(UNIX) || OS(WINDOWS))) \ + || (CPU(IA64) && !CPU(IA64_32)) \ + || CPU(ALPHA) \ + || CPU(SPARC64) \ + || CPU(S390X) \ + || CPU(PPC64) +#define WTF_USE_JSVALUE64 1 +#else +#define WTF_USE_JSVALUE32_64 1 +#endif +#endif /* !defined(WTF_USE_JSVALUE64) && !defined(WTF_USE_JSVALUE32_64) */ + +#if !defined(ENABLE_REPAINT_THROTTLING) +#define ENABLE_REPAINT_THROTTLING 0 +#endif + +/* Disable the JIT on versions of GCC prior to 4.1 */ +#if !defined(ENABLE_JIT) && COMPILER(GCC) && !GCC_VERSION_AT_LEAST(4, 1, 0) +#define ENABLE_JIT 0 +#endif + +/* JIT is not implemented for Windows 64-bit */ +#if !defined(ENABLE_JIT) && OS(WINDOWS) && CPU(X86_64) +#define ENABLE_JIT 0 +#endif + +/* The JIT is enabled by default on all x86, x64-64, ARM & MIPS platforms. */ +#if !defined(ENABLE_JIT) \ + && (CPU(X86) || CPU(X86_64) || CPU(ARM) || CPU(MIPS)) \ + && (OS(DARWIN) || !COMPILER(GCC) || GCC_VERSION_AT_LEAST(4, 1, 0)) \ + && !OS(WINCE) \ + && !OS(QNX) +#define ENABLE_JIT 1 +#endif + +#if !defined(ENABLE_DFG_JIT) && ENABLE(JIT) +/* Enable the DFG JIT on X86 and X86_64. Only tested on Mac and GNU/Linux. */ +#if (CPU(X86) || CPU(X86_64)) && (PLATFORM(MAC) || OS(LINUX)) +#define ENABLE_DFG_JIT 1 +#endif +/* Enable the DFG JIT on ARMv7. Only tested on iOS. */ +#if CPU(ARM_THUMB2) && PLATFORM(IOS) +#define ENABLE_DFG_JIT 1 +#endif +#endif + +/* Profiling of types and values used by JIT code. DFG_JIT depends on it, but you + can enable it manually with DFG turned off if you want to use it as a standalone + profiler. In that case, you probably want to also enable VERBOSE_VALUE_PROFILE + below. */ +#if !defined(ENABLE_VALUE_PROFILER) && ENABLE(DFG_JIT) +#define ENABLE_VALUE_PROFILER 1 +#endif + +#if !defined(ENABLE_VERBOSE_VALUE_PROFILE) && ENABLE(VALUE_PROFILER) +#define ENABLE_VERBOSE_VALUE_PROFILE 0 +#endif + +#if !defined(ENABLE_SIMPLE_HEAP_PROFILING) +#define ENABLE_SIMPLE_HEAP_PROFILING 0 +#endif + +/* Counts uses of write barriers using sampling counters. Be sure to also + set ENABLE_SAMPLING_COUNTERS to 1. */ +#if !defined(ENABLE_WRITE_BARRIER_PROFILING) +#define ENABLE_WRITE_BARRIER_PROFILING 0 +#endif + +/* Ensure that either the JIT or the interpreter has been enabled. */ +#if !defined(ENABLE_INTERPRETER) && !ENABLE(JIT) +#define ENABLE_INTERPRETER 1 +#endif +#if !(ENABLE(JIT) || ENABLE(INTERPRETER)) +#error You have to have at least one execution model enabled to build JSC +#endif + +#if CPU(SH4) && PLATFORM(QT) +#define ENABLE_JIT 1 +#endif + +/* Configure the JIT */ +#if CPU(ARM) +#if !defined(ENABLE_JIT_USE_SOFT_MODULO) && WTF_ARM_ARCH_AT_LEAST(5) +#define ENABLE_JIT_USE_SOFT_MODULO 1 +#endif +#endif + +#if CPU(X86) || CPU(X86_64) || CPU(MIPS) +#if !defined(ENABLE_JIT_USE_SOFT_MODULO) +#define ENABLE_JIT_USE_SOFT_MODULO 1 +#endif +#endif + +#if CPU(X86) && COMPILER(MSVC) +#define JSC_HOST_CALL __fastcall +#elif CPU(X86) && COMPILER(GCC) +#define JSC_HOST_CALL __attribute__ ((fastcall)) +#else +#define JSC_HOST_CALL +#endif + +/* Configure the interpreter */ +#if COMPILER(GCC) || (RVCT_VERSION_AT_LEAST(4, 0, 0, 0) && defined(__GNUC__)) +#define HAVE_COMPUTED_GOTO 1 +#endif +#if HAVE(COMPUTED_GOTO) && ENABLE(INTERPRETER) +#define ENABLE_COMPUTED_GOTO_INTERPRETER 1 +#endif + +/* Regular Expression Tracing - Set to 1 to trace RegExp's in jsc. Results dumped at exit */ +#define ENABLE_REGEXP_TRACING 0 + +/* Yet Another Regex Runtime - turned on by default for JIT enabled ports. */ +#if PLATFORM(CHROMIUM) +#define ENABLE_YARR_JIT 0 + +#elif ENABLE(JIT) && !defined(ENABLE_YARR_JIT) +#define ENABLE_YARR_JIT 1 + +/* Setting this flag compares JIT results with interpreter results. */ +#define ENABLE_YARR_JIT_DEBUG 0 +#endif + +#if ENABLE(JIT) || ENABLE(YARR_JIT) +#define ENABLE_ASSEMBLER 1 +#endif + +/* Pick which allocator to use; we only need an executable allocator if the assembler is compiled in. + On x86-64 we use a single fixed mmap, on other platforms we mmap on demand. */ +#if ENABLE(ASSEMBLER) +#if CPU(X86_64) || PLATFORM(IOS) +#define ENABLE_EXECUTABLE_ALLOCATOR_FIXED 1 +#else +#define ENABLE_EXECUTABLE_ALLOCATOR_DEMAND 1 +#endif +#endif + +#if !defined(ENABLE_PAN_SCROLLING) && OS(WINDOWS) +#define ENABLE_PAN_SCROLLING 1 +#endif + +#if !defined(ENABLE_SMOOTH_SCROLLING) +#define ENABLE_SMOOTH_SCROLLING 0 +#endif + +#if !defined(ENABLE_WEB_ARCHIVE) +#define ENABLE_WEB_ARCHIVE 0 +#endif + +/* Use the QXmlStreamReader implementation for XMLDocumentParser */ +/* Use the QXmlQuery implementation for XSLTProcessor */ +#if PLATFORM(QT) +#if !USE(LIBXML2) +#define WTF_USE_QXMLSTREAM 1 +#define WTF_USE_QXMLQUERY 1 +#endif +#endif + +#if PLATFORM(MAC) +/* Complex text framework */ +#ifndef BUILDING_ON_LEOPARD +#define WTF_USE_ATSUI 0 +#define WTF_USE_CORE_TEXT 1 +#else +#define WTF_USE_ATSUI 1 +#define WTF_USE_CORE_TEXT 0 +#endif +#endif + +/* Accelerated compositing */ +#if PLATFORM(MAC) || PLATFORM(IOS) || PLATFORM(QT) || (PLATFORM(WIN) && !OS(WINCE) && !PLATFORM(WIN_CAIRO)) || PLATFORM(EFL) +#define WTF_USE_ACCELERATED_COMPOSITING 1 +#endif + +#if (PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD)) || PLATFORM(IOS) +#define WTF_USE_PROTECTION_SPACE_AUTH_CALLBACK 1 +#endif + +#if !ENABLE(NETSCAPE_PLUGIN_API) || (ENABLE(NETSCAPE_PLUGIN_API) && ((OS(UNIX) && (PLATFORM(QT) || PLATFORM(WX))) || PLATFORM(GTK) || PLATFORM(EFL))) +#define ENABLE_PLUGIN_PACKAGE_SIMPLE_HASH 1 +#endif + +#if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) && !defined(BUILDING_ON_LION) +#define ENABLE_THREADED_SCROLLING 1 +#endif + +/* Set up a define for a common error that is intended to cause a build error -- thus the space after Error. */ +#define WTF_PLATFORM_CFNETWORK Error USE_macro_should_be_used_with_CFNETWORK + +/* FIXME: Eventually we should enable this for all platforms and get rid of the define. */ +#if PLATFORM(IOS) || PLATFORM(MAC) || PLATFORM(WIN) || PLATFORM(QT) +#define WTF_USE_PLATFORM_STRATEGIES 1 +#endif + +#if PLATFORM(WIN) +#define WTF_USE_CROSS_PLATFORM_CONTEXT_MENUS 1 +#endif + +/* Geolocation request policy. pre-emptive policy is to acquire user permission before acquiring location. + Client based implementations will have option to choose between pre-emptive and nonpre-emptive permission policy. + pre-emptive permission policy is enabled by default for all client-based implementations. */ +#if ENABLE(CLIENT_BASED_GEOLOCATION) +#define WTF_USE_PREEMPT_GEOLOCATION_PERMISSION 1 +#endif + +#if CPU(ARM_THUMB2) +#define ENABLE_BRANCH_COMPACTION 1 +#endif + +#if !defined(ENABLE_THREADING_LIBDISPATCH) && HAVE(DISPATCH_H) +#define ENABLE_THREADING_LIBDISPATCH 1 +#elif !defined(ENABLE_THREADING_OPENMP) && defined(_OPENMP) +#define ENABLE_THREADING_OPENMP 1 +#elif !defined(THREADING_GENERIC) +#define ENABLE_THREADING_GENERIC 1 +#endif + +#if ENABLE(GLIB_SUPPORT) +#include "GTypedefs.h" +#endif + +/* FIXME: This define won't be needed once #27551 is fully landed. However, + since most ports try to support sub-project independence, adding new headers + to WTF causes many ports to break, and so this way we can address the build + breakages one port at a time. */ +#define WTF_USE_EXPORT_MACROS 0 + +#if (PLATFORM(QT) && !OS(DARWIN)) || PLATFORM(GTK) || PLATFORM(EFL) +#define WTF_USE_UNIX_DOMAIN_SOCKETS 1 +#endif + +#if !defined(ENABLE_COMPARE_AND_SWAP) && COMPILER(GCC) && (CPU(X86) || CPU(X86_64) || CPU(ARM_THUMB2)) +#define ENABLE_COMPARE_AND_SWAP 1 +#endif + +#if !defined(ENABLE_PARALLEL_GC) && (PLATFORM(MAC) || PLATFORM(IOS)) && ENABLE(COMPARE_AND_SWAP) +#define ENABLE_PARALLEL_GC 1 +#endif + +#ifndef NDEBUG +#ifndef ENABLE_GC_VALIDATION +#define ENABLE_GC_VALIDATION 1 +#endif +#endif + +#if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) +#define WTF_USE_AVFOUNDATION 1 +#endif + +#if PLATFORM(MAC) || PLATFORM(GTK) || PLATFORM(EFL) || (PLATFORM(WIN) && !OS(WINCE) && !PLATFORM(WIN_CAIRO)) || PLATFORM(QT) +#define WTF_USE_REQUEST_ANIMATION_FRAME_TIMER 1 +#endif + +#if PLATFORM(MAC) +#define WTF_USE_REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR 1 +#endif + +#if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) +#define HAVE_INVERTED_WHEEL_EVENTS 1 +#endif + +#if PLATFORM(MAC) +#define WTF_USE_COREAUDIO 1 +#endif + +#if PLATFORM(CHROMIUM) +#if !defined(WTF_USE_V8) +#define WTF_USE_V8 1 +#endif +#endif /* PLATFORM(CHROMIUM) */ + +#if !defined(WTF_USE_V8) +#define WTF_USE_V8 0 +#endif /* !defined(WTF_USE_V8) */ + +/* Using V8 implies not using JSC and vice versa */ +#define WTF_USE_JSC !WTF_USE_V8 + +#if ENABLE(NOTIFICATIONS) && PLATFORM(MAC) +#define ENABLE_TEXT_NOTIFICATIONS_ONLY 1 +#endif + +#endif /* WTF_Platform_h */ diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PossiblyNull.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PossiblyNull.h new file mode 100644 index 000000000..79c4d8200 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PossiblyNull.h @@ -0,0 +1,59 @@ +/* + * 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 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 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 PossiblyNull_h +#define PossiblyNull_h + +#include "Assertions.h" + +namespace WTF { + +template struct PossiblyNull { + PossiblyNull(T data) + : m_data(data) + { + } + PossiblyNull(const PossiblyNull& source) + : m_data(source.m_data) + { + source.m_data = 0; + } + ~PossiblyNull() { ASSERT(!m_data); } + bool getValue(T& out) WARN_UNUSED_RETURN; +private: + mutable T m_data; +}; + +template bool PossiblyNull::getValue(T& out) +{ + out = m_data; + bool result = !!m_data; + m_data = 0; + return result; +} + +} + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PredictedType.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PredictedType.h new file mode 100644 index 000000000..47583361d --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PredictedType.h @@ -0,0 +1,249 @@ +/* + * Copyright (C) 2011 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 PredictedType_h +#define PredictedType_h + +#include "JSValue.h" + +namespace JSC { + +class Structure; + +typedef uint32_t PredictedType; +static const PredictedType PredictNone = 0x00000000; // We don't know anything yet. +static const PredictedType PredictFinalObject = 0x00000001; // It's definitely a JSFinalObject. +static const PredictedType PredictArray = 0x00000002; // It's definitely a JSArray. +static const PredictedType PredictByteArray = 0x00000004; // It's definitely a JSByteArray or one of its subclasses. +static const PredictedType PredictFunction = 0x00000008; // It's definitely a JSFunction or one of its subclasses. +static const PredictedType PredictInt8Array = 0x00000010; // It's definitely an Int8Array or one of its subclasses. +static const PredictedType PredictInt16Array = 0x00000020; // It's definitely an Int16Array or one of its subclasses. +static const PredictedType PredictInt32Array = 0x00000040; // It's definitely an Int32Array or one of its subclasses. +static const PredictedType PredictUint8Array = 0x00000080; // It's definitely an Uint8Array or one of its subclasses. +static const PredictedType PredictUint8ClampedArray = 0x00000100; // It's definitely an Uint8ClampedArray or one of its subclasses. +static const PredictedType PredictUint16Array = 0x00000200; // It's definitely an Uint16Array or one of its subclasses. +static const PredictedType PredictUint32Array = 0x00000400; // It's definitely an Uint32Array or one of its subclasses. +static const PredictedType PredictFloat32Array = 0x00000800; // It's definitely an Uint16Array or one of its subclasses. +static const PredictedType PredictFloat64Array = 0x00001000; // It's definitely an Uint16Array or one of its subclasses. +static const PredictedType PredictObjectOther = 0x00002000; // It's definitely an object but not JSFinalObject, JSArray, JSByteArray, or JSFunction. +static const PredictedType PredictObjectMask = 0x00003fff; // Bitmask used for testing for any kind of object prediction. +static const PredictedType PredictString = 0x00004000; // It's definitely a JSString. +static const PredictedType PredictCellOther = 0x00008000; // It's definitely a JSCell but not a subclass of JSObject and definitely not a JSString. +static const PredictedType PredictCell = 0x0000ffff; // It's definitely a JSCell. +static const PredictedType PredictInt32 = 0x00010000; // It's definitely an Int32. +static const PredictedType PredictDoubleReal = 0x00020000; // It's definitely a non-NaN double. +static const PredictedType PredictDoubleNaN = 0x00040000; // It's definitely a NaN. +static const PredictedType PredictDouble = 0x00060000; // It's either a non-NaN or a NaN double. +static const PredictedType PredictNumber = 0x00070000; // It's either an Int32 or a Double. +static const PredictedType PredictBoolean = 0x00080000; // It's definitely a Boolean. +static const PredictedType PredictOther = 0x40000000; // It's definitely none of the above. +static const PredictedType PredictTop = 0x7fffffff; // It can be any of the above. +static const PredictedType FixedIndexedStorageMask = PredictByteArray | PredictInt8Array | PredictInt16Array | PredictInt32Array | PredictUint8Array | PredictUint8ClampedArray | PredictUint16Array | PredictUint32Array | PredictFloat32Array | PredictFloat64Array; + +typedef bool (*PredictionChecker)(PredictedType); + +inline bool isCellPrediction(PredictedType value) +{ + return !!(value & PredictCell) && !(value & ~PredictCell); +} + +inline bool isObjectPrediction(PredictedType value) +{ + return !!(value & PredictObjectMask) && !(value & ~PredictObjectMask); +} + +inline bool isFinalObjectPrediction(PredictedType value) +{ + return value == PredictFinalObject; +} + +inline bool isFinalObjectOrOtherPrediction(PredictedType value) +{ + return !!(value & (PredictFinalObject | PredictOther)) && !(value & ~(PredictFinalObject | PredictOther)); +} + +inline bool isFixedIndexedStorageObjectPrediction(PredictedType value) +{ + return (value & FixedIndexedStorageMask) == value; +} + +inline bool isStringPrediction(PredictedType value) +{ + return value == PredictString; +} + +inline bool isArrayPrediction(PredictedType value) +{ + return value == PredictArray; +} + +inline bool isFunctionPrediction(PredictedType value) +{ + return value == PredictFunction; +} + +inline bool isByteArrayPrediction(PredictedType value) +{ + return value == PredictByteArray; +} + +inline bool isInt8ArrayPrediction(PredictedType value) +{ + return value == PredictInt8Array; +} + +inline bool isInt16ArrayPrediction(PredictedType value) +{ + return value == PredictInt16Array; +} + +inline bool isInt32ArrayPrediction(PredictedType value) +{ + return value == PredictInt32Array; +} + +inline bool isUint8ArrayPrediction(PredictedType value) +{ + return value == PredictUint8Array; +} + +inline bool isUint8ClampedArrayPrediction(PredictedType value) +{ + return value == PredictUint8ClampedArray; +} + +inline bool isUint16ArrayPrediction(PredictedType value) +{ + return value == PredictUint16Array; +} + +inline bool isUint32ArrayPrediction(PredictedType value) +{ + return value == PredictUint32Array; +} + +inline bool isFloat32ArrayPrediction(PredictedType value) +{ + return value == PredictFloat32Array; +} + +inline bool isFloat64ArrayPrediction(PredictedType value) +{ + return value == PredictFloat64Array; +} + +inline bool isActionableMutableArrayPrediction(PredictedType value) +{ + return isArrayPrediction(value) + || isByteArrayPrediction(value) +#if CPU(X86) || CPU(X86_64) + || isInt8ArrayPrediction(value) + || isInt16ArrayPrediction(value) +#endif + || isInt32ArrayPrediction(value) + || isUint8ArrayPrediction(value) + || isUint8ClampedArrayPrediction(value) + || isUint16ArrayPrediction(value) + || isUint32ArrayPrediction(value) +#if CPU(X86) || CPU(X86_64) + || isFloat32ArrayPrediction(value) +#endif + || isFloat64ArrayPrediction(value); +} + +inline bool isActionableArrayPrediction(PredictedType value) +{ + return isStringPrediction(value) + || isActionableMutableArrayPrediction(value); +} + +inline bool isArrayOrOtherPrediction(PredictedType value) +{ + return !!(value & (PredictArray | PredictOther)) && !(value & ~(PredictArray | PredictOther)); +} + +inline bool isInt32Prediction(PredictedType value) +{ + return value == PredictInt32; +} + +inline bool isDoubleRealPrediction(PredictedType value) +{ + return value == PredictDoubleReal; +} + +inline bool isDoublePrediction(PredictedType value) +{ + return (value & PredictDouble) == value; +} + +inline bool isNumberPrediction(PredictedType value) +{ + return !!(value & PredictNumber) && !(value & ~PredictNumber); +} + +inline bool isBooleanPrediction(PredictedType value) +{ + return value == PredictBoolean; +} + +inline bool isOtherPrediction(PredictedType value) +{ + return value == PredictOther; +} + +#ifndef NDEBUG +const char* predictionToString(PredictedType value); +#endif + +// Merge two predictions. Note that currently this just does left | right. It may +// seem tempting to do so directly, but you would be doing so at your own peril, +// since the merging protocol PredictedType may change at any time (and has already +// changed several times in its history). +inline PredictedType mergePredictions(PredictedType left, PredictedType right) +{ + return left | right; +} + +template +inline bool mergePrediction(T& left, PredictedType right) +{ + PredictedType newPrediction = static_cast(mergePredictions(static_cast(left), right)); + bool result = newPrediction != static_cast(left); + left = newPrediction; + return result; +} + +PredictedType predictionFromClassInfo(const ClassInfo*); +PredictedType predictionFromStructure(Structure*); +PredictedType predictionFromCell(JSCell*); +PredictedType predictionFromValue(JSValue); + +} // namespace JSC + +#endif // PredictedType_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PredictionTracker.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PredictionTracker.h new file mode 100644 index 000000000..7551cd3f3 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PredictionTracker.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2011 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 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 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 PredictionTracker_h +#define PredictionTracker_h + +#include "PredictedType.h" +#include + +namespace JSC { + +struct PredictionSlot { +public: + PredictionSlot() + : m_value(PredictNone) + { + } + PredictedType m_value; +}; + +class PredictionTracker { +public: + PredictionTracker() + { + } + + bool predictGlobalVar(unsigned varNumber, PredictedType prediction) + { + HashMap::iterator iter = m_globalVars.find(varNumber + 1); + if (iter == m_globalVars.end()) { + PredictionSlot predictionSlot; + bool result = mergePrediction(predictionSlot.m_value, prediction); + m_globalVars.add(varNumber + 1, predictionSlot); + return result; + } + return mergePrediction(iter->second.m_value, prediction); + } + + PredictedType getGlobalVarPrediction(unsigned varNumber) + { + HashMap::iterator iter = m_globalVars.find(varNumber + 1); + if (iter == m_globalVars.end()) + return PredictNone; + return iter->second.m_value; + } + +private: + HashMap m_globalVars; +}; + +} // namespace JSC + +#endif // PredictionTracker_h + diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Profile.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Profile.h new file mode 100644 index 000000000..9455e3595 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Profile.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 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 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 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 Profile_h +#define Profile_h + +#include "ProfileNode.h" +#include +#include +#include + +namespace JSC { + + class Profile : public RefCounted { + public: + static PassRefPtr create(const UString& title, unsigned uid); + virtual ~Profile(); + + const UString& title() const { return m_title; } + ProfileNode* head() const { return m_head.get(); } + void setHead(PassRefPtr head) { m_head = head; } + double totalTime() const { return m_head->totalTime(); } + unsigned int uid() const { return m_uid; } + + JS_EXPORT_PRIVATE void forEach(void (ProfileNode::*)()); + + JS_EXPORT_PRIVATE void focus(const ProfileNode*); + JS_EXPORT_PRIVATE void exclude(const ProfileNode*); + JS_EXPORT_PRIVATE void restoreAll(); + +#ifndef NDEBUG + void debugPrintData() const; + void debugPrintDataSampleStyle() const; +#endif + + protected: + Profile(const UString& title, unsigned uid); + + private: + void removeProfileStart(); + void removeProfileEnd(); + + UString m_title; + RefPtr m_head; + unsigned int m_uid; + }; + +} // namespace JSC + +#endif // Profile_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ProfileNode.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ProfileNode.h new file mode 100644 index 000000000..ffe7b6f9d --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ProfileNode.h @@ -0,0 +1,172 @@ +/* + * Copyright (C) 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. + * 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 ProfileNode_h +#define ProfileNode_h + +#include "CallIdentifier.h" +#include +#include +#include +#include + +namespace JSC { + + class ExecState; + class ProfileNode; + + typedef Vector >::const_iterator StackIterator; + typedef HashCountedSet FunctionCallHashCount; + + class ProfileNode : public RefCounted { + public: + static PassRefPtr create(ExecState* callerCallFrame, const CallIdentifier& callIdentifier, ProfileNode* headNode, ProfileNode* parentNode) + { + return adoptRef(new ProfileNode(callerCallFrame, callIdentifier, headNode, parentNode)); + } + static PassRefPtr create(ExecState* callerCallFrame, ProfileNode* headNode, ProfileNode* node) + { + return adoptRef(new ProfileNode(callerCallFrame, headNode, node)); + } + + bool operator==(ProfileNode* node) { return m_callIdentifier == node->callIdentifier(); } + + ProfileNode* willExecute(ExecState* callerCallFrame, const CallIdentifier&); + ProfileNode* didExecute(); + + void stopProfiling(); + + // CallIdentifier members + ExecState* callerCallFrame() const { return m_callerCallFrame; } + const CallIdentifier& callIdentifier() const { return m_callIdentifier; } + const UString& functionName() const { return m_callIdentifier.m_name; } + const UString& url() const { return m_callIdentifier.m_url; } + unsigned lineNumber() const { return m_callIdentifier.m_lineNumber; } + + // Relationships + ProfileNode* head() const { return m_head; } + void setHead(ProfileNode* head) { m_head = head; } + ProfileNode* parent() const { return m_parent; } + void setParent(ProfileNode* parent) { m_parent = parent; } + ProfileNode* nextSibling() const { return m_nextSibling; } + void setNextSibling(ProfileNode* nextSibling) { m_nextSibling = nextSibling; } + + // Time members + double startTime() const { return m_startTime; } + void setStartTime(double startTime) { m_startTime = startTime; } + double totalTime() const { return m_visibleTotalTime; } + double actualTotalTime() const { return m_actualTotalTime; } + void setTotalTime(double time) { m_actualTotalTime = time; m_visibleTotalTime = time; } + void setActualTotalTime(double time) { m_actualTotalTime = time; } + void setVisibleTotalTime(double time) { m_visibleTotalTime = time; } + double selfTime() const { return m_visibleSelfTime; } + double actualSelfTime() const { return m_actualSelfTime; } + void setSelfTime(double time) {m_actualSelfTime = time; m_visibleSelfTime = time; } + void setActualSelfTime(double time) { m_actualSelfTime = time; } + void setVisibleSelfTime(double time) { m_visibleSelfTime = time; } + + double totalPercent() const { return (m_visibleTotalTime / (m_head ? m_head->totalTime() : totalTime())) * 100.0; } + double selfPercent() const { return (m_visibleSelfTime / (m_head ? m_head->totalTime() : totalTime())) * 100.0; } + + unsigned numberOfCalls() const { return m_numberOfCalls; } + void setNumberOfCalls(unsigned number) { m_numberOfCalls = number; } + + // Children members + const Vector >& children() const { return m_children; } + ProfileNode* firstChild() const { return m_children.size() ? m_children.first().get() : 0; } + ProfileNode* lastChild() const { return m_children.size() ? m_children.last().get() : 0; } + ProfileNode* findChild(ProfileNode*) const; + void removeChild(ProfileNode*); + void addChild(PassRefPtr prpChild); + void insertNode(PassRefPtr prpNode); + + // Visiblity + bool visible() const { return m_visible; } + void setVisible(bool visible) { m_visible = visible; } + + static void setTreeVisible(ProfileNode*, bool visible); + + // Sorting + ProfileNode* traverseNextNodePostOrder() const; + ProfileNode* traverseNextNodePreOrder(bool processChildren = true) const; + + // Views + void calculateVisibleTotalTime(); + bool focus(const CallIdentifier&); + void exclude(const CallIdentifier&); + void restore(); + + void endAndRecordCall(); + +#ifndef NDEBUG + const char* c_str() const { return m_callIdentifier; } + void debugPrintData(int indentLevel) const; + double debugPrintDataSampleStyle(int indentLevel, FunctionCallHashCount&) const; +#endif + + private: + ProfileNode(ExecState* callerCallFrame, const CallIdentifier&, ProfileNode* headNode, ProfileNode* parentNode); + ProfileNode(ExecState* callerCallFrame, ProfileNode* headNode, ProfileNode* nodeToCopy); + + void startTimer(); + void resetChildrensSiblings(); + + RefPtr* childrenBegin() { return m_children.begin(); } + RefPtr* childrenEnd() { return m_children.end(); } + + // Sorting comparators + static inline bool totalTimeDescendingComparator(const RefPtr& a, const RefPtr& b) { return a->totalTime() > b->totalTime(); } + static inline bool totalTimeAscendingComparator(const RefPtr& a, const RefPtr& b) { return a->totalTime() < b->totalTime(); } + static inline bool selfTimeDescendingComparator(const RefPtr& a, const RefPtr& b) { return a->selfTime() > b->selfTime(); } + static inline bool selfTimeAscendingComparator(const RefPtr& a, const RefPtr& b) { return a->selfTime() < b->selfTime(); } + static inline bool callsDescendingComparator(const RefPtr& a, const RefPtr& b) { return a->numberOfCalls() > b->numberOfCalls(); } + static inline bool callsAscendingComparator(const RefPtr& a, const RefPtr& b) { return a->numberOfCalls() < b->numberOfCalls(); } + static inline bool functionNameDescendingComparator(const RefPtr& a, const RefPtr& b) { return a->functionName() > b->functionName(); } + static inline bool functionNameAscendingComparator(const RefPtr& a, const RefPtr& b) { return a->functionName() < b->functionName(); } + + ExecState* m_callerCallFrame; + CallIdentifier m_callIdentifier; + ProfileNode* m_head; + ProfileNode* m_parent; + ProfileNode* m_nextSibling; + + double m_startTime; + double m_actualTotalTime; + double m_visibleTotalTime; + double m_actualSelfTime; + double m_visibleSelfTime; + unsigned m_numberOfCalls; + + bool m_visible; + + Vector > m_children; + }; + +} // namespace JSC + +#endif // ProfileNode_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Profiler.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Profiler.h new file mode 100644 index 000000000..45f91af44 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Profiler.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 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. + * 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 Profiler_h +#define Profiler_h + +#include "Profile.h" +#include +#include +#include + +namespace JSC { + + class ExecState; + class JSGlobalData; + class JSGlobalObject; + class JSObject; + class JSValue; + class ProfileGenerator; + class UString; + struct CallIdentifier; + + class Profiler { + WTF_MAKE_FAST_ALLOCATED; + public: + static Profiler** enabledProfilerReference() + { + return &s_sharedEnabledProfilerReference; + } + + JS_EXPORT_PRIVATE static Profiler* profiler(); + static CallIdentifier createCallIdentifier(ExecState* exec, JSValue, const UString& sourceURL, int lineNumber); + + JS_EXPORT_PRIVATE void startProfiling(ExecState*, const UString& title); + JS_EXPORT_PRIVATE PassRefPtr stopProfiling(ExecState*, const UString& title); + void stopProfiling(JSGlobalObject*); + + void willExecute(ExecState* callerCallFrame, JSValue function); + void willExecute(ExecState* callerCallFrame, const UString& sourceURL, int startingLineNumber); + void didExecute(ExecState* callerCallFrame, JSValue function); + void didExecute(ExecState* callerCallFrame, const UString& sourceURL, int startingLineNumber); + + void exceptionUnwind(ExecState* handlerCallFrame); + + const Vector >& currentProfiles() { return m_currentProfiles; }; + + private: + Vector > m_currentProfiles; + static Profiler* s_sharedProfiler; + static Profiler* s_sharedEnabledProfilerReference; + }; + +} // namespace JSC + +#endif // Profiler_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PropertyDescriptor.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PropertyDescriptor.h new file mode 100644 index 000000000..98af02e66 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PropertyDescriptor.h @@ -0,0 +1,89 @@ +/* + * 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 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 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 PropertyDescriptor_h +#define PropertyDescriptor_h + +#include "JSValue.h" + +namespace JSC { + class GetterSetter; + + // See ES5.1 9.12 + bool sameValue(ExecState*, JSValue, JSValue); + + class PropertyDescriptor { + public: + PropertyDescriptor() + : m_attributes(defaultAttributes) + , m_seenAttributes(0) + { + } + JS_EXPORT_PRIVATE bool writable() const; + JS_EXPORT_PRIVATE bool enumerable() const; + JS_EXPORT_PRIVATE bool configurable() const; + JS_EXPORT_PRIVATE bool isDataDescriptor() const; + bool isGenericDescriptor() const; + JS_EXPORT_PRIVATE bool isAccessorDescriptor() const; + unsigned attributes() const { return m_attributes; } + JSValue value() const { return m_value; } + JS_EXPORT_PRIVATE JSValue getter() const; + JS_EXPORT_PRIVATE JSValue setter() const; + JSObject* getterObject() const; + JSObject* setterObject() const; + JS_EXPORT_PRIVATE void setUndefined(); + JS_EXPORT_PRIVATE void setDescriptor(JSValue value, unsigned attributes); + void setAccessorDescriptor(GetterSetter* accessor, unsigned attributes); + JS_EXPORT_PRIVATE void setWritable(bool); + JS_EXPORT_PRIVATE void setEnumerable(bool); + JS_EXPORT_PRIVATE void setConfigurable(bool); + void setValue(JSValue value) { m_value = value; } + JS_EXPORT_PRIVATE void setSetter(JSValue); + JS_EXPORT_PRIVATE void setGetter(JSValue); + bool isEmpty() const { return !(m_value || m_getter || m_setter || m_seenAttributes); } + bool writablePresent() const { return m_seenAttributes & WritablePresent; } + bool enumerablePresent() const { return m_seenAttributes & EnumerablePresent; } + bool configurablePresent() const { return m_seenAttributes & ConfigurablePresent; } + bool setterPresent() const { return m_setter; } + bool getterPresent() const { return m_getter; } + bool equalTo(ExecState* exec, const PropertyDescriptor& other) const; + bool attributesEqual(const PropertyDescriptor& other) const; + unsigned attributesWithOverride(const PropertyDescriptor& other) const; + unsigned attributesOverridingCurrent(const PropertyDescriptor& current) const; + + private: + JS_EXPORTDATA static unsigned defaultAttributes; + bool operator==(const PropertyDescriptor&){ return false; } + enum { WritablePresent = 1, EnumerablePresent = 2, ConfigurablePresent = 4}; + // May be a getter/setter + JSValue m_value; + JSValue m_getter; + JSValue m_setter; + unsigned m_attributes; + unsigned m_seenAttributes; + }; +} + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PropertyMapHashTable.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PropertyMapHashTable.h new file mode 100644 index 000000000..7c8cabb7b --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PropertyMapHashTable.h @@ -0,0 +1,591 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef PropertyMapHashTable_h +#define PropertyMapHashTable_h + +#include "UString.h" +#include "WriteBarrier.h" +#include +#include +#include + + +#ifndef NDEBUG +#define DUMP_PROPERTYMAP_STATS 0 +#else +#define DUMP_PROPERTYMAP_STATS 0 +#endif + +#if DUMP_PROPERTYMAP_STATS + +extern int numProbes; +extern int numCollisions; +extern int numRehashes; +extern int numRemoves; + +#endif + +#define PROPERTY_MAP_DELETED_ENTRY_KEY ((StringImpl*)1) + +namespace JSC { + +inline bool isPowerOf2(unsigned v) +{ + // Taken from http://www.cs.utk.edu/~vose/c-stuff/bithacks.html + + return !(v & (v - 1)) && v; +} + +inline unsigned nextPowerOf2(unsigned v) +{ + // Taken from http://www.cs.utk.edu/~vose/c-stuff/bithacks.html + // Devised by Sean Anderson, Sepember 14, 2001 + + v--; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + v++; + + return v; +} + +struct PropertyMapEntry { + StringImpl* key; + unsigned offset; + unsigned attributes; + WriteBarrier specificValue; + + PropertyMapEntry(JSGlobalData& globalData, JSCell* owner, StringImpl* key, unsigned offset, unsigned attributes, JSCell* specificValue) + : key(key) + , offset(offset) + , attributes(attributes) + , specificValue(globalData, owner, specificValue, WriteBarrier::MayBeNull) + { + } +}; + +class PropertyTable { + WTF_MAKE_FAST_ALLOCATED; + + // This is the implementation for 'iterator' and 'const_iterator', + // used for iterating over the table in insertion order. + template + class ordered_iterator { + public: + ordered_iterator& operator++() + { + m_valuePtr = skipDeletedEntries(m_valuePtr + 1); + return *this; + } + + bool operator==(const ordered_iterator& other) + { + return m_valuePtr == other.m_valuePtr; + } + + bool operator!=(const ordered_iterator& other) + { + return m_valuePtr != other.m_valuePtr; + } + + T& operator*() + { + return *m_valuePtr; + } + + T* operator->() + { + return m_valuePtr; + } + + ordered_iterator(T* valuePtr) + : m_valuePtr(valuePtr) + { + } + + private: + T* m_valuePtr; + }; + +public: + typedef StringImpl* KeyType; + typedef PropertyMapEntry ValueType; + + // The in order iterator provides overloaded * and -> to access the Value at the current position. + typedef ordered_iterator iterator; + typedef ordered_iterator const_iterator; + + // The find_iterator is a pair of a pointer to a Value* an the entry in the index. + // If 'find' does not find an entry then iter.first will be 0, and iter.second will + // give the point in m_index where an entry should be inserted. + typedef std::pair find_iterator; + + // Constructor is passed an initial capacity, a PropertyTable to copy, or both. + explicit PropertyTable(unsigned initialCapacity); + PropertyTable(JSGlobalData&, JSCell*, const PropertyTable&); + PropertyTable(JSGlobalData&, JSCell*, unsigned initialCapacity, const PropertyTable&); + ~PropertyTable(); + + // Ordered iteration methods. + iterator begin(); + iterator end(); + const_iterator begin() const; + const_iterator end() const; + + // Find a value in the table. + find_iterator find(const KeyType&); + find_iterator findWithString(const KeyType&); + // Add a value to the table + std::pair add(const ValueType& entry); + // Remove a value from the table. + void remove(const find_iterator& iter); + void remove(const KeyType& key); + + // Returns the number of values in the hashtable. + unsigned size() const; + + // Checks if there are any values in the hashtable. + bool isEmpty() const; + + // Number of slots in the property storage array in use, included deletedOffsets. + unsigned propertyStorageSize() const; + + // Used to maintain a list of unused entries in the property storage. + void clearDeletedOffsets(); + bool hasDeletedOffset(); + unsigned getDeletedOffset(); + void addDeletedOffset(unsigned offset); + + // Copy this PropertyTable, ensuring the copy has at least the capacity provided. + PassOwnPtr copy(JSGlobalData&, JSCell* owner, unsigned newCapacity); + +#ifndef NDEBUG + size_t sizeInMemory(); + void checkConsistency(); +#endif + +private: + PropertyTable(const PropertyTable&); + // Used to insert a value known not to be in the table, and where we know capacity to be available. + void reinsert(const ValueType& entry); + + // Rehash the table. Used to grow, or to recover deleted slots. + void rehash(unsigned newCapacity); + + // The capacity of the table of values is half of the size of the index. + unsigned tableCapacity() const; + + // We keep an extra deleted slot after the array to make iteration work, + // and to use for deleted values. Index values into the array are 1-based, + // so this is tableCapacity() + 1. + // For example, if m_tableSize is 16, then tableCapacity() is 8 - but the + // values array is actually 9 long (the 9th used for the deleted value/ + // iteration guard). The 8 valid entries are numbered 1..8, so the + // deleted index is 9 (0 being reserved for empty). + unsigned deletedEntryIndex() const; + + // Used in iterator creation/progression. + template + static T* skipDeletedEntries(T* valuePtr); + + // The table of values lies after the hash index. + ValueType* table(); + const ValueType* table() const; + + // total number of used entries in the values array - by either valid entries, or deleted ones. + unsigned usedCount() const; + + // The size in bytes of data needed for by the table. + size_t dataSize(); + + // Calculates the appropriate table size (rounds up to a power of two). + static unsigned sizeForCapacity(unsigned capacity); + + // Check if capacity is available. + bool canInsert(); + + unsigned m_indexSize; + unsigned m_indexMask; + unsigned* m_index; + unsigned m_keyCount; + unsigned m_deletedCount; + OwnPtr< Vector > m_deletedOffsets; + + static const unsigned MinimumTableSize = 16; + static const unsigned EmptyEntryIndex = 0; +}; + +inline PropertyTable::PropertyTable(unsigned initialCapacity) + : m_indexSize(sizeForCapacity(initialCapacity)) + , m_indexMask(m_indexSize - 1) + , m_index(static_cast(fastZeroedMalloc(dataSize()))) + , m_keyCount(0) + , m_deletedCount(0) +{ + ASSERT(isPowerOf2(m_indexSize)); +} + +inline PropertyTable::PropertyTable(JSGlobalData&, JSCell* owner, const PropertyTable& other) + : m_indexSize(other.m_indexSize) + , m_indexMask(other.m_indexMask) + , m_index(static_cast(fastMalloc(dataSize()))) + , m_keyCount(other.m_keyCount) + , m_deletedCount(other.m_deletedCount) +{ + ASSERT(isPowerOf2(m_indexSize)); + + memcpy(m_index, other.m_index, dataSize()); + + iterator end = this->end(); + for (iterator iter = begin(); iter != end; ++iter) { + iter->key->ref(); + Heap::writeBarrier(owner, iter->specificValue.get()); + } + + // Copy the m_deletedOffsets vector. + Vector* otherDeletedOffsets = other.m_deletedOffsets.get(); + if (otherDeletedOffsets) + m_deletedOffsets = adoptPtr(new Vector(*otherDeletedOffsets)); +} + +inline PropertyTable::PropertyTable(JSGlobalData&, JSCell* owner, unsigned initialCapacity, const PropertyTable& other) + : m_indexSize(sizeForCapacity(initialCapacity)) + , m_indexMask(m_indexSize - 1) + , m_index(static_cast(fastZeroedMalloc(dataSize()))) + , m_keyCount(0) + , m_deletedCount(0) +{ + ASSERT(isPowerOf2(m_indexSize)); + ASSERT(initialCapacity >= other.m_keyCount); + + const_iterator end = other.end(); + for (const_iterator iter = other.begin(); iter != end; ++iter) { + ASSERT(canInsert()); + reinsert(*iter); + iter->key->ref(); + Heap::writeBarrier(owner, iter->specificValue.get()); + } + + // Copy the m_deletedOffsets vector. + Vector* otherDeletedOffsets = other.m_deletedOffsets.get(); + if (otherDeletedOffsets) + m_deletedOffsets = adoptPtr(new Vector(*otherDeletedOffsets)); +} + +inline PropertyTable::~PropertyTable() +{ + iterator end = this->end(); + for (iterator iter = begin(); iter != end; ++iter) + iter->key->deref(); + + fastFree(m_index); +} + +inline PropertyTable::iterator PropertyTable::begin() +{ + return iterator(skipDeletedEntries(table())); +} + +inline PropertyTable::iterator PropertyTable::end() +{ + return iterator(table() + usedCount()); +} + +inline PropertyTable::const_iterator PropertyTable::begin() const +{ + return const_iterator(skipDeletedEntries(table())); +} + +inline PropertyTable::const_iterator PropertyTable::end() const +{ + return const_iterator(table() + usedCount()); +} + +inline PropertyTable::find_iterator PropertyTable::find(const KeyType& key) +{ + ASSERT(key); + ASSERT(key->isIdentifier()); + unsigned hash = key->existingHash(); + unsigned step = 0; + +#if DUMP_PROPERTYMAP_STATS + ++numProbes; +#endif + + while (true) { + unsigned entryIndex = m_index[hash & m_indexMask]; + if (entryIndex == EmptyEntryIndex) + return std::make_pair((ValueType*)0, hash & m_indexMask); + if (key == table()[entryIndex - 1].key) + return std::make_pair(&table()[entryIndex - 1], hash & m_indexMask); + +#if DUMP_PROPERTYMAP_STATS + ++numCollisions; +#endif + + if (!step) + step = WTF::doubleHash(key->existingHash()) | 1; + hash += step; + +#if DUMP_PROPERTYMAP_STATS + ++numRehashes; +#endif + } +} + +inline PropertyTable::find_iterator PropertyTable::findWithString(const KeyType& key) +{ + ASSERT(key); + ASSERT(!key->isIdentifier() && !key->hasHash()); + unsigned hash = key->hash(); + unsigned step = 0; + +#if DUMP_PROPERTYMAP_STATS + ++numProbes; +#endif + + while (true) { + unsigned entryIndex = m_index[hash & m_indexMask]; + if (entryIndex == EmptyEntryIndex) + return std::make_pair((ValueType*)0, hash & m_indexMask); + if (equal(key, table()[entryIndex - 1].key)) + return std::make_pair(&table()[entryIndex - 1], hash & m_indexMask); + +#if DUMP_PROPERTYMAP_STATS + ++numCollisions; +#endif + + if (!step) + step = WTF::doubleHash(key->existingHash()) | 1; + hash += step; + +#if DUMP_PROPERTYMAP_STATS + ++numRehashes; +#endif + } +} + +inline std::pair PropertyTable::add(const ValueType& entry) +{ + // Look for a value with a matching key already in the array. + find_iterator iter = find(entry.key); + if (iter.first) + return std::make_pair(iter, false); + + // Ref the key + entry.key->ref(); + + // ensure capacity is available. + if (!canInsert()) { + rehash(m_keyCount + 1); + iter = find(entry.key); + ASSERT(!iter.first); + } + + // Allocate a slot in the hashtable, and set the index to reference this. + unsigned entryIndex = usedCount() + 1; + m_index[iter.second] = entryIndex; + iter.first = &table()[entryIndex - 1]; + *iter.first = entry; + + ++m_keyCount; + return std::make_pair(iter, true); +} + +inline void PropertyTable::remove(const find_iterator& iter) +{ + // Removing a key that doesn't exist does nothing! + if (!iter.first) + return; + +#if DUMP_PROPERTYMAP_STATS + ++numRemoves; +#endif + + // Replace this one element with the deleted sentinel. Also clear out + // the entry so we can iterate all the entries as needed. + m_index[iter.second] = deletedEntryIndex(); + iter.first->key->deref(); + iter.first->key = PROPERTY_MAP_DELETED_ENTRY_KEY; + + ASSERT(m_keyCount >= 1); + --m_keyCount; + ++m_deletedCount; + + if (m_deletedCount * 4 >= m_indexSize) + rehash(m_keyCount); +} + +inline void PropertyTable::remove(const KeyType& key) +{ + remove(find(key)); +} + +// returns the number of values in the hashtable. +inline unsigned PropertyTable::size() const +{ + return m_keyCount; +} + +inline bool PropertyTable::isEmpty() const +{ + return !m_keyCount; +} + +inline unsigned PropertyTable::propertyStorageSize() const +{ + return size() + (m_deletedOffsets ? m_deletedOffsets->size() : 0); +} + +inline void PropertyTable::clearDeletedOffsets() +{ + m_deletedOffsets.clear(); +} + +inline bool PropertyTable::hasDeletedOffset() +{ + return m_deletedOffsets && !m_deletedOffsets->isEmpty(); +} + +inline unsigned PropertyTable::getDeletedOffset() +{ + unsigned offset = m_deletedOffsets->last(); + m_deletedOffsets->removeLast(); + return offset; +} + +inline void PropertyTable::addDeletedOffset(unsigned offset) +{ + if (!m_deletedOffsets) + m_deletedOffsets = adoptPtr(new Vector); + m_deletedOffsets->append(offset); +} + +inline PassOwnPtr PropertyTable::copy(JSGlobalData& globalData, JSCell* owner, unsigned newCapacity) +{ + ASSERT(newCapacity >= m_keyCount); + + // Fast case; if the new table will be the same m_indexSize as this one, we can memcpy it, + // save rehashing all keys. + if (sizeForCapacity(newCapacity) == m_indexSize) + return adoptPtr(new PropertyTable(globalData, owner, *this)); + return adoptPtr(new PropertyTable(globalData, owner, newCapacity, *this)); +} + +#ifndef NDEBUG +inline size_t PropertyTable::sizeInMemory() +{ + size_t result = sizeof(PropertyTable) + dataSize(); + if (m_deletedOffsets) + result += (m_deletedOffsets->capacity() * sizeof(unsigned)); + return result; +} +#endif + +inline void PropertyTable::reinsert(const ValueType& entry) +{ + // Used to insert a value known not to be in the table, and where + // we know capacity to be available. + ASSERT(canInsert()); + find_iterator iter = find(entry.key); + ASSERT(!iter.first); + + unsigned entryIndex = usedCount() + 1; + m_index[iter.second] = entryIndex; + table()[entryIndex - 1] = entry; + + ++m_keyCount; +} + +inline void PropertyTable::rehash(unsigned newCapacity) +{ + unsigned* oldEntryIndices = m_index; + iterator iter = this->begin(); + iterator end = this->end(); + + m_indexSize = sizeForCapacity(newCapacity); + m_indexMask = m_indexSize - 1; + m_keyCount = 0; + m_deletedCount = 0; + m_index = static_cast(fastZeroedMalloc(dataSize())); + + for (; iter != end; ++iter) { + ASSERT(canInsert()); + reinsert(*iter); + } + + fastFree(oldEntryIndices); +} + +inline unsigned PropertyTable::tableCapacity() const { return m_indexSize >> 1; } + +inline unsigned PropertyTable::deletedEntryIndex() const { return tableCapacity() + 1; } + +template +inline T* PropertyTable::skipDeletedEntries(T* valuePtr) +{ + while (valuePtr->key == PROPERTY_MAP_DELETED_ENTRY_KEY) + ++valuePtr; + return valuePtr; +} + +inline PropertyTable::ValueType* PropertyTable::table() +{ + // The table of values lies after the hash index. + return reinterpret_cast(m_index + m_indexSize); +} + +inline const PropertyTable::ValueType* PropertyTable::table() const +{ + // The table of values lies after the hash index. + return reinterpret_cast(m_index + m_indexSize); +} + +inline unsigned PropertyTable::usedCount() const +{ + // Total number of used entries in the values array - by either valid entries, or deleted ones. + return m_keyCount + m_deletedCount; +} + +inline size_t PropertyTable::dataSize() +{ + // The size in bytes of data needed for by the table. + return m_indexSize * sizeof(unsigned) + ((tableCapacity()) + 1) * sizeof(ValueType); +} + +inline unsigned PropertyTable::sizeForCapacity(unsigned capacity) +{ + if (capacity < 8) + return MinimumTableSize; + return nextPowerOf2(capacity + 1) * 2; +} + +inline bool PropertyTable::canInsert() +{ + return usedCount() < tableCapacity(); +} + +} // namespace JSC + +#endif // PropertyMapHashTable_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PropertyNameArray.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PropertyNameArray.h new file mode 100644 index 000000000..dabda945b --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PropertyNameArray.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef PropertyNameArray_h +#define PropertyNameArray_h + +#include "CallFrame.h" +#include "Identifier.h" +#include +#include +#include + +namespace JSC { + + class Structure; + class StructureChain; + + // FIXME: Rename to PropertyNameArray. + class PropertyNameArrayData : public RefCounted { + public: + typedef Vector PropertyNameVector; + + static PassRefPtr create() { return adoptRef(new PropertyNameArrayData); } + + PropertyNameVector& propertyNameVector() { return m_propertyNameVector; } + + private: + PropertyNameArrayData() + { + } + + PropertyNameVector m_propertyNameVector; + }; + + // FIXME: Rename to PropertyNameArrayBuilder. + class PropertyNameArray { + public: + PropertyNameArray(JSGlobalData* globalData) + : m_data(PropertyNameArrayData::create()) + , m_globalData(globalData) + , m_shouldCache(true) + { + } + + PropertyNameArray(ExecState* exec) + : m_data(PropertyNameArrayData::create()) + , m_globalData(&exec->globalData()) + , m_shouldCache(true) + { + } + + JSGlobalData* globalData() { return m_globalData; } + + void add(const Identifier& identifier) { add(identifier.impl()); } + JS_EXPORT_PRIVATE void add(StringImpl*); + void addKnownUnique(StringImpl* identifier) { m_data->propertyNameVector().append(Identifier(m_globalData, identifier)); } + + Identifier& operator[](unsigned i) { return m_data->propertyNameVector()[i]; } + const Identifier& operator[](unsigned i) const { return m_data->propertyNameVector()[i]; } + + void setData(PassRefPtr data) { m_data = data; } + PropertyNameArrayData* data() { return m_data.get(); } + PassRefPtr releaseData() { return m_data.release(); } + + // FIXME: Remove these functions. + typedef PropertyNameArrayData::PropertyNameVector::const_iterator const_iterator; + size_t size() const { return m_data->propertyNameVector().size(); } + const_iterator begin() const { return m_data->propertyNameVector().begin(); } + const_iterator end() const { return m_data->propertyNameVector().end(); } + + private: + typedef HashSet > IdentifierSet; + + RefPtr m_data; + IdentifierSet m_set; + JSGlobalData* m_globalData; + bool m_shouldCache; + }; + +} // namespace JSC + +#endif // PropertyNameArray_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PropertySlot.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PropertySlot.h new file mode 100644 index 000000000..cfedf7876 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PropertySlot.h @@ -0,0 +1,241 @@ +/* + * Copyright (C) 2005, 2007, 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef PropertySlot_h +#define PropertySlot_h + +#include "Identifier.h" +#include "JSValue.h" +#include "Register.h" +#include +#include + +namespace JSC { + + class ExecState; + class JSObject; + +#define JSC_VALUE_MARKER 0 +#define INDEX_GETTER_MARKER reinterpret_cast(2) +#define GETTER_FUNCTION_MARKER reinterpret_cast(3) + + class PropertySlot { + public: + enum CachedPropertyType { + Uncacheable, + Getter, + Custom, + Value + }; + + PropertySlot() + : m_cachedPropertyType(Uncacheable) + { + clearBase(); + clearOffset(); + clearValue(); + } + + explicit PropertySlot(const JSValue base) + : m_slotBase(base) + , m_cachedPropertyType(Uncacheable) + { + clearOffset(); + clearValue(); + } + + typedef JSValue (*GetValueFunc)(ExecState*, JSValue slotBase, const Identifier&); + typedef JSValue (*GetIndexValueFunc)(ExecState*, JSValue slotBase, unsigned); + + JSValue getValue(ExecState* exec, const Identifier& propertyName) const + { + if (m_getValue == JSC_VALUE_MARKER) + return m_value; + if (m_getValue == INDEX_GETTER_MARKER) + return m_getIndexValue(exec, slotBase(), index()); + if (m_getValue == GETTER_FUNCTION_MARKER) + return functionGetter(exec); + return m_getValue(exec, slotBase(), propertyName); + } + + JSValue getValue(ExecState* exec, unsigned propertyName) const + { + if (m_getValue == JSC_VALUE_MARKER) + return m_value; + if (m_getValue == INDEX_GETTER_MARKER) + return m_getIndexValue(exec, m_slotBase, m_data.index); + if (m_getValue == GETTER_FUNCTION_MARKER) + return functionGetter(exec); + return m_getValue(exec, slotBase(), Identifier::from(exec, propertyName)); + } + + CachedPropertyType cachedPropertyType() const { return m_cachedPropertyType; } + bool isCacheable() const { return m_cachedPropertyType != Uncacheable; } + bool isCacheableValue() const { return m_cachedPropertyType == Value; } + size_t cachedOffset() const + { + ASSERT(isCacheable()); + return m_offset; + } + + void setValue(JSValue slotBase, JSValue value) + { + ASSERT(value); + clearOffset(); + m_getValue = JSC_VALUE_MARKER; + m_slotBase = slotBase; + m_value = value; + } + + void setValue(JSValue slotBase, JSValue value, size_t offset) + { + ASSERT(value); + m_getValue = JSC_VALUE_MARKER; + m_slotBase = slotBase; + m_value = value; + m_offset = offset; + m_cachedPropertyType = Value; + } + + void setValue(JSValue value) + { + ASSERT(value); + clearBase(); + clearOffset(); + m_getValue = JSC_VALUE_MARKER; + m_value = value; + } + + void setCustom(JSValue slotBase, GetValueFunc getValue) + { + ASSERT(slotBase); + ASSERT(getValue); + m_getValue = getValue; + m_getIndexValue = 0; + m_slotBase = slotBase; + } + + void setCacheableCustom(JSValue slotBase, GetValueFunc getValue) + { + ASSERT(slotBase); + ASSERT(getValue); + m_getValue = getValue; + m_getIndexValue = 0; + m_slotBase = slotBase; + m_cachedPropertyType = Custom; + } + + void setCustomIndex(JSValue slotBase, unsigned index, GetIndexValueFunc getIndexValue) + { + ASSERT(slotBase); + ASSERT(getIndexValue); + m_getValue = INDEX_GETTER_MARKER; + m_getIndexValue = getIndexValue; + m_slotBase = slotBase; + m_data.index = index; + } + + void setGetterSlot(JSObject* getterFunc) + { + ASSERT(getterFunc); + m_thisValue = m_slotBase; + m_getValue = GETTER_FUNCTION_MARKER; + m_data.getterFunc = getterFunc; + } + + void setCacheableGetterSlot(JSValue slotBase, JSObject* getterFunc, unsigned offset) + { + ASSERT(getterFunc); + m_getValue = GETTER_FUNCTION_MARKER; + m_thisValue = m_slotBase; + m_slotBase = slotBase; + m_data.getterFunc = getterFunc; + m_offset = offset; + m_cachedPropertyType = Getter; + } + + void setUndefined() + { + setValue(jsUndefined()); + } + + JSValue slotBase() const + { + return m_slotBase; + } + + void setBase(JSValue base) + { + ASSERT(m_slotBase); + ASSERT(base); + m_slotBase = base; + } + + void clearBase() + { +#ifndef NDEBUG + m_slotBase = JSValue(); +#endif + } + + void clearValue() + { +#ifndef NDEBUG + m_value = JSValue(); +#endif + } + + void clearOffset() + { + // Clear offset even in release builds, in case this PropertySlot has been used before. + // (For other data members, we don't need to clear anything because reuse would meaningfully overwrite them.) + m_offset = 0; + m_cachedPropertyType = Uncacheable; + } + + unsigned index() const { return m_data.index; } + + GetValueFunc customGetter() const + { + ASSERT(m_cachedPropertyType == Custom); + return m_getValue; + } + private: + JS_EXPORT_PRIVATE JSValue functionGetter(ExecState*) const; + + GetValueFunc m_getValue; + GetIndexValueFunc m_getIndexValue; + + JSValue m_slotBase; + union { + JSObject* getterFunc; + unsigned index; + } m_data; + + JSValue m_value; + JSValue m_thisValue; + + size_t m_offset; + CachedPropertyType m_cachedPropertyType; + }; + +} // namespace JSC + +#endif // PropertySlot_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Protect.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Protect.h new file mode 100644 index 000000000..843c9e111 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Protect.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2004, 2008, 2009 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + + +#ifndef Protect_h +#define Protect_h + +#include "Heap.h" +#include "JSValue.h" + +namespace JSC { + + inline void gcProtect(JSCell* val) + { + Heap::heap(val)->protect(val); + } + + inline void gcUnprotect(JSCell* val) + { + Heap::heap(val)->unprotect(val); + } + + inline void gcProtectNullTolerant(JSCell* val) + { + if (val) + gcProtect(val); + } + + inline void gcUnprotectNullTolerant(JSCell* val) + { + if (val) + gcUnprotect(val); + } + + inline void gcProtect(JSValue value) + { + if (value && value.isCell()) + gcProtect(value.asCell()); + } + + inline void gcUnprotect(JSValue value) + { + if (value && value.isCell()) + gcUnprotect(value.asCell()); + } + +} // namespace JSC + +#endif // Protect_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PutByIdStatus.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PutByIdStatus.h new file mode 100644 index 000000000..b33f4d09c --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PutByIdStatus.h @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2012 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 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 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 PutByIdStatus_h +#define PutByIdStatus_h + +#include + +namespace JSC { + +class CodeBlock; +class Identifier; +class Structure; +class StructureChain; + +class PutByIdStatus { +public: + enum State { + // It's uncached so we have no information. + NoInformation, + // It's cached as a direct store into an object property for cases where the object + // already has the property. + SimpleReplace, + // It's cached as a transition from one structure that lacks the property to one that + // includes the property, and a direct store to this new property. + SimpleTransition, + // It's known to often take slow path. + TakesSlowPath + }; + + PutByIdStatus() + : m_state(NoInformation) + , m_oldStructure(0) + , m_newStructure(0) + , m_structureChain(0) + , m_offset(notFound) + { + } + + PutByIdStatus( + State state, + Structure* oldStructure, + Structure* newStructure, + StructureChain* structureChain, + size_t offset) + : m_state(state) + , m_oldStructure(oldStructure) + , m_newStructure(newStructure) + , m_structureChain(structureChain) + , m_offset(offset) + { + ASSERT((m_state == NoInformation || m_state == TakesSlowPath) == !m_oldStructure); + ASSERT((m_state != SimpleTransition) == !m_newStructure); + ASSERT((m_state != SimpleTransition) == !m_structureChain); + ASSERT((m_state == NoInformation || m_state == TakesSlowPath) == (m_offset == notFound)); + } + + static PutByIdStatus computeFor(CodeBlock*, unsigned bytecodeIndex, Identifier&); + + State state() const { return m_state; } + + bool isSet() const { return m_state != NoInformation; } + bool operator!() const { return m_state == NoInformation; } + bool isSimpleReplace() const { return m_state == SimpleReplace; } + bool isSimpleTransition() const { return m_state == SimpleTransition; } + bool takesSlowPath() const { return m_state == TakesSlowPath; } + + Structure* oldStructure() const { return m_oldStructure; } + Structure* newStructure() const { return m_newStructure; } + StructureChain* structureChain() const { return m_structureChain; } + size_t offset() const { return m_offset; } + +private: + State m_state; + Structure* m_oldStructure; + Structure* m_newStructure; + StructureChain* m_structureChain; + size_t m_offset; +}; + +} // namespace JSC + +#endif // PutByIdStatus_h + diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PutPropertySlot.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PutPropertySlot.h new file mode 100644 index 000000000..69d1f8bd2 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/PutPropertySlot.h @@ -0,0 +1,81 @@ +// -*- mode: c++; c-basic-offset: 4 -*- +/* + * Copyright (C) 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. + */ + +#ifndef PutPropertySlot_h +#define PutPropertySlot_h + +#include + +namespace JSC { + + class JSObject; + class JSFunction; + + class PutPropertySlot { + public: + enum Type { Uncachable, ExistingProperty, NewProperty }; + + PutPropertySlot(bool isStrictMode = false) + : m_type(Uncachable) + , m_base(0) + , m_isStrictMode(isStrictMode) + { + } + + void setExistingProperty(JSObject* base, size_t offset) + { + m_type = ExistingProperty; + m_base = base; + m_offset = offset; + } + + void setNewProperty(JSObject* base, size_t offset) + { + m_type = NewProperty; + m_base = base; + m_offset = offset; + } + + Type type() const { return m_type; } + JSObject* base() const { return m_base; } + + bool isStrictMode() const { return m_isStrictMode; } + bool isCacheable() const { return m_type != Uncachable; } + size_t cachedOffset() const { + ASSERT(isCacheable()); + return m_offset; + } + + private: + Type m_type; + JSObject* m_base; + size_t m_offset; + bool m_isStrictMode; + }; + +} // namespace JSC + +#endif // PutPropertySlot_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/RandomNumber.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/RandomNumber.h new file mode 100644 index 000000000..76b223582 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/RandomNumber.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * 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 WTF_RandomNumber_h +#define WTF_RandomNumber_h + +namespace WTF { + + // Returns a pseudo-random number in the range [0, 1), attempts to be + // cryptographically secure if possible on the target platform + WTF_EXPORT_PRIVATE double randomNumber(); + +} + +using WTF::randomNumber; + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/RedBlackTree.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/RedBlackTree.h new file mode 100644 index 000000000..19460c141 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/RedBlackTree.h @@ -0,0 +1,574 @@ +/* + * Copyright (C) 2010, 2011 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 RedBlackTree_h +#define RedBlackTree_h + +#include +#include + +namespace WTF { + +// This implements a red-black tree with the following properties: +// - The allocation of nodes in the tree is entirely up to the user. +// - If you are in possession of a pointer to a node, you can delete +// it from the tree. The tree will subsequently no longer have a +// reference to this node. +// - The key type must implement operator< and ==. + +template +class RedBlackTree { + WTF_MAKE_NONCOPYABLE(RedBlackTree); +private: + enum Color { + Red = 1, + Black + }; + +public: + class Node { + friend class RedBlackTree; + + public: + const NodeType* successor() const + { + const Node* x = this; + if (x->right()) + return treeMinimum(x->right()); + const NodeType* y = x->parent(); + while (y && x == y->right()) { + x = y; + y = y->parent(); + } + return y; + } + + const NodeType* predecessor() const + { + const Node* x = this; + if (x->left()) + return treeMaximum(x->left()); + const NodeType* y = x->parent(); + while (y && x == y->left()) { + x = y; + y = y->parent(); + } + return y; + } + + NodeType* successor() + { + return const_cast(const_cast(this)->successor()); + } + + NodeType* predecessor() + { + return const_cast(const_cast(this)->predecessor()); + } + + private: + void reset() + { + m_left = 0; + m_right = 0; + m_parentAndRed = 1; // initialize to red + } + + // NOTE: these methods should pack the parent and red into a single + // word. But doing so appears to reveal a bug in the compiler. + NodeType* parent() const + { + return reinterpret_cast(m_parentAndRed & ~static_cast(1)); + } + + void setParent(NodeType* newParent) + { + m_parentAndRed = reinterpret_cast(newParent) | (m_parentAndRed & 1); + } + + NodeType* left() const + { + return m_left; + } + + void setLeft(NodeType* node) + { + m_left = node; + } + + NodeType* right() const + { + return m_right; + } + + void setRight(NodeType* node) + { + m_right = node; + } + + Color color() const + { + if (m_parentAndRed & 1) + return Red; + return Black; + } + + void setColor(Color value) + { + if (value == Red) + m_parentAndRed |= 1; + else + m_parentAndRed &= ~static_cast(1); + } + + NodeType* m_left; + NodeType* m_right; + uintptr_t m_parentAndRed; + }; + + RedBlackTree() + : m_root(0) + { + } + + void insert(NodeType* x) + { + x->reset(); + treeInsert(x); + x->setColor(Red); + + while (x != m_root && x->parent()->color() == Red) { + if (x->parent() == x->parent()->parent()->left()) { + NodeType* y = x->parent()->parent()->right(); + if (y && y->color() == Red) { + // Case 1 + x->parent()->setColor(Black); + y->setColor(Black); + x->parent()->parent()->setColor(Red); + x = x->parent()->parent(); + } else { + if (x == x->parent()->right()) { + // Case 2 + x = x->parent(); + leftRotate(x); + } + // Case 3 + x->parent()->setColor(Black); + x->parent()->parent()->setColor(Red); + rightRotate(x->parent()->parent()); + } + } else { + // Same as "then" clause with "right" and "left" exchanged. + NodeType* y = x->parent()->parent()->left(); + if (y && y->color() == Red) { + // Case 1 + x->parent()->setColor(Black); + y->setColor(Black); + x->parent()->parent()->setColor(Red); + x = x->parent()->parent(); + } else { + if (x == x->parent()->left()) { + // Case 2 + x = x->parent(); + rightRotate(x); + } + // Case 3 + x->parent()->setColor(Black); + x->parent()->parent()->setColor(Red); + leftRotate(x->parent()->parent()); + } + } + } + + m_root->setColor(Black); + } + + NodeType* remove(NodeType* z) + { + ASSERT(z); + ASSERT(z->parent() || z == m_root); + + // Y is the node to be unlinked from the tree. + NodeType* y; + if (!z->left() || !z->right()) + y = z; + else + y = z->successor(); + + // Y is guaranteed to be non-null at this point. + NodeType* x; + if (y->left()) + x = y->left(); + else + x = y->right(); + + // X is the child of y which might potentially replace y in + // the tree. X might be null at this point. + NodeType* xParent; + if (x) { + x->setParent(y->parent()); + xParent = x->parent(); + } else + xParent = y->parent(); + if (!y->parent()) + m_root = x; + else { + if (y == y->parent()->left()) + y->parent()->setLeft(x); + else + y->parent()->setRight(x); + } + + if (y != z) { + if (y->color() == Black) + removeFixup(x, xParent); + + y->setParent(z->parent()); + y->setColor(z->color()); + y->setLeft(z->left()); + y->setRight(z->right()); + + if (z->left()) + z->left()->setParent(y); + if (z->right()) + z->right()->setParent(y); + if (z->parent()) { + if (z->parent()->left() == z) + z->parent()->setLeft(y); + else + z->parent()->setRight(y); + } else { + ASSERT(m_root == z); + m_root = y; + } + } else if (y->color() == Black) + removeFixup(x, xParent); + + return z; + } + + NodeType* remove(const KeyType& key) + { + NodeType* result = findExact(key); + if (!result) + return 0; + return remove(result); + } + + NodeType* findExact(const KeyType& key) const + { + for (NodeType* current = m_root; current;) { + if (current->key() == key) + return current; + if (key < current->key()) + current = current->left(); + else + current = current->right(); + } + return 0; + } + + NodeType* findLeastGreaterThanOrEqual(const KeyType& key) const + { + NodeType* best = 0; + for (NodeType* current = m_root; current;) { + if (current->key() == key) + return current; + if (current->key() < key) + current = current->right(); + else { + best = current; + current = current->left(); + } + } + return best; + } + + NodeType* findGreatestLessThanOrEqual(const KeyType& key) const + { + NodeType* best = 0; + for (NodeType* current = m_root; current;) { + if (current->key() == key) + return current; + if (current->key() > key) + current = current->left(); + else { + best = current; + current = current->right(); + } + } + return best; + } + + NodeType* first() const + { + if (!m_root) + return 0; + return treeMinimum(m_root); + } + + NodeType* last() const + { + if (!m_root) + return 0; + return treeMaximum(m_root); + } + + // This is an O(n) operation. + size_t size() + { + size_t result = 0; + for (NodeType* current = first(); current; current = current->successor()) + result++; + return result; + } + + // This is an O(1) operation. + bool isEmpty() + { + return !m_root; + } + +private: + // Finds the minimum element in the sub-tree rooted at the given + // node. + static NodeType* treeMinimum(NodeType* x) + { + while (x->left()) + x = x->left(); + return x; + } + + static NodeType* treeMaximum(NodeType* x) + { + while (x->right()) + x = x->right(); + return x; + } + + static const NodeType* treeMinimum(const NodeType* x) + { + while (x->left()) + x = x->left(); + return x; + } + + static const NodeType* treeMaximum(const NodeType* x) + { + while (x->right()) + x = x->right(); + return x; + } + + void treeInsert(NodeType* z) + { + ASSERT(!z->left()); + ASSERT(!z->right()); + ASSERT(!z->parent()); + ASSERT(z->color() == Red); + + NodeType* y = 0; + NodeType* x = m_root; + while (x) { + y = x; + if (z->key() < x->key()) + x = x->left(); + else + x = x->right(); + } + z->setParent(y); + if (!y) + m_root = z; + else { + if (z->key() < y->key()) + y->setLeft(z); + else + y->setRight(z); + } + } + + //---------------------------------------------------------------------- + // Red-Black tree operations + // + + // Left-rotates the subtree rooted at x. + // Returns the new root of the subtree (x's right child). + NodeType* leftRotate(NodeType* x) + { + // Set y. + NodeType* y = x->right(); + + // Turn y's left subtree into x's right subtree. + x->setRight(y->left()); + if (y->left()) + y->left()->setParent(x); + + // Link x's parent to y. + y->setParent(x->parent()); + if (!x->parent()) + m_root = y; + else { + if (x == x->parent()->left()) + x->parent()->setLeft(y); + else + x->parent()->setRight(y); + } + + // Put x on y's left. + y->setLeft(x); + x->setParent(y); + + return y; + } + + // Right-rotates the subtree rooted at y. + // Returns the new root of the subtree (y's left child). + NodeType* rightRotate(NodeType* y) + { + // Set x. + NodeType* x = y->left(); + + // Turn x's right subtree into y's left subtree. + y->setLeft(x->right()); + if (x->right()) + x->right()->setParent(y); + + // Link y's parent to x. + x->setParent(y->parent()); + if (!y->parent()) + m_root = x; + else { + if (y == y->parent()->left()) + y->parent()->setLeft(x); + else + y->parent()->setRight(x); + } + + // Put y on x's right. + x->setRight(y); + y->setParent(x); + + return x; + } + + // Restores the red-black property to the tree after splicing out + // a node. Note that x may be null, which is why xParent must be + // supplied. + void removeFixup(NodeType* x, NodeType* xParent) + { + while (x != m_root && (!x || x->color() == Black)) { + if (x == xParent->left()) { + // Note: the text points out that w can not be null. + // The reason is not obvious from simply looking at + // the code; it comes about from the properties of the + // red-black tree. + NodeType* w = xParent->right(); + ASSERT(w); // x's sibling should not be null. + if (w->color() == Red) { + // Case 1 + w->setColor(Black); + xParent->setColor(Red); + leftRotate(xParent); + w = xParent->right(); + } + if ((!w->left() || w->left()->color() == Black) + && (!w->right() || w->right()->color() == Black)) { + // Case 2 + w->setColor(Red); + x = xParent; + xParent = x->parent(); + } else { + if (!w->right() || w->right()->color() == Black) { + // Case 3 + w->left()->setColor(Black); + w->setColor(Red); + rightRotate(w); + w = xParent->right(); + } + // Case 4 + w->setColor(xParent->color()); + xParent->setColor(Black); + if (w->right()) + w->right()->setColor(Black); + leftRotate(xParent); + x = m_root; + xParent = x->parent(); + } + } else { + // Same as "then" clause with "right" and "left" + // exchanged. + + // Note: the text points out that w can not be null. + // The reason is not obvious from simply looking at + // the code; it comes about from the properties of the + // red-black tree. + NodeType* w = xParent->left(); + ASSERT(w); // x's sibling should not be null. + if (w->color() == Red) { + // Case 1 + w->setColor(Black); + xParent->setColor(Red); + rightRotate(xParent); + w = xParent->left(); + } + if ((!w->right() || w->right()->color() == Black) + && (!w->left() || w->left()->color() == Black)) { + // Case 2 + w->setColor(Red); + x = xParent; + xParent = x->parent(); + } else { + if (!w->left() || w->left()->color() == Black) { + // Case 3 + w->right()->setColor(Black); + w->setColor(Red); + leftRotate(w); + w = xParent->left(); + } + // Case 4 + w->setColor(xParent->color()); + xParent->setColor(Black); + if (w->left()) + w->left()->setColor(Black); + rightRotate(xParent); + x = m_root; + xParent = x->parent(); + } + } + } + if (x) + x->setColor(Black); + } + + NodeType* m_root; +}; + +} + +#endif + diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/RefCounted.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/RefCounted.h new file mode 100644 index 000000000..51c5dc26e --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/RefCounted.h @@ -0,0 +1,234 @@ +/* + * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef RefCounted_h +#define RefCounted_h + +#include "Assertions.h" +#include "FastAllocBase.h" +#include "ThreadRestrictionVerifier.h" +#include "Noncopyable.h" +#include "OwnPtr.h" +#include "UnusedParam.h" + +namespace WTF { + +// This base class holds the non-template methods and attributes. +// The RefCounted class inherits from it reducing the template bloat +// generated by the compiler (technique called template hoisting). +class RefCountedBase { +public: + void ref() + { +#ifndef NDEBUG + // Start thread verification as soon as the ref count gets to 2. This + // heuristic reflects the fact that items are often created on one thread + // and then given to another thread to be used. + // FIXME: Make this restriction tigher. Especially as we move to more + // common methods for sharing items across threads like CrossThreadCopier.h + // We should be able to add a "detachFromThread" method to make this explicit. + if (m_refCount == 1) + m_verifier.setShared(true); +#endif + // If this assert fires, it either indicates a thread safety issue or + // that the verification needs to change. See ThreadRestrictionVerifier for + // the different modes. + ASSERT(m_verifier.isSafeToUse()); + ASSERT(!m_deletionHasBegun); + ASSERT(!m_adoptionIsRequired); + ++m_refCount; + } + + bool hasOneRef() const + { + ASSERT(m_verifier.isSafeToUse()); + ASSERT(!m_deletionHasBegun); + return m_refCount == 1; + } + + int refCount() const + { + ASSERT(m_verifier.isSafeToUse()); + return m_refCount; + } + + void setMutexForVerifier(Mutex&); + +#if HAVE(DISPATCH_H) + void setDispatchQueueForVerifier(dispatch_queue_t); +#endif + + // Turns off verification. Use of this method is discouraged (instead extend + // ThreadRestrictionVerifier to verify your case). + // FIXME: remove this method. + void deprecatedTurnOffVerifier() + { +#ifndef NDEBUG + m_verifier.turnOffVerification(); +#endif + } + + void relaxAdoptionRequirement() + { +#ifndef NDEBUG + ASSERT(!m_deletionHasBegun); + ASSERT(m_adoptionIsRequired); + m_adoptionIsRequired = false; +#endif + } + + // Helper for generating JIT code. Please do not use for non-JIT purposes. + const int* addressOfCount() const + { + return &m_refCount; + } + +protected: + RefCountedBase() + : m_refCount(1) +#ifndef NDEBUG + , m_deletionHasBegun(false) + , m_adoptionIsRequired(true) +#endif + { + } + + ~RefCountedBase() + { + ASSERT(m_deletionHasBegun); + ASSERT(!m_adoptionIsRequired); + } + + // Returns whether the pointer should be freed or not. + bool derefBase() + { + ASSERT(m_verifier.isSafeToUse()); + ASSERT(!m_deletionHasBegun); + ASSERT(!m_adoptionIsRequired); + + ASSERT(m_refCount > 0); + if (m_refCount == 1) { +#ifndef NDEBUG + m_deletionHasBegun = true; +#endif + return true; + } + + --m_refCount; +#ifndef NDEBUG + // Stop thread verification when the ref goes to 1 because it + // is safe to be passed to another thread at this point. + if (m_refCount == 1) + m_verifier.setShared(false); +#endif + return false; + } + +#ifndef NDEBUG + bool deletionHasBegun() const + { + return m_deletionHasBegun; + } +#endif + +private: + +#ifndef NDEBUG + friend void adopted(RefCountedBase*); +#endif + + int m_refCount; +#ifndef NDEBUG + bool m_deletionHasBegun; + bool m_adoptionIsRequired; + ThreadRestrictionVerifier m_verifier; +#endif +}; + +#ifndef NDEBUG + +inline void adopted(RefCountedBase* object) +{ + if (!object) + return; + ASSERT(!object->m_deletionHasBegun); + object->m_adoptionIsRequired = false; +} + +#endif + +template class RefCounted : public RefCountedBase { + WTF_MAKE_NONCOPYABLE(RefCounted); WTF_MAKE_FAST_ALLOCATED; +public: + void deref() + { + if (derefBase()) + delete static_cast(this); + } + +protected: + RefCounted() { } + ~RefCounted() + { + } +}; + +template class RefCountedCustomAllocated : public RefCountedBase { + WTF_MAKE_NONCOPYABLE(RefCountedCustomAllocated); + +public: + void deref() + { + if (derefBase()) + delete static_cast(this); + } + +protected: + ~RefCountedCustomAllocated() + { + } +}; + +#ifdef NDEBUG +inline void RefCountedBase::setMutexForVerifier(Mutex&) { } +#else +inline void RefCountedBase::setMutexForVerifier(Mutex& mutex) +{ + m_verifier.setMutexMode(mutex); +} +#endif + +#if HAVE(DISPATCH_H) +#ifdef NDEBUG +inline void RefCountedBase::setDispatchQueueForVerifier(dispatch_queue_t) { } +#else +inline void RefCountedBase::setDispatchQueueForVerifier(dispatch_queue_t queue) +{ + m_verifier.setDispatchQueueMode(queue); +} +#endif // NDEBUG +#endif // HAVE(DISPATCH_H) + +} // namespace WTF + +using WTF::RefCounted; +using WTF::RefCountedCustomAllocated; + +#endif // RefCounted_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/RefCountedLeakCounter.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/RefCountedLeakCounter.h new file mode 100644 index 000000000..476b1735a --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/RefCountedLeakCounter.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef RefCountedLeakCounter_h +#define RefCountedLeakCounter_h + +#include "Assertions.h" +#include "Threading.h" + +namespace WTF { + + struct RefCountedLeakCounter { + WTF_EXPORT_PRIVATE static void suppressMessages(const char*); + WTF_EXPORT_PRIVATE static void cancelMessageSuppression(const char*); + + WTF_EXPORT_PRIVATE explicit RefCountedLeakCounter(const char* description); + WTF_EXPORT_PRIVATE ~RefCountedLeakCounter(); + + WTF_EXPORT_PRIVATE void increment(); + WTF_EXPORT_PRIVATE void decrement(); + +#ifndef NDEBUG + private: +#if COMPILER(MINGW) || COMPILER(MSVC7_OR_LOWER) || OS(WINCE) + int m_count; +#else + volatile int m_count; +#endif + const char* m_description; +#endif + }; + +} // namespace WTF + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/RefPtr.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/RefPtr.h new file mode 100644 index 000000000..ac94993e3 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/RefPtr.h @@ -0,0 +1,232 @@ +/* + * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +// RefPtr and PassRefPtr are documented at http://webkit.org/coding/RefPtr.html + +#ifndef WTF_RefPtr_h +#define WTF_RefPtr_h + +#include +#include "FastAllocBase.h" +#include "PassRefPtr.h" + +namespace WTF { + + enum PlacementNewAdoptType { PlacementNewAdopt }; + + template class PassRefPtr; + template class NonNullPassRefPtr; + + enum HashTableDeletedValueType { HashTableDeletedValue }; + + template class RefPtr { + WTF_MAKE_FAST_ALLOCATED; + public: + ALWAYS_INLINE RefPtr() : m_ptr(0) { } + ALWAYS_INLINE RefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); } + ALWAYS_INLINE RefPtr(const RefPtr& o) : m_ptr(o.m_ptr) { refIfNotNull(m_ptr); } + template RefPtr(const RefPtr& o) : m_ptr(o.get()) { refIfNotNull(m_ptr); } + + // See comments in PassRefPtr.h for an explanation of why these takes const references. + template RefPtr(const PassRefPtr&); + template RefPtr(const NonNullPassRefPtr&); + + // Special constructor for cases where we overwrite an object in place. + ALWAYS_INLINE RefPtr(PlacementNewAdoptType) { } + + // Hash table deleted values, which are only constructed and never copied or destroyed. + RefPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { } + bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); } + + ALWAYS_INLINE ~RefPtr() { derefIfNotNull(m_ptr); } + + T* get() const { return m_ptr; } + + void clear(); + PassRefPtr release() { PassRefPtr tmp = adoptRef(m_ptr); m_ptr = 0; return tmp; } + + T& operator*() const { return *m_ptr; } + ALWAYS_INLINE T* operator->() const { return m_ptr; } + + bool operator!() const { return !m_ptr; } + + // This conversion operator allows implicit conversion to bool but not to other integer types. + typedef T* (RefPtr::*UnspecifiedBoolType); + operator UnspecifiedBoolType() const { return m_ptr ? &RefPtr::m_ptr : 0; } + + RefPtr& operator=(const RefPtr&); + RefPtr& operator=(T*); + RefPtr& operator=(const PassRefPtr&); + RefPtr& operator=(const NonNullPassRefPtr&); +#if !COMPILER_SUPPORTS(CXX_NULLPTR) + RefPtr& operator=(std::nullptr_t) { clear(); return *this; } +#endif + template RefPtr& operator=(const RefPtr&); + template RefPtr& operator=(const PassRefPtr&); + template RefPtr& operator=(const NonNullPassRefPtr&); + + void swap(RefPtr&); + + static T* hashTableDeletedValue() { return reinterpret_cast(-1); } + + private: + T* m_ptr; + }; + + template template inline RefPtr::RefPtr(const PassRefPtr& o) + : m_ptr(o.leakRef()) + { + } + + template template inline RefPtr::RefPtr(const NonNullPassRefPtr& o) + : m_ptr(o.leakRef()) + { + } + + template inline void RefPtr::clear() + { + T* ptr = m_ptr; + m_ptr = 0; + derefIfNotNull(ptr); + } + + template inline RefPtr& RefPtr::operator=(const RefPtr& o) + { + T* optr = o.get(); + refIfNotNull(optr); + T* ptr = m_ptr; + m_ptr = optr; + derefIfNotNull(ptr); + return *this; + } + + template template inline RefPtr& RefPtr::operator=(const RefPtr& o) + { + T* optr = o.get(); + refIfNotNull(optr); + T* ptr = m_ptr; + m_ptr = optr; + derefIfNotNull(ptr); + return *this; + } + + template inline RefPtr& RefPtr::operator=(T* optr) + { + refIfNotNull(optr); + T* ptr = m_ptr; + m_ptr = optr; + derefIfNotNull(ptr); + return *this; + } + + template inline RefPtr& RefPtr::operator=(const PassRefPtr& o) + { + T* ptr = m_ptr; + m_ptr = o.leakRef(); + derefIfNotNull(ptr); + return *this; + } + + template inline RefPtr& RefPtr::operator=(const NonNullPassRefPtr& o) + { + T* ptr = m_ptr; + m_ptr = o.leakRef(); + derefIfNotNull(ptr); + return *this; + } + + template template inline RefPtr& RefPtr::operator=(const PassRefPtr& o) + { + T* ptr = m_ptr; + m_ptr = o.leakRef(); + derefIfNotNull(ptr); + return *this; + } + + template template inline RefPtr& RefPtr::operator=(const NonNullPassRefPtr& o) + { + T* ptr = m_ptr; + m_ptr = o.leakRef(); + derefIfNotNull(ptr); + return *this; + } + + template inline void RefPtr::swap(RefPtr& o) + { + std::swap(m_ptr, o.m_ptr); + } + + template inline void swap(RefPtr& a, RefPtr& b) + { + a.swap(b); + } + + template inline bool operator==(const RefPtr& a, const RefPtr& b) + { + return a.get() == b.get(); + } + + template inline bool operator==(const RefPtr& a, U* b) + { + return a.get() == b; + } + + template inline bool operator==(T* a, const RefPtr& b) + { + return a == b.get(); + } + + template inline bool operator!=(const RefPtr& a, const RefPtr& b) + { + return a.get() != b.get(); + } + + template inline bool operator!=(const RefPtr& a, U* b) + { + return a.get() != b; + } + + template inline bool operator!=(T* a, const RefPtr& b) + { + return a != b.get(); + } + + template inline RefPtr static_pointer_cast(const RefPtr& p) + { + return RefPtr(static_cast(p.get())); + } + + template inline RefPtr const_pointer_cast(const RefPtr& p) + { + return RefPtr(const_cast(p.get())); + } + + template inline T* getPtr(const RefPtr& p) + { + return p.get(); + } + +} // namespace WTF + +using WTF::RefPtr; +using WTF::static_pointer_cast; +using WTF::const_pointer_cast; + +#endif // WTF_RefPtr_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/RefPtrHashMap.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/RefPtrHashMap.h new file mode 100644 index 000000000..f48a59cf6 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/RefPtrHashMap.h @@ -0,0 +1,329 @@ +/* + * Copyright (C) 2005, 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef RefPtrHashMap_h +#define RefPtrHashMap_h + +namespace WTF { + + // This specialization is a copy of HashMap for use with RefPtr keys, with overloaded functions + // to allow for lookup by pointer instead of RefPtr, avoiding ref-count churn. + + // FIXME: Find a way to do this with traits that doesn't require a copy of the HashMap template. + + template + class HashMap, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> { + WTF_MAKE_FAST_ALLOCATED; + private: + typedef KeyTraitsArg KeyTraits; + typedef MappedTraitsArg MappedTraits; + typedef PairHashTraits ValueTraits; + + public: + typedef typename KeyTraits::TraitType KeyType; + typedef T* RawKeyType; + typedef typename MappedTraits::TraitType MappedType; + typedef typename ValueTraits::TraitType ValueType; + + private: + typedef typename MappedTraits::PassInType MappedPassInType; + typedef typename MappedTraits::PassOutType MappedPassOutType; + typedef typename MappedTraits::PeekType MappedPeekType; + + typedef typename ReferenceTypeMaker::ReferenceType MappedPassInReferenceType; + + typedef HashArg HashFunctions; + + typedef HashTable, + HashFunctions, ValueTraits, KeyTraits> HashTableType; + + typedef HashMapTranslator + Translator; + + public: + typedef HashTableIteratorAdapter iterator; + typedef HashTableConstIteratorAdapter const_iterator; + + void swap(HashMap&); + + int size() const; + int capacity() const; + bool isEmpty() const; + + // iterators iterate over pairs of keys and values + iterator begin(); + iterator end(); + const_iterator begin() const; + const_iterator end() const; + + iterator find(const KeyType&); + iterator find(RawKeyType); + const_iterator find(const KeyType&) const; + const_iterator find(RawKeyType) const; + bool contains(const KeyType&) const; + bool contains(RawKeyType) const; + MappedPeekType get(const KeyType&) const; + MappedPeekType get(RawKeyType) const; + MappedPeekType inlineGet(RawKeyType) const; + + // replaces value but not key if key is already present + // return value is a pair of the iterator to the key location, + // and a boolean that's true if a new value was actually added + pair set(const KeyType&, MappedPassInType); + pair set(RawKeyType, MappedPassInType); + + // does nothing if key is already present + // return value is a pair of the iterator to the key location, + // and a boolean that's true if a new value was actually added + pair add(const KeyType&, MappedPassInType); + pair add(RawKeyType, MappedPassInType); + + void remove(const KeyType&); + void remove(RawKeyType); + void remove(iterator); + void clear(); + + MappedPassOutType take(const KeyType&); // efficient combination of get with remove + MappedPassOutType take(RawKeyType); // efficient combination of get with remove + + private: + pair inlineAdd(const KeyType&, MappedPassInReferenceType); + pair inlineAdd(RawKeyType, MappedPassInReferenceType); + + HashTableType m_impl; + }; + + template + inline void HashMap, U, V, W, X>::swap(HashMap& other) + { + m_impl.swap(other.m_impl); + } + + template + inline int HashMap, U, V, W, X>::size() const + { + return m_impl.size(); + } + + template + inline int HashMap, U, V, W, X>::capacity() const + { + return m_impl.capacity(); + } + + template + inline bool HashMap, U, V, W, X>::isEmpty() const + { + return m_impl.isEmpty(); + } + + template + inline typename HashMap, U, V, W, X>::iterator HashMap, U, V, W, X>::begin() + { + return m_impl.begin(); + } + + template + inline typename HashMap, U, V, W, X>::iterator HashMap, U, V, W, X>::end() + { + return m_impl.end(); + } + + template + inline typename HashMap, U, V, W, X>::const_iterator HashMap, U, V, W, X>::begin() const + { + return m_impl.begin(); + } + + template + inline typename HashMap, U, V, W, X>::const_iterator HashMap, U, V, W, X>::end() const + { + return m_impl.end(); + } + + template + inline typename HashMap, U, V, W, X>::iterator HashMap, U, V, W, X>::find(const KeyType& key) + { + return m_impl.find(key); + } + + template + inline typename HashMap, U, V, W, X>::iterator HashMap, U, V, W, X>::find(RawKeyType key) + { + return m_impl.template find(key); + } + + template + inline typename HashMap, U, V, W, X>::const_iterator HashMap, U, V, W, X>::find(const KeyType& key) const + { + return m_impl.find(key); + } + + template + inline typename HashMap, U, V, W, X>::const_iterator HashMap, U, V, W, X>::find(RawKeyType key) const + { + return m_impl.template find(key); + } + + template + inline bool HashMap, U, V, W, X>::contains(const KeyType& key) const + { + return m_impl.contains(key); + } + + template + inline bool HashMap, U, V, W, X>::contains(RawKeyType key) const + { + return m_impl.template contains(key); + } + + template + inline pair, U, V, W, X>::iterator, bool> + HashMap, U, V, W, X>::inlineAdd(const KeyType& key, MappedPassInReferenceType mapped) + { + return m_impl.template add(key, mapped); + } + + template + inline pair, U, V, W, X>::iterator, bool> + HashMap, U, V, W, X>::inlineAdd(RawKeyType key, MappedPassInReferenceType mapped) + { + return m_impl.template add(key, mapped); + } + + template + pair, U, V, W, X>::iterator, bool> + HashMap, U, V, W, X>::set(const KeyType& key, MappedPassInType mapped) + { + pair result = inlineAdd(key, mapped); + if (!result.second) { + // The inlineAdd call above found an existing hash table entry; we need to set the mapped value. + MappedTraits::store(mapped, result.first->second); + } + return result; + } + + template + pair, U, V, W, X>::iterator, bool> + HashMap, U, V, W, X>::set(RawKeyType key, MappedPassInType mapped) + { + pair result = inlineAdd(key, mapped); + if (!result.second) { + // The inlineAdd call above found an existing hash table entry; we need to set the mapped value. + MappedTraits::store(mapped, result.first->second); + } + return result; + } + + template + pair, U, V, W, X>::iterator, bool> + HashMap, U, V, W, X>::add(const KeyType& key, MappedPassInType mapped) + { + return inlineAdd(key, mapped); + } + + template + pair, U, V, W, X>::iterator, bool> + HashMap, U, V, W, X>::add(RawKeyType key, MappedPassInType mapped) + { + return inlineAdd(key, mapped); + } + + template + typename HashMap, U, V, W, MappedTraits>::MappedPeekType + HashMap, U, V, W, MappedTraits>::get(const KeyType& key) const + { + ValueType* entry = const_cast(m_impl).lookup(key); + if (!entry) + return MappedTraits::peek(MappedTraits::emptyValue()); + return MappedTraits::peek(entry->second); + } + + template + typename HashMap, U, V, W, MappedTraits>::MappedPeekType + inline HashMap, U, V, W, MappedTraits>::inlineGet(RawKeyType key) const + { + ValueType* entry = const_cast(m_impl).template lookup(key); + if (!entry) + return MappedTraits::peek(MappedTraits::emptyValue()); + return MappedTraits::peek(entry->second); + } + + template + typename HashMap, U, V, W, MappedTraits>::MappedPeekType + HashMap, U, V, W, MappedTraits>::get(RawKeyType key) const + { + return inlineGet(key); + } + + template + inline void HashMap, U, V, W, X>::remove(iterator it) + { + if (it.m_impl == m_impl.end()) + return; + m_impl.internalCheckTableConsistency(); + m_impl.removeWithoutEntryConsistencyCheck(it.m_impl); + } + + template + inline void HashMap, U, V, W, X>::remove(const KeyType& key) + { + remove(find(key)); + } + + template + inline void HashMap, U, V, W, X>::remove(RawKeyType key) + { + remove(find(key)); + } + + template + inline void HashMap, U, V, W, X>::clear() + { + m_impl.clear(); + } + + template + typename HashMap, U, V, W, MappedTraits>::MappedPassOutType + HashMap, U, V, W, MappedTraits>::take(const KeyType& key) + { + iterator it = find(key); + if (it == end()) + return MappedTraits::passOut(MappedTraits::emptyValue()); + MappedPassOutType result = MappedTraits::passOut(it->second); + remove(it); + return result; + } + + template + typename HashMap, U, V, W, MappedTraits>::MappedPassOutType + HashMap, U, V, W, MappedTraits>::take(RawKeyType key) + { + iterator it = find(key); + if (it == end()) + return MappedTraits::passOut(MappedTraits::emptyValue()); + MappedPassOutType result = MappedTraits::passOut(it->second); + remove(it); + return result; + } + +} // namespace WTF + +#endif // RefPtrHashMap_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/RegExp.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/RegExp.h new file mode 100644 index 000000000..311bb7532 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/RegExp.h @@ -0,0 +1,116 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2009 Torch Mobile, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef RegExp_h +#define RegExp_h + +#include "UString.h" +#include "ExecutableAllocator.h" +#include "Structure.h" +#include "RegExpKey.h" +#include "yarr/Yarr.h" +#include +#include + +namespace JSC { + + struct RegExpRepresentation; + class JSGlobalData; + + JS_EXPORT_PRIVATE RegExpFlags regExpFlags(const UString&); + + class RegExp : public JSCell { + public: + typedef JSCell Base; + + JS_EXPORT_PRIVATE static RegExp* create(JSGlobalData&, const UString& pattern, RegExpFlags); + static void destroy(JSCell*); + + bool global() const { return m_flags & FlagGlobal; } + bool ignoreCase() const { return m_flags & FlagIgnoreCase; } + bool multiline() const { return m_flags & FlagMultiline; } + + const UString& pattern() const { return m_patternString; } + + bool isValid() const { return !m_constructionError && m_flags != InvalidFlags; } + const char* errorMessage() const { return m_constructionError; } + + JS_EXPORT_PRIVATE int match(JSGlobalData&, const UString&, unsigned startOffset, Vector* ovector = 0); + unsigned numSubpatterns() const { return m_numSubpatterns; } + + bool hasCode() + { + return m_representation; + } + + void invalidateCode(); + +#if ENABLE(REGEXP_TRACING) + void printTraceData(); +#endif + + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + { + return Structure::create(globalData, globalObject, prototype, TypeInfo(LeafType, 0), &s_info); + } + + static JS_EXPORTDATA const ClassInfo s_info; + + RegExpKey key() { return RegExpKey(m_flags, m_patternString); } + + protected: + void finishCreation(JSGlobalData&); + + private: + friend class RegExpCache; + RegExp(JSGlobalData&, const UString&, RegExpFlags); + + static RegExp* createWithoutCaching(JSGlobalData&, const UString&, RegExpFlags); + + enum RegExpState { + ParseError, + JITCode, + ByteCode, + NotCompiled + } m_state; + + void compile(JSGlobalData*, Yarr::YarrCharSize); + void compileIfNecessary(JSGlobalData&, Yarr::YarrCharSize); + +#if ENABLE(YARR_JIT_DEBUG) + void matchCompareWithInterpreter(const UString&, int startOffset, int* offsetVector, int jitResult); +#endif + + UString m_patternString; + RegExpFlags m_flags; + const char* m_constructionError; + unsigned m_numSubpatterns; +#if ENABLE(REGEXP_TRACING) + unsigned m_rtMatchCallCount; + unsigned m_rtMatchFoundCount; +#endif + + OwnPtr m_representation; + }; + +} // namespace JSC + +#endif // RegExp_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/RegExpCache.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/RegExpCache.h new file mode 100644 index 000000000..4f3ea1536 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/RegExpCache.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2010 University of Szeged + * Copyright (C) 2010 Renata Hodovan (hodovan@inf.u-szeged.hu) + * 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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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 "RegExp.h" +#include "RegExpKey.h" +#include "Strong.h" +#include "UString.h" +#include "Weak.h" +#include +#include + +#ifndef RegExpCache_h +#define RegExpCache_h + +namespace JSC { + +class RegExpCache : private WeakHandleOwner { +friend class RegExp; +typedef HashMap > RegExpCacheMap; + +public: + RegExpCache(JSGlobalData* globalData); + void invalidateCode(); + +private: + + static const unsigned maxStrongCacheablePatternLength = 256; + + static const int maxStrongCacheableEntries = 32; + + virtual void finalize(Handle, void* context); + + RegExp* lookupOrCreate(const UString& patternString, RegExpFlags); + void addToStrongCache(RegExp*); + RegExpCacheMap m_weakCache; // Holds all regular expressions currently live. + int m_nextEntryInStrongCache; + WTF::FixedArray, maxStrongCacheableEntries> m_strongCache; // Holds a select few regular expressions that have compiled and executed + JSGlobalData* m_globalData; +}; + +} // namespace JSC + +#endif // RegExpCache_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/RegExpKey.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/RegExpKey.h new file mode 100644 index 000000000..b4847f971 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/RegExpKey.h @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2010 University of Szeged + * Copyright (C) 2010 Renata Hodovan (hodovan@inf.u-szeged.hu) + * 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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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 RegExpKey_h +#define RegExpKey_h + +#include "UString.h" +#include + +namespace JSC { + +enum RegExpFlags { + NoFlags = 0, + FlagGlobal = 1, + FlagIgnoreCase = 2, + FlagMultiline = 4, + InvalidFlags = 8, + DeletedValueFlags = -1 +}; + +struct RegExpKey { + RegExpFlags flagsValue; + RefPtr pattern; + + RegExpKey() + : flagsValue(NoFlags) + { + } + + RegExpKey(RegExpFlags flags) + : flagsValue(flags) + { + } + + RegExpKey(RegExpFlags flags, const UString& pattern) + : flagsValue(flags) + , pattern(pattern.impl()) + { + } + + RegExpKey(RegExpFlags flags, const PassRefPtr pattern) + : flagsValue(flags) + , pattern(pattern) + { + } + + RegExpKey(RegExpFlags flags, const RefPtr& pattern) + : flagsValue(flags) + , pattern(pattern) + { + } +}; + +inline bool operator==(const RegExpKey& a, const RegExpKey& b) +{ + if (a.flagsValue != b.flagsValue) + return false; + if (!a.pattern) + return !b.pattern; + if (!b.pattern) + return false; + return equal(a.pattern.get(), b.pattern.get()); +} + +} // namespace JSC + +namespace WTF { +template struct DefaultHash; +template struct RegExpHash; + +template<> struct RegExpHash { + static unsigned hash(const JSC::RegExpKey& key) { return key.pattern->hash(); } + static bool equal(const JSC::RegExpKey& a, const JSC::RegExpKey& b) { return a == b; } + static const bool safeToCompareToEmptyOrDeleted = false; +}; + +template<> struct DefaultHash { + typedef RegExpHash Hash; +}; + +template<> struct HashTraits : GenericHashTraits { + static void constructDeletedValue(JSC::RegExpKey& slot) { slot.flagsValue = JSC::DeletedValueFlags; } + static bool isDeletedValue(const JSC::RegExpKey& value) { return value.flagsValue == JSC::DeletedValueFlags; } +}; +} // namespace WTF + +#endif // RegExpKey_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/RegExpObject.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/RegExpObject.h new file mode 100644 index 000000000..081a7f111 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/RegExpObject.h @@ -0,0 +1,117 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2003, 2007, 2008 Apple Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef RegExpObject_h +#define RegExpObject_h + +#include "JSObject.h" +#include "RegExp.h" + +namespace JSC { + + class RegExpObject : public JSNonFinalObject { + public: + typedef JSNonFinalObject Base; + + static RegExpObject* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, RegExp* regExp) + { + RegExpObject* object = new (NotNull, allocateCell(*exec->heap())) RegExpObject(globalObject, structure, regExp); + object->finishCreation(globalObject); + return object; + } + + static RegExpObject* create(JSGlobalData& globalData, JSGlobalObject* globalObject, Structure* structure, RegExp* regExp) + { + RegExpObject* object = new (NotNull, allocateCell(globalData.heap)) RegExpObject(globalObject, structure, regExp); + object->finishCreation(globalObject); + return object; + } + + void setRegExp(JSGlobalData& globalData, RegExp* r) { d->regExp.set(globalData, this, r); } + RegExp* regExp() const { return d->regExp.get(); } + + void setLastIndex(size_t lastIndex) + { + d->lastIndex.setWithoutWriteBarrier(jsNumber(lastIndex)); + } + void setLastIndex(JSGlobalData& globalData, JSValue lastIndex) + { + d->lastIndex.set(globalData, this, lastIndex); + } + JSValue getLastIndex() const + { + return d->lastIndex.get(); + } + + JSValue test(ExecState*); + JSValue exec(ExecState*); + + static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier& propertyName, PropertySlot&); + static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); + static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); + + static JS_EXPORTDATA const ClassInfo s_info; + + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + { + return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); + } + + protected: + JS_EXPORT_PRIVATE RegExpObject(JSGlobalObject*, Structure*, RegExp*); + JS_EXPORT_PRIVATE void finishCreation(JSGlobalObject*); + static void destroy(JSCell*); + + static const unsigned StructureFlags = OverridesVisitChildren | OverridesGetOwnPropertySlot | Base::StructureFlags; + + static void visitChildren(JSCell*, SlotVisitor&); + + private: + bool match(ExecState*); + + struct RegExpObjectData { + WTF_MAKE_FAST_ALLOCATED; + public: + RegExpObjectData(JSGlobalData& globalData, RegExpObject* owner, RegExp* regExp) + : regExp(globalData, owner, regExp) + { + lastIndex.setWithoutWriteBarrier(jsNumber(0)); + } + + WriteBarrier regExp; + WriteBarrier lastIndex; + }; +#if COMPILER(MSVC) + friend void WTF::deleteOwnedPtr(RegExpObjectData*); +#endif + OwnPtr d; + }; + + RegExpObject* asRegExpObject(JSValue); + + inline RegExpObject* asRegExpObject(JSValue value) + { + ASSERT(asObject(value)->inherits(&RegExpObject::s_info)); + return static_cast(asObject(value)); + } + +} // namespace JSC + +#endif // RegExpObject_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Register.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Register.h new file mode 100644 index 000000000..f3b2125cb --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Register.h @@ -0,0 +1,228 @@ +/* + * Copyright (C) 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 Register_h +#define Register_h + +#include "JSValue.h" +#include +#include + +namespace JSC { + + class CodeBlock; + class ExecState; + class JSActivation; + class JSObject; + class JSPropertyNameIterator; + class ScopeChainNode; + + struct InlineCallFrame; + struct Instruction; + + typedef ExecState CallFrame; + + class Register { + WTF_MAKE_FAST_ALLOCATED; + public: + Register(); + + Register(const JSValue&); + Register& operator=(const JSValue&); + JSValue jsValue() const; + EncodedJSValue encodedJSValue() const; + + Register& operator=(CallFrame*); + Register& operator=(CodeBlock*); + Register& operator=(ScopeChainNode*); + Register& operator=(Instruction*); + Register& operator=(InlineCallFrame*); + + int32_t i() const; + JSActivation* activation() const; + CallFrame* callFrame() const; + CodeBlock* codeBlock() const; + JSObject* function() const; + JSPropertyNameIterator* propertyNameIterator() const; + ScopeChainNode* scopeChain() const; + Instruction* vPC() const; + InlineCallFrame* asInlineCallFrame() const; + int32_t unboxedInt32() const; + bool unboxedBoolean() const; + JSCell* unboxedCell() const; + int32_t payload() const; + int32_t tag() const; + int32_t& payload(); + int32_t& tag(); + + static Register withInt(int32_t i) + { + Register r = jsNumber(i); + return r; + } + + static inline Register withCallee(JSObject* callee); + + private: + union { + EncodedJSValue value; + CallFrame* callFrame; + CodeBlock* codeBlock; + Instruction* vPC; + InlineCallFrame* inlineCallFrame; + EncodedValueDescriptor encodedValue; + } u; + }; + + ALWAYS_INLINE Register::Register() + { +#ifndef NDEBUG + *this = JSValue(); +#endif + } + + ALWAYS_INLINE Register::Register(const JSValue& v) + { + u.value = JSValue::encode(v); + } + + ALWAYS_INLINE Register& Register::operator=(const JSValue& v) + { + u.value = JSValue::encode(v); + return *this; + } + + ALWAYS_INLINE JSValue Register::jsValue() const + { + return JSValue::decode(u.value); + } + + ALWAYS_INLINE EncodedJSValue Register::encodedJSValue() const + { + return u.value; + } + + // Interpreter functions + + ALWAYS_INLINE Register& Register::operator=(CallFrame* callFrame) + { + u.callFrame = callFrame; + return *this; + } + + ALWAYS_INLINE Register& Register::operator=(CodeBlock* codeBlock) + { + u.codeBlock = codeBlock; + return *this; + } + + ALWAYS_INLINE Register& Register::operator=(Instruction* vPC) + { + u.vPC = vPC; + return *this; + } + + ALWAYS_INLINE Register& Register::operator=(InlineCallFrame* inlineCallFrame) + { + u.inlineCallFrame = inlineCallFrame; + return *this; + } + + ALWAYS_INLINE int32_t Register::i() const + { + return jsValue().asInt32(); + } + + ALWAYS_INLINE CallFrame* Register::callFrame() const + { + return u.callFrame; + } + + ALWAYS_INLINE CodeBlock* Register::codeBlock() const + { + return u.codeBlock; + } + + ALWAYS_INLINE Instruction* Register::vPC() const + { + return u.vPC; + } + + ALWAYS_INLINE InlineCallFrame* Register::asInlineCallFrame() const + { + return u.inlineCallFrame; + } + + ALWAYS_INLINE int32_t Register::unboxedInt32() const + { + return payload(); + } + + ALWAYS_INLINE bool Register::unboxedBoolean() const + { + return !!payload(); + } + + ALWAYS_INLINE JSCell* Register::unboxedCell() const + { +#if USE(JSVALUE64) + return u.encodedValue.ptr; +#else + return bitwise_cast(payload()); +#endif + } + + ALWAYS_INLINE int32_t Register::payload() const + { + return u.encodedValue.asBits.payload; + } + + ALWAYS_INLINE int32_t Register::tag() const + { + return u.encodedValue.asBits.tag; + } + + ALWAYS_INLINE int32_t& Register::payload() + { + return u.encodedValue.asBits.payload; + } + + ALWAYS_INLINE int32_t& Register::tag() + { + return u.encodedValue.asBits.tag; + } + +} // namespace JSC + +namespace WTF { + + template<> struct VectorTraits : VectorTraitsBase { }; + +} // namespace WTF + +#endif // Register_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/RegisterFile.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/RegisterFile.h new file mode 100644 index 000000000..e45b869a1 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/RegisterFile.h @@ -0,0 +1,120 @@ +/* + * Copyright (C) 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 RegisterFile_h +#define RegisterFile_h + +#include "ExecutableAllocator.h" +#include "Register.h" +#include +#include +#include + +namespace JSC { + + class ConservativeRoots; + class DFGCodeBlocks; + + class RegisterFile { + WTF_MAKE_NONCOPYABLE(RegisterFile); + public: + enum CallFrameHeaderEntry { + CallFrameHeaderSize = 6, + + ArgumentCount = -6, + CallerFrame = -5, + Callee = -4, + ScopeChain = -3, + ReturnPC = -2, // This is either an Instruction* or a pointer into JIT generated code stored as an Instruction*. + CodeBlock = -1, + }; + + static const size_t defaultCapacity = 512 * 1024; + static const size_t commitSize = 16 * 1024; + // Allow 8k of excess registers before we start trying to reap the registerfile + static const ptrdiff_t maxExcessCapacity = 8 * 1024; + + RegisterFile(size_t capacity = defaultCapacity); + ~RegisterFile(); + + void gatherConservativeRoots(ConservativeRoots&); + void gatherConservativeRoots(ConservativeRoots&, DFGCodeBlocks&); + + Register* begin() const { return static_cast(m_reservation.base()); } + Register* end() const { return m_end; } + size_t size() const { return end() - begin(); } + + bool grow(Register*); + void shrink(Register*); + + static size_t committedByteCount(); + static void initializeThreading(); + + Register* const * addressOfEnd() const + { + return &m_end; + } + + private: + bool growSlowCase(Register*); + void releaseExcessCapacity(); + void addToCommittedByteCount(long); + Register* m_end; + Register* m_commitEnd; + PageReservation m_reservation; + }; + + inline RegisterFile::RegisterFile(size_t capacity) + : m_end(0) + { + ASSERT(capacity && isPageAligned(capacity)); + + m_reservation = PageReservation::reserve(roundUpAllocationSize(capacity * sizeof(Register), commitSize), OSAllocator::JSVMStackPages); + m_end = static_cast(m_reservation.base()); + m_commitEnd = static_cast(m_reservation.base()); + } + + inline void RegisterFile::shrink(Register* newEnd) + { + if (newEnd >= m_end) + return; + m_end = newEnd; + if (m_end == m_reservation.base() && (m_commitEnd - begin()) >= maxExcessCapacity) + releaseExcessCapacity(); + } + + inline bool RegisterFile::grow(Register* newEnd) + { + if (newEnd <= m_end) + return true; + return growSlowCase(newEnd); + } + +} // namespace JSC + +#endif // RegisterFile_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ResultType.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ResultType.h new file mode 100644 index 000000000..27b8112a0 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ResultType.h @@ -0,0 +1,182 @@ +/* + * Copyright (C) 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 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 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 ResultType_h +#define ResultType_h + +namespace JSC { + + struct ResultType { + friend struct OperandTypes; + + typedef char Type; + static const Type TypeReusable = 1; + static const Type TypeInt32 = 2; + + static const Type TypeMaybeNumber = 0x04; + static const Type TypeMaybeString = 0x08; + static const Type TypeMaybeNull = 0x10; + static const Type TypeMaybeBool = 0x20; + static const Type TypeMaybeOther = 0x40; + + static const Type TypeBits = TypeMaybeNumber | TypeMaybeString | TypeMaybeNull | TypeMaybeBool | TypeMaybeOther; + + explicit ResultType(Type type) + : m_type(type) + { + } + + bool isReusable() + { + return m_type & TypeReusable; + } + + bool isInt32() + { + return m_type & TypeInt32; + } + + bool definitelyIsNumber() + { + return (m_type & TypeBits) == TypeMaybeNumber; + } + + bool definitelyIsString() + { + return (m_type & TypeBits) == TypeMaybeString; + } + + bool mightBeNumber() + { + return m_type & TypeMaybeNumber; + } + + bool isNotNumber() + { + return !mightBeNumber(); + } + + static ResultType nullType() + { + return ResultType(TypeMaybeNull); + } + + static ResultType booleanType() + { + return ResultType(TypeMaybeBool); + } + + static ResultType numberType() + { + return ResultType(TypeMaybeNumber); + } + + static ResultType numberTypeCanReuse() + { + return ResultType(TypeReusable | TypeMaybeNumber); + } + + static ResultType numberTypeCanReuseIsInt32() + { + return ResultType(TypeReusable | TypeInt32 | TypeMaybeNumber); + } + + static ResultType stringOrNumberTypeCanReuse() + { + return ResultType(TypeReusable | TypeMaybeNumber | TypeMaybeString); + } + + static ResultType stringType() + { + return ResultType(TypeMaybeString); + } + + static ResultType unknownType() + { + return ResultType(TypeBits); + } + + static ResultType forAdd(ResultType op1, ResultType op2) + { + if (op1.definitelyIsNumber() && op2.definitelyIsNumber()) + return numberTypeCanReuse(); + if (op1.definitelyIsString() || op2.definitelyIsString()) + return stringType(); + return stringOrNumberTypeCanReuse(); + } + + static ResultType forBitOp() + { + return numberTypeCanReuseIsInt32(); + } + + private: + Type m_type; + }; + + struct OperandTypes + { + OperandTypes(ResultType first = ResultType::unknownType(), ResultType second = ResultType::unknownType()) + { + // We have to initialize one of the int to ensure that + // the entire struct is initialized. + m_u.i = 0; + m_u.rds.first = first.m_type; + m_u.rds.second = second.m_type; + } + + union { + struct { + ResultType::Type first; + ResultType::Type second; + } rds; + int i; + } m_u; + + ResultType first() + { + return ResultType(m_u.rds.first); + } + + ResultType second() + { + return ResultType(m_u.rds.second); + } + + int toInt() + { + return m_u.i; + } + static OperandTypes fromInt(int value) + { + OperandTypes types; + types.m_u.i = value; + return types; + } + }; + +} // namespace JSC + +#endif // ResultType_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/RetainPtr.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/RetainPtr.h new file mode 100644 index 000000000..3d4b0c3f9 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/RetainPtr.h @@ -0,0 +1,299 @@ +/* + * Copyright (C) 2005, 2006, 2007, 2008, 2010 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef RetainPtr_h +#define RetainPtr_h + +#include "HashTraits.h" +#include "NullPtr.h" +#include "TypeTraits.h" +#include + +#if USE(CF) +#include +#endif + +#ifdef __OBJC__ +#import +#endif + +namespace WTF { + + // Unlike most most of our smart pointers, RetainPtr can take either the pointer type or the pointed-to type, + // so both RetainPtr and RetainPtr will work. + + enum AdoptCFTag { AdoptCF }; + enum AdoptNSTag { AdoptNS }; + +#ifdef __OBJC__ + inline void adoptNSReference(id ptr) + { + if (ptr) { + CFRetain(ptr); + [ptr release]; + } + } +#endif + + template class RetainPtr { + public: + typedef typename RemovePointer::Type ValueType; + typedef ValueType* PtrType; + + RetainPtr() : m_ptr(0) {} + RetainPtr(PtrType ptr) : m_ptr(ptr) { if (ptr) CFRetain(ptr); } + + RetainPtr(AdoptCFTag, PtrType ptr) : m_ptr(ptr) { } + RetainPtr(AdoptNSTag, PtrType ptr) : m_ptr(ptr) { adoptNSReference(ptr); } + + RetainPtr(const RetainPtr& o) : m_ptr(o.m_ptr) { if (PtrType ptr = m_ptr) CFRetain(ptr); } + +#if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES) + RetainPtr(RetainPtr&& o) : m_ptr(o.leakRef()) { } +#endif + + // Hash table deleted values, which are only constructed and never copied or destroyed. + RetainPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { } + bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); } + + ~RetainPtr() { if (PtrType ptr = m_ptr) CFRelease(ptr); } + + template RetainPtr(const RetainPtr&); + + PtrType get() const { return m_ptr; } + + void clear(); + PtrType leakRef() WARN_UNUSED_RETURN; + + PtrType operator->() const { return m_ptr; } + + bool operator!() const { return !m_ptr; } + + // This conversion operator allows implicit conversion to bool but not to other integer types. + typedef PtrType RetainPtr::*UnspecifiedBoolType; + operator UnspecifiedBoolType() const { return m_ptr ? &RetainPtr::m_ptr : 0; } + + RetainPtr& operator=(const RetainPtr&); + template RetainPtr& operator=(const RetainPtr&); + RetainPtr& operator=(PtrType); + template RetainPtr& operator=(U*); + +#if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES) + RetainPtr& operator=(RetainPtr&&); + template RetainPtr& operator=(RetainPtr&&); +#endif + +#if !COMPILER_SUPPORTS(CXX_NULLPTR) + RetainPtr& operator=(std::nullptr_t) { clear(); return *this; } +#endif + + void adoptCF(PtrType); + void adoptNS(PtrType); + + void swap(RetainPtr&); + + private: + static PtrType hashTableDeletedValue() { return reinterpret_cast(-1); } + + PtrType m_ptr; + }; + + template template inline RetainPtr::RetainPtr(const RetainPtr& o) + : m_ptr(o.get()) + { + if (PtrType ptr = m_ptr) + CFRetain(ptr); + } + + template inline void RetainPtr::clear() + { + if (PtrType ptr = m_ptr) { + m_ptr = 0; + CFRelease(ptr); + } + } + + template inline typename RetainPtr::PtrType RetainPtr::leakRef() + { + PtrType ptr = m_ptr; + m_ptr = 0; + return ptr; + } + + template inline RetainPtr& RetainPtr::operator=(const RetainPtr& o) + { + PtrType optr = o.get(); + if (optr) + CFRetain(optr); + PtrType ptr = m_ptr; + m_ptr = optr; + if (ptr) + CFRelease(ptr); + return *this; + } + + template template inline RetainPtr& RetainPtr::operator=(const RetainPtr& o) + { + PtrType optr = o.get(); + if (optr) + CFRetain(optr); + PtrType ptr = m_ptr; + m_ptr = optr; + if (ptr) + CFRelease(ptr); + return *this; + } + + template inline RetainPtr& RetainPtr::operator=(PtrType optr) + { + if (optr) + CFRetain(optr); + PtrType ptr = m_ptr; + m_ptr = optr; + if (ptr) + CFRelease(ptr); + return *this; + } + + template template inline RetainPtr& RetainPtr::operator=(U* optr) + { + if (optr) + CFRetain(optr); + PtrType ptr = m_ptr; + m_ptr = optr; + if (ptr) + CFRelease(ptr); + return *this; + } + +#if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES) + template inline RetainPtr& RetainPtr::operator=(RetainPtr&& o) + { + adoptCF(o.leakRef()); + return *this; + } + + template template inline RetainPtr& RetainPtr::operator=(RetainPtr&& o) + { + adoptCF(o.leakRef()); + return *this; + } +#endif + + template inline void RetainPtr::adoptCF(PtrType optr) + { + PtrType ptr = m_ptr; + m_ptr = optr; + if (ptr) + CFRelease(ptr); + } + + template inline void RetainPtr::adoptNS(PtrType optr) + { + adoptNSReference(optr); + + PtrType ptr = m_ptr; + m_ptr = optr; + if (ptr) + CFRelease(ptr); + } + + template inline void RetainPtr::swap(RetainPtr& o) + { + std::swap(m_ptr, o.m_ptr); + } + + template inline void swap(RetainPtr& a, RetainPtr& b) + { + a.swap(b); + } + + template inline bool operator==(const RetainPtr& a, const RetainPtr& b) + { + return a.get() == b.get(); + } + + template inline bool operator==(const RetainPtr& a, U* b) + { + return a.get() == b; + } + + template inline bool operator==(T* a, const RetainPtr& b) + { + return a == b.get(); + } + + template inline bool operator!=(const RetainPtr& a, const RetainPtr& b) + { + return a.get() != b.get(); + } + + template inline bool operator!=(const RetainPtr& a, U* b) + { + return a.get() != b; + } + + template inline bool operator!=(T* a, const RetainPtr& b) + { + return a != b.get(); + } + + template inline RetainPtr adoptCF(T) WARN_UNUSED_RETURN; + template inline RetainPtr adoptCF(T o) + { + return RetainPtr(AdoptCF, o); + } + + template inline RetainPtr adoptNS(T) WARN_UNUSED_RETURN; + template inline RetainPtr adoptNS(T o) + { + return RetainPtr(AdoptNS, o); + } + + // Helper function for creating a RetainPtr using template argument deduction. + template inline RetainPtr retainPtr(T) WARN_UNUSED_RETURN; + template inline RetainPtr retainPtr(T o) + { + return RetainPtr(o); + } + + template struct HashTraits > : SimpleClassHashTraits > { }; + + template struct PtrHash > : PtrHash::PtrType> { + using PtrHash::PtrType>::hash; + static unsigned hash(const RetainPtr

& key) { return hash(key.get()); } + using PtrHash::PtrType>::equal; + static bool equal(const RetainPtr

& a, const RetainPtr

& b) { return a == b; } + static bool equal(typename RetainPtr

::PtrType a, const RetainPtr

& b) { return a == b; } + static bool equal(const RetainPtr

& a, typename RetainPtr

::PtrType b) { return a == b; } + }; + + template struct DefaultHash > { typedef PtrHash > Hash; }; + +} // namespace WTF + +using WTF::AdoptCF; +using WTF::AdoptNS; +using WTF::adoptCF; +using WTF::adoptNS; +using WTF::RetainPtr; +using WTF::retainPtr; + +#endif // WTF_RetainPtr_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SHA1.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SHA1.h new file mode 100644 index 000000000..e8cc802e9 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SHA1.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2011 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 WTF_SHA1_h +#define WTF_SHA1_h + +#include + +namespace WTF { + +class SHA1 { +public: + WTF_EXPORT_PRIVATE SHA1(); + + void addBytes(const Vector& input) + { + addBytes(input.data(), input.size()); + } + WTF_EXPORT_PRIVATE void addBytes(const uint8_t* input, size_t length); + + // computeHash has a side effect of resetting the state of the object. + WTF_EXPORT_PRIVATE void computeHash(Vector&); + +private: + void finalize(); + void processBlock(); + void reset(); + + uint8_t m_buffer[64]; + size_t m_cursor; // Number of bytes filled in m_buffer (0-64). + uint64_t m_totalBytes; // Number of bytes added so far. + uint32_t m_hash[5]; +}; + +} // namespace WTF + +using WTF::SHA1; + +#endif // WTF_SHA1_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SamplingCounter.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SamplingCounter.h new file mode 100644 index 000000000..329a5cfd3 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SamplingCounter.h @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2011 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 SamplingCounter_h +#define SamplingCounter_h + +#include +#include + +namespace JSC { + +// AbstractSamplingCounter: +// +// Implements a named set of counters, printed on exit if ENABLE(SAMPLING_COUNTERS). +// See subclasses below, SamplingCounter, GlobalSamplingCounter and DeletableSamplingCounter. +class AbstractSamplingCounter { + friend class DeletableSamplingCounter; +public: + void count(uint32_t count = 1) + { + m_counter += count; + } + + JS_EXPORT_PRIVATE static void dump(); + + int64_t* addressOfCounter() { return &m_counter; } + +protected: + // Effectively the contructor, however called lazily in the case of GlobalSamplingCounter. + void init(const char* name) + { + m_counter = 0; + m_name = name; + + // Set m_next to point to the head of the chain, and inform whatever is + // currently at the head that this node will now hold the pointer to it. + m_next = s_abstractSamplingCounterChain; + s_abstractSamplingCounterChain->m_referer = &m_next; + // Add this node to the head of the list. + s_abstractSamplingCounterChain = this; + m_referer = &s_abstractSamplingCounterChain; + } + + int64_t m_counter; + const char* m_name; + AbstractSamplingCounter* m_next; + // This is a pointer to the pointer to this node in the chain; used to + // allow fast linked list deletion. + AbstractSamplingCounter** m_referer; + // Null object used to detect end of static chain. + static AbstractSamplingCounter s_abstractSamplingCounterChainEnd; + JS_EXPORTDATA static AbstractSamplingCounter* s_abstractSamplingCounterChain; + static bool s_completed; +}; + +#if ENABLE(SAMPLING_COUNTERS) +// SamplingCounter: +// +// This class is suitable and (hopefully!) convenient for cases where a counter is +// required within the scope of a single function. It can be instantiated as a +// static variable since it contains a constructor but not a destructor (static +// variables in WebKit cannot have destructors). +// +// For example: +// +// void someFunction() +// { +// static SamplingCounter countMe("This is my counter. There are many like it, but this one is mine."); +// countMe.count(); +// // ... +// } +// +class SamplingCounter : public AbstractSamplingCounter { +public: + SamplingCounter(const char* name) { init(name); } +}; + +// GlobalSamplingCounter: +// +// This class is suitable for use where a counter is to be declared globally, +// since it contains neither a constructor nor destructor. Instead, ensure +// that 'name()' is called to provide the counter with a name (and also to +// allow it to be printed out on exit). +// +// GlobalSamplingCounter globalCounter; +// +// void firstFunction() +// { +// // Put this within a function that is definitely called! +// // (Or alternatively alongside all calls to 'count()'). +// globalCounter.name("I Name You Destroyer."); +// globalCounter.count(); +// // ... +// } +// +// void secondFunction() +// { +// globalCounter.count(); +// // ... +// } +// +class GlobalSamplingCounter : public AbstractSamplingCounter { +public: + void name(const char* name) + { + // Global objects should be mapped in zero filled memory, so this should + // be a safe (albeit not necessarily threadsafe) check for 'first call'. + if (!m_next) + init(name); + } +}; + +// DeletableSamplingCounter: +// +// The above classes (SamplingCounter, GlobalSamplingCounter), are intended for +// use within a global or static scope, and as such cannot have a destructor. +// This means there is no convenient way for them to remove themselves from the +// static list of counters, and should an instance of either class be freed +// before 'dump()' has walked over the list it will potentially walk over an +// invalid pointer. +// +// This class is intended for use where the counter may possibly be deleted before +// the program exits. Should this occur, the counter will print it's value to +// stderr, and remove itself from the static list. Example: +// +// DeletableSamplingCounter* counter = new DeletableSamplingCounter("The Counter With No Name"); +// counter->count(); +// delete counter; +// +class DeletableSamplingCounter : public AbstractSamplingCounter { +public: + DeletableSamplingCounter(const char* name) { init(name); } + + ~DeletableSamplingCounter() + { + if (!s_completed) + fprintf(stderr, "DeletableSamplingCounter \"%s\" deleted early (with count %lld)\n", m_name, m_counter); + // Our m_referer pointer should know where the pointer to this node is, + // and m_next should know that this node is the previous node in the list. + ASSERT(*m_referer == this); + ASSERT(m_next->m_referer == &m_next); + // Remove this node from the list, and inform m_next that we have done so. + m_next->m_referer = m_referer; + *m_referer = m_next; + } +}; +#endif + +} // namespace JSC + +#endif // SamplingCounter_h + + diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SamplingTool.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SamplingTool.h new file mode 100644 index 000000000..32a44ad69 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SamplingTool.h @@ -0,0 +1,363 @@ +/* + * Copyright (C) 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. + * 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 SamplingTool_h +#define SamplingTool_h + +#include "Strong.h" +#include "Nodes.h" +#include "Opcode.h" +#include "SamplingCounter.h" +#include +#include +#include +#include +#include + +namespace JSC { + + class ScriptExecutable; + + class SamplingFlags { + public: + JS_EXPORT_PRIVATE static void start(); + JS_EXPORT_PRIVATE static void stop(); + +#if ENABLE(SAMPLING_FLAGS) + static void setFlag(unsigned flag) + { + ASSERT(flag >= 1); + ASSERT(flag <= 32); + s_flags |= 1u << (flag - 1); + } + + static void clearFlag(unsigned flag) + { + ASSERT(flag >= 1); + ASSERT(flag <= 32); + s_flags &= ~(1u << (flag - 1)); + } + + static void sample(); + + class ScopedFlag { + public: + ScopedFlag(int flag) + : m_flag(flag) + { + setFlag(flag); + } + + ~ScopedFlag() + { + clearFlag(m_flag); + } + + private: + int m_flag; + }; + + static const void* addressOfFlags() + { + return &s_flags; + } + +#endif + private: + JS_EXPORTDATA static uint32_t s_flags; +#if ENABLE(SAMPLING_FLAGS) + static uint64_t s_flagCounts[33]; +#endif + }; + +#if ENABLE(SAMPLING_REGIONS) + class SamplingRegion { + public: + // Create a scoped sampling region using a C string constant name that describes + // what you are doing. This must be a string constant that persists for the + // lifetime of the process and is immutable. + SamplingRegion(const char* name) + { + if (!isMainThread()) { + m_name = 0; + return; + } + + m_name = name; + exchangeCurrent(this, &m_previous); + ASSERT(!m_previous || m_previous > this); + } + + ~SamplingRegion() + { + if (!m_name) + return; + + ASSERT(bitwise_cast(s_currentOrReserved & ~1) == this); + exchangeCurrent(m_previous); + } + + static void sample(); + + static void dump(); + + private: + const char* m_name; + SamplingRegion* m_previous; + + static void exchangeCurrent(SamplingRegion* current, SamplingRegion** previousPtr = 0) + { + uintptr_t previous; + while (true) { + previous = s_currentOrReserved; + + // If it's reserved (i.e. sampling thread is reading it), loop around. + if (previous & 1) { +#if OS(UNIX) + sched_yield(); +#endif + continue; + } + + // If we're going to CAS, then make sure previous is set. + if (previousPtr) + *previousPtr = bitwise_cast(previous); + + if (WTF::weakCompareAndSwap(&s_currentOrReserved, previous, bitwise_cast(current))) + break; + } + } + + static void dumpInternal(); + + class Locker { + public: + Locker(); + ~Locker(); + }; + + static volatile uintptr_t s_currentOrReserved; + + // rely on identity hashing of string constants + static Spectrum* s_spectrum; + + static unsigned long s_noneOfTheAbove; + + static unsigned s_numberOfSamplesSinceDump; + }; +#else // ENABLE(SAMPLING_REGIONS) + class SamplingRegion { + public: + SamplingRegion(const char*) { } + JS_EXPORT_PRIVATE void dump(); + }; +#endif // ENABLE(SAMPLING_REGIONS) + + class CodeBlock; + class ExecState; + class Interpreter; + class ScopeNode; + struct Instruction; + + struct ScriptSampleRecord { + ScriptSampleRecord(JSGlobalData& globalData, ScriptExecutable* executable) + : m_executable(globalData, executable) + , m_codeBlock(0) + , m_sampleCount(0) + , m_opcodeSampleCount(0) + , m_samples(0) + , m_size(0) + { + } + + ~ScriptSampleRecord() + { + if (m_samples) + free(m_samples); + } + + void sample(CodeBlock*, Instruction*); + + Strong m_executable; + CodeBlock* m_codeBlock; + int m_sampleCount; + int m_opcodeSampleCount; + int* m_samples; + unsigned m_size; + }; + + typedef HashMap > ScriptSampleRecordMap; + + class SamplingThread { + public: + // Sampling thread state. + static bool s_running; + static unsigned s_hertz; + static ThreadIdentifier s_samplingThread; + + JS_EXPORT_PRIVATE static void start(unsigned hertz=10000); + JS_EXPORT_PRIVATE static void stop(); + + static void* threadStartFunc(void*); + }; + + class SamplingTool { + public: + friend struct CallRecord; + friend class HostCallRecord; + +#if ENABLE(OPCODE_SAMPLING) + class CallRecord { + WTF_MAKE_NONCOPYABLE(CallRecord); + public: + CallRecord(SamplingTool* samplingTool) + : m_samplingTool(samplingTool) + , m_savedSample(samplingTool->m_sample) + , m_savedCodeBlock(samplingTool->m_codeBlock) + { + } + + ~CallRecord() + { + m_samplingTool->m_sample = m_savedSample; + m_samplingTool->m_codeBlock = m_savedCodeBlock; + } + + private: + SamplingTool* m_samplingTool; + intptr_t m_savedSample; + CodeBlock* m_savedCodeBlock; + }; + + class HostCallRecord : public CallRecord { + public: + HostCallRecord(SamplingTool* samplingTool) + : CallRecord(samplingTool) + { + samplingTool->m_sample |= 0x1; + } + }; +#else + class CallRecord { + WTF_MAKE_NONCOPYABLE(CallRecord); + public: + CallRecord(SamplingTool*) + { + } + }; + + class HostCallRecord : public CallRecord { + public: + HostCallRecord(SamplingTool* samplingTool) + : CallRecord(samplingTool) + { + } + }; +#endif + + SamplingTool(Interpreter* interpreter) + : m_interpreter(interpreter) + , m_codeBlock(0) + , m_sample(0) + , m_sampleCount(0) + , m_opcodeSampleCount(0) +#if ENABLE(CODEBLOCK_SAMPLING) + , m_scopeSampleMap(adoptPtr(new ScriptSampleRecordMap)) +#endif + { + memset(m_opcodeSamples, 0, sizeof(m_opcodeSamples)); + memset(m_opcodeSamplesInCTIFunctions, 0, sizeof(m_opcodeSamplesInCTIFunctions)); + } + + JS_EXPORT_PRIVATE void setup(); + void dump(ExecState*); + + void notifyOfScope(JSGlobalData&, ScriptExecutable* scope); + + void sample(CodeBlock* codeBlock, Instruction* vPC) + { + ASSERT(!(reinterpret_cast(vPC) & 0x3)); + m_codeBlock = codeBlock; + m_sample = reinterpret_cast(vPC); + } + + CodeBlock** codeBlockSlot() { return &m_codeBlock; } + intptr_t* sampleSlot() { return &m_sample; } + + void* encodeSample(Instruction* vPC, bool inCTIFunction = false, bool inHostFunction = false) + { + ASSERT(!(reinterpret_cast(vPC) & 0x3)); + return reinterpret_cast(reinterpret_cast(vPC) | (static_cast(inCTIFunction) << 1) | static_cast(inHostFunction)); + } + + static void sample(); + + private: + class Sample { + public: + Sample(volatile intptr_t sample, CodeBlock* volatile codeBlock) + : m_sample(sample) + , m_codeBlock(codeBlock) + { + } + + bool isNull() { return !m_sample; } + CodeBlock* codeBlock() { return m_codeBlock; } + Instruction* vPC() { return reinterpret_cast(m_sample & ~0x3); } + bool inHostFunction() { return m_sample & 0x1; } + bool inCTIFunction() { return m_sample & 0x2; } + + private: + intptr_t m_sample; + CodeBlock* m_codeBlock; + }; + + void doRun(); + static SamplingTool* s_samplingTool; + + Interpreter* m_interpreter; + + // State tracked by the main thread, used by the sampling thread. + CodeBlock* m_codeBlock; + intptr_t m_sample; + + // Gathered sample data. + long long m_sampleCount; + long long m_opcodeSampleCount; + unsigned m_opcodeSamples[numOpcodeIDs]; + unsigned m_opcodeSamplesInCTIFunctions[numOpcodeIDs]; + +#if ENABLE(CODEBLOCK_SAMPLING) + Mutex m_scriptSampleMapMutex; + OwnPtr m_scopeSampleMap; +#endif + }; + +} // namespace JSC + +#endif // SamplingTool_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ScopeChain.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ScopeChain.h new file mode 100644 index 000000000..6e358d779 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ScopeChain.h @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2003, 2008, 2009 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef ScopeChain_h +#define ScopeChain_h + +#include "JSCell.h" +#include "Structure.h" +#include + +namespace JSC { + + class JSGlobalData; + class JSGlobalObject; + class JSObject; + class ScopeChainIterator; + class SlotVisitor; + + class ScopeChainNode : public JSCell { + private: + ScopeChainNode(ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis) + : JSCell(*globalData, globalData->scopeChainNodeStructure.get()) + , globalData(globalData) + , next(*globalData, this, next, WriteBarrier::MayBeNull) + , object(*globalData, this, object) + , globalObject(*globalData, this, globalObject) + , globalThis(*globalData, this, globalThis) + { + } + + protected: + void finishCreation(JSGlobalData* globalData, JSGlobalObject* globalObject) + { + Base::finishCreation(*globalData); + ASSERT_UNUSED(globalObject, globalObject); + } + + public: + typedef JSCell Base; + + static ScopeChainNode* create(ExecState* exec, ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis) + { + ScopeChainNode* node = new (NotNull, allocateCell(*exec->heap())) ScopeChainNode(next, object, globalData, globalObject, globalThis); + node->finishCreation(globalData, globalObject); + return node; + } + static ScopeChainNode* create(ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis) + { + ScopeChainNode* node = new (NotNull, allocateCell(globalData->heap)) ScopeChainNode(next, object, globalData, globalObject, globalThis); + node->finishCreation(globalData, globalObject); + return node; + } + + JSGlobalData* globalData; + WriteBarrier next; + WriteBarrier object; + WriteBarrier globalObject; + WriteBarrier globalThis; + + ScopeChainNode* push(JSObject*); + ScopeChainNode* pop(); + + ScopeChainIterator begin(); + ScopeChainIterator end(); + + int localDepth(); + +#ifndef NDEBUG + void print(); +#endif + + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(globalData, globalObject, proto, TypeInfo(CompoundType, StructureFlags), &s_info); } + static void visitChildren(JSCell*, SlotVisitor&); + static JS_EXPORTDATA const ClassInfo s_info; + + private: + static const unsigned StructureFlags = OverridesVisitChildren; + }; + + inline ScopeChainNode* ScopeChainNode::push(JSObject* o) + { + ASSERT(o); + return ScopeChainNode::create(this, o, globalData, globalObject.get(), globalThis.get()); + } + + inline ScopeChainNode* ScopeChainNode::pop() + { + ASSERT(next); + return next.get(); + } + + class ScopeChainIterator { + public: + ScopeChainIterator(ScopeChainNode* node) + : m_node(node) + { + } + + WriteBarrier const & operator*() const { return m_node->object; } + WriteBarrier const * operator->() const { return &(operator*()); } + + ScopeChainIterator& operator++() { m_node = m_node->next.get(); return *this; } + + // postfix ++ intentionally omitted + + bool operator==(const ScopeChainIterator& other) const { return m_node == other.m_node; } + bool operator!=(const ScopeChainIterator& other) const { return m_node != other.m_node; } + + private: + ScopeChainNode* m_node; + }; + + inline ScopeChainIterator ScopeChainNode::begin() + { + return ScopeChainIterator(this); + } + + inline ScopeChainIterator ScopeChainNode::end() + { + return ScopeChainIterator(0); + } + + ALWAYS_INLINE JSGlobalData& ExecState::globalData() const + { + ASSERT(scopeChain()->globalData); + return *scopeChain()->globalData; + } + + ALWAYS_INLINE JSGlobalObject* ExecState::lexicalGlobalObject() const + { + return scopeChain()->globalObject.get(); + } + + ALWAYS_INLINE JSObject* ExecState::globalThisValue() const + { + return scopeChain()->globalThis.get(); + } + + ALWAYS_INLINE ScopeChainNode* Register::scopeChain() const + { + return static_cast(jsValue().asCell()); + } + + ALWAYS_INLINE Register& Register::operator=(ScopeChainNode* scopeChain) + { + *this = JSValue(scopeChain); + return *this; + } + +} // namespace JSC + +#endif // ScopeChain_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SegmentedVector.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SegmentedVector.h new file mode 100644 index 000000000..cb9a5f3a8 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SegmentedVector.h @@ -0,0 +1,255 @@ +/* + * Copyright (C) 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. + * 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 SegmentedVector_h +#define SegmentedVector_h + +#include + +namespace WTF { + + // An iterator for SegmentedVector. It supports only the pre ++ operator + template class SegmentedVector; + template class SegmentedVectorIterator { + private: + friend class SegmentedVector; + public: + typedef SegmentedVectorIterator Iterator; + + ~SegmentedVectorIterator() { } + + T& operator*() const { return m_vector.m_segments.at(m_segment)->at(m_index); } + T* operator->() const { return &m_vector.m_segments.at(m_segment)->at(m_index); } + + // Only prefix ++ operator supported + Iterator& operator++() + { + ASSERT(m_index != SegmentSize); + ++m_index; + if (m_index >= m_vector.m_segments.at(m_segment)->size()) { + if (m_segment + 1 < m_vector.m_segments.size()) { + ASSERT(m_vector.m_segments.at(m_segment)->size() > 0); + ++m_segment; + m_index = 0; + } else { + // Points to the "end" symbol + m_segment = 0; + m_index = SegmentSize; + } + } + return *this; + } + + bool operator==(const Iterator& other) const + { + return m_index == other.m_index && m_segment == other.m_segment && &m_vector == &other.m_vector; + } + + bool operator!=(const Iterator& other) const + { + return m_index != other.m_index || m_segment != other.m_segment || &m_vector != &other.m_vector; + } + + SegmentedVectorIterator& operator=(const SegmentedVectorIterator& other) + { + m_vector = other.m_vector; + m_segment = other.m_segment; + m_index = other.m_index; + return *this; + } + + private: + SegmentedVectorIterator(SegmentedVector& vector, size_t segment, size_t index) + : m_vector(vector) + , m_segment(segment) + , m_index(index) + { + } + + SegmentedVector& m_vector; + size_t m_segment; + size_t m_index; + }; + + // SegmentedVector is just like Vector, but it doesn't move the values + // stored in its buffer when it grows. Therefore, it is safe to keep + // pointers into a SegmentedVector. + template class SegmentedVector { + friend class SegmentedVectorIterator; + public: + typedef SegmentedVectorIterator Iterator; + + SegmentedVector() + : m_size(0) + { + m_segments.append(&m_inlineSegment); + } + + ~SegmentedVector() + { + deleteAllSegments(); + } + + size_t size() const { return m_size; } + bool isEmpty() const { return !size(); } + + T& at(size_t index) + { + if (index < SegmentSize) + return m_inlineSegment[index]; + return segmentFor(index)->at(subscriptFor(index)); + } + + T& operator[](size_t index) + { + return at(index); + } + + T& last() + { + return at(size() - 1); + } + + template void append(const U& value) + { + ++m_size; + + if (m_size <= SegmentSize) { + m_inlineSegment.uncheckedAppend(value); + return; + } + + if (!segmentExistsFor(m_size - 1)) + m_segments.append(new Segment); + segmentFor(m_size - 1)->uncheckedAppend(value); + } + + T& alloc() + { + append(T()); + return last(); + } + + void removeLast() + { + if (m_size <= SegmentSize) + m_inlineSegment.removeLast(); + else + segmentFor(m_size - 1)->removeLast(); + --m_size; + } + + void grow(size_t size) + { + ASSERT(size > m_size); + ensureSegmentsFor(size); + m_size = size; + } + + void clear() + { + deleteAllSegments(); + m_segments.resize(1); + m_inlineSegment.clear(); + m_size = 0; + } + + Iterator begin() + { + return Iterator(*this, 0, m_size ? 0 : SegmentSize); + } + + Iterator end() + { + return Iterator(*this, 0, SegmentSize); + } + + private: + typedef Vector Segment; + + void deleteAllSegments() + { + // Skip the first segment, because it's our inline segment, which was + // not created by new. + for (size_t i = 1; i < m_segments.size(); i++) + delete m_segments[i]; + } + + bool segmentExistsFor(size_t index) + { + return index / SegmentSize < m_segments.size(); + } + + Segment* segmentFor(size_t index) + { + return m_segments[index / SegmentSize]; + } + + size_t subscriptFor(size_t index) + { + return index % SegmentSize; + } + + void ensureSegmentsFor(size_t size) + { + size_t segmentCount = m_size / SegmentSize; + if (m_size % SegmentSize) + ++segmentCount; + segmentCount = std::max(segmentCount, 1); // We always have at least our inline segment. + + size_t neededSegmentCount = size / SegmentSize; + if (size % SegmentSize) + ++neededSegmentCount; + + // Fill up to N - 1 segments. + size_t end = neededSegmentCount - 1; + for (size_t i = segmentCount - 1; i < end; ++i) + ensureSegment(i, SegmentSize); + + // Grow segment N to accomodate the remainder. + ensureSegment(end, subscriptFor(size - 1) + 1); + } + + void ensureSegment(size_t segmentIndex, size_t size) + { + ASSERT(segmentIndex <= m_segments.size()); + if (segmentIndex == m_segments.size()) + m_segments.append(new Segment); + m_segments[segmentIndex]->grow(size); + } + + size_t m_size; + Segment m_inlineSegment; + Vector m_segments; + }; + +} // namespace WTF + +using WTF::SegmentedVector; + +#endif // SegmentedVector_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SentinelLinkedList.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SentinelLinkedList.h new file mode 100644 index 000000000..ecd602452 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SentinelLinkedList.h @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2011 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 INC. 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 INC. 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. + */ + +// A SentinelLinkedList is a linked list with dummy head and tail sentinels, +// which allow for branch-less insertion and removal, and removal without a +// pointer to the list. +// +// Requires: Node is a concrete class with: +// Node(SentinelTag); +// void setPrev(Node*); +// Node* prev(); +// void setNext(Node*); +// Node* next(); + +#ifndef SentinelLinkedList_h +#define SentinelLinkedList_h + +namespace WTF { + +enum SentinelTag { Sentinel }; + +template +class BasicRawSentinelNode { +public: + BasicRawSentinelNode(SentinelTag) + : m_next(0) + , m_prev(0) + { + } + + BasicRawSentinelNode() + : m_next(0) + , m_prev(0) + { + } + + void setPrev(BasicRawSentinelNode* prev) { m_prev = prev; } + void setNext(BasicRawSentinelNode* next) { m_next = next; } + + T* prev() { return static_cast(m_prev); } + T* next() { return static_cast(m_next); } + + bool isOnList() const + { + ASSERT(!!m_prev == !!m_next); + return !!m_prev; + } + + void remove(); + +private: + BasicRawSentinelNode* m_next; + BasicRawSentinelNode* m_prev; +}; + +template class SentinelLinkedList { +public: + typedef T* iterator; + + SentinelLinkedList(); + + void push(T*); + static void remove(T*); + + iterator begin(); + iterator end(); + +private: + RawNode m_headSentinel; + RawNode m_tailSentinel; +}; + +template void BasicRawSentinelNode::remove() +{ + SentinelLinkedList >::remove(static_cast(this)); +} + +template inline SentinelLinkedList::SentinelLinkedList() + : m_headSentinel(Sentinel) + , m_tailSentinel(Sentinel) +{ + m_headSentinel.setNext(&m_tailSentinel); + m_headSentinel.setPrev(0); + + m_tailSentinel.setPrev(&m_headSentinel); + m_tailSentinel.setNext(0); +} + +template inline typename SentinelLinkedList::iterator SentinelLinkedList::begin() +{ + return static_cast(m_headSentinel.next()); +} + +template inline typename SentinelLinkedList::iterator SentinelLinkedList::end() +{ + return static_cast(&m_tailSentinel); +} + +template inline void SentinelLinkedList::push(T* node) +{ + ASSERT(node); + ASSERT(!node->prev()); + ASSERT(!node->next()); + + RawNode* prev = &m_headSentinel; + RawNode* next = m_headSentinel.next(); + + node->setPrev(prev); + node->setNext(next); + + prev->setNext(node); + next->setPrev(node); +} + +template inline void SentinelLinkedList::remove(T* node) +{ + ASSERT(node); + ASSERT(!!node->prev()); + ASSERT(!!node->next()); + + RawNode* prev = node->prev(); + RawNode* next = node->next(); + + prev->setNext(next); + next->setPrev(prev); + + node->setPrev(0); + node->setNext(0); +} + +} + +using WTF::BasicRawSentinelNode; +using WTF::SentinelLinkedList; + +#endif + diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SinglyLinkedList.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SinglyLinkedList.h new file mode 100644 index 000000000..c00bf3687 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SinglyLinkedList.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2011 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 INC. 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 INC. 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 SinglyLinkedList_h +#define SinglyLinkedList_h + +namespace WTF { + +template class SinglyLinkedList { +public: + SinglyLinkedList(); + + bool isEmpty(); + + void push(Node*); + Node* pop(); + +private: + Node* m_head; +}; + +template inline SinglyLinkedList::SinglyLinkedList() + : m_head(0) +{ +} + +template inline bool SinglyLinkedList::isEmpty() +{ + return !m_head; +} + +template inline void SinglyLinkedList::push(Node* node) +{ + ASSERT(node); + node->setNext(m_head); + m_head = node; +} + +template inline Node* SinglyLinkedList::pop() +{ + Node* tmp = m_head; + m_head = m_head->next(); + return tmp; +} + +} + +using WTF::SinglyLinkedList; + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SlotVisitor.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SlotVisitor.h new file mode 100644 index 000000000..e49a9a637 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SlotVisitor.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2011 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 INC. 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 INC. 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 SlotVisitor_h +#define SlotVisitor_h + +#include "BumpSpace.h" +#include "MarkStack.h" + +namespace JSC { + +class Heap; + +class SlotVisitor : public MarkStack { + friend class HeapRootVisitor; +public: + SlotVisitor(MarkStackThreadSharedData&); + + void donate() + { + ASSERT(m_isInParallelMode); + if (Options::numberOfGCMarkers == 1) + return; + + donateKnownParallel(); + } + + void drain(); + + void donateAndDrain() + { + donate(); + drain(); + } + + enum SharedDrainMode { SlaveDrain, MasterDrain }; + void drainFromShared(SharedDrainMode); + + void harvestWeakReferences(); + void finalizeUnconditionalFinalizers(); + + void startCopying(); + void copy(void**, size_t); + void copyAndAppend(void**, size_t, JSValue*, unsigned); + void doneCopying(); + +private: + void* allocateNewSpace(void*, size_t); + + void donateSlow(); + + void donateKnownParallel() + { + if (!m_stack.canDonateSomeCells()) + return; + donateSlow(); + } + + BumpBlock* m_copyBlock; +}; + +inline SlotVisitor::SlotVisitor(MarkStackThreadSharedData& shared) + : MarkStack(shared) + , m_copyBlock(0) +{ +} + +} // namespace JSC + +#endif // SlotVisitor_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SmallStrings.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SmallStrings.h new file mode 100644 index 000000000..cd8e63095 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SmallStrings.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 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 SmallStrings_h +#define SmallStrings_h + +#include "UString.h" +#include +#include + +namespace JSC { + + class HeapRootVisitor; + class JSGlobalData; + class JSString; + class SmallStringsStorage; + class SlotVisitor; + + static const unsigned maxSingleCharacterString = 0xFF; + + class SmallStrings { + WTF_MAKE_NONCOPYABLE(SmallStrings); + public: + SmallStrings(); + ~SmallStrings(); + + JSString* emptyString(JSGlobalData* globalData) + { + if (!m_emptyString) + createEmptyString(globalData); + return m_emptyString; + } + + JSString* singleCharacterString(JSGlobalData* globalData, unsigned char character) + { + if (!m_singleCharacterStrings[character]) + createSingleCharacterString(globalData, character); + return m_singleCharacterStrings[character]; + } + + JS_EXPORT_PRIVATE StringImpl* singleCharacterStringRep(unsigned char character); + + void finalizeSmallStrings(); + void clear(); + + unsigned count() const; + + JSString** singleCharacterStrings() { return &m_singleCharacterStrings[0]; } + + private: + static const unsigned singleCharacterStringCount = maxSingleCharacterString + 1; + + JS_EXPORT_PRIVATE void createEmptyString(JSGlobalData*); + JS_EXPORT_PRIVATE void createSingleCharacterString(JSGlobalData*, unsigned char); + + JSString* m_emptyString; + JSString* m_singleCharacterStrings[singleCharacterStringCount]; + OwnPtr m_storage; + }; + +} // namespace JSC + +#endif // SmallStrings_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SourceCode.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SourceCode.h new file mode 100644 index 000000000..2a162b90f --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SourceCode.h @@ -0,0 +1,105 @@ +/* + * Copyright (C) 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. + * 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 SourceCode_h +#define SourceCode_h + +#include "SourceProvider.h" +#include + +namespace JSC { + + class SourceCode { + public: + SourceCode() + : m_provider(0) + , m_startChar(0) + , m_endChar(0) + , m_firstLine(0) + { + } + + SourceCode(PassRefPtr provider, int firstLine = 1) + : m_provider(provider) + , m_startChar(0) + , m_endChar(m_provider->length()) + , m_firstLine(std::max(firstLine, 1)) + { + } + + SourceCode(PassRefPtr provider, int start, int end, int firstLine) + : m_provider(provider) + , m_startChar(start) + , m_endChar(end) + , m_firstLine(std::max(firstLine, 1)) + { + } + + UString toString() const + { + if (!m_provider) + return UString(); + return m_provider->getRange(m_startChar, m_endChar); + } + + bool isNull() const { return !m_provider; } + SourceProvider* provider() const { return m_provider.get(); } + int firstLine() const { return m_firstLine; } + int startOffset() const { return m_startChar; } + int endOffset() const { return m_endChar; } + const UChar* data() const + { + ASSERT(m_provider->data()); + return m_provider->data()->characters16() + m_startChar; + } + int length() const { return m_endChar - m_startChar; } + + SourceCode subExpression(unsigned openBrace, unsigned closeBrace, int firstLine); + + private: + RefPtr m_provider; + int m_startChar; + int m_endChar; + int m_firstLine; + }; + + inline SourceCode makeSource(const UString& source, const UString& url = UString(), const TextPosition& startPosition = TextPosition::minimumPosition()) + { + return SourceCode(UStringSourceProvider::create(source, url, startPosition), startPosition.m_line.oneBasedInt()); + } + + inline SourceCode SourceCode::subExpression(unsigned openBrace, unsigned closeBrace, int firstLine) + { + ASSERT((*provider()->data())[openBrace] == '{'); + ASSERT((*provider()->data())[closeBrace] == '}'); + return SourceCode(provider(), openBrace, closeBrace + 1, firstLine); + } + +} // namespace JSC + +#endif // SourceCode_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SourceProvider.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SourceProvider.h new file mode 100644 index 000000000..dfc8d88e2 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SourceProvider.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) 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 SourceProvider_h +#define SourceProvider_h + +#include "SourceProviderCache.h" +#include "UString.h" +#include +#include +#include +#include + +namespace JSC { + + class SourceProvider : public RefCounted { + public: + SourceProvider(const UString& url, const TextPosition& startPosition, SourceProviderCache* cache = 0) + : m_url(url) + , m_startPosition(startPosition) + , m_validated(false) + , m_cache(cache ? cache : new SourceProviderCache) + , m_cacheOwned(!cache) + { + deprecatedTurnOffVerifier(); + } + virtual ~SourceProvider() + { + if (m_cacheOwned) + delete m_cache; + } + + virtual UString getRange(int start, int end) const = 0; + virtual const StringImpl* data() const = 0; + virtual int length() const = 0; + + const UString& url() { return m_url; } + TextPosition startPosition() const { return m_startPosition; } + intptr_t asID() { return reinterpret_cast(this); } + + bool isValid() const { return m_validated; } + void setValid() { m_validated = true; } + + SourceProviderCache* cache() const { return m_cache; } + void notifyCacheSizeChanged(int delta) { if (!m_cacheOwned) cacheSizeChanged(delta); } + + private: + virtual void cacheSizeChanged(int delta) { UNUSED_PARAM(delta); } + + UString m_url; + TextPosition m_startPosition; + bool m_validated; + SourceProviderCache* m_cache; + bool m_cacheOwned; + }; + + class UStringSourceProvider : public SourceProvider { + public: + static PassRefPtr create(const UString& source, const UString& url, const TextPosition& startPosition = TextPosition::minimumPosition()) + { + return adoptRef(new UStringSourceProvider(source, url, startPosition)); + } + + UString getRange(int start, int end) const + { + return m_source.substringSharingImpl(start, end - start); + } + const StringImpl* data() const { return m_source.impl(); } + int length() const { return m_source.length(); } + + private: + UStringSourceProvider(const UString& source, const UString& url, const TextPosition& startPosition) + : SourceProvider(url, startPosition) + , m_source(source) + { + } + + UString m_source; + }; + +} // namespace JSC + +#endif // SourceProvider_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SourceProviderCache.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SourceProviderCache.h new file mode 100644 index 000000000..e94230d10 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SourceProviderCache.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2011 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 INC. 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 INC. 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 SourceProviderCache_h +#define SourceProviderCache_h + +#include "SourceProviderCacheItem.h" +#include +#include +#include + +namespace JSC { + +class SourceProviderCache { +public: + SourceProviderCache() : m_contentByteSize(0) {} + JS_EXPORT_PRIVATE ~SourceProviderCache(); + + JS_EXPORT_PRIVATE void clear(); + JS_EXPORT_PRIVATE unsigned byteSize() const; + void add(int sourcePosition, PassOwnPtr, unsigned size); + const SourceProviderCacheItem* get(int sourcePosition) const { return m_map.get(sourcePosition); } + +private: + HashMap > m_map; + unsigned m_contentByteSize; +}; + +} + +#endif // SourceProviderCache_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SourceProviderCacheItem.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SourceProviderCacheItem.h new file mode 100644 index 000000000..3662367a0 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SourceProviderCacheItem.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2011 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 INC. 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 INC. 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 SourceProviderCacheItem_h +#define SourceProviderCacheItem_h + +#include "ParserTokens.h" +#include +#include + +namespace JSC { + +class SourceProviderCacheItem { +public: + SourceProviderCacheItem(int closeBraceLine, int closeBracePos) + : closeBraceLine(closeBraceLine) + , closeBracePos(closeBracePos) + { + } + unsigned approximateByteSize() const + { + // The identifiers are uniqued strings so most likely there are few names that actually use any additional memory. + static const unsigned assummedAverageIdentifierSize = sizeof(RefPtr) + 2; + unsigned size = sizeof(*this); + size += usedVariables.size() * assummedAverageIdentifierSize; + size += writtenVariables.size() * assummedAverageIdentifierSize; + return size; + } + JSToken closeBraceToken() const + { + JSToken token; + token.m_type = CLOSEBRACE; + token.m_data.intValue = closeBracePos; + token.m_info.startOffset = closeBracePos; + token.m_info.endOffset = closeBracePos + 1; + token.m_info.line = closeBraceLine; + return token; + } + + int closeBraceLine; + int closeBracePos; + bool usesEval; + bool strictMode; + bool needsFullActivation; + Vector > usedVariables; + Vector > writtenVariables; +}; + +} + +#endif // SourceProviderCacheItem_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Spectrum.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Spectrum.h new file mode 100644 index 000000000..c403eda18 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Spectrum.h @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2011 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 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 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 Spectrum_h +#define Spectrum_h + +#include "HashMap.h" +#include "Vector.h" +#include + +namespace WTF { + +template +class Spectrum { +public: + typedef typename HashMap::iterator iterator; + typedef typename HashMap::const_iterator const_iterator; + + Spectrum() { } + + void add(const T& key, unsigned long count = 1) + { + std::pair result = m_map.add(key, count); + if (!result.second) + result.first->second += count; + } + + unsigned long get(const T& key) const + { + const_iterator iter = m_map.find(key); + if (iter == m_map.end()) + return 0; + return iter->second; + } + + iterator begin() { return m_map.begin(); } + iterator end() { return m_map.end(); } + const_iterator begin() const { return m_map.begin(); } + const_iterator end() const { return m_map.end(); } + + struct KeyAndCount { + KeyAndCount() { } + + KeyAndCount(const T& key, unsigned long count) + : key(key) + , count(count) + { + } + + bool operator<(const KeyAndCount& other) const + { + if (count != other.count) + return count < other.count; + // This causes lower-ordered keys being returned first; this is really just + // here to make sure that the order is somewhat deterministic rather than being + // determined by hashing. + return key > other.key; + } + + T key; + unsigned long count; + }; + + // Returns a list ordered from lowest-count to highest-count. + Vector buildList() const + { + Vector list; + for (const_iterator iter = begin(); iter != end(); ++iter) + list.append(KeyAndCount(iter->first, iter->second)); + + std::sort(list.begin(), list.end()); + return list; + } + +private: + HashMap m_map; +}; + +} // namespace WTF + +using WTF::Spectrum; + +#endif // Spectrum_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StackBounds.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StackBounds.h new file mode 100644 index 000000000..afce8606f --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StackBounds.h @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2010 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 StackBounds_h +#define StackBounds_h + +namespace WTF { + +class StackBounds { + // recursionCheck() / recursionLimit() tests (by default) + // that we are at least this far from the end of the stack. + const static size_t s_defaultAvailabilityDelta = 4096; + +public: + StackBounds() + : m_origin(0) + , m_bound(0) + { + } + + static StackBounds currentThreadStackBounds() + { + StackBounds bounds; + bounds.initialize(); + bounds.checkConsistency(); + return bounds; + } + + void* origin() const + { + ASSERT(m_origin); + return m_origin; + } + + void* current() const + { + checkConsistency(); + void* currentPosition = ¤tPosition; + return currentPosition; + } + + void* recursionLimit(size_t minAvailableDelta = s_defaultAvailabilityDelta) const + { + checkConsistency(); + return isGrowingDownward() + ? static_cast(m_bound) + minAvailableDelta + : static_cast(m_bound) - minAvailableDelta; + } + + bool recursionCheck(size_t minAvailableDelta = s_defaultAvailabilityDelta) const + { + checkConsistency(); + return isGrowingDownward() + ? current() >= recursionLimit(minAvailableDelta) + : current() <= recursionLimit(minAvailableDelta); + } + +private: + void initialize(); + + + bool isGrowingDownward() const + { + ASSERT(m_origin && m_bound); +#if OS(WINCE) + return m_origin > m_bound; +#else + return true; +#endif + } + + void checkConsistency() const + { +#if !ASSERT_DISABLED + void* currentPosition = ¤tPosition; + ASSERT(m_origin != m_bound); + ASSERT(isGrowingDownward() + ? (currentPosition < m_origin && currentPosition > m_bound) + : (currentPosition > m_origin && currentPosition < m_bound)); +#endif + } + + void* m_origin; + void* m_bound; +}; + +} // namespace WTF + +using WTF::StackBounds; + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StaticConstructors.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StaticConstructors.h new file mode 100644 index 000000000..702c0ca5c --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StaticConstructors.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef StaticConstructors_h +#define StaticConstructors_h + +// We need to avoid having static constructors. We achieve this +// with two separate methods for GCC and MSVC. Both methods prevent the static +// initializers from being registered and called on program startup. On GCC, we +// declare the global objects with a different type that can be POD default +// initialized by the linker/loader. On MSVC we use a special compiler feature +// to have the CRT ignore our static initializers. The constructors will never +// be called and the objects will be left uninitialized. +// +// With both of these approaches, we must define and explicitly call an init +// routine that uses placement new to create the objects and overwrite the +// uninitialized placeholders. +// +// This is not completely portable, but is what we have for now without +// changing how a lot of code accesses these global objects. + +#ifdef SKIP_STATIC_CONSTRUCTORS_ON_MSVC +// - Assume that all includes of this header want ALL of their static +// initializers ignored. This is currently the case. This means that if +// a .cc includes this header (or it somehow gets included), all static +// initializers after the include will not be executed. +// - We do this with a pragma, so that all of the static initializer pointers +// go into our own section, and the CRT won't call them. Eventually it would +// be nice if the section was discarded, because we don't want the pointers. +// See: http://msdn.microsoft.com/en-us/library/7977wcck(VS.80).aspx +#pragma warning(disable:4075) +#pragma init_seg(".unwantedstaticinits") +#endif + +#ifndef SKIP_STATIC_CONSTRUCTORS_ON_GCC + // Define an global in the normal way. +#if COMPILER(MSVC7_OR_LOWER) +#define DEFINE_GLOBAL(type, name) \ + const type name; +#else +#define DEFINE_GLOBAL(type, name, ...) \ + const type name; +#endif + +#else +// Define an correctly-sized array of pointers to avoid static initialization. +// Use an array of pointers instead of an array of char in case there is some alignment issue. +#if COMPILER(MSVC7_OR_LOWER) +#define DEFINE_GLOBAL(type, name) \ + void * name[(sizeof(type) + sizeof(void *) - 1) / sizeof(void *)]; +#else +#define DEFINE_GLOBAL(type, name, ...) \ + void * name[(sizeof(type) + sizeof(void *) - 1) / sizeof(void *)]; +#endif +#endif + +#endif // StaticConstructors_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StdLibExtras.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StdLibExtras.h new file mode 100644 index 000000000..e4d7c8fc0 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StdLibExtras.h @@ -0,0 +1,299 @@ +/* + * Copyright (C) 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 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 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 WTF_StdLibExtras_h +#define WTF_StdLibExtras_h + +#include "CheckedArithmetic.h" +#include "Assertions.h" + +// Use these to declare and define a static local variable (static T;) so that +// it is leaked so that its destructors are not called at exit. Using this +// macro also allows workarounds a compiler bug present in Apple's version of GCC 4.0.1. +#ifndef DEFINE_STATIC_LOCAL +#if COMPILER(GCC) && defined(__APPLE_CC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 0 && __GNUC_PATCHLEVEL__ == 1 +#define DEFINE_STATIC_LOCAL(type, name, arguments) \ + static type* name##Ptr = new type arguments; \ + type& name = *name##Ptr +#else +#define DEFINE_STATIC_LOCAL(type, name, arguments) \ + static type& name = *new type arguments +#endif +#endif + +// Use this macro to declare and define a debug-only global variable that may have a +// non-trivial constructor and destructor. When building with clang, this will suppress +// warnings about global constructors and exit-time destructors. +#ifndef NDEBUG +#if COMPILER(CLANG) +#define DEFINE_DEBUG_ONLY_GLOBAL(type, name, arguments) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wglobal-constructors\"") \ + _Pragma("clang diagnostic ignored \"-Wexit-time-destructors\"") \ + static type name arguments; \ + _Pragma("clang diagnostic pop") +#else +#define DEFINE_DEBUG_ONLY_GLOBAL(type, name, arguments) \ + static type name arguments; +#endif // COMPILER(CLANG) +#else +#define DEFINE_DEBUG_ONLY_GLOBAL(type, name, arguments) +#endif // NDEBUG + +// OBJECT_OFFSETOF: Like the C++ offsetof macro, but you can use it with classes. +// The magic number 0x4000 is insignificant. We use it to avoid using NULL, since +// NULL can cause compiler problems, especially in cases of multiple inheritance. +#define OBJECT_OFFSETOF(class, field) (reinterpret_cast(&(reinterpret_cast(0x4000)->field)) - 0x4000) + +// STRINGIZE: Can convert any value to quoted string, even expandable macros +#define STRINGIZE(exp) #exp +#define STRINGIZE_VALUE_OF(exp) STRINGIZE(exp) + +/* + * The reinterpret_cast([pointer to Type2]) expressions - where + * sizeof(Type1) > sizeof(Type2) - cause the following warning on ARM with GCC: + * increases required alignment of target type. + * + * An implicit or an extra static_cast bypasses the warning. + * For more info see the following bugzilla entries: + * - https://bugs.webkit.org/show_bug.cgi?id=38045 + * - http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43976 + */ +#if (CPU(ARM) || CPU(MIPS)) && COMPILER(GCC) +template +bool isPointerTypeAlignmentOkay(Type* ptr) +{ + return !(reinterpret_cast(ptr) % __alignof__(Type)); +} + +template +TypePtr reinterpret_cast_ptr(void* ptr) +{ + ASSERT(isPointerTypeAlignmentOkay(reinterpret_cast(ptr))); + return reinterpret_cast(ptr); +} + +template +TypePtr reinterpret_cast_ptr(const void* ptr) +{ + ASSERT(isPointerTypeAlignmentOkay(reinterpret_cast(ptr))); + return reinterpret_cast(ptr); +} +#else +#define reinterpret_cast_ptr reinterpret_cast +#endif + +namespace WTF { + +static const size_t KB = 1024; + +inline bool isPointerAligned(void* p) +{ + return !((intptr_t)(p) & (sizeof(char*) - 1)); +} + +/* + * C++'s idea of a reinterpret_cast lacks sufficient cojones. + */ +template +inline TO bitwise_cast(FROM from) +{ + COMPILE_ASSERT(sizeof(TO) == sizeof(FROM), WTF_bitwise_cast_sizeof_casted_types_is_equal); + union { + FROM from; + TO to; + } u; + u.from = from; + return u.to; +} + +template +inline To safeCast(From value) +{ + ASSERT(isInBounds(value)); + return static_cast(value); +} + +// Returns a count of the number of bits set in 'bits'. +inline size_t bitCount(unsigned bits) +{ + bits = bits - ((bits >> 1) & 0x55555555); + bits = (bits & 0x33333333) + ((bits >> 2) & 0x33333333); + return (((bits + (bits >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24; +} + +// Macro that returns a compile time constant with the length of an array, but gives an error if passed a non-array. +template char (&ArrayLengthHelperFunction(T (&)[Size]))[Size]; +#define WTF_ARRAY_LENGTH(array) sizeof(::WTF::ArrayLengthHelperFunction(array)) + +// Efficient implementation that takes advantage of powers of two. +template inline size_t roundUpToMultipleOf(size_t x) +{ + COMPILE_ASSERT(divisor && !(divisor & (divisor - 1)), divisor_is_a_power_of_two); + + size_t remainderMask = divisor - 1; + return (x + remainderMask) & ~remainderMask; +} + +enum BinarySearchMode { + KeyMustBePresentInArray, + KeyMustNotBePresentInArray +}; + +// Binary search algorithm, calls extractKey on pre-sorted elements in array, +// compares result with key (KeyTypes should be comparable with '--', '<', '>'). +template +inline ArrayElementType* binarySearch(ArrayElementType* array, size_t size, KeyType key, BinarySearchMode mode = KeyMustBePresentInArray) +{ + // The array must contain at least one element (pre-condition, array does contain key). + // If the array contains only one element, no need to do the comparison. + while (size > 1) { + // Pick an element to check, half way through the array, and read the value. + int pos = (size - 1) >> 1; + KeyType val = extractKey(&array[pos]); + + // If the key matches, success! + if (val == key) + return &array[pos]; + // The item we are looking for is smaller than the item being check; reduce the value of 'size', + // chopping off the right hand half of the array. + else if (key < val) + size = pos; + // Discard all values in the left hand half of the array, up to and including the item at pos. + else { + size -= (pos + 1); + array += (pos + 1); + } + + // In case of BinarySearchMode = KeyMustBePresentInArray 'size' should never reach zero. + if (mode == KeyMustBePresentInArray) + ASSERT(size); + } + + // In case of BinarySearchMode = KeyMustBePresentInArray if we reach this point + // we've chopped down to one element, no need to check it matches + if (mode == KeyMustBePresentInArray) { + ASSERT(size == 1); + ASSERT(key == extractKey(&array[0])); + } + + return &array[0]; +} + +// Modified binary search algorithm that uses a functor. Note that this is strictly +// more powerful than the above, but results in somewhat less template specialization. +// Hence, depending on inlining heuristics, it might be slower. +template +inline ArrayElementType* binarySearchWithFunctor(ArrayElementType* array, size_t size, KeyType key, BinarySearchMode mode = KeyMustBePresentInArray, const ExtractKey& extractKey = ExtractKey()) +{ + // The array must contain at least one element (pre-condition, array does contain key). + // If the array contains only one element, no need to do the comparison. + while (size > 1) { + // Pick an element to check, half way through the array, and read the value. + int pos = (size - 1) >> 1; + KeyType val = extractKey(&array[pos]); + + // If the key matches, success! + if (val == key) + return &array[pos]; + // The item we are looking for is smaller than the item being check; reduce the value of 'size', + // chopping off the right hand half of the array. + else if (key < val) + size = pos; + // Discard all values in the left hand half of the array, up to and including the item at pos. + else { + size -= (pos + 1); + array += (pos + 1); + } + + // In case of BinarySearchMode = KeyMustBePresentInArray 'size' should never reach zero. + if (mode == KeyMustBePresentInArray) + ASSERT(size); + } + + // In case of BinarySearchMode = KeyMustBePresentInArray if we reach this point + // we've chopped down to one element, no need to check it matches + if (mode == KeyMustBePresentInArray) { + ASSERT(size == 1); + ASSERT(key == extractKey(&array[0])); + } + + return &array[0]; +} + +// Modified binarySearch() algorithm designed for array-like classes that support +// operator[] but not operator+=. One example of a class that qualifies is +// SegmentedVector. +template +inline ArrayElementType* genericBinarySearch(ArrayType& array, size_t size, KeyType key) +{ + // The array must contain at least one element (pre-condition, array does conatin key). + // If the array only contains one element, no need to do the comparison. + size_t offset = 0; + while (size > 1) { + // Pick an element to check, half way through the array, and read the value. + int pos = (size - 1) >> 1; + KeyType val = extractKey(&array[offset + pos]); + + // If the key matches, success! + if (val == key) + return &array[offset + pos]; + // The item we are looking for is smaller than the item being check; reduce the value of 'size', + // chopping off the right hand half of the array. + if (key < val) + size = pos; + // Discard all values in the left hand half of the array, up to and including the item at pos. + else { + size -= (pos + 1); + offset += (pos + 1); + } + + // 'size' should never reach zero. + ASSERT(size); + } + + // If we reach this point we've chopped down to one element, no need to check it matches + ASSERT(size == 1); + ASSERT(key == extractKey(&array[offset])); + return &array[offset]; +} + +} // namespace WTF + +// This version of placement new omits a 0 check. +enum NotNullTag { NotNull }; +inline void* operator new(size_t, NotNullTag, void* location) +{ + ASSERT(location); + return location; +} + +using WTF::KB; +using WTF::isPointerAligned; +using WTF::binarySearch; +using WTF::bitwise_cast; +using WTF::safeCast; + +#endif // WTF_StdLibExtras_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StorageBarrier.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StorageBarrier.h new file mode 100644 index 000000000..2a0c842ba --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StorageBarrier.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2011 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 INC. 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 INC. 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 StorageBarrier_h +#define StorageBarrier_h + +#include "JSGlobalData.h" +#include "WriteBarrier.h" + +namespace JSC { + +typedef WriteBarrierBase* PropertyStorage; +typedef const WriteBarrierBase* ConstPropertyStorage; + +class StorageBarrier { +public: + enum UncheckedTag { Unchecked }; + StorageBarrier(JSGlobalData& globalData, JSCell* owner, PropertyStorage storage) + { + set(globalData, owner, storage); + } + + StorageBarrier(PropertyStorage storage, UncheckedTag) + { + set(storage, Unchecked); + } + + void set(JSGlobalData&, JSCell*, PropertyStorage newStorage) + { + m_storage = newStorage; + } + + void set(PropertyStorage newStorage, UncheckedTag) + { + m_storage = newStorage; + } + + WriteBarrierBase* operator->() const { return m_storage; } + WriteBarrierBase* operator->() { return m_storage; } + WriteBarrierBase operator*() const { return *m_storage; } + WriteBarrierBase operator*() { return *m_storage; } + const WriteBarrierBase& operator[](size_t i) const { return m_storage[i]; } + WriteBarrierBase& operator[](size_t i) { return m_storage[i]; } + + ConstPropertyStorage get() const { return m_storage; } + PropertyStorage get() { return m_storage; } + +private: + PropertyStorage m_storage; +}; + +} + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StringBuffer.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StringBuffer.h new file mode 100644 index 000000000..739260d27 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StringBuffer.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2008, 2010 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 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 StringBuffer_h +#define StringBuffer_h + +#include +#include +#include + +namespace WTF { + +template +class StringBuffer { + WTF_MAKE_NONCOPYABLE(StringBuffer); +public: + explicit StringBuffer(unsigned length) + : m_length(length) + { + if (m_length > std::numeric_limits::max() / sizeof(CharType)) + CRASH(); + m_data = static_cast(fastMalloc(m_length * sizeof(CharType))); + } + + ~StringBuffer() + { + fastFree(m_data); + } + + void shrink(unsigned newLength) + { + ASSERT(newLength <= m_length); + m_length = newLength; + } + + void resize(unsigned newLength) + { + if (newLength > m_length) { + if (newLength > std::numeric_limits::max() / sizeof(UChar)) + CRASH(); + m_data = static_cast(fastRealloc(m_data, newLength * sizeof(UChar))); + } + m_length = newLength; + } + + unsigned length() const { return m_length; } + CharType* characters() { return m_data; } + + UChar& operator[](unsigned i) { ASSERT(i < m_length); return m_data[i]; } + + CharType* release() { CharType* data = m_data; m_data = 0; return data; } + +private: + unsigned m_length; + CharType* m_data; +}; + +} // namespace WTF + +using WTF::StringBuffer; + +#endif // StringBuffer_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StringBuilder.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StringBuilder.h new file mode 100644 index 000000000..6475d54f8 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StringBuilder.h @@ -0,0 +1,319 @@ +/* + * Copyright (C) 2009, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2012 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: + * 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 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 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 StringBuilder_h +#define StringBuilder_h + +#include +#include + +namespace WTF { + +class StringBuilder { + // Disallow copying since it's expensive and we don't want code to do it by accident. + WTF_MAKE_NONCOPYABLE(StringBuilder); + +public: + StringBuilder() + : m_length(0) + , m_is8Bit(true) + , m_valid16BitShadowLength(0) + , m_bufferCharacters8(0) + { + } + + WTF_EXPORT_PRIVATE void append(const UChar*, unsigned); + WTF_EXPORT_PRIVATE void append(const LChar*, unsigned); + + ALWAYS_INLINE void append(const char* characters, unsigned length) { append(reinterpret_cast(characters), length); } + + void append(const String& string) + { + if (!string.length()) + return; + + // If we're appending to an empty string, and there is not a buffer (reserveCapacity has not been called) + // then just retain the string. + if (!m_length && !m_buffer) { + m_string = string; + m_length = string.length(); + m_is8Bit = m_string.is8Bit(); + return; + } + + if (string.is8Bit()) + append(string.characters8(), string.length()); + else + append(string.characters16(), string.length()); + } + + void append(const StringBuilder& other) + { + if (!other.m_length) + return; + + // If we're appending to an empty string, and there is not a buffer (reserveCapacity has not been called) + // then just retain the string. + if (!m_length && !m_buffer && !other.m_string.isNull()) { + m_string = other.m_string; + m_length = other.m_length; + return; + } + + append(other.characters(), other.m_length); + } + + void append(const char* characters) + { + if (characters) + append(characters, strlen(characters)); + } + + void append(UChar c) + { + if (m_buffer && !m_is8Bit && m_length < m_buffer->length() && m_string.isNull()) + m_bufferCharacters16[m_length++] = c; + else + append(&c, 1); + } + + void append(LChar c) + { + if (m_buffer && m_length < m_buffer->length() && m_string.isNull()) { + if (m_is8Bit) + m_bufferCharacters8[m_length++] = c; + else + m_bufferCharacters16[m_length++] = c; + } else + append(&c, 1); + } + + void append(char c) + { + append(static_cast(c)); + } + + String toString() + { + shrinkToFit(); + if (m_string.isNull()) + reifyString(); + return m_string; + } + + const String& toStringPreserveCapacity() const + { + if (m_string.isNull()) + reifyString(); + return m_string; + } + + AtomicString toAtomicString() const + { + if (!m_length) + return AtomicString(); + + // If the buffer is sufficiently over-allocated, make a new AtomicString from a copy so its buffer is not so large. + if (canShrink()) + return AtomicString(characters(), length()); + + if (!m_string.isNull()) + return AtomicString(m_string); + + ASSERT(m_buffer); + return AtomicString(m_buffer.get(), 0, m_length); + } + + unsigned length() const + { + return m_length; + } + + bool isEmpty() const { return !m_length; } + + WTF_EXPORT_PRIVATE void reserveCapacity(unsigned newCapacity); + + unsigned capacity() const + { + return m_buffer ? m_buffer->length() : m_length; + } + + WTF_EXPORT_PRIVATE void resize(unsigned newSize); + + WTF_EXPORT_PRIVATE bool canShrink() const; + + WTF_EXPORT_PRIVATE void shrinkToFit(); + + UChar operator[](unsigned i) const + { + ASSERT(i < m_length); + if (m_is8Bit) + return characters8()[i]; + return characters16()[i]; + } + + const LChar* characters8() const + { + ASSERT(m_is8Bit); + if (!m_length) + return 0; + if (!m_string.isNull()) + return m_string.characters8(); + ASSERT(m_buffer); + return m_buffer->characters8(); + } + + const UChar* characters16() const + { + ASSERT(!m_is8Bit); + if (!m_length) + return 0; + if (!m_string.isNull()) + return m_string.characters16(); + ASSERT(m_buffer); + return m_buffer->characters16(); + } + + const UChar* characters() const + { + if (!m_length) + return 0; + if (!m_string.isNull()) + return m_string.characters(); + ASSERT(m_buffer); + if (m_buffer->has16BitShadow() && m_valid16BitShadowLength < m_length) + m_buffer->upconvertCharacters(m_valid16BitShadowLength, m_length); + + m_valid16BitShadowLength = m_length; + + return m_buffer->characters(); + } + + bool is8Bit() const { return m_is8Bit; } + + void clear() + { + m_length = 0; + m_string = String(); + m_buffer = 0; + m_bufferCharacters8 = 0; + m_is8Bit = true; + m_valid16BitShadowLength = 0; + } + + void swap(StringBuilder& stringBuilder) + { + std::swap(m_length, stringBuilder.m_length); + m_string.swap(stringBuilder.m_string); + m_buffer.swap(stringBuilder.m_buffer); + std::swap(m_is8Bit, stringBuilder.m_is8Bit); + std::swap(m_valid16BitShadowLength, stringBuilder.m_valid16BitShadowLength); + std::swap(m_bufferCharacters8, stringBuilder.m_bufferCharacters8); + } + +private: + void allocateBuffer(const LChar* currentCharacters, unsigned requiredLength); + void allocateBuffer(const UChar* currentCharacters, unsigned requiredLength); + void allocateBufferUpConvert(const LChar* currentCharacters, unsigned requiredLength); + template + void reallocateBuffer(unsigned requiredLength); + template + ALWAYS_INLINE CharType* appendUninitialized(unsigned length); + template + CharType* appendUninitializedSlow(unsigned length); + template + ALWAYS_INLINE CharType * getBufferCharacters(); + WTF_EXPORT_PRIVATE void reifyString() const; + + unsigned m_length; + mutable String m_string; + RefPtr m_buffer; + bool m_is8Bit; + mutable unsigned m_valid16BitShadowLength; + union { + LChar* m_bufferCharacters8; + UChar* m_bufferCharacters16; + }; +}; + +template <> +ALWAYS_INLINE LChar* StringBuilder::getBufferCharacters() +{ + ASSERT(m_is8Bit); + return m_bufferCharacters8; +} + +template <> +ALWAYS_INLINE UChar* StringBuilder::getBufferCharacters() +{ + ASSERT(!m_is8Bit); + return m_bufferCharacters16; +} + +template +bool equal(const StringBuilder& s, const CharType* buffer, unsigned length) +{ + if (s.length() != length) + return false; + + if (s.is8Bit()) + return equal(s.characters8(), buffer, length); + + return equal(s.characters16(), buffer, length); +} + +template +bool equal(const StringBuilder& a, const StringType& b) +{ + if (a.length() != b.length()) + return false; + + if (!a.length()) + return true; + + if (a.is8Bit()) { + if (b.is8Bit()) + return equal(a.characters8(), b.characters8(), a.length()); + return equal(a.characters8(), b.characters16(), a.length()); + } + + if (b.is8Bit()) + return equal(a.characters16(), b.characters8(), a.length()); + return equal(a.characters16(), b.characters16(), a.length()); +} + +inline bool operator==(const StringBuilder& a, const StringBuilder& b) { return equal(a, b); } +inline bool operator!=(const StringBuilder& a, const StringBuilder& b) { return !equal(a, b); } +inline bool operator==(const StringBuilder& a, const String& b) { return equal(a, b); } +inline bool operator!=(const StringBuilder& a, const String& b) { return !equal(a, b); } +inline bool operator==(const String& a, const StringBuilder& b) { return equal(b, a); } +inline bool operator!=(const String& a, const StringBuilder& b) { return !equal(b, a); } + +} // namespace WTF + +using WTF::StringBuilder; + +#endif // StringBuilder_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StringConcatenate.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StringConcatenate.h new file mode 100644 index 000000000..08d67dcf0 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StringConcatenate.h @@ -0,0 +1,964 @@ +/* + * Copyright (C) 2010 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 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 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 StringConcatenate_h +#define StringConcatenate_h + +#ifndef WTFString_h +#include "AtomicString.h" +#endif + +// This macro is helpful for testing how many intermediate Strings are created while evaluating an +// expression containing operator+. +#ifndef WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING +#define WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING() ((void)0) +#endif + +namespace WTF { + +template +class StringTypeAdapter { +}; + +template<> +class StringTypeAdapter { +public: + StringTypeAdapter(char buffer) + : m_buffer(buffer) + { + } + + unsigned length() { return 1; } + + bool is8Bit() { return true; } + + void writeTo(LChar* destination) + { + *destination = m_buffer; + } + + void writeTo(UChar* destination) { *destination = m_buffer; } + +private: + unsigned char m_buffer; +}; + +template<> +class StringTypeAdapter { +public: + StringTypeAdapter(LChar buffer) + : m_buffer(buffer) + { + } + + unsigned length() { return 1; } + + bool is8Bit() { return true; } + + void writeTo(LChar* destination) + { + *destination = m_buffer; + } + + void writeTo(UChar* destination) { *destination = m_buffer; } + +private: + LChar m_buffer; +}; + +template<> +class StringTypeAdapter { +public: + StringTypeAdapter(UChar buffer) + : m_buffer(buffer) + { + } + + unsigned length() { return 1; } + + bool is8Bit() { return m_buffer <= 0xff; } + + void writeTo(LChar* destination) + { + ASSERT(is8Bit()); + *destination = static_cast(m_buffer); + } + + void writeTo(UChar* destination) { *destination = m_buffer; } + +private: + UChar m_buffer; +}; + +template<> +class StringTypeAdapter { +public: + StringTypeAdapter(char* buffer) + : m_buffer(buffer) + , m_length(strlen(buffer)) + { + } + + unsigned length() { return m_length; } + + bool is8Bit() { return true; } + + void writeTo(LChar* destination) + { + for (unsigned i = 0; i < m_length; ++i) + destination[i] = static_cast(m_buffer[i]); + } + + void writeTo(UChar* destination) + { + for (unsigned i = 0; i < m_length; ++i) { + unsigned char c = m_buffer[i]; + destination[i] = c; + } + } + +private: + const char* m_buffer; + unsigned m_length; +}; + +template<> +class StringTypeAdapter { +public: + StringTypeAdapter(LChar* buffer) + : m_buffer(buffer) + , m_length(strlen(reinterpret_cast(buffer))) + { + } + + unsigned length() { return m_length; } + + bool is8Bit() { return true; } + + void writeTo(LChar* destination) + { + memcpy(destination, m_buffer, m_length * sizeof(LChar)); + } + + void writeTo(UChar* destination) + { + for (unsigned i = 0; i < m_length; ++i) + destination[i] = m_buffer[i]; + } + +private: + const LChar* m_buffer; + unsigned m_length; +}; + +template<> +class StringTypeAdapter { +public: + StringTypeAdapter(const UChar* buffer) + : m_buffer(buffer) + { + size_t len = 0; + while (m_buffer[len] != UChar(0)) + len++; + + if (len > std::numeric_limits::max()) + CRASH(); + + m_length = len; + } + + unsigned length() { return m_length; } + + bool is8Bit() { return false; } + + NO_RETURN_DUE_TO_CRASH void writeTo(LChar*) + { + CRASH(); + } + + void writeTo(UChar* destination) + { + memcpy(destination, m_buffer, m_length * sizeof(UChar)); + } + +private: + const UChar* m_buffer; + unsigned m_length; +}; + +template<> +class StringTypeAdapter { +public: + StringTypeAdapter(const char* buffer) + : m_buffer(buffer) + , m_length(strlen(buffer)) + { + } + + unsigned length() { return m_length; } + + bool is8Bit() { return true; } + + void writeTo(LChar* destination) + { + memcpy(destination, m_buffer, static_cast(m_length) * sizeof(LChar)); + } + + void writeTo(UChar* destination) + { + for (unsigned i = 0; i < m_length; ++i) { + unsigned char c = m_buffer[i]; + destination[i] = c; + } + } + +private: + const char* m_buffer; + unsigned m_length; +}; + +template<> +class StringTypeAdapter { +public: + StringTypeAdapter(const LChar* buffer) + : m_buffer(buffer) + , m_length(strlen(reinterpret_cast(buffer))) + { + } + + unsigned length() { return m_length; } + + bool is8Bit() { return true; } + + void writeTo(LChar* destination) + { + memcpy(destination, m_buffer, static_cast(m_length) * sizeof(LChar)); + } + + void writeTo(UChar* destination) + { + for (unsigned i = 0; i < m_length; ++i) + destination[i] = m_buffer[i]; + } + +private: + const LChar* m_buffer; + unsigned m_length; +}; + +template<> +class StringTypeAdapter > { +public: + StringTypeAdapter >(const Vector& buffer) + : m_buffer(buffer) + { + } + + size_t length() { return m_buffer.size(); } + + bool is8Bit() { return true; } + + void writeTo(LChar* destination) + { + for (size_t i = 0; i < m_buffer.size(); ++i) + destination[i] = static_cast(m_buffer[i]); + } + + void writeTo(UChar* destination) + { + for (size_t i = 0; i < m_buffer.size(); ++i) + destination[i] = static_cast(m_buffer[i]); + } + +private: + const Vector& m_buffer; +}; + +template<> +class StringTypeAdapter > { +public: + StringTypeAdapter >(const Vector& buffer) + : m_buffer(buffer) + { + } + + size_t length() { return m_buffer.size(); } + + bool is8Bit() { return true; } + + void writeTo(LChar* destination) + { + for (size_t i = 0; i < m_buffer.size(); ++i) + destination[i] = m_buffer[i]; + } + + void writeTo(UChar* destination) + { + for (size_t i = 0; i < m_buffer.size(); ++i) + destination[i] = m_buffer[i]; + } + +private: + const Vector& m_buffer; +}; + +template<> +class StringTypeAdapter { +public: + StringTypeAdapter(const String& string) + : m_buffer(string) + { + } + + unsigned length() { return m_buffer.length(); } + + bool is8Bit() { return m_buffer.isNull() || m_buffer.is8Bit(); } + + void writeTo(LChar* destination) + { + unsigned length = m_buffer.length(); + + ASSERT(is8Bit()); + const LChar* data = m_buffer.characters8(); + for (unsigned i = 0; i < length; ++i) + destination[i] = data[i]; + + WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING(); + } + + void writeTo(UChar* destination) + { + unsigned length = m_buffer.length(); + + if (is8Bit()) { + const LChar* data = m_buffer.characters8(); + for (unsigned i = 0; i < length; ++i) + destination[i] = data[i]; + } else { + const UChar* data = m_buffer.characters16(); + for (unsigned i = 0; i < length; ++i) + destination[i] = data[i]; + } + + WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING(); + } + +private: + const String& m_buffer; +}; + +template<> +class StringTypeAdapter { +public: + StringTypeAdapter(const AtomicString& string) + : m_adapter(string.string()) + { + } + + unsigned length() { return m_adapter.length(); } + + bool is8Bit() { return m_adapter.is8Bit(); } + + void writeTo(LChar* destination) { m_adapter.writeTo(destination); } + void writeTo(UChar* destination) { m_adapter.writeTo(destination); } + +private: + StringTypeAdapter m_adapter; +}; + +inline void sumWithOverflow(unsigned& total, unsigned addend, bool& overflow) +{ + unsigned oldTotal = total; + total = oldTotal + addend; + if (total < oldTotal) + overflow = true; +} + +template +PassRefPtr tryMakeString(StringType1 string1, StringType2 string2) +{ + StringTypeAdapter adapter1(string1); + StringTypeAdapter adapter2(string2); + + bool overflow = false; + unsigned length = adapter1.length(); + sumWithOverflow(length, adapter2.length(), overflow); + if (overflow) + return 0; + + if (adapter1.is8Bit() && adapter2.is8Bit()) { + LChar* buffer; + RefPtr resultImpl = StringImpl::tryCreateUninitialized(length, buffer); + if (!resultImpl) + return 0; + + LChar* result = buffer; + adapter1.writeTo(result); + result += adapter1.length(); + adapter2.writeTo(result); + + return resultImpl.release(); + } + + UChar* buffer; + RefPtr resultImpl = StringImpl::tryCreateUninitialized(length, buffer); + if (!resultImpl) + return 0; + + UChar* result = buffer; + adapter1.writeTo(result); + result += adapter1.length(); + adapter2.writeTo(result); + + return resultImpl.release(); +} + +template +PassRefPtr tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3) +{ + StringTypeAdapter adapter1(string1); + StringTypeAdapter adapter2(string2); + StringTypeAdapter adapter3(string3); + + bool overflow = false; + unsigned length = adapter1.length(); + sumWithOverflow(length, adapter2.length(), overflow); + sumWithOverflow(length, adapter3.length(), overflow); + if (overflow) + return 0; + + if (adapter1.is8Bit() && adapter2.is8Bit() && adapter3.is8Bit()) { + LChar* buffer; + RefPtr resultImpl = StringImpl::tryCreateUninitialized(length, buffer); + if (!resultImpl) + return 0; + + LChar* result = buffer; + adapter1.writeTo(result); + result += adapter1.length(); + adapter2.writeTo(result); + result += adapter2.length(); + adapter3.writeTo(result); + + return resultImpl.release(); + } + + UChar* buffer = 0; + RefPtr resultImpl = StringImpl::tryCreateUninitialized(length, buffer); + if (!resultImpl) + return 0; + + UChar* result = buffer; + adapter1.writeTo(result); + result += adapter1.length(); + adapter2.writeTo(result); + result += adapter2.length(); + adapter3.writeTo(result); + + return resultImpl.release(); +} + +template +PassRefPtr tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4) +{ + StringTypeAdapter adapter1(string1); + StringTypeAdapter adapter2(string2); + StringTypeAdapter adapter3(string3); + StringTypeAdapter adapter4(string4); + + bool overflow = false; + unsigned length = adapter1.length(); + sumWithOverflow(length, adapter2.length(), overflow); + sumWithOverflow(length, adapter3.length(), overflow); + sumWithOverflow(length, adapter4.length(), overflow); + if (overflow) + return 0; + + if (adapter1.is8Bit() && adapter2.is8Bit() && adapter3.is8Bit() && adapter4.is8Bit()) { + LChar* buffer; + RefPtr resultImpl = StringImpl::tryCreateUninitialized(length, buffer); + if (!resultImpl) + return 0; + + LChar* result = buffer; + adapter1.writeTo(result); + result += adapter1.length(); + adapter2.writeTo(result); + result += adapter2.length(); + adapter3.writeTo(result); + result += adapter3.length(); + adapter4.writeTo(result); + + return resultImpl.release(); + } + + UChar* buffer; + RefPtr resultImpl = StringImpl::tryCreateUninitialized(length, buffer); + if (!resultImpl) + return 0; + + UChar* result = buffer; + adapter1.writeTo(result); + result += adapter1.length(); + adapter2.writeTo(result); + result += adapter2.length(); + adapter3.writeTo(result); + result += adapter3.length(); + adapter4.writeTo(result); + + return resultImpl.release(); +} + +template +PassRefPtr tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5) +{ + StringTypeAdapter adapter1(string1); + StringTypeAdapter adapter2(string2); + StringTypeAdapter adapter3(string3); + StringTypeAdapter adapter4(string4); + StringTypeAdapter adapter5(string5); + + bool overflow = false; + unsigned length = adapter1.length(); + sumWithOverflow(length, adapter2.length(), overflow); + sumWithOverflow(length, adapter3.length(), overflow); + sumWithOverflow(length, adapter4.length(), overflow); + sumWithOverflow(length, adapter5.length(), overflow); + if (overflow) + return 0; + + if (adapter1.is8Bit() && adapter2.is8Bit() && adapter3.is8Bit() && adapter4.is8Bit() && adapter5.is8Bit()) { + LChar* buffer; + RefPtr resultImpl = StringImpl::tryCreateUninitialized(length, buffer); + if (!resultImpl) + return 0; + + LChar* result = buffer; + adapter1.writeTo(result); + result += adapter1.length(); + adapter2.writeTo(result); + result += adapter2.length(); + adapter3.writeTo(result); + result += adapter3.length(); + adapter4.writeTo(result); + result += adapter4.length(); + adapter5.writeTo(result); + + return resultImpl.release(); + } + + UChar* buffer; + RefPtr resultImpl = StringImpl::tryCreateUninitialized(length, buffer); + if (!resultImpl) + return 0; + + UChar* result = buffer; + adapter1.writeTo(result); + result += adapter1.length(); + adapter2.writeTo(result); + result += adapter2.length(); + adapter3.writeTo(result); + result += adapter3.length(); + adapter4.writeTo(result); + result += adapter4.length(); + adapter5.writeTo(result); + + return resultImpl.release(); +} + +template +PassRefPtr tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6) +{ + StringTypeAdapter adapter1(string1); + StringTypeAdapter adapter2(string2); + StringTypeAdapter adapter3(string3); + StringTypeAdapter adapter4(string4); + StringTypeAdapter adapter5(string5); + StringTypeAdapter adapter6(string6); + + bool overflow = false; + unsigned length = adapter1.length(); + sumWithOverflow(length, adapter2.length(), overflow); + sumWithOverflow(length, adapter3.length(), overflow); + sumWithOverflow(length, adapter4.length(), overflow); + sumWithOverflow(length, adapter5.length(), overflow); + sumWithOverflow(length, adapter6.length(), overflow); + if (overflow) + return 0; + + if (adapter1.is8Bit() && adapter2.is8Bit() && adapter3.is8Bit() && adapter4.is8Bit() && adapter5.is8Bit() && adapter6.is8Bit()) { + LChar* buffer; + RefPtr resultImpl = StringImpl::tryCreateUninitialized(length, buffer); + if (!resultImpl) + return 0; + + LChar* result = buffer; + adapter1.writeTo(result); + result += adapter1.length(); + adapter2.writeTo(result); + result += adapter2.length(); + adapter3.writeTo(result); + result += adapter3.length(); + adapter4.writeTo(result); + result += adapter4.length(); + adapter5.writeTo(result); + result += adapter5.length(); + adapter6.writeTo(result); + + return resultImpl.release(); + } + + UChar* buffer; + RefPtr resultImpl = StringImpl::tryCreateUninitialized(length, buffer); + if (!resultImpl) + return 0; + + UChar* result = buffer; + adapter1.writeTo(result); + result += adapter1.length(); + adapter2.writeTo(result); + result += adapter2.length(); + adapter3.writeTo(result); + result += adapter3.length(); + adapter4.writeTo(result); + result += adapter4.length(); + adapter5.writeTo(result); + result += adapter5.length(); + adapter6.writeTo(result); + + return resultImpl.release(); +} + +template +PassRefPtr tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7) +{ + StringTypeAdapter adapter1(string1); + StringTypeAdapter adapter2(string2); + StringTypeAdapter adapter3(string3); + StringTypeAdapter adapter4(string4); + StringTypeAdapter adapter5(string5); + StringTypeAdapter adapter6(string6); + StringTypeAdapter adapter7(string7); + + bool overflow = false; + unsigned length = adapter1.length(); + sumWithOverflow(length, adapter2.length(), overflow); + sumWithOverflow(length, adapter3.length(), overflow); + sumWithOverflow(length, adapter4.length(), overflow); + sumWithOverflow(length, adapter5.length(), overflow); + sumWithOverflow(length, adapter6.length(), overflow); + sumWithOverflow(length, adapter7.length(), overflow); + if (overflow) + return 0; + + if (adapter1.is8Bit() && adapter2.is8Bit() && adapter3.is8Bit() && adapter4.is8Bit() && adapter5.is8Bit() && adapter6.is8Bit()) { + LChar* buffer; + RefPtr resultImpl = StringImpl::tryCreateUninitialized(length, buffer); + if (!resultImpl) + return 0; + + LChar* result = buffer; + adapter1.writeTo(result); + result += adapter1.length(); + adapter2.writeTo(result); + result += adapter2.length(); + adapter3.writeTo(result); + result += adapter3.length(); + adapter4.writeTo(result); + result += adapter4.length(); + adapter5.writeTo(result); + result += adapter5.length(); + adapter6.writeTo(result); + result += adapter6.length(); + adapter7.writeTo(result); + + return resultImpl.release(); + } + + UChar* buffer; + RefPtr resultImpl = StringImpl::tryCreateUninitialized(length, buffer); + if (!resultImpl) + return 0; + + UChar* result = buffer; + adapter1.writeTo(result); + result += adapter1.length(); + adapter2.writeTo(result); + result += adapter2.length(); + adapter3.writeTo(result); + result += adapter3.length(); + adapter4.writeTo(result); + result += adapter4.length(); + adapter5.writeTo(result); + result += adapter5.length(); + adapter6.writeTo(result); + result += adapter6.length(); + adapter7.writeTo(result); + + return resultImpl.release(); +} + +template +PassRefPtr tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8) +{ + StringTypeAdapter adapter1(string1); + StringTypeAdapter adapter2(string2); + StringTypeAdapter adapter3(string3); + StringTypeAdapter adapter4(string4); + StringTypeAdapter adapter5(string5); + StringTypeAdapter adapter6(string6); + StringTypeAdapter adapter7(string7); + StringTypeAdapter adapter8(string8); + + bool overflow = false; + unsigned length = adapter1.length(); + sumWithOverflow(length, adapter2.length(), overflow); + sumWithOverflow(length, adapter3.length(), overflow); + sumWithOverflow(length, adapter4.length(), overflow); + sumWithOverflow(length, adapter5.length(), overflow); + sumWithOverflow(length, adapter6.length(), overflow); + sumWithOverflow(length, adapter7.length(), overflow); + sumWithOverflow(length, adapter8.length(), overflow); + if (overflow) + return 0; + + if (adapter1.is8Bit() && adapter2.is8Bit() && adapter3.is8Bit() && adapter4.is8Bit() && adapter5.is8Bit() && adapter6.is8Bit() && adapter7.is8Bit() && adapter8.is8Bit()) { + LChar* buffer; + RefPtr resultImpl = StringImpl::tryCreateUninitialized(length, buffer); + if (!resultImpl) + return 0; + + LChar* result = buffer; + adapter1.writeTo(result); + result += adapter1.length(); + adapter2.writeTo(result); + result += adapter2.length(); + adapter3.writeTo(result); + result += adapter3.length(); + adapter4.writeTo(result); + result += adapter4.length(); + adapter5.writeTo(result); + result += adapter5.length(); + adapter6.writeTo(result); + result += adapter6.length(); + adapter7.writeTo(result); + result += adapter7.length(); + adapter8.writeTo(result); + + return resultImpl.release(); + } + + UChar* buffer; + RefPtr resultImpl = StringImpl::tryCreateUninitialized(length, buffer); + if (!resultImpl) + return 0; + + UChar* result = buffer; + adapter1.writeTo(result); + result += adapter1.length(); + adapter2.writeTo(result); + result += adapter2.length(); + adapter3.writeTo(result); + result += adapter3.length(); + adapter4.writeTo(result); + result += adapter4.length(); + adapter5.writeTo(result); + result += adapter5.length(); + adapter6.writeTo(result); + result += adapter6.length(); + adapter7.writeTo(result); + result += adapter7.length(); + adapter8.writeTo(result); + + return resultImpl.release(); +} + +template +PassRefPtr tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8, StringType9 string9) +{ + StringTypeAdapter adapter1(string1); + StringTypeAdapter adapter2(string2); + StringTypeAdapter adapter3(string3); + StringTypeAdapter adapter4(string4); + StringTypeAdapter adapter5(string5); + StringTypeAdapter adapter6(string6); + StringTypeAdapter adapter7(string7); + StringTypeAdapter adapter8(string8); + StringTypeAdapter adapter9(string9); + + bool overflow = false; + unsigned length = adapter1.length(); + sumWithOverflow(length, adapter2.length(), overflow); + sumWithOverflow(length, adapter3.length(), overflow); + sumWithOverflow(length, adapter4.length(), overflow); + sumWithOverflow(length, adapter5.length(), overflow); + sumWithOverflow(length, adapter6.length(), overflow); + sumWithOverflow(length, adapter7.length(), overflow); + sumWithOverflow(length, adapter8.length(), overflow); + sumWithOverflow(length, adapter9.length(), overflow); + if (overflow) + return 0; + + if (adapter1.is8Bit() && adapter2.is8Bit() && adapter3.is8Bit() && adapter4.is8Bit() && adapter5.is8Bit() && adapter6.is8Bit() && adapter7.is8Bit() && adapter8.is8Bit() && adapter9.is8Bit()) { + LChar* buffer; + RefPtr resultImpl = StringImpl::tryCreateUninitialized(length, buffer); + if (!resultImpl) + return 0; + + LChar* result = buffer; + adapter1.writeTo(result); + result += adapter1.length(); + adapter2.writeTo(result); + result += adapter2.length(); + adapter3.writeTo(result); + result += adapter3.length(); + adapter4.writeTo(result); + result += adapter4.length(); + adapter5.writeTo(result); + result += adapter5.length(); + adapter6.writeTo(result); + result += adapter6.length(); + adapter7.writeTo(result); + result += adapter7.length(); + adapter8.writeTo(result); + result += adapter8.length(); + adapter9.writeTo(result); + + return resultImpl.release(); + } + + UChar* buffer; + RefPtr resultImpl = StringImpl::tryCreateUninitialized(length, buffer); + if (!resultImpl) + return 0; + + UChar* result = buffer; + adapter1.writeTo(result); + result += adapter1.length(); + adapter2.writeTo(result); + result += adapter2.length(); + adapter3.writeTo(result); + result += adapter3.length(); + adapter4.writeTo(result); + result += adapter4.length(); + adapter5.writeTo(result); + result += adapter5.length(); + adapter6.writeTo(result); + result += adapter6.length(); + adapter7.writeTo(result); + result += adapter7.length(); + adapter8.writeTo(result); + result += adapter8.length(); + adapter9.writeTo(result); + + return resultImpl.release(); +} + + +// Convenience only. +template +String makeString(StringType1 string1) +{ + return String(string1); +} + +template +String makeString(StringType1 string1, StringType2 string2) +{ + RefPtr resultImpl = tryMakeString(string1, string2); + if (!resultImpl) + CRASH(); + return resultImpl.release(); +} + +template +String makeString(StringType1 string1, StringType2 string2, StringType3 string3) +{ + RefPtr resultImpl = tryMakeString(string1, string2, string3); + if (!resultImpl) + CRASH(); + return resultImpl.release(); +} + +template +String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4) +{ + RefPtr resultImpl = tryMakeString(string1, string2, string3, string4); + if (!resultImpl) + CRASH(); + return resultImpl.release(); +} + +template +String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5) +{ + RefPtr resultImpl = tryMakeString(string1, string2, string3, string4, string5); + if (!resultImpl) + CRASH(); + return resultImpl.release(); +} + +template +String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6) +{ + RefPtr resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6); + if (!resultImpl) + CRASH(); + return resultImpl.release(); +} + +template +String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7) +{ + RefPtr resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7); + if (!resultImpl) + CRASH(); + return resultImpl.release(); +} + +template +String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8) +{ + RefPtr resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7, string8); + if (!resultImpl) + CRASH(); + return resultImpl.release(); +} + +template +String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8, StringType9 string9) +{ + RefPtr resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7, string8, string9); + if (!resultImpl) + CRASH(); + return resultImpl.release(); +} + +} // namespace WTF + +using WTF::makeString; + +#include "StringOperators.h" +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StringExtras.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StringExtras.h new file mode 100644 index 000000000..371e33bf9 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StringExtras.h @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2006, 2010 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 WTF_StringExtras_h +#define WTF_StringExtras_h + +#include +#include +#include + +#if HAVE(STRINGS_H) +#include +#endif + +#if COMPILER(MSVC) +// FIXME: why a COMPILER check instead of OS? also, these should be HAVE checks + +inline int snprintf(char* buffer, size_t count, const char* format, ...) +{ + int result; + va_list args; + va_start(args, format); + result = _vsnprintf(buffer, count, format, args); + va_end(args); + + // In the case where the string entirely filled the buffer, _vsnprintf will not + // null-terminate it, but snprintf must. + if (count > 0) + buffer[count - 1] = '\0'; + + return result; +} + +inline double wtf_vsnprintf(char* buffer, size_t count, const char* format, va_list args) +{ + int result = _vsnprintf(buffer, count, format, args); + + // In the case where the string entirely filled the buffer, _vsnprintf will not + // null-terminate it, but vsnprintf must. + if (count > 0) + buffer[count - 1] = '\0'; + + return result; +} + +// Work around a difference in Microsoft's implementation of vsnprintf, where +// vsnprintf does not null terminate the buffer. WebKit can rely on the null termination. +#define vsnprintf(buffer, count, format, args) wtf_vsnprintf(buffer, count, format, args) + +#if OS(WINCE) + +inline int strnicmp(const char* string1, const char* string2, size_t count) +{ + return _strnicmp(string1, string2, count); +} + +inline int stricmp(const char* string1, const char* string2) +{ + return _stricmp(string1, string2); +} + +inline char* strdup(const char* strSource) +{ + return _strdup(strSource); +} + +#endif + +inline int strncasecmp(const char* s1, const char* s2, size_t len) +{ + return _strnicmp(s1, s2, len); +} + +inline int strcasecmp(const char* s1, const char* s2) +{ + return _stricmp(s1, s2); +} + +#endif + +#if !HAVE(STRNSTR) + +inline char* strnstr(const char* buffer, const char* target, size_t bufferLength) +{ + size_t targetLength = strlen(target); + if (targetLength == 0) + return const_cast(buffer); + for (const char* start = buffer; *start && start + targetLength <= buffer + bufferLength; start++) { + if (*start == *target && strncmp(start + 1, target + 1, targetLength - 1) == 0) + return const_cast(start); + } + return 0; +} + +#endif + +#if COMPILER(RVCT) && __ARMCC_VERSION < 400000 + +int strcasecmp(const char* s1, const char* s2); +int strncasecmp(const char* s1, const char* s2, size_t len); + +#endif + +#endif // WTF_StringExtras_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StringHash.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StringHash.h new file mode 100644 index 000000000..cde591c18 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StringHash.h @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved + * Copyright (C) Research In Motion Limited 2009. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef StringHash_h +#define StringHash_h + +#include "AtomicString.h" +#include "WTFString.h" +#include +#include +#include +#include + +namespace WTF { + + // The hash() functions on StringHash and CaseFoldingHash do not support + // null strings. get(), contains(), and add() on HashMap + // cause a null-pointer dereference when passed null strings. + + // FIXME: We should really figure out a way to put the computeHash function that's + // currently a member function of StringImpl into this file so we can be a little + // closer to having all the nearly-identical hash functions in one place. + + struct StringHash { + static unsigned hash(StringImpl* key) { return key->hash(); } + static bool equal(const StringImpl* a, const StringImpl* b) + { + if (a == b) + return true; + if (!a || !b) + return false; + + unsigned aLength = a->length(); + unsigned bLength = b->length(); + if (aLength != bLength) + return false; + + if (a->is8Bit()) { + if (b->is8Bit()) { + // Both a & b are 8 bit. + return WTF::equal(a->characters8(), b->characters8(), aLength); + } + + // We know that a is 8 bit & b is 16 bit. + return WTF::equal(a->characters8(), b->characters16(), aLength); + } + + if (b->is8Bit()) { + // We know that a is 8 bit and b is 16 bit. + return WTF::equal(a->characters16(), b->characters8(), aLength); + } + + return WTF::equal(a->characters16(), b->characters16(), aLength); + } + + static unsigned hash(const RefPtr& key) { return key->hash(); } + static bool equal(const RefPtr& a, const RefPtr& b) + { + return equal(a.get(), b.get()); + } + + static unsigned hash(const String& key) { return key.impl()->hash(); } + static bool equal(const String& a, const String& b) + { + return equal(a.impl(), b.impl()); + } + + static const bool safeToCompareToEmptyOrDeleted = false; + }; + + class CaseFoldingHash { + public: + template static inline UChar foldCase(T ch) + { + return WTF::Unicode::foldCase(ch); + } + + static unsigned hash(const UChar* data, unsigned length) + { + return StringHasher::computeHash >(data, length); + } + + static unsigned hash(StringImpl* str) + { + return hash(str->characters(), str->length()); + } + + static unsigned hash(const LChar* data, unsigned length) + { + return StringHasher::computeHash >(data, length); + } + + static inline unsigned hash(const char* data, unsigned length) + { + return CaseFoldingHash::hash(reinterpret_cast(data), length); + } + + static bool equal(const StringImpl* a, const StringImpl* b) + { + if (a == b) + return true; + if (!a || !b) + return false; + unsigned length = a->length(); + if (length != b->length()) + return false; + return WTF::Unicode::umemcasecmp(a->characters(), b->characters(), length) == 0; + } + + static unsigned hash(const RefPtr& key) + { + return hash(key.get()); + } + + static bool equal(const RefPtr& a, const RefPtr& b) + { + return equal(a.get(), b.get()); + } + + static unsigned hash(const String& key) + { + return hash(key.impl()); + } + static unsigned hash(const AtomicString& key) + { + return hash(key.impl()); + } + static bool equal(const String& a, const String& b) + { + return equal(a.impl(), b.impl()); + } + static bool equal(const AtomicString& a, const AtomicString& b) + { + return (a == b) || equal(a.impl(), b.impl()); + } + + static const bool safeToCompareToEmptyOrDeleted = false; + }; + + // This hash can be used in cases where the key is a hash of a string, but we don't + // want to store the string. It's not really specific to string hashing, but all our + // current uses of it are for strings. + struct AlreadyHashed : IntHash { + static unsigned hash(unsigned key) { return key; } + + // To use a hash value as a key for a hash table, we need to eliminate the + // "deleted" value, which is negative one. That could be done by changing + // the string hash function to never generate negative one, but this works + // and is still relatively efficient. + static unsigned avoidDeletedValue(unsigned hash) + { + ASSERT(hash); + unsigned newHash = hash | (!(hash + 1) << 31); + ASSERT(newHash); + ASSERT(newHash != 0xFFFFFFFF); + return newHash; + } + }; + +} + +using WTF::StringHash; +using WTF::CaseFoldingHash; +using WTF::AlreadyHashed; + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StringHasher.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StringHasher.h new file mode 100644 index 000000000..714525188 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StringHasher.h @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2005, 2006, 2008, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010 Patrick Gansterer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ +#ifndef WTF_StringHasher_h +#define WTF_StringHasher_h + +#include + +namespace WTF { + +// Golden ratio - arbitrary start value to avoid mapping all 0's to all 0's +static const unsigned stringHashingStartValue = 0x9e3779b9U; + +// Paul Hsieh's SuperFastHash +// http://www.azillionmonkeys.com/qed/hash.html +// char* data is interpreted as latin-encoded (zero extended to 16 bits). + +// NOTE: This class must stay in sync with the create_hash_table script in +// JavaScriptCore and the CodeGeneratorJS.pm script in WebCore. +class StringHasher { +public: + static const unsigned flagCount = 8; // Save 8 bits for StringImpl to use as flags. + + inline StringHasher() + : m_hash(stringHashingStartValue) + , m_hasPendingCharacter(false) + , m_pendingCharacter(0) + { + } + + inline void addCharacters(UChar a, UChar b) + { + ASSERT(!m_hasPendingCharacter); + addCharactersToHash(a, b); + } + + inline void addCharacter(UChar ch) + { + if (m_hasPendingCharacter) { + addCharactersToHash(m_pendingCharacter, ch); + m_hasPendingCharacter = false; + return; + } + + m_pendingCharacter = ch; + m_hasPendingCharacter = true; + } + + inline unsigned hash() const + { + unsigned result = m_hash; + + // Handle end case. + if (m_hasPendingCharacter) { + result += m_pendingCharacter; + result ^= result << 11; + result += result >> 17; + } + + // Force "avalanching" of final 31 bits. + result ^= result << 3; + result += result >> 5; + result ^= result << 2; + result += result >> 15; + result ^= result << 10; + + // Reserving space from the high bits for flags preserves most of the hash's + // value, since hash lookup typically masks out the high bits anyway. + result &= (1u << (sizeof(result) * 8 - flagCount)) - 1; + + // This avoids ever returning a hash code of 0, since that is used to + // signal "hash not computed yet". Setting the high bit maintains + // reasonable fidelity to a hash code of 0 because it is likely to yield + // exactly 0 when hash lookup masks out the high bits. + if (!result) + result = 0x80000000 >> flagCount; + + return result; + } + + template static inline unsigned computeHash(const T* data, unsigned length) + { + StringHasher hasher; + bool rem = length & 1; + length >>= 1; + + while (length--) { + hasher.addCharacters(Converter(data[0]), Converter(data[1])); + data += 2; + } + + if (rem) + hasher.addCharacter(Converter(*data)); + + return hasher.hash(); + } + + template static inline unsigned computeHash(const T* data) + { + StringHasher hasher; + + while (true) { + UChar b0 = Converter(*data++); + if (!b0) + break; + UChar b1 = Converter(*data++); + if (!b1) { + hasher.addCharacter(b0); + break; + } + + hasher.addCharacters(b0, b1); + } + + return hasher.hash(); + } + + template static inline unsigned computeHash(const T* data, unsigned length) + { + return computeHash(data, length); + } + + template static inline unsigned computeHash(const T* data) + { + return computeHash(data); + } + + template static inline unsigned hashMemory(const void* data) + { + COMPILE_ASSERT(!(length % 4), length_must_be_a_multible_of_four); + return computeHash(static_cast(data), length / sizeof(UChar)); + } + + static inline unsigned hashMemory(const void* data, unsigned size) + { + ASSERT(!(size % 2)); + return computeHash(static_cast(data), size / sizeof(UChar)); + } + +private: + static inline UChar defaultConverter(UChar ch) + { + return ch; + } + + static inline UChar defaultConverter(LChar ch) + { + return ch; + } + + inline void addCharactersToHash(UChar a, UChar b) + { + m_hash += a; + unsigned tmp = (b << 11) ^ m_hash; + m_hash = (m_hash << 16) ^ tmp; + m_hash += m_hash >> 11; + } + + unsigned m_hash; + bool m_hasPendingCharacter; + UChar m_pendingCharacter; +}; + +} // namespace WTF + +using WTF::StringHasher; + +#endif // WTF_StringHasher_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StringImpl.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StringImpl.h new file mode 100644 index 000000000..1c743cbaa --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StringImpl.h @@ -0,0 +1,775 @@ +/* + * Copyright (C) 1999 Lars Knoll (knoll@kde.org) + * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef StringImpl_h +#define StringImpl_h + +#include +#include +#include +#include +#include +#include +#include + +#if USE(CF) +typedef const struct __CFString * CFStringRef; +#endif + +#ifdef __OBJC__ +@class NSString; +#endif + +// FIXME: This is a temporary layering violation while we move string code to WTF. +// Landing the file moves in one patch, will follow on with patches to change the namespaces. +namespace JSC { +struct IdentifierCStringTranslator; +template struct IdentifierCharBufferTranslator; +struct IdentifierLCharFromUCharTranslator; +} + +namespace WTF { + +struct CStringTranslator; +struct HashAndCharactersTranslator; +struct HashAndUTF8CharactersTranslator; +struct SubstringTranslator; +struct UCharBufferTranslator; + +enum TextCaseSensitivity { TextCaseSensitive, TextCaseInsensitive }; + +typedef bool (*CharacterMatchFunctionPtr)(UChar); +typedef bool (*IsWhiteSpaceFunctionPtr)(UChar); + +class StringImpl { + WTF_MAKE_NONCOPYABLE(StringImpl); WTF_MAKE_FAST_ALLOCATED; + friend struct JSC::IdentifierCStringTranslator; + friend struct JSC::IdentifierCharBufferTranslator; + friend struct JSC::IdentifierCharBufferTranslator; + friend struct JSC::IdentifierLCharFromUCharTranslator; + friend struct WTF::CStringTranslator; + friend struct WTF::HashAndCharactersTranslator; + friend struct WTF::HashAndUTF8CharactersTranslator; + friend struct WTF::SubstringTranslator; + friend struct WTF::UCharBufferTranslator; + friend class AtomicStringImpl; + +private: + enum BufferOwnership { + BufferInternal, + BufferOwned, + BufferSubstring, + }; + + // Used to construct static strings, which have an special refCount that can never hit zero. + // This means that the static string will never be destroyed, which is important because + // static strings will be shared across threads & ref-counted in a non-threadsafe manner. + enum ConstructStaticStringTag { ConstructStaticString }; + StringImpl(const UChar* characters, unsigned length, ConstructStaticStringTag) + : m_refCount(s_refCountFlagIsStaticString) + , m_length(length) + , m_data16(characters) + , m_buffer(0) + , m_hashAndFlags(s_hashFlagIsIdentifier | BufferOwned) + { + // Ensure that the hash is computed so that AtomicStringHash can call existingHash() + // with impunity. The empty string is special because it is never entered into + // AtomicString's HashKey, but still needs to compare correctly. + hash(); + } + + // Used to construct static strings, which have an special refCount that can never hit zero. + // This means that the static string will never be destroyed, which is important because + // static strings will be shared across threads & ref-counted in a non-threadsafe manner. + StringImpl(const LChar* characters, unsigned length, ConstructStaticStringTag) + : m_refCount(s_refCountFlagIsStaticString) + , m_length(length) + , m_data8(characters) + , m_buffer(0) + , m_hashAndFlags(s_hashFlag8BitBuffer | s_hashFlagIsIdentifier | BufferOwned) + { + // Ensure that the hash is computed so that AtomicStringHash can call existingHash() + // with impunity. The empty string is special because it is never entered into + // AtomicString's HashKey, but still needs to compare correctly. + hash(); + } + + // FIXME: there has to be a less hacky way to do this. + enum Force8Bit { Force8BitConstructor }; + // Create a normal 8-bit string with internal storage (BufferInternal) + StringImpl(unsigned length, Force8Bit) + : m_refCount(s_refCountIncrement) + , m_length(length) + , m_data8(reinterpret_cast(this + 1)) + , m_buffer(0) + , m_hashAndFlags(s_hashFlag8BitBuffer | BufferInternal) + { + ASSERT(m_data8); + ASSERT(m_length); + } + + // Create a normal 16-bit string with internal storage (BufferInternal) + StringImpl(unsigned length) + : m_refCount(s_refCountIncrement) + , m_length(length) + , m_data16(reinterpret_cast(this + 1)) + , m_buffer(0) + , m_hashAndFlags(BufferInternal) + { + ASSERT(m_data16); + ASSERT(m_length); + } + + // Create a StringImpl adopting ownership of the provided buffer (BufferOwned) + StringImpl(const LChar* characters, unsigned length) + : m_refCount(s_refCountIncrement) + , m_length(length) + , m_data8(characters) + , m_buffer(0) + , m_hashAndFlags(s_hashFlag8BitBuffer | BufferOwned) + { + ASSERT(m_data8); + ASSERT(m_length); + } + + // Create a StringImpl adopting ownership of the provided buffer (BufferOwned) + StringImpl(const UChar* characters, unsigned length) + : m_refCount(s_refCountIncrement) + , m_length(length) + , m_data16(characters) + , m_buffer(0) + , m_hashAndFlags(BufferOwned) + { + ASSERT(m_data16); + ASSERT(m_length); + } + + // Used to create new strings that are a substring of an existing 8-bit StringImpl (BufferSubstring) + StringImpl(const LChar* characters, unsigned length, PassRefPtr base) + : m_refCount(s_refCountIncrement) + , m_length(length) + , m_data8(characters) + , m_substringBuffer(base.leakRef()) + , m_hashAndFlags(s_hashFlag8BitBuffer | BufferSubstring) + { + ASSERT(is8Bit()); + ASSERT(m_data8); + ASSERT(m_length); + ASSERT(m_substringBuffer->bufferOwnership() != BufferSubstring); + } + + // Used to create new strings that are a substring of an existing 16-bit StringImpl (BufferSubstring) + StringImpl(const UChar* characters, unsigned length, PassRefPtr base) + : m_refCount(s_refCountIncrement) + , m_length(length) + , m_data16(characters) + , m_substringBuffer(base.leakRef()) + , m_hashAndFlags(BufferSubstring) + { + ASSERT(!is8Bit()); + ASSERT(m_data16); + ASSERT(m_length); + ASSERT(m_substringBuffer->bufferOwnership() != BufferSubstring); + } + +public: + WTF_EXPORT_PRIVATE ~StringImpl(); + + WTF_EXPORT_PRIVATE static PassRefPtr create(const UChar*, unsigned length); + static PassRefPtr create(const LChar*, unsigned length); + ALWAYS_INLINE static PassRefPtr create(const char* s, unsigned length) { return create(reinterpret_cast(s), length); } + WTF_EXPORT_PRIVATE static PassRefPtr create(const LChar*); + ALWAYS_INLINE static PassRefPtr create(const char* s) { return create(reinterpret_cast(s)); } + + static ALWAYS_INLINE PassRefPtr create8(PassRefPtr rep, unsigned offset, unsigned length) + { + ASSERT(rep); + ASSERT(length <= rep->length()); + + if (!length) + return empty(); + + ASSERT(rep->is8Bit()); + StringImpl* ownerRep = (rep->bufferOwnership() == BufferSubstring) ? rep->m_substringBuffer : rep.get(); + return adoptRef(new StringImpl(rep->m_data8 + offset, length, ownerRep)); + } + + static ALWAYS_INLINE PassRefPtr create(PassRefPtr rep, unsigned offset, unsigned length) + { + ASSERT(rep); + ASSERT(length <= rep->length()); + + if (!length) + return empty(); + + StringImpl* ownerRep = (rep->bufferOwnership() == BufferSubstring) ? rep->m_substringBuffer : rep.get(); + if (rep->is8Bit()) + return adoptRef(new StringImpl(rep->m_data8 + offset, length, ownerRep)); + return adoptRef(new StringImpl(rep->m_data16 + offset, length, ownerRep)); + } + + static PassRefPtr createUninitialized(unsigned length, LChar*& data); + WTF_EXPORT_PRIVATE static PassRefPtr createUninitialized(unsigned length, UChar*& data); + template static ALWAYS_INLINE PassRefPtr tryCreateUninitialized(unsigned length, T*& output) + { + if (!length) { + output = 0; + return empty(); + } + + if (length > ((std::numeric_limits::max() - sizeof(StringImpl)) / sizeof(T))) { + output = 0; + return 0; + } + StringImpl* resultImpl; + if (!tryFastMalloc(sizeof(T) * length + sizeof(StringImpl)).getValue(resultImpl)) { + output = 0; + return 0; + } + output = reinterpret_cast(resultImpl + 1); + + if (sizeof(T) == sizeof(char)) + return adoptRef(new (NotNull, resultImpl) StringImpl(length, Force8BitConstructor)); + + return adoptRef(new (NotNull, resultImpl) StringImpl(length)); + } + + // Reallocate the StringImpl. The originalString must be only owned by the PassRefPtr, + // and the buffer ownership must be BufferInternal. Just like the input pointer of realloc(), + // the originalString can't be used after this function. + static PassRefPtr reallocate(PassRefPtr originalString, unsigned length, LChar*& data); + static PassRefPtr reallocate(PassRefPtr originalString, unsigned length, UChar*& data); + + static unsigned flagsOffset() { return OBJECT_OFFSETOF(StringImpl, m_hashAndFlags); } + static unsigned flagIs8Bit() { return s_hashFlag8BitBuffer; } + static unsigned dataOffset() { return OBJECT_OFFSETOF(StringImpl, m_data8); } + static PassRefPtr createWithTerminatingNullCharacter(const StringImpl&); + + template + static PassRefPtr adopt(Vector& vector) + { + if (size_t size = vector.size()) { + ASSERT(vector.data()); + if (size > std::numeric_limits::max()) + CRASH(); + return adoptRef(new StringImpl(vector.releaseBuffer(), size)); + } + return empty(); + } + + static PassRefPtr adopt(StringBuffer& buffer); + WTF_EXPORT_PRIVATE static PassRefPtr adopt(StringBuffer& buffer); + + unsigned length() const { return m_length; } + bool is8Bit() const { return m_hashAndFlags & s_hashFlag8BitBuffer; } + + // FIXME: Remove all unnecessary usages of characters() + ALWAYS_INLINE const LChar* characters8() const { ASSERT(is8Bit()); return m_data8; } + ALWAYS_INLINE const UChar* characters16() const { ASSERT(!is8Bit()); return m_data16; } + ALWAYS_INLINE const UChar* characters() const + { + if (!is8Bit()) + return m_data16; + + return getData16SlowCase(); + } + + template + ALWAYS_INLINE const CharType * getCharacters() const; + + size_t cost() + { + // For substrings, return the cost of the base string. + if (bufferOwnership() == BufferSubstring) + return m_substringBuffer->cost(); + + if (m_hashAndFlags & s_hashFlagDidReportCost) + return 0; + + m_hashAndFlags |= s_hashFlagDidReportCost; + return m_length; + } + + bool has16BitShadow() const { return m_hashAndFlags & s_hashFlagHas16BitShadow; } + WTF_EXPORT_PRIVATE void upconvertCharacters(unsigned, unsigned) const; + bool isIdentifier() const { return m_hashAndFlags & s_hashFlagIsIdentifier; } + void setIsIdentifier(bool isIdentifier) + { + ASSERT(!isStatic()); + if (isIdentifier) + m_hashAndFlags |= s_hashFlagIsIdentifier; + else + m_hashAndFlags &= ~s_hashFlagIsIdentifier; + } + + bool hasTerminatingNullCharacter() const { return m_hashAndFlags & s_hashFlagHasTerminatingNullCharacter; } + + bool isAtomic() const { return m_hashAndFlags & s_hashFlagIsAtomic; } + void setIsAtomic(bool isIdentifier) + { + ASSERT(!isStatic()); + if (isIdentifier) + m_hashAndFlags |= s_hashFlagIsAtomic; + else + m_hashAndFlags &= ~s_hashFlagIsAtomic; + } + +private: + // The high bits of 'hash' are always empty, but we prefer to store our flags + // in the low bits because it makes them slightly more efficient to access. + // So, we shift left and right when setting and getting our hash code. + void setHash(unsigned hash) const + { + ASSERT(!hasHash()); + // Multiple clients assume that StringHasher is the canonical string hash function. + ASSERT(hash == (is8Bit() ? StringHasher::computeHash(m_data8, m_length) : StringHasher::computeHash(m_data16, m_length))); + ASSERT(!(hash & (s_flagMask << (8 * sizeof(hash) - s_flagCount)))); // Verify that enough high bits are empty. + + hash <<= s_flagCount; + ASSERT(!(hash & m_hashAndFlags)); // Verify that enough low bits are empty after shift. + ASSERT(hash); // Verify that 0 is a valid sentinel hash value. + + m_hashAndFlags |= hash; // Store hash with flags in low bits. + } + + unsigned rawHash() const + { + return m_hashAndFlags >> s_flagCount; + } + +public: + bool hasHash() const + { + return rawHash() != 0; + } + + unsigned existingHash() const + { + ASSERT(hasHash()); + return rawHash(); + } + + unsigned hash() const + { + if (hasHash()) + return existingHash(); + return hashSlowCase(); + } + + inline bool hasOneRef() const + { + return m_refCount == s_refCountIncrement; + } + + inline void ref() + { + m_refCount += s_refCountIncrement; + } + + inline void deref() + { + if (m_refCount == s_refCountIncrement) { + delete this; + return; + } + + m_refCount -= s_refCountIncrement; + } + + WTF_EXPORT_PRIVATE static StringImpl* empty(); + + // FIXME: Does this really belong in StringImpl? + template static void copyChars(T* destination, const T* source, unsigned numCharacters) + { + if (numCharacters == 1) { + *destination = *source; + return; + } + + if (numCharacters <= s_copyCharsInlineCutOff) { + unsigned i = 0; +#if (CPU(X86) || CPU(X86_64)) + const unsigned charsPerInt = sizeof(uint32_t) / sizeof(T); + + if (numCharacters > charsPerInt) { + unsigned stopCount = numCharacters & ~(charsPerInt - 1); + + const uint32_t* srcCharacters = reinterpret_cast(source); + uint32_t* destCharacters = reinterpret_cast(destination); + for (unsigned j = 0; i < stopCount; i += charsPerInt, ++j) + destCharacters[j] = srcCharacters[j]; + } +#endif + for (; i < numCharacters; ++i) + destination[i] = source[i]; + } else + memcpy(destination, source, numCharacters * sizeof(T)); + } + + // Some string features, like refcounting and the atomicity flag, are not + // thread-safe. We achieve thread safety by isolation, giving each thread + // its own copy of the string. + PassRefPtr isolatedCopy() const; + + WTF_EXPORT_PRIVATE PassRefPtr substring(unsigned pos, unsigned len = UINT_MAX); + + UChar operator[](unsigned i) const + { + ASSERT(i < m_length); + if (is8Bit()) + return m_data8[i]; + return m_data16[i]; + } + WTF_EXPORT_PRIVATE UChar32 characterStartingAt(unsigned); + + WTF_EXPORT_PRIVATE bool containsOnlyWhitespace(); + + int toIntStrict(bool* ok = 0, int base = 10); + unsigned toUIntStrict(bool* ok = 0, int base = 10); + int64_t toInt64Strict(bool* ok = 0, int base = 10); + uint64_t toUInt64Strict(bool* ok = 0, int base = 10); + intptr_t toIntPtrStrict(bool* ok = 0, int base = 10); + + WTF_EXPORT_PRIVATE int toInt(bool* ok = 0); // ignores trailing garbage + unsigned toUInt(bool* ok = 0); // ignores trailing garbage + int64_t toInt64(bool* ok = 0); // ignores trailing garbage + uint64_t toUInt64(bool* ok = 0); // ignores trailing garbage + intptr_t toIntPtr(bool* ok = 0); // ignores trailing garbage + + double toDouble(bool* ok = 0, bool* didReadNumber = 0); + float toFloat(bool* ok = 0, bool* didReadNumber = 0); + + WTF_EXPORT_PRIVATE PassRefPtr lower(); + WTF_EXPORT_PRIVATE PassRefPtr upper(); + + WTF_EXPORT_PRIVATE PassRefPtr fill(UChar); + // FIXME: Do we need fill(char) or can we just do the right thing if UChar is ASCII? + PassRefPtr foldCase(); + + PassRefPtr stripWhiteSpace(); + PassRefPtr stripWhiteSpace(IsWhiteSpaceFunctionPtr); + WTF_EXPORT_PRIVATE PassRefPtr simplifyWhiteSpace(); + PassRefPtr simplifyWhiteSpace(IsWhiteSpaceFunctionPtr); + + PassRefPtr removeCharacters(CharacterMatchFunctionPtr); + template + ALWAYS_INLINE PassRefPtr removeCharacters(const CharType* characters, CharacterMatchFunctionPtr); + + WTF_EXPORT_PRIVATE size_t find(UChar, unsigned index = 0); + WTF_EXPORT_PRIVATE size_t find(CharacterMatchFunctionPtr, unsigned index = 0); + size_t find(const LChar*, unsigned index = 0); + ALWAYS_INLINE size_t find(const char* s, unsigned index = 0) { return find(reinterpret_cast(s), index); }; + WTF_EXPORT_PRIVATE size_t find(StringImpl*, unsigned index = 0); + size_t findIgnoringCase(const LChar*, unsigned index = 0); + ALWAYS_INLINE size_t findIgnoringCase(const char* s, unsigned index = 0) { return findIgnoringCase(reinterpret_cast(s), index); }; + WTF_EXPORT_PRIVATE size_t findIgnoringCase(StringImpl*, unsigned index = 0); + + WTF_EXPORT_PRIVATE size_t reverseFind(UChar, unsigned index = UINT_MAX); + WTF_EXPORT_PRIVATE size_t reverseFind(StringImpl*, unsigned index = UINT_MAX); + WTF_EXPORT_PRIVATE size_t reverseFindIgnoringCase(StringImpl*, unsigned index = UINT_MAX); + + bool startsWith(StringImpl* str, bool caseSensitive = true) { return (caseSensitive ? reverseFind(str, 0) : reverseFindIgnoringCase(str, 0)) == 0; } + WTF_EXPORT_PRIVATE bool endsWith(StringImpl*, bool caseSensitive = true); + + WTF_EXPORT_PRIVATE PassRefPtr replace(UChar, UChar); + WTF_EXPORT_PRIVATE PassRefPtr replace(UChar, StringImpl*); + WTF_EXPORT_PRIVATE PassRefPtr replace(StringImpl*, StringImpl*); + WTF_EXPORT_PRIVATE PassRefPtr replace(unsigned index, unsigned len, StringImpl*); + + WTF_EXPORT_PRIVATE WTF::Unicode::Direction defaultWritingDirection(bool* hasStrongDirectionality = 0); + +#if USE(CF) + CFStringRef createCFString(); +#endif +#ifdef __OBJC__ + operator NSString*(); +#endif + +private: + // This number must be at least 2 to avoid sharing empty, null as well as 1 character strings from SmallStrings. + static const unsigned s_copyCharsInlineCutOff = 20; + + BufferOwnership bufferOwnership() const { return static_cast(m_hashAndFlags & s_hashMaskBufferOwnership); } + bool isStatic() const { return m_refCount & s_refCountFlagIsStaticString; } + template PassRefPtr stripMatchedCharacters(UCharPredicate); + template PassRefPtr simplifyMatchedCharactersToSpace(UCharPredicate); + WTF_EXPORT_PRIVATE NEVER_INLINE const UChar* getData16SlowCase() const; + WTF_EXPORT_PRIVATE NEVER_INLINE unsigned hashSlowCase() const; + + // The bottom bit in the ref count indicates a static (immortal) string. + static const unsigned s_refCountFlagIsStaticString = 0x1; + static const unsigned s_refCountIncrement = 0x2; // This allows us to ref / deref without disturbing the static string flag. + + // The bottom 8 bits in the hash are flags. + static const unsigned s_flagCount = 8; + static const unsigned s_flagMask = (1u << s_flagCount) - 1; + COMPILE_ASSERT(s_flagCount == StringHasher::flagCount, StringHasher_reserves_enough_bits_for_StringImpl_flags); + + static const unsigned s_hashFlagHas16BitShadow = 1u << 7; + static const unsigned s_hashFlag8BitBuffer = 1u << 6; + static const unsigned s_hashFlagHasTerminatingNullCharacter = 1u << 5; + static const unsigned s_hashFlagIsAtomic = 1u << 4; + static const unsigned s_hashFlagDidReportCost = 1u << 3; + static const unsigned s_hashFlagIsIdentifier = 1u << 2; + static const unsigned s_hashMaskBufferOwnership = 1u | (1u << 1); + + unsigned m_refCount; + unsigned m_length; + union { + const LChar* m_data8; + const UChar* m_data16; + }; + union { + void* m_buffer; + StringImpl* m_substringBuffer; + mutable UChar* m_copyData16; + }; + mutable unsigned m_hashAndFlags; +}; + +template <> +ALWAYS_INLINE const LChar* StringImpl::getCharacters() const { return characters8(); } + +template <> +ALWAYS_INLINE const UChar* StringImpl::getCharacters() const { return characters16(); } + +WTF_EXPORT_PRIVATE bool equal(const StringImpl*, const StringImpl*); +WTF_EXPORT_PRIVATE bool equal(const StringImpl*, const LChar*); +inline bool equal(const StringImpl* a, const char* b) { return equal(a, reinterpret_cast(b)); } +WTF_EXPORT_PRIVATE bool equal(const StringImpl*, const LChar*, unsigned); +inline bool equal(const StringImpl* a, const char* b, unsigned length) { return equal(a, reinterpret_cast(b), length); } +inline bool equal(const LChar* a, StringImpl* b) { return equal(b, a); } +inline bool equal(const char* a, StringImpl* b) { return equal(b, reinterpret_cast(a)); } +WTF_EXPORT_PRIVATE bool equal(const StringImpl*, const UChar*, unsigned); + +// Do comparisons 8 or 4 bytes-at-a-time on architectures where it's safe. +#if CPU(X86_64) +ALWAYS_INLINE bool equal(const LChar* a, const LChar* b, unsigned length) +{ + unsigned dwordLength = length >> 3; + + if (dwordLength) { + const uint64_t* aDWordCharacters = reinterpret_cast(a); + const uint64_t* bDWordCharacters = reinterpret_cast(b); + + for (unsigned i = 0; i != dwordLength; ++i) { + if (*aDWordCharacters++ != *bDWordCharacters++) + return false; + } + + a = reinterpret_cast(aDWordCharacters); + b = reinterpret_cast(bDWordCharacters); + } + + if (length & 4) { + if (*reinterpret_cast(a) != *reinterpret_cast(b)) + return false; + + a += 4; + b += 4; + } + + if (length & 2) { + if (*reinterpret_cast(a) != *reinterpret_cast(b)) + return false; + + a += 2; + b += 2; + } + + if (length & 1 && (*a != *b)) + return false; + + return true; +} + +ALWAYS_INLINE bool equal(const UChar* a, const UChar* b, unsigned length) +{ + unsigned dwordLength = length >> 2; + + if (dwordLength) { + const uint64_t* aDWordCharacters = reinterpret_cast(a); + const uint64_t* bDWordCharacters = reinterpret_cast(b); + + for (unsigned i = 0; i != dwordLength; ++i) { + if (*aDWordCharacters++ != *bDWordCharacters++) + return false; + } + + a = reinterpret_cast(aDWordCharacters); + b = reinterpret_cast(bDWordCharacters); + } + + if (length & 2) { + if (*reinterpret_cast(a) != *reinterpret_cast(b)) + return false; + + a += 2; + b += 2; + } + + if (length & 1 && (*a != *b)) + return false; + + return true; +} +#elif CPU(X86) +ALWAYS_INLINE bool equal(const LChar* a, const LChar* b, unsigned length) +{ + const uint32_t* aCharacters = reinterpret_cast(a); + const uint32_t* bCharacters = reinterpret_cast(b); + + unsigned wordLength = length >> 2; + for (unsigned i = 0; i != wordLength; ++i) { + if (*aCharacters++ != *bCharacters++) + return false; + } + + length &= 3; + + if (length) { + const LChar* aRemainder = reinterpret_cast(aCharacters); + const LChar* bRemainder = reinterpret_cast(bCharacters); + + for (unsigned i = 0; i < length; ++i) { + if (aRemainder[i] != bRemainder[i]) + return false; + } + } + + return true; +} + +ALWAYS_INLINE bool equal(const UChar* a, const UChar* b, unsigned length) +{ + const uint32_t* aCharacters = reinterpret_cast(a); + const uint32_t* bCharacters = reinterpret_cast(b); + + unsigned wordLength = length >> 1; + for (unsigned i = 0; i != wordLength; ++i) { + if (*aCharacters++ != *bCharacters++) + return false; + } + + if (length & 1 && *reinterpret_cast(aCharacters) != *reinterpret_cast(bCharacters)) + return false; + + return true; +} +#else +ALWAYS_INLINE bool equal(const LChar* a, const LChar* b, unsigned length) +{ + for (unsigned i = 0; i != length; ++i) { + if (a[i] != b[i]) + return false; + } + + return true; +} + +ALWAYS_INLINE bool equal(const UChar* a, const UChar* b, unsigned length) +{ + for (unsigned i = 0; i != length; ++i) { + if (a[i] != b[i]) + return false; + } + + return true; +} +#endif + +ALWAYS_INLINE bool equal(const LChar* a, const UChar* b, unsigned length) +{ + for (unsigned i = 0; i != length; ++i) { + if (a[i] != b[i]) + return false; + } + + return true; +} + +ALWAYS_INLINE bool equal(const UChar* a, const LChar* b, unsigned length) +{ + for (unsigned i = 0; i != length; ++i) { + if (a[i] != b[i]) + return false; + } + + return true; +} + +WTF_EXPORT_PRIVATE bool equalIgnoringCase(StringImpl*, StringImpl*); +WTF_EXPORT_PRIVATE bool equalIgnoringCase(StringImpl*, const LChar*); +inline bool equalIgnoringCase(const LChar* a, StringImpl* b) { return equalIgnoringCase(b, a); } +WTF_EXPORT_PRIVATE bool equalIgnoringCase(const UChar*, const LChar*, unsigned); +inline bool equalIgnoringCase(const UChar* a, const char* b, unsigned length) { return equalIgnoringCase(a, reinterpret_cast(b), length); } +inline bool equalIgnoringCase(const LChar* a, const UChar* b, unsigned length) { return equalIgnoringCase(b, a, length); } +inline bool equalIgnoringCase(const char* a, const UChar* b, unsigned length) { return equalIgnoringCase(b, reinterpret_cast(a), length); } + +WTF_EXPORT_PRIVATE bool equalIgnoringNullity(StringImpl*, StringImpl*); + +template +bool equalIgnoringNullity(const Vector& a, StringImpl* b) +{ + if (!b) + return !a.size(); + if (a.size() != b->length()) + return false; + return !memcmp(a.data(), b->characters(), b->length()); +} + +WTF_EXPORT_PRIVATE int codePointCompare(const StringImpl*, const StringImpl*); + +static inline bool isSpaceOrNewline(UChar c) +{ + // Use isASCIISpace() for basic Latin-1. + // This will include newlines, which aren't included in Unicode DirWS. + return c <= 0x7F ? WTF::isASCIISpace(c) : WTF::Unicode::direction(c) == WTF::Unicode::WhiteSpaceNeutral; +} + +inline PassRefPtr StringImpl::isolatedCopy() const +{ + if (is8Bit()) + return create(m_data8, m_length); + return create(m_data16, m_length); +} + +struct StringHash; + +// StringHash is the default hash for StringImpl* and RefPtr +template struct DefaultHash; +template<> struct DefaultHash { + typedef StringHash Hash; +}; +template<> struct DefaultHash > { + typedef StringHash Hash; +}; + +} + +using WTF::StringImpl; +using WTF::equal; +using WTF::TextCaseSensitivity; +using WTF::TextCaseSensitive; +using WTF::TextCaseInsensitive; + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StringObject.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StringObject.h new file mode 100644 index 000000000..248c71601 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StringObject.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef StringObject_h +#define StringObject_h + +#include "JSWrapperObject.h" +#include "JSString.h" + +namespace JSC { + + class StringObject : public JSWrapperObject { + public: + typedef JSWrapperObject Base; + + static StringObject* create(ExecState* exec, Structure* structure) + { + JSString* string = jsEmptyString(exec); + StringObject* object = new (NotNull, allocateCell(*exec->heap())) StringObject(exec->globalData(), structure); + object->finishCreation(exec->globalData(), string); + return object; + } + static StringObject* create(ExecState* exec, Structure* structure, JSString* string) + { + StringObject* object = new (NotNull, allocateCell(*exec->heap())) StringObject(exec->globalData(), structure); + object->finishCreation(exec->globalData(), string); + return object; + } + static StringObject* create(ExecState*, JSGlobalObject*, JSString*); + + static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier& propertyName, PropertySlot&); + static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&); + static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); + + static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); + + static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName); + static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); + + static const JS_EXPORTDATA ClassInfo s_info; + + JSString* internalValue() const { return asString(JSWrapperObject::internalValue());} + + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + { + return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); + } + + protected: + JS_EXPORT_PRIVATE void finishCreation(JSGlobalData&, JSString*); + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | JSWrapperObject::StructureFlags; + JS_EXPORT_PRIVATE StringObject(JSGlobalData&, Structure*); + }; + + StringObject* asStringObject(JSValue); + + inline StringObject* asStringObject(JSValue value) + { + ASSERT(asObject(value)->inherits(&StringObject::s_info)); + return static_cast(asObject(value)); + } + +} // namespace JSC + +#endif // StringObject_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StringOperators.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StringOperators.h new file mode 100644 index 000000000..9e1637be1 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StringOperators.h @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * Copyright (C) Research In Motion Limited 2011. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef StringOperators_h +#define StringOperators_h + +namespace WTF { + +template +class StringAppend { +public: + StringAppend(StringType1 string1, StringType2 string2) + : m_string1(string1) + , m_string2(string2) + { + } + + operator String() const + { + RefPtr resultImpl = tryMakeString(m_string1, m_string2); + if (!resultImpl) + CRASH(); + return resultImpl.release(); + } + + operator AtomicString() const + { + return operator String(); + } + + bool is8Bit() + { + StringTypeAdapter adapter1(m_string1); + StringTypeAdapter adapter2(m_string2); + return adapter1.is8Bit() && adapter2.is8Bit(); + } + + void writeTo(LChar* destination) + { + ASSERT(is8Bit()); + StringTypeAdapter adapter1(m_string1); + StringTypeAdapter adapter2(m_string2); + adapter1.writeTo(destination); + adapter2.writeTo(destination + adapter1.length()); + } + + void writeTo(UChar* destination) + { + StringTypeAdapter adapter1(m_string1); + StringTypeAdapter adapter2(m_string2); + adapter1.writeTo(destination); + adapter2.writeTo(destination + adapter1.length()); + } + + unsigned length() + { + StringTypeAdapter adapter1(m_string1); + StringTypeAdapter adapter2(m_string2); + return adapter1.length() + adapter2.length(); + } + +private: + StringType1 m_string1; + StringType2 m_string2; +}; + +template +class StringTypeAdapter > { +public: + StringTypeAdapter >(StringAppend& buffer) + : m_buffer(buffer) + { + } + + unsigned length() { return m_buffer.length(); } + + bool is8Bit() { return m_buffer.is8Bit(); } + + void writeTo(LChar* destination) { m_buffer.writeTo(destination); } + void writeTo(UChar* destination) { m_buffer.writeTo(destination); } + +private: + StringAppend& m_buffer; +}; + +inline StringAppend operator+(const char* string1, const String& string2) +{ + return StringAppend(string1, string2); +} + +inline StringAppend operator+(const char* string1, const AtomicString& string2) +{ + return StringAppend(string1, string2); +} + +template +StringAppend > operator+(const char* string1, const StringAppend& string2) +{ + return StringAppend >(string1, string2); +} + +inline StringAppend operator+(const UChar* string1, const String& string2) +{ + return StringAppend(string1, string2); +} + +inline StringAppend operator+(const UChar* string1, const AtomicString& string2) +{ + return StringAppend(string1, string2); +} + +template +StringAppend > operator+(const UChar* string1, const StringAppend& string2) +{ + return StringAppend >(string1, string2); +} + +template +StringAppend operator+(const String& string1, T string2) +{ + return StringAppend(string1, string2); +} + +template +StringAppend, W> operator+(const StringAppend& string1, W string2) +{ + return StringAppend, W>(string1, string2); +} + +} // namespace WTF + +#endif // StringOperators_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StringPrototype.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StringPrototype.h new file mode 100644 index 000000000..113f21f2a --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StringPrototype.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef StringPrototype_h +#define StringPrototype_h + +#include "StringObject.h" + +namespace JSC { + + class ObjectPrototype; + + class StringPrototype : public StringObject { + private: + StringPrototype(ExecState*, Structure*); + + public: + typedef StringObject Base; + + static StringPrototype* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure) + { + JSString* empty = jsEmptyString(exec); + StringPrototype* prototype = new (NotNull, allocateCell(*exec->heap())) StringPrototype(exec, structure); + prototype->finishCreation(exec, globalObject, empty); + return prototype; + } + + static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier& propertyName, PropertySlot&); + static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); + + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) + { + return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); + } + + static const ClassInfo s_info; + + protected: + void finishCreation(ExecState*, JSGlobalObject*, JSString*); + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | StringObject::StructureFlags; + + }; + +} // namespace JSC + +#endif // StringPrototype_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Strong.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Strong.h new file mode 100644 index 000000000..a9389fa53 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Strong.h @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2011 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 INC. 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 INC. 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 Strong_h +#define Strong_h + +#include "Assertions.h" +#include "Handle.h" +#include "HandleHeap.h" + +namespace JSC { + +class JSGlobalData; + +// A strongly referenced handle that prevents the object it points to from being garbage collected. +template class Strong : public Handle { + using Handle::slot; + using Handle::setSlot; + +public: + typedef typename Handle::ExternalType ExternalType; + + Strong() + : Handle() + { + } + + Strong(JSGlobalData&, ExternalType = ExternalType()); + + Strong(JSGlobalData&, Handle); + + Strong(const Strong& other) + : Handle() + { + if (!other.slot()) + return; + setSlot(HandleHeap::heapFor(other.slot())->allocate()); + set(other.get()); + } + + template Strong(const Strong& other) + : Handle() + { + if (!other.slot()) + return; + setSlot(HandleHeap::heapFor(other.slot())->allocate()); + set(other.get()); + } + + enum HashTableDeletedValueTag { HashTableDeletedValue }; + bool isHashTableDeletedValue() const { return slot() == hashTableDeletedValue(); } + Strong(HashTableDeletedValueTag) + : Handle(hashTableDeletedValue()) + { + } + + ~Strong() + { + clear(); + } + + void swap(Strong& other) + { + Handle::swap(other); + } + + void set(JSGlobalData&, ExternalType); + + template Strong& operator=(const Strong& other) + { + if (!other.slot()) { + clear(); + return *this; + } + + set(*HandleHeap::heapFor(other.slot())->globalData(), other.get()); + return *this; + } + + Strong& operator=(const Strong& other) + { + if (!other.slot()) { + clear(); + return *this; + } + + set(*HandleHeap::heapFor(other.slot())->globalData(), other.get()); + return *this; + } + + void clear() + { + if (!slot()) + return; + HandleHeap::heapFor(slot())->deallocate(slot()); + setSlot(0); + } + +private: + static HandleSlot hashTableDeletedValue() { return reinterpret_cast(-1); } + + void set(ExternalType externalType) + { + ASSERT(slot()); + JSValue value = HandleTypes::toJSValue(externalType); + HandleHeap::heapFor(slot())->writeBarrier(slot(), value); + *slot() = value; + } +}; + +template inline void swap(Strong& a, Strong& b) +{ + a.swap(b); +} + +} // namespace JSC + +namespace WTF { + +template struct VectorTraits > : SimpleClassVectorTraits { + static const bool canCompareWithMemcmp = false; +}; + +template struct HashTraits > : SimpleClassHashTraits > { }; + +} + +#endif // Strong_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StrongInlines.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StrongInlines.h new file mode 100644 index 000000000..46049096a --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StrongInlines.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2011 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 INC. 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 INC. 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 StrongInlines_h +#define StrongInlines_h + +namespace JSC { + +template +inline Strong::Strong(JSGlobalData& globalData, ExternalType value) + : Handle(globalData.heap.handleHeap()->allocate()) +{ + set(value); +} + +template +inline Strong::Strong(JSGlobalData& globalData, Handle handle) + : Handle(globalData.heap.handleHeap()->allocate()) +{ + set(handle.get()); +} + +template +inline void Strong::set(JSGlobalData& globalData, ExternalType value) +{ + if (!slot()) + setSlot(globalData.heap.handleHeap()->allocate()); + set(value); +} + +} // namespace JSC + +#endif // StrongInlines_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Structure.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Structure.h new file mode 100644 index 000000000..ced296856 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Structure.h @@ -0,0 +1,406 @@ +/* + * Copyright (C) 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. + * + * 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 Structure_h +#define Structure_h + +#include "ClassInfo.h" +#include "Identifier.h" +#include "JSCell.h" +#include "JSType.h" +#include "JSValue.h" +#include "PropertyMapHashTable.h" +#include "PropertyNameArray.h" +#include "Protect.h" +#include "StructureTransitionTable.h" +#include "JSTypeInfo.h" +#include "UString.h" +#include "Weak.h" +#include +#include +#include + + +namespace JSC { + + class PropertyNameArray; + class PropertyNameArrayData; + class StructureChain; + class SlotVisitor; + + class Structure : public JSCell { + public: + friend class StructureTransitionTable; + + typedef JSCell Base; + + static Structure* create(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype, const TypeInfo& typeInfo, const ClassInfo* classInfo) + { + ASSERT(globalData.structureStructure); + ASSERT(classInfo); + Structure* structure = new (NotNull, allocateCell(globalData.heap)) Structure(globalData, globalObject, prototype, typeInfo, classInfo); + structure->finishCreation(globalData); + return structure; + } + + protected: + void finishCreation(JSGlobalData& globalData) + { + Base::finishCreation(globalData); + ASSERT(m_prototype); + ASSERT(m_prototype.isObject() || m_prototype.isNull()); + } + + void finishCreation(JSGlobalData& globalData, CreatingEarlyCellTag) + { + Base::finishCreation(globalData, this, CreatingEarlyCell); + ASSERT(m_prototype); + ASSERT(m_prototype.isNull()); + ASSERT(!globalData.structureStructure); + } + + public: + static void dumpStatistics(); + + JS_EXPORT_PRIVATE static Structure* addPropertyTransition(JSGlobalData&, Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset); + JS_EXPORT_PRIVATE static Structure* addPropertyTransitionToExistingStructure(Structure*, const Identifier& propertyName, unsigned attributes, JSCell* specificValue, size_t& offset); + static Structure* removePropertyTransition(JSGlobalData&, Structure*, const Identifier& propertyName, size_t& offset); + JS_EXPORT_PRIVATE static Structure* changePrototypeTransition(JSGlobalData&, Structure*, JSValue prototype); + JS_EXPORT_PRIVATE static Structure* despecifyFunctionTransition(JSGlobalData&, Structure*, const Identifier&); + static Structure* attributeChangeTransition(JSGlobalData&, Structure*, const Identifier& propertyName, unsigned attributes); + static Structure* toCacheableDictionaryTransition(JSGlobalData&, Structure*); + static Structure* toUncacheableDictionaryTransition(JSGlobalData&, Structure*); + static Structure* sealTransition(JSGlobalData&, Structure*); + static Structure* freezeTransition(JSGlobalData&, Structure*); + static Structure* preventExtensionsTransition(JSGlobalData&, Structure*); + + bool isSealed(JSGlobalData&); + bool isFrozen(JSGlobalData&); + bool isExtensible() const { return !m_preventExtensions; } + bool didTransition() const { return m_didTransition; } + + Structure* flattenDictionaryStructure(JSGlobalData&, JSObject*); + + static void destroy(JSCell*); + + // These should be used with caution. + JS_EXPORT_PRIVATE size_t addPropertyWithoutTransition(JSGlobalData&, const Identifier& propertyName, unsigned attributes, JSCell* specificValue); + size_t removePropertyWithoutTransition(JSGlobalData&, const Identifier& propertyName); + void setPrototypeWithoutTransition(JSGlobalData& globalData, JSValue prototype) { m_prototype.set(globalData, this, prototype); } + + bool isDictionary() const { return m_dictionaryKind != NoneDictionaryKind; } + bool isUncacheableDictionary() const { return m_dictionaryKind == UncachedDictionaryKind; } + + // Type accessors. + const TypeInfo& typeInfo() const { ASSERT(structure()->classInfo() == &s_info); return m_typeInfo; } + bool isObject() const { return typeInfo().isObject(); } + + + JSGlobalObject* globalObject() const { return m_globalObject.get(); } + void setGlobalObject(JSGlobalData& globalData, JSGlobalObject* globalObject) { m_globalObject.set(globalData, this, globalObject); } + + JSValue storedPrototype() const { return m_prototype.get(); } + JSValue prototypeForLookup(ExecState*) const; + StructureChain* prototypeChain(ExecState*) const; + static void visitChildren(JSCell*, SlotVisitor&); + + Structure* previousID() const { ASSERT(structure()->classInfo() == &s_info); return m_previous.get(); } + bool transitivelyTransitionedFrom(Structure* structureToFind); + + void growPropertyStorageCapacity(); + unsigned propertyStorageCapacity() const { ASSERT(structure()->classInfo() == &s_info); return m_propertyStorageCapacity; } + unsigned propertyStorageSize() const { ASSERT(structure()->classInfo() == &s_info); return (m_propertyTable ? m_propertyTable->propertyStorageSize() : static_cast(m_offset + 1)); } + bool isUsingInlineStorage() const; + + size_t get(JSGlobalData&, const Identifier& propertyName); + size_t get(JSGlobalData&, const UString& name); + JS_EXPORT_PRIVATE size_t get(JSGlobalData&, StringImpl* propertyName, unsigned& attributes, JSCell*& specificValue); + size_t get(JSGlobalData& globalData, const Identifier& propertyName, unsigned& attributes, JSCell*& specificValue) + { + ASSERT(!propertyName.isNull()); + ASSERT(structure()->classInfo() == &s_info); + return get(globalData, propertyName.impl(), attributes, specificValue); + } + + bool hasGetterSetterProperties() const { return m_hasGetterSetterProperties; } + void setHasGetterSetterProperties(bool hasGetterSetterProperties) { m_hasGetterSetterProperties = hasGetterSetterProperties; } + + bool hasNonEnumerableProperties() const { return m_hasNonEnumerableProperties; } + + bool isEmpty() const { return m_propertyTable ? m_propertyTable->isEmpty() : m_offset == noOffset; } + + JS_EXPORT_PRIVATE void despecifyDictionaryFunction(JSGlobalData&, const Identifier& propertyName); + void disableSpecificFunctionTracking() { m_specificFunctionThrashCount = maxSpecificFunctionThrashCount; } + + void setEnumerationCache(JSGlobalData&, JSPropertyNameIterator* enumerationCache); // Defined in JSPropertyNameIterator.h. + JSPropertyNameIterator* enumerationCache(); // Defined in JSPropertyNameIterator.h. + void getPropertyNamesFromStructure(JSGlobalData&, PropertyNameArray&, EnumerationMode); + + bool staticFunctionsReified() + { + return m_staticFunctionReified; + } + + void setStaticFunctionsReified() + { + m_staticFunctionReified = true; + } + + const ClassInfo* classInfo() const { return m_classInfo; } + + static ptrdiff_t prototypeOffset() + { + return OBJECT_OFFSETOF(Structure, m_prototype); + } + + static ptrdiff_t typeInfoFlagsOffset() + { + return OBJECT_OFFSETOF(Structure, m_typeInfo) + TypeInfo::flagsOffset(); + } + + static ptrdiff_t typeInfoTypeOffset() + { + return OBJECT_OFFSETOF(Structure, m_typeInfo) + TypeInfo::typeOffset(); + } + + static Structure* createStructure(JSGlobalData& globalData) + { + ASSERT(!globalData.structureStructure); + Structure* structure = new (NotNull, allocateCell(globalData.heap)) Structure(globalData); + structure->finishCreation(globalData, CreatingEarlyCell); + return structure; + } + + static JS_EXPORTDATA const ClassInfo s_info; + + private: + JS_EXPORT_PRIVATE Structure(JSGlobalData&, JSGlobalObject*, JSValue prototype, const TypeInfo&, const ClassInfo*); + Structure(JSGlobalData&); + Structure(JSGlobalData&, const Structure*); + + static Structure* create(JSGlobalData& globalData, const Structure* structure) + { + ASSERT(globalData.structureStructure); + Structure* newStructure = new (NotNull, allocateCell(globalData.heap)) Structure(globalData, structure); + newStructure->finishCreation(globalData); + return newStructure; + } + + typedef enum { + NoneDictionaryKind = 0, + CachedDictionaryKind = 1, + UncachedDictionaryKind = 2 + } DictionaryKind; + static Structure* toDictionaryTransition(JSGlobalData&, Structure*, DictionaryKind); + + size_t putSpecificValue(JSGlobalData&, const Identifier& propertyName, unsigned attributes, JSCell* specificValue); + size_t remove(const Identifier& propertyName); + + void createPropertyMap(unsigned keyCount = 0); + void checkConsistency(); + + bool despecifyFunction(JSGlobalData&, const Identifier&); + void despecifyAllFunctions(JSGlobalData&); + + PassOwnPtr copyPropertyTable(JSGlobalData&, Structure* owner); + PassOwnPtr copyPropertyTableForPinning(JSGlobalData&, Structure* owner); + JS_EXPORT_PRIVATE void materializePropertyMap(JSGlobalData&); + void materializePropertyMapIfNecessary(JSGlobalData& globalData) + { + ASSERT(structure()->classInfo() == &s_info); + if (!m_propertyTable && m_previous) + materializePropertyMap(globalData); + } + void materializePropertyMapIfNecessaryForPinning(JSGlobalData& globalData) + { + ASSERT(structure()->classInfo() == &s_info); + if (!m_propertyTable) + materializePropertyMap(globalData); + } + + int transitionCount() const + { + // Since the number of transitions is always the same as m_offset, we keep the size of Structure down by not storing both. + return m_offset == noOffset ? 0 : m_offset + 1; + } + + bool isValid(ExecState*, StructureChain* cachedPrototypeChain) const; + + void pin(); + + static const int s_maxTransitionLength = 64; + + static const int noOffset = -1; + + static const unsigned maxSpecificFunctionThrashCount = 3; + + TypeInfo m_typeInfo; + + WriteBarrier m_globalObject; + WriteBarrier m_prototype; + mutable WriteBarrier m_cachedPrototypeChain; + + WriteBarrier m_previous; + RefPtr m_nameInPrevious; + WriteBarrier m_specificValueInPrevious; + + const ClassInfo* m_classInfo; + + StructureTransitionTable m_transitionTable; + + WriteBarrier m_enumerationCache; + + OwnPtr m_propertyTable; + + uint32_t m_propertyStorageCapacity; + + // m_offset does not account for anonymous slots + int m_offset; + + unsigned m_dictionaryKind : 2; + bool m_isPinnedPropertyTable : 1; + bool m_hasGetterSetterProperties : 1; + bool m_hasNonEnumerableProperties : 1; + unsigned m_attributesInPrevious : 7; + unsigned m_specificFunctionThrashCount : 2; + unsigned m_preventExtensions : 1; + unsigned m_didTransition : 1; + unsigned m_staticFunctionReified; + }; + + inline size_t Structure::get(JSGlobalData& globalData, const Identifier& propertyName) + { + ASSERT(structure()->classInfo() == &s_info); + materializePropertyMapIfNecessary(globalData); + if (!m_propertyTable) + return notFound; + + PropertyMapEntry* entry = m_propertyTable->find(propertyName.impl()).first; + return entry ? entry->offset : notFound; + } + + inline size_t Structure::get(JSGlobalData& globalData, const UString& name) + { + ASSERT(structure()->classInfo() == &s_info); + materializePropertyMapIfNecessary(globalData); + if (!m_propertyTable) + return notFound; + + PropertyMapEntry* entry = m_propertyTable->findWithString(name.impl()).first; + return entry ? entry->offset : notFound; + } + + inline bool JSCell::isObject() const + { + return m_structure->isObject(); + } + + inline bool JSCell::isString() const + { + return m_structure->typeInfo().type() == StringType; + } + + inline bool JSCell::isGetterSetter() const + { + return m_structure->typeInfo().type() == GetterSetterType; + } + + inline bool JSCell::isAPIValueWrapper() const + { + return m_structure->typeInfo().type() == APIValueWrapperType; + } + + inline void JSCell::setStructure(JSGlobalData& globalData, Structure* structure) + { + ASSERT(structure->typeInfo().overridesVisitChildren() == this->structure()->typeInfo().overridesVisitChildren()); + ASSERT(structure->classInfo() == m_structure->classInfo()); + m_structure.set(globalData, this, structure); + } + + inline const ClassInfo* JSCell::validatedClassInfo() const + { +#if ENABLE(GC_VALIDATION) + ASSERT(m_structure.unvalidatedGet()->classInfo() == m_classInfo); +#else + ASSERT(m_structure->classInfo() == m_classInfo); +#endif + return m_classInfo; + } + + ALWAYS_INLINE void MarkStack::internalAppend(JSCell* cell) + { + ASSERT(!m_isCheckingForDefaultMarkViolation); +#if ENABLE(GC_VALIDATION) + validate(cell); +#endif + m_visitCount++; + if (Heap::testAndSetMarked(cell) || !cell->structure()) + return; + + // Should never attempt to mark something that is zapped. + ASSERT(!cell->isZapped()); + + m_stack.append(cell); + } + + inline StructureTransitionTable::Hash::Key StructureTransitionTable::keyForWeakGCMapFinalizer(void*, Structure* structure) + { + // Newer versions of the STL have an std::make_pair function that takes rvalue references. + // When either of the parameters are bitfields, the C++ compiler will try to bind them as lvalues, which is invalid. To work around this, use unary "+" to make the parameter an rvalue. + // See https://bugs.webkit.org/show_bug.cgi?id=59261 for more details. + return Hash::Key(structure->m_nameInPrevious.get(), +structure->m_attributesInPrevious); + } + + inline bool Structure::transitivelyTransitionedFrom(Structure* structureToFind) + { + for (Structure* current = this; current; current = current->previousID()) { + if (current == structureToFind) + return true; + } + return false; + } + + inline JSCell::JSCell(JSGlobalData& globalData, Structure* structure) + : m_classInfo(structure->classInfo()) + , m_structure(globalData, this, structure) + { + } + + inline void JSCell::finishCreation(JSGlobalData& globalData, Structure* structure, CreatingEarlyCellTag) + { +#if ENABLE(GC_VALIDATION) + ASSERT(globalData.isInitializingObject()); + globalData.setInitializingObject(false); + if (structure) +#endif + m_structure.setEarlyValue(globalData, this, structure); + m_classInfo = structure->classInfo(); + // Very first set of allocations won't have a real structure. + ASSERT(m_structure || !globalData.structureStructure); + } + +} // namespace JSC + +#endif // Structure_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StructureChain.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StructureChain.h new file mode 100644 index 000000000..df7a37fa7 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StructureChain.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) 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. + */ + +#ifndef StructureChain_h +#define StructureChain_h + +#include "JSCell.h" +#include "JSObject.h" +#include "Structure.h" + +#include +#include +#include +#include + +namespace JSC { + + class Structure; + + class StructureChain : public JSCell { + friend class JIT; + + public: + typedef JSCell Base; + + static StructureChain* create(JSGlobalData& globalData, Structure* head) + { + StructureChain* chain = new (NotNull, allocateCell(globalData.heap)) StructureChain(globalData, globalData.structureChainStructure.get()); + chain->finishCreation(globalData, head); + return chain; + } + WriteBarrier* head() { return m_vector.get(); } + static void visitChildren(JSCell*, SlotVisitor&); + + static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) { return Structure::create(globalData, globalObject, prototype, TypeInfo(CompoundType, OverridesVisitChildren), &s_info); } + + static ClassInfo s_info; + + protected: + void finishCreation(JSGlobalData& globalData, Structure* head) + { + Base::finishCreation(globalData); + size_t size = 0; + for (Structure* current = head; current; current = current->storedPrototype().isNull() ? 0 : asObject(current->storedPrototype())->structure()) + ++size; + + m_vector = adoptArrayPtr(new WriteBarrier[size + 1]); + + size_t i = 0; + for (Structure* current = head; current; current = current->storedPrototype().isNull() ? 0 : asObject(current->storedPrototype())->structure()) + m_vector[i++].set(globalData, this, current); + } + + private: + StructureChain(JSGlobalData&, Structure*); + static void destroy(JSCell*); + OwnArrayPtr > m_vector; + }; + +} // namespace JSC + +#endif // StructureChain_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StructureSet.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StructureSet.h new file mode 100644 index 000000000..344183b45 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StructureSet.h @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2011 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 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 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 StructureSet_h +#define StructureSet_h + +#include "PredictedType.h" +#include +#include + +namespace JSC { + +class Structure; + +namespace DFG { +class StructureAbstractValue; +} + +class StructureSet { +public: + StructureSet() { } + + StructureSet(Structure* structure) + { + m_structures.append(structure); + } + + void clear() + { + m_structures.clear(); + } + + void add(Structure* structure) + { + ASSERT(!contains(structure)); + m_structures.append(structure); + } + + bool addAll(const StructureSet& other) + { + bool changed = false; + for (size_t i = 0; i < other.size(); ++i) { + if (contains(other[i])) + continue; + add(other[i]); + changed = true; + } + return changed; + } + + void remove(Structure* structure) + { + for (size_t i = 0; i < m_structures.size(); ++i) { + if (m_structures[i] != structure) + continue; + + m_structures[i] = m_structures.last(); + m_structures.removeLast(); + return; + } + } + + bool contains(Structure* structure) const + { + for (size_t i = 0; i < m_structures.size(); ++i) { + if (m_structures[i] == structure) + return true; + } + return false; + } + + bool isSubsetOf(const StructureSet& other) const + { + for (size_t i = 0; i < m_structures.size(); ++i) { + if (!other.contains(m_structures[i])) + return false; + } + return true; + } + + bool isSupersetOf(const StructureSet& other) const + { + return other.isSubsetOf(*this); + } + + size_t size() const { return m_structures.size(); } + + Structure* at(size_t i) const { return m_structures.at(i); } + + Structure* operator[](size_t i) const { return at(i); } + + Structure* last() const { return m_structures.last(); } + + PredictedType predictionFromStructures() const + { + PredictedType result = PredictNone; + + for (size_t i = 0; i < m_structures.size(); ++i) + mergePrediction(result, predictionFromStructure(m_structures[i])); + + return result; + } + + bool operator==(const StructureSet& other) const + { + if (m_structures.size() != other.m_structures.size()) + return false; + + for (size_t i = 0; i < m_structures.size(); ++i) { + if (!other.contains(m_structures[i])) + return false; + } + + return true; + } + + void dump(FILE* out) + { + fprintf(out, "["); + for (size_t i = 0; i < m_structures.size(); ++i) { + if (i) + fprintf(out, ", "); + fprintf(out, "%p", m_structures[i]); + } + fprintf(out, "]"); + } + +private: + friend class DFG::StructureAbstractValue; + + Vector m_structures; +}; + +} // namespace JSC + +#endif // StructureSet_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StructureTransitionTable.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StructureTransitionTable.h new file mode 100644 index 000000000..536237a33 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/StructureTransitionTable.h @@ -0,0 +1,172 @@ +/* + * Copyright (C) 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. + * + * 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 StructureTransitionTable_h +#define StructureTransitionTable_h + +#include "UString.h" +#include "WeakGCMap.h" +#include +#include +#include +#include + +namespace JSC { + +class Structure; + +class StructureTransitionTable { + static const intptr_t UsingSingleSlotFlag = 1; + + struct Hash { + typedef std::pair, unsigned> Key; + static unsigned hash(const Key& p) + { + return p.first->existingHash(); + } + + static bool equal(const Key& a, const Key& b) + { + return a == b; + } + + static const bool safeToCompareToEmptyOrDeleted = true; + }; + + struct HashTraits { + typedef WTF::HashTraits > FirstTraits; + typedef WTF::GenericHashTraits SecondTraits; + typedef std::pair TraitType; + + static const bool emptyValueIsZero = FirstTraits::emptyValueIsZero && SecondTraits::emptyValueIsZero; + static TraitType emptyValue() { return std::make_pair(FirstTraits::emptyValue(), SecondTraits::emptyValue()); } + + static const bool needsDestruction = FirstTraits::needsDestruction || SecondTraits::needsDestruction; + + static const int minimumTableSize = FirstTraits::minimumTableSize; + + static void constructDeletedValue(TraitType& slot) { FirstTraits::constructDeletedValue(slot.first); } + static bool isDeletedValue(const TraitType& value) { return FirstTraits::isDeletedValue(value.first); } + }; + + struct WeakGCMapFinalizerCallback { + static void* finalizerContextFor(Hash::Key) + { + return 0; + } + + static inline Hash::Key keyForFinalizer(void* context, Structure* structure) + { + return keyForWeakGCMapFinalizer(context, structure); + } + }; + + typedef WeakGCMap TransitionMap; + + static Hash::Key keyForWeakGCMapFinalizer(void* context, Structure*); + +public: + StructureTransitionTable() + : m_data(UsingSingleSlotFlag) + { + } + + ~StructureTransitionTable() + { + if (!isUsingSingleSlot()) { + delete map(); + return; + } + + HandleSlot slot = this->slot(); + if (!slot) + return; + HandleHeap::heapFor(slot)->deallocate(slot); + } + + inline void add(JSGlobalData&, Structure*); + inline bool contains(StringImpl* rep, unsigned attributes) const; + inline Structure* get(StringImpl* rep, unsigned attributes) const; + +private: + bool isUsingSingleSlot() const + { + return m_data & UsingSingleSlotFlag; + } + + TransitionMap* map() const + { + ASSERT(!isUsingSingleSlot()); + return reinterpret_cast(m_data); + } + + HandleSlot slot() const + { + ASSERT(isUsingSingleSlot()); + return reinterpret_cast(m_data & ~UsingSingleSlotFlag); + } + + void setMap(TransitionMap* map) + { + ASSERT(isUsingSingleSlot()); + + if (HandleSlot slot = this->slot()) + HandleHeap::heapFor(slot)->deallocate(slot); + + // This implicitly clears the flag that indicates we're using a single transition + m_data = reinterpret_cast(map); + + ASSERT(!isUsingSingleSlot()); + } + + Structure* singleTransition() const + { + ASSERT(isUsingSingleSlot()); + if (HandleSlot slot = this->slot()) { + if (*slot) + return reinterpret_cast(slot->asCell()); + } + return 0; + } + + void setSingleTransition(JSGlobalData& globalData, Structure* structure) + { + ASSERT(isUsingSingleSlot()); + HandleSlot slot = this->slot(); + if (!slot) { + slot = globalData.heap.handleHeap()->allocate(); + HandleHeap::heapFor(slot)->makeWeak(slot, 0, 0); + m_data = reinterpret_cast(slot) | UsingSingleSlotFlag; + } + HandleHeap::heapFor(slot)->writeBarrier(slot, reinterpret_cast(structure)); + *slot = reinterpret_cast(structure); + } + + intptr_t m_data; +}; + +} // namespace JSC + +#endif // StructureTransitionTable_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SymbolTable.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SymbolTable.h new file mode 100644 index 000000000..81731222b --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/SymbolTable.h @@ -0,0 +1,133 @@ +/* + * 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. + * 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 SymbolTable_h +#define SymbolTable_h + +#include "JSObject.h" +#include "UString.h" +#include +#include + +namespace JSC { + + static ALWAYS_INLINE int missingSymbolMarker() { return std::numeric_limits::max(); } + + // The bit twiddling in this class assumes that every register index is a + // reasonably small positive or negative number, and therefore has its high + // four bits all set or all unset. + + struct SymbolTableEntry { + SymbolTableEntry() + : m_bits(0) + { + } + + SymbolTableEntry(int index) + { + ASSERT(isValidIndex(index)); + pack(index, false, false); + } + + SymbolTableEntry(int index, unsigned attributes) + { + ASSERT(isValidIndex(index)); + pack(index, attributes & ReadOnly, attributes & DontEnum); + } + + bool isNull() const + { + return !m_bits; + } + + int getIndex() const + { + return m_bits >> FlagBits; + } + + unsigned getAttributes() const + { + unsigned attributes = 0; + if (m_bits & ReadOnlyFlag) + attributes |= ReadOnly; + if (m_bits & DontEnumFlag) + attributes |= DontEnum; + return attributes; + } + + void setAttributes(unsigned attributes) + { + pack(getIndex(), attributes & ReadOnly, attributes & DontEnum); + } + + bool isReadOnly() const + { + return m_bits & ReadOnlyFlag; + } + + private: + static const unsigned ReadOnlyFlag = 0x1; + static const unsigned DontEnumFlag = 0x2; + static const unsigned NotNullFlag = 0x4; + static const unsigned FlagBits = 3; + + void pack(int index, bool readOnly, bool dontEnum) + { + m_bits = (index << FlagBits) | NotNullFlag; + if (readOnly) + m_bits |= ReadOnlyFlag; + if (dontEnum) + m_bits |= DontEnumFlag; + } + + bool isValidIndex(int index) + { + return ((index << FlagBits) >> FlagBits) == index; + } + + int m_bits; + }; + + struct SymbolTableIndexHashTraits : HashTraits { + static const bool emptyValueIsZero = true; + static const bool needsDestruction = false; + }; + + typedef HashMap, SymbolTableEntry, IdentifierRepHash, HashTraits >, SymbolTableIndexHashTraits> SymbolTable; + + class SharedSymbolTable : public SymbolTable, public RefCounted { + WTF_MAKE_FAST_ALLOCATED; + public: + static PassRefPtr create() { return adoptRef(new SharedSymbolTable); } + private: + SharedSymbolTable() { deprecatedTurnOffVerifier(); } + }; + +} // namespace JSC + +#endif // SymbolTable_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/TCSpinLock.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/TCSpinLock.h new file mode 100644 index 000000000..81b7d0cae --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/TCSpinLock.h @@ -0,0 +1,284 @@ +// Copyright (c) 2005, 2006, Google Inc. +// Copyright (c) 2010, Patrick Gansterer +// 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. + +// --- +// Author: Sanjay Ghemawat + +#ifndef TCMALLOC_INTERNAL_SPINLOCK_H__ +#define TCMALLOC_INTERNAL_SPINLOCK_H__ + +#if (CPU(X86) || CPU(X86_64) || CPU(PPC)) && (COMPILER(GCC) || COMPILER(MSVC)) + +#include /* For nanosleep() */ + +#if HAVE(STDINT_H) +#include +#elif HAVE(INTTYPES_H) +#include +#else +#include +#endif + +#if OS(WINDOWS) +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#else +#include /* For sched_yield() */ +#endif + +static void TCMalloc_SlowLock(volatile unsigned int* lockword); + +// The following is a struct so that it can be initialized at compile time +struct TCMalloc_SpinLock { + + inline void Lock() { + int r; +#if COMPILER(GCC) +#if CPU(X86) || CPU(X86_64) + __asm__ __volatile__ + ("xchgl %0, %1" + : "=r"(r), "=m"(lockword_) + : "0"(1), "m"(lockword_) + : "memory"); +#else + volatile unsigned int *lockword_ptr = &lockword_; + __asm__ __volatile__ + ("1: lwarx %0, 0, %1\n\t" + "stwcx. %2, 0, %1\n\t" + "bne- 1b\n\t" + "isync" + : "=&r" (r), "=r" (lockword_ptr) + : "r" (1), "1" (lockword_ptr) + : "memory"); +#endif +#elif COMPILER(MSVC) + __asm { + mov eax, this ; store &lockword_ (which is this+0) in eax + mov ebx, 1 ; store 1 in ebx + xchg [eax], ebx ; exchange lockword_ and 1 + mov r, ebx ; store old value of lockword_ in r + } +#endif + if (r) TCMalloc_SlowLock(&lockword_); + } + + inline void Unlock() { +#if COMPILER(GCC) +#if CPU(X86) || CPU(X86_64) + __asm__ __volatile__ + ("movl $0, %0" + : "=m"(lockword_) + : "m" (lockword_) + : "memory"); +#else + __asm__ __volatile__ + ("isync\n\t" + "eieio\n\t" + "stw %1, %0" +#if OS(DARWIN) || CPU(PPC) + : "=o" (lockword_) +#else + : "=m" (lockword_) +#endif + : "r" (0) + : "memory"); +#endif +#elif COMPILER(MSVC) + __asm { + mov eax, this ; store &lockword_ (which is this+0) in eax + mov [eax], 0 ; set lockword_ to 0 + } +#endif + } + // Report if we think the lock can be held by this thread. + // When the lock is truly held by the invoking thread + // we will always return true. + // Indended to be used as CHECK(lock.IsHeld()); + inline bool IsHeld() const { + return lockword_ != 0; + } + + inline void Init() { lockword_ = 0; } + + volatile unsigned int lockword_; +}; + +#define SPINLOCK_INITIALIZER { 0 } + +static void TCMalloc_SlowLock(volatile unsigned int* lockword) { +// Yield immediately since fast path failed +#if OS(WINDOWS) + Sleep(0); +#else + sched_yield(); +#endif + while (true) { + int r; +#if COMPILER(GCC) +#if CPU(X86) || CPU(X86_64) + __asm__ __volatile__ + ("xchgl %0, %1" + : "=r"(r), "=m"(*lockword) + : "0"(1), "m"(*lockword) + : "memory"); + +#else + int tmp = 1; + __asm__ __volatile__ + ("1: lwarx %0, 0, %1\n\t" + "stwcx. %2, 0, %1\n\t" + "bne- 1b\n\t" + "isync" + : "=&r" (r), "=r" (lockword) + : "r" (tmp), "1" (lockword) + : "memory"); +#endif +#elif COMPILER(MSVC) + __asm { + mov eax, lockword ; assign lockword into eax + mov ebx, 1 ; assign 1 into ebx + xchg [eax], ebx ; exchange *lockword and 1 + mov r, ebx ; store old value of *lockword in r + } +#endif + if (!r) { + return; + } + + // This code was adapted from the ptmalloc2 implementation of + // spinlocks which would sched_yield() upto 50 times before + // sleeping once for a few milliseconds. Mike Burrows suggested + // just doing one sched_yield() outside the loop and always + // sleeping after that. This change helped a great deal on the + // performance of spinlocks under high contention. A test program + // with 10 threads on a dual Xeon (four virtual processors) went + // from taking 30 seconds to 16 seconds. + + // Sleep for a few milliseconds +#if OS(WINDOWS) + Sleep(2); +#else + struct timespec tm; + tm.tv_sec = 0; + tm.tv_nsec = 2000001; + nanosleep(&tm, NULL); +#endif + } +} + +#elif OS(WINDOWS) + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include + +static void TCMalloc_SlowLock(LPLONG lockword); + +// The following is a struct so that it can be initialized at compile time +struct TCMalloc_SpinLock { + + inline void Lock() { + if (InterlockedExchange(&m_lockword, 1)) + TCMalloc_SlowLock(&m_lockword); + } + + inline void Unlock() { + InterlockedExchange(&m_lockword, 0); + } + + inline bool IsHeld() const { + return m_lockword != 0; + } + + inline void Init() { m_lockword = 0; } + + LONG m_lockword; +}; + +#define SPINLOCK_INITIALIZER { 0 } + +static void TCMalloc_SlowLock(LPLONG lockword) { + Sleep(0); // Yield immediately since fast path failed + while (InterlockedExchange(lockword, 1)) + Sleep(2); +} + +#else + +#include + +// Portable version +struct TCMalloc_SpinLock { + pthread_mutex_t private_lock_; + + inline void Init() { + if (pthread_mutex_init(&private_lock_, NULL) != 0) CRASH(); + } + inline void Finalize() { + if (pthread_mutex_destroy(&private_lock_) != 0) CRASH(); + } + inline void Lock() { + if (pthread_mutex_lock(&private_lock_) != 0) CRASH(); + } + inline void Unlock() { + if (pthread_mutex_unlock(&private_lock_) != 0) CRASH(); + } + bool IsHeld() { + if (pthread_mutex_trylock(&private_lock_)) + return true; + + Unlock(); + return false; + } +}; + +#define SPINLOCK_INITIALIZER { PTHREAD_MUTEX_INITIALIZER } + +#endif + +// Corresponding locker object that arranges to acquire a spinlock for +// the duration of a C++ scope. +class TCMalloc_SpinLockHolder { + private: + TCMalloc_SpinLock* lock_; + public: + inline explicit TCMalloc_SpinLockHolder(TCMalloc_SpinLock* l) + : lock_(l) { l->Lock(); } + inline ~TCMalloc_SpinLockHolder() { lock_->Unlock(); } +}; + +// Short-hands for convenient use by tcmalloc.cc +typedef TCMalloc_SpinLock SpinLock; +typedef TCMalloc_SpinLockHolder SpinLockHolder; + +#endif // TCMALLOC_INTERNAL_SPINLOCK_H__ diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/TemporaryChange.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/TemporaryChange.h new file mode 100644 index 000000000..fe374b194 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/TemporaryChange.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2011 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: + * + * 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 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 TemporaryChange_h +#define TemporaryChange_h + +#include "Noncopyable.h" + +namespace WTF { + +// TemporaryChange<> is useful for setting a variable to a new value only within a +// particular scope. An TemporaryChange<> object changes a variable to its original +// value upon destruction, making it an alternative to writing "var = false;" +// or "var = oldVal;" at all of a block's exit points. +// +// This should be obvious, but note that an TemporaryChange<> instance should have a +// shorter lifetime than its scopedVariable, to prevent invalid memory writes +// when the TemporaryChange<> object is destroyed. + +template +class TemporaryChange { + WTF_MAKE_NONCOPYABLE(TemporaryChange); +public: + TemporaryChange(T& scopedVariable, T newValue) + : m_scopedVariable(scopedVariable) + , m_originalValue(scopedVariable) + { + m_scopedVariable = newValue; + } + + ~TemporaryChange() + { + m_scopedVariable = m_originalValue; + } + + +private: + T& m_scopedVariable; + T m_originalValue; +}; + +} + +using WTF::TemporaryChange; + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Terminator.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Terminator.h new file mode 100644 index 000000000..6b0f2366f --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Terminator.h @@ -0,0 +1,47 @@ +/* + * 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: + * + * 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 Google Inc. ("Google") 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 Terminator_h +#define Terminator_h + +namespace JSC { + +class Terminator { +public: + Terminator() : m_shouldTerminate(false) { } + + void terminateSoon() { m_shouldTerminate = true; } + bool shouldTerminate() const { return m_shouldTerminate; } + +private: + bool m_shouldTerminate; +}; + +} // namespace JSC + +#endif // Terminator_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/TextPosition.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/TextPosition.h new file mode 100644 index 000000000..be49c157a --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/TextPosition.h @@ -0,0 +1,85 @@ +/* + * 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: + * 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 INC. 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 INC. 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 TextPosition_h +#define TextPosition_h + +#include + +namespace WTF { + +// An abstract number of element in a sequence. The sequence has a first element. +// This type should be used instead of integer because 2 contradicting traditions can +// call a first element '0' or '1' which makes integer type ambiguous. +class OrdinalNumber { +public: + static OrdinalNumber fromZeroBasedInt(int zeroBasedInt) { return OrdinalNumber(zeroBasedInt); } + static OrdinalNumber fromOneBasedInt(int oneBasedInt) { return OrdinalNumber(oneBasedInt - 1); } + OrdinalNumber() : m_zeroBasedValue(0) { } + + int zeroBasedInt() const { return m_zeroBasedValue; } + int oneBasedInt() const { return m_zeroBasedValue + 1; } + + bool operator==(OrdinalNumber other) { return m_zeroBasedValue == other.m_zeroBasedValue; } + bool operator!=(OrdinalNumber other) { return !((*this) == other); } + + static OrdinalNumber first() { return OrdinalNumber(0); } + static OrdinalNumber beforeFirst() { return OrdinalNumber(-1); } + +private: + OrdinalNumber(int zeroBasedInt) : m_zeroBasedValue(zeroBasedInt) { } + int m_zeroBasedValue; +}; + + +// TextPosition structure specifies coordinates within an text resource. It is used mostly +// for saving script source position. +class TextPosition { +public: + TextPosition(OrdinalNumber line, OrdinalNumber column) + : m_line(line) + , m_column(column) + { + } + TextPosition() { } + bool operator==(const TextPosition& other) { return m_line == other.m_line && m_column == other.m_column; } + bool operator!=(const TextPosition& other) { return !((*this) == other); } + + // A 'minimum' value of position, used as a default value. + static TextPosition minimumPosition() { return TextPosition(OrdinalNumber::first(), OrdinalNumber::first()); } + + // A value with line value less than a minimum; used as an impossible position. + static TextPosition belowRangePosition() { return TextPosition(OrdinalNumber::beforeFirst(), OrdinalNumber::beforeFirst()); } + + OrdinalNumber m_line; + OrdinalNumber m_column; +}; + +} + +using WTF::OrdinalNumber; + +using WTF::TextPosition; + +#endif // TextPosition_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ThreadRestrictionVerifier.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ThreadRestrictionVerifier.h new file mode 100644 index 000000000..0eeac8e62 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ThreadRestrictionVerifier.h @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2011 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 ThreadRestrictionVerifier_h +#define ThreadRestrictionVerifier_h + +#include +#include +#include + +#if HAVE(DISPATCH_H) +#include +#endif + +#ifndef NDEBUG + +namespace WTF { + +// Verifies that a class is used in a way that respects its lack of thread-safety. +// The default mode is to verify that the object will only be used on a single thread. The +// thread gets captured when setShared(true) is called. +// The mode may be changed by calling useMutexMode (or turnOffVerification). +class ThreadRestrictionVerifier { +public: + ThreadRestrictionVerifier() + : m_mode(SingleThreadVerificationMode) + , m_shared(false) + , m_owningThread(0) + , m_mutex(0) +#if HAVE(DISPATCH_H) + , m_owningQueue(0) +#endif + { + } + +#if HAVE(DISPATCH_H) + ~ThreadRestrictionVerifier() + { + if (m_owningQueue) + dispatch_release(m_owningQueue); + } +#endif + + void setMutexMode(Mutex& mutex) + { + ASSERT(m_mode == SingleThreadVerificationMode || (m_mode == MutexVerificationMode && &mutex == m_mutex)); + m_mode = MutexVerificationMode; + m_mutex = &mutex; + } + +#if HAVE(DISPATCH_H) + void setDispatchQueueMode(dispatch_queue_t queue) + { + ASSERT(m_mode == SingleThreadVerificationMode); + m_mode = SingleDispatchQueueVerificationMode; + m_owningQueue = queue; + dispatch_retain(m_owningQueue); + } +#endif + + void turnOffVerification() + { + ASSERT(m_mode == SingleThreadVerificationMode); + m_mode = NoVerificationMode; + } + + // Indicates that the object may (or may not) be owned by more than one place. + void setShared(bool shared) + { +#if !ASSERT_DISABLED + bool previouslyShared = m_shared; +#endif + m_shared = shared; + + if (!m_shared) + return; + + switch (m_mode) { + case SingleThreadVerificationMode: + ASSERT(shared != previouslyShared); + // Capture the current thread to verify that subsequent ref/deref happen on this thread. + m_owningThread = currentThread(); + return; + +#if HAVE(DISPATCH_H) + case SingleDispatchQueueVerificationMode: +#endif + case MutexVerificationMode: + case NoVerificationMode: + return; + } + ASSERT_NOT_REACHED(); + } + + // Is it OK to use the object at this moment on the current thread? + bool isSafeToUse() const + { + if (!m_shared) + return true; + + switch (m_mode) { + case SingleThreadVerificationMode: + return m_owningThread == currentThread(); + + case MutexVerificationMode: + if (!m_mutex->tryLock()) + return true; + m_mutex->unlock(); + return false; + +#if HAVE(DISPATCH_H) + case SingleDispatchQueueVerificationMode: + return m_owningQueue == dispatch_get_current_queue(); +#endif + + case NoVerificationMode: + return true; + } + ASSERT_NOT_REACHED(); + return true; + } + +private: + enum VerificationMode { + SingleThreadVerificationMode, + MutexVerificationMode, + NoVerificationMode, +#if HAVE(DISPATCH_H) + SingleDispatchQueueVerificationMode, +#endif + }; + + VerificationMode m_mode; + bool m_shared; + + // Used by SingleThreadVerificationMode + ThreadIdentifier m_owningThread; + + // Used by MutexVerificationMode. + Mutex* m_mutex; + +#if HAVE(DISPATCH_H) + // Used by SingleDispatchQueueVerificationMode. + dispatch_queue_t m_owningQueue; +#endif +}; + +} + +#endif +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ThreadSafeRefCounted.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ThreadSafeRefCounted.h new file mode 100644 index 000000000..8497b3bc2 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ThreadSafeRefCounted.h @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2007, 2008, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com) + * + * 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. + * + * + * Note: The implementations of InterlockedIncrement and InterlockedDecrement are based + * on atomic_increment and atomic_exchange_and_add from the Boost C++ Library. The license + * is virtually identical to the Apple license above but is included here for completeness. + * + * Boost Software License - Version 1.0 - August 17th, 2003 + * + * Permission is hereby granted, free of charge, to any person or organization + * obtaining a copy of the software and accompanying documentation covered by + * this license (the "Software") to use, reproduce, display, distribute, + * execute, and transmit the Software, and to prepare derivative works of the + * Software, and to permit third-parties to whom the Software is furnished to + * do so, all subject to the following: + * + * The copyright notices in the Software and this entire statement, including + * the above license grant, this restriction and the following disclaimer, + * must be included in all copies of the Software, in whole or in part, and + * all derivative works of the Software, unless such copies or derivative + * works are solely in the form of machine-executable object code generated by + * a source language processor. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT + * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE + * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef ThreadSafeRefCounted_h +#define ThreadSafeRefCounted_h + +#include "Platform.h" + +#include +#include +#include + +namespace WTF { + +class ThreadSafeRefCountedBase { + WTF_MAKE_NONCOPYABLE(ThreadSafeRefCountedBase); + WTF_MAKE_FAST_ALLOCATED; +public: + ThreadSafeRefCountedBase(int initialRefCount = 1) + : m_refCount(initialRefCount) + { + } + + void ref() + { +#if USE(LOCKFREE_THREADSAFEREFCOUNTED) + atomicIncrement(&m_refCount); +#else + MutexLocker locker(m_mutex); + ++m_refCount; +#endif + } + + bool hasOneRef() + { + return refCount() == 1; + } + + int refCount() const + { +#if !USE(LOCKFREE_THREADSAFEREFCOUNTED) + MutexLocker locker(m_mutex); +#endif + return static_cast(m_refCount); + } + +protected: + // Returns whether the pointer should be freed or not. + bool derefBase() + { +#if USE(LOCKFREE_THREADSAFEREFCOUNTED) + WTF_ANNOTATE_HAPPENS_BEFORE(&m_refCount); + if (atomicDecrement(&m_refCount) <= 0) { + WTF_ANNOTATE_HAPPENS_AFTER(&m_refCount); + return true; + } +#else + int refCount; + { + MutexLocker locker(m_mutex); + --m_refCount; + refCount = m_refCount; + } + if (refCount <= 0) + return true; +#endif + return false; + } + +private: + int m_refCount; +#if !USE(LOCKFREE_THREADSAFEREFCOUNTED) + mutable Mutex m_mutex; +#endif +}; + +template class ThreadSafeRefCounted : public ThreadSafeRefCountedBase { +public: + void deref() + { + if (derefBase()) + delete static_cast(this); + } + +protected: + ThreadSafeRefCounted() + { + } +}; + +} // namespace WTF + +using WTF::ThreadSafeRefCounted; + +#endif // ThreadSafeRefCounted_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ThreadSpecific.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ThreadSpecific.h new file mode 100644 index 000000000..7c75a83ee --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ThreadSpecific.h @@ -0,0 +1,276 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2009 Jian Li + * + * 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. + */ + +/* Thread local storage is implemented by using either pthread API or Windows + * native API. There is subtle semantic discrepancy for the cleanup function + * implementation as noted below: + * @ In pthread implementation, the destructor function will be called + * repeatedly if there is still non-NULL value associated with the function. + * @ In Windows native implementation, the destructor function will be called + * only once. + * This semantic discrepancy does not impose any problem because nowhere in + * WebKit the repeated call bahavior is utilized. + */ + +#ifndef WTF_ThreadSpecific_h +#define WTF_ThreadSpecific_h + +#include +#include + +#if USE(PTHREADS) +#include +#elif PLATFORM(GTK) +#include +#elif OS(WINDOWS) +#include +#endif + +namespace WTF { + +#if OS(WINDOWS) +// ThreadSpecificThreadExit should be called each time when a thread is detached. +// This is done automatically for threads created with WTF::createThread. +void ThreadSpecificThreadExit(); +#endif + +template class ThreadSpecific { + WTF_MAKE_NONCOPYABLE(ThreadSpecific); +public: + ThreadSpecific(); + bool isSet(); // Useful as a fast check to see if this thread has set this value. + T* operator->(); + operator T*(); + T& operator*(); + +private: +#if OS(WINDOWS) + friend void ThreadSpecificThreadExit(); +#endif + + // Not implemented. It's technically possible to destroy a thread specific key, but one would need + // to make sure that all values have been destroyed already (usually, that all threads that used it + // have exited). It's unlikely that any user of this call will be in that situation - and having + // a destructor defined can be confusing, given that it has such strong pre-requisites to work correctly. + ~ThreadSpecific(); + + T* get(); + void set(T*); + void static destroy(void* ptr); + +#if USE(PTHREADS) || PLATFORM(QT) || PLATFORM(GTK) || OS(WINDOWS) + struct Data { + WTF_MAKE_NONCOPYABLE(Data); + public: + Data(T* value, ThreadSpecific* owner) : value(value), owner(owner) {} + + T* value; + ThreadSpecific* owner; +#if OS(WINDOWS) + void (*destructor)(void*); +#endif + }; +#endif + +#if USE(PTHREADS) + pthread_key_t m_key; +#elif PLATFORM(GTK) + GStaticPrivate m_key; +#elif OS(WINDOWS) + int m_index; +#endif +}; + +#if USE(PTHREADS) +template +inline ThreadSpecific::ThreadSpecific() +{ + int error = pthread_key_create(&m_key, destroy); + if (error) + CRASH(); +} + +template +inline T* ThreadSpecific::get() +{ + Data* data = static_cast(pthread_getspecific(m_key)); + return data ? data->value : 0; +} + +template +inline void ThreadSpecific::set(T* ptr) +{ + ASSERT(!get()); + pthread_setspecific(m_key, new Data(ptr, this)); +} + +#elif PLATFORM(GTK) + +template +inline ThreadSpecific::ThreadSpecific() +{ + g_static_private_init(&m_key); +} + +template +inline T* ThreadSpecific::get() +{ + Data* data = static_cast(g_static_private_get(&m_key)); + return data ? data->value : 0; +} + +template +inline void ThreadSpecific::set(T* ptr) +{ + ASSERT(!get()); + Data* data = new Data(ptr, this); + g_static_private_set(&m_key, data, destroy); +} + +#elif OS(WINDOWS) + +// TLS_OUT_OF_INDEXES is not defined on WinCE. +#ifndef TLS_OUT_OF_INDEXES +#define TLS_OUT_OF_INDEXES 0xffffffff +#endif + +// The maximum number of TLS keys that can be created. For simplification, we assume that: +// 1) Once the instance of ThreadSpecific<> is created, it will not be destructed until the program dies. +// 2) We do not need to hold many instances of ThreadSpecific<> data. This fixed number should be far enough. +const int kMaxTlsKeySize = 256; + +long& tlsKeyCount(); +DWORD* tlsKeys(); + +template +inline ThreadSpecific::ThreadSpecific() + : m_index(-1) +{ + DWORD tlsKey = TlsAlloc(); + if (tlsKey == TLS_OUT_OF_INDEXES) + CRASH(); + + m_index = InterlockedIncrement(&tlsKeyCount()) - 1; + if (m_index >= kMaxTlsKeySize) + CRASH(); + tlsKeys()[m_index] = tlsKey; +} + +template +inline ThreadSpecific::~ThreadSpecific() +{ + // Does not invoke destructor functions. They will be called from ThreadSpecificThreadExit when the thread is detached. + TlsFree(tlsKeys()[m_index]); +} + +template +inline T* ThreadSpecific::get() +{ + Data* data = static_cast(TlsGetValue(tlsKeys()[m_index])); + return data ? data->value : 0; +} + +template +inline void ThreadSpecific::set(T* ptr) +{ + ASSERT(!get()); + Data* data = new Data(ptr, this); + data->destructor = &ThreadSpecific::destroy; + TlsSetValue(tlsKeys()[m_index], data); +} + +#else +#error ThreadSpecific is not implemented for this platform. +#endif + +template +inline void ThreadSpecific::destroy(void* ptr) +{ + Data* data = static_cast(ptr); + +#if USE(PTHREADS) + // We want get() to keep working while data destructor works, because it can be called indirectly by the destructor. + // Some pthreads implementations zero out the pointer before calling destroy(), so we temporarily reset it. + pthread_setspecific(data->owner->m_key, ptr); +#elif PLATFORM(GTK) + // See comment as above + g_static_private_set(&data->owner->m_key, data, 0); +#endif + + data->value->~T(); + fastFree(data->value); + +#if USE(PTHREADS) + pthread_setspecific(data->owner->m_key, 0); +#elif PLATFORM(GTK) + g_static_private_set(&data->owner->m_key, 0, 0); +#elif OS(WINDOWS) + TlsSetValue(tlsKeys()[data->owner->m_index], 0); +#else +#error ThreadSpecific is not implemented for this platform. +#endif + + delete data; +} + +template +inline bool ThreadSpecific::isSet() +{ + return !!get(); +} + +template +inline ThreadSpecific::operator T*() +{ + T* ptr = static_cast(get()); + if (!ptr) { + // Set up thread-specific value's memory pointer before invoking constructor, in case any function it calls + // needs to access the value, to avoid recursion. + ptr = static_cast(fastZeroedMalloc(sizeof(T))); + set(ptr); + new (NotNull, ptr) T; + } + return ptr; +} + +template +inline T* ThreadSpecific::operator->() +{ + return operator T*(); +} + +template +inline T& ThreadSpecific::operator*() +{ + return *operator T*(); +} + +} + +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Threading.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Threading.h new file mode 100644 index 000000000..1dee5da1c --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Threading.h @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2007, 2008, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com) + * + * 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. + * + * + * Note: The implementations of InterlockedIncrement and InterlockedDecrement are based + * on atomic_increment and atomic_exchange_and_add from the Boost C++ Library. The license + * is virtually identical to the Apple license above but is included here for completeness. + * + * Boost Software License - Version 1.0 - August 17th, 2003 + * + * Permission is hereby granted, free of charge, to any person or organization + * obtaining a copy of the software and accompanying documentation covered by + * this license (the "Software") to use, reproduce, display, distribute, + * execute, and transmit the Software, and to prepare derivative works of the + * Software, and to permit third-parties to whom the Software is furnished to + * do so, all subject to the following: + * + * The copyright notices in the Software and this entire statement, including + * the above license grant, this restriction and the following disclaimer, + * must be included in all copies of the Software, in whole or in part, and + * all derivative works of the Software, unless such copies or derivative + * works are solely in the form of machine-executable object code generated by + * a source language processor. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT + * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE + * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef Threading_h +#define Threading_h + +#include "Platform.h" + +#include +#include +#include +#include +#include +#include +#include + +// For portability, we do not use thread-safe statics natively supported by some compilers (e.g. gcc). +#define AtomicallyInitializedStatic(T, name) \ + WTF::lockAtomicallyInitializedStaticMutex(); \ + static T name; \ + WTF::unlockAtomicallyInitializedStaticMutex(); + +namespace WTF { + +typedef uint32_t ThreadIdentifier; +typedef void* (*ThreadFunction)(void* argument); + +// 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 it from any thread, the only +// requirement is that the calls are not reentrant. +WTF_EXPORT_PRIVATE void initializeThreading(); + +// Returns 0 if thread creation failed. +// The thread name must be a literal since on some platforms it's passed in to the thread. +WTF_EXPORT_PRIVATE ThreadIdentifier createThread(ThreadFunction, void*, const char* threadName); + +// Internal platform-specific createThread implementation. +ThreadIdentifier createThreadInternal(ThreadFunction, void*, const char* threadName); + +// Called in the thread during initialization. +// Helpful for platforms where the thread name must be set from within the thread. +void initializeCurrentThreadInternal(const char* threadName); + +WTF_EXPORT_PRIVATE ThreadIdentifier currentThread(); +WTF_EXPORT_PRIVATE int waitForThreadCompletion(ThreadIdentifier, void**); +WTF_EXPORT_PRIVATE void detachThread(ThreadIdentifier); + +WTF_EXPORT_PRIVATE void yield(); + +WTF_EXPORT_PRIVATE void lockAtomicallyInitializedStaticMutex(); +WTF_EXPORT_PRIVATE void unlockAtomicallyInitializedStaticMutex(); + +} // namespace WTF + +using WTF::ThreadIdentifier; +using WTF::createThread; +using WTF::currentThread; +using WTF::detachThread; +using WTF::waitForThreadCompletion; +using WTF::yield; + +#endif // Threading_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ThreadingPrimitives.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ThreadingPrimitives.h new file mode 100644 index 000000000..2ac42c8f1 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ThreadingPrimitives.h @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2007, 2008, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com) + * + * 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 ThreadingPrimitives_h +#define ThreadingPrimitives_h + +#include "Platform.h" + +#include +#include +#include +#include + +#if OS(WINDOWS) +#include +#endif + +#if USE(PTHREADS) +#include +#endif + +namespace WTF { + +#if USE(PTHREADS) +typedef pthread_mutex_t PlatformMutex; +#if HAVE(PTHREAD_RWLOCK) +typedef pthread_rwlock_t PlatformReadWriteLock; +#else +typedef void* PlatformReadWriteLock; +#endif +typedef pthread_cond_t PlatformCondition; +#elif OS(WINDOWS) +struct PlatformMutex { + CRITICAL_SECTION m_internalMutex; + size_t m_recursionCount; +}; +typedef void* PlatformReadWriteLock; // FIXME: Implement. +struct PlatformCondition { + size_t m_waitersGone; + size_t m_waitersBlocked; + size_t m_waitersToUnblock; + HANDLE m_blockLock; + HANDLE m_blockQueue; + HANDLE m_unblockLock; + + bool timedWait(PlatformMutex&, DWORD durationMilliseconds); + void signal(bool unblockAll); +}; +#else +typedef void* PlatformMutex; +typedef void* PlatformReadWriteLock; +typedef void* PlatformCondition; +#endif + +class Mutex { + WTF_MAKE_NONCOPYABLE(Mutex); WTF_MAKE_FAST_ALLOCATED; +public: + WTF_EXPORT_PRIVATE Mutex(); + WTF_EXPORT_PRIVATE ~Mutex(); + + WTF_EXPORT_PRIVATE void lock(); + WTF_EXPORT_PRIVATE bool tryLock(); + WTF_EXPORT_PRIVATE void unlock(); + +public: + PlatformMutex& impl() { return m_mutex; } +private: + PlatformMutex m_mutex; +}; + +typedef Locker MutexLocker; + +class ReadWriteLock { + WTF_MAKE_NONCOPYABLE(ReadWriteLock); +public: + ReadWriteLock(); + ~ReadWriteLock(); + + void readLock(); + bool tryReadLock(); + + void writeLock(); + bool tryWriteLock(); + + void unlock(); + +private: + PlatformReadWriteLock m_readWriteLock; +}; + +class ThreadCondition { + WTF_MAKE_NONCOPYABLE(ThreadCondition); +public: + WTF_EXPORT_PRIVATE ThreadCondition(); + WTF_EXPORT_PRIVATE ~ThreadCondition(); + + WTF_EXPORT_PRIVATE void wait(Mutex& mutex); + // Returns true if the condition was signaled before absoluteTime, false if the absoluteTime was reached or is in the past. + // The absoluteTime is in seconds, starting on January 1, 1970. The time is assumed to use the same time zone as WTF::currentTime(). + WTF_EXPORT_PRIVATE bool timedWait(Mutex&, double absoluteTime); + WTF_EXPORT_PRIVATE void signal(); + WTF_EXPORT_PRIVATE void broadcast(); + +private: + PlatformCondition m_condition; +}; + +#if OS(WINDOWS) +// The absoluteTime is in seconds, starting on January 1, 1970. The time is assumed to use the same time zone as WTF::currentTime(). +// Returns an interval in milliseconds suitable for passing to one of the Win32 wait functions (e.g., ::WaitForSingleObject). +DWORD absoluteTimeToWaitTimeoutInterval(double absoluteTime); +#endif + +} // namespace WTF + +using WTF::Mutex; +using WTF::MutexLocker; +using WTF::ThreadCondition; + +#if OS(WINDOWS) +using WTF::absoluteTimeToWaitTimeoutInterval; +#endif + +#endif // ThreadingPrimitives_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ThunkGenerators.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ThunkGenerators.h new file mode 100644 index 000000000..b251f6be8 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ThunkGenerators.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2010 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 INC. 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 INC. 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 ThunkGenerators_h +#define ThunkGenerators_h + +#if ENABLE(JIT) +namespace JSC { + class ExecutablePool; + class JSGlobalData; + class NativeExecutable; + class MacroAssemblerCodeRef; + + typedef MacroAssemblerCodeRef (*ThunkGenerator)(JSGlobalData*); + MacroAssemblerCodeRef charCodeAtThunkGenerator(JSGlobalData*); + MacroAssemblerCodeRef charAtThunkGenerator(JSGlobalData*); + MacroAssemblerCodeRef fromCharCodeThunkGenerator(JSGlobalData*); + MacroAssemblerCodeRef absThunkGenerator(JSGlobalData*); + MacroAssemblerCodeRef ceilThunkGenerator(JSGlobalData*); + MacroAssemblerCodeRef expThunkGenerator(JSGlobalData*); + MacroAssemblerCodeRef floorThunkGenerator(JSGlobalData*); + MacroAssemblerCodeRef logThunkGenerator(JSGlobalData*); + MacroAssemblerCodeRef roundThunkGenerator(JSGlobalData*); + MacroAssemblerCodeRef sqrtThunkGenerator(JSGlobalData*); + MacroAssemblerCodeRef powThunkGenerator(JSGlobalData*); +} +#endif + +#endif // ThunkGenerator_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/TimeoutChecker.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/TimeoutChecker.h new file mode 100644 index 000000000..89d6158cc --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/TimeoutChecker.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 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. + * 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 TimeoutChecker_h +#define TimeoutChecker_h + +#include + +namespace JSC { + + class ExecState; + + class TimeoutChecker { + public: + TimeoutChecker(); + + void setTimeoutInterval(unsigned timeoutInterval) { m_timeoutInterval = timeoutInterval; } + unsigned timeoutInterval() const { return m_timeoutInterval; } + + unsigned ticksUntilNextCheck() { return m_ticksUntilNextCheck; } + + void start() + { + if (!m_startCount) + reset(); + ++m_startCount; + } + + void stop() + { + ASSERT(m_startCount); + --m_startCount; + } + + JS_EXPORT_PRIVATE void reset(); + + JS_EXPORT_PRIVATE bool didTimeOut(ExecState*); + + private: + unsigned m_timeoutInterval; + unsigned m_timeAtLastCheck; + unsigned m_timeExecuting; + unsigned m_startCount; + unsigned m_ticksUntilNextCheck; + }; + +} // namespace JSC + +#endif // TimeoutChecker_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/TinyBloomFilter.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/TinyBloomFilter.h new file mode 100644 index 000000000..a75ce8ce5 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/TinyBloomFilter.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2011 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 INC. 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 INC. 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 TinyBloomFilter_h +#define TinyBloomFilter_h + +namespace JSC { + +typedef uintptr_t Bits; + +class TinyBloomFilter { +public: + TinyBloomFilter(); + + void add(Bits); + bool ruleOut(Bits) const; // True for 0. + void reset(); + +private: + Bits m_bits; +}; + +inline TinyBloomFilter::TinyBloomFilter() + : m_bits(0) +{ +} + +inline void TinyBloomFilter::add(Bits bits) +{ + m_bits |= bits; +} + +inline bool TinyBloomFilter::ruleOut(Bits bits) const +{ + if (!bits) + return true; + + if ((bits & m_bits) != bits) + return true; + + return false; +} + +inline void TinyBloomFilter::reset() +{ + m_bits = 0; +} + +} // namespace JSC + +#endif // TinyBloomFilter_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/TypeTraits.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/TypeTraits.h new file mode 100644 index 000000000..34e8b79a3 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/TypeTraits.h @@ -0,0 +1,435 @@ + /* + * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2009, 2010 Google Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef TypeTraits_h +#define TypeTraits_h + +#include "Platform.h" + +#if (defined(__GLIBCXX__) && (__GLIBCXX__ >= 20070724) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || (defined(_MSC_VER) && (_MSC_VER >= 1600)) +#include +#if defined(__GXX_EXPERIMENTAL_CXX0X__) +#include +#endif +#endif + +namespace WTF { + + // The following are provided in this file: + // + // Conditional::Type + // + // IsInteger::value + // IsPod::value, see the definition for a note about its limitations + // IsConvertibleToInteger::value + // + // IsArray::value + // + // IsSameType::value + // + // RemovePointer::Type + // RemoveReference::Type + // RemoveConst::Type + // RemoveVolatile::Type + // RemoveConstVolatile::Type + // RemoveExtent::Type + // + // DecayArray::Type + // + // COMPILE_ASSERT's in TypeTraits.cpp illustrate their usage and what they do. + + template struct Conditional { typedef If Type; }; + template struct Conditional { typedef Then Type; }; + + template struct IsInteger { static const bool value = false; }; + template<> struct IsInteger { static const bool value = true; }; + template<> struct IsInteger { static const bool value = true; }; + template<> struct IsInteger { static const bool value = true; }; + template<> struct IsInteger { static const bool value = true; }; + template<> struct IsInteger { static const bool value = true; }; + template<> struct IsInteger { static const bool value = true; }; + template<> struct IsInteger { static const bool value = true; }; + template<> struct IsInteger { static const bool value = true; }; + template<> struct IsInteger { static const bool value = true; }; + template<> struct IsInteger { static const bool value = true; }; + template<> struct IsInteger { static const bool value = true; }; + template<> struct IsInteger { static const bool value = true; }; +#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED) + template<> struct IsInteger { static const bool value = true; }; +#endif + + template struct IsFloatingPoint { static const bool value = false; }; + template<> struct IsFloatingPoint { static const bool value = true; }; + template<> struct IsFloatingPoint { static const bool value = true; }; + template<> struct IsFloatingPoint { static const bool value = true; }; + + template struct IsArithmetic { static const bool value = IsInteger::value || IsFloatingPoint::value; }; + + // IsPod is misnamed as it doesn't cover all plain old data (pod) types. + // Specifically, it doesn't allow for enums or for structs. + template struct IsPod { static const bool value = IsArithmetic::value; }; + template struct IsPod { static const bool value = true; }; + + template class IsConvertibleToInteger { + // Avoid "possible loss of data" warning when using Microsoft's C++ compiler + // by not converting int's to doubles. + template class IsConvertibleToDouble; + template class IsConvertibleToDouble { + public: + static const bool value = false; + }; + + template class IsConvertibleToDouble { + typedef char YesType; + struct NoType { + char padding[8]; + }; + + static YesType floatCheck(long double); + static NoType floatCheck(...); + static T& t; + public: + static const bool value = sizeof(floatCheck(t)) == sizeof(YesType); + }; + + public: + static const bool value = IsInteger::value || IsConvertibleToDouble::value, T>::value; + }; + + + template struct IsArray { + static const bool value = false; + }; + + template struct IsArray { + static const bool value = true; + }; + + template struct IsArray { + static const bool value = true; + }; + + + template struct IsSameType { + static const bool value = false; + }; + + template struct IsSameType { + static const bool value = true; + }; + + template class IsSubclass { + typedef char YesType; + struct NoType { + char padding[8]; + }; + + static YesType subclassCheck(U*); + static NoType subclassCheck(...); + static T* t; + public: + static const bool value = sizeof(subclassCheck(t)) == sizeof(YesType); + }; + + template class U> class IsSubclassOfTemplate { + typedef char YesType; + struct NoType { + char padding[8]; + }; + + template static YesType subclassCheck(U*); + static NoType subclassCheck(...); + static T* t; + public: + static const bool value = sizeof(subclassCheck(t)) == sizeof(YesType); + }; + + template class OuterTemplate> struct RemoveTemplate { + typedef T Type; + }; + + template class OuterTemplate> struct RemoveTemplate, OuterTemplate> { + typedef T Type; + }; + + template struct RemoveConst { + typedef T Type; + }; + + template struct RemoveConst { + typedef T Type; + }; + + template struct RemoveVolatile { + typedef T Type; + }; + + template struct RemoveVolatile { + typedef T Type; + }; + + template struct RemoveConstVolatile { + typedef typename RemoveVolatile::Type>::Type Type; + }; + + template struct RemovePointer { + typedef T Type; + }; + + template struct RemovePointer { + typedef T Type; + }; + + template struct RemoveReference { + typedef T Type; + }; + + template struct RemoveReference { + typedef T Type; + }; + + template struct RemoveExtent { + typedef T Type; + }; + + template struct RemoveExtent { + typedef T Type; + }; + + template struct RemoveExtent { + typedef T Type; + }; + + template struct DecayArray { + typedef typename RemoveReference::Type U; + public: + typedef typename Conditional< + IsArray::value, + typename RemoveExtent::Type*, + typename RemoveConstVolatile::Type + >::Type Type; + }; + +#if (defined(__GLIBCXX__) && (__GLIBCXX__ >= 20070724) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || (defined(_MSC_VER) && (_MSC_VER >= 1600)) + + // GCC's libstdc++ 20070724 and later supports C++ TR1 type_traits in the std namespace. + // VC10 (VS2010) and later support C++ TR1 type_traits in the std::tr1 namespace. + template struct HasTrivialConstructor : public std::tr1::has_trivial_constructor { }; + template struct HasTrivialDestructor : public std::tr1::has_trivial_destructor { }; + +#else + + // This compiler doesn't provide type traits, so we provide basic HasTrivialConstructor + // and HasTrivialDestructor definitions. The definitions here include most built-in + // scalar types but do not include POD structs and classes. For the intended purposes of + // type_traits this results correct but potentially less efficient code. + template + struct IntegralConstant { + static const T value = v; + typedef T value_type; + typedef IntegralConstant type; + }; + + typedef IntegralConstant true_type; + typedef IntegralConstant false_type; + +#if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__INTEL_COMPILER) + // VC8 (VS2005) and later have built-in compiler support for HasTrivialConstructor / HasTrivialDestructor, + // but for some unexplained reason it doesn't work on built-in types. + template struct HasTrivialConstructor : public IntegralConstant{ }; + template struct HasTrivialDestructor : public IntegralConstant{ }; +#else + template struct HasTrivialConstructor : public false_type{ }; + template struct HasTrivialDestructor : public false_type{ }; +#endif + + template struct HasTrivialConstructor : public true_type{ }; + template struct HasTrivialDestructor : public true_type{ }; + + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + + #if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + template <> struct HasTrivialConstructor : public true_type{ }; + #endif + + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + + #if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + template <> struct HasTrivialDestructor : public true_type{ }; + #endif + +#endif // __GLIBCXX__, etc. + +} // namespace WTF + +#endif // TypeTraits_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/TypedArrayBase.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/TypedArrayBase.h new file mode 100644 index 000000000..dba95d55f --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/TypedArrayBase.h @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * 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: + * 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 TypedArrayBase_h +#define TypedArrayBase_h + +#include "ArrayBuffer.h" +#include "ArrayBufferView.h" + +namespace WTF { + +template +class TypedArrayBase : public ArrayBufferView { + public: + T* data() const { return static_cast(baseAddress()); } + + bool set(TypedArrayBase* array, unsigned offset) + { + return setImpl(array, offset * sizeof(T)); + } + + bool setRange(const T* data, size_t dataLength, unsigned offset) + { + return setRangeImpl(reinterpret_cast(data), dataLength * sizeof(T), offset * sizeof(T)); + } + + bool zeroRange(unsigned offset, size_t length) + { + return zeroRangeImpl(offset * sizeof(T), length * sizeof(T)); + } + + // Overridden from ArrayBufferView. This must be public because of + // rules about inheritance of members in template classes, and + // because it is accessed via pointers to subclasses. + unsigned length() const + { + return m_length; + } + + virtual unsigned byteLength() const + { + return m_length * sizeof(T); + } + +protected: + TypedArrayBase(PassRefPtr buffer, unsigned byteOffset, unsigned length) + : ArrayBufferView(buffer, byteOffset) + , m_length(length) + { + } + + template + static PassRefPtr create(unsigned length) + { + RefPtr buffer = ArrayBuffer::create(length, sizeof(T)); + if (!buffer.get()) + return 0; + return create(buffer, 0, length); + } + + template + static PassRefPtr create(const T* array, unsigned length) + { + RefPtr a = create(length); + if (a) + for (unsigned i = 0; i < length; ++i) + a->set(i, array[i]); + return a; + } + + template + static PassRefPtr create(PassRefPtr buffer, + unsigned byteOffset, + unsigned length) + { + RefPtr buf(buffer); + if (!verifySubRange(buf, byteOffset, length)) + return 0; + + return adoptRef(new Subclass(buf, byteOffset, length)); + } + + template + PassRefPtr subarrayImpl(int start, int end) const + { + unsigned offset, length; + calculateOffsetAndLength(start, end, m_length, &offset, &length); + clampOffsetAndNumElements(buffer(), m_byteOffset, &offset, &length); + return create(buffer(), offset, length); + } + + virtual void neuter() + { + ArrayBufferView::neuter(); + m_length = 0; + } + + // We do not want to have to access this via a virtual function in subclasses, + // which is why it is protected rather than private. + unsigned m_length; +}; + +} // namespace WTF + +using WTF::TypedArrayBase; + +#endif // TypedArrayBase_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/UString.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/UString.h new file mode 100644 index 000000000..c11c5676a --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/UString.h @@ -0,0 +1,288 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef UString_h +#define UString_h + +#include + +namespace JSC { + +class UString { +public: + // Construct a null string, distinguishable from an empty string. + UString() { } + + // Construct a string with UTF-16 data. + JS_EXPORT_PRIVATE UString(const UChar* characters, unsigned length); + + // Construct a string with UTF-16 data, from a null-terminated source. + JS_EXPORT_PRIVATE UString(const UChar*); + + // Construct a string with latin1 data. + UString(const LChar* characters, unsigned length); + JS_EXPORT_PRIVATE UString(const char* characters, unsigned length); + + // Construct a string with latin1 data, from a null-terminated source. + UString(const LChar* characters); + JS_EXPORT_PRIVATE UString(const char* characters); + + // Construct a string referencing an existing StringImpl. + UString(StringImpl* impl) : m_impl(impl) { } + UString(PassRefPtr impl) : m_impl(impl) { } + UString(RefPtr impl) : m_impl(impl) { } + + // Inline the destructor. + ALWAYS_INLINE ~UString() { } + + void swap(UString& o) { m_impl.swap(o.m_impl); } + + template + static UString adopt(Vector& vector) { return StringImpl::adopt(vector); } + + bool isNull() const { return !m_impl; } + bool isEmpty() const { return !m_impl || !m_impl->length(); } + + StringImpl* impl() const { return m_impl.get(); } + + unsigned length() const + { + if (!m_impl) + return 0; + return m_impl->length(); + } + + const UChar* characters() const + { + if (!m_impl) + return 0; + return m_impl->characters(); + } + + const LChar* characters8() const + { + if (!m_impl) + return 0; + ASSERT(m_impl->is8Bit()); + return m_impl->characters8(); + } + + const UChar* characters16() const + { + if (!m_impl) + return 0; + ASSERT(!m_impl->is8Bit()); + return m_impl->characters16(); + } + + template + inline const CharType* getCharacters() const; + + bool is8Bit() const { return m_impl->is8Bit(); } + + JS_EXPORT_PRIVATE CString ascii() const; + CString latin1() const; + JS_EXPORT_PRIVATE CString utf8(bool strict = false) const; + + UChar operator[](unsigned index) const + { + if (!m_impl || index >= m_impl->length()) + return 0; + if (is8Bit()) + return m_impl->characters8()[index]; + return m_impl->characters16()[index]; + } + + JS_EXPORT_PRIVATE static UString number(int); + JS_EXPORT_PRIVATE static UString number(unsigned); + JS_EXPORT_PRIVATE static UString number(long); + static UString number(long long); + JS_EXPORT_PRIVATE static UString number(double); + + // Find a single character or string, also with match function & latin1 forms. + size_t find(UChar c, unsigned start = 0) const + { return m_impl ? m_impl->find(c, start) : notFound; } + size_t find(const UString& str, unsigned start = 0) const + { return m_impl ? m_impl->find(str.impl(), start) : notFound; } + size_t find(const LChar* str, unsigned start = 0) const + { return m_impl ? m_impl->find(str, start) : notFound; } + + // Find the last instance of a single character or string. + size_t reverseFind(UChar c, unsigned start = UINT_MAX) const + { return m_impl ? m_impl->reverseFind(c, start) : notFound; } + size_t reverseFind(const UString& str, unsigned start = UINT_MAX) const + { return m_impl ? m_impl->reverseFind(str.impl(), start) : notFound; } + + JS_EXPORT_PRIVATE UString substringSharingImpl(unsigned pos, unsigned len = UINT_MAX) const; + +private: + RefPtr m_impl; +}; + +template<> +inline const LChar* UString::getCharacters() const +{ + ASSERT(is8Bit()); + return characters8(); +} + +template<> +inline const UChar* UString::getCharacters() const +{ + ASSERT(!is8Bit()); + return characters16(); +} + +NEVER_INLINE bool equalSlowCase(const UString& s1, const UString& s2); + +ALWAYS_INLINE bool operator==(const UString& s1, const UString& s2) +{ + StringImpl* rep1 = s1.impl(); + StringImpl* rep2 = s2.impl(); + + if (rep1 == rep2) // If they're the same rep, they're equal. + return true; + + unsigned size1 = 0; + unsigned size2 = 0; + + if (rep1) + size1 = rep1->length(); + + if (rep2) + size2 = rep2->length(); + + if (size1 != size2) // If the lengths are not the same, we're done. + return false; + + if (!size1) + return true; + + if (size1 == 1) + return (*rep1)[0u] == (*rep2)[0u]; + + return equalSlowCase(s1, s2); +} + + +inline bool operator!=(const UString& s1, const UString& s2) +{ + return !JSC::operator==(s1, s2); +} + +JS_EXPORT_PRIVATE bool operator<(const UString& s1, const UString& s2); +JS_EXPORT_PRIVATE bool operator>(const UString& s1, const UString& s2); + +JS_EXPORT_PRIVATE bool operator==(const UString& s1, const char* s2); + +inline bool operator!=(const UString& s1, const char* s2) +{ + return !JSC::operator==(s1, s2); +} + +inline bool operator==(const char *s1, const UString& s2) +{ + return operator==(s2, s1); +} + +inline bool operator!=(const char *s1, const UString& s2) +{ + return !JSC::operator==(s1, s2); +} + +inline int codePointCompare(const UString& s1, const UString& s2) +{ + return codePointCompare(s1.impl(), s2.impl()); +} + +struct UStringHash { + static unsigned hash(StringImpl* key) { return key->hash(); } + static bool equal(const StringImpl* a, const StringImpl* b) + { + if (a == b) + return true; + if (!a || !b) + return false; + + unsigned aLength = a->length(); + unsigned bLength = b->length(); + if (aLength != bLength) + return false; + + // FIXME: perhaps we should have a more abstract macro that indicates when + // going 4 bytes at a time is unsafe +#if CPU(ARM) || CPU(SH4) || CPU(MIPS) || CPU(SPARC) + const UChar* aChars = a->characters(); + const UChar* bChars = b->characters(); + for (unsigned i = 0; i != aLength; ++i) { + if (*aChars++ != *bChars++) + return false; + } + return true; +#else + /* Do it 4-bytes-at-a-time on architectures where it's safe */ + const uint32_t* aChars = reinterpret_cast(a->characters()); + const uint32_t* bChars = reinterpret_cast(b->characters()); + + unsigned halfLength = aLength >> 1; + for (unsigned i = 0; i != halfLength; ++i) + if (*aChars++ != *bChars++) + return false; + + if (aLength & 1 && *reinterpret_cast(aChars) != *reinterpret_cast(bChars)) + return false; + + return true; +#endif + } + + static unsigned hash(const RefPtr& key) { return key->hash(); } + static bool equal(const RefPtr& a, const RefPtr& b) + { + return equal(a.get(), b.get()); + } + + static unsigned hash(const UString& key) { return key.impl()->hash(); } + static bool equal(const UString& a, const UString& b) + { + return equal(a.impl(), b.impl()); + } + + static const bool safeToCompareToEmptyOrDeleted = false; +}; + +} // namespace JSC + +namespace WTF { + +// UStringHash is the default hash for UString +template struct DefaultHash; +template<> struct DefaultHash { + typedef JSC::UStringHash Hash; +}; + +template <> struct VectorTraits : SimpleClassVectorTraits { }; + +} // namespace WTF + +#endif + diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/UStringBuilder.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/UStringBuilder.h new file mode 100644 index 000000000..31ccf382a --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/UStringBuilder.h @@ -0,0 +1,43 @@ +/* + * 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 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 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 UStringBuilder_h +#define UStringBuilder_h + +#include + +namespace JSC { + +class UStringBuilder : public StringBuilder { +public: + using StringBuilder::append; + void append(const UString& str) { append(String(str.impl())); } + + UString toUString() { return toString().impl(); } +}; + +} // namespace JSC + +#endif // UStringBuilder_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/UTF8.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/UTF8.h new file mode 100644 index 000000000..bc2497b72 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/UTF8.h @@ -0,0 +1,84 @@ +/* + * 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. + */ + +#ifndef WTF_UTF8_h +#define WTF_UTF8_h + +#include "Unicode.h" + +namespace WTF { +namespace Unicode { + + // Given a first byte, gives the length of the UTF-8 sequence it begins. + // Returns 0 for bytes that are not legal starts of UTF-8 sequences. + // Only allows sequences of up to 4 bytes, since that works for all Unicode characters (U-00000000 to U-0010FFFF). + int UTF8SequenceLength(char); + + // Takes a null-terminated C-style string with a UTF-8 sequence in it and converts it to a character. + // Only allows Unicode characters (U-00000000 to U-0010FFFF). + // Returns -1 if the sequence is not valid (including presence of extra bytes). + int decodeUTF8Sequence(const char*); + + typedef enum { + conversionOK, // conversion successful + sourceExhausted, // partial character in source, but hit end + targetExhausted, // insuff. room in target for conversion + sourceIllegal // source sequence is illegal/malformed + } ConversionResult; + + // These conversion functions take a "strict" argument. When this + // flag is set to strict, both irregular sequences and isolated surrogates + // will cause an error. When the flag is set to lenient, both irregular + // sequences and isolated surrogates are converted. + // + // Whether the flag is strict or lenient, all illegal sequences will cause + // an error return. This includes sequences such as: , , + // or in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code + // must check for illegal sequences. + // + // When the flag is set to lenient, characters over 0x10FFFF are converted + // to the replacement character; otherwise (when the flag is set to strict) + // they constitute an error. + + WTF_EXPORT_PRIVATE ConversionResult convertUTF8ToUTF16( + const char** sourceStart, const char* sourceEnd, + UChar** targetStart, UChar* targetEnd, bool strict = true); + + ConversionResult convertLatin1ToUTF8( + const LChar** sourceStart, const LChar* sourceEnd, + char** targetStart, char* targetEnd); + + WTF_EXPORT_PRIVATE ConversionResult convertUTF16ToUTF8( + const UChar** sourceStart, const UChar* sourceEnd, + char** targetStart, char* targetEnd, bool strict = true); + + unsigned calculateStringHashAndLengthFromUTF8(const char* data, const char* dataEnd, unsigned& dataLength, unsigned& utf16Length); + + bool equalUTF16WithUTF8(const UChar* a, const UChar* aEnd, const char* b, const char* bEnd); + +} // namespace Unicode +} // namespace WTF + +#endif // WTF_UTF8_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Uint16Array.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Uint16Array.h new file mode 100644 index 000000000..2d0765051 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Uint16Array.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * 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: + * 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 Uint16Array_h +#define Uint16Array_h + +#include "IntegralTypedArrayBase.h" + +namespace WTF { + +class ArrayBuffer; + +class Uint16Array : public IntegralTypedArrayBase { +public: + static inline PassRefPtr create(unsigned length); + static inline PassRefPtr create(unsigned short* array, unsigned length); + static inline PassRefPtr create(PassRefPtr, unsigned byteOffset, unsigned length); + + // Can’t use "using" here due to a bug in the RVCT compiler. + bool set(TypedArrayBase* array, unsigned offset) { return TypedArrayBase::set(array, offset); } + void set(unsigned index, double value) { IntegralTypedArrayBase::set(index, value); } + + inline PassRefPtr subarray(int start) const; + inline PassRefPtr subarray(int start, int end) const; + +private: + inline Uint16Array(PassRefPtr, + unsigned byteOffset, + unsigned length); + // Make constructor visible to superclass. + friend class TypedArrayBase; + + // Overridden from ArrayBufferView. + virtual bool isUnsignedShortArray() const { return true; } +}; + +PassRefPtr Uint16Array::create(unsigned length) +{ + return TypedArrayBase::create(length); +} + +PassRefPtr Uint16Array::create(unsigned short* array, unsigned length) +{ + return TypedArrayBase::create(array, length); +} + +PassRefPtr Uint16Array::create(PassRefPtr buffer, unsigned byteOffset, unsigned length) +{ + return TypedArrayBase::create(buffer, byteOffset, length); +} + +Uint16Array::Uint16Array(PassRefPtr buffer, unsigned byteOffset, unsigned length) + : IntegralTypedArrayBase(buffer, byteOffset, length) +{ +} + +PassRefPtr Uint16Array::subarray(int start) const +{ + return subarray(start, length()); +} + +PassRefPtr Uint16Array::subarray(int start, int end) const +{ + return subarrayImpl(start, end); +} + +} // namespace WTF + +using WTF::Uint16Array; + +#endif // Uint16Array_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Uint32Array.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Uint32Array.h new file mode 100644 index 000000000..3765f8077 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Uint32Array.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * 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: + * 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 Uint32Array_h +#define Uint32Array_h + +#include "IntegralTypedArrayBase.h" + +namespace WTF { + +class ArrayBuffer; + +class Uint32Array : public IntegralTypedArrayBase { +public: + static inline PassRefPtr create(unsigned length); + static inline PassRefPtr create(unsigned int* array, unsigned length); + static inline PassRefPtr create(PassRefPtr, unsigned byteOffset, unsigned length); + + // Can’t use "using" here due to a bug in the RVCT compiler. + bool set(TypedArrayBase* array, unsigned offset) { return TypedArrayBase::set(array, offset); } + void set(unsigned index, double value) { IntegralTypedArrayBase::set(index, value); } + + inline PassRefPtr subarray(int start) const; + inline PassRefPtr subarray(int start, int end) const; + +private: + inline Uint32Array(PassRefPtr, + unsigned byteOffset, + unsigned length); + // Make constructor visible to superclass. + friend class TypedArrayBase; + + // Overridden from ArrayBufferView. + virtual bool isUnsignedIntArray() const { return true; } +}; + +PassRefPtr Uint32Array::create(unsigned length) +{ + return TypedArrayBase::create(length); +} + +PassRefPtr Uint32Array::create(unsigned int* array, unsigned length) +{ + return TypedArrayBase::create(array, length); +} + +PassRefPtr Uint32Array::create(PassRefPtr buffer, unsigned byteOffset, unsigned length) +{ + return TypedArrayBase::create(buffer, byteOffset, length); +} + +Uint32Array::Uint32Array(PassRefPtr buffer, unsigned byteOffset, unsigned length) + : IntegralTypedArrayBase(buffer, byteOffset, length) +{ +} + +PassRefPtr Uint32Array::subarray(int start) const +{ + return subarray(start, length()); +} + +PassRefPtr Uint32Array::subarray(int start, int end) const +{ + return subarrayImpl(start, end); +} + +} // namespace WTF + +using WTF::Uint32Array; + +#endif // Uint32Array_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Uint8Array.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Uint8Array.h new file mode 100644 index 000000000..a0959706c --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Uint8Array.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * 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: + * 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 Uint8Array_h +#define Uint8Array_h + +#include "IntegralTypedArrayBase.h" + +namespace WTF { + +class ArrayBuffer; + +class Uint8Array : public IntegralTypedArrayBase { +public: + static inline PassRefPtr create(unsigned length); + static inline PassRefPtr create(unsigned char* array, unsigned length); + static inline PassRefPtr create(PassRefPtr, unsigned byteOffset, unsigned length); + + // Can’t use "using" here due to a bug in the RVCT compiler. + bool set(TypedArrayBase* array, unsigned offset) { return TypedArrayBase::set(array, offset); } + void set(unsigned index, double value) { IntegralTypedArrayBase::set(index, value); } + + inline PassRefPtr subarray(int start) const; + inline PassRefPtr subarray(int start, int end) const; + +protected: + inline Uint8Array(PassRefPtr, + unsigned byteOffset, + unsigned length); + // Make constructor visible to superclass. + friend class TypedArrayBase; + + // Overridden from ArrayBufferView. + virtual bool isUnsignedByteArray() const { return true; } +}; + +PassRefPtr Uint8Array::create(unsigned length) +{ + return TypedArrayBase::create(length); +} + +PassRefPtr Uint8Array::create(unsigned char* array, unsigned length) +{ + return TypedArrayBase::create(array, length); +} + +PassRefPtr Uint8Array::create(PassRefPtr buffer, unsigned byteOffset, unsigned length) +{ + return TypedArrayBase::create(buffer, byteOffset, length); +} + +Uint8Array::Uint8Array(PassRefPtr buffer, unsigned byteOffset, unsigned length) +: IntegralTypedArrayBase(buffer, byteOffset, length) +{ +} + +PassRefPtr Uint8Array::subarray(int start) const +{ + return subarray(start, length()); +} + +PassRefPtr Uint8Array::subarray(int start, int end) const +{ + return subarrayImpl(start, end); +} + +} // namespace WTF + +using WTF::Uint8Array; + +#endif // Uint8Array_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Uint8ClampedArray.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Uint8ClampedArray.h new file mode 100644 index 000000000..f1044091b --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Uint8ClampedArray.h @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). + * + * 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 Uint8ClampedArray_h +#define Uint8ClampedArray_h + +#include "Uint8Array.h" + +namespace WTF { + +class Uint8ClampedArray : public Uint8Array { +public: + static inline PassRefPtr create(unsigned length); + static inline PassRefPtr create(unsigned char* array, unsigned length); + static inline PassRefPtr create(PassRefPtr, unsigned byteOffset, unsigned length); + + // Can’t use "using" here due to a bug in the RVCT compiler. + bool set(TypedArrayBase* array, unsigned offset) { return TypedArrayBase::set(array, offset); } + inline void set(unsigned index, double value); + + inline PassRefPtr subarray(int start) const; + inline PassRefPtr subarray(int start, int end) const; + +private: + inline Uint8ClampedArray(PassRefPtr, + unsigned byteOffset, + unsigned length); + // Make constructor visible to superclass. + friend class TypedArrayBase; + + // Overridden from ArrayBufferView. + virtual bool isUnsignedByteClampedArray() const { return true; } +}; + +PassRefPtr Uint8ClampedArray::create(unsigned length) +{ + return TypedArrayBase::create(length); +} + +PassRefPtr Uint8ClampedArray::create(unsigned char* array, unsigned length) +{ + return TypedArrayBase::create(array, length); +} + +PassRefPtr Uint8ClampedArray::create(PassRefPtr buffer, unsigned byteOffset, unsigned length) +{ + return TypedArrayBase::create(buffer, byteOffset, length); +} + +void Uint8ClampedArray::set(unsigned index, double value) +{ + if (index >= m_length) + return; + if (isnan(value) || value < 0) + value = 0; + else if (value > 255) + value = 255; + data()[index] = static_cast(value + 0.5); +} + +Uint8ClampedArray::Uint8ClampedArray(PassRefPtr buffer, unsigned byteOffset, unsigned length) +: Uint8Array(buffer, byteOffset, length) +{ +} + +PassRefPtr Uint8ClampedArray::subarray(int start) const +{ + return subarray(start, length()); +} + +PassRefPtr Uint8ClampedArray::subarray(int start, int end) const +{ + return subarrayImpl(start, end); +} + +} // namespace WTF + +using WTF::Uint8ClampedArray; + +#endif // Uint8ClampedArray_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/UnconditionalFinalizer.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/UnconditionalFinalizer.h new file mode 100644 index 000000000..26029d046 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/UnconditionalFinalizer.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2011 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 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 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 UnconditionalFinalizer_h +#define UnconditionalFinalizer_h + +#include "ListableHandler.h" + +namespace JSC { + +// An unconditional finalizer is useful for caches that you would like to +// destroy on each GC. This is currently used for the bytecode stream +// associated with each CodeBlock. + +class UnconditionalFinalizer : public ListableHandler { +public: + virtual void finalizeUnconditionally() = 0; + +protected: + virtual ~UnconditionalFinalizer() { } +}; + +} + +#endif // UltraWeakFinalizer_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Unicode.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Unicode.h new file mode 100644 index 000000000..cc44476a6 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Unicode.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2006 George Staikos + * Copyright (C) 2006, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2007-2009 Torch Mobile, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WTF_UNICODE_H +#define WTF_UNICODE_H + +#include + +// Define platform neutral 8 bit character type (L is for Latin-1). +typedef unsigned char LChar; + +#if USE(QT4_UNICODE) +#include "qt4/UnicodeQt4.h" +#elif USE(ICU_UNICODE) +#include +#elif USE(GLIB_UNICODE) +#include +#elif USE(WINCE_UNICODE) +#include +#else +#error "Unknown Unicode implementation" +#endif + +COMPILE_ASSERT(sizeof(UChar) == 2, UCharIsTwoBytes); + +#endif // WTF_UNICODE_H diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/UnicodeIcu.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/UnicodeIcu.h new file mode 100644 index 000000000..fe524b2a2 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/UnicodeIcu.h @@ -0,0 +1,236 @@ +/* + * Copyright (C) 2006 George Staikos + * Copyright (C) 2006 Alexey Proskuryakov + * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WTF_UNICODE_ICU_H +#define WTF_UNICODE_ICU_H + +#include +#include +#include +#include +#include + +namespace WTF { +namespace Unicode { + +enum Direction { + LeftToRight = U_LEFT_TO_RIGHT, + RightToLeft = U_RIGHT_TO_LEFT, + EuropeanNumber = U_EUROPEAN_NUMBER, + EuropeanNumberSeparator = U_EUROPEAN_NUMBER_SEPARATOR, + EuropeanNumberTerminator = U_EUROPEAN_NUMBER_TERMINATOR, + ArabicNumber = U_ARABIC_NUMBER, + CommonNumberSeparator = U_COMMON_NUMBER_SEPARATOR, + BlockSeparator = U_BLOCK_SEPARATOR, + SegmentSeparator = U_SEGMENT_SEPARATOR, + WhiteSpaceNeutral = U_WHITE_SPACE_NEUTRAL, + OtherNeutral = U_OTHER_NEUTRAL, + LeftToRightEmbedding = U_LEFT_TO_RIGHT_EMBEDDING, + LeftToRightOverride = U_LEFT_TO_RIGHT_OVERRIDE, + RightToLeftArabic = U_RIGHT_TO_LEFT_ARABIC, + RightToLeftEmbedding = U_RIGHT_TO_LEFT_EMBEDDING, + RightToLeftOverride = U_RIGHT_TO_LEFT_OVERRIDE, + PopDirectionalFormat = U_POP_DIRECTIONAL_FORMAT, + NonSpacingMark = U_DIR_NON_SPACING_MARK, + BoundaryNeutral = U_BOUNDARY_NEUTRAL +}; + +enum DecompositionType { + DecompositionNone = U_DT_NONE, + DecompositionCanonical = U_DT_CANONICAL, + DecompositionCompat = U_DT_COMPAT, + DecompositionCircle = U_DT_CIRCLE, + DecompositionFinal = U_DT_FINAL, + DecompositionFont = U_DT_FONT, + DecompositionFraction = U_DT_FRACTION, + DecompositionInitial = U_DT_INITIAL, + DecompositionIsolated = U_DT_ISOLATED, + DecompositionMedial = U_DT_MEDIAL, + DecompositionNarrow = U_DT_NARROW, + DecompositionNoBreak = U_DT_NOBREAK, + DecompositionSmall = U_DT_SMALL, + DecompositionSquare = U_DT_SQUARE, + DecompositionSub = U_DT_SUB, + DecompositionSuper = U_DT_SUPER, + DecompositionVertical = U_DT_VERTICAL, + DecompositionWide = U_DT_WIDE, +}; + +enum CharCategory { + NoCategory = 0, + Other_NotAssigned = U_MASK(U_GENERAL_OTHER_TYPES), + Letter_Uppercase = U_MASK(U_UPPERCASE_LETTER), + Letter_Lowercase = U_MASK(U_LOWERCASE_LETTER), + Letter_Titlecase = U_MASK(U_TITLECASE_LETTER), + Letter_Modifier = U_MASK(U_MODIFIER_LETTER), + Letter_Other = U_MASK(U_OTHER_LETTER), + + Mark_NonSpacing = U_MASK(U_NON_SPACING_MARK), + Mark_Enclosing = U_MASK(U_ENCLOSING_MARK), + Mark_SpacingCombining = U_MASK(U_COMBINING_SPACING_MARK), + + Number_DecimalDigit = U_MASK(U_DECIMAL_DIGIT_NUMBER), + Number_Letter = U_MASK(U_LETTER_NUMBER), + Number_Other = U_MASK(U_OTHER_NUMBER), + + Separator_Space = U_MASK(U_SPACE_SEPARATOR), + Separator_Line = U_MASK(U_LINE_SEPARATOR), + Separator_Paragraph = U_MASK(U_PARAGRAPH_SEPARATOR), + + Other_Control = U_MASK(U_CONTROL_CHAR), + Other_Format = U_MASK(U_FORMAT_CHAR), + Other_PrivateUse = U_MASK(U_PRIVATE_USE_CHAR), + Other_Surrogate = U_MASK(U_SURROGATE), + + Punctuation_Dash = U_MASK(U_DASH_PUNCTUATION), + Punctuation_Open = U_MASK(U_START_PUNCTUATION), + Punctuation_Close = U_MASK(U_END_PUNCTUATION), + Punctuation_Connector = U_MASK(U_CONNECTOR_PUNCTUATION), + Punctuation_Other = U_MASK(U_OTHER_PUNCTUATION), + + Symbol_Math = U_MASK(U_MATH_SYMBOL), + Symbol_Currency = U_MASK(U_CURRENCY_SYMBOL), + Symbol_Modifier = U_MASK(U_MODIFIER_SYMBOL), + Symbol_Other = U_MASK(U_OTHER_SYMBOL), + + Punctuation_InitialQuote = U_MASK(U_INITIAL_PUNCTUATION), + Punctuation_FinalQuote = U_MASK(U_FINAL_PUNCTUATION) +}; + +inline UChar32 foldCase(UChar32 c) +{ + return u_foldCase(c, U_FOLD_CASE_DEFAULT); +} + +inline int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error) +{ + UErrorCode status = U_ZERO_ERROR; + int realLength = u_strFoldCase(result, resultLength, src, srcLength, U_FOLD_CASE_DEFAULT, &status); + *error = !U_SUCCESS(status); + return realLength; +} + +inline int toLower(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error) +{ + UErrorCode status = U_ZERO_ERROR; + int realLength = u_strToLower(result, resultLength, src, srcLength, "", &status); + *error = !!U_FAILURE(status); + return realLength; +} + +inline UChar32 toLower(UChar32 c) +{ + return u_tolower(c); +} + +inline UChar32 toUpper(UChar32 c) +{ + return u_toupper(c); +} + +inline int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error) +{ + UErrorCode status = U_ZERO_ERROR; + int realLength = u_strToUpper(result, resultLength, src, srcLength, "", &status); + *error = !!U_FAILURE(status); + return realLength; +} + +inline UChar32 toTitleCase(UChar32 c) +{ + return u_totitle(c); +} + +inline bool isArabicChar(UChar32 c) +{ + return ublock_getCode(c) == UBLOCK_ARABIC; +} + +inline bool isAlphanumeric(UChar32 c) +{ + return u_isalnum(c); +} + +inline bool isSeparatorSpace(UChar32 c) +{ + return u_charType(c) == U_SPACE_SEPARATOR; +} + +inline bool isPrintableChar(UChar32 c) +{ + return !!u_isprint(c); +} + +inline bool isPunct(UChar32 c) +{ + return !!u_ispunct(c); +} + +inline bool hasLineBreakingPropertyComplexContext(UChar32 c) +{ + return u_getIntPropertyValue(c, UCHAR_LINE_BREAK) == U_LB_COMPLEX_CONTEXT; +} + +inline bool hasLineBreakingPropertyComplexContextOrIdeographic(UChar32 c) +{ + int32_t prop = u_getIntPropertyValue(c, UCHAR_LINE_BREAK); + return prop == U_LB_COMPLEX_CONTEXT || prop == U_LB_IDEOGRAPHIC; +} + +inline UChar32 mirroredChar(UChar32 c) +{ + return u_charMirror(c); +} + +inline CharCategory category(UChar32 c) +{ + return static_cast(U_GET_GC_MASK(c)); +} + +inline Direction direction(UChar32 c) +{ + return static_cast(u_charDirection(c)); +} + +inline bool isLower(UChar32 c) +{ + return !!u_islower(c); +} + +inline uint8_t combiningClass(UChar32 c) +{ + return u_getCombiningClass(c); +} + +inline DecompositionType decompositionType(UChar32 c) +{ + return static_cast(u_getIntPropertyValue(c, UCHAR_DECOMPOSITION_TYPE)); +} + +inline int umemcasecmp(const UChar* a, const UChar* b, int len) +{ + return u_memcasecmp(a, b, len, U_FOLD_CASE_DEFAULT); +} + +} } + +#endif // WTF_UNICODE_ICU_H diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/UnionFind.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/UnionFind.h new file mode 100644 index 000000000..fa737116c --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/UnionFind.h @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2011 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 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 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 UnionFind_h +#define UnionFind_h + +#include + +namespace WTF { + +// A UnionFind class can be used to compute disjoint sets using the +// disjoint-set forest data structure. Each UnionFind instance is a +// node in the forest. Typically you use it by using UnionFind as a +// superclass: +// +// class MemberOfSet : public UnionFind { ... } +// +// Calling x->find() gives you a MemberOfSet* that represents the +// disjoint set that x belongs to. Calling x->unify(y) unifies x's +// set with y's set, and ensures that: +// +// x->find() == y->find() +// +// and that: +// +// a->find() == b->find() +// +// for any a, b if prior to the call to x->unify(y), we would have +// had: +// +// a->find() == x +// b->find() == y +// +// This implementation is almost amortized O(1), but could be worse +// in unlikely pathological cases. It favors having a non-recursive +// single pass implementation of unify() and find() over ensuring the +// theoretical O(InverseAckermann[n]) amortized bound, which is much +// closer to amortized O(1). + +template +class UnionFind { +public: + UnionFind() + : m_parent(0) + { + } + + T* find() + { + T* result = static_cast(this); + T* next = result->m_parent; + while (next) { + result = next; + next = result->m_parent; + } + ASSERT(result); + if (result != this) + m_parent = result; + return result; + } + + void unify(T* other) + { + T* a = static_cast(this)->find(); + T* b = other->find(); + + ASSERT(!a->m_parent); + ASSERT(!b->m_parent); + + if (a == b) + return; + + a->m_parent = b; + } +private: + T* m_parent; +}; + +} // namespace WTF + +using WTF::UnionFind; + +#endif // UnionFind_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/UnusedParam.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/UnusedParam.h new file mode 100644 index 000000000..6ff6fd895 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/UnusedParam.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WTF_UnusedParam_h +#define WTF_UnusedParam_h + +/* don't use this for C++, it should only be used in plain C files or + ObjC methods, where leaving off the parameter name is not allowed. */ + +#include "Platform.h" + +#if COMPILER(INTEL) && !OS(WINDOWS) || COMPILER(RVCT) +template +inline void unusedParam(T& x) { (void)x; } +#define UNUSED_PARAM(variable) unusedParam(variable) +#else +#define UNUSED_PARAM(variable) (void)variable +#endif + +#endif /* WTF_UnusedParam_h */ diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/VMTags.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/VMTags.h new file mode 100644 index 000000000..117bc3721 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/VMTags.h @@ -0,0 +1,75 @@ +/* + * 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 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 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 VMTags_h +#define VMTags_h + +// On Mac OS X, the VM subsystem allows tagging memory requested from mmap and vm_map +// in order to aid tools that inspect system memory use. +#if OS(DARWIN) + +#include + +#if defined(VM_MEMORY_TCMALLOC) +#define VM_TAG_FOR_TCMALLOC_MEMORY VM_MAKE_TAG(VM_MEMORY_TCMALLOC) +#else +#define VM_TAG_FOR_TCMALLOC_MEMORY VM_MAKE_TAG(53) +#endif // defined(VM_MEMORY_TCMALLOC) + +#if defined(VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR) +#define VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY VM_MAKE_TAG(VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR) +#else +#define VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY VM_MAKE_TAG(64) +#endif // defined(VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR) + +#if defined(VM_MEMORY_JAVASCRIPT_JIT_REGISTER_FILE) +#define VM_TAG_FOR_REGISTERFILE_MEMORY VM_MAKE_TAG(VM_MEMORY_JAVASCRIPT_JIT_REGISTER_FILE) +#else +#define VM_TAG_FOR_REGISTERFILE_MEMORY VM_MAKE_TAG(65) +#endif // defined(VM_MEMORY_JAVASCRIPT_JIT_REGISTER_FILE) + +#if defined(VM_MEMORY_JAVASCRIPT_CORE) +#define VM_TAG_FOR_COLLECTOR_MEMORY VM_MAKE_TAG(VM_MEMORY_JAVASCRIPT_CORE) +#else +#define VM_TAG_FOR_COLLECTOR_MEMORY VM_MAKE_TAG(63) +#endif // defined(VM_MEMORY_JAVASCRIPT_CORE) + +#if defined(VM_MEMORY_WEBCORE_PURGEABLE_BUFFERS) +#define VM_TAG_FOR_WEBCORE_PURGEABLE_MEMORY VM_MAKE_TAG(VM_MEMORY_WEBCORE_PURGEABLE_BUFFERS) +#else +#define VM_TAG_FOR_WEBCORE_PURGEABLE_MEMORY VM_MAKE_TAG(69) +#endif // defined(VM_MEMORY_WEBCORE_PURGEABLE_BUFFERS) + +#else // OS(DARWIN) + +#define VM_TAG_FOR_TCMALLOC_MEMORY -1 +#define VM_TAG_FOR_COLLECTOR_MEMORY -1 +#define VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY -1 +#define VM_TAG_FOR_REGISTERFILE_MEMORY -1 +#define VM_TAG_FOR_WEBCORE_PURGEABLE_MEMORY -1 + +#endif // OS(DARWIN) + +#endif // VMTags_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/VTableSpectrum.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/VTableSpectrum.h new file mode 100644 index 000000000..a50a04f47 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/VTableSpectrum.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2011 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 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 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 VTableSpectrum_h +#define VTableSpectrum_h + +#include +#include + +namespace JSC { + +class JSCell; + +class VTableSpectrum : Spectrum { +public: + VTableSpectrum(); + ~VTableSpectrum(); + + void countVPtr(void*); + JS_EXPORT_PRIVATE void count(JSCell*); + + void dump(FILE* output, const char* comment); +}; + +} // namespace JSC + +#endif // VTableSpectrum_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ValueCheck.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ValueCheck.h new file mode 100644 index 000000000..2a86eb0f2 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ValueCheck.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2010 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 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 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 ValueCheck_h +#define ValueCheck_h + +#include + +namespace WTF { + +template struct ValueCheck { + typedef T TraitType; + static void checkConsistency(const T&) { } +}; + +#if !ASSERT_DISABLED +template struct ValueCheck { + typedef P* TraitType; + static void checkConsistency(const P* p) + { + if (!p) + return; + ASSERT(fastMallocSize(p)); + ValueCheck

::checkConsistency(*p); + } +}; +#endif + +} + +#endif // ValueCheck_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ValueProfile.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ValueProfile.h new file mode 100644 index 000000000..02a1d6bf9 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ValueProfile.h @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2011 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 ValueProfile_h +#define ValueProfile_h + +#include "JSArray.h" +#include "PredictedType.h" +#include "Structure.h" +#include "WriteBarrier.h" + +namespace JSC { + +#if ENABLE(VALUE_PROFILER) +struct ValueProfile { + static const unsigned logNumberOfBuckets = 0; // 1 bucket + static const unsigned numberOfBuckets = 1 << logNumberOfBuckets; + static const unsigned numberOfSpecFailBuckets = 1; + static const unsigned bucketIndexMask = numberOfBuckets - 1; + static const unsigned totalNumberOfBuckets = numberOfBuckets + numberOfSpecFailBuckets; + + ValueProfile() + : m_bytecodeOffset(-1) + , m_prediction(PredictNone) + , m_numberOfSamplesInPrediction(0) + { + for (unsigned i = 0; i < totalNumberOfBuckets; ++i) + m_buckets[i] = JSValue::encode(JSValue()); + } + + ValueProfile(int bytecodeOffset) + : m_bytecodeOffset(bytecodeOffset) + , m_prediction(PredictNone) + , m_numberOfSamplesInPrediction(0) + { + for (unsigned i = 0; i < totalNumberOfBuckets; ++i) + m_buckets[i] = JSValue::encode(JSValue()); + } + + EncodedJSValue* specFailBucket(unsigned i) + { + ASSERT(numberOfBuckets + i < totalNumberOfBuckets); + return m_buckets + numberOfBuckets + i; + } + + const ClassInfo* classInfo(unsigned bucket) const + { + JSValue value = JSValue::decode(m_buckets[bucket]); + if (!!value) { + if (!value.isCell()) + return 0; + return value.asCell()->structure()->classInfo(); + } + return 0; + } + + unsigned numberOfSamples() const + { + unsigned result = 0; + for (unsigned i = 0; i < totalNumberOfBuckets; ++i) { + if (!!JSValue::decode(m_buckets[i])) + result++; + } + return result; + } + + unsigned totalNumberOfSamples() const + { + return numberOfSamples() + m_numberOfSamplesInPrediction; + } + + bool isLive() const + { + for (unsigned i = 0; i < totalNumberOfBuckets; ++i) { + if (!!JSValue::decode(m_buckets[i])) + return true; + } + return false; + } + +#ifndef NDEBUG + void dump(FILE* out) + { + fprintf(out, + "samples = %u, prediction = %s", + totalNumberOfSamples(), + predictionToString(m_prediction)); + bool first = true; + for (unsigned i = 0; i < totalNumberOfBuckets; ++i) { + JSValue value = JSValue::decode(m_buckets[i]); + if (!!value) { + if (first) { + fprintf(out, ": "); + first = false; + } else + fprintf(out, ", "); + fprintf(out, "%s", value.description()); + } + } + } +#endif + + // Updates the prediction and returns the new one. + PredictedType computeUpdatedPrediction(); + + int m_bytecodeOffset; // -1 for prologue + + PredictedType m_prediction; + unsigned m_numberOfSamplesInPrediction; + + EncodedJSValue m_buckets[totalNumberOfBuckets]; +}; + +inline int getValueProfileBytecodeOffset(ValueProfile* valueProfile) +{ + return valueProfile->m_bytecodeOffset; +} + +// This is a mini value profile to catch pathologies. It is a counter that gets +// incremented when we take the slow path on any instruction. +struct RareCaseProfile { + RareCaseProfile(int bytecodeOffset) + : m_bytecodeOffset(bytecodeOffset) + , m_counter(0) + { + } + + int m_bytecodeOffset; + uint32_t m_counter; +}; + +inline int getRareCaseProfileBytecodeOffset(RareCaseProfile* rareCaseProfile) +{ + return rareCaseProfile->m_bytecodeOffset; +} +#endif + +} + +#endif + diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ValueRecovery.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ValueRecovery.h new file mode 100644 index 000000000..356abe84f --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/ValueRecovery.h @@ -0,0 +1,337 @@ +/* + * Copyright (C) 2011 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 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 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 ValueRecovery_h +#define ValueRecovery_h + +#include "DataFormat.h" +#include "JSValue.h" +#include "MacroAssembler.h" +#include "VirtualRegister.h" +#include + +#ifndef NDEBUG +#include +#endif + +namespace JSC { + +// Describes how to recover a given bytecode virtual register at a given +// code point. +enum ValueRecoveryTechnique { + // It's already in the register file at the right location. + AlreadyInRegisterFile, + // It's already in the register file but unboxed. + AlreadyInRegisterFileAsUnboxedInt32, + AlreadyInRegisterFileAsUnboxedCell, + AlreadyInRegisterFileAsUnboxedBoolean, + AlreadyInRegisterFileAsUnboxedDouble, + // It's in a register. + InGPR, + UnboxedInt32InGPR, + UnboxedBooleanInGPR, +#if USE(JSVALUE32_64) + InPair, +#endif + InFPR, + UInt32InGPR, + // It's in the register file, but at a different location. + DisplacedInRegisterFile, + // It's in the register file, at a different location, and it's unboxed. + Int32DisplacedInRegisterFile, + DoubleDisplacedInRegisterFile, + CellDisplacedInRegisterFile, + BooleanDisplacedInRegisterFile, + // It's a constant. + Constant, + // Don't know how to recover it. + DontKnow +}; + +class ValueRecovery { +public: + ValueRecovery() + : m_technique(DontKnow) + { + } + + static ValueRecovery alreadyInRegisterFile() + { + ValueRecovery result; + result.m_technique = AlreadyInRegisterFile; + return result; + } + + static ValueRecovery alreadyInRegisterFileAsUnboxedInt32() + { + ValueRecovery result; + result.m_technique = AlreadyInRegisterFileAsUnboxedInt32; + return result; + } + + static ValueRecovery alreadyInRegisterFileAsUnboxedCell() + { + ValueRecovery result; + result.m_technique = AlreadyInRegisterFileAsUnboxedCell; + return result; + } + + static ValueRecovery alreadyInRegisterFileAsUnboxedBoolean() + { + ValueRecovery result; + result.m_technique = AlreadyInRegisterFileAsUnboxedBoolean; + return result; + } + + static ValueRecovery alreadyInRegisterFileAsUnboxedDouble() + { + ValueRecovery result; + result.m_technique = AlreadyInRegisterFileAsUnboxedDouble; + return result; + } + + static ValueRecovery inGPR(MacroAssembler::RegisterID gpr, DataFormat dataFormat) + { + ASSERT(dataFormat != DataFormatNone); +#if USE(JSVALUE32_64) + ASSERT(dataFormat == DataFormatInteger || dataFormat == DataFormatCell || dataFormat == DataFormatBoolean); +#endif + ValueRecovery result; + if (dataFormat == DataFormatInteger) + result.m_technique = UnboxedInt32InGPR; + else if (dataFormat == DataFormatBoolean) + result.m_technique = UnboxedBooleanInGPR; + else + result.m_technique = InGPR; + result.m_source.gpr = gpr; + return result; + } + + static ValueRecovery uint32InGPR(MacroAssembler::RegisterID gpr) + { + ValueRecovery result; + result.m_technique = UInt32InGPR; + result.m_source.gpr = gpr; + return result; + } + +#if USE(JSVALUE32_64) + static ValueRecovery inPair(MacroAssembler::RegisterID tagGPR, MacroAssembler::RegisterID payloadGPR) + { + ValueRecovery result; + result.m_technique = InPair; + result.m_source.pair.tagGPR = tagGPR; + result.m_source.pair.payloadGPR = payloadGPR; + return result; + } +#endif + + static ValueRecovery inFPR(MacroAssembler::FPRegisterID fpr) + { + ValueRecovery result; + result.m_technique = InFPR; + result.m_source.fpr = fpr; + return result; + } + + static ValueRecovery displacedInRegisterFile(VirtualRegister virtualReg, DataFormat dataFormat) + { + ValueRecovery result; + switch (dataFormat) { + case DataFormatInteger: + result.m_technique = Int32DisplacedInRegisterFile; + break; + + case DataFormatDouble: + result.m_technique = DoubleDisplacedInRegisterFile; + break; + + case DataFormatCell: + result.m_technique = CellDisplacedInRegisterFile; + break; + + case DataFormatBoolean: + result.m_technique = BooleanDisplacedInRegisterFile; + break; + + default: + ASSERT(dataFormat != DataFormatNone && dataFormat != DataFormatStorage); + result.m_technique = DisplacedInRegisterFile; + break; + } + result.m_source.virtualReg = virtualReg; + return result; + } + + static ValueRecovery constant(JSValue value) + { + ValueRecovery result; + result.m_technique = Constant; + result.m_source.constant = JSValue::encode(value); + return result; + } + + ValueRecoveryTechnique technique() const { return m_technique; } + + bool isInRegisters() const + { + switch (m_technique) { + case InGPR: + case UnboxedInt32InGPR: + case UnboxedBooleanInGPR: +#if USE(JSVALUE32_64) + case InPair: +#endif + case InFPR: + return true; + default: + return false; + } + } + + MacroAssembler::RegisterID gpr() const + { + ASSERT(m_technique == InGPR || m_technique == UnboxedInt32InGPR || m_technique == UnboxedBooleanInGPR || m_technique == UInt32InGPR); + return m_source.gpr; + } + +#if USE(JSVALUE32_64) + MacroAssembler::RegisterID tagGPR() const + { + ASSERT(m_technique == InPair); + return m_source.pair.tagGPR; + } + + MacroAssembler::RegisterID payloadGPR() const + { + ASSERT(m_technique == InPair); + return m_source.pair.payloadGPR; + } +#endif + + MacroAssembler::FPRegisterID fpr() const + { + ASSERT(m_technique == InFPR); + return m_source.fpr; + } + + VirtualRegister virtualRegister() const + { + ASSERT(m_technique == DisplacedInRegisterFile || m_technique == Int32DisplacedInRegisterFile || m_technique == DoubleDisplacedInRegisterFile || m_technique == CellDisplacedInRegisterFile || m_technique == BooleanDisplacedInRegisterFile); + return m_source.virtualReg; + } + + JSValue constant() const + { + ASSERT(m_technique == Constant); + return JSValue::decode(m_source.constant); + } + +#ifndef NDEBUG + void dump(FILE* out) const + { + switch (technique()) { + case AlreadyInRegisterFile: + fprintf(out, "-"); + break; + case AlreadyInRegisterFileAsUnboxedInt32: + fprintf(out, "(int32)"); + break; + case AlreadyInRegisterFileAsUnboxedCell: + fprintf(out, "(cell)"); + break; + case AlreadyInRegisterFileAsUnboxedBoolean: + fprintf(out, "(bool)"); + break; + case AlreadyInRegisterFileAsUnboxedDouble: + fprintf(out, "(double)"); + break; + case InGPR: + fprintf(out, "%%r%d", gpr()); + break; + case UnboxedInt32InGPR: + fprintf(out, "int32(%%r%d)", gpr()); + break; + case UnboxedBooleanInGPR: + fprintf(out, "bool(%%r%d)", gpr()); + break; + case UInt32InGPR: + fprintf(out, "uint32(%%r%d)", gpr()); + break; + case InFPR: + fprintf(out, "%%fr%d", fpr()); + break; +#if USE(JSVALUE32_64) + case InPair: + fprintf(out, "pair(%%r%d, %%r%d)", tagGPR(), payloadGPR()); + break; +#endif + case DisplacedInRegisterFile: + fprintf(out, "*%d", virtualRegister()); + break; + case Int32DisplacedInRegisterFile: + fprintf(out, "*int32(%d)", virtualRegister()); + break; + case DoubleDisplacedInRegisterFile: + fprintf(out, "*double(%d)", virtualRegister()); + break; + case CellDisplacedInRegisterFile: + fprintf(out, "*cell(%d)", virtualRegister()); + break; + case BooleanDisplacedInRegisterFile: + fprintf(out, "*bool(%d)", virtualRegister()); + break; + case Constant: + fprintf(out, "[%s]", constant().description()); + break; + case DontKnow: + fprintf(out, "!"); + break; + default: + fprintf(out, "?%d", technique()); + break; + } + } +#endif + +private: + ValueRecoveryTechnique m_technique; + union { + MacroAssembler::RegisterID gpr; + MacroAssembler::FPRegisterID fpr; +#if USE(JSVALUE32_64) + struct { + MacroAssembler::RegisterID tagGPR; + MacroAssembler::RegisterID payloadGPR; + } pair; +#endif + VirtualRegister virtualReg; + EncodedJSValue constant; + } m_source; +}; + +} // namespace JSC + +#endif // ValueRecovery_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Vector.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Vector.h new file mode 100644 index 000000000..1368ac99b --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Vector.h @@ -0,0 +1,1191 @@ +/* + * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WTF_Vector_h +#define WTF_Vector_h + +#include "Alignment.h" +#include "FastAllocBase.h" +#include "Noncopyable.h" +#include "NotFound.h" +#include "StdLibExtras.h" +#include "ValueCheck.h" +#include "VectorTraits.h" +#include +#include + +#if PLATFORM(QT) +#include +#endif + +namespace WTF { + + using std::min; + using std::max; + + template + struct VectorDestructor; + + template + struct VectorDestructor + { + static void destruct(T*, T*) {} + }; + + template + struct VectorDestructor + { + static void destruct(T* begin, T* end) + { + for (T* cur = begin; cur != end; ++cur) + cur->~T(); + } + }; + + template + struct VectorInitializer; + + template + struct VectorInitializer + { + static void initialize(T*, T*) {} + }; + + template + struct VectorInitializer + { + static void initialize(T* begin, T* end) + { + for (T* cur = begin; cur != end; ++cur) + new (NotNull, cur) T; + } + }; + + template + struct VectorInitializer + { + static void initialize(T* begin, T* end) + { + memset(begin, 0, reinterpret_cast(end) - reinterpret_cast(begin)); + } + }; + + template + struct VectorMover; + + template + struct VectorMover + { + static void move(const T* src, const T* srcEnd, T* dst) + { + while (src != srcEnd) { + new (NotNull, dst) T(*src); +#if COMPILER(SUNCC) && __SUNPRO_CC <= 0x590 + const_cast(src)->~T(); // Work around obscure SunCC 12 compiler bug. +#else + src->~T(); +#endif + ++dst; + ++src; + } + } + static void moveOverlapping(const T* src, const T* srcEnd, T* dst) + { + if (src > dst) + move(src, srcEnd, dst); + else { + T* dstEnd = dst + (srcEnd - src); + while (src != srcEnd) { + --srcEnd; + --dstEnd; + new (NotNull, dstEnd) T(*srcEnd); + srcEnd->~T(); + } + } + } + }; + + template + struct VectorMover + { + static void move(const T* src, const T* srcEnd, T* dst) + { + memcpy(dst, src, reinterpret_cast(srcEnd) - reinterpret_cast(src)); + } + static void moveOverlapping(const T* src, const T* srcEnd, T* dst) + { + memmove(dst, src, reinterpret_cast(srcEnd) - reinterpret_cast(src)); + } + }; + + template + struct VectorCopier; + + template + struct VectorCopier + { + static void uninitializedCopy(const T* src, const T* srcEnd, T* dst) + { + while (src != srcEnd) { + new (NotNull, dst) T(*src); + ++dst; + ++src; + } + } + }; + + template + struct VectorCopier + { + static void uninitializedCopy(const T* src, const T* srcEnd, T* dst) + { + memcpy(dst, src, reinterpret_cast(srcEnd) - reinterpret_cast(src)); + } + }; + + template + struct VectorFiller; + + template + struct VectorFiller + { + static void uninitializedFill(T* dst, T* dstEnd, const T& val) + { + while (dst != dstEnd) { + new (NotNull, dst) T(val); + ++dst; + } + } + }; + + template + struct VectorFiller + { + static void uninitializedFill(T* dst, T* dstEnd, const T& val) + { + ASSERT(sizeof(T) == sizeof(char)); + memset(dst, val, dstEnd - dst); + } + }; + + template + struct VectorComparer; + + template + struct VectorComparer + { + static bool compare(const T* a, const T* b, size_t size) + { + for (size_t i = 0; i < size; ++i) + if (a[i] != b[i]) + return false; + return true; + } + }; + + template + struct VectorComparer + { + static bool compare(const T* a, const T* b, size_t size) + { + return memcmp(a, b, sizeof(T) * size) == 0; + } + }; + + template + struct VectorTypeOperations + { + static void destruct(T* begin, T* end) + { + VectorDestructor::needsDestruction, T>::destruct(begin, end); + } + + static void initialize(T* begin, T* end) + { + VectorInitializer::needsInitialization, VectorTraits::canInitializeWithMemset, T>::initialize(begin, end); + } + + static void move(const T* src, const T* srcEnd, T* dst) + { + VectorMover::canMoveWithMemcpy, T>::move(src, srcEnd, dst); + } + + static void moveOverlapping(const T* src, const T* srcEnd, T* dst) + { + VectorMover::canMoveWithMemcpy, T>::moveOverlapping(src, srcEnd, dst); + } + + static void uninitializedCopy(const T* src, const T* srcEnd, T* dst) + { + VectorCopier::canCopyWithMemcpy, T>::uninitializedCopy(src, srcEnd, dst); + } + + static void uninitializedFill(T* dst, T* dstEnd, const T& val) + { + VectorFiller::canFillWithMemset, T>::uninitializedFill(dst, dstEnd, val); + } + + static bool compare(const T* a, const T* b, size_t size) + { + return VectorComparer::canCompareWithMemcmp, T>::compare(a, b, size); + } + }; + + template + class VectorBufferBase { + WTF_MAKE_NONCOPYABLE(VectorBufferBase); + public: + void allocateBuffer(size_t newCapacity) + { + ASSERT(newCapacity); + m_capacity = newCapacity; + if (newCapacity > std::numeric_limits::max() / sizeof(T)) + CRASH(); + m_buffer = static_cast(fastMalloc(newCapacity * sizeof(T))); + } + + bool tryAllocateBuffer(size_t newCapacity) + { + ASSERT(newCapacity); + if (newCapacity > std::numeric_limits::max() / sizeof(T)) + return false; + + T* newBuffer; + if (tryFastMalloc(newCapacity * sizeof(T)).getValue(newBuffer)) { + m_capacity = newCapacity; + m_buffer = newBuffer; + return true; + } + return false; + } + + void deallocateBuffer(T* bufferToDeallocate) + { + if (m_buffer == bufferToDeallocate) { + m_buffer = 0; + m_capacity = 0; + } + fastFree(bufferToDeallocate); + } + + T* buffer() { return m_buffer; } + const T* buffer() const { return m_buffer; } + T** bufferSlot() { return &m_buffer; } + size_t capacity() const { return m_capacity; } + + T* releaseBuffer() + { + T* buffer = m_buffer; + m_buffer = 0; + m_capacity = 0; + return buffer; + } + + protected: + VectorBufferBase() + : m_buffer(0) + , m_capacity(0) + { + } + + VectorBufferBase(T* buffer, size_t capacity) + : m_buffer(buffer) + , m_capacity(capacity) + { + } + + ~VectorBufferBase() + { + // FIXME: It would be nice to find a way to ASSERT that m_buffer hasn't leaked here. + } + + T* m_buffer; + size_t m_capacity; + }; + + template + class VectorBuffer; + + template + class VectorBuffer : private VectorBufferBase { + private: + typedef VectorBufferBase Base; + public: + VectorBuffer() + { + } + + VectorBuffer(size_t capacity) + { + // Calling malloc(0) might take a lock and may actually do an + // allocation on some systems. + if (capacity) + allocateBuffer(capacity); + } + + ~VectorBuffer() + { + deallocateBuffer(buffer()); + } + + void swap(VectorBuffer& other) + { + std::swap(m_buffer, other.m_buffer); + std::swap(m_capacity, other.m_capacity); + } + + void restoreInlineBufferIfNeeded() { } + + using Base::allocateBuffer; + using Base::tryAllocateBuffer; + using Base::deallocateBuffer; + + using Base::buffer; + using Base::bufferSlot; + using Base::capacity; + + using Base::releaseBuffer; + private: + using Base::m_buffer; + using Base::m_capacity; + }; + + template + class VectorBuffer : private VectorBufferBase { + WTF_MAKE_NONCOPYABLE(VectorBuffer); + private: + typedef VectorBufferBase Base; + public: + VectorBuffer() + : Base(inlineBuffer(), inlineCapacity) + { + } + + VectorBuffer(size_t capacity) + : Base(inlineBuffer(), inlineCapacity) + { + if (capacity > inlineCapacity) + Base::allocateBuffer(capacity); + } + + ~VectorBuffer() + { + deallocateBuffer(buffer()); + } + + void allocateBuffer(size_t newCapacity) + { + // FIXME: This should ASSERT(!m_buffer) to catch misuse/leaks. + if (newCapacity > inlineCapacity) + Base::allocateBuffer(newCapacity); + else { + m_buffer = inlineBuffer(); + m_capacity = inlineCapacity; + } + } + + bool tryAllocateBuffer(size_t newCapacity) + { + if (newCapacity > inlineCapacity) + return Base::tryAllocateBuffer(newCapacity); + m_buffer = inlineBuffer(); + m_capacity = inlineCapacity; + return true; + } + + void deallocateBuffer(T* bufferToDeallocate) + { + if (bufferToDeallocate == inlineBuffer()) + return; + Base::deallocateBuffer(bufferToDeallocate); + } + + void swap(VectorBuffer& other) + { + if (buffer() == inlineBuffer() && other.buffer() == other.inlineBuffer()) { + WTF::swap(m_inlineBuffer, other.m_inlineBuffer); + std::swap(m_capacity, other.m_capacity); + } else if (buffer() == inlineBuffer()) { + m_buffer = other.m_buffer; + other.m_buffer = other.inlineBuffer(); + WTF::swap(m_inlineBuffer, other.m_inlineBuffer); + std::swap(m_capacity, other.m_capacity); + } else if (other.buffer() == other.inlineBuffer()) { + other.m_buffer = m_buffer; + m_buffer = inlineBuffer(); + WTF::swap(m_inlineBuffer, other.m_inlineBuffer); + std::swap(m_capacity, other.m_capacity); + } else { + std::swap(m_buffer, other.m_buffer); + std::swap(m_capacity, other.m_capacity); + } + } + + void restoreInlineBufferIfNeeded() + { + if (m_buffer) + return; + m_buffer = inlineBuffer(); + m_capacity = inlineCapacity; + } + + using Base::buffer; + using Base::bufferSlot; + using Base::capacity; + + T* releaseBuffer() + { + if (buffer() == inlineBuffer()) + return 0; + return Base::releaseBuffer(); + } + + private: + using Base::m_buffer; + using Base::m_capacity; + + static const size_t m_inlineBufferSize = inlineCapacity * sizeof(T); + T* inlineBuffer() { return reinterpret_cast_ptr(m_inlineBuffer.buffer); } + + AlignedBuffer m_inlineBuffer; + }; + + template + class Vector { + WTF_MAKE_FAST_ALLOCATED; + private: + typedef VectorBuffer Buffer; + typedef VectorTypeOperations TypeOperations; + + class VectorReverseProxy; + + public: + typedef T ValueType; + + typedef T* iterator; + typedef const T* const_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + Vector() + : m_size(0) + { + } + + explicit Vector(size_t size) + : m_size(size) + , m_buffer(size) + { + if (begin()) + TypeOperations::initialize(begin(), end()); + } + + ~Vector() + { + if (m_size) + shrink(0); + } + + Vector(const Vector&); + template + Vector(const Vector&); + + Vector& operator=(const Vector&); + template + Vector& operator=(const Vector&); + + size_t size() const { return m_size; } + size_t capacity() const { return m_buffer.capacity(); } + bool isEmpty() const { return !size(); } + + T& at(size_t i) + { + ASSERT(i < size()); + return m_buffer.buffer()[i]; + } + const T& at(size_t i) const + { + ASSERT(i < size()); + return m_buffer.buffer()[i]; + } + + T& operator[](size_t i) { return at(i); } + const T& operator[](size_t i) const { return at(i); } + + T* data() { return m_buffer.buffer(); } + const T* data() const { return m_buffer.buffer(); } + T** dataSlot() { return m_buffer.bufferSlot(); } + + iterator begin() { return data(); } + iterator end() { return begin() + m_size; } + const_iterator begin() const { return data(); } + const_iterator end() const { return begin() + m_size; } + + reverse_iterator rbegin() { return reverse_iterator(end()); } + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } + const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } + + VectorReverseProxy& reversed() { return static_cast(*this); } + const VectorReverseProxy& reversed() const { return static_cast(*this); } + + T& first() { return at(0); } + const T& first() const { return at(0); } + T& last() { return at(size() - 1); } + const T& last() const { return at(size() - 1); } + + template bool contains(const U&) const; + template size_t find(const U&) const; + template size_t reverseFind(const U&) const; + + void shrink(size_t size); + void grow(size_t size); + void resize(size_t size); + void reserveCapacity(size_t newCapacity); + bool tryReserveCapacity(size_t newCapacity); + void reserveInitialCapacity(size_t initialCapacity); + void shrinkCapacity(size_t newCapacity); + void shrinkToFit() { shrinkCapacity(size()); } + + void clear() { shrinkCapacity(0); } + + template void append(const U*, size_t); + template void append(const U&); + template void uncheckedAppend(const U& val); + template void append(const Vector&); + template bool tryAppend(const U*, size_t); + + template void insert(size_t position, const U*, size_t); + template void insert(size_t position, const U&); + template void insert(size_t position, const Vector&); + + template void prepend(const U*, size_t); + template void prepend(const U&); + template void prepend(const Vector&); + + void remove(size_t position); + void remove(size_t position, size_t length); + + void removeLast() + { + ASSERT(!isEmpty()); + shrink(size() - 1); + } + + Vector(size_t size, const T& val) + : m_size(size) + , m_buffer(size) + { + if (begin()) + TypeOperations::uninitializedFill(begin(), end(), val); + } + + void fill(const T&, size_t); + void fill(const T& val) { fill(val, size()); } + + template void appendRange(Iterator start, Iterator end); + + T* releaseBuffer(); + + void swap(Vector& other) + { + std::swap(m_size, other.m_size); + m_buffer.swap(other.m_buffer); + } + + void reverse(); + + void checkConsistency(); + + private: + void expandCapacity(size_t newMinCapacity); + const T* expandCapacity(size_t newMinCapacity, const T*); + bool tryExpandCapacity(size_t newMinCapacity); + const T* tryExpandCapacity(size_t newMinCapacity, const T*); + template U* expandCapacity(size_t newMinCapacity, U*); + template void appendSlowCase(const U&); + + class VectorReverseProxy : private Vector { + public: + typedef typename Vector::reverse_iterator iterator; + typedef typename Vector::const_reverse_iterator const_iterator; + + iterator begin() { return Vector::rbegin(); } + iterator end() { return Vector::rend(); } + const_iterator begin() const { return Vector::rbegin(); } + const_iterator end() const { return Vector::rend(); } + + private: + friend class Vector; + + // These are intentionally not implemented. + VectorReverseProxy(); + VectorReverseProxy(const VectorReverseProxy&); + VectorReverseProxy& operator=(const VectorReverseProxy&); + ~VectorReverseProxy(); + }; + + size_t m_size; + Buffer m_buffer; + }; + +#if PLATFORM(QT) + template + QDataStream& operator<<(QDataStream& stream, const Vector& data) + { + stream << qint64(data.size()); + foreach (const T& i, data) + stream << i; + return stream; + } + + template + QDataStream& operator>>(QDataStream& stream, Vector& data) + { + data.clear(); + qint64 count; + T item; + stream >> count; + data.reserveCapacity(count); + for (qint64 i = 0; i < count; ++i) { + stream >> item; + data.append(item); + } + return stream; + } +#endif + + template + Vector::Vector(const Vector& other) + : m_size(other.size()) + , m_buffer(other.capacity()) + { + if (begin()) + TypeOperations::uninitializedCopy(other.begin(), other.end(), begin()); + } + + template + template + Vector::Vector(const Vector& other) + : m_size(other.size()) + , m_buffer(other.capacity()) + { + if (begin()) + TypeOperations::uninitializedCopy(other.begin(), other.end(), begin()); + } + + template + Vector& Vector::operator=(const Vector& other) + { + if (&other == this) + return *this; + + if (size() > other.size()) + shrink(other.size()); + else if (other.size() > capacity()) { + clear(); + reserveCapacity(other.size()); + if (!begin()) + return *this; + } + +// Works around an assert in VS2010. See https://connect.microsoft.com/VisualStudio/feedback/details/558044/std-copy-should-not-check-dest-when-first-last +#if COMPILER(MSVC) && defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL + if (!begin()) + return *this; +#endif + + std::copy(other.begin(), other.begin() + size(), begin()); + TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end()); + m_size = other.size(); + + return *this; + } + + inline bool typelessPointersAreEqual(const void* a, const void* b) { return a == b; } + + template + template + Vector& Vector::operator=(const Vector& other) + { + // If the inline capacities match, we should call the more specific + // template. If the inline capacities don't match, the two objects + // shouldn't be allocated the same address. + ASSERT(!typelessPointersAreEqual(&other, this)); + + if (size() > other.size()) + shrink(other.size()); + else if (other.size() > capacity()) { + clear(); + reserveCapacity(other.size()); + if (!begin()) + return *this; + } + +// Works around an assert in VS2010. See https://connect.microsoft.com/VisualStudio/feedback/details/558044/std-copy-should-not-check-dest-when-first-last +#if COMPILER(MSVC) && defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL + if (!begin()) + return *this; +#endif + + std::copy(other.begin(), other.begin() + size(), begin()); + TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end()); + m_size = other.size(); + + return *this; + } + + template + template + bool Vector::contains(const U& value) const + { + return find(value) != notFound; + } + + template + template + size_t Vector::find(const U& value) const + { + for (size_t i = 0; i < size(); ++i) { + if (at(i) == value) + return i; + } + return notFound; + } + + template + template + size_t Vector::reverseFind(const U& value) const + { + for (size_t i = 1; i <= size(); ++i) { + const size_t index = size() - i; + if (at(index) == value) + return index; + } + return notFound; + } + + template + void Vector::fill(const T& val, size_t newSize) + { + if (size() > newSize) + shrink(newSize); + else if (newSize > capacity()) { + clear(); + reserveCapacity(newSize); + if (!begin()) + return; + } + + std::fill(begin(), end(), val); + TypeOperations::uninitializedFill(end(), begin() + newSize, val); + m_size = newSize; + } + + template + template + void Vector::appendRange(Iterator start, Iterator end) + { + for (Iterator it = start; it != end; ++it) + append(*it); + } + + template + void Vector::expandCapacity(size_t newMinCapacity) + { + reserveCapacity(max(newMinCapacity, max(static_cast(16), capacity() + capacity() / 4 + 1))); + } + + template + const T* Vector::expandCapacity(size_t newMinCapacity, const T* ptr) + { + if (ptr < begin() || ptr >= end()) { + expandCapacity(newMinCapacity); + return ptr; + } + size_t index = ptr - begin(); + expandCapacity(newMinCapacity); + return begin() + index; + } + + template + bool Vector::tryExpandCapacity(size_t newMinCapacity) + { + return tryReserveCapacity(max(newMinCapacity, max(static_cast(16), capacity() + capacity() / 4 + 1))); + } + + template + const T* Vector::tryExpandCapacity(size_t newMinCapacity, const T* ptr) + { + if (ptr < begin() || ptr >= end()) { + if (!tryExpandCapacity(newMinCapacity)) + return 0; + return ptr; + } + size_t index = ptr - begin(); + if (!tryExpandCapacity(newMinCapacity)) + return 0; + return begin() + index; + } + + template template + inline U* Vector::expandCapacity(size_t newMinCapacity, U* ptr) + { + expandCapacity(newMinCapacity); + return ptr; + } + + template + inline void Vector::resize(size_t size) + { + if (size <= m_size) + TypeOperations::destruct(begin() + size, end()); + else { + if (size > capacity()) + expandCapacity(size); + if (begin()) + TypeOperations::initialize(end(), begin() + size); + } + + m_size = size; + } + + template + void Vector::shrink(size_t size) + { + ASSERT(size <= m_size); + TypeOperations::destruct(begin() + size, end()); + m_size = size; + } + + template + void Vector::grow(size_t size) + { + ASSERT(size >= m_size); + if (size > capacity()) + expandCapacity(size); + if (begin()) + TypeOperations::initialize(end(), begin() + size); + m_size = size; + } + + template + void Vector::reserveCapacity(size_t newCapacity) + { + if (newCapacity <= capacity()) + return; + T* oldBuffer = begin(); + T* oldEnd = end(); + m_buffer.allocateBuffer(newCapacity); + if (begin()) + TypeOperations::move(oldBuffer, oldEnd, begin()); + m_buffer.deallocateBuffer(oldBuffer); + } + + template + bool Vector::tryReserveCapacity(size_t newCapacity) + { + if (newCapacity <= capacity()) + return true; + T* oldBuffer = begin(); + T* oldEnd = end(); + if (!m_buffer.tryAllocateBuffer(newCapacity)) + return false; + ASSERT(begin()); + TypeOperations::move(oldBuffer, oldEnd, begin()); + m_buffer.deallocateBuffer(oldBuffer); + return true; + } + + template + inline void Vector::reserveInitialCapacity(size_t initialCapacity) + { + ASSERT(!m_size); + ASSERT(capacity() == inlineCapacity); + if (initialCapacity > inlineCapacity) + m_buffer.allocateBuffer(initialCapacity); + } + + template + void Vector::shrinkCapacity(size_t newCapacity) + { + if (newCapacity >= capacity()) + return; + + if (newCapacity < size()) + shrink(newCapacity); + + T* oldBuffer = begin(); + if (newCapacity > 0) { + T* oldEnd = end(); + m_buffer.allocateBuffer(newCapacity); + if (begin() != oldBuffer) + TypeOperations::move(oldBuffer, oldEnd, begin()); + } + + m_buffer.deallocateBuffer(oldBuffer); + m_buffer.restoreInlineBufferIfNeeded(); + } + + // Templatizing these is better than just letting the conversion happen implicitly, + // because for instance it allows a PassRefPtr to be appended to a RefPtr vector + // without refcount thrash. + + template template + void Vector::append(const U* data, size_t dataSize) + { + size_t newSize = m_size + dataSize; + if (newSize > capacity()) { + data = expandCapacity(newSize, data); + if (!begin()) + return; + } + if (newSize < m_size) + CRASH(); + T* dest = end(); + for (size_t i = 0; i < dataSize; ++i) + new (NotNull, &dest[i]) T(data[i]); + m_size = newSize; + } + + template template + bool Vector::tryAppend(const U* data, size_t dataSize) + { + size_t newSize = m_size + dataSize; + if (newSize > capacity()) { + data = tryExpandCapacity(newSize, data); + if (!data) + return false; + ASSERT(begin()); + } + if (newSize < m_size) + return false; + T* dest = end(); + for (size_t i = 0; i < dataSize; ++i) + new (NotNull, &dest[i]) T(data[i]); + m_size = newSize; + return true; + } + + template template + ALWAYS_INLINE void Vector::append(const U& val) + { + if (size() != capacity()) { + new (NotNull, end()) T(val); + ++m_size; + return; + } + + appendSlowCase(val); + } + + template template + void Vector::appendSlowCase(const U& val) + { + ASSERT(size() == capacity()); + + const U* ptr = &val; + ptr = expandCapacity(size() + 1, ptr); + if (!begin()) + return; + + new (NotNull, end()) T(*ptr); + ++m_size; + } + + // This version of append saves a branch in the case where you know that the + // vector's capacity is large enough for the append to succeed. + + template template + inline void Vector::uncheckedAppend(const U& val) + { + ASSERT(size() < capacity()); + const U* ptr = &val; + new (NotNull, end()) T(*ptr); + ++m_size; + } + + // This method should not be called append, a better name would be appendElements. + // It could also be eliminated entirely, and call sites could just use + // appendRange(val.begin(), val.end()). + template template + inline void Vector::append(const Vector& val) + { + append(val.begin(), val.size()); + } + + template template + void Vector::insert(size_t position, const U* data, size_t dataSize) + { + ASSERT(position <= size()); + size_t newSize = m_size + dataSize; + if (newSize > capacity()) { + data = expandCapacity(newSize, data); + if (!begin()) + return; + } + if (newSize < m_size) + CRASH(); + T* spot = begin() + position; + TypeOperations::moveOverlapping(spot, end(), spot + dataSize); + for (size_t i = 0; i < dataSize; ++i) + new (NotNull, &spot[i]) T(data[i]); + m_size = newSize; + } + + template template + inline void Vector::insert(size_t position, const U& val) + { + ASSERT(position <= size()); + const U* data = &val; + if (size() == capacity()) { + data = expandCapacity(size() + 1, data); + if (!begin()) + return; + } + T* spot = begin() + position; + TypeOperations::moveOverlapping(spot, end(), spot + 1); + new (NotNull, spot) T(*data); + ++m_size; + } + + template template + inline void Vector::insert(size_t position, const Vector& val) + { + insert(position, val.begin(), val.size()); + } + + template template + void Vector::prepend(const U* data, size_t dataSize) + { + insert(0, data, dataSize); + } + + template template + inline void Vector::prepend(const U& val) + { + insert(0, val); + } + + template template + inline void Vector::prepend(const Vector& val) + { + insert(0, val.begin(), val.size()); + } + + template + inline void Vector::remove(size_t position) + { + ASSERT(position < size()); + T* spot = begin() + position; + spot->~T(); + TypeOperations::moveOverlapping(spot + 1, end(), spot); + --m_size; + } + + template + inline void Vector::remove(size_t position, size_t length) + { + ASSERT(position < size()); + ASSERT(position + length <= size()); + T* beginSpot = begin() + position; + T* endSpot = beginSpot + length; + TypeOperations::destruct(beginSpot, endSpot); + TypeOperations::moveOverlapping(endSpot, end(), beginSpot); + m_size -= length; + } + + template + inline void Vector::reverse() + { + for (size_t i = 0; i < m_size / 2; ++i) + std::swap(at(i), at(m_size - 1 - i)); + } + + template + inline T* Vector::releaseBuffer() + { + T* buffer = m_buffer.releaseBuffer(); + if (inlineCapacity && !buffer && m_size) { + // If the vector had some data, but no buffer to release, + // that means it was using the inline buffer. In that case, + // we create a brand new buffer so the caller always gets one. + size_t bytes = m_size * sizeof(T); + buffer = static_cast(fastMalloc(bytes)); + memcpy(buffer, data(), bytes); + } + m_size = 0; + return buffer; + } + + template + inline void Vector::checkConsistency() + { +#if !ASSERT_DISABLED + for (size_t i = 0; i < size(); ++i) + ValueCheck::checkConsistency(at(i)); +#endif + } + + template + void deleteAllValues(const Vector& collection) + { + typedef typename Vector::const_iterator iterator; + iterator end = collection.end(); + for (iterator it = collection.begin(); it != end; ++it) + delete *it; + } + + template + inline void swap(Vector& a, Vector& b) + { + a.swap(b); + } + + template + bool operator==(const Vector& a, const Vector& b) + { + if (a.size() != b.size()) + return false; + + return VectorTypeOperations::compare(a.data(), b.data(), a.size()); + } + + template + inline bool operator!=(const Vector& a, const Vector& b) + { + return !(a == b); + } + +#if !ASSERT_DISABLED + template struct ValueCheck > { + typedef Vector TraitType; + static void checkConsistency(const Vector& v) + { + v.checkConsistency(); + } + }; +#endif + +} // namespace WTF + +using WTF::Vector; + +#endif // WTF_Vector_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/VectorTraits.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/VectorTraits.h new file mode 100644 index 000000000..6777c9ebf --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/VectorTraits.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WTF_VectorTraits_h +#define WTF_VectorTraits_h + +#include "OwnPtr.h" +#include "RefPtr.h" +#include "TypeTraits.h" +#include +#include + +using std::pair; + +namespace WTF { + + template + struct VectorTraitsBase; + + template + struct VectorTraitsBase + { + static const bool needsDestruction = true; + static const bool needsInitialization = true; + static const bool canInitializeWithMemset = false; + static const bool canMoveWithMemcpy = false; + static const bool canCopyWithMemcpy = false; + static const bool canFillWithMemset = false; + static const bool canCompareWithMemcmp = false; + }; + + template + struct VectorTraitsBase + { + static const bool needsDestruction = false; + static const bool needsInitialization = false; + static const bool canInitializeWithMemset = false; + static const bool canMoveWithMemcpy = true; + static const bool canCopyWithMemcpy = true; + static const bool canFillWithMemset = sizeof(T) == sizeof(char); + static const bool canCompareWithMemcmp = true; + }; + + template + struct VectorTraits : VectorTraitsBase::value, T> { }; + + struct SimpleClassVectorTraits : VectorTraitsBase + { + static const bool canInitializeWithMemset = true; + static const bool canMoveWithMemcpy = true; + static const bool canCompareWithMemcmp = true; + }; + + // we know OwnPtr and RefPtr are simple enough that initializing to 0 and moving with memcpy + // (and then not destructing the original) will totally work + template + struct VectorTraits > : SimpleClassVectorTraits { }; + + template + struct VectorTraits > : SimpleClassVectorTraits { }; + + template + struct VectorTraits > + { + typedef VectorTraits FirstTraits; + typedef VectorTraits SecondTraits; + + static const bool needsDestruction = FirstTraits::needsDestruction || SecondTraits::needsDestruction; + static const bool needsInitialization = FirstTraits::needsInitialization || SecondTraits::needsInitialization; + static const bool canInitializeWithMemset = FirstTraits::canInitializeWithMemset && SecondTraits::canInitializeWithMemset; + static const bool canMoveWithMemcpy = FirstTraits::canMoveWithMemcpy && SecondTraits::canMoveWithMemcpy; + static const bool canCopyWithMemcpy = FirstTraits::canCopyWithMemcpy && SecondTraits::canCopyWithMemcpy; + static const bool canFillWithMemset = false; + static const bool canCompareWithMemcmp = FirstTraits::canCompareWithMemcmp && SecondTraits::canCompareWithMemcmp; + }; + +} // namespace WTF + +using WTF::VectorTraits; +using WTF::SimpleClassVectorTraits; + +#endif // WTF_VectorTraits_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/VirtualRegister.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/VirtualRegister.h new file mode 100644 index 000000000..b95f8b8fa --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/VirtualRegister.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2011 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 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 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 VirtualRegister_h +#define VirtualRegister_h + +#include + +namespace JSC { + +// Type for a virtual register number (spill location). +// Using an enum to make this type-checked at compile time, to avert programmer errors. +enum VirtualRegister { InvalidVirtualRegister = -1 }; +COMPILE_ASSERT(sizeof(VirtualRegister) == sizeof(int), VirtualRegister_is_32bit); + +} // namespace JSC + +#endif // VirtualRegister_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/WTFString.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/WTFString.h new file mode 100644 index 000000000..eb45c7f82 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/WTFString.h @@ -0,0 +1,648 @@ +/* + * (C) 1999 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WTFString_h +#define WTFString_h + +// This file would be called String.h, but that conflicts with +// on systems without case-sensitive file systems. + +#include "ASCIIFastPath.h" +#include "StringImpl.h" + +#ifdef __OBJC__ +#include +#endif + +#if USE(CF) +typedef const struct __CFString * CFStringRef; +#endif + +#if PLATFORM(QT) +QT_BEGIN_NAMESPACE +class QString; +QT_END_NAMESPACE +#include +#endif + +#if PLATFORM(WX) +class wxString; +#endif + +#if PLATFORM(BLACKBERRY) +namespace BlackBerry { +namespace WebKit { + class WebString; +} +} +#endif + +namespace WTF { + +class CString; +struct StringHash; + +// Declarations of string operations + +WTF_EXPORT_PRIVATE int charactersToIntStrict(const LChar*, size_t, bool* ok = 0, int base = 10); +WTF_EXPORT_PRIVATE int charactersToIntStrict(const UChar*, size_t, bool* ok = 0, int base = 10); +WTF_EXPORT_PRIVATE unsigned charactersToUIntStrict(const LChar*, size_t, bool* ok = 0, int base = 10); +WTF_EXPORT_PRIVATE unsigned charactersToUIntStrict(const UChar*, size_t, bool* ok = 0, int base = 10); +int64_t charactersToInt64Strict(const LChar*, size_t, bool* ok = 0, int base = 10); +int64_t charactersToInt64Strict(const UChar*, size_t, bool* ok = 0, int base = 10); +uint64_t charactersToUInt64Strict(const LChar*, size_t, bool* ok = 0, int base = 10); +uint64_t charactersToUInt64Strict(const UChar*, size_t, bool* ok = 0, int base = 10); +intptr_t charactersToIntPtrStrict(const LChar*, size_t, bool* ok = 0, int base = 10); +intptr_t charactersToIntPtrStrict(const UChar*, size_t, bool* ok = 0, int base = 10); + +int charactersToInt(const LChar*, size_t, bool* ok = 0); // ignores trailing garbage +WTF_EXPORT_PRIVATE int charactersToInt(const UChar*, size_t, bool* ok = 0); // ignores trailing garbage +unsigned charactersToUInt(const LChar*, size_t, bool* ok = 0); // ignores trailing garbage +unsigned charactersToUInt(const UChar*, size_t, bool* ok = 0); // ignores trailing garbage +int64_t charactersToInt64(const LChar*, size_t, bool* ok = 0); // ignores trailing garbage +int64_t charactersToInt64(const UChar*, size_t, bool* ok = 0); // ignores trailing garbage +uint64_t charactersToUInt64(const LChar*, size_t, bool* ok = 0); // ignores trailing garbage +uint64_t charactersToUInt64(const UChar*, size_t, bool* ok = 0); // ignores trailing garbage +intptr_t charactersToIntPtr(const LChar*, size_t, bool* ok = 0); // ignores trailing garbage +intptr_t charactersToIntPtr(const UChar*, size_t, bool* ok = 0); // ignores trailing garbage + +WTF_EXPORT_PRIVATE double charactersToDouble(const LChar*, size_t, bool* ok = 0, bool* didReadNumber = 0); +WTF_EXPORT_PRIVATE double charactersToDouble(const UChar*, size_t, bool* ok = 0, bool* didReadNumber = 0); +float charactersToFloat(const LChar*, size_t, bool* ok = 0, bool* didReadNumber = 0); +WTF_EXPORT_PRIVATE float charactersToFloat(const UChar*, size_t, bool* ok = 0, bool* didReadNumber = 0); + +enum FloatConversionFlags { + ShouldRoundSignificantFigures = 1 << 0, + ShouldRoundDecimalPlaces = 1 << 1, + ShouldTruncateTrailingZeros = 1 << 2 +}; + +template bool isAllSpecialCharacters(const UChar*, size_t); + +class String { +public: + // Construct a null string, distinguishable from an empty string. + String() { } + + // Construct a string with UTF-16 data. + WTF_EXPORT_PRIVATE String(const UChar* characters, unsigned length); + + // Construct a string by copying the contents of a vector. To avoid + // copying, consider using String::adopt instead. + template + explicit String(const Vector&); + + // Construct a string with UTF-16 data, from a null-terminated source. + WTF_EXPORT_PRIVATE String(const UChar*); + + // Construct a string with latin1 data. + WTF_EXPORT_PRIVATE String(const LChar* characters, unsigned length); + WTF_EXPORT_PRIVATE String(const char* characters, unsigned length); + + // Construct a string with latin1 data, from a null-terminated source. + WTF_EXPORT_PRIVATE String(const LChar* characters); + WTF_EXPORT_PRIVATE String(const char* characters); + + // Construct a string referencing an existing StringImpl. + String(StringImpl* impl) : m_impl(impl) { } + String(PassRefPtr impl) : m_impl(impl) { } + String(RefPtr impl) : m_impl(impl) { } + + // Inline the destructor. + ALWAYS_INLINE ~String() { } + + void swap(String& o) { m_impl.swap(o.m_impl); } + + static String adopt(StringBuffer& buffer) { return StringImpl::adopt(buffer); } + static String adopt(StringBuffer& buffer) { return StringImpl::adopt(buffer); } + template + static String adopt(Vector& vector) { return StringImpl::adopt(vector); } + + bool isNull() const { return !m_impl; } + bool isEmpty() const { return !m_impl || !m_impl->length(); } + + StringImpl* impl() const { return m_impl.get(); } + + unsigned length() const + { + if (!m_impl) + return 0; + return m_impl->length(); + } + + const UChar* characters() const + { + if (!m_impl) + return 0; + return m_impl->characters(); + } + + const LChar* characters8() const + { + if (!m_impl) + return 0; + ASSERT(m_impl->is8Bit()); + return m_impl->characters8(); + } + + const UChar* characters16() const + { + if (!m_impl) + return 0; + ASSERT(!m_impl->is8Bit()); + return m_impl->characters16(); + } + + template + inline const CharType* getCharacters() const; + + bool is8Bit() const { return m_impl->is8Bit(); } + + WTF_EXPORT_PRIVATE CString ascii() const; + WTF_EXPORT_PRIVATE CString latin1() const; + WTF_EXPORT_PRIVATE CString utf8(bool strict = false) const; + + UChar operator[](unsigned index) const + { + if (!m_impl || index >= m_impl->length()) + return 0; + return m_impl->characters()[index]; + } + + WTF_EXPORT_PRIVATE static String number(short); + WTF_EXPORT_PRIVATE static String number(unsigned short); + WTF_EXPORT_PRIVATE static String number(int); + WTF_EXPORT_PRIVATE static String number(unsigned); + WTF_EXPORT_PRIVATE static String number(long); + WTF_EXPORT_PRIVATE static String number(unsigned long); + WTF_EXPORT_PRIVATE static String number(long long); + WTF_EXPORT_PRIVATE static String number(unsigned long long); + WTF_EXPORT_PRIVATE static String number(double, unsigned = ShouldRoundSignificantFigures | ShouldTruncateTrailingZeros, unsigned precision = 6); + + // Find a single character or string, also with match function & latin1 forms. + size_t find(UChar c, unsigned start = 0) const + { return m_impl ? m_impl->find(c, start) : notFound; } + size_t find(const String& str, unsigned start = 0) const + { return m_impl ? m_impl->find(str.impl(), start) : notFound; } + size_t find(CharacterMatchFunctionPtr matchFunction, unsigned start = 0) const + { return m_impl ? m_impl->find(matchFunction, start) : notFound; } + size_t find(const LChar* str, unsigned start = 0) const + { return m_impl ? m_impl->find(str, start) : notFound; } + + // Find the last instance of a single character or string. + size_t reverseFind(UChar c, unsigned start = UINT_MAX) const + { return m_impl ? m_impl->reverseFind(c, start) : notFound; } + size_t reverseFind(const String& str, unsigned start = UINT_MAX) const + { return m_impl ? m_impl->reverseFind(str.impl(), start) : notFound; } + + // Case insensitive string matching. + size_t findIgnoringCase(const LChar* str, unsigned start = 0) const + { return m_impl ? m_impl->findIgnoringCase(str, start) : notFound; } + size_t findIgnoringCase(const String& str, unsigned start = 0) const + { return m_impl ? m_impl->findIgnoringCase(str.impl(), start) : notFound; } + size_t reverseFindIgnoringCase(const String& str, unsigned start = UINT_MAX) const + { return m_impl ? m_impl->reverseFindIgnoringCase(str.impl(), start) : notFound; } + + // Wrappers for find & reverseFind adding dynamic sensitivity check. + size_t find(const LChar* str, unsigned start, bool caseSensitive) const + { return caseSensitive ? find(str, start) : findIgnoringCase(str, start); } + size_t find(const String& str, unsigned start, bool caseSensitive) const + { return caseSensitive ? find(str, start) : findIgnoringCase(str, start); } + size_t reverseFind(const String& str, unsigned start, bool caseSensitive) const + { return caseSensitive ? reverseFind(str, start) : reverseFindIgnoringCase(str, start); } + + WTF_EXPORT_PRIVATE const UChar* charactersWithNullTermination(); + + WTF_EXPORT_PRIVATE UChar32 characterStartingAt(unsigned) const; // Ditto. + + bool contains(UChar c) const { return find(c) != notFound; } + bool contains(const LChar* str, bool caseSensitive = true) const { return find(str, 0, caseSensitive) != notFound; } + bool contains(const String& str, bool caseSensitive = true) const { return find(str, 0, caseSensitive) != notFound; } + + bool startsWith(const String& s, bool caseSensitive = true) const + { return m_impl ? m_impl->startsWith(s.impl(), caseSensitive) : s.isEmpty(); } + bool endsWith(const String& s, bool caseSensitive = true) const + { return m_impl ? m_impl->endsWith(s.impl(), caseSensitive) : s.isEmpty(); } + + WTF_EXPORT_PRIVATE void append(const String&); + WTF_EXPORT_PRIVATE void append(LChar); + void append(char c) { append(static_cast(c)); }; + WTF_EXPORT_PRIVATE void append(UChar); + WTF_EXPORT_PRIVATE void append(const UChar*, unsigned length); + WTF_EXPORT_PRIVATE void insert(const String&, unsigned pos); + void insert(const UChar*, unsigned length, unsigned pos); + + String& replace(UChar a, UChar b) { if (m_impl) m_impl = m_impl->replace(a, b); return *this; } + String& replace(UChar a, const String& b) { if (m_impl) m_impl = m_impl->replace(a, b.impl()); return *this; } + String& replace(const String& a, const String& b) { if (m_impl) m_impl = m_impl->replace(a.impl(), b.impl()); return *this; } + String& replace(unsigned index, unsigned len, const String& b) { if (m_impl) m_impl = m_impl->replace(index, len, b.impl()); return *this; } + + void makeLower() { if (m_impl) m_impl = m_impl->lower(); } + void makeUpper() { if (m_impl) m_impl = m_impl->upper(); } + void fill(UChar c) { if (m_impl) m_impl = m_impl->fill(c); } + + WTF_EXPORT_PRIVATE void truncate(unsigned len); + WTF_EXPORT_PRIVATE void remove(unsigned pos, int len = 1); + + WTF_EXPORT_PRIVATE String substring(unsigned pos, unsigned len = UINT_MAX) const; + String substringSharingImpl(unsigned pos, unsigned len = UINT_MAX) const; + String left(unsigned len) const { return substring(0, len); } + String right(unsigned len) const { return substring(length() - len, len); } + + // Returns a lowercase/uppercase version of the string + WTF_EXPORT_PRIVATE String lower() const; + WTF_EXPORT_PRIVATE String upper() const; + + WTF_EXPORT_PRIVATE String stripWhiteSpace() const; + WTF_EXPORT_PRIVATE String stripWhiteSpace(IsWhiteSpaceFunctionPtr) const; + WTF_EXPORT_PRIVATE String simplifyWhiteSpace() const; + WTF_EXPORT_PRIVATE String simplifyWhiteSpace(IsWhiteSpaceFunctionPtr) const; + + WTF_EXPORT_PRIVATE String removeCharacters(CharacterMatchFunctionPtr) const; + template bool isAllSpecialCharacters() const; + + // Return the string with case folded for case insensitive comparison. + WTF_EXPORT_PRIVATE String foldCase() const; + +#if !PLATFORM(QT) + WTF_EXPORT_PRIVATE static String format(const char *, ...) WTF_ATTRIBUTE_PRINTF(1, 2); +#else + WTF_EXPORT_PRIVATE static String format(const char *, ...); +#endif + + // Returns an uninitialized string. The characters needs to be written + // into the buffer returned in data before the returned string is used. + // Failure to do this will have unpredictable results. + static String createUninitialized(unsigned length, UChar*& data) { return StringImpl::createUninitialized(length, data); } + + WTF_EXPORT_PRIVATE void split(const String& separator, Vector& result) const; + WTF_EXPORT_PRIVATE void split(const String& separator, bool allowEmptyEntries, Vector& result) const; + WTF_EXPORT_PRIVATE void split(UChar separator, Vector& result) const; + WTF_EXPORT_PRIVATE void split(UChar separator, bool allowEmptyEntries, Vector& result) const; + + WTF_EXPORT_PRIVATE int toIntStrict(bool* ok = 0, int base = 10) const; + WTF_EXPORT_PRIVATE unsigned toUIntStrict(bool* ok = 0, int base = 10) const; + WTF_EXPORT_PRIVATE int64_t toInt64Strict(bool* ok = 0, int base = 10) const; + WTF_EXPORT_PRIVATE uint64_t toUInt64Strict(bool* ok = 0, int base = 10) const; + WTF_EXPORT_PRIVATE intptr_t toIntPtrStrict(bool* ok = 0, int base = 10) const; + + WTF_EXPORT_PRIVATE int toInt(bool* ok = 0) const; + WTF_EXPORT_PRIVATE unsigned toUInt(bool* ok = 0) const; + int64_t toInt64(bool* ok = 0) const; + WTF_EXPORT_PRIVATE uint64_t toUInt64(bool* ok = 0) const; + WTF_EXPORT_PRIVATE intptr_t toIntPtr(bool* ok = 0) const; + WTF_EXPORT_PRIVATE double toDouble(bool* ok = 0, bool* didReadNumber = 0) const; + WTF_EXPORT_PRIVATE float toFloat(bool* ok = 0, bool* didReadNumber = 0) const; + + bool percentage(int& percentage) const; + + WTF_EXPORT_PRIVATE String isolatedCopy() const; + + // Prevent Strings from being implicitly convertable to bool as it will be ambiguous on any platform that + // allows implicit conversion to another pointer type (e.g., Mac allows implicit conversion to NSString*). + typedef struct ImplicitConversionFromWTFStringToBoolDisallowedA* (String::*UnspecifiedBoolTypeA); + typedef struct ImplicitConversionFromWTFStringToBoolDisallowedB* (String::*UnspecifiedBoolTypeB); + operator UnspecifiedBoolTypeA() const; + operator UnspecifiedBoolTypeB() const; + +#if USE(CF) + String(CFStringRef); + CFStringRef createCFString() const; +#endif + +#ifdef __OBJC__ + String(NSString*); + + // This conversion maps NULL to "", which loses the meaning of NULL, but we + // need this mapping because AppKit crashes when passed nil NSStrings. + operator NSString*() const { if (!m_impl) return @""; return *m_impl; } +#endif + +#if PLATFORM(QT) + String(const QString&); + String(const QStringRef&); + operator QString() const; +#endif + +#if PLATFORM(WX) + WTF_EXPORT_PRIVATE String(const wxString&); + WTF_EXPORT_PRIVATE operator wxString() const; +#endif + +#if PLATFORM(BLACKBERRY) + String(const BlackBerry::WebKit::WebString&); + operator BlackBerry::WebKit::WebString() const; +#endif + + // String::fromUTF8 will return a null string if + // the input data contains invalid UTF-8 sequences. + WTF_EXPORT_PRIVATE static String fromUTF8(const LChar*, size_t); + WTF_EXPORT_PRIVATE static String fromUTF8(const LChar*); + static String fromUTF8(const char* s, size_t length) { return fromUTF8(reinterpret_cast(s), length); }; + static String fromUTF8(const char* s) { return fromUTF8(reinterpret_cast(s)); }; + + // Tries to convert the passed in string to UTF-8, but will fall back to Latin-1 if the string is not valid UTF-8. + WTF_EXPORT_PRIVATE static String fromUTF8WithLatin1Fallback(const LChar*, size_t); + static String fromUTF8WithLatin1Fallback(const char* s, size_t length) { return fromUTF8WithLatin1Fallback(reinterpret_cast(s), length); }; + + // Determines the writing direction using the Unicode Bidi Algorithm rules P2 and P3. + WTF::Unicode::Direction defaultWritingDirection(bool* hasStrongDirectionality = 0) const + { + if (m_impl) + return m_impl->defaultWritingDirection(hasStrongDirectionality); + if (hasStrongDirectionality) + *hasStrongDirectionality = false; + return WTF::Unicode::LeftToRight; + } + + bool containsOnlyASCII() const; + bool containsOnlyLatin1() const; + bool containsOnlyWhitespace() const { return !m_impl || m_impl->containsOnlyWhitespace(); } + + // Hash table deleted values, which are only constructed and never copied or destroyed. + String(WTF::HashTableDeletedValueType) : m_impl(WTF::HashTableDeletedValue) { } + bool isHashTableDeletedValue() const { return m_impl.isHashTableDeletedValue(); } + +#ifndef NDEBUG + void show() const; +#endif + +private: + RefPtr m_impl; +}; + +#if PLATFORM(QT) +QDataStream& operator<<(QDataStream& stream, const String& str); +QDataStream& operator>>(QDataStream& stream, String& str); +#endif + +inline String& operator+=(String& a, const String& b) { a.append(b); return a; } + +inline bool operator==(const String& a, const String& b) { return equal(a.impl(), b.impl()); } +inline bool operator==(const String& a, const LChar* b) { return equal(a.impl(), b); } +inline bool operator==(const String& a, const char* b) { return equal(a.impl(), reinterpret_cast(b)); } +inline bool operator==(const LChar* a, const String& b) { return equal(a, b.impl()); } +inline bool operator==(const char* a, const String& b) { return equal(reinterpret_cast(a), b.impl()); } +template +inline bool operator==(const Vector& a, const String& b) { return equal(b.impl(), a.data(), a.size()); } +template +inline bool operator==(const String& a, const Vector& b) { return b == a; } + + +inline bool operator!=(const String& a, const String& b) { return !equal(a.impl(), b.impl()); } +inline bool operator!=(const String& a, const LChar* b) { return !equal(a.impl(), b); } +inline bool operator!=(const String& a, const char* b) { return !equal(a.impl(), reinterpret_cast(b)); } +inline bool operator!=(const LChar* a, const String& b) { return !equal(a, b.impl()); } +inline bool operator!=(const char* a, const String& b) { return !equal(reinterpret_cast(a), b.impl()); } +template +inline bool operator!=(const Vector& a, const String& b) { return !(a == b); } +template +inline bool operator!=(const String& a, const Vector& b) { return b != a; } + +inline bool equalIgnoringCase(const String& a, const String& b) { return equalIgnoringCase(a.impl(), b.impl()); } +inline bool equalIgnoringCase(const String& a, const LChar* b) { return equalIgnoringCase(a.impl(), b); } +inline bool equalIgnoringCase(const String& a, const char* b) { return equalIgnoringCase(a.impl(), reinterpret_cast(b)); } +inline bool equalIgnoringCase(const LChar* a, const String& b) { return equalIgnoringCase(a, b.impl()); } +inline bool equalIgnoringCase(const char* a, const String& b) { return equalIgnoringCase(reinterpret_cast(a), b.impl()); } + +inline bool equalPossiblyIgnoringCase(const String& a, const String& b, bool ignoreCase) +{ + return ignoreCase ? equalIgnoringCase(a, b) : (a == b); +} + +inline bool equalIgnoringNullity(const String& a, const String& b) { return equalIgnoringNullity(a.impl(), b.impl()); } + +template +inline bool equalIgnoringNullity(const Vector& a, const String& b) { return equalIgnoringNullity(a, b.impl()); } + +inline bool operator!(const String& str) { return str.isNull(); } + +inline void swap(String& a, String& b) { a.swap(b); } + +// Definitions of string operations + +template +String::String(const Vector& vector) + : m_impl(vector.size() ? StringImpl::create(vector.data(), vector.size()) : 0) +{ +} + +template<> +inline const LChar* String::getCharacters() const +{ + ASSERT(is8Bit()); + return characters8(); +} + +template<> +inline const UChar* String::getCharacters() const +{ + ASSERT(!is8Bit()); + return characters16(); +} + +inline bool String::containsOnlyLatin1() const +{ + if (isEmpty()) + return true; + + if (is8Bit()) + return true; + + const UChar* characters = characters16(); + UChar ored = 0; + for (size_t i = 0; i < m_impl->length(); ++i) + ored |= characters[i]; + return !(ored & 0xFF00); +} + + +#ifdef __OBJC__ +// This is for situations in WebKit where the long standing behavior has been +// "nil if empty", so we try to maintain longstanding behavior for the sake of +// entrenched clients +inline NSString* nsStringNilIfEmpty(const String& str) { return str.isEmpty() ? nil : (NSString*)str; } +#endif + +inline bool String::containsOnlyASCII() const +{ + if (isEmpty()) + return true; + + if (is8Bit()) + return charactersAreAllASCII(characters8(), m_impl->length()); + + return charactersAreAllASCII(characters16(), m_impl->length()); +} + +WTF_EXPORT_PRIVATE int codePointCompare(const String&, const String&); + +inline bool codePointCompareLessThan(const String& a, const String& b) +{ + return codePointCompare(a.impl(), b.impl()) < 0; +} + +inline size_t find(const LChar* characters, unsigned length, LChar matchCharacter, unsigned index = 0) +{ + while (index < length) { + if (characters[index] == matchCharacter) + return index; + ++index; + } + return notFound; +} + +inline size_t find(const UChar* characters, unsigned length, UChar matchCharacter, unsigned index = 0) +{ + while (index < length) { + if (characters[index] == matchCharacter) + return index; + ++index; + } + return notFound; +} + +inline size_t find(const LChar* characters, unsigned length, CharacterMatchFunctionPtr matchFunction, unsigned index = 0) +{ + while (index < length) { + if (matchFunction(characters[index])) + return index; + ++index; + } + return notFound; +} + +inline size_t find(const UChar* characters, unsigned length, CharacterMatchFunctionPtr matchFunction, unsigned index = 0) +{ + while (index < length) { + if (matchFunction(characters[index])) + return index; + ++index; + } + return notFound; +} + +inline size_t reverseFind(const LChar* characters, unsigned length, LChar matchCharacter, unsigned index = UINT_MAX) +{ + if (!length) + return notFound; + if (index >= length) + index = length - 1; + while (characters[index] != matchCharacter) { + if (!index--) + return notFound; + } + return index; +} + +inline size_t reverseFind(const UChar* characters, unsigned length, UChar matchCharacter, unsigned index = UINT_MAX) +{ + if (!length) + return notFound; + if (index >= length) + index = length - 1; + while (characters[index] != matchCharacter) { + if (!index--) + return notFound; + } + return index; +} + +inline void append(Vector& vector, const String& string) +{ + vector.append(string.characters(), string.length()); +} + +inline void appendNumber(Vector& vector, unsigned char number) +{ + int numberLength = number > 99 ? 3 : (number > 9 ? 2 : 1); + size_t vectorSize = vector.size(); + vector.grow(vectorSize + numberLength); + + switch (numberLength) { + case 3: + vector[vectorSize + 2] = number % 10 + '0'; + number /= 10; + + case 2: + vector[vectorSize + 1] = number % 10 + '0'; + number /= 10; + + case 1: + vector[vectorSize] = number % 10 + '0'; + } +} + +template inline bool isAllSpecialCharacters(const UChar* characters, size_t length) +{ + for (size_t i = 0; i < length; ++i) { + if (!isSpecialCharacter(characters[i])) + return false; + } + return true; +} + +template inline bool String::isAllSpecialCharacters() const +{ + return WTF::isAllSpecialCharacters(characters(), length()); +} + +// StringHash is the default hash for String +template struct DefaultHash; +template<> struct DefaultHash { + typedef StringHash Hash; +}; + +template <> struct VectorTraits : SimpleClassVectorTraits { }; + +// Shared global empty string. +WTF_EXPORT_PRIVATE const String& emptyString(); + +} + +using WTF::CString; +using WTF::String; +using WTF::emptyString; +using WTF::append; +using WTF::appendNumber; +using WTF::charactersAreAllASCII; +using WTF::charactersToIntStrict; +using WTF::charactersToUIntStrict; +using WTF::charactersToInt64Strict; +using WTF::charactersToUInt64Strict; +using WTF::charactersToIntPtrStrict; +using WTF::charactersToInt; +using WTF::charactersToUInt; +using WTF::charactersToInt64; +using WTF::charactersToUInt64; +using WTF::charactersToIntPtr; +using WTF::charactersToDouble; +using WTF::charactersToFloat; +using WTF::equal; +using WTF::equalIgnoringCase; +using WTF::find; +using WTF::isAllSpecialCharacters; +using WTF::isSpaceOrNewline; +using WTF::reverseFind; +using WTF::ShouldRoundDecimalPlaces; + +#include "AtomicString.h" +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/WTFThreadData.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/WTFThreadData.h new file mode 100644 index 000000000..b02d10d7c --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/WTFThreadData.h @@ -0,0 +1,146 @@ +/* + * Copyright (C) 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. + * + */ + +#ifndef WTFThreadData_h +#define WTFThreadData_h + +#include +#include +#include +#include +#include +#include +#include + +#if USE(JSC) +// FIXME: This is a temporary layering violation while we move more string code to WTF. +namespace JSC { + +typedef HashMap, PtrHash > LiteralIdentifierTable; + +class IdentifierTable { + WTF_MAKE_FAST_ALLOCATED; +public: + ~IdentifierTable(); + + std::pair::iterator, bool> add(StringImpl* value); + template + std::pair::iterator, bool> add(U value); + + bool remove(StringImpl* r) + { + HashSet::iterator iter = m_table.find(r); + if (iter == m_table.end()) + return false; + m_table.remove(iter); + return true; + } + + LiteralIdentifierTable& literalTable() { return m_literalTable; } + +private: + HashSet m_table; + LiteralIdentifierTable m_literalTable; +}; + +} +#endif + +namespace WTF { + +class AtomicStringTable; + +typedef void (*AtomicStringTableDestructor)(AtomicStringTable*); + +class WTFThreadData { + WTF_MAKE_NONCOPYABLE(WTFThreadData); +public: + WTF_EXPORT_PRIVATE WTFThreadData(); + WTF_EXPORT_PRIVATE ~WTFThreadData(); + + AtomicStringTable* atomicStringTable() + { + return m_atomicStringTable; + } + +#if USE(JSC) + JSC::IdentifierTable* currentIdentifierTable() + { + return m_currentIdentifierTable; + } + + JSC::IdentifierTable* setCurrentIdentifierTable(JSC::IdentifierTable* identifierTable) + { + JSC::IdentifierTable* oldIdentifierTable = m_currentIdentifierTable; + m_currentIdentifierTable = identifierTable; + return oldIdentifierTable; + } + + void resetCurrentIdentifierTable() + { + m_currentIdentifierTable = m_defaultIdentifierTable; + } + + const StackBounds& stack() const + { + return m_stackBounds; + } +#endif + +private: + AtomicStringTable* m_atomicStringTable; + AtomicStringTableDestructor m_atomicStringTableDestructor; + +#if USE(JSC) + JSC::IdentifierTable* m_defaultIdentifierTable; + JSC::IdentifierTable* m_currentIdentifierTable; + StackBounds m_stackBounds; +#endif + + static WTF_EXPORTDATA ThreadSpecific* staticData; + friend WTFThreadData& wtfThreadData(); + friend class AtomicStringTable; +}; + +inline WTFThreadData& wtfThreadData() +{ + // WRT WebCore: + // WTFThreadData is used on main thread before it could possibly be used + // on secondary ones, so there is no need for synchronization here. + // WRT JavaScriptCore: + // wtfThreadData() is initially called from initializeThreading(), ensuring + // this is initially called in a pthread_once locked context. + if (!WTFThreadData::staticData) + WTFThreadData::staticData = new ThreadSpecific; + return **WTFThreadData::staticData; +} + +} // namespace WTF + +using WTF::WTFThreadData; +using WTF::wtfThreadData; + +#endif // WTFThreadData_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Weak.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Weak.h new file mode 100644 index 000000000..f0c028d71 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Weak.h @@ -0,0 +1,169 @@ +/* + * 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 INC. 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 INC. 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 Weak_h +#define Weak_h + +#include "Assertions.h" +#include "Handle.h" +#include "HandleHeap.h" +#include "JSGlobalData.h" + +namespace JSC { + +// A weakly referenced handle that becomes 0 when the value it points to is garbage collected. +template class Weak : public Handle { + using Handle::slot; + using Handle::setSlot; + +public: + typedef typename Handle::ExternalType ExternalType; + + Weak() + : Handle() + { + } + + Weak(JSGlobalData& globalData, ExternalType value = ExternalType(), WeakHandleOwner* weakOwner = 0, void* context = 0) + : Handle(globalData.heap.handleHeap()->allocate()) + { + HandleHeap::heapFor(slot())->makeWeak(slot(), weakOwner, context); + set(value); + } + + enum AdoptTag { Adopt }; + template Weak(AdoptTag, Handle handle) + : Handle(handle.slot()) + { + validateCell(get()); + } + + Weak(const Weak& other) + : Handle() + { + if (!other.slot()) + return; + setSlot(HandleHeap::heapFor(other.slot())->copyWeak(other.slot())); + } + + template Weak(const Weak& other) + : Handle() + { + if (!other.slot()) + return; + setSlot(HandleHeap::heapFor(other.slot())->copyWeak(other.slot())); + } + + enum HashTableDeletedValueTag { HashTableDeletedValue }; + bool isHashTableDeletedValue() const { return slot() == hashTableDeletedValue(); } + Weak(HashTableDeletedValueTag) + : Handle(hashTableDeletedValue()) + { + } + + ~Weak() + { + clear(); + } + + void swap(Weak& other) + { + Handle::swap(other); + } + + ExternalType get() const { return HandleTypes::getFromSlot(slot()); } + + void clear() + { + if (!slot()) + return; + HandleHeap::heapFor(slot())->deallocate(slot()); + setSlot(0); + } + + void set(JSGlobalData& globalData, ExternalType value, WeakHandleOwner* weakOwner = 0, void* context = 0) + { + if (!slot()) { + setSlot(globalData.heap.handleHeap()->allocate()); + HandleHeap::heapFor(slot())->makeWeak(slot(), weakOwner, context); + } + ASSERT(HandleHeap::heapFor(slot())->hasWeakOwner(slot(), weakOwner)); + set(value); + } + + template Weak& operator=(const Weak& other) + { + clear(); + if (other.slot()) + setSlot(HandleHeap::heapFor(other.slot())->copyWeak(other.slot())); + return *this; + } + + Weak& operator=(const Weak& other) + { + clear(); + if (other.slot()) + setSlot(HandleHeap::heapFor(other.slot())->copyWeak(other.slot())); + return *this; + } + + HandleSlot leakHandle() + { + ASSERT(HandleHeap::heapFor(slot())->hasFinalizer(slot())); + HandleSlot result = slot(); + setSlot(0); + return result; + } + +private: + static HandleSlot hashTableDeletedValue() { return reinterpret_cast(-1); } + + void set(ExternalType externalType) + { + ASSERT(slot()); + JSValue value = HandleTypes::toJSValue(externalType); + HandleHeap::heapFor(slot())->writeBarrier(slot(), value); + *slot() = value; + } +}; + +template inline void swap(Weak& a, Weak& b) +{ + a.swap(b); +} + +} // namespace JSC + +namespace WTF { + +template struct VectorTraits > : SimpleClassVectorTraits { + static const bool canCompareWithMemcmp = false; +}; + +template struct HashTraits > : SimpleClassHashTraits > { }; + +} + +#endif // Weak_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/WeakGCMap.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/WeakGCMap.h new file mode 100644 index 000000000..1bb3cd5bb --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/WeakGCMap.h @@ -0,0 +1,191 @@ +/* + * 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 INC. 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 INC. 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 WeakGCMap_h +#define WeakGCMap_h + +#include "Handle.h" +#include "JSGlobalData.h" +#include + +namespace JSC { + +// A HashMap for GC'd values that removes entries when the associated value +// dies. +template struct DefaultWeakGCMapFinalizerCallback { + static void* finalizerContextFor(KeyType key) + { + return reinterpret_cast(key); + } + + static KeyType keyForFinalizer(void* context, typename HandleTypes::ExternalType) + { + return reinterpret_cast(context); + } +}; + +template, typename HashArg = typename DefaultHash::Hash, typename KeyTraitsArg = HashTraits > +class WeakGCMap : private WeakHandleOwner { + WTF_MAKE_FAST_ALLOCATED; + WTF_MAKE_NONCOPYABLE(WeakGCMap); + + typedef HashMap MapType; + typedef typename HandleTypes::ExternalType ExternalType; + typedef typename MapType::iterator map_iterator; + +public: + + struct iterator { + friend class WeakGCMap; + iterator(map_iterator iter) + : m_iterator(iter) + { + } + + std::pair get() const { return std::make_pair(m_iterator->first, HandleTypes::getFromSlot(m_iterator->second)); } + std::pair getSlot() const { return *m_iterator; } + + iterator& operator++() { ++m_iterator; return *this; } + + // postfix ++ intentionally omitted + + // Comparison. + bool operator==(const iterator& other) const { return m_iterator == other.m_iterator; } + bool operator!=(const iterator& other) const { return m_iterator != other.m_iterator; } + + private: + map_iterator m_iterator; + }; + + WeakGCMap() + { + } + + bool isEmpty() { return m_map.isEmpty(); } + void clear() + { + map_iterator end = m_map.end(); + for (map_iterator ptr = m_map.begin(); ptr != end; ++ptr) + HandleHeap::heapFor(ptr->second)->deallocate(ptr->second); + m_map.clear(); + } + + bool contains(const KeyType& key) const + { + return m_map.contains(key); + } + + iterator find(const KeyType& key) + { + return m_map.find(key); + } + + void remove(iterator iter) + { + ASSERT(iter.m_iterator != m_map.end()); + HandleSlot slot = iter.m_iterator->second; + ASSERT(slot); + HandleHeap::heapFor(slot)->deallocate(slot); + m_map.remove(iter.m_iterator); + } + + ExternalType get(const KeyType& key) const + { + return HandleTypes::getFromSlot(m_map.get(key)); + } + + HandleSlot getSlot(const KeyType& key) const + { + return m_map.get(key); + } + + pair add(JSGlobalData& globalData, const KeyType& key, ExternalType value) + { + pair iter = m_map.add(key, 0); + if (iter.second) { + HandleSlot slot = globalData.heap.handleHeap()->allocate(); + iter.first->second = slot; + HandleHeap::heapFor(slot)->makeWeak(slot, this, FinalizerCallback::finalizerContextFor(key)); + HandleHeap::heapFor(slot)->writeBarrier(slot, value); + *slot = value; + } + return iter; + } + + void set(iterator iter, ExternalType value) + { + HandleSlot slot = iter.m_iterator->second; + ASSERT(slot); + HandleHeap::heapFor(slot)->writeBarrier(slot, value); + *slot = value; + } + + void set(JSGlobalData& globalData, const KeyType& key, ExternalType value) + { + pair iter = m_map.add(key, 0); + HandleSlot slot = iter.first->second; + if (iter.second) { + slot = globalData.heap.handleHeap()->allocate(); + HandleHeap::heapFor(slot)->makeWeak(slot, this, key); + iter.first->second = slot; + } + HandleHeap::heapFor(slot)->writeBarrier(slot, value); + *slot = value; + } + + ExternalType take(const KeyType& key) + { + HandleSlot slot = m_map.take(key); + if (!slot) + return HashTraits::emptyValue(); + ExternalType result = HandleTypes::getFromSlot(slot); + HandleHeap::heapFor(slot)->deallocate(slot); + return result; + } + + size_t size() { return m_map.size(); } + + iterator begin() { return iterator(m_map.begin()); } + iterator end() { return iterator(m_map.end()); } + + ~WeakGCMap() + { + clear(); + } + +private: + virtual void finalize(Handle handle, void* context) + { + HandleSlot slot = m_map.take(FinalizerCallback::keyForFinalizer(context, HandleTypes::getFromSlot(handle.slot()))); + ASSERT(slot); + HandleHeap::heapFor(slot)->deallocate(slot); + } + + MapType m_map; +}; + +} // namespace JSC + +#endif // WeakGCMap_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/WeakRandom.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/WeakRandom.h new file mode 100644 index 000000000..6083980d2 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/WeakRandom.h @@ -0,0 +1,91 @@ +/* + * 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 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 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. + * + * + * Copyright (c) 2009 Ian C. Bullard + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef WeakRandom_h +#define WeakRandom_h + +#include +#include + +namespace JSC { + +class WeakRandom { +public: + WeakRandom(unsigned seed) + : m_low(seed ^ 0x49616E42) + , m_high(seed) + { + } + + double get() + { + return advance() / (UINT_MAX + 1.0); + } + + unsigned getUint32() + { + return advance(); + } + +private: + unsigned advance() + { + m_high = (m_high << 16) + (m_high >> 16); + m_high += m_low; + m_low += m_high; + return m_high; + } + + unsigned m_low; + unsigned m_high; +}; + +} // namespace JSC + +#endif // WeakRandom_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/WeakReferenceHarvester.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/WeakReferenceHarvester.h new file mode 100644 index 000000000..90b4deed0 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/WeakReferenceHarvester.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef WeakReferenceHarvester_h +#define WeakReferenceHarvester_h + +#include "ListableHandler.h" + +namespace JSC { + +class MarkStack; +class MarkStackSharedData; +class SlotVisitor; + +class WeakReferenceHarvester : public ListableHandler { +public: + virtual void visitWeakReferences(SlotVisitor&) = 0; + +protected: + WeakReferenceHarvester() + { + } + + virtual ~WeakReferenceHarvester() { } +}; + +} // namespace JSC + +#endif // WeakReferenceHarvester_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/WriteBarrier.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/WriteBarrier.h new file mode 100644 index 000000000..a7bd7a100 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/WriteBarrier.h @@ -0,0 +1,231 @@ +/* + * Copyright (C) 2011 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 INC. 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 INC. 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 WriteBarrier_h +#define WriteBarrier_h + +#include "HandleTypes.h" +#include "Heap.h" +#include "SamplingCounter.h" +#include "TypeTraits.h" + +namespace JSC { + +class JSCell; +class JSGlobalData; +class JSGlobalObject; + +template class WriteBarrierBase; +template<> class WriteBarrierBase; + +JS_EXPORT_PRIVATE void slowValidateCell(JSCell*); +JS_EXPORT_PRIVATE void slowValidateCell(JSGlobalObject*); + +#if ENABLE(GC_VALIDATION) +template inline void validateCell(T cell) +{ + ASSERT_GC_OBJECT_INHERITS(cell, &WTF::RemovePointer::Type::s_info); +} + +template<> inline void validateCell(JSCell* cell) +{ + slowValidateCell(cell); +} + +template<> inline void validateCell(JSGlobalObject* globalObject) +{ + slowValidateCell(globalObject); +} +#else +template inline void validateCell(T) +{ +} +#endif + +// We have a separate base class with no constructors for use in Unions. +template class WriteBarrierBase { +public: + void set(JSGlobalData& globalData, const JSCell* owner, T* value) + { + ASSERT(value); + validateCell(value); + setEarlyValue(globalData, owner, value); + } + + void setMayBeNull(JSGlobalData& globalData, const JSCell* owner, T* value) + { + if (value) + validateCell(value); + setEarlyValue(globalData, owner, value); + } + + // Should only be used by JSCell during early initialisation + // when some basic types aren't yet completely instantiated + void setEarlyValue(JSGlobalData&, const JSCell* owner, T* value) + { + this->m_cell = reinterpret_cast(value); + Heap::writeBarrier(owner, this->m_cell); + } + + T* get() const + { + if (m_cell) + validateCell(m_cell); + return reinterpret_cast(m_cell); + } + + T* operator*() const + { + ASSERT(m_cell); + validateCell(static_cast(m_cell)); + return static_cast(m_cell); + } + + T* operator->() const + { + ASSERT(m_cell); + validateCell(static_cast(m_cell)); + return static_cast(m_cell); + } + + void clear() { m_cell = 0; } + + JSCell** slot() { return &m_cell; } + + typedef T* (WriteBarrierBase::*UnspecifiedBoolType); + operator UnspecifiedBoolType*() const { return m_cell ? reinterpret_cast(1) : 0; } + + bool operator!() const { return !m_cell; } + + void setWithoutWriteBarrier(T* value) + { +#if ENABLE(WRITE_BARRIER_PROFILING) + WriteBarrierCounters::usesWithoutBarrierFromCpp.count(); +#endif + this->m_cell = reinterpret_cast(value); + } + +#if ENABLE(GC_VALIDATION) + T* unvalidatedGet() const { return reinterpret_cast(m_cell); } +#endif + +private: + JSCell* m_cell; +}; + +template <> class WriteBarrierBase { +public: + void set(JSGlobalData&, const JSCell* owner, JSValue value) + { + m_value = JSValue::encode(value); + Heap::writeBarrier(owner, value); + } + + void setWithoutWriteBarrier(JSValue value) + { + m_value = JSValue::encode(value); + } + + JSValue get() const + { + return JSValue::decode(m_value); + } + void clear() { m_value = JSValue::encode(JSValue()); } + void setUndefined() { m_value = JSValue::encode(jsUndefined()); } + bool isNumber() const { return get().isNumber(); } + bool isObject() const { return get().isObject(); } + bool isNull() const { return get().isNull(); } + bool isGetterSetter() const { return get().isGetterSetter(); } + + JSValue* slot() + { + union { + EncodedJSValue* v; + JSValue* slot; + } u; + u.v = &m_value; + return u.slot; + } + + typedef JSValue (WriteBarrierBase::*UnspecifiedBoolType); + operator UnspecifiedBoolType*() const { return get() ? reinterpret_cast(1) : 0; } + bool operator!() const { return !get(); } + +private: + EncodedJSValue m_value; +}; + +template class WriteBarrier : public WriteBarrierBase { +public: + WriteBarrier() + { + this->setWithoutWriteBarrier(0); + } + + WriteBarrier(JSGlobalData& globalData, const JSCell* owner, T* value) + { + this->set(globalData, owner, value); + } + + enum MayBeNullTag { MayBeNull }; + WriteBarrier(JSGlobalData& globalData, const JSCell* owner, T* value, MayBeNullTag) + { + this->setMayBeNull(globalData, owner, value); + } +}; + +template <> class WriteBarrier : public WriteBarrierBase { +public: + WriteBarrier() + { + this->setWithoutWriteBarrier(JSValue()); + } + + WriteBarrier(JSGlobalData& globalData, const JSCell* owner, JSValue value) + { + this->set(globalData, owner, value); + } +}; + +template inline bool operator==(const WriteBarrierBase& lhs, const WriteBarrierBase& rhs) +{ + return lhs.get() == rhs.get(); +} + +// MarkStack functions + +template inline void MarkStack::append(WriteBarrierBase* slot) +{ + internalAppend(*slot->slot()); +} + +ALWAYS_INLINE void MarkStack::appendValues(WriteBarrierBase* barriers, size_t count) +{ + append(barriers->slot(), count); +} + +} // namespace JSC + +#endif // WriteBarrier_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/WriteBarrierSupport.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/WriteBarrierSupport.h new file mode 100644 index 000000000..5d7d2f6fe --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/WriteBarrierSupport.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2011 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 INC. 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 INC. 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 WriteBarrierSupport_h +#define WriteBarrierSupport_h + +#include "SamplingCounter.h" +#include + +namespace JSC { + +// This allows the JIT to distinguish between uses of the barrier for different +// kinds of writes. This is used by the JIT for profiling, and may be appropriate +// for allowing the GC implementation to specialize the JIT's write barrier code +// for different kinds of target objects. +enum WriteBarrierUseKind { + // This allows specialization for access to the property storage (either + // array element or property), but not for any other kind of property + // accesses (such as writes that are a consequence of setter execution). + WriteBarrierForPropertyAccess, + + // This allows specialization for variable accesses (such as global or + // scoped variables). + WriteBarrierForVariableAccess, + + // This captures all other forms of write barriers. It should always be + // correct to use a generic access write barrier, even when storing to + // properties. Hence, if optimization is not necessary, it is preferable + // to just use a generic access. + WriteBarrierForGenericAccess +}; + +class WriteBarrierCounters { +private: + WriteBarrierCounters() { } + +public: +#if ENABLE(WRITE_BARRIER_PROFILING) + static GlobalSamplingCounter usesWithBarrierFromCpp; + static GlobalSamplingCounter usesWithoutBarrierFromCpp; + static GlobalSamplingCounter usesWithBarrierFromJit; + static GlobalSamplingCounter usesForPropertiesFromJit; + static GlobalSamplingCounter usesForVariablesFromJit; + static GlobalSamplingCounter usesWithoutBarrierFromJit; + + static void initialize(); + + static GlobalSamplingCounter& jitCounterFor(WriteBarrierUseKind useKind) + { + switch (useKind) { + case WriteBarrierForPropertyAccess: + return usesForPropertiesFromJit; + case WriteBarrierForVariableAccess: + return usesForVariablesFromJit; + default: + ASSERT(useKind == WriteBarrierForGenericAccess); + return usesWithBarrierFromJit; + } + } +#else + // These are necessary to work around not having conditional exports. + JS_EXPORTDATA static char usesWithBarrierFromCpp; + JS_EXPORTDATA static char usesWithoutBarrierFromCpp; +#endif // ENABLE(WRITE_BARRIER_PROFILING) + + static void countWriteBarrier() + { +#if ENABLE(WRITE_BARRIER_PROFILING) + WriteBarrierCounters::usesWithBarrierFromCpp.count(); +#endif + } +}; + +} // namespace JSC + +#endif // WriteBarrierSupport_h + diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Yarr.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Yarr.h new file mode 100644 index 000000000..3495fc7e4 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/Yarr.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2010 Peter Varga (pvarga@inf.u-szeged.hu), University of Szeged + * 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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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 Yarr_h +#define Yarr_h + +#include "YarrInterpreter.h" +#include "YarrPattern.h" + +namespace JSC { namespace Yarr { + +#define YarrStackSpaceForBackTrackInfoPatternCharacter 1 // Only for !fixed quantifiers. +#define YarrStackSpaceForBackTrackInfoCharacterClass 1 // Only for !fixed quantifiers. +#define YarrStackSpaceForBackTrackInfoBackReference 2 +#define YarrStackSpaceForBackTrackInfoAlternative 1 // One per alternative. +#define YarrStackSpaceForBackTrackInfoParentheticalAssertion 1 +#define YarrStackSpaceForBackTrackInfoParenthesesOnce 1 // Only for !fixed quantifiers. +#define YarrStackSpaceForBackTrackInfoParenthesesTerminal 1 +#define YarrStackSpaceForBackTrackInfoParentheses 2 + +static const unsigned quantifyInfinite = UINT_MAX; + +// The below limit restricts the number of "recursive" match calls in order to +// avoid spending exponential time on complex regular expressions. +static const unsigned matchLimit = 1000000; + +enum JSRegExpResult { + JSRegExpMatch = 1, + JSRegExpNoMatch = 0, + JSRegExpErrorNoMatch = -1, + JSRegExpErrorHitLimit = -2, + JSRegExpErrorNoMemory = -3, + JSRegExpErrorInternal = -4 +}; + +enum YarrCharSize { + Char8, + Char16 +}; + +JS_EXPORT_PRIVATE PassOwnPtr byteCompile(YarrPattern&, BumpPointerAllocator*); +JS_EXPORT_PRIVATE int interpret(BytecodePattern*, const UString& input, unsigned start, unsigned length, int* output); + +} } // namespace JSC::Yarr + +#endif // Yarr_h + diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/YarrInterpreter.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/YarrInterpreter.h new file mode 100644 index 000000000..eb5fdc6dc --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/YarrInterpreter.h @@ -0,0 +1,380 @@ +/* + * Copyright (C) 2009, 2010 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 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 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 YarrInterpreter_h +#define YarrInterpreter_h + +#include "YarrPattern.h" +#include +#include + +namespace WTF { +class BumpPointerAllocator; +} +using WTF::BumpPointerAllocator; + +namespace JSC { namespace Yarr { + +class ByteDisjunction; + +struct ByteTerm { + enum Type { + TypeBodyAlternativeBegin, + TypeBodyAlternativeDisjunction, + TypeBodyAlternativeEnd, + TypeAlternativeBegin, + TypeAlternativeDisjunction, + TypeAlternativeEnd, + TypeSubpatternBegin, + TypeSubpatternEnd, + TypeAssertionBOL, + TypeAssertionEOL, + TypeAssertionWordBoundary, + TypePatternCharacterOnce, + TypePatternCharacterFixed, + TypePatternCharacterGreedy, + TypePatternCharacterNonGreedy, + TypePatternCasedCharacterOnce, + TypePatternCasedCharacterFixed, + TypePatternCasedCharacterGreedy, + TypePatternCasedCharacterNonGreedy, + TypeCharacterClass, + TypeBackReference, + TypeParenthesesSubpattern, + TypeParenthesesSubpatternOnceBegin, + TypeParenthesesSubpatternOnceEnd, + TypeParenthesesSubpatternTerminalBegin, + TypeParenthesesSubpatternTerminalEnd, + TypeParentheticalAssertionBegin, + TypeParentheticalAssertionEnd, + TypeCheckInput, + TypeUncheckInput, + TypeDotStarEnclosure, + } type; + union { + struct { + union { + UChar patternCharacter; + struct { + UChar lo; + UChar hi; + } casedCharacter; + CharacterClass* characterClass; + unsigned subpatternId; + }; + union { + ByteDisjunction* parenthesesDisjunction; + unsigned parenthesesWidth; + }; + QuantifierType quantityType; + unsigned quantityCount; + } atom; + struct { + int next; + int end; + bool onceThrough; + } alternative; + struct { + bool m_bol : 1; + bool m_eol : 1; + } anchors; + unsigned checkInputCount; + }; + unsigned frameLocation; + bool m_capture : 1; + bool m_invert : 1; + int inputPosition; + + ByteTerm(UChar ch, int inputPos, unsigned frameLocation, Checked quantityCount, QuantifierType quantityType) + : frameLocation(frameLocation) + , m_capture(false) + , m_invert(false) + { + switch (quantityType) { + case QuantifierFixedCount: + type = (quantityCount == 1) ? ByteTerm::TypePatternCharacterOnce : ByteTerm::TypePatternCharacterFixed; + break; + case QuantifierGreedy: + type = ByteTerm::TypePatternCharacterGreedy; + break; + case QuantifierNonGreedy: + type = ByteTerm::TypePatternCharacterNonGreedy; + break; + } + + atom.patternCharacter = ch; + atom.quantityType = quantityType; + atom.quantityCount = quantityCount.unsafeGet(); + inputPosition = inputPos; + } + + ByteTerm(UChar lo, UChar hi, int inputPos, unsigned frameLocation, Checked quantityCount, QuantifierType quantityType) + : frameLocation(frameLocation) + , m_capture(false) + , m_invert(false) + { + switch (quantityType) { + case QuantifierFixedCount: + type = (quantityCount == 1) ? ByteTerm::TypePatternCasedCharacterOnce : ByteTerm::TypePatternCasedCharacterFixed; + break; + case QuantifierGreedy: + type = ByteTerm::TypePatternCasedCharacterGreedy; + break; + case QuantifierNonGreedy: + type = ByteTerm::TypePatternCasedCharacterNonGreedy; + break; + } + + atom.casedCharacter.lo = lo; + atom.casedCharacter.hi = hi; + atom.quantityType = quantityType; + atom.quantityCount = quantityCount.unsafeGet(); + inputPosition = inputPos; + } + + ByteTerm(CharacterClass* characterClass, bool invert, int inputPos) + : type(ByteTerm::TypeCharacterClass) + , m_capture(false) + , m_invert(invert) + { + atom.characterClass = characterClass; + atom.quantityType = QuantifierFixedCount; + atom.quantityCount = 1; + inputPosition = inputPos; + } + + ByteTerm(Type type, unsigned subpatternId, ByteDisjunction* parenthesesInfo, bool capture, int inputPos) + : type(type) + , m_capture(capture) + , m_invert(false) + { + atom.subpatternId = subpatternId; + atom.parenthesesDisjunction = parenthesesInfo; + atom.quantityType = QuantifierFixedCount; + atom.quantityCount = 1; + inputPosition = inputPos; + } + + ByteTerm(Type type, bool invert = false) + : type(type) + , m_capture(false) + , m_invert(invert) + { + atom.quantityType = QuantifierFixedCount; + atom.quantityCount = 1; + } + + ByteTerm(Type type, unsigned subpatternId, bool capture, bool invert, int inputPos) + : type(type) + , m_capture(capture) + , m_invert(invert) + { + atom.subpatternId = subpatternId; + atom.quantityType = QuantifierFixedCount; + atom.quantityCount = 1; + inputPosition = inputPos; + } + + static ByteTerm BOL(int inputPos) + { + ByteTerm term(TypeAssertionBOL); + term.inputPosition = inputPos; + return term; + } + + static ByteTerm CheckInput(Checked count) + { + ByteTerm term(TypeCheckInput); + term.checkInputCount = count.unsafeGet(); + return term; + } + + static ByteTerm UncheckInput(Checked count) + { + ByteTerm term(TypeUncheckInput); + term.checkInputCount = count.unsafeGet(); + return term; + } + + static ByteTerm EOL(int inputPos) + { + ByteTerm term(TypeAssertionEOL); + term.inputPosition = inputPos; + return term; + } + + static ByteTerm WordBoundary(bool invert, int inputPos) + { + ByteTerm term(TypeAssertionWordBoundary, invert); + term.inputPosition = inputPos; + return term; + } + + static ByteTerm BackReference(unsigned subpatternId, int inputPos) + { + return ByteTerm(TypeBackReference, subpatternId, false, false, inputPos); + } + + static ByteTerm BodyAlternativeBegin(bool onceThrough) + { + ByteTerm term(TypeBodyAlternativeBegin); + term.alternative.next = 0; + term.alternative.end = 0; + term.alternative.onceThrough = onceThrough; + return term; + } + + static ByteTerm BodyAlternativeDisjunction(bool onceThrough) + { + ByteTerm term(TypeBodyAlternativeDisjunction); + term.alternative.next = 0; + term.alternative.end = 0; + term.alternative.onceThrough = onceThrough; + return term; + } + + static ByteTerm BodyAlternativeEnd() + { + ByteTerm term(TypeBodyAlternativeEnd); + term.alternative.next = 0; + term.alternative.end = 0; + term.alternative.onceThrough = false; + return term; + } + + static ByteTerm AlternativeBegin() + { + ByteTerm term(TypeAlternativeBegin); + term.alternative.next = 0; + term.alternative.end = 0; + term.alternative.onceThrough = false; + return term; + } + + static ByteTerm AlternativeDisjunction() + { + ByteTerm term(TypeAlternativeDisjunction); + term.alternative.next = 0; + term.alternative.end = 0; + term.alternative.onceThrough = false; + return term; + } + + static ByteTerm AlternativeEnd() + { + ByteTerm term(TypeAlternativeEnd); + term.alternative.next = 0; + term.alternative.end = 0; + term.alternative.onceThrough = false; + return term; + } + + static ByteTerm SubpatternBegin() + { + return ByteTerm(TypeSubpatternBegin); + } + + static ByteTerm SubpatternEnd() + { + return ByteTerm(TypeSubpatternEnd); + } + + static ByteTerm DotStarEnclosure(bool bolAnchor, bool eolAnchor) + { + ByteTerm term(TypeDotStarEnclosure); + term.anchors.m_bol = bolAnchor; + term.anchors.m_eol = eolAnchor; + return term; + } + + bool invert() + { + return m_invert; + } + + bool capture() + { + return m_capture; + } +}; + +class ByteDisjunction { + WTF_MAKE_FAST_ALLOCATED; +public: + ByteDisjunction(unsigned numSubpatterns, unsigned frameSize) + : m_numSubpatterns(numSubpatterns) + , m_frameSize(frameSize) + { + } + + Vector terms; + unsigned m_numSubpatterns; + unsigned m_frameSize; +}; + +struct BytecodePattern { + WTF_MAKE_FAST_ALLOCATED; +public: + BytecodePattern(PassOwnPtr body, Vector allParenthesesInfo, YarrPattern& pattern, BumpPointerAllocator* allocator) + : m_body(body) + , m_ignoreCase(pattern.m_ignoreCase) + , m_multiline(pattern.m_multiline) + , m_allocator(allocator) + { + newlineCharacterClass = pattern.newlineCharacterClass(); + wordcharCharacterClass = pattern.wordcharCharacterClass(); + + m_allParenthesesInfo.append(allParenthesesInfo); + m_userCharacterClasses.append(pattern.m_userCharacterClasses); + // 'Steal' the YarrPattern's CharacterClasses! We clear its + // array, so that it won't delete them on destruction. We'll + // take responsibility for that. + pattern.m_userCharacterClasses.clear(); + } + + ~BytecodePattern() + { + deleteAllValues(m_allParenthesesInfo); + deleteAllValues(m_userCharacterClasses); + } + + OwnPtr m_body; + bool m_ignoreCase; + bool m_multiline; + // Each BytecodePattern is associated with a RegExp, each RegExp is associated + // with a JSGlobalData. Cache a pointer to out JSGlobalData's m_regExpAllocator. + BumpPointerAllocator* m_allocator; + + CharacterClass* newlineCharacterClass; + CharacterClass* wordcharCharacterClass; + +private: + Vector m_allParenthesesInfo; + Vector m_userCharacterClasses; +}; + +} } // namespace JSC::Yarr + +#endif // YarrInterpreter_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/YarrPattern.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/YarrPattern.h new file mode 100644 index 000000000..a31deee67 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/YarrPattern.h @@ -0,0 +1,421 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2010 Peter Varga (pvarga@inf.u-szeged.hu), University of Szeged + * + * 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 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 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 YarrPattern_h +#define YarrPattern_h + +#include +#include +#include +#include +#include + +namespace JSC { namespace Yarr { + +struct PatternDisjunction; + +struct CharacterRange { + UChar begin; + UChar end; + + CharacterRange(UChar begin, UChar end) + : begin(begin) + , end(end) + { + } +}; + +struct CharacterClassTable : RefCounted { + const char* m_table; + bool m_inverted; + static PassRefPtr create(const char* table, bool inverted) + { + return adoptRef(new CharacterClassTable(table, inverted)); + } + +private: + CharacterClassTable(const char* table, bool inverted) + : m_table(table) + , m_inverted(inverted) + { + } +}; + +struct CharacterClass { + WTF_MAKE_FAST_ALLOCATED; +public: + // All CharacterClass instances have to have the full set of matches and ranges, + // they may have an optional table for faster lookups (which must match the + // specified matches and ranges) + CharacterClass(PassRefPtr table) + : m_table(table) + { + } + Vector m_matches; + Vector m_ranges; + Vector m_matchesUnicode; + Vector m_rangesUnicode; + RefPtr m_table; +}; + +enum QuantifierType { + QuantifierFixedCount, + QuantifierGreedy, + QuantifierNonGreedy, +}; + +struct PatternTerm { + enum Type { + TypeAssertionBOL, + TypeAssertionEOL, + TypeAssertionWordBoundary, + TypePatternCharacter, + TypeCharacterClass, + TypeBackReference, + TypeForwardReference, + TypeParenthesesSubpattern, + TypeParentheticalAssertion, + TypeDotStarEnclosure, + } type; + bool m_capture :1; + bool m_invert :1; + union { + UChar patternCharacter; + CharacterClass* characterClass; + unsigned backReferenceSubpatternId; + struct { + PatternDisjunction* disjunction; + unsigned subpatternId; + unsigned lastSubpatternId; + bool isCopy; + bool isTerminal; + } parentheses; + struct { + bool bolAnchor : 1; + bool eolAnchor : 1; + } anchors; + }; + QuantifierType quantityType; + Checked quantityCount; + int inputPosition; + unsigned frameLocation; + + PatternTerm(UChar ch) + : type(PatternTerm::TypePatternCharacter) + , m_capture(false) + , m_invert(false) + { + patternCharacter = ch; + quantityType = QuantifierFixedCount; + quantityCount = 1; + } + + PatternTerm(CharacterClass* charClass, bool invert) + : type(PatternTerm::TypeCharacterClass) + , m_capture(false) + , m_invert(invert) + { + characterClass = charClass; + quantityType = QuantifierFixedCount; + quantityCount = 1; + } + + PatternTerm(Type type, unsigned subpatternId, PatternDisjunction* disjunction, bool capture = false, bool invert = false) + : type(type) + , m_capture(capture) + , m_invert(invert) + { + parentheses.disjunction = disjunction; + parentheses.subpatternId = subpatternId; + parentheses.isCopy = false; + parentheses.isTerminal = false; + quantityType = QuantifierFixedCount; + quantityCount = 1; + } + + PatternTerm(Type type, bool invert = false) + : type(type) + , m_capture(false) + , m_invert(invert) + { + quantityType = QuantifierFixedCount; + quantityCount = 1; + } + + PatternTerm(unsigned spatternId) + : type(TypeBackReference) + , m_capture(false) + , m_invert(false) + { + backReferenceSubpatternId = spatternId; + quantityType = QuantifierFixedCount; + quantityCount = 1; + } + + PatternTerm(bool bolAnchor, bool eolAnchor) + : type(TypeDotStarEnclosure) + , m_capture(false) + , m_invert(false) + { + anchors.bolAnchor = bolAnchor; + anchors.eolAnchor = eolAnchor; + quantityType = QuantifierFixedCount; + quantityCount = 1; + } + + static PatternTerm ForwardReference() + { + return PatternTerm(TypeForwardReference); + } + + static PatternTerm BOL() + { + return PatternTerm(TypeAssertionBOL); + } + + static PatternTerm EOL() + { + return PatternTerm(TypeAssertionEOL); + } + + static PatternTerm WordBoundary(bool invert) + { + return PatternTerm(TypeAssertionWordBoundary, invert); + } + + bool invert() + { + return m_invert; + } + + bool capture() + { + return m_capture; + } + + void quantify(unsigned count, QuantifierType type) + { + quantityCount = count; + quantityType = type; + } +}; + +struct PatternAlternative { + WTF_MAKE_FAST_ALLOCATED; +public: + PatternAlternative(PatternDisjunction* disjunction) + : m_parent(disjunction) + , m_onceThrough(false) + , m_hasFixedSize(false) + , m_startsWithBOL(false) + , m_containsBOL(false) + { + } + + PatternTerm& lastTerm() + { + ASSERT(m_terms.size()); + return m_terms[m_terms.size() - 1]; + } + + void removeLastTerm() + { + ASSERT(m_terms.size()); + m_terms.shrink(m_terms.size() - 1); + } + + void setOnceThrough() + { + m_onceThrough = true; + } + + bool onceThrough() + { + return m_onceThrough; + } + + Vector m_terms; + PatternDisjunction* m_parent; + unsigned m_minimumSize; + bool m_onceThrough : 1; + bool m_hasFixedSize : 1; + bool m_startsWithBOL : 1; + bool m_containsBOL : 1; +}; + +struct PatternDisjunction { + WTF_MAKE_FAST_ALLOCATED; +public: + PatternDisjunction(PatternAlternative* parent = 0) + : m_parent(parent) + , m_hasFixedSize(false) + { + } + + ~PatternDisjunction() + { + deleteAllValues(m_alternatives); + } + + PatternAlternative* addNewAlternative() + { + PatternAlternative* alternative = new PatternAlternative(this); + m_alternatives.append(alternative); + return alternative; + } + + Vector m_alternatives; + PatternAlternative* m_parent; + unsigned m_minimumSize; + unsigned m_callFrameSize; + bool m_hasFixedSize; +}; + +// You probably don't want to be calling these functions directly +// (please to be calling newlineCharacterClass() et al on your +// friendly neighborhood YarrPattern instance to get nicely +// cached copies). +CharacterClass* newlineCreate(); +CharacterClass* digitsCreate(); +CharacterClass* spacesCreate(); +CharacterClass* wordcharCreate(); +CharacterClass* nondigitsCreate(); +CharacterClass* nonspacesCreate(); +CharacterClass* nonwordcharCreate(); + +struct TermChain { + TermChain(PatternTerm term) + : term(term) + {} + + PatternTerm term; + Vector hotTerms; +}; + +struct YarrPattern { + JS_EXPORT_PRIVATE YarrPattern(const UString& pattern, bool ignoreCase, bool multiline, const char** error); + + ~YarrPattern() + { + deleteAllValues(m_disjunctions); + deleteAllValues(m_userCharacterClasses); + } + + void reset() + { + m_numSubpatterns = 0; + m_maxBackReference = 0; + + m_containsBackreferences = false; + m_containsBOL = false; + + newlineCached = 0; + digitsCached = 0; + spacesCached = 0; + wordcharCached = 0; + nondigitsCached = 0; + nonspacesCached = 0; + nonwordcharCached = 0; + + deleteAllValues(m_disjunctions); + m_disjunctions.clear(); + deleteAllValues(m_userCharacterClasses); + m_userCharacterClasses.clear(); + } + + bool containsIllegalBackReference() + { + return m_maxBackReference > m_numSubpatterns; + } + + CharacterClass* newlineCharacterClass() + { + if (!newlineCached) + m_userCharacterClasses.append(newlineCached = newlineCreate()); + return newlineCached; + } + CharacterClass* digitsCharacterClass() + { + if (!digitsCached) + m_userCharacterClasses.append(digitsCached = digitsCreate()); + return digitsCached; + } + CharacterClass* spacesCharacterClass() + { + if (!spacesCached) + m_userCharacterClasses.append(spacesCached = spacesCreate()); + return spacesCached; + } + CharacterClass* wordcharCharacterClass() + { + if (!wordcharCached) + m_userCharacterClasses.append(wordcharCached = wordcharCreate()); + return wordcharCached; + } + CharacterClass* nondigitsCharacterClass() + { + if (!nondigitsCached) + m_userCharacterClasses.append(nondigitsCached = nondigitsCreate()); + return nondigitsCached; + } + CharacterClass* nonspacesCharacterClass() + { + if (!nonspacesCached) + m_userCharacterClasses.append(nonspacesCached = nonspacesCreate()); + return nonspacesCached; + } + CharacterClass* nonwordcharCharacterClass() + { + if (!nonwordcharCached) + m_userCharacterClasses.append(nonwordcharCached = nonwordcharCreate()); + return nonwordcharCached; + } + + bool m_ignoreCase : 1; + bool m_multiline : 1; + bool m_containsBackreferences : 1; + bool m_containsBOL : 1; + unsigned m_numSubpatterns; + unsigned m_maxBackReference; + PatternDisjunction* m_body; + Vector m_disjunctions; + Vector m_userCharacterClasses; + +private: + const char* compile(const UString& patternString); + + CharacterClass* newlineCached; + CharacterClass* digitsCached; + CharacterClass* spacesCached; + CharacterClass* wordcharCached; + CharacterClass* nondigitsCached; + CharacterClass* nonspacesCached; + CharacterClass* nonwordcharCached; +}; + +} } // namespace JSC::Yarr + +#endif // YarrPattern_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/bignum-dtoa.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/bignum-dtoa.h new file mode 100644 index 000000000..076168709 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/bignum-dtoa.h @@ -0,0 +1,86 @@ +// Copyright 2010 the V8 project authors. 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 DOUBLE_CONVERSION_BIGNUM_DTOA_H_ +#define DOUBLE_CONVERSION_BIGNUM_DTOA_H_ + +#include "utils.h" + +namespace WTF { + +namespace double_conversion { + + enum BignumDtoaMode { + // Return the shortest correct representation. + // For example the output of 0.299999999999999988897 is (the less accurate but + // correct) 0.3. + BIGNUM_DTOA_SHORTEST, + // Return a fixed number of digits after the decimal point. + // For instance fixed(0.1, 4) becomes 0.1000 + // If the input number is big, the output will be big. + BIGNUM_DTOA_FIXED, + // Return a fixed number of digits, no matter what the exponent is. + BIGNUM_DTOA_PRECISION + }; + + // Converts the given double 'v' to ascii. + // The result should be interpreted as buffer * 10^(point-length). + // The buffer will be null-terminated. + // + // The input v must be > 0 and different from NaN, and Infinity. + // + // The output depends on the given mode: + // - SHORTEST: produce the least amount of digits for which the internal + // identity requirement is still satisfied. If the digits are printed + // (together with the correct exponent) then reading this number will give + // 'v' again. The buffer will choose the representation that is closest to + // 'v'. If there are two at the same distance, than the number is round up. + // In this mode the 'requested_digits' parameter is ignored. + // - FIXED: produces digits necessary to print a given number with + // 'requested_digits' digits after the decimal point. The produced digits + // might be too short in which case the caller has to fill the gaps with '0's. + // Example: toFixed(0.001, 5) is allowed to return buffer="1", point=-2. + // Halfway cases are rounded up. The call toFixed(0.15, 2) thus returns + // buffer="2", point=0. + // Note: the length of the returned buffer has no meaning wrt the significance + // of its digits. That is, just because it contains '0's does not mean that + // any other digit would not satisfy the internal identity requirement. + // - PRECISION: produces 'requested_digits' where the first digit is not '0'. + // Even though the length of produced digits usually equals + // 'requested_digits', the function is allowed to return fewer digits, in + // which case the caller has to fill the missing digits with '0's. + // Halfway cases are again rounded up. + // 'BignumDtoa' expects the given buffer to be big enough to hold all digits + // and a terminating null-character. + void BignumDtoa(double v, BignumDtoaMode mode, int requested_digits, + Vector buffer, int* length, int* point); + +} // namespace double_conversion + +} // namespace WTF + +#endif // DOUBLE_CONVERSION_BIGNUM_DTOA_H_ diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/bignum.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/bignum.h new file mode 100644 index 000000000..1a750581a --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/bignum.h @@ -0,0 +1,145 @@ +// Copyright 2010 the V8 project authors. 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 DOUBLE_CONVERSION_BIGNUM_H_ +#define DOUBLE_CONVERSION_BIGNUM_H_ + +#include "utils.h" + +namespace WTF { + +namespace double_conversion { + + class Bignum { + public: + // 3584 = 128 * 28. We can represent 2^3584 > 10^1000 accurately. + // This bignum can encode much bigger numbers, since it contains an + // exponent. + static const int kMaxSignificantBits = 3584; + + Bignum(); + void AssignUInt16(uint16_t value); + void AssignUInt64(uint64_t value); + void AssignBignum(const Bignum& other); + + void AssignDecimalString(Vector value); + void AssignHexString(Vector value); + + void AssignPowerUInt16(uint16_t base, int exponent); + + void AddUInt16(uint16_t operand); + void AddUInt64(uint64_t operand); + void AddBignum(const Bignum& other); + // Precondition: this >= other. + void SubtractBignum(const Bignum& other); + + void Square(); + void ShiftLeft(int shift_amount); + void MultiplyByUInt32(uint32_t factor); + void MultiplyByUInt64(uint64_t factor); + void MultiplyByPowerOfTen(int exponent); + void Times10() { return MultiplyByUInt32(10); } + // Pseudocode: + // int result = this / other; + // this = this % other; + // In the worst case this function is in O(this/other). + uint16_t DivideModuloIntBignum(const Bignum& other); + + bool ToHexString(char* buffer, int buffer_size) const; + + static int Compare(const Bignum& a, const Bignum& b); + static bool Equal(const Bignum& a, const Bignum& b) { + return Compare(a, b) == 0; + } + static bool LessEqual(const Bignum& a, const Bignum& b) { + return Compare(a, b) <= 0; + } + static bool Less(const Bignum& a, const Bignum& b) { + return Compare(a, b) < 0; + } + // Returns Compare(a + b, c); + static int PlusCompare(const Bignum& a, const Bignum& b, const Bignum& c); + // Returns a + b == c + static bool PlusEqual(const Bignum& a, const Bignum& b, const Bignum& c) { + return PlusCompare(a, b, c) == 0; + } + // Returns a + b <= c + static bool PlusLessEqual(const Bignum& a, const Bignum& b, const Bignum& c) { + return PlusCompare(a, b, c) <= 0; + } + // Returns a + b < c + static bool PlusLess(const Bignum& a, const Bignum& b, const Bignum& c) { + return PlusCompare(a, b, c) < 0; + } + private: + typedef uint32_t Chunk; + typedef uint64_t DoubleChunk; + + static const int kChunkSize = sizeof(Chunk) * 8; + static const int kDoubleChunkSize = sizeof(DoubleChunk) * 8; + // With bigit size of 28 we loose some bits, but a double still fits easily + // into two chunks, and more importantly we can use the Comba multiplication. + static const int kBigitSize = 28; + static const Chunk kBigitMask = (1 << kBigitSize) - 1; + // Every instance allocates kBigitLength chunks on the stack. Bignums cannot + // grow. There are no checks if the stack-allocated space is sufficient. + static const int kBigitCapacity = kMaxSignificantBits / kBigitSize; + + void EnsureCapacity(int size) { + if (size > kBigitCapacity) { + UNREACHABLE(); + } + } + void Align(const Bignum& other); + void Clamp(); + bool IsClamped() const; + void Zero(); + // Requires this to have enough capacity (no tests done). + // Updates used_digits_ if necessary. + // shift_amount must be < kBigitSize. + void BigitsShiftLeft(int shift_amount); + // BigitLength includes the "hidden" digits encoded in the exponent. + int BigitLength() const { return used_digits_ + exponent_; } + Chunk BigitAt(int index) const; + void SubtractTimes(const Bignum& other, int factor); + + Chunk bigits_buffer_[kBigitCapacity]; + // A vector backed by bigits_buffer_. This way accesses to the array are + // checked for out-of-bounds errors. + Vector bigits_; + int used_digits_; + // The Bignum's value equals value(bigits_) * 2^(exponent_ * kBigitSize). + int exponent_; + + DISALLOW_COPY_AND_ASSIGN(Bignum); + }; + +} // namespace double_conversion + +} // namespace WTF + +#endif // DOUBLE_CONVERSION_BIGNUM_H_ diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/cached-powers.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/cached-powers.h new file mode 100644 index 000000000..cbc04d43d --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/cached-powers.h @@ -0,0 +1,72 @@ +// Copyright 2010 the V8 project authors. 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 DOUBLE_CONVERSION_CACHED_POWERS_H_ +#define DOUBLE_CONVERSION_CACHED_POWERS_H_ + +#include "diy-fp.h" + +namespace WTF { + +namespace double_conversion { + + class PowersOfTenCache { + public: + + // Not all powers of ten are cached. The decimal exponent of two neighboring + // cached numbers will differ by kDecimalExponentDistance. + static int kDecimalExponentDistance; + + static int kMinDecimalExponent; + static int kMaxDecimalExponent; + + // Returns a cached power-of-ten with a binary exponent in the range + // [min_exponent; max_exponent] (boundaries included). + static void GetCachedPowerForBinaryExponentRange(int min_exponent, + int max_exponent, + DiyFp* power, + int* decimal_exponent); + + // Returns a cached power of ten x ~= 10^k such that + // k <= decimal_exponent < k + kCachedPowersDecimalDistance. + // The given decimal_exponent must satisfy + // kMinDecimalExponent <= requested_exponent, and + // requested_exponent < kMaxDecimalExponent + kDecimalExponentDistance. + static void GetCachedPowerForDecimalExponent(int requested_exponent, + DiyFp* power, + int* found_exponent); + }; + + // Initializes the table of cached powers used by the dtoa algorithm. + // This needs to be called when JSC is being initialized. + void initialize(); + +} // namespace double_conversion + +} // namespace WTF + +#endif // DOUBLE_CONVERSION_CACHED_POWERS_H_ diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/config.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/config.h new file mode 100644 index 000000000..ba65476a5 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/config.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006 Samuel Weinig + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H +#ifdef BUILDING_WITH_CMAKE +#include "cmakeconfig.h" +#else +#include "autotoolsconfig.h" +#endif +#endif + +#include +#include +// WTF cannot depend on JSC even if USE(JSC). +#if USE(JSC) && !defined(BUILDING_WTF) +#include "JSExportMacros.h" +#elif PLATFORM(CHROMIUM) +// Chromium doesn't have runtime/ in its include paths. +#include "runtime/JSExportMacros.h" +#endif + +#if OS(WINDOWS) + +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0500 +#endif + +#ifndef WINVER +#define WINVER 0x0500 +#endif + +// If we don't define these, they get defined in windef.h. +// We want to use std::min and std::max +#define max max +#define min min + +#if !COMPILER(MSVC7_OR_LOWER) && !OS(WINCE) +// We need to define this before the first #include of stdlib.h or it won't contain rand_s. +#ifndef _CRT_RAND_S +#define _CRT_RAND_S +#endif +#endif + +#endif + +#if OS(UNIX) || OS(WINDOWS) +#define WTF_USE_OS_RANDOMNESS 1 +#endif + +#if (OS(FREEBSD) || OS(OPENBSD)) && !defined(__GLIBC__) +#define HAVE_PTHREAD_NP_H 1 +#endif + +/* FIXME: if all platforms have these, do they really need #defines? */ +#define HAVE_STDINT_H 1 + +#define WTF_CHANGES 1 + +#ifdef __cplusplus +#undef new +#undef delete +#include +#endif + +// this breaks compilation of , at least, so turn it off for now +// Also generates errors on wx on Windows and QNX, because these functions +// are used from wx and QNX headers. +#if !PLATFORM(QT) && !PLATFORM(WX) && !OS(QNX) +#include +#endif + +#if COMPILER(MSVC) +#define SKIP_STATIC_CONSTRUCTORS_ON_MSVC 1 +#else +#define SKIP_STATIC_CONSTRUCTORS_ON_GCC 1 +#endif diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/diy-fp.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/diy-fp.h new file mode 100644 index 000000000..e843100a8 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/diy-fp.h @@ -0,0 +1,122 @@ +// Copyright 2010 the V8 project authors. 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 DOUBLE_CONVERSION_DIY_FP_H_ +#define DOUBLE_CONVERSION_DIY_FP_H_ + +#include "utils.h" + +namespace WTF { + +namespace double_conversion { + + // This "Do It Yourself Floating Point" class implements a floating-point number + // with a uint64 significand and an int exponent. Normalized DiyFp numbers will + // have the most significant bit of the significand set. + // Multiplication and Subtraction do not normalize their results. + // DiyFp are not designed to contain special doubles (NaN and Infinity). + class DiyFp { + public: + static const int kSignificandSize = 64; + + DiyFp() : f_(0), e_(0) {} + DiyFp(uint64_t f, int e) : f_(f), e_(e) {} + + // this = this - other. + // The exponents of both numbers must be the same and the significand of this + // must be bigger than the significand of other. + // The result will not be normalized. + void Subtract(const DiyFp& other) { + ASSERT(e_ == other.e_); + ASSERT(f_ >= other.f_); + f_ -= other.f_; + } + + // Returns a - b. + // The exponents of both numbers must be the same and this must be bigger + // than other. The result will not be normalized. + static DiyFp Minus(const DiyFp& a, const DiyFp& b) { + DiyFp result = a; + result.Subtract(b); + return result; + } + + + // this = this * other. + void Multiply(const DiyFp& other); + + // returns a * b; + static DiyFp Times(const DiyFp& a, const DiyFp& b) { + DiyFp result = a; + result.Multiply(b); + return result; + } + + void Normalize() { + ASSERT(f_ != 0); + uint64_t f = f_; + int e = e_; + + // This method is mainly called for normalizing boundaries. In general + // boundaries need to be shifted by 10 bits. We thus optimize for this case. + const uint64_t k10MSBits = UINT64_2PART_C(0xFFC00000, 00000000); + while ((f & k10MSBits) == 0) { + f <<= 10; + e -= 10; + } + while ((f & kUint64MSB) == 0) { + f <<= 1; + e--; + } + f_ = f; + e_ = e; + } + + static DiyFp Normalize(const DiyFp& a) { + DiyFp result = a; + result.Normalize(); + return result; + } + + uint64_t f() const { return f_; } + int e() const { return e_; } + + void set_f(uint64_t new_value) { f_ = new_value; } + void set_e(int new_value) { e_ = new_value; } + + private: + static const uint64_t kUint64MSB = UINT64_2PART_C(0x80000000, 00000000); + + uint64_t f_; + int e_; + }; + +} // namespace double_conversion + +} // namespace WTF + +#endif // DOUBLE_CONVERSION_DIY_FP_H_ diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/double-conversion.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/double-conversion.h new file mode 100644 index 000000000..4d6fc2f57 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/double-conversion.h @@ -0,0 +1,502 @@ +// Copyright 2010 the V8 project authors. 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 DOUBLE_CONVERSION_DOUBLE_CONVERSION_H_ +#define DOUBLE_CONVERSION_DOUBLE_CONVERSION_H_ + +#include "utils.h" + +namespace WTF { + +namespace double_conversion { + + class DoubleToStringConverter { + public: + // When calling ToFixed with a double > 10^kMaxFixedDigitsBeforePoint + // or a requested_digits parameter > kMaxFixedDigitsAfterPoint then the + // function returns false. + static const int kMaxFixedDigitsBeforePoint = 60; + static const int kMaxFixedDigitsAfterPoint = 60; + + // When calling ToExponential with a requested_digits + // parameter > kMaxExponentialDigits then the function returns false. + static const int kMaxExponentialDigits = 120; + + // When calling ToPrecision with a requested_digits + // parameter < kMinPrecisionDigits or requested_digits > kMaxPrecisionDigits + // then the function returns false. + static const int kMinPrecisionDigits = 1; + static const int kMaxPrecisionDigits = 120; + + enum Flags { + NO_FLAGS = 0, + EMIT_POSITIVE_EXPONENT_SIGN = 1, + EMIT_TRAILING_DECIMAL_POINT = 2, + EMIT_TRAILING_ZERO_AFTER_POINT = 4, + UNIQUE_ZERO = 8 + }; + + // Flags should be a bit-or combination of the possible Flags-enum. + // - NO_FLAGS: no special flags. + // - EMIT_POSITIVE_EXPONENT_SIGN: when the number is converted into exponent + // form, emits a '+' for positive exponents. Example: 1.2e+2. + // - EMIT_TRAILING_DECIMAL_POINT: when the input number is an integer and is + // converted into decimal format then a trailing decimal point is appended. + // Example: 2345.0 is converted to "2345.". + // - EMIT_TRAILING_ZERO_AFTER_POINT: in addition to a trailing decimal point + // emits a trailing '0'-character. This flag requires the + // EXMIT_TRAILING_DECIMAL_POINT flag. + // Example: 2345.0 is converted to "2345.0". + // - UNIQUE_ZERO: "-0.0" is converted to "0.0". + // + // Infinity symbol and nan_symbol provide the string representation for these + // special values. If the string is NULL and the special value is encountered + // then the conversion functions return false. + // + // The exponent_character is used in exponential representations. It is + // usually 'e' or 'E'. + // + // When converting to the shortest representation the converter will + // represent input numbers in decimal format if they are in the interval + // [10^decimal_in_shortest_low; 10^decimal_in_shortest_high[ + // (lower boundary included, greater boundary excluded). + // Example: with decimal_in_shortest_low = -6 and + // decimal_in_shortest_high = 21: + // ToShortest(0.000001) -> "0.000001" + // ToShortest(0.0000001) -> "1e-7" + // ToShortest(111111111111111111111.0) -> "111111111111111110000" + // ToShortest(100000000000000000000.0) -> "100000000000000000000" + // ToShortest(1111111111111111111111.0) -> "1.1111111111111111e+21" + // + // When converting to precision mode the converter may add + // max_leading_padding_zeroes before returning the number in exponential + // format. + // Example with max_leading_padding_zeroes_in_precision_mode = 6. + // ToPrecision(0.0000012345, 2) -> "0.0000012" + // ToPrecision(0.00000012345, 2) -> "1.2e-7" + // Similarily the converter may add up to + // max_trailing_padding_zeroes_in_precision_mode in precision mode to avoid + // returning an exponential representation. A zero added by the + // EMIT_TRAILING_ZERO_AFTER_POINT flag is counted for this limit. + // Examples for max_trailing_padding_zeroes_in_precision_mode = 1: + // ToPrecision(230.0, 2) -> "230" + // ToPrecision(230.0, 2) -> "230." with EMIT_TRAILING_DECIMAL_POINT. + // ToPrecision(230.0, 2) -> "2.3e2" with EMIT_TRAILING_ZERO_AFTER_POINT. + DoubleToStringConverter(int flags, + const char* infinity_symbol, + const char* nan_symbol, + char exponent_character, + int decimal_in_shortest_low, + int decimal_in_shortest_high, + int max_leading_padding_zeroes_in_precision_mode, + int max_trailing_padding_zeroes_in_precision_mode) + : flags_(flags), + infinity_symbol_(infinity_symbol), + nan_symbol_(nan_symbol), + exponent_character_(exponent_character), + decimal_in_shortest_low_(decimal_in_shortest_low), + decimal_in_shortest_high_(decimal_in_shortest_high), + max_leading_padding_zeroes_in_precision_mode_( + max_leading_padding_zeroes_in_precision_mode), + max_trailing_padding_zeroes_in_precision_mode_( + max_trailing_padding_zeroes_in_precision_mode) { + // When 'trailing zero after the point' is set, then 'trailing point' + // must be set too. + ASSERT(((flags & EMIT_TRAILING_DECIMAL_POINT) != 0) || + !((flags & EMIT_TRAILING_ZERO_AFTER_POINT) != 0)); + } + + // Returns a converter following the EcmaScript specification. + static const DoubleToStringConverter& EcmaScriptConverter(); + + // Computes the shortest string of digits that correctly represent the input + // number. Depending on decimal_in_shortest_low and decimal_in_shortest_high + // (see constructor) it then either returns a decimal representation, or an + // exponential representation. + // Example with decimal_in_shortest_low = -6, + // decimal_in_shortest_high = 21, + // EMIT_POSITIVE_EXPONENT_SIGN activated, and + // EMIT_TRAILING_DECIMAL_POINT deactived: + // ToShortest(0.000001) -> "0.000001" + // ToShortest(0.0000001) -> "1e-7" + // ToShortest(111111111111111111111.0) -> "111111111111111110000" + // ToShortest(100000000000000000000.0) -> "100000000000000000000" + // ToShortest(1111111111111111111111.0) -> "1.1111111111111111e+21" + // + // Note: the conversion may round the output if the returned string + // is accurate enough to uniquely identify the input-number. + // For example the most precise representation of the double 9e59 equals + // "899999999999999918767229449717619953810131273674690656206848", but + // the converter will return the shorter (but still correct) "9e59". + // + // Returns true if the conversion succeeds. The conversion always succeeds + // except when the input value is special and no infinity_symbol or + // nan_symbol has been given to the constructor. + bool ToShortest(double value, StringBuilder* result_builder) const; + + + // Computes a decimal representation with a fixed number of digits after the + // decimal point. The last emitted digit is rounded. + // + // Examples: + // ToFixed(3.12, 1) -> "3.1" + // ToFixed(3.1415, 3) -> "3.142" + // ToFixed(1234.56789, 4) -> "1234.5679" + // ToFixed(1.23, 5) -> "1.23000" + // ToFixed(0.1, 4) -> "0.1000" + // ToFixed(1e30, 2) -> "1000000000000000019884624838656.00" + // ToFixed(0.1, 30) -> "0.100000000000000005551115123126" + // ToFixed(0.1, 17) -> "0.10000000000000001" + // + // If requested_digits equals 0, then the tail of the result depends on + // the EMIT_TRAILING_DECIMAL_POINT and EMIT_TRAILING_ZERO_AFTER_POINT. + // Examples, for requested_digits == 0, + // let EMIT_TRAILING_DECIMAL_POINT and EMIT_TRAILING_ZERO_AFTER_POINT be + // - false and false: then 123.45 -> 123 + // 0.678 -> 1 + // - true and false: then 123.45 -> 123. + // 0.678 -> 1. + // - true and true: then 123.45 -> 123.0 + // 0.678 -> 1.0 + // + // Returns true if the conversion succeeds. The conversion always succeeds + // except for the following cases: + // - the input value is special and no infinity_symbol or nan_symbol has + // been provided to the constructor, + // - 'value' > 10^kMaxFixedDigitsBeforePoint, or + // - 'requested_digits' > kMaxFixedDigitsAfterPoint. + // The last two conditions imply that the result will never contain more than + // 1 + kMaxFixedDigitsBeforePoint + 1 + kMaxFixedDigitsAfterPoint characters + // (one additional character for the sign, and one for the decimal point). + bool ToFixed(double value, + int requested_digits, + StringBuilder* result_builder) const; + + // Computes a representation in exponential format with requested_digits + // after the decimal point. The last emitted digit is rounded. + // If requested_digits equals -1, then the shortest exponential representation + // is computed. + // + // Examples with EMIT_POSITIVE_EXPONENT_SIGN deactivated, and + // exponent_character set to 'e'. + // ToExponential(3.12, 1) -> "3.1e0" + // ToExponential(5.0, 3) -> "5.000e0" + // ToExponential(0.001, 2) -> "1.00e-3" + // ToExponential(3.1415, -1) -> "3.1415e0" + // ToExponential(3.1415, 4) -> "3.1415e0" + // ToExponential(3.1415, 3) -> "3.142e0" + // ToExponential(123456789000000, 3) -> "1.235e14" + // ToExponential(1000000000000000019884624838656.0, -1) -> "1e30" + // ToExponential(1000000000000000019884624838656.0, 32) -> + // "1.00000000000000001988462483865600e30" + // ToExponential(1234, 0) -> "1e3" + // + // Returns true if the conversion succeeds. The conversion always succeeds + // except for the following cases: + // - the input value is special and no infinity_symbol or nan_symbol has + // been provided to the constructor, + // - 'requested_digits' > kMaxExponentialDigits. + // The last condition implies that the result will never contain more than + // kMaxExponentialDigits + 8 characters (the sign, the digit before the + // decimal point, the decimal point, the exponent character, the + // exponent's sign, and at most 3 exponent digits). + bool ToExponential(double value, + int requested_digits, + StringBuilder* result_builder) const; + + // Computes 'precision' leading digits of the given 'value' and returns them + // either in exponential or decimal format, depending on + // max_{leading|trailing}_padding_zeroes_in_precision_mode (given to the + // constructor). + // The last computed digit is rounded. + // + // Example with max_leading_padding_zeroes_in_precision_mode = 6. + // ToPrecision(0.0000012345, 2) -> "0.0000012" + // ToPrecision(0.00000012345, 2) -> "1.2e-7" + // Similarily the converter may add up to + // max_trailing_padding_zeroes_in_precision_mode in precision mode to avoid + // returning an exponential representation. A zero added by the + // EMIT_TRAILING_ZERO_AFTER_POINT flag is counted for this limit. + // Examples for max_trailing_padding_zeroes_in_precision_mode = 1: + // ToPrecision(230.0, 2) -> "230" + // ToPrecision(230.0, 2) -> "230." with EMIT_TRAILING_DECIMAL_POINT. + // ToPrecision(230.0, 2) -> "2.3e2" with EMIT_TRAILING_ZERO_AFTER_POINT. + // Examples for max_trailing_padding_zeroes_in_precision_mode = 3, and no + // EMIT_TRAILING_ZERO_AFTER_POINT: + // ToPrecision(123450.0, 6) -> "123450" + // ToPrecision(123450.0, 5) -> "123450" + // ToPrecision(123450.0, 4) -> "123500" + // ToPrecision(123450.0, 3) -> "123000" + // ToPrecision(123450.0, 2) -> "1.2e5" + // + // Returns true if the conversion succeeds. The conversion always succeeds + // except for the following cases: + // - the input value is special and no infinity_symbol or nan_symbol has + // been provided to the constructor, + // - precision < kMinPericisionDigits + // - precision > kMaxPrecisionDigits + // The last condition implies that the result will never contain more than + // kMaxPrecisionDigits + 7 characters (the sign, the decimal point, the + // exponent character, the exponent's sign, and at most 3 exponent digits). + bool ToPrecision(double value, + int precision, + StringBuilder* result_builder) const; + + enum DtoaMode { + // Produce the shortest correct representation. + // For example the output of 0.299999999999999988897 is (the less accurate + // but correct) 0.3. + SHORTEST, + // Produce a fixed number of digits after the decimal point. + // For instance fixed(0.1, 4) becomes 0.1000 + // If the input number is big, the output will be big. + FIXED, + // Fixed number of digits (independent of the decimal point). + PRECISION + }; + + // The maximal number of digits that are needed to emit a double in base 10. + // A higher precision can be achieved by using more digits, but the shortest + // accurate representation of any double will never use more digits than + // kBase10MaximalLength. + // Note that DoubleToAscii null-terminates its input. So the given buffer + // should be at least kBase10MaximalLength + 1 characters long. + static const int kBase10MaximalLength = 17; + + // Converts the given double 'v' to ascii. + // The result should be interpreted as buffer * 10^(point-length). + // + // The output depends on the given mode: + // - SHORTEST: produce the least amount of digits for which the internal + // identity requirement is still satisfied. If the digits are printed + // (together with the correct exponent) then reading this number will give + // 'v' again. The buffer will choose the representation that is closest to + // 'v'. If there are two at the same distance, than the one farther away + // from 0 is chosen (halfway cases - ending with 5 - are rounded up). + // In this mode the 'requested_digits' parameter is ignored. + // - FIXED: produces digits necessary to print a given number with + // 'requested_digits' digits after the decimal point. The produced digits + // might be too short in which case the caller has to fill the remainder + // with '0's. + // Example: toFixed(0.001, 5) is allowed to return buffer="1", point=-2. + // Halfway cases are rounded towards +/-Infinity (away from 0). The call + // toFixed(0.15, 2) thus returns buffer="2", point=0. + // The returned buffer may contain digits that would be truncated from the + // shortest representation of the input. + // - PRECISION: produces 'requested_digits' where the first digit is not '0'. + // Even though the length of produced digits usually equals + // 'requested_digits', the function is allowed to return fewer digits, in + // which case the caller has to fill the missing digits with '0's. + // Halfway cases are again rounded away from 0. + // DoubleToAscii expects the given buffer to be big enough to hold all + // digits and a terminating null-character. In SHORTEST-mode it expects a + // buffer of at least kBase10MaximalLength + 1. In all other modes the + // requested_digits parameter (+ 1 for the null-character) limits the size of + // the output. The given length is only used in debug mode to ensure the + // buffer is big enough. + static void DoubleToAscii(double v, + DtoaMode mode, + int requested_digits, + char* buffer, + int buffer_length, + bool* sign, + int* length, + int* point); + + private: + // If the value is a special value (NaN or Infinity) constructs the + // corresponding string using the configured infinity/nan-symbol. + // If either of them is NULL or the value is not special then the + // function returns false. + bool HandleSpecialValues(double value, StringBuilder* result_builder) const; + // Constructs an exponential representation (i.e. 1.234e56). + // The given exponent assumes a decimal point after the first decimal digit. + void CreateExponentialRepresentation(const char* decimal_digits, + int length, + int exponent, + StringBuilder* result_builder) const; + // Creates a decimal representation (i.e 1234.5678). + void CreateDecimalRepresentation(const char* decimal_digits, + int length, + int decimal_point, + int digits_after_point, + StringBuilder* result_builder) const; + + const int flags_; + const char* const infinity_symbol_; + const char* const nan_symbol_; + const char exponent_character_; + const int decimal_in_shortest_low_; + const int decimal_in_shortest_high_; + const int max_leading_padding_zeroes_in_precision_mode_; + const int max_trailing_padding_zeroes_in_precision_mode_; + + DISALLOW_IMPLICIT_CONSTRUCTORS(DoubleToStringConverter); + }; + + + class StringToDoubleConverter { + public: + // Enumeration for allowing octals and ignoring junk when converting + // strings to numbers. + enum Flags { + NO_FLAGS = 0, + ALLOW_HEX = 1, + ALLOW_OCTALS = 2, + ALLOW_TRAILING_JUNK = 4, + ALLOW_LEADING_SPACES = 8, + ALLOW_TRAILING_SPACES = 16, + ALLOW_SPACES_AFTER_SIGN = 32 + }; + + // Flags should be a bit-or combination of the possible Flags-enum. + // - NO_FLAGS: no special flags. + // - ALLOW_HEX: recognizes the prefix "0x". Hex numbers may only be integers. + // Ex: StringToDouble("0x1234") -> 4660.0 + // In StringToDouble("0x1234.56") the characters ".56" are trailing + // junk. The result of the call is hence dependent on + // the ALLOW_TRAILING_JUNK flag and/or the junk value. + // With this flag "0x" is a junk-string. Even with ALLOW_TRAILING_JUNK, + // the string will not be parsed as "0" followed by junk. + // + // - ALLOW_OCTALS: recognizes the prefix "0" for octals: + // If a sequence of octal digits starts with '0', then the number is + // read as octal integer. Octal numbers may only be integers. + // Ex: StringToDouble("01234") -> 668.0 + // StringToDouble("012349") -> 12349.0 // Not a sequence of octal + // // digits. + // In StringToDouble("01234.56") the characters ".56" are trailing + // junk. The result of the call is hence dependent on + // the ALLOW_TRAILING_JUNK flag and/or the junk value. + // In StringToDouble("01234e56") the characters "e56" are trailing + // junk, too. + // - ALLOW_TRAILING_JUNK: ignore trailing characters that are not part of + // a double literal. + // - ALLOW_LEADING_SPACES: skip over leading spaces. + // - ALLOW_TRAILING_SPACES: ignore trailing spaces. + // - ALLOW_SPACES_AFTER_SIGN: ignore spaces after the sign. + // Ex: StringToDouble("- 123.2") -> -123.2. + // StringToDouble("+ 123.2") -> 123.2 + // + // empty_string_value is returned when an empty string is given as input. + // If ALLOW_LEADING_SPACES or ALLOW_TRAILING_SPACES are set, then a string + // containing only spaces is converted to the 'empty_string_value', too. + // + // junk_string_value is returned when + // a) ALLOW_TRAILING_JUNK is not set, and a junk character (a character not + // part of a double-literal) is found. + // b) ALLOW_TRAILING_JUNK is set, but the string does not start with a + // double literal. + // + // infinity_symbol and nan_symbol are strings that are used to detect + // inputs that represent infinity and NaN. They can be null, in which case + // they are ignored. + // The conversion routine first reads any possible signs. Then it compares the + // following character of the input-string with the first character of + // the infinity, and nan-symbol. If either matches, the function assumes, that + // a match has been found, and expects the following input characters to match + // the remaining characters of the special-value symbol. + // This means that the following restrictions apply to special-value symbols: + // - they must not start with signs ('+', or '-'), + // - they must not have the same first character. + // - they must not start with digits. + // + // Examples: + // flags = ALLOW_HEX | ALLOW_TRAILING_JUNK, + // empty_string_value = 0.0, + // junk_string_value = NaN, + // infinity_symbol = "infinity", + // nan_symbol = "nan": + // StringToDouble("0x1234") -> 4660.0. + // StringToDouble("0x1234K") -> 4660.0. + // StringToDouble("") -> 0.0 // empty_string_value. + // StringToDouble(" ") -> NaN // junk_string_value. + // StringToDouble(" 1") -> NaN // junk_string_value. + // StringToDouble("0x") -> NaN // junk_string_value. + // StringToDouble("-123.45") -> -123.45. + // StringToDouble("--123.45") -> NaN // junk_string_value. + // StringToDouble("123e45") -> 123e45. + // StringToDouble("123E45") -> 123e45. + // StringToDouble("123e+45") -> 123e45. + // StringToDouble("123E-45") -> 123e-45. + // StringToDouble("123e") -> 123.0 // trailing junk ignored. + // StringToDouble("123e-") -> 123.0 // trailing junk ignored. + // StringToDouble("+NaN") -> NaN // NaN string literal. + // StringToDouble("-infinity") -> -inf. // infinity literal. + // StringToDouble("Infinity") -> NaN // junk_string_value. + // + // flags = ALLOW_OCTAL | ALLOW_LEADING_SPACES, + // empty_string_value = 0.0, + // junk_string_value = NaN, + // infinity_symbol = NULL, + // nan_symbol = NULL: + // StringToDouble("0x1234") -> NaN // junk_string_value. + // StringToDouble("01234") -> 668.0. + // StringToDouble("") -> 0.0 // empty_string_value. + // StringToDouble(" ") -> 0.0 // empty_string_value. + // StringToDouble(" 1") -> 1.0 + // StringToDouble("0x") -> NaN // junk_string_value. + // StringToDouble("0123e45") -> NaN // junk_string_value. + // StringToDouble("01239E45") -> 1239e45. + // StringToDouble("-infinity") -> NaN // junk_string_value. + // StringToDouble("NaN") -> NaN // junk_string_value. + StringToDoubleConverter(int flags, + double empty_string_value, + double junk_string_value, + const char* infinity_symbol, + const char* nan_symbol) + : flags_(flags), + empty_string_value_(empty_string_value), + junk_string_value_(junk_string_value), + infinity_symbol_(infinity_symbol), + nan_symbol_(nan_symbol) { + } + + // Performs the conversion. + // The output parameter 'processed_characters_count' is set to the number + // of characters that have been processed to read the number. + // Spaces than are processed with ALLOW_{LEADING|TRAILING}_SPACES are included + // in the 'processed_characters_count'. Trailing junk is never included. + double StringToDouble(const char* buffer, + int length, + int* processed_characters_count); + + private: + const int flags_; + const double empty_string_value_; + const double junk_string_value_; + const char* const infinity_symbol_; + const char* const nan_symbol_; + + DISALLOW_IMPLICIT_CONSTRUCTORS(StringToDoubleConverter); + }; + +} // namespace double_conversion + +} // namespace WTF + +#endif // DOUBLE_CONVERSION_DOUBLE_CONVERSION_H_ diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/double.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/double.h new file mode 100644 index 000000000..0544fdb5a --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/double.h @@ -0,0 +1,249 @@ +// Copyright 2010 the V8 project authors. 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 DOUBLE_CONVERSION_DOUBLE_H_ +#define DOUBLE_CONVERSION_DOUBLE_H_ + +#include "diy-fp.h" + +namespace WTF { + +namespace double_conversion { + + // We assume that doubles and uint64_t have the same endianness. + static uint64_t double_to_uint64(double d) { return BitCast(d); } + static double uint64_to_double(uint64_t d64) { return BitCast(d64); } + + // Helper functions for doubles. + class Double { + public: + static const uint64_t kSignMask = UINT64_2PART_C(0x80000000, 00000000); + static const uint64_t kExponentMask = UINT64_2PART_C(0x7FF00000, 00000000); + static const uint64_t kSignificandMask = UINT64_2PART_C(0x000FFFFF, FFFFFFFF); + static const uint64_t kHiddenBit = UINT64_2PART_C(0x00100000, 00000000); + static const int kPhysicalSignificandSize = 52; // Excludes the hidden bit. + static const int kSignificandSize = 53; + + Double() : d64_(0) {} + explicit Double(double d) : d64_(double_to_uint64(d)) {} + explicit Double(uint64_t d64) : d64_(d64) {} + explicit Double(DiyFp diy_fp) + : d64_(DiyFpToUint64(diy_fp)) {} + + // The value encoded by this Double must be greater or equal to +0.0. + // It must not be special (infinity, or NaN). + DiyFp AsDiyFp() const { + ASSERT(Sign() > 0); + ASSERT(!IsSpecial()); + return DiyFp(Significand(), Exponent()); + } + + // The value encoded by this Double must be strictly greater than 0. + DiyFp AsNormalizedDiyFp() const { + ASSERT(value() > 0.0); + uint64_t f = Significand(); + int e = Exponent(); + + // The current double could be a denormal. + while ((f & kHiddenBit) == 0) { + f <<= 1; + e--; + } + // Do the final shifts in one go. + f <<= DiyFp::kSignificandSize - kSignificandSize; + e -= DiyFp::kSignificandSize - kSignificandSize; + return DiyFp(f, e); + } + + // Returns the double's bit as uint64. + uint64_t AsUint64() const { + return d64_; + } + + // Returns the next greater double. Returns +infinity on input +infinity. + double NextDouble() const { + if (d64_ == kInfinity) return Double(kInfinity).value(); + if (Sign() < 0 && Significand() == 0) { + // -0.0 + return 0.0; + } + if (Sign() < 0) { + return Double(d64_ - 1).value(); + } else { + return Double(d64_ + 1).value(); + } + } + + int Exponent() const { + if (IsDenormal()) return kDenormalExponent; + + uint64_t d64 = AsUint64(); + int biased_e = + static_cast((d64 & kExponentMask) >> kPhysicalSignificandSize); + return biased_e - kExponentBias; + } + + uint64_t Significand() const { + uint64_t d64 = AsUint64(); + uint64_t significand = d64 & kSignificandMask; + if (!IsDenormal()) { + return significand + kHiddenBit; + } else { + return significand; + } + } + + // Returns true if the double is a denormal. + bool IsDenormal() const { + uint64_t d64 = AsUint64(); + return (d64 & kExponentMask) == 0; + } + + // We consider denormals not to be special. + // Hence only Infinity and NaN are special. + bool IsSpecial() const { + uint64_t d64 = AsUint64(); + return (d64 & kExponentMask) == kExponentMask; + } + + bool IsNan() const { + uint64_t d64 = AsUint64(); + return ((d64 & kExponentMask) == kExponentMask) && + ((d64 & kSignificandMask) != 0); + } + + bool IsInfinite() const { + uint64_t d64 = AsUint64(); + return ((d64 & kExponentMask) == kExponentMask) && + ((d64 & kSignificandMask) == 0); + } + + int Sign() const { + uint64_t d64 = AsUint64(); + return (d64 & kSignMask) == 0? 1: -1; + } + + // Precondition: the value encoded by this Double must be greater or equal + // than +0.0. + DiyFp UpperBoundary() const { + ASSERT(Sign() > 0); + return DiyFp(Significand() * 2 + 1, Exponent() - 1); + } + + // Computes the two boundaries of this. + // The bigger boundary (m_plus) is normalized. The lower boundary has the same + // exponent as m_plus. + // Precondition: the value encoded by this Double must be greater than 0. + void NormalizedBoundaries(DiyFp* out_m_minus, DiyFp* out_m_plus) const { + ASSERT(value() > 0.0); + DiyFp v = this->AsDiyFp(); + bool significand_is_zero = (v.f() == kHiddenBit); + DiyFp m_plus = DiyFp::Normalize(DiyFp((v.f() << 1) + 1, v.e() - 1)); + DiyFp m_minus; + if (significand_is_zero && v.e() != kDenormalExponent) { + // The boundary is closer. Think of v = 1000e10 and v- = 9999e9. + // Then the boundary (== (v - v-)/2) is not just at a distance of 1e9 but + // at a distance of 1e8. + // The only exception is for the smallest normal: the largest denormal is + // at the same distance as its successor. + // Note: denormals have the same exponent as the smallest normals. + m_minus = DiyFp((v.f() << 2) - 1, v.e() - 2); + } else { + m_minus = DiyFp((v.f() << 1) - 1, v.e() - 1); + } + m_minus.set_f(m_minus.f() << (m_minus.e() - m_plus.e())); + m_minus.set_e(m_plus.e()); + *out_m_plus = m_plus; + *out_m_minus = m_minus; + } + + double value() const { return uint64_to_double(d64_); } + + // Returns the significand size for a given order of magnitude. + // If v = f*2^e with 2^p-1 <= f <= 2^p then p+e is v's order of magnitude. + // This function returns the number of significant binary digits v will have + // once it's encoded into a double. In almost all cases this is equal to + // kSignificandSize. The only exceptions are denormals. They start with + // leading zeroes and their effective significand-size is hence smaller. + static int SignificandSizeForOrderOfMagnitude(int order) { + if (order >= (kDenormalExponent + kSignificandSize)) { + return kSignificandSize; + } + if (order <= kDenormalExponent) return 0; + return order - kDenormalExponent; + } + + static double Infinity() { + return Double(kInfinity).value(); + } + + static double NaN() { + return Double(kNaN).value(); + } + + private: + static const int kExponentBias = 0x3FF + kPhysicalSignificandSize; + static const int kDenormalExponent = -kExponentBias + 1; + static const int kMaxExponent = 0x7FF - kExponentBias; + static const uint64_t kInfinity = UINT64_2PART_C(0x7FF00000, 00000000); + static const uint64_t kNaN = UINT64_2PART_C(0x7FF80000, 00000000); + + const uint64_t d64_; + + static uint64_t DiyFpToUint64(DiyFp diy_fp) { + uint64_t significand = diy_fp.f(); + int exponent = diy_fp.e(); + while (significand > kHiddenBit + kSignificandMask) { + significand >>= 1; + exponent++; + } + if (exponent >= kMaxExponent) { + return kInfinity; + } + if (exponent < kDenormalExponent) { + return 0; + } + while (exponent > kDenormalExponent && (significand & kHiddenBit) == 0) { + significand <<= 1; + exponent--; + } + uint64_t biased_exponent; + if (exponent == kDenormalExponent && (significand & kHiddenBit) == 0) { + biased_exponent = 0; + } else { + biased_exponent = static_cast(exponent + kExponentBias); + } + return (significand & kSignificandMask) | + (biased_exponent << kPhysicalSignificandSize); + } + }; + +} // namespace double_conversion + +} // namespace WTF + +#endif // DOUBLE_CONVERSION_DOUBLE_H_ diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/dtoa.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/dtoa.h new file mode 100644 index 000000000..d27c59206 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/dtoa.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2003, 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WTF_dtoa_h +#define WTF_dtoa_h + +#include +#include + +namespace WTF { +class Mutex; + +extern WTF::Mutex* s_dtoaP5Mutex; + +typedef char DtoaBuffer[80]; + +WTF_EXPORT_PRIVATE void dtoa(DtoaBuffer result, double dd, bool& sign, int& exponent, unsigned& precision); +WTF_EXPORT_PRIVATE void dtoaRoundSF(DtoaBuffer result, double dd, int ndigits, bool& sign, int& exponent, unsigned& precision); +WTF_EXPORT_PRIVATE void dtoaRoundDP(DtoaBuffer result, double dd, int ndigits, bool& sign, int& exponent, unsigned& precision); + +// s00: input string. Must not be 0 and must be terminated by 0. +// se: *se will have the last consumed character position + 1. +WTF_EXPORT_PRIVATE double strtod(const char* s00, char** se); + +// Size = 80 for sizeof(DtoaBuffer) + some sign bits, decimal point, 'e', exponent digits. +const unsigned NumberToStringBufferLength = 96; +typedef char NumberToStringBuffer[NumberToStringBufferLength]; +typedef UChar NumberToUStringBuffer[NumberToStringBufferLength]; +WTF_EXPORT_PRIVATE const char* numberToString(double, NumberToStringBuffer); +const char* numberToFixedPrecisionString(double, unsigned significantFigures, NumberToStringBuffer, bool truncateTrailingZeros = false); +const char* numberToFixedWidthString(double, unsigned decimalPlaces, NumberToStringBuffer); + +} // namespace WTF + +using WTF::NumberToStringBuffer; +using WTF::NumberToUStringBuffer; +using WTF::numberToString; +using WTF::numberToFixedPrecisionString; +using WTF::numberToFixedWidthString; + +#endif // WTF_dtoa_h diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/fast-dtoa.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/fast-dtoa.h new file mode 100644 index 000000000..876a9f382 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/fast-dtoa.h @@ -0,0 +1,88 @@ +// Copyright 2010 the V8 project authors. 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 DOUBLE_CONVERSION_FAST_DTOA_H_ +#define DOUBLE_CONVERSION_FAST_DTOA_H_ + +#include "utils.h" + +namespace WTF { + +namespace double_conversion { + + enum FastDtoaMode { + // Computes the shortest representation of the given input. The returned + // result will be the most accurate number of this length. Longer + // representations might be more accurate. + FAST_DTOA_SHORTEST, + // Computes a representation where the precision (number of digits) is + // given as input. The precision is independent of the decimal point. + FAST_DTOA_PRECISION + }; + + // FastDtoa will produce at most kFastDtoaMaximalLength digits. This does not + // include the terminating '\0' character. + static const int kFastDtoaMaximalLength = 17; + + // Provides a decimal representation of v. + // The result should be interpreted as buffer * 10^(point - length). + // + // Precondition: + // * v must be a strictly positive finite double. + // + // Returns true if it succeeds, otherwise the result can not be trusted. + // There will be *length digits inside the buffer followed by a null terminator. + // If the function returns true and mode equals + // - FAST_DTOA_SHORTEST, then + // the parameter requested_digits is ignored. + // The result satisfies + // v == (double) (buffer * 10^(point - length)). + // The digits in the buffer are the shortest representation possible. E.g. + // if 0.099999999999 and 0.1 represent the same double then "1" is returned + // with point = 0. + // The last digit will be closest to the actual v. That is, even if several + // digits might correctly yield 'v' when read again, the buffer will contain + // the one closest to v. + // - FAST_DTOA_PRECISION, then + // the buffer contains requested_digits digits. + // the difference v - (buffer * 10^(point-length)) is closest to zero for + // all possible representations of requested_digits digits. + // If there are two values that are equally close, then FastDtoa returns + // false. + // For both modes the buffer must be large enough to hold the result. + bool FastDtoa(double d, + FastDtoaMode mode, + int requested_digits, + Vector buffer, + int* length, + int* decimal_point); + +} // namespace double_conversion + +} // namespace WTF + +#endif // DOUBLE_CONVERSION_FAST_DTOA_H_ diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/fixed-dtoa.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/fixed-dtoa.h new file mode 100644 index 000000000..8c0adb758 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/fixed-dtoa.h @@ -0,0 +1,60 @@ +// Copyright 2010 the V8 project authors. 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 DOUBLE_CONVERSION_FIXED_DTOA_H_ +#define DOUBLE_CONVERSION_FIXED_DTOA_H_ + +#include "utils.h" + +namespace WTF { + +namespace double_conversion { + + // Produces digits necessary to print a given number with + // 'fractional_count' digits after the decimal point. + // The buffer must be big enough to hold the result plus one terminating null + // character. + // + // The produced digits might be too short in which case the caller has to fill + // the gaps with '0's. + // Example: FastFixedDtoa(0.001, 5, ...) is allowed to return buffer = "1", and + // decimal_point = -2. + // Halfway cases are rounded towards +/-Infinity (away from 0). The call + // FastFixedDtoa(0.15, 2, ...) thus returns buffer = "2", decimal_point = 0. + // The returned buffer may contain digits that would be truncated from the + // shortest representation of the input. + // + // This method only works for some parameters. If it can't handle the input it + // returns false. The output is null-terminated when the function succeeds. + bool FastFixedDtoa(double v, int fractional_count, + Vector buffer, int* length, int* decimal_point); + +} // namespace double_conversion + +} // namespace WTF + +#endif // DOUBLE_CONVERSION_FIXED_DTOA_H_ diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/strtod.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/strtod.h new file mode 100644 index 000000000..8ed350ad8 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/strtod.h @@ -0,0 +1,45 @@ +// Copyright 2010 the V8 project authors. 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 DOUBLE_CONVERSION_STRTOD_H_ +#define DOUBLE_CONVERSION_STRTOD_H_ + +#include "utils.h" + +namespace WTF { + +namespace double_conversion { + + // The buffer must only contain digits in the range [0-9]. It must not + // contain a dot or a sign. It must not start with '0', and must not be empty. + double Strtod(Vector buffer, int exponent); + +} // namespace double_conversion + +} // namespace WTF + +#endif // DOUBLE_CONVERSION_STRTOD_H_ diff --git a/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/utils.h b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/utils.h new file mode 100644 index 000000000..d5cfe9c29 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/PrivateHeaders/utils.h @@ -0,0 +1,310 @@ +// Copyright 2010 the V8 project authors. 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 DOUBLE_CONVERSION_UTILS_H_ +#define DOUBLE_CONVERSION_UTILS_H_ + +#include "Assertions.h" +#include +#include + +#define UNIMPLEMENTED ASSERT_NOT_REACHED +#define UNREACHABLE ASSERT_NOT_REACHED + +// Double operations detection based on target architecture. +// Linux uses a 80bit wide floating point stack on x86. This induces double +// rounding, which in turn leads to wrong results. +// An easy way to test if the floating-point operations are correct is to +// evaluate: 89255.0/1e22. If the floating-point stack is 64 bits wide then +// the result is equal to 89255e-22. +// The best way to test this, is to create a division-function and to compare +// the output of the division with the expected result. (Inlining must be +// disabled.) +// On Linux,x86 89255e-22 != Div_double(89255.0/1e22) +#if defined(_M_X64) || defined(__x86_64__) || \ +defined(__ARMEL__) || \ +defined(_MIPS_ARCH_MIPS32R2) +#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1 +#elif CPU(MIPS) || CPU(PPC) || CPU(PPC64) || OS(WINCE) || CPU(SH4) || CPU(S390) || CPU(S390X) +#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1 +#elif defined(_M_IX86) || defined(__i386__) +#if defined(_WIN32) +// Windows uses a 64bit wide floating point stack. +#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1 +#else +#undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS +#endif // _WIN32 +#else +#error Target architecture was not detected as supported by Double-Conversion. +#endif + + +#if defined(_WIN32) && !defined(__MINGW32__) + +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef short int16_t; // NOLINT +typedef unsigned short uint16_t; // NOLINT +typedef int int32_t; +typedef unsigned int uint32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +// intptr_t and friends are defined in crtdefs.h through stdio.h. + +#else + +#include + +#endif + +// The following macro works on both 32 and 64-bit platforms. +// Usage: instead of writing 0x1234567890123456 +// write UINT64_2PART_C(0x12345678,90123456); +#define UINT64_2PART_C(a, b) (((static_cast(a) << 32) + 0x##b##u)) + + +// The expression ARRAY_SIZE(a) is a compile-time constant of type +// size_t which represents the number of elements of the given +// array. You should only use ARRAY_SIZE on statically allocated +// arrays. +#define ARRAY_SIZE(a) \ +((sizeof(a) / sizeof(*(a))) / \ +static_cast(!(sizeof(a) % sizeof(*(a))))) + +// A macro to disallow the evil copy constructor and operator= functions +// This should be used in the private: declarations for a class +#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ +TypeName(const TypeName&); \ +void operator=(const TypeName&) + +// A macro to disallow all the implicit constructors, namely the +// default constructor, copy constructor and operator= functions. +// +// This should be used in the private: declarations for a class +// that wants to prevent anyone from instantiating it. This is +// especially useful for classes containing only static methods. +#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ +TypeName(); \ +DISALLOW_COPY_AND_ASSIGN(TypeName) + +namespace WTF { + +namespace double_conversion { + + static const int kCharSize = sizeof(char); + + // Returns the maximum of the two parameters. + template + static T Max(T a, T b) { + return a < b ? b : a; + } + + + // Returns the minimum of the two parameters. + template + static T Min(T a, T b) { + return a < b ? a : b; + } + + + inline int StrLength(const char* string) { + size_t length = strlen(string); + ASSERT(length == static_cast(static_cast(length))); + return static_cast(length); + } + + // This is a simplified version of V8's Vector class. + template + class Vector { + public: + Vector() : start_(NULL), length_(0) {} + Vector(T* data, int length) : start_(data), length_(length) { + ASSERT(length == 0 || (length > 0 && data != NULL)); + } + + // Returns a vector using the same backing storage as this one, + // spanning from and including 'from', to but not including 'to'. + Vector SubVector(int from, int to) { + ASSERT(to <= length_); + ASSERT(from < to); + ASSERT(0 <= from); + return Vector(start() + from, to - from); + } + + // Returns the length of the vector. + int length() const { return length_; } + + // Returns whether or not the vector is empty. + bool is_empty() const { return length_ == 0; } + + // Returns the pointer to the start of the data in the vector. + T* start() const { return start_; } + + // Access individual vector elements - checks bounds in debug mode. + T& operator[](int index) const { + ASSERT(0 <= index && index < length_); + return start_[index]; + } + + T& first() { return start_[0]; } + + T& last() { return start_[length_ - 1]; } + + private: + T* start_; + int length_; + }; + + + // Helper class for building result strings in a character buffer. The + // purpose of the class is to use safe operations that checks the + // buffer bounds on all operations in debug mode. + class StringBuilder { + public: + StringBuilder(char* buffer, int size) + : buffer_(buffer, size), position_(0) { } + + ~StringBuilder() { if (!is_finalized()) Finalize(); } + + int size() const { return buffer_.length(); } + + // Get the current position in the builder. + int position() const { + ASSERT(!is_finalized()); + return position_; + } + + // Set the current position in the builder. + void SetPosition(int position) + { + ASSERT(!is_finalized()); + ASSERT(position < size()); + position_ = position; + } + + // Reset the position. + void Reset() { position_ = 0; } + + // Add a single character to the builder. It is not allowed to add + // 0-characters; use the Finalize() method to terminate the string + // instead. + void AddCharacter(char c) { + ASSERT(c != '\0'); + ASSERT(!is_finalized() && position_ < buffer_.length()); + buffer_[position_++] = c; + } + + // Add an entire string to the builder. Uses strlen() internally to + // compute the length of the input string. + void AddString(const char* s) { + AddSubstring(s, StrLength(s)); + } + + // Add the first 'n' characters of the given string 's' to the + // builder. The input string must have enough characters. + void AddSubstring(const char* s, int n) { + ASSERT(!is_finalized() && position_ + n < buffer_.length()); + ASSERT(static_cast(n) <= strlen(s)); + memcpy(&buffer_[position_], s, n * kCharSize); + position_ += n; + } + + + // Add character padding to the builder. If count is non-positive, + // nothing is added to the builder. + void AddPadding(char c, int count) { + for (int i = 0; i < count; i++) { + AddCharacter(c); + } + } + + // Finalize the string by 0-terminating it and returning the buffer. + char* Finalize() { + ASSERT(!is_finalized() && position_ < buffer_.length()); + buffer_[position_] = '\0'; + // Make sure nobody managed to add a 0-character to the + // buffer while building the string. + ASSERT(strlen(buffer_.start()) == static_cast(position_)); + position_ = -1; + ASSERT(is_finalized()); + return buffer_.start(); + } + + private: + Vector buffer_; + int position_; + + bool is_finalized() const { return position_ < 0; } + + DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder); + }; + + // The type-based aliasing rule allows the compiler to assume that pointers of + // different types (for some definition of different) never alias each other. + // Thus the following code does not work: + // + // float f = foo(); + // int fbits = *(int*)(&f); + // + // The compiler 'knows' that the int pointer can't refer to f since the types + // don't match, so the compiler may cache f in a register, leaving random data + // in fbits. Using C++ style casts makes no difference, however a pointer to + // char data is assumed to alias any other pointer. This is the 'memcpy + // exception'. + // + // Bit_cast uses the memcpy exception to move the bits from a variable of one + // type of a variable of another type. Of course the end result is likely to + // be implementation dependent. Most compilers (gcc-4.2 and MSVC 2005) + // will completely optimize BitCast away. + // + // There is an additional use for BitCast. + // Recent gccs will warn when they see casts that may result in breakage due to + // the type-based aliasing rule. If you have checked that there is no breakage + // you can use BitCast to cast one pointer type to another. This confuses gcc + // enough that it can no longer see that you have cast one pointer type to + // another thus avoiding the warning. + template + inline Dest BitCast(const Source& source) { + // Compile time assertion: sizeof(Dest) == sizeof(Source) + // A compile error here means your Dest and Source have different sizes. + typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1]; + + Dest dest; + memcpy(&dest, &source, sizeof(dest)); + return dest; + } + + template + inline Dest BitCast(Source* source) { + return BitCast(reinterpret_cast(source)); + } + +} // namespace double_conversion + +} // namespace WTF + +#endif // DOUBLE_CONVERSION_UTILS_H_ diff --git a/frameworks/JavaScriptCore.framework/Versions/A/Resources/Info.plist b/frameworks/JavaScriptCore.framework/Versions/A/Resources/Info.plist new file mode 100644 index 000000000..6b901ef2e --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/A/Resources/Info.plist @@ -0,0 +1,40 @@ + + + + + BuildMachineOSBuild + 11A511 + CFBundleDevelopmentRegion + English + CFBundleExecutable + JavaScriptCore + CFBundleGetInfoString + 535.19+, Copyright 2003-2012 Apple Inc.; Copyright 1999-2001 Harri Porten <porten@kde.org>; Copyright 2001 Peter Kelly <pmk@post.com>; Copyright 1997-2005 University of Cambridge; Copyright 1991, 2000, 2001 by Lucent Technologies. + CFBundleIdentifier + com.apple.JavaScriptCore + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + JavaScriptCore + CFBundlePackageType + FMWK + CFBundleShortVersionString + 535+ + CFBundleVersion + 535.19+ + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 4D199 + DTPlatformVersion + GM + DTSDKBuild + 11A511 + DTSDKName + + DTXcode + 0420 + DTXcodeBuild + 4D199 + + diff --git a/frameworks/JavaScriptCore.framework/Versions/A/Resources/jsc b/frameworks/JavaScriptCore.framework/Versions/A/Resources/jsc new file mode 100755 index 000000000..252531d1c Binary files /dev/null and b/frameworks/JavaScriptCore.framework/Versions/A/Resources/jsc differ diff --git a/frameworks/JavaScriptCore.framework/Versions/Current b/frameworks/JavaScriptCore.framework/Versions/Current new file mode 120000 index 000000000..8c7e5a667 --- /dev/null +++ b/frameworks/JavaScriptCore.framework/Versions/Current @@ -0,0 +1 @@ +A \ No newline at end of file diff --git a/frameworks/WebCore.framework/PrivateHeaders b/frameworks/WebCore.framework/PrivateHeaders new file mode 120000 index 000000000..d8e564526 --- /dev/null +++ b/frameworks/WebCore.framework/PrivateHeaders @@ -0,0 +1 @@ +Versions/Current/PrivateHeaders \ No newline at end of file diff --git a/frameworks/WebCore.framework/Resources b/frameworks/WebCore.framework/Resources new file mode 120000 index 000000000..953ee36f3 --- /dev/null +++ b/frameworks/WebCore.framework/Resources @@ -0,0 +1 @@ +Versions/Current/Resources \ No newline at end of file diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AXObjectCache.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AXObjectCache.h new file mode 100644 index 000000000..7dbe56d40 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AXObjectCache.h @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010, 2011 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 AXObjectCache_h +#define AXObjectCache_h + +#include "AccessibilityObject.h" +#include "Timer.h" +#include +#include +#include +#include +#include + +namespace WebCore { + +class Document; +class HTMLAreaElement; +class Node; +class Page; +class RenderObject; +class ScrollView; +class VisiblePosition; +class Widget; + +struct TextMarkerData { + AXID axID; + Node* node; + int offset; + EAffinity affinity; +}; + +enum PostType { PostSynchronously, PostAsynchronously }; + +class AXObjectCache { + WTF_MAKE_NONCOPYABLE(AXObjectCache); WTF_MAKE_FAST_ALLOCATED; +public: + AXObjectCache(const Document*); + ~AXObjectCache(); + + static AccessibilityObject* focusedUIElementForPage(const Page*); + + // Returns the root object for the entire document. + AccessibilityObject* rootObject(); + // Returns the root object for a specific frame. + AccessibilityObject* rootObjectForFrame(Frame*); + + // For AX objects with elements that back them. + AccessibilityObject* getOrCreate(RenderObject*); + AccessibilityObject* getOrCreate(Widget*); + + // used for objects without backing elements + AccessibilityObject* getOrCreate(AccessibilityRole); + + // will only return the AccessibilityObject if it already exists + AccessibilityObject* get(RenderObject*); + AccessibilityObject* get(Widget*); + + void remove(RenderObject*); + void remove(Widget*); + void remove(AXID); + + void detachWrapper(AccessibilityObject*); + void attachWrapper(AccessibilityObject*); + void childrenChanged(RenderObject*); + void checkedStateChanged(RenderObject*); + void selectedChildrenChanged(RenderObject*); + // Called by a node when text or a text equivalent (e.g. alt) attribute is changed. + void contentChanged(RenderObject*); + + void handleActiveDescendantChanged(RenderObject*); + void handleAriaRoleChanged(RenderObject*); + void handleFocusedUIElementChanged(RenderObject* oldFocusedRenderer, RenderObject* newFocusedRenderer); + void handleScrolledToAnchor(const Node* anchorNode); + void handleAriaExpandedChange(RenderObject*); + void handleScrollbarUpdate(ScrollView*); + + static void enableAccessibility() { gAccessibilityEnabled = true; } + // Enhanced user interface accessibility can be toggled by the assistive technology. + static void setEnhancedUserInterfaceAccessibility(bool flag) { gAccessibilityEnhancedUserInterfaceEnabled = flag; } + + static bool accessibilityEnabled() { return gAccessibilityEnabled; } + static bool accessibilityEnhancedUserInterfaceEnabled() { return gAccessibilityEnhancedUserInterfaceEnabled; } + + void removeAXID(AccessibilityObject*); + bool isIDinUse(AXID id) const { return m_idsInUse.contains(id); } + + Element* rootAXEditableElement(Node*); + const Element* rootAXEditableElement(const Node*); + bool nodeIsTextControl(const Node*); + + AXID platformGenerateAXID() const; + AccessibilityObject* objectFromAXID(AXID id) const { return m_objects.get(id).get(); } + + // This is a weak reference cache for knowing if Nodes used by TextMarkers are valid. + void setNodeInUse(Node* n) { m_textMarkerNodes.add(n); } + void removeNodeForUse(Node* n) { m_textMarkerNodes.remove(n); } + bool isNodeInUse(Node* n) { return m_textMarkerNodes.contains(n); } + + // Text marker utilities. + void textMarkerDataForVisiblePosition(TextMarkerData&, const VisiblePosition&); + VisiblePosition visiblePositionForTextMarkerData(TextMarkerData&); + + enum AXNotification { + AXActiveDescendantChanged, + AXAutocorrectionOccured, + AXCheckedStateChanged, + AXChildrenChanged, + AXFocusedUIElementChanged, + AXLayoutComplete, + AXLoadComplete, + AXSelectedChildrenChanged, + AXSelectedTextChanged, + AXValueChanged, + AXScrolledToAnchor, + AXLiveRegionChanged, + AXMenuListItemSelected, + AXMenuListValueChanged, + AXRowCountChanged, + AXRowCollapsed, + AXRowExpanded, + AXInvalidStatusChanged, + }; + + void postNotification(RenderObject*, AXNotification, bool postToElement, PostType = PostAsynchronously); + void postNotification(AccessibilityObject*, Document*, AXNotification, bool postToElement, PostType = PostAsynchronously); + + enum AXTextChange { + AXTextInserted, + AXTextDeleted, + }; + + void nodeTextChangeNotification(RenderObject*, AXTextChange, unsigned offset, const String&); + + enum AXLoadingEvent { + AXLoadingStarted, + AXLoadingReloaded, + AXLoadingFailed, + AXLoadingFinished + }; + + void frameLoadingEventNotification(Frame*, AXLoadingEvent); + + bool nodeHasRole(Node*, const AtomicString& role); + +protected: + void postPlatformNotification(AccessibilityObject*, AXNotification); + void nodeTextChangePlatformNotification(AccessibilityObject*, AXTextChange, unsigned offset, const String&); + void frameLoadingEventPlatformNotification(AccessibilityObject*, AXLoadingEvent); + +private: + Document* m_document; + HashMap > m_objects; + HashMap m_renderObjectMapping; + HashMap m_widgetObjectMapping; + HashSet m_textMarkerNodes; + static bool gAccessibilityEnabled; + static bool gAccessibilityEnhancedUserInterfaceEnabled; + + HashSet m_idsInUse; + + Timer m_notificationPostTimer; + Vector, AXNotification> > m_notificationsToPost; + void notificationPostTimerFired(Timer*); + + static AccessibilityObject* focusedImageMapUIElement(HTMLAreaElement*); + + AXID getAXID(AccessibilityObject*); +}; + +bool nodeHasRole(Node*, const String& role); + +#if !HAVE(ACCESSIBILITY) +inline void AXObjectCache::handleActiveDescendantChanged(RenderObject*) { } +inline void AXObjectCache::handleAriaRoleChanged(RenderObject*) { } +inline void AXObjectCache::detachWrapper(AccessibilityObject*) { } +inline void AXObjectCache::attachWrapper(AccessibilityObject*) { } +inline void AXObjectCache::checkedStateChanged(RenderObject*) { } +inline void AXObjectCache::selectedChildrenChanged(RenderObject*) { } +inline void AXObjectCache::postNotification(RenderObject*, AXNotification, bool postToElement, PostType) { } +inline void AXObjectCache::postNotification(AccessibilityObject*, Document*, AXNotification, bool postToElement, PostType) { } +inline void AXObjectCache::postPlatformNotification(AccessibilityObject*, AXNotification) { } +inline void AXObjectCache::nodeTextChangeNotification(RenderObject*, AXTextChange, unsigned, const String&) { } +inline void AXObjectCache::nodeTextChangePlatformNotification(AccessibilityObject*, AXTextChange, unsigned, const String&) { } +inline void AXObjectCache::frameLoadingEventNotification(Frame*, AXLoadingEvent) { } +inline void AXObjectCache::frameLoadingEventPlatformNotification(AccessibilityObject*, AXLoadingEvent) { } +inline void AXObjectCache::handleFocusedUIElementChanged(RenderObject*, RenderObject*) { } +inline void AXObjectCache::handleScrolledToAnchor(const Node*) { } +inline void AXObjectCache::contentChanged(RenderObject*) { } +inline void AXObjectCache::handleAriaExpandedChange(RenderObject*) { } +inline void AXObjectCache::handleScrollbarUpdate(ScrollView*) { } +#endif + +} + +#endif diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AbstractDatabase.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AbstractDatabase.h new file mode 100644 index 000000000..3286a87b2 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AbstractDatabase.h @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2011 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: + * + * 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 AbstractDatabase_h +#define AbstractDatabase_h + +#if ENABLE(SQL_DATABASE) + +#include "PlatformString.h" +#include "SQLiteDatabase.h" +#include +#include +#if !LOG_DISABLED || !ERROR_DISABLED +#include "SecurityOrigin.h" +#endif + +namespace WebCore { + +class DatabaseAuthorizer; +class ScriptExecutionContext; +class SecurityOrigin; + +typedef int ExceptionCode; + +class AbstractDatabase : public ThreadSafeRefCounted { +public: + static bool isAvailable(); + static void setIsAvailable(bool available); + + virtual ~AbstractDatabase(); + + virtual String version() const; + + bool opened() const { return m_opened; } + bool isNew() const { return m_new; } + bool isSyncDatabase() const { return m_isSyncDatabase; } + + virtual ScriptExecutionContext* scriptExecutionContext() const; + virtual SecurityOrigin* securityOrigin() const; + virtual String stringIdentifier() const; + virtual String displayName() const; + virtual unsigned long estimatedSize() const; + virtual String fileName() const; + SQLiteDatabase& sqliteDatabase() { return m_sqliteDatabase; } + + unsigned long long maximumSize() const; + void incrementalVacuumIfNeeded(); + void interrupt(); + bool isInterrupted(); + + void disableAuthorizer(); + void enableAuthorizer(); + void setAuthorizerReadOnly(); + void setAuthorizerPermissions(int permissions); + bool lastActionChangedDatabase(); + bool lastActionWasInsert(); + void resetDeletes(); + bool hadDeletes(); + void resetAuthorizer(); + + virtual void markAsDeletedAndClose() = 0; + virtual void closeImmediately() = 0; + +protected: + friend class ChangeVersionWrapper; + friend class SQLStatement; + friend class SQLStatementSync; + friend class SQLTransactionSync; + friend class SQLTransaction; + + enum DatabaseType { + AsyncDatabase, + SyncDatabase + }; + + AbstractDatabase(ScriptExecutionContext*, const String& name, const String& expectedVersion, + const String& displayName, unsigned long estimatedSize, DatabaseType); + + void closeDatabase(); + + virtual bool performOpenAndVerify(bool shouldSetVersionInNewDatabase, ExceptionCode&, String& errorMessage); + + bool getVersionFromDatabase(String& version, bool shouldCacheVersion = true); + bool setVersionInDatabase(const String& version, bool shouldCacheVersion = true); + void setExpectedVersion(const String&); + const String& expectedVersion() const { return m_expectedVersion; } + String getCachedVersion()const; + void setCachedVersion(const String&); + bool getActualVersionForTransaction(String& version); + + void logErrorMessage(const String& message); + + void reportOpenDatabaseResult(int errorSite, int webSqlErrorCode, int sqliteErrorCode); + void reportChangeVersionResult(int errorSite, int webSqlErrorCode, int sqliteErrorCode); + void reportStartTransactionResult(int errorSite, int webSqlErrorCode, int sqliteErrorCode); + void reportCommitTransactionResult(int errorSite, int webSqlErrorCode, int sqliteErrorCode); + void reportExecuteStatementResult(int errorSite, int webSqlErrorCode, int sqliteErrorCode); + void reportVacuumDatabaseResult(int sqliteErrorCode); + + static const char* databaseInfoTableName(); + + RefPtr m_scriptExecutionContext; + RefPtr m_contextThreadSecurityOrigin; + + String m_name; + String m_expectedVersion; + String m_displayName; + unsigned long m_estimatedSize; + String m_filename; + +#if !LOG_DISABLED || !ERROR_DISABLED + String databaseDebugName() const { return m_contextThreadSecurityOrigin->toString() + "::" + m_name; } +#endif + +private: + int m_guid; + bool m_opened; + bool m_new; + const bool m_isSyncDatabase; + + SQLiteDatabase m_sqliteDatabase; + + RefPtr m_databaseAuthorizer; +}; + +} // namespace WebCore + +#endif // ENABLE(SQL_DATABASE) + +#endif // AbstractDatabase_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AccessibilityObject.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AccessibilityObject.h new file mode 100644 index 000000000..c417cc958 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AccessibilityObject.h @@ -0,0 +1,719 @@ +/* + * Copyright (C) 2008, 2009, 2011 Apple Inc. All rights reserved. + * Copyright (C) 2008 Nuanti Ltd. + * + * 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 AccessibilityObject_h +#define AccessibilityObject_h + +#include "FloatQuad.h" +#include "LayoutTypes.h" +#include "VisiblePosition.h" +#include "VisibleSelection.h" +#include +#include +#include + +#if PLATFORM(MAC) +#include +#elif PLATFORM(WIN) && !OS(WINCE) +#include "AccessibilityObjectWrapperWin.h" +#include "COMPtr.h" +#elif PLATFORM(CHROMIUM) +#include "AccessibilityObjectWrapper.h" +#endif + +#if PLATFORM(MAC) + +typedef struct _NSRange NSRange; + +OBJC_CLASS NSArray; +OBJC_CLASS NSAttributedString; +OBJC_CLASS NSData; +OBJC_CLASS NSMutableAttributedString; +OBJC_CLASS NSString; +OBJC_CLASS NSValue; +OBJC_CLASS NSView; +OBJC_CLASS WebAccessibilityObjectWrapper; + +typedef WebAccessibilityObjectWrapper AccessibilityObjectWrapper; + +#elif PLATFORM(GTK) +typedef struct _AtkObject AtkObject; +typedef struct _AtkObject AccessibilityObjectWrapper; +#else +class AccessibilityObjectWrapper; +#endif + +namespace WebCore { + +class AccessibilityObject; +class AXObjectCache; +class Element; +class Frame; +class FrameView; +class HTMLAnchorElement; +class HTMLAreaElement; +class IntPoint; +class IntSize; +class Node; +class Page; +class RenderObject; +class RenderListItem; +class ScrollableArea; +class VisibleSelection; +class Widget; + +typedef unsigned AXID; + +enum AccessibilityRole { + AnnotationRole = 1, + ApplicationRole, + ApplicationAlertRole, + ApplicationAlertDialogRole, + ApplicationDialogRole, + ApplicationLogRole, + ApplicationMarqueeRole, + ApplicationStatusRole, + ApplicationTimerRole, + BrowserRole, + BusyIndicatorRole, + ButtonRole, + CellRole, + CheckBoxRole, + ColorWellRole, + ColumnRole, + ColumnHeaderRole, + ComboBoxRole, + DefinitionListTermRole, + DefinitionListDefinitionRole, + DirectoryRole, + DisclosureTriangleRole, + DivRole, + DocumentRole, + DocumentArticleRole, + DocumentMathRole, + DocumentNoteRole, + DocumentRegionRole, + DrawerRole, + EditableTextRole, + FormRole, + GridRole, + GroupRole, + GrowAreaRole, + HeadingRole, + HelpTagRole, + IgnoredRole, + ImageRole, + ImageMapRole, + ImageMapLinkRole, + IncrementorRole, + LabelRole, + LandmarkApplicationRole, + LandmarkBannerRole, + LandmarkComplementaryRole, + LandmarkContentInfoRole, + LandmarkMainRole, + LandmarkNavigationRole, + LandmarkSearchRole, + LinkRole, + ListRole, + ListBoxRole, + ListBoxOptionRole, + ListItemRole, + ListMarkerRole, + MatteRole, + MenuRole, + MenuBarRole, + MenuButtonRole, + MenuItemRole, + MenuListPopupRole, + MenuListOptionRole, + OutlineRole, + ParagraphRole, + PopUpButtonRole, + PresentationalRole, + ProgressIndicatorRole, + RadioButtonRole, + RadioGroupRole, + RowHeaderRole, + RowRole, + RulerRole, + RulerMarkerRole, + ScrollAreaRole, + ScrollBarRole, + SheetRole, + SliderRole, + SliderThumbRole, + SpinButtonRole, + SpinButtonPartRole, + SplitGroupRole, + SplitterRole, + StaticTextRole, + SystemWideRole, + TabGroupRole, + TabListRole, + TabPanelRole, + TabRole, + TableRole, + TableHeaderContainerRole, + TextAreaRole, + TreeRole, + TreeGridRole, + TreeItemRole, + TextFieldRole, + ToolbarRole, + UnknownRole, + UserInterfaceTooltipRole, + ValueIndicatorRole, + WebAreaRole, + WebCoreLinkRole, + WindowRole, +}; + +enum AccessibilityOrientation { + AccessibilityOrientationVertical, + AccessibilityOrientationHorizontal, +}; + +enum AccessibilityObjectInclusion { + IncludeObject, + IgnoreObject, + DefaultBehavior, +}; + +enum AccessibilityButtonState { + ButtonStateOff = 0, + ButtonStateOn, + ButtonStateMixed, +}; + +enum AccessibilitySortDirection { + SortDirectionNone, + SortDirectionAscending, + SortDirectionDescending, +}; + +enum AccessibilitySearchDirection { + SearchDirectionNext = 1, + SearchDirectionPrevious +}; + +enum AccessibilitySearchKey { + AnyTypeSearchKey = 1, + BlockquoteSameLevelSearchKey, + BlockquoteSearchKey, + BoldFontSearchKey, + ButtonSearchKey, + CheckBoxSearchKey, + ControlSearchKey, + DifferentTypeSearchKey, + FontChangeSearchKey, + FontColorChangeSearchKey, + FrameSearchKey, + GraphicSearchKey, + HeadingLevel1SearchKey, + HeadingLevel2SearchKey, + HeadingLevel3SearchKey, + HeadingLevel4SearchKey, + HeadingLevel5SearchKey, + HeadingLevel6SearchKey, + HeadingSameLevelSearchKey, + HeadingSearchKey, + ItalicFontSearchKey, + LandmarkSearchKey, + LinkSearchKey, + ListSearchKey, + LiveRegionSearchKey, + MisspelledWordSearchKey, + PlainTextSearchKey, + RadioGroupSearchKey, + SameTypeSearchKey, + StaticTextSearchKey, + StyleChangeSearchKey, + TableSameLevelSearchKey, + TableSearchKey, + TextFieldSearchKey, + UnderlineSearchKey, + UnvisitedLinkSearchKey, + VisitedLinkSearchKey +}; + +struct AccessibilitySearchCriteria { + AccessibilityObject* startObject; + AccessibilitySearchDirection searchDirection; + AccessibilitySearchKey searchKey; + String* searchText; + unsigned resultsLimit; +}; + +struct VisiblePositionRange { + + VisiblePosition start; + VisiblePosition end; + + VisiblePositionRange() {} + + VisiblePositionRange(const VisiblePosition& s, const VisiblePosition& e) + : start(s) + , end(e) + { } + + bool isNull() const { return start.isNull() || end.isNull(); } +}; + +struct PlainTextRange { + + unsigned start; + unsigned length; + + PlainTextRange() + : start(0) + , length(0) + { } + + PlainTextRange(unsigned s, unsigned l) + : start(s) + , length(l) + { } + + bool isNull() const { return !start && !length; } +}; + +class AccessibilityObject : public RefCounted { +protected: + AccessibilityObject(); + +public: + virtual ~AccessibilityObject(); + virtual void detach(); + + typedef Vector > AccessibilityChildrenVector; + + virtual bool isAccessibilityRenderObject() const { return false; } + virtual bool isAccessibilityScrollbar() const { return false; } + virtual bool isAccessibilityScrollView() const { return false; } + + bool accessibilityObjectContainsText(String *) const; + + virtual bool isAnchor() const { return false; } + virtual bool isAttachment() const { return false; } + virtual bool isHeading() const { return false; } + virtual bool isLink() const { return false; } + virtual bool isImage() const { return false; } + virtual bool isNativeImage() const { return false; } + virtual bool isImageButton() const { return false; } + virtual bool isPasswordField() const { return false; } + virtual bool isNativeTextControl() const { return false; } + virtual bool isWebArea() const { return false; } + virtual bool isCheckbox() const { return roleValue() == CheckBoxRole; } + virtual bool isRadioButton() const { return roleValue() == RadioButtonRole; } + virtual bool isListBox() const { return roleValue() == ListBoxRole; } + virtual bool isMediaTimeline() const { return false; } + virtual bool isMenuRelated() const { return false; } + virtual bool isMenu() const { return false; } + virtual bool isMenuBar() const { return false; } + virtual bool isMenuButton() const { return false; } + virtual bool isMenuItem() const { return false; } + virtual bool isFileUploadButton() const { return false; } + virtual bool isInputImage() const { return false; } + virtual bool isProgressIndicator() const { return false; } + virtual bool isSlider() const { return false; } + virtual bool isInputSlider() const { return false; } + virtual bool isControl() const { return false; } + virtual bool isList() const { return false; } + virtual bool isAccessibilityTable() const { return false; } + virtual bool isDataTable() const { return false; } + virtual bool isTableRow() const { return false; } + virtual bool isTableColumn() const { return false; } + virtual bool isTableCell() const { return false; } + virtual bool isFieldset() const { return false; } + virtual bool isGroup() const { return false; } + virtual bool isARIATreeGridRow() const { return false; } + virtual bool isImageMapLink() const { return false; } + virtual bool isMenuList() const { return false; } + virtual bool isMenuListPopup() const { return false; } + virtual bool isMenuListOption() const { return false; } + virtual bool isSpinButton() const { return false; } + virtual bool isSpinButtonPart() const { return false; } + virtual bool isMockObject() const { return false; } + bool isTextControl() const { return roleValue() == TextAreaRole || roleValue() == TextFieldRole; } + bool isARIATextControl() const; + bool isTabList() const { return roleValue() == TabListRole; } + bool isTabItem() const { return roleValue() == TabRole; } + bool isRadioGroup() const { return roleValue() == RadioGroupRole; } + bool isComboBox() const { return roleValue() == ComboBoxRole; } + bool isTree() const { return roleValue() == TreeRole; } + bool isTreeItem() const { return roleValue() == TreeItemRole; } + bool isScrollbar() const { return roleValue() == ScrollBarRole; } + bool isButton() const { return roleValue() == ButtonRole; } + bool isListItem() const { return roleValue() == ListItemRole; } + bool isCheckboxOrRadio() const { return isCheckbox() || isRadioButton(); } + bool isScrollView() const { return roleValue() == ScrollAreaRole; } + bool isBlockquote() const; + bool isLandmark() const; + + virtual bool isChecked() const { return false; } + virtual bool isEnabled() const { return false; } + virtual bool isSelected() const { return false; } + virtual bool isFocused() const { return false; } + virtual bool isHovered() const { return false; } + virtual bool isIndeterminate() const { return false; } + virtual bool isLoaded() const { return false; } + virtual bool isMultiSelectable() const { return false; } + virtual bool isOffScreen() const { return false; } + virtual bool isPressed() const { return false; } + virtual bool isReadOnly() const { return false; } + virtual bool isUnvisited() const { return false; } + virtual bool isVisited() const { return false; } + virtual bool isRequired() const { return false; } + virtual bool isLinked() const { return false; } + virtual bool isExpanded() const; + virtual bool isVisible() const { return true; } + virtual bool isCollapsed() const { return false; } + virtual void setIsExpanded(bool) { } + + // In a multi-select list, many items can be selected but only one is active at a time. + virtual bool isSelectedOptionActive() const { return false; } + + virtual bool hasBoldFont() const { return false; } + virtual bool hasItalicFont() const { return false; } + bool hasMisspelling() const; + virtual bool hasPlainText() const { return false; } + virtual bool hasSameFont(RenderObject*) const { return false; } + virtual bool hasSameFontColor(RenderObject*) const { return false; } + virtual bool hasSameStyle(RenderObject*) const { return false; } + bool hasStaticText() const { return roleValue() == StaticTextRole; } + virtual bool hasUnderline() const { return false; } + + virtual bool canSetFocusAttribute() const { return false; } + virtual bool canSetTextRangeAttributes() const { return false; } + virtual bool canSetValueAttribute() const { return false; } + virtual bool canSetNumericValue() const { return false; } + virtual bool canSetSelectedAttribute() const { return false; } + virtual bool canSetSelectedChildrenAttribute() const { return false; } + virtual bool canSetExpandedAttribute() const { return false; } + + // A programmatic way to set a name on an AccessibleObject. + virtual void setAccessibleName(const AtomicString&) { } + + virtual Node* node() const { return 0; } + virtual RenderObject* renderer() const { return 0; } + virtual bool accessibilityIsIgnored() const { return true; } + + int blockquoteLevel() const; + virtual int headingLevel() const { return 0; } + virtual int tableLevel() const { return 0; } + virtual AccessibilityButtonState checkboxOrRadioValue() const; + virtual String valueDescription() const { return String(); } + virtual float valueForRange() const { return 0.0f; } + virtual float maxValueForRange() const { return 0.0f; } + virtual float minValueForRange() const { return 0.0f; } + virtual float stepValueForRange() const { return 0.0f; } + virtual AccessibilityObject* selectedRadioButton() { return 0; } + virtual AccessibilityObject* selectedTabItem() { return 0; } + virtual int layoutCount() const { return 0; } + virtual double estimatedLoadingProgress() const { return 0; } + static bool isARIAControl(AccessibilityRole); + static bool isARIAInput(AccessibilityRole); + virtual bool supportsARIAOwns() const { return false; } + virtual void ariaOwnsElements(AccessibilityChildrenVector&) const { } + virtual bool supportsARIAFlowTo() const { return false; } + virtual void ariaFlowToElements(AccessibilityChildrenVector&) const { } + virtual bool ariaHasPopup() const { return false; } + bool ariaIsMultiline() const; + virtual const AtomicString& invalidStatus() const; + bool supportsARIAExpanded() const; + AccessibilitySortDirection sortDirection() const; + + // ARIA drag and drop + virtual bool supportsARIADropping() const { return false; } + virtual bool supportsARIADragging() const { return false; } + virtual bool isARIAGrabbed() { return false; } + virtual void setARIAGrabbed(bool) { } + virtual void determineARIADropEffects(Vector&) { } + + // Called on the root AX object to return the deepest available element. + virtual AccessibilityObject* accessibilityHitTest(const LayoutPoint&) const { return 0; } + // Called on the AX object after the render tree determines which is the right AccessibilityRenderObject. + virtual AccessibilityObject* elementAccessibilityHitTest(const LayoutPoint&) const; + + virtual AccessibilityObject* focusedUIElement() const; + + virtual AccessibilityObject* firstChild() const { return 0; } + virtual AccessibilityObject* lastChild() const { return 0; } + virtual AccessibilityObject* previousSibling() const { return 0; } + virtual AccessibilityObject* nextSibling() const { return 0; } + virtual AccessibilityObject* parentObject() const = 0; + virtual AccessibilityObject* parentObjectUnignored() const; + virtual AccessibilityObject* parentObjectIfExists() const { return 0; } + static AccessibilityObject* firstAccessibleObjectFromNode(const Node*); + void findMatchingObjects(AccessibilitySearchCriteria*, AccessibilityChildrenVector&); + + virtual AccessibilityObject* observableObject() const { return 0; } + virtual void linkedUIElements(AccessibilityChildrenVector&) const { } + virtual AccessibilityObject* titleUIElement() const { return 0; } + virtual bool exposesTitleUIElement() const { return true; } + virtual AccessibilityObject* correspondingLabelForControlElement() const { return 0; } + virtual AccessibilityObject* correspondingControlForLabelElement() const { return 0; } + virtual AccessibilityObject* scrollBar(AccessibilityOrientation) { return 0; } + + virtual AccessibilityRole ariaRoleAttribute() const { return UnknownRole; } + virtual bool isPresentationalChildOfAriaRole() const { return false; } + virtual bool ariaRoleHasPresentationalChildren() const { return false; } + + void setRoleValue(AccessibilityRole role) { m_role = role; } + virtual AccessibilityRole roleValue() const { return m_role; } + virtual String ariaLabeledByAttribute() const { return String(); } + virtual String ariaDescribedByAttribute() const { return String(); } + virtual String accessibilityDescription() const { return String(); } + + virtual AXObjectCache* axObjectCache() const; + AXID axObjectID() const { return m_id; } + void setAXObjectID(AXID axObjectID) { m_id = axObjectID; } + + static AccessibilityObject* anchorElementForNode(Node*); + virtual Element* anchorElement() const { return 0; } + virtual Element* actionElement() const { return 0; } + virtual LayoutRect boundingBoxRect() const { return LayoutRect(); } + virtual LayoutRect elementRect() const = 0; + virtual LayoutSize size() const { return elementRect().size(); } + virtual LayoutPoint clickPoint(); + static LayoutRect boundingBoxForQuads(RenderObject*, const Vector&); + + virtual PlainTextRange selectedTextRange() const { return PlainTextRange(); } + unsigned selectionStart() const { return selectedTextRange().start; } + unsigned selectionEnd() const { return selectedTextRange().length; } + + virtual KURL url() const { return KURL(); } + virtual VisibleSelection selection() const { return VisibleSelection(); } + virtual String stringValue() const { return String(); } + virtual String title() const { return String(); } + virtual String helpText() const { return String(); } + virtual String textUnderElement() const { return String(); } + virtual String text() const { return String(); } + virtual int textLength() const { return 0; } + virtual String selectedText() const { return String(); } + virtual const AtomicString& accessKey() const { return nullAtom; } + const String& actionVerb() const; + virtual Widget* widget() const { return 0; } + virtual Widget* widgetForAttachmentView() const { return 0; } + Page* page() const; + virtual Document* document() const; + virtual FrameView* topDocumentFrameView() const { return 0; } + virtual FrameView* documentFrameView() const; + String language() const; + virtual unsigned hierarchicalLevel() const { return 0; } + const AtomicString& placeholderValue() const; + + virtual void setFocused(bool) { } + virtual void setSelectedText(const String&) { } + virtual void setSelectedTextRange(const PlainTextRange&) { } + virtual void setValue(const String&) { } + virtual void setValue(float) { } + virtual void setSelected(bool) { } + virtual void setSelectedRows(AccessibilityChildrenVector&) { } + + virtual void makeRangeVisible(const PlainTextRange&) { } + virtual bool press() const; + bool performDefaultAction() const { return press(); } + + virtual AccessibilityOrientation orientation() const; + virtual void increment() { } + virtual void decrement() { } + + virtual void childrenChanged() { } + virtual void contentChanged() { } + const AccessibilityChildrenVector& children(); + virtual void addChildren() { } + virtual bool canHaveChildren() const { return true; } + virtual bool hasChildren() const { return m_haveChildren; } + virtual void updateChildrenIfNecessary(); + virtual void setNeedsToUpdateChildren() { } + virtual void clearChildren(); + virtual void detachFromParent() { } + + virtual void selectedChildren(AccessibilityChildrenVector&) { } + virtual void visibleChildren(AccessibilityChildrenVector&) { } + virtual void tabChildren(AccessibilityChildrenVector&) { } + virtual bool shouldFocusActiveDescendant() const { return false; } + virtual AccessibilityObject* activeDescendant() const { return 0; } + virtual void handleActiveDescendantChanged() { } + virtual void handleAriaExpandedChanged() { } + bool isDescendantOfObject(const AccessibilityObject*) const; + bool isAncestorOfObject(const AccessibilityObject*) const; + + static AccessibilityRole ariaRoleToWebCoreRole(const String&); + const AtomicString& getAttribute(const QualifiedName&) const; + + virtual VisiblePositionRange visiblePositionRange() const { return VisiblePositionRange(); } + virtual VisiblePositionRange visiblePositionRangeForLine(unsigned) const { return VisiblePositionRange(); } + + VisiblePositionRange visiblePositionRangeForUnorderedPositions(const VisiblePosition&, const VisiblePosition&) const; + VisiblePositionRange positionOfLeftWord(const VisiblePosition&) const; + VisiblePositionRange positionOfRightWord(const VisiblePosition&) const; + VisiblePositionRange leftLineVisiblePositionRange(const VisiblePosition&) const; + VisiblePositionRange rightLineVisiblePositionRange(const VisiblePosition&) const; + VisiblePositionRange sentenceForPosition(const VisiblePosition&) const; + VisiblePositionRange paragraphForPosition(const VisiblePosition&) const; + VisiblePositionRange styleRangeForPosition(const VisiblePosition&) const; + VisiblePositionRange visiblePositionRangeForRange(const PlainTextRange&) const; + + String stringForVisiblePositionRange(const VisiblePositionRange&) const; + virtual LayoutRect boundsForVisiblePositionRange(const VisiblePositionRange&) const { return LayoutRect(); } + int lengthForVisiblePositionRange(const VisiblePositionRange&) const; + virtual void setSelectedVisiblePositionRange(const VisiblePositionRange&) const { } + + virtual VisiblePosition visiblePositionForPoint(const IntPoint&) const { return VisiblePosition(); } + VisiblePosition nextVisiblePosition(const VisiblePosition& visiblePos) const { return visiblePos.next(); } + VisiblePosition previousVisiblePosition(const VisiblePosition& visiblePos) const { return visiblePos.previous(); } + VisiblePosition nextWordEnd(const VisiblePosition&) const; + VisiblePosition previousWordStart(const VisiblePosition&) const; + VisiblePosition nextLineEndPosition(const VisiblePosition&) const; + VisiblePosition previousLineStartPosition(const VisiblePosition&) const; + VisiblePosition nextSentenceEndPosition(const VisiblePosition&) const; + VisiblePosition previousSentenceStartPosition(const VisiblePosition&) const; + VisiblePosition nextParagraphEndPosition(const VisiblePosition&) const; + VisiblePosition previousParagraphStartPosition(const VisiblePosition&) const; + virtual VisiblePosition visiblePositionForIndex(unsigned, bool /*lastIndexOK */) const { return VisiblePosition(); } + + virtual VisiblePosition visiblePositionForIndex(int) const { return VisiblePosition(); } + virtual int indexForVisiblePosition(const VisiblePosition&) const { return 0; } + + AccessibilityObject* accessibilityObjectForPosition(const VisiblePosition&) const; + int lineForPosition(const VisiblePosition&) const; + PlainTextRange plainTextRangeForVisiblePositionRange(const VisiblePositionRange&) const; + virtual int index(const VisiblePosition&) const { return -1; } + + virtual PlainTextRange doAXRangeForLine(unsigned) const { return PlainTextRange(); } + PlainTextRange doAXRangeForPosition(const IntPoint&) const; + virtual PlainTextRange doAXRangeForIndex(unsigned) const { return PlainTextRange(); } + PlainTextRange doAXStyleRangeForIndex(unsigned) const; + + virtual String doAXStringForRange(const PlainTextRange&) const { return String(); } + virtual LayoutRect doAXBoundsForRange(const PlainTextRange&) const { return LayoutRect(); } + String listMarkerTextForNodeAndPosition(Node*, const VisiblePosition&) const; + + unsigned doAXLineForIndex(unsigned); + + virtual String stringValueForMSAA() const { return String(); } + virtual String stringRoleForMSAA() const { return String(); } + virtual String nameForMSAA() const { return String(); } + virtual String descriptionForMSAA() const { return String(); } + virtual AccessibilityRole roleValueForMSAA() const { return roleValue(); } + + // Used by an ARIA tree to get all its rows. + void ariaTreeRows(AccessibilityChildrenVector&); + // Used by an ARIA tree item to get all of its direct rows that it can disclose. + void ariaTreeItemDisclosedRows(AccessibilityChildrenVector&); + // Used by an ARIA tree item to get only its content, and not its child tree items and groups. + void ariaTreeItemContent(AccessibilityChildrenVector&); + + // ARIA live-region features. + bool supportsARIALiveRegion() const; + bool isInsideARIALiveRegion() const; + virtual const AtomicString& ariaLiveRegionStatus() const { return nullAtom; } + virtual const AtomicString& ariaLiveRegionRelevant() const { return nullAtom; } + virtual bool ariaLiveRegionAtomic() const { return false; } + virtual bool ariaLiveRegionBusy() const { return false; } + + bool supportsARIAAttributes() const; + + // CSS3 Speech properties. + virtual ESpeak speakProperty() const { return SpeakNormal; } + + // Make this object visible by scrolling as many nested scrollable views as needed. + virtual void scrollToMakeVisible() const; + // Same, but if the whole object can't be made visible, try for this subrect, in local coordinates. + virtual void scrollToMakeVisibleWithSubFocus(const IntRect&) const; + // Scroll this object to a given point in global coordinates of the top-level window. + virtual void scrollToGlobalPoint(const IntPoint&) const; + +#if HAVE(ACCESSIBILITY) +#if PLATFORM(GTK) + AccessibilityObjectWrapper* wrapper() const; + void setWrapper(AccessibilityObjectWrapper*); +#else + AccessibilityObjectWrapper* wrapper() const { return m_wrapper.get(); } + void setWrapper(AccessibilityObjectWrapper* wrapper) + { + m_wrapper = wrapper; + } +#endif +#endif + +#if HAVE(ACCESSIBILITY) + // a platform-specific method for determining if an attachment is ignored + bool accessibilityIgnoreAttachment() const; + // gives platforms the opportunity to indicate if and how an object should be included + AccessibilityObjectInclusion accessibilityPlatformIncludesObject() const; +#else + bool accessibilityIgnoreAttachment() const { return true; } + AccessibilityObjectInclusion accessibilityPlatformIncludesObject() const { return DefaultBehavior; } +#endif + + // allows for an AccessibilityObject to update its render tree or perform + // other operations update type operations + void updateBackingStore(); + +protected: + AXID m_id; + AccessibilityChildrenVector m_children; + mutable bool m_haveChildren; + AccessibilityRole m_role; + + // If this object itself scrolls, return its ScrollableArea. + virtual ScrollableArea* getScrollableAreaIfScrollable() const { return 0; } + virtual void scrollTo(const IntPoint&) const { } + + virtual bool isDetached() const { return true; } + static bool isAccessibilityObjectSearchMatch(AccessibilityObject*, AccessibilitySearchCriteria*); + static bool isAccessibilityTextSearchMatch(AccessibilityObject*, AccessibilitySearchCriteria*); + static bool objectMatchesSearchCriteriaWithResultLimit(AccessibilityObject*, AccessibilitySearchCriteria*, AccessibilityChildrenVector&); + +#if PLATFORM(GTK) + bool allowsTextRanges() const; + unsigned getLengthForTextRange() const; +#else + bool allowsTextRanges() const { return isTextControl(); } + unsigned getLengthForTextRange() const { return text().length(); } +#endif + +#if PLATFORM(MAC) + RetainPtr m_wrapper; +#elif PLATFORM(WIN) && !OS(WINCE) + COMPtr m_wrapper; +#elif PLATFORM(GTK) + AtkObject* m_wrapper; +#elif PLATFORM(CHROMIUM) + RefPtr m_wrapper; +#endif +}; + +} // namespace WebCore + +#endif // AccessibilityObject_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/ActiveDOMObject.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/ActiveDOMObject.h new file mode 100644 index 000000000..db7ca66c0 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/ActiveDOMObject.h @@ -0,0 +1,95 @@ +/* + * Copyright (C) 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. + * + */ + +#ifndef ActiveDOMObject_h +#define ActiveDOMObject_h + +#include + +namespace WebCore { + + class ScriptExecutionContext; + + // FIXME: Move this class to it's own file. + class ContextDestructionObserver { + public: + explicit ContextDestructionObserver(ScriptExecutionContext*); + virtual void contextDestroyed(); + + ScriptExecutionContext* scriptExecutionContext() const { return m_scriptExecutionContext; } + + protected: + virtual ~ContextDestructionObserver(); + + ScriptExecutionContext* m_scriptExecutionContext; + }; + + class ActiveDOMObject : public ContextDestructionObserver { + public: + ActiveDOMObject(ScriptExecutionContext*, void* upcastPointer); + + virtual bool hasPendingActivity() const; + + // canSuspend() is used by the caller if there is a choice between suspending and stopping. + // For example, a page won't be suspended and placed in the back/forward cache if it has + // the objects that can not be suspended. + // However, 'suspend' can be called even if canSuspend() would return 'false'. That + // happens in step-by-step JS debugging for example - in this case it would be incorrect + // to stop the object. Exact semantics of suspend is up to the object then. + enum ReasonForSuspension { + JavaScriptDebuggerPaused, + WillShowDialog, + DocumentWillBecomeInactive + }; + virtual bool canSuspend() const; + virtual void suspend(ReasonForSuspension); + virtual void resume(); + virtual void stop(); + + template void setPendingActivity(T* thisObject) + { + ASSERT(thisObject == this); + thisObject->ref(); + m_pendingActivityCount++; + } + + template void unsetPendingActivity(T* thisObject) + { + ASSERT(m_pendingActivityCount > 0); + --m_pendingActivityCount; + thisObject->deref(); + } + + protected: + virtual ~ActiveDOMObject(); + + private: + unsigned m_pendingActivityCount; + }; + +} // namespace WebCore + +#endif // ActiveDOMObject_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AdjustViewSizeOrNot.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AdjustViewSizeOrNot.h new file mode 100644 index 000000000..0137ad910 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AdjustViewSizeOrNot.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2011 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 INC. 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 INC. 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 AdjustViewSizeOrNot_h +#define AdjustViewSizeOrNot_h + +namespace WebCore { + +enum AdjustViewSizeOrNot { + DoNotAdjustViewSize, + AdjustViewSize +}; + +} // namespace WebCore + +#endif // AdjustViewSizeOrNot_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AffineTransform.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AffineTransform.h new file mode 100644 index 000000000..7d83f592f --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AffineTransform.h @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2005, 2006 Apple Computer, Inc. All rights reserved. + * 2010 Dirk Schulze + * + * 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 AffineTransform_h +#define AffineTransform_h + +#include "TransformationMatrix.h" + +#include // for memcpy +#include + +#if USE(CG) +#include +#elif USE(CAIRO) +#include +#elif PLATFORM(OPENVG) +#include "VGUtils.h" +#elif PLATFORM(QT) +#include +#elif USE(SKIA) +#include +#elif PLATFORM(WX) && USE(WXGC) +#include +#endif + +namespace WebCore { + +class FloatPoint; +class FloatQuad; +class FloatRect; +class IntPoint; +class IntRect; +class TransformationMatrix; + +class AffineTransform { + WTF_MAKE_FAST_ALLOCATED; +public: + typedef double Transform[6]; + + AffineTransform(); + AffineTransform(double a, double b, double c, double d, double e, double f); + +#if USE(CG) + AffineTransform(const CGAffineTransform&); +#endif + + void setMatrix(double a, double b, double c, double d, double e, double f); + + void map(double x, double y, double& x2, double& y2) const; + + // Rounds the mapped point to the nearest integer value. + IntPoint mapPoint(const IntPoint&) const; + + FloatPoint mapPoint(const FloatPoint&) const; + + IntSize mapSize(const IntSize&) const; + + FloatSize mapSize(const FloatSize&) const; + + // Rounds the resulting mapped rectangle out. This is helpful for bounding + // box computations but may not be what is wanted in other contexts. + IntRect mapRect(const IntRect&) const; + + FloatRect mapRect(const FloatRect&) const; + FloatQuad mapQuad(const FloatQuad&) const; + + bool isIdentity() const; + + double a() const { return m_transform[0]; } + void setA(double a) { m_transform[0] = a; } + double b() const { return m_transform[1]; } + void setB(double b) { m_transform[1] = b; } + double c() const { return m_transform[2]; } + void setC(double c) { m_transform[2] = c; } + double d() const { return m_transform[3]; } + void setD(double d) { m_transform[3] = d; } + double e() const { return m_transform[4]; } + void setE(double e) { m_transform[4] = e; } + double f() const { return m_transform[5]; } + void setF(double f) { m_transform[5] = f; } + + void makeIdentity(); + + AffineTransform& multiply(const AffineTransform& other); + AffineTransform& scale(double); + AffineTransform& scale(double sx, double sy); + AffineTransform& scaleNonUniform(double sx, double sy); + AffineTransform& rotate(double d); + AffineTransform& rotateFromVector(double x, double y); + AffineTransform& translate(double tx, double ty); + AffineTransform& shear(double sx, double sy); + AffineTransform& flipX(); + AffineTransform& flipY(); + AffineTransform& skew(double angleX, double angleY); + AffineTransform& skewX(double angle); + AffineTransform& skewY(double angle); + + double xScale() const; + double yScale() const; + + double det() const; + bool isInvertible() const; + AffineTransform inverse() const; + + void blend(const AffineTransform& from, double progress); + + TransformationMatrix toTransformationMatrix() const; + + bool isIdentityOrTranslation() const + { + return m_transform[0] == 1 && m_transform[1] == 0 && m_transform[2] == 0 && m_transform[3] == 1; + } + + bool isIdentityOrTranslationOrFlipped() const + { + return m_transform[0] == 1 && m_transform[1] == 0 && m_transform[2] == 0 && (m_transform[3] == 1 || m_transform[3] == -1); + } + + bool preservesAxisAlignment() const + { + return (m_transform[1] == 0 && m_transform[2] == 0) || (m_transform[0] == 0 && m_transform[3] == 0); + } + + bool operator== (const AffineTransform& m2) const + { + return (m_transform[0] == m2.m_transform[0] + && m_transform[1] == m2.m_transform[1] + && m_transform[2] == m2.m_transform[2] + && m_transform[3] == m2.m_transform[3] + && m_transform[4] == m2.m_transform[4] + && m_transform[5] == m2.m_transform[5]); + } + + bool operator!=(const AffineTransform& other) const { return !(*this == other); } + + // *this = *this * t (i.e., a multRight) + AffineTransform& operator*=(const AffineTransform& t) + { + return multiply(t); + } + + // result = *this * t (i.e., a multRight) + AffineTransform operator*(const AffineTransform& t) const + { + AffineTransform result = *this; + result *= t; + return result; + } + +#if USE(CG) + operator CGAffineTransform() const; +#elif USE(CAIRO) + operator cairo_matrix_t() const; +#elif PLATFORM(OPENVG) + operator VGMatrix() const; +#elif PLATFORM(QT) + operator QTransform() const; +#elif USE(SKIA) + operator SkMatrix() const; +#elif PLATFORM(WX) && USE(WXGC) + operator wxGraphicsMatrix() const; +#endif + + static AffineTransform translation(double x, double y) + { + return AffineTransform(1, 0, 0, 1, x, y); + } + + // decompose the matrix into its component parts + typedef struct { + double scaleX, scaleY; + double angle; + double remainderA, remainderB, remainderC, remainderD; + double translateX, translateY; + } DecomposedType; + + bool decompose(DecomposedType&) const; + void recompose(const DecomposedType&); + +private: + void setMatrix(const Transform m) + { + if (m && m != m_transform) + memcpy(m_transform, m, sizeof(Transform)); + } + + Transform m_transform; +}; + +AffineTransform makeMapBetweenRects(const FloatRect& source, const FloatRect& dest); + +} + +#endif diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/Animation.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/Animation.h new file mode 100644 index 000000000..0a5f4d286 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/Animation.h @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2000 Lars Knoll (knoll@kde.org) + * (C) 2000 Antti Koivisto (koivisto@kde.org) + * (C) 2000 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef Animation_h +#define Animation_h + +#include "PlatformString.h" +#include "RenderStyleConstants.h" +#include "TimingFunction.h" +#include +#include + +namespace WebCore { + +const int cAnimateNone = 0; +const int cAnimateAll = -2; + +class Animation : public RefCounted { +public: + ~Animation(); + + static PassRefPtr create() { return adoptRef(new Animation); } + static PassRefPtr create(const Animation* o) { return adoptRef(new Animation(*o)); } + + bool isDelaySet() const { return m_delaySet; } + bool isDirectionSet() const { return m_directionSet; } + bool isDurationSet() const { return m_durationSet; } + bool isFillModeSet() const { return m_fillModeSet; } + bool isIterationCountSet() const { return m_iterationCountSet; } + bool isNameSet() const { return m_nameSet; } + bool isPlayStateSet() const { return m_playStateSet; } + bool isPropertySet() const { return m_propertySet; } + bool isTimingFunctionSet() const { return m_timingFunctionSet; } + + // Flags this to be the special "none" animation (animation-name: none) + bool isNoneAnimation() const { return m_isNone; } + // We can make placeholder Animation objects to keep the comma-separated lists + // of properties in sync. isValidAnimation means this is not a placeholder. + bool isValidAnimation() const { return !m_isNone && !m_name.isEmpty(); } + + bool isEmpty() const + { + return (!m_directionSet && !m_durationSet && !m_fillModeSet + && !m_nameSet && !m_playStateSet && !m_iterationCountSet + && !m_delaySet && !m_timingFunctionSet && !m_propertySet); + } + + bool isEmptyOrZeroDuration() const + { + return isEmpty() || (m_duration == 0 && m_delay <= 0); + } + + void clearDelay() { m_delaySet = false; } + void clearDirection() { m_directionSet = false; } + void clearDuration() { m_durationSet = false; } + void clearFillMode() { m_fillModeSet = false; } + void clearIterationCount() { m_iterationCountSet = false; } + void clearName() { m_nameSet = false; } + void clearPlayState() { m_playStateSet = AnimPlayStatePlaying; } + void clearProperty() { m_propertySet = false; } + void clearTimingFunction() { m_timingFunctionSet = false; } + + void clearAll() + { + clearDelay(); + clearDirection(); + clearDuration(); + clearFillMode(); + clearIterationCount(); + clearName(); + clearPlayState(); + clearProperty(); + clearTimingFunction(); + } + + double delay() const { return m_delay; } + + enum AnimationDirection { AnimationDirectionNormal, AnimationDirectionAlternate }; + AnimationDirection direction() const { return static_cast(m_direction); } + + unsigned fillMode() const { return m_fillMode; } + + double duration() const { return m_duration; } + + enum { IterationCountInfinite = -1 }; + int iterationCount() const { return m_iterationCount; } + const String& name() const { return m_name; } + EAnimPlayState playState() const { return static_cast(m_playState); } + int property() const { return m_property; } + const PassRefPtr timingFunction() const { return m_timingFunction; } + + void setDelay(double c) { m_delay = c; m_delaySet = true; } + void setDirection(AnimationDirection d) { m_direction = d; m_directionSet = true; } + void setDuration(double d) { ASSERT(d >= 0); m_duration = d; m_durationSet = true; } + void setFillMode(unsigned f) { m_fillMode = f; m_fillModeSet = true; } + void setIterationCount(int c) { m_iterationCount = c; m_iterationCountSet = true; } + void setName(const String& n) { m_name = n; m_nameSet = true; } + void setPlayState(EAnimPlayState d) { m_playState = d; m_playStateSet = true; } + void setProperty(int t) { m_property = t; m_propertySet = true; } + void setTimingFunction(PassRefPtr f) { m_timingFunction = f; m_timingFunctionSet = true; } + + void setIsNoneAnimation(bool n) { m_isNone = n; } + + Animation& operator=(const Animation& o); + + // return true if all members of this class match (excluding m_next) + bool animationsMatch(const Animation*, bool matchPlayStates = true) const; + + // return true every Animation in the chain (defined by m_next) match + bool operator==(const Animation& o) const { return animationsMatch(&o); } + bool operator!=(const Animation& o) const { return !(*this == o); } + + bool fillsBackwards() const { return m_fillModeSet && (m_fillMode == AnimationFillModeBackwards || m_fillMode == AnimationFillModeBoth); } + bool fillsForwards() const { return m_fillModeSet && (m_fillMode == AnimationFillModeForwards || m_fillMode == AnimationFillModeBoth); } + +private: + Animation(); + Animation(const Animation& o); + + String m_name; + int m_property; + int m_iterationCount; + double m_delay; + double m_duration; + RefPtr m_timingFunction; + unsigned m_direction : 1; // AnimationDirection + unsigned m_fillMode : 2; + + unsigned m_playState : 2; + + bool m_delaySet : 1; + bool m_directionSet : 1; + bool m_durationSet : 1; + bool m_fillModeSet : 1; + bool m_iterationCountSet : 1; + bool m_nameSet : 1; + bool m_playStateSet : 1; + bool m_propertySet : 1; + bool m_timingFunctionSet : 1; + + bool m_isNone : 1; + +public: + static double initialAnimationDelay() { return 0; } + static AnimationDirection initialAnimationDirection() { return AnimationDirectionNormal; } + static double initialAnimationDuration() { return 0; } + static unsigned initialAnimationFillMode() { return AnimationFillModeNone; } + static int initialAnimationIterationCount() { return 1; } + static const String& initialAnimationName(); + static EAnimPlayState initialAnimationPlayState() { return AnimPlayStatePlaying; } + static int initialAnimationProperty() { return cAnimateAll; } + static const PassRefPtr initialAnimationTimingFunction() { return CubicBezierTimingFunction::create(); } +}; + +} // namespace WebCore + +#endif // Animation_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AnimationController.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AnimationController.h new file mode 100644 index 000000000..ccdc6c4a4 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AnimationController.h @@ -0,0 +1,86 @@ +/* + * 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. + * 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 AnimationController_h +#define AnimationController_h + +#include "CSSPropertyNames.h" +#include +#include + +namespace WebCore { + +class AnimationBase; +class AnimationControllerPrivate; +class Document; +class Element; +class Frame; +class Node; +class RenderObject; +class RenderStyle; +class WebKitAnimationList; + +class AnimationController { +public: + AnimationController(Frame*); + ~AnimationController(); + + void cancelAnimations(RenderObject*); + PassRefPtr updateAnimations(RenderObject*, RenderStyle* newStyle); + PassRefPtr getAnimatedStyleForRenderer(RenderObject*); + + // This is called when an accelerated animation or transition has actually started to animate. + void notifyAnimationStarted(RenderObject*, double startTime); + + bool pauseAnimationAtTime(RenderObject*, const String& name, double t); // To be used only for testing + bool pauseTransitionAtTime(RenderObject*, const String& property, double t); // To be used only for testing + unsigned numberOfActiveAnimations(Document*) const; // To be used only for testing + + bool isRunningAnimationOnRenderer(RenderObject*, CSSPropertyID, bool isRunningNow = true) const; + bool isRunningAcceleratedAnimationOnRenderer(RenderObject*, CSSPropertyID, bool isRunningNow = true) const; + + void suspendAnimations(); + void resumeAnimations(); + + void suspendAnimationsForDocument(Document*); + void resumeAnimationsForDocument(Document*); + + void beginAnimationUpdate(); + void endAnimationUpdate(); + + static bool supportsAcceleratedAnimationOfProperty(CSSPropertyID); + + PassRefPtr animationsForRenderer(RenderObject*) const; + +private: + OwnPtr m_data; +}; + +} // namespace WebCore + +#endif // AnimationController_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AnimationList.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AnimationList.h new file mode 100644 index 000000000..bf8ff9f1e --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AnimationList.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2000 Lars Knoll (knoll@kde.org) + * (C) 2000 Antti Koivisto (koivisto@kde.org) + * (C) 2000 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef AnimationList_h +#define AnimationList_h + +#include "Animation.h" +#include +#include + +namespace WebCore { + +class AnimationList { + WTF_MAKE_FAST_ALLOCATED; +public: + AnimationList() { } + AnimationList(const AnimationList&); + + void fillUnsetProperties(); + bool operator==(const AnimationList& o) const; + bool operator!=(const AnimationList& o) const + { + return !(*this == o); + } + + size_t size() const { return m_animations.size(); } + bool isEmpty() const { return m_animations.isEmpty(); } + + void resize(size_t n) { m_animations.resize(n); } + void remove(size_t i) { m_animations.remove(i); } + void append(PassRefPtr anim) { m_animations.append(anim); } + + Animation* animation(size_t i) { return m_animations[i].get(); } + const Animation* animation(size_t i) const { return m_animations[i].get(); } + +private: + AnimationList& operator=(const AnimationList&); + + Vector > m_animations; +}; + + +} // namespace WebCore + +#endif // AnimationList_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AnimationUtilities.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AnimationUtilities.h new file mode 100644 index 000000000..aebca46bb --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AnimationUtilities.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2011 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 AnimationUtilities_h +#define AnimationUtilities_h + +#include + +namespace WebCore { + +inline int blend(int from, int to, double progress) +{ + return static_cast(lround(static_cast(from) + static_cast(to - from) * progress)); +} + +inline unsigned blend(unsigned from, unsigned to, double progress) +{ + return static_cast(lround(static_cast(from) + static_cast(to - from) * progress)); +} + +inline double blend(double from, double to, double progress) +{ + return from + (to - from) * progress; +} + +inline float blend(float from, float to, double progress) +{ + return static_cast(from + (to - from) * progress); +} + +} // namespace WebCore + +#endif // AnimationUtilities_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/ApplicationCache.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/ApplicationCache.h new file mode 100644 index 000000000..325e4c05b --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/ApplicationCache.h @@ -0,0 +1,118 @@ +/* + * Copyright (C) 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 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 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 ApplicationCache_h +#define ApplicationCache_h + +#include "PlatformString.h" +#include +#include +#include +#include +#include + +namespace WebCore { + +class ApplicationCacheGroup; +class ApplicationCacheResource; +class DocumentLoader; +class KURL; +class ResourceRequest; +class SecurityOrigin; + +typedef Vector > FallbackURLVector; + +class ApplicationCache : public RefCounted { +public: + static PassRefPtr create() { return adoptRef(new ApplicationCache); } + + static void deleteCacheForOrigin(SecurityOrigin*); + + ~ApplicationCache(); + + void addResource(PassRefPtr resource); + unsigned removeResource(const String& url); + + void setManifestResource(PassRefPtr manifest); + ApplicationCacheResource* manifestResource() const { return m_manifest; } + + void setGroup(ApplicationCacheGroup*); + ApplicationCacheGroup* group() const { return m_group; } + + bool isComplete() const; + + ApplicationCacheResource* resourceForRequest(const ResourceRequest&); + ApplicationCacheResource* resourceForURL(const String& url); + + void setAllowsAllNetworkRequests(bool value) { m_allowAllNetworkRequests = value; } + bool allowsAllNetworkRequests() const { return m_allowAllNetworkRequests; } + void setOnlineWhitelist(const Vector& onlineWhitelist); + const Vector& onlineWhitelist() const { return m_onlineWhitelist; } + bool isURLInOnlineWhitelist(const KURL&); // There is an entry in online whitelist that has the same origin as the resource's URL and that is a prefix match for the resource's URL. + + void setFallbackURLs(const FallbackURLVector&); + const FallbackURLVector& fallbackURLs() const { return m_fallbackURLs; } + bool urlMatchesFallbackNamespace(const KURL&, KURL* fallbackURL = 0); + +#ifndef NDEBUG + void dump(); +#endif + + typedef HashMap > ResourceMap; + ResourceMap::const_iterator begin() const { return m_resources.begin(); } + ResourceMap::const_iterator end() const { return m_resources.end(); } + + void setStorageID(unsigned storageID) { m_storageID = storageID; } + unsigned storageID() const { return m_storageID; } + void clearStorageID(); + + static bool requestIsHTTPOrHTTPSGet(const ResourceRequest&); + + static int64_t diskUsageForOrigin(SecurityOrigin*); + + int64_t estimatedSizeInStorage() const { return m_estimatedSizeInStorage; } + +private: + ApplicationCache(); + + ApplicationCacheGroup* m_group; + ResourceMap m_resources; + ApplicationCacheResource* m_manifest; + + bool m_allowAllNetworkRequests; + Vector m_onlineWhitelist; + FallbackURLVector m_fallbackURLs; + + // The total size of the resources belonging to this Application Cache instance. + // This is an estimation of the size this Application Cache occupies in the + // database file. + int64_t m_estimatedSizeInStorage; + + unsigned m_storageID; +}; + +} // namespace WebCore + +#endif // ApplicationCache_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/ApplicationCacheStorage.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/ApplicationCacheStorage.h new file mode 100644 index 000000000..0d35d18f7 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/ApplicationCacheStorage.h @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2008, 2010, 2011 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 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 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 ApplicationCacheStorage_h +#define ApplicationCacheStorage_h + +#include "PlatformString.h" +#include "SecurityOriginHash.h" +#include "SQLiteDatabase.h" +#include +#include +#include + +namespace WebCore { + +class ApplicationCache; +class ApplicationCacheGroup; +class ApplicationCacheHost; +class ApplicationCacheResource; +class KURL; +template +class StorageIDJournal; +class SecurityOrigin; + +class ApplicationCacheStorage { + WTF_MAKE_NONCOPYABLE(ApplicationCacheStorage); WTF_MAKE_FAST_ALLOCATED; +public: + enum FailureReason { + OriginQuotaReached, + TotalQuotaReached, + DiskOrOperationFailure + }; + + void setCacheDirectory(const String&); + const String& cacheDirectory() const; + + void setMaximumSize(int64_t size); + int64_t maximumSize() const; + bool isMaximumSizeReached() const; + int64_t spaceNeeded(int64_t cacheToSave); + + int64_t defaultOriginQuota() const { return m_defaultOriginQuota; } + void setDefaultOriginQuota(int64_t quota); + bool calculateUsageForOrigin(const SecurityOrigin*, int64_t& usage); + bool calculateQuotaForOrigin(const SecurityOrigin*, int64_t& quota); + bool calculateRemainingSizeForOriginExcludingCache(const SecurityOrigin*, ApplicationCache*, int64_t& remainingSize); + bool storeUpdatedQuotaForOrigin(const SecurityOrigin*, int64_t quota); + bool checkOriginQuota(ApplicationCacheGroup*, ApplicationCache* oldCache, ApplicationCache* newCache, int64_t& totalSpaceNeeded); + + ApplicationCacheGroup* cacheGroupForURL(const KURL&); // Cache to load a main resource from. + ApplicationCacheGroup* fallbackCacheGroupForURL(const KURL&); // Cache that has a fallback entry to load a main resource from if normal loading fails. + + ApplicationCacheGroup* findOrCreateCacheGroup(const KURL& manifestURL); + ApplicationCacheGroup* findInMemoryCacheGroup(const KURL& manifestURL) const; + void cacheGroupDestroyed(ApplicationCacheGroup*); + void cacheGroupMadeObsolete(ApplicationCacheGroup*); + + bool storeNewestCache(ApplicationCacheGroup*, ApplicationCache* oldCache, FailureReason& failureReason); + bool storeNewestCache(ApplicationCacheGroup*); // Updates the cache group, but doesn't remove old cache. + bool store(ApplicationCacheResource*, ApplicationCache*); + bool storeUpdatedType(ApplicationCacheResource*, ApplicationCache*); + + // Removes the group if the cache to be removed is the newest one (so, storeNewestCache() needs to be called beforehand when updating). + void remove(ApplicationCache*); + + void empty(); + + static bool storeCopyOfCache(const String& cacheDirectory, ApplicationCacheHost*); + + bool manifestURLs(Vector* urls); + bool cacheGroupSize(const String& manifestURL, int64_t* size); + bool deleteCacheGroup(const String& manifestURL); + void vacuumDatabaseFile(); + + void getOriginsWithCache(HashSet, SecurityOriginHash>&); + void deleteAllEntries(); + + static int64_t unknownQuota() { return -1; } + static int64_t noQuota() { return std::numeric_limits::max(); } +private: + ApplicationCacheStorage(); + PassRefPtr loadCache(unsigned storageID); + ApplicationCacheGroup* loadCacheGroup(const KURL& manifestURL); + + typedef StorageIDJournal ResourceStorageIDJournal; + typedef StorageIDJournal GroupStorageIDJournal; + + bool store(ApplicationCacheGroup*, GroupStorageIDJournal*); + bool store(ApplicationCache*, ResourceStorageIDJournal*); + bool store(ApplicationCacheResource*, unsigned cacheStorageID); + + bool ensureOriginRecord(const SecurityOrigin*); + bool shouldStoreResourceAsFlatFile(ApplicationCacheResource*); + void deleteTables(); + bool writeDataToUniqueFileInDirectory(SharedBuffer*, const String& directory, String& outFilename, const String& fileExtension); + + void loadManifestHostHashes(); + + void verifySchemaVersion(); + + void openDatabase(bool createIfDoesNotExist); + + bool executeStatement(SQLiteStatement&); + bool executeSQLCommand(const String&); + + void checkForMaxSizeReached(); + void checkForDeletedResources(); + long long flatFileAreaSize(); + + String m_cacheDirectory; + String m_cacheFile; + + int64_t m_maximumSize; + bool m_isMaximumSizeReached; + + int64_t m_defaultOriginQuota; + + SQLiteDatabase m_database; + + // In order to quickly determine if a given resource exists in an application cache, + // we keep a hash set of the hosts of the manifest URLs of all non-obsolete cache groups. + HashCountedSet m_cacheHostSet; + + typedef HashMap CacheGroupMap; + CacheGroupMap m_cachesInMemory; // Excludes obsolete cache groups. + + friend ApplicationCacheStorage& cacheStorage(); +}; + +ApplicationCacheStorage& cacheStorage(); + +} // namespace WebCore + +#endif // ApplicationCacheStorage_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/ApplyBlockElementCommand.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/ApplyBlockElementCommand.h new file mode 100644 index 000000000..4b6e5fbc2 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/ApplyBlockElementCommand.h @@ -0,0 +1,61 @@ +/* + * 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. + * * 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 ApplyBlockElementCommand_h +#define ApplyBlockElementCommand_h + +#include "CompositeEditCommand.h" +#include "QualifiedName.h" + +namespace WebCore { + +class ApplyBlockElementCommand : public CompositeEditCommand { +protected: + ApplyBlockElementCommand(Document*, const QualifiedName& tagName, const AtomicString& inlineStyle); + ApplyBlockElementCommand(Document*, const QualifiedName& tagName); + + virtual void formatSelection(const VisiblePosition& startOfSelection, const VisiblePosition& endOfSelection); + PassRefPtr createBlockElement() const; + const QualifiedName tagName() const { return m_tagName; } + +private: + virtual void doApply(); + virtual void formatRange(const Position& start, const Position& end, const Position& endOfSelection, RefPtr&) = 0; + void rangeForParagraphSplittingTextNodesIfNeeded(const VisiblePosition&, Position&, Position&); + VisiblePosition endOfNextParagrahSplittingTextNodesIfNeeded(VisiblePosition&, Position&, Position&); + + QualifiedName m_tagName; + AtomicString m_inlineStyle; + Position m_endOfLastParagraph; +}; + +} + +#endif diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/Archive.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/Archive.h new file mode 100644 index 000000000..d41c60872 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/Archive.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 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. + * 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 Archive_h +#define Archive_h + +#include "ArchiveResource.h" + +#include +#include +#include +#include + +namespace WebCore { + +class Archive : public RefCounted { +public: + enum Type { + WebArchive, + MHTML + }; + virtual ~Archive(); + virtual Type type() const = 0; + ArchiveResource* mainResource() { return m_mainResource.get(); } + const Vector >& subresources() const { return m_subresources; } + const Vector >& subframeArchives() const { return m_subframeArchives; } + +protected: + // These methods are meant for subclasses for different archive types to add resources in to the archive, + // and should not be exposed as archives should be immutable to clients + void setMainResource(PassRefPtr mainResource) { m_mainResource = mainResource; } + void addSubresource(PassRefPtr subResource) { m_subresources.append(subResource); } + void addSubframeArchive(PassRefPtr subframeArchive) { m_subframeArchives.append(subframeArchive); } + +private: + RefPtr m_mainResource; + Vector > m_subresources; + Vector > m_subframeArchives; +}; + +} + +#endif // Archive diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/ArchiveResource.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/ArchiveResource.h new file mode 100644 index 000000000..97d6e32f7 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/ArchiveResource.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2008, 2010 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 ArchiveResource_h +#define ArchiveResource_h + +#include "SubstituteResource.h" + +namespace WebCore { + +class ArchiveResource : public SubstituteResource { +public: + static PassRefPtr create(PassRefPtr, const KURL&, const ResourceResponse&); + static PassRefPtr create(PassRefPtr, const KURL&, + const String& mimeType, const String& textEncoding, const String& frameName, + const ResourceResponse& = ResourceResponse()); + + const String& mimeType() const { return m_mimeType; } + const String& textEncoding() const { return m_textEncoding; } + const String& frameName() const { return m_frameName; } + + void ignoreWhenUnarchiving() { m_shouldIgnoreWhenUnarchiving = true; } + bool shouldIgnoreWhenUnarchiving() const { return m_shouldIgnoreWhenUnarchiving; } + +private: + ArchiveResource(PassRefPtr, const KURL&, const String& mimeType, const String& textEncoding, const String& frameName, const ResourceResponse&); + + String m_mimeType; + String m_textEncoding; + String m_frameName; + + bool m_shouldIgnoreWhenUnarchiving; +}; + +} + +#endif // ArchiveResource_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/Arena.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/Arena.h new file mode 100644 index 000000000..06e09f2a5 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/Arena.h @@ -0,0 +1,139 @@ +/* + * Copyright (C) 1998-2000 Netscape Communications Corporation. + * Copyright (C) 2003-6 Apple Computer + * Copyright (C) Research In Motion Limited 2010. All rights reserved. + * + * Other contributors: + * Nick Blievers + * Jeff Hostetler + * Tom Rini + * Raffaele Sena + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Alternatively, the contents of this file may be used under the terms + * of either the Mozilla Public License Version 1.1, found at + * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public + * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html + * (the "GPL"), in which case the provisions of the MPL or the GPL are + * applicable instead of those above. If you wish to allow use of your + * version of this file only under the terms of one of those two + * licenses (the MPL or the GPL) and not to allow others to use your + * version of this file under the LGPL, indicate your decision by + * deletingthe provisions above and replace them with the notice and + * other provisions required by the MPL or the GPL, as the case may be. + * If you do not delete the provisions above, a recipient may use your + * version of this file under any of the LGPL, the MPL or the GPL. + */ + +#ifndef Arena_h +#define Arena_h + +#include + +// FIXME: We'd always like to use AllocAlignmentInteger for Arena alignment +// but there is concern over the memory growth this may cause. +#ifdef WTF_USE_ARENA_ALLOC_ALIGNMENT_INTEGER +#define ARENA_ALIGN_MASK (sizeof(WTF::AllocAlignmentInteger) - 1) +#else +#define ARENA_ALIGN_MASK 3 +#endif + +namespace WebCore { + +typedef uintptr_t uword; + +struct Arena { + Arena* next; // next arena + uword base; // aligned base address + uword limit; // end of arena (1+last byte) + uword avail; // points to next available byte in arena +}; + +struct ArenaPool { + Arena first; // first arena in pool list. + Arena* current; // current arena. + unsigned int arenasize; + uword mask; // Mask (power-of-2 - 1) +}; + +void InitArenaPool(ArenaPool *pool, const char *name, + unsigned int size, unsigned int align); +void FinishArenaPool(ArenaPool *pool); +void FreeArenaPool(ArenaPool *pool); +void* ArenaAllocate(ArenaPool *pool, unsigned int nb); + +#define ARENA_ALIGN(n) (((uword)(n) + ARENA_ALIGN_MASK) & ~ARENA_ALIGN_MASK) +#define INIT_ARENA_POOL(pool, name, size) \ + InitArenaPool(pool, name, size, ARENA_ALIGN_MASK + 1) + +#define ARENA_ALLOCATE(p, pool, nb) \ + Arena *_a = (pool)->current; \ + unsigned int _nb = ARENA_ALIGN(nb); \ + uword _p = _a->avail; \ + uword _q = _p + _nb; \ + if (_q > _a->limit) \ + _p = (uword)ArenaAllocate(pool, _nb); \ + else \ + _a->avail = _q; \ + p = (void *)_p; + +#define ARENA_GROW(p, pool, size, incr) \ + Arena *_a = (pool)->current; \ + unsigned int _incr = ARENA_ALIGN(incr); \ + uword _p = _a->avail; \ + uword _q = _p + _incr; \ + if (_p == (uword)(p) + ARENA_ALIGN(size) && \ + _q <= _a->limit) { \ + _a->avail = _q; \ + } else { \ + p = ArenaGrow(pool, p, size, incr); \ + } + +#define ARENA_MARK(pool) ((void *) (pool)->current->avail) +#define UPTRDIFF(p,q) ((uword)(p) - (uword)(q)) + +#ifdef DEBUG +#define FREE_PATTERN 0xDA +#define CLEAR_UNUSED(a) ASSERT((a)->avail <= (a)->limit); \ + memset((void*)(a)->avail, FREE_PATTERN, \ + (a)->limit - (a)->avail) +#define CLEAR_ARENA(a) memset((void*)(a), FREE_PATTERN, \ + (a)->limit - (uword)(a)) +#else +#define CLEAR_UNUSED(a) +#define CLEAR_ARENA(a) +#endif + +#define ARENA_RELEASE(pool, mark) \ + char *_m = (char *)(mark); \ + Arena *_a = (pool)->current; \ + if (UPTRDIFF(_m, _a->base) <= UPTRDIFF(_a->avail, _a->base)) { \ + _a->avail = (uword)ARENA_ALIGN(_m); \ + CLEAR_UNUSED(_a); \ + } else { \ + ArenaRelease(pool, _m); \ + } + +#define ARENA_DESTROY(pool, a, pnext) \ + if ((pool)->current == (a)) (pool)->current = &(pool)->first; \ + *(pnext) = (a)->next; \ + CLEAR_ARENA(a); \ + fastFree(a); \ + (a) = 0; + +} + +#endif diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AsyncFileStream.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AsyncFileStream.h new file mode 100644 index 000000000..a555a2467 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AsyncFileStream.h @@ -0,0 +1,74 @@ +/* + * 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. + * * 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 AsyncFileStream_h +#define AsyncFileStream_h + +#if ENABLE(BLOB) || ENABLE(FILE_SYSTEM) + +#include "FileStreamClient.h" +#include +#include + +namespace WebCore { + +class KURL; + +class AsyncFileStream : public RefCounted { +public: + virtual ~AsyncFileStream() { } + + virtual void getSize(const String& path, double expectedModificationTime) = 0; + virtual void openForRead(const String& path, long long offset, long long length) = 0; + virtual void openForWrite(const String& path) = 0; + virtual void close() = 0; + virtual void read(char* buffer, int length) = 0; + virtual void write(const KURL& blobURL, long long position, int length) = 0; + virtual void truncate(long long position) = 0; + virtual void stop() = 0; + + FileStreamClient* client() const { return m_client; } + void setClient(FileStreamClient* client) { m_client = client; } + +protected: + AsyncFileStream(FileStreamClient* client) + : m_client(client) + { + } + +private: + FileStreamClient* m_client; +}; + +} // namespace WebCore + +#endif // ENABLE(BLOB) || ENABLE(FILE_SYSTEM) + +#endif // AsyncFileStream_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/Attr.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/Attr.h new file mode 100644 index 000000000..7b6e332ee --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/Attr.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 1999 Lars Knoll (knoll@kde.org) + * (C) 1999 Antti Koivisto (koivisto@kde.org) + * (C) 2001 Peter Kelly (pmk@post.com) + * (C) 2001 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef Attr_h +#define Attr_h + +#include "ContainerNode.h" +#include "Attribute.h" + +namespace WebCore { + +// Attr can have Text and EntityReference children +// therefore it has to be a fullblown Node. The plan +// is to dynamically allocate a textchild and store the +// resulting nodevalue in the Attribute upon +// destruction. however, this is not yet implemented. + +class Attr : public ContainerNode { + friend class NamedNodeMap; +public: + static PassRefPtr create(Element*, Document*, PassRefPtr); + virtual ~Attr(); + + String name() const { return qualifiedName().toString(); } + bool specified() const { return m_specified; } + Element* ownerElement() const { return m_element; } + + const AtomicString& value() const { return m_attribute->value(); } + void setValue(const AtomicString&, ExceptionCode&); + void setValue(const AtomicString&); + + Attribute* attr() const { return m_attribute.get(); } + const QualifiedName& qualifiedName() const { return m_attribute->name(); } + + bool isId() const; + + // An extension to get presentational information for attributes. + CSSStyleDeclaration* style() { return m_attribute->decl(); } + + void setSpecified(bool specified) { m_specified = specified; } + +private: + Attr(Element*, Document*, PassRefPtr); + + void createTextChild(); + + virtual String nodeName() const; + virtual NodeType nodeType() const; + + const AtomicString& localName() const; + const AtomicString& namespaceURI() const; + const AtomicString& prefix() const; + + virtual void setPrefix(const AtomicString&, ExceptionCode&); + + virtual String nodeValue() const; + virtual void setNodeValue(const String&, ExceptionCode&); + virtual PassRefPtr cloneNode(bool deep); + + virtual bool isAttributeNode() const { return true; } + virtual bool childTypeAllowed(NodeType) const; + + virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); + + virtual const AtomicString& virtualPrefix() const { return prefix(); } + virtual const AtomicString& virtualLocalName() const { return localName(); } + virtual const AtomicString& virtualNamespaceURI() const { return namespaceURI(); } + + Element* m_element; + RefPtr m_attribute; + unsigned m_ignoreChildrenChanged : 31; + bool m_specified : 1; +}; + +} // namespace WebCore + +#endif // Attr_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/Attribute.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/Attribute.h new file mode 100644 index 000000000..6c2b468bb --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/Attribute.h @@ -0,0 +1,118 @@ +/* + * Copyright (C) 1999 Lars Knoll (knoll@kde.org) + * (C) 1999 Antti Koivisto (koivisto@kde.org) + * (C) 2001 Peter Kelly (pmk@post.com) + * (C) 2001 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2003, 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef Attribute_h +#define Attribute_h + +#include "CSSMappedAttributeDeclaration.h" +#include "QualifiedName.h" + +namespace WebCore { + +class Attr; +class CSSStyleDeclaration; +class Element; +class NamedNodeMap; + +// This has no counterpart in DOM. +// It is an internal representation of the node value of an Attr. +// The actual Attr with its value as a Text child is allocated only if needed. +class Attribute : public RefCounted { + friend class Attr; +public: + static PassRefPtr create(const QualifiedName& name, const AtomicString& value) + { + return adoptRef(new Attribute(name, value, false, 0)); + } + static PassRefPtr createMapped(const QualifiedName& name, const AtomicString& value) + { + return adoptRef(new Attribute(name, value, true, 0)); + } + static PassRefPtr createMapped(const AtomicString& name, const AtomicString& value) + { + return adoptRef(new Attribute(name, value, true, 0)); + } + + const AtomicString& value() const { return m_value; } + const AtomicString& prefix() const { return m_name.prefix(); } + const AtomicString& localName() const { return m_name.localName(); } + const AtomicString& namespaceURI() const { return m_name.namespaceURI(); } + + const QualifiedName& name() const { return m_name; } + + Attr* attr() const; + PassRefPtr createAttrIfNeeded(Element*); + + bool isNull() const { return m_value.isNull(); } + bool isEmpty() const { return m_value.isEmpty(); } + + PassRefPtr clone() const; + + CSSMappedAttributeDeclaration* decl() const { return m_styleDecl.get(); } + void setDecl(PassRefPtr decl) { m_styleDecl = decl; } + + void setValue(const AtomicString& value) { m_value = value; } + void setPrefix(const AtomicString& prefix) { m_name.setPrefix(prefix); } + + // Note: This API is only for HTMLTreeBuilder. It is not safe to change the + // name of an attribute once parseMappedAttribute has been called as DOM + // elements may have placed the Attribute in a hash by name. + void parserSetName(const QualifiedName& name) { m_name = name; } + + bool isMappedAttribute() { return m_isMappedAttribute; } + +private: + Attribute(const QualifiedName& name, const AtomicString& value, bool isMappedAttribute, CSSMappedAttributeDeclaration* styleDecl) + : m_isMappedAttribute(isMappedAttribute) + , m_hasAttr(false) + , m_name(name) + , m_value(value) + , m_styleDecl(styleDecl) + { + } + + Attribute(const AtomicString& name, const AtomicString& value, bool isMappedAttribute, CSSMappedAttributeDeclaration* styleDecl) + : m_isMappedAttribute(isMappedAttribute) + , m_hasAttr(false) + , m_name(nullAtom, name, nullAtom) + , m_value(value) + , m_styleDecl(styleDecl) + { + } + + void bindAttr(Attr*); + void unbindAttr(Attr*); + + // These booleans will go into the spare 32-bits of padding from RefCounted in 64-bit. + bool m_isMappedAttribute; + bool m_hasAttr; + + QualifiedName m_name; + AtomicString m_value; + RefPtr m_styleDecl; +}; + +} // namespace WebCore + +#endif // Attribute_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AuthenticationCF.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AuthenticationCF.h new file mode 100644 index 000000000..f1281cb91 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AuthenticationCF.h @@ -0,0 +1,56 @@ +/* + * 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. + */ + +#ifndef AuthenticationCF_h +#define AuthenticationCF_h + +#if USE(CFNETWORK) + +#include + +typedef struct _CFURLAuthChallenge* CFURLAuthChallengeRef; +typedef struct _CFURLProtectionSpace* CFURLProtectionSpaceRef; + +namespace WebCore { + +class AuthenticationChallenge; +class Credential; +class ProtectionSpace; + +CFURLAuthChallengeRef createCF(const AuthenticationChallenge&); +CFURLCredentialRef createCF(const Credential&); +CFURLProtectionSpaceRef createCF(const ProtectionSpace&); + +#if PLATFORM(MAC) +AuthenticationChallenge core(CFURLAuthChallengeRef); +#endif +Credential core(CFURLCredentialRef); +ProtectionSpace core(CFURLProtectionSpaceRef); + +} + +#endif // USE(CFNETWORK) + +#endif // AuthenticationCF_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AuthenticationChallenge.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AuthenticationChallenge.h new file mode 100644 index 000000000..109ede81b --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AuthenticationChallenge.h @@ -0,0 +1,85 @@ +/* + * 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. + */ + +#ifndef AuthenticationChallenge_h +#define AuthenticationChallenge_h + +#include "AuthenticationChallengeBase.h" +#include "AuthenticationClient.h" +#include + +#if USE(CFNETWORK) + +typedef struct _CFURLAuthChallenge* CFURLAuthChallengeRef; + +#else + +#ifndef __OBJC__ +typedef struct objc_object *id; +#endif + +OBJC_CLASS NSURLAuthenticationChallenge; + +#endif + +namespace WebCore { + +class AuthenticationChallenge : public AuthenticationChallengeBase { +public: + AuthenticationChallenge() {} + AuthenticationChallenge(const ProtectionSpace& protectionSpace, const Credential& proposedCredential, unsigned previousFailureCount, const ResourceResponse& response, const ResourceError& error); +#if USE(CFNETWORK) + AuthenticationChallenge(CFURLAuthChallengeRef, AuthenticationClient*); + + AuthenticationClient* authenticationClient() const; + void setAuthenticationClient(AuthenticationClient* client) { m_authenticationClient = client; } + + CFURLAuthChallengeRef cfURLAuthChallengeRef() const { return m_cfChallenge.get(); } +#else + AuthenticationChallenge(NSURLAuthenticationChallenge *); + + id sender() const { return m_sender.get(); } + NSURLAuthenticationChallenge *nsURLAuthenticationChallenge() const { return m_nsChallenge.get(); } + + void setAuthenticationClient(AuthenticationClient*); // Changes sender to one that invokes client methods. + AuthenticationClient* authenticationClient() const; +#endif + +private: + friend class AuthenticationChallengeBase; + static bool platformCompare(const AuthenticationChallenge& a, const AuthenticationChallenge& b); + +#if USE(CFNETWORK) + RefPtr m_authenticationClient; + RetainPtr m_cfChallenge; +#else + RetainPtr m_sender; // Always the same as [m_macChallenge.get() sender], cached here for performance. + RetainPtr m_nsChallenge; +#endif +}; + +} + +#endif diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AuthenticationChallengeBase.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AuthenticationChallengeBase.h new file mode 100644 index 000000000..9d8586600 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AuthenticationChallengeBase.h @@ -0,0 +1,70 @@ +/* + * 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. + */ +#ifndef AuthenticationChallengeBase_h +#define AuthenticationChallengeBase_h + +#include "Credential.h" +#include "ProtectionSpace.h" +#include "ResourceResponse.h" +#include "ResourceError.h" + +namespace WebCore { + +class AuthenticationChallenge; + +class AuthenticationChallengeBase { +public: + AuthenticationChallengeBase(); + AuthenticationChallengeBase(const ProtectionSpace& protectionSpace, const Credential& proposedCredential, unsigned previousFailureCount, const ResourceResponse& response, const ResourceError& error); + + unsigned previousFailureCount() const; + const Credential& proposedCredential() const; + const ProtectionSpace& protectionSpace() const; + const ResourceResponse& failureResponse() const; + const ResourceError& error() const; + + bool isNull() const; + void nullify(); + + static bool compare(const AuthenticationChallenge& a, const AuthenticationChallenge& b); + +protected: + // The AuthenticationChallenge subclass may "shadow" this method to compare platform specific fields + static bool platformCompare(const AuthenticationChallengeBase&, const AuthenticationChallengeBase&) { return true; } + + bool m_isNull; + ProtectionSpace m_protectionSpace; + Credential m_proposedCredential; + unsigned m_previousFailureCount; + ResourceResponse m_failureResponse; + ResourceError m_error; +}; + +inline bool operator==(const AuthenticationChallenge& a, const AuthenticationChallenge& b) { return AuthenticationChallengeBase::compare(a, b); } +inline bool operator!=(const AuthenticationChallenge& a, const AuthenticationChallenge& b) { return !(a == b); } + +} + +#endif diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AuthenticationClient.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AuthenticationClient.h new file mode 100644 index 000000000..1e17910e2 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AuthenticationClient.h @@ -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 INC. 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 INC. 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 AuthenticationClient_h +#define AuthenticationClient_h + +namespace WebCore { + +class AuthenticationChallenge; +class Credential; + +class AuthenticationClient { +public: + virtual void receivedCredential(const AuthenticationChallenge&, const Credential&) = 0; + virtual void receivedRequestToContinueWithoutCredential(const AuthenticationChallenge&) = 0; + virtual void receivedCancellation(const AuthenticationChallenge&) = 0; + + void ref() { refAuthenticationClient(); } + void deref() { derefAuthenticationClient(); } + +protected: + virtual ~AuthenticationClient() { } + +private: + virtual void refAuthenticationClient() = 0; + virtual void derefAuthenticationClient() = 0; +}; + +} + +#endif diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AuthenticationMac.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AuthenticationMac.h new file mode 100644 index 000000000..82d2db41d --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/AuthenticationMac.h @@ -0,0 +1,51 @@ +/* + * 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. + */ +#ifndef AuthenticationMac_h +#define AuthenticationMac_h + +#ifdef __OBJC__ + +@class NSURLAuthenticationChallenge; +@class NSURLCredential; +@class NSURLProtectionSpace; + +namespace WebCore { + +class AuthenticationChallenge; +class Credential; +class ProtectionSpace; + +NSURLAuthenticationChallenge *mac(const AuthenticationChallenge&); +NSURLProtectionSpace *mac(const ProtectionSpace&); +NSURLCredential *mac(const Credential&); + +AuthenticationChallenge core(NSURLAuthenticationChallenge *); +ProtectionSpace core(NSURLProtectionSpace *); +Credential core(NSURLCredential *); + +} +#endif // __OBJC__ + +#endif // AuthenticationMac_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/BackForwardController.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/BackForwardController.h new file mode 100644 index 000000000..379628a90 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/BackForwardController.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2010 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 INC. 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 INC. 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 BackForwardController_h +#define BackForwardController_h + +#include +#include +#include + +namespace WebCore { + +class BackForwardList; +class HistoryItem; +class Page; + +class BackForwardController { + WTF_MAKE_NONCOPYABLE(BackForwardController); WTF_MAKE_FAST_ALLOCATED; +public: + ~BackForwardController(); + + static PassOwnPtr create(Page*, PassRefPtr); + + BackForwardList* client() const { return m_client.get(); } + + bool canGoBackOrForward(int distance) const; + void goBackOrForward(int distance); + + bool goBack(); + bool goForward(); + + void addItem(PassRefPtr); + void setCurrentItem(HistoryItem*); + + int count() const; + int backCount() const; + int forwardCount() const; + + HistoryItem* itemAtIndex(int); + + bool isActive(); + + void close(); + + HistoryItem* backItem() { return itemAtIndex(-1); } + HistoryItem* currentItem() { return itemAtIndex(0); } + HistoryItem* forwardItem() { return itemAtIndex(1); } + + void markPagesForFullStyleRecalc(); + +private: + BackForwardController(Page*, PassRefPtr); + + Page* m_page; + RefPtr m_client; +}; + +} // namespace WebCore + +#endif // BackForwardController_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/BackForwardList.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/BackForwardList.h new file mode 100644 index 000000000..3f2881963 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/BackForwardList.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2006, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * 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: + * 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 BackForwardList_h +#define BackForwardList_h + +#include +#include + +namespace WebCore { + +class HistoryItem; + +// FIXME: Rename this class to BackForwardClient, and rename the +// getter in Page accordingly. +class BackForwardList : public RefCounted { +public: + virtual ~BackForwardList() + { + } + + virtual void addItem(PassRefPtr) = 0; + + virtual void goToItem(HistoryItem*) = 0; + + virtual HistoryItem* itemAtIndex(int) = 0; + virtual int backListCount() = 0; + virtual int forwardListCount() = 0; + + virtual bool isActive() = 0; + + virtual void close() = 0; + + // FIXME: Delete these once all callers are using BackForwardController + // instead of calling this directly. + HistoryItem* backItem() { return itemAtIndex(-1); } + HistoryItem* currentItem() { return itemAtIndex(0); } + HistoryItem* forwardItem() { return itemAtIndex(1); } +}; + +} // namespace WebCore + +#endif // BackForwardList_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/BackForwardListImpl.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/BackForwardListImpl.h new file mode 100644 index 000000000..0e5c26c93 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/BackForwardListImpl.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2006, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * 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: + * 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 BackForwardListImpl_h +#define BackForwardListImpl_h + +#include "BackForwardList.h" +#include +#include + +namespace WebCore { + +class Page; + +typedef Vector > HistoryItemVector; +typedef HashSet > HistoryItemHashSet; + +// FIXME: After renaming BackForwardList to BackForwardClient, +// rename this to BackForwardList. +class BackForwardListImpl : public BackForwardList { +public: + static PassRefPtr create(Page* page) { return adoptRef(new BackForwardListImpl(page)); } + virtual ~BackForwardListImpl(); + + Page* page() { return m_page; } + + virtual void addItem(PassRefPtr); + void goBack(); + void goForward(); + virtual void goToItem(HistoryItem*); + + HistoryItem* backItem(); + HistoryItem* currentItem(); + HistoryItem* forwardItem(); + virtual HistoryItem* itemAtIndex(int); + + void backListWithLimit(int, HistoryItemVector&); + void forwardListWithLimit(int, HistoryItemVector&); + + int capacity(); + void setCapacity(int); + bool enabled(); + void setEnabled(bool); + virtual int backListCount(); + virtual int forwardListCount(); + bool containsItem(HistoryItem*); + + virtual void close(); + bool closed(); + + void removeItem(HistoryItem*); + HistoryItemVector& entries(); + +private: + BackForwardListImpl(Page*); + + virtual bool isActive() { return enabled() && capacity(); } + + Page* m_page; + HistoryItemVector m_entries; + HistoryItemHashSet m_entryHash; + unsigned m_current; + unsigned m_capacity; + bool m_closed; + bool m_enabled; +}; + +} // namespace WebCore + +#endif // BackForwardListImpl_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/Base64.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/Base64.h new file mode 100644 index 000000000..70855de04 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/Base64.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2006 Alexey Proskuryakov + * Copyright (C) 2010 Patrick Gansterer + * + * 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 Base64_h +#define Base64_h + +#include +#include +#include + +namespace WebCore { + +enum Base64DecodePolicy { FailOnInvalidCharacter, IgnoreWhitespace, IgnoreInvalidCharacters }; + +void base64Encode(const char*, unsigned, Vector&, bool insertLFs = false); +void base64Encode(const Vector&, Vector&, bool insertLFs = false); +void base64Encode(const CString&, Vector&, bool insertLFs = false); +String base64Encode(const char*, unsigned, bool insertLFs = false); +String base64Encode(const Vector&, bool insertLFs = false); +String base64Encode(const CString&, bool insertLFs = false); + +bool base64Decode(const String&, Vector&, Base64DecodePolicy = FailOnInvalidCharacter); +bool base64Decode(const Vector&, Vector&, Base64DecodePolicy = FailOnInvalidCharacter); +bool base64Decode(const char*, unsigned, Vector&, Base64DecodePolicy = FailOnInvalidCharacter); + +inline void base64Encode(const Vector& in, Vector& out, bool insertLFs) +{ + base64Encode(in.data(), in.size(), out, insertLFs); +} + +inline void base64Encode(const CString& in, Vector& out, bool insertLFs) +{ + base64Encode(in.data(), in.length(), out, insertLFs); +} + +inline String base64Encode(const Vector& in, bool insertLFs) +{ + return base64Encode(in.data(), in.size(), insertLFs); +} + +inline String base64Encode(const CString& in, bool insertLFs) +{ + return base64Encode(in.data(), in.length(), insertLFs); +} + +} // namespace WebCore + +#endif // Base64_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/BidiContext.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/BidiContext.h new file mode 100644 index 000000000..9f45d6553 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/BidiContext.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2000 Lars Knoll (knoll@kde.org) + * Copyright (C) 2003, 2004, 2006, 2007, 2009, 2010 Apple Inc. All right reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef BidiContext_h +#define BidiContext_h + +#include +#include +#include +#include +#include + +namespace WebCore { + +enum BidiEmbeddingSource { + FromStyleOrDOM, + FromUnicode +}; + +// Used to keep track of explicit embeddings. +class BidiContext : public RefCounted { +public: + static PassRefPtr create(unsigned char level, WTF::Unicode::Direction, bool override = false, BidiEmbeddingSource = FromStyleOrDOM, BidiContext* parent = 0); + + BidiContext* parent() const { return m_parent.get(); } + unsigned char level() const { return m_level; } + WTF::Unicode::Direction dir() const { return static_cast(m_direction); } + bool override() const { return m_override; } + BidiEmbeddingSource source() const { return static_cast(m_source); } + + PassRefPtr copyStackRemovingUnicodeEmbeddingContexts(); +private: + BidiContext(unsigned char level, WTF::Unicode::Direction direction, bool override, BidiEmbeddingSource source, BidiContext* parent) + : m_level(level) + , m_direction(direction) + , m_override(override) + , m_source(source) + , m_parent(parent) + { + } + + static PassRefPtr createUncached(unsigned char level, WTF::Unicode::Direction, bool override, BidiEmbeddingSource, BidiContext* parent); + + unsigned char m_level; + unsigned m_direction : 5; // Direction + bool m_override : 1; + unsigned m_source : 1; // BidiEmbeddingSource + RefPtr m_parent; +}; + +inline unsigned char nextGreaterOddLevel(unsigned char level) +{ + return (level + 1) | 1; +} + +inline unsigned char nextGreaterEvenLevel(unsigned char level) +{ + return (level + 2) & ~1; +} + +bool operator==(const BidiContext&, const BidiContext&); + +} // namespace WebCore + +#endif // BidiContext_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/BidiResolver.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/BidiResolver.h new file mode 100644 index 000000000..5806ca55e --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/BidiResolver.h @@ -0,0 +1,920 @@ +/* + * Copyright (C) 2000 Lars Knoll (knoll@kde.org) + * Copyright (C) 2003, 2004, 2006, 2007, 2008 Apple Inc. All right reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef BidiResolver_h +#define BidiResolver_h + +#include "BidiContext.h" +#include "BidiRunList.h" +#include "TextDirection.h" +#include +#include +#include + +namespace WebCore { + +template struct MidpointState { + MidpointState() + { + reset(); + } + + void reset() + { + numMidpoints = 0; + currentMidpoint = 0; + betweenMidpoints = false; + } + + // The goal is to reuse the line state across multiple + // lines so we just keep an array around for midpoints and never clear it across multiple + // lines. We track the number of items and position using the two other variables. + Vector midpoints; + unsigned numMidpoints; + unsigned currentMidpoint; + bool betweenMidpoints; +}; + +// The BidiStatus at a given position (typically the end of a line) can +// be cached and then used to restart bidi resolution at that position. +struct BidiStatus { + BidiStatus() + : eor(WTF::Unicode::OtherNeutral) + , lastStrong(WTF::Unicode::OtherNeutral) + , last(WTF::Unicode::OtherNeutral) + { + } + + // Creates a BidiStatus representing a new paragraph root with a default direction. + // Uses TextDirection as it only has two possibilities instead of WTF::Unicode::Direction which has 19. + BidiStatus(TextDirection textDirection, bool isOverride) + { + WTF::Unicode::Direction direction = textDirection == LTR ? WTF::Unicode::LeftToRight : WTF::Unicode::RightToLeft; + eor = lastStrong = last = direction; + context = BidiContext::create(textDirection == LTR ? 0 : 1, direction, isOverride); + } + + BidiStatus(WTF::Unicode::Direction eorDir, WTF::Unicode::Direction lastStrongDir, WTF::Unicode::Direction lastDir, PassRefPtr bidiContext) + : eor(eorDir) + , lastStrong(lastStrongDir) + , last(lastDir) + , context(bidiContext) + { + } + + WTF::Unicode::Direction eor; + WTF::Unicode::Direction lastStrong; + WTF::Unicode::Direction last; + RefPtr context; +}; + +class BidiEmbedding { +public: + BidiEmbedding(WTF::Unicode::Direction direction, BidiEmbeddingSource source) + : m_direction(direction) + , m_source(source) + { + } + + WTF::Unicode::Direction direction() const { return m_direction; } + BidiEmbeddingSource source() const { return m_source; } +private: + WTF::Unicode::Direction m_direction; + BidiEmbeddingSource m_source; +}; + +inline bool operator==(const BidiStatus& status1, const BidiStatus& status2) +{ + return status1.eor == status2.eor && status1.last == status2.last && status1.lastStrong == status2.lastStrong && *(status1.context) == *(status2.context); +} + +inline bool operator!=(const BidiStatus& status1, const BidiStatus& status2) +{ + return !(status1 == status2); +} + +struct BidiCharacterRun { + BidiCharacterRun(int start, int stop, BidiContext* context, WTF::Unicode::Direction dir) + : m_start(start) + , m_stop(stop) + , m_override(context->override()) + , m_next(0) + { + if (dir == WTF::Unicode::OtherNeutral) + dir = context->dir(); + + m_level = context->level(); + + // add level of run (cases I1 & I2) + if (m_level % 2) { + if (dir == WTF::Unicode::LeftToRight || dir == WTF::Unicode::ArabicNumber || dir == WTF::Unicode::EuropeanNumber) + m_level++; + } else { + if (dir == WTF::Unicode::RightToLeft) + m_level++; + else if (dir == WTF::Unicode::ArabicNumber || dir == WTF::Unicode::EuropeanNumber) + m_level += 2; + } + } + + void destroy() { delete this; } + + int start() const { return m_start; } + int stop() const { return m_stop; } + unsigned char level() const { return m_level; } + bool reversed(bool visuallyOrdered) { return m_level % 2 && !visuallyOrdered; } + bool dirOverride(bool visuallyOrdered) { return m_override || visuallyOrdered; } + + BidiCharacterRun* next() const { return m_next; } + void setNext(BidiCharacterRun* next) { m_next = next; } + + unsigned char m_level; + int m_start; + int m_stop; + bool m_override; + BidiCharacterRun* m_next; +}; + +enum VisualDirectionOverride { + NoVisualOverride, + VisualLeftToRightOverride, + VisualRightToLeftOverride +}; + +// BidiResolver is WebKit's implementation of the Unicode Bidi Algorithm +// http://unicode.org/reports/tr9 +template class BidiResolver { + WTF_MAKE_NONCOPYABLE(BidiResolver); +public: + BidiResolver() + : m_direction(WTF::Unicode::OtherNeutral) + , m_reachedEndOfLine(false) + , m_emptyRun(true) + , m_nestedIsolateCount(0) + { + } + +#ifndef NDEBUG + ~BidiResolver(); +#endif + + const Iterator& position() const { return m_current; } + void setPositionIgnoringNestedIsolates(const Iterator& position) { m_current = position; } + void setPosition(const Iterator& position, unsigned nestedIsolatedCount) + { + m_current = position; + m_nestedIsolateCount = nestedIsolatedCount; + } + + void increment() { m_current.increment(); } + + BidiContext* context() const { return m_status.context.get(); } + void setContext(PassRefPtr c) { m_status.context = c; } + + void setLastDir(WTF::Unicode::Direction lastDir) { m_status.last = lastDir; } + void setLastStrongDir(WTF::Unicode::Direction lastStrongDir) { m_status.lastStrong = lastStrongDir; } + void setEorDir(WTF::Unicode::Direction eorDir) { m_status.eor = eorDir; } + + WTF::Unicode::Direction dir() const { return m_direction; } + void setDir(WTF::Unicode::Direction d) { m_direction = d; } + + const BidiStatus& status() const { return m_status; } + void setStatus(const BidiStatus s) { m_status = s; } + + MidpointState& midpointState() { return m_midpointState; } + + // The current algorithm handles nested isolates one layer of nesting at a time. + // But when we layout each isolated span, we will walk into (and ignore) all + // child isolated spans. + void enterIsolate() { m_nestedIsolateCount++; } + void exitIsolate() { ASSERT(m_nestedIsolateCount >= 1); m_nestedIsolateCount--; } + bool inIsolate() const { return m_nestedIsolateCount; } + + void embed(WTF::Unicode::Direction, BidiEmbeddingSource); + bool commitExplicitEmbedding(); + + void createBidiRunsForLine(const Iterator& end, VisualDirectionOverride = NoVisualOverride, bool hardLineBreak = false); + + BidiRunList& runs() { return m_runs; } + + // FIXME: This used to be part of deleteRuns() but was a layering violation. + // It's unclear if this is still needed. + void markCurrentRunEmpty() { m_emptyRun = true; } + + Vector& isolatedRuns() { return m_isolatedRuns; } + +protected: + // FIXME: Instead of InlineBidiResolvers subclassing this method, we should + // pass in some sort of Traits object which knows how to create runs for appending. + void appendRun(); + + Iterator m_current; + // sor and eor are "start of run" and "end of run" respectively and correpond + // to abreviations used in UBA spec: http://unicode.org/reports/tr9/#BD7 + Iterator m_sor; // Points to the first character in the current run. + Iterator m_eor; // Points to the last character in the current run. + Iterator m_last; + BidiStatus m_status; + WTF::Unicode::Direction m_direction; + Iterator endOfLine; + bool m_reachedEndOfLine; + Iterator m_lastBeforeET; // Before a EuropeanNumberTerminator + bool m_emptyRun; + + // FIXME: This should not belong to the resolver, but rather be passed + // into createBidiRunsForLine by the caller. + BidiRunList m_runs; + + MidpointState m_midpointState; + + unsigned m_nestedIsolateCount; + Vector m_isolatedRuns; + +private: + void raiseExplicitEmbeddingLevel(WTF::Unicode::Direction from, WTF::Unicode::Direction to); + void lowerExplicitEmbeddingLevel(WTF::Unicode::Direction from); + void checkDirectionInLowerRaiseEmbeddingLevel(); + + void updateStatusLastFromCurrentDirection(WTF::Unicode::Direction); + void reorderRunsFromLevels(); + + Vector m_currentExplicitEmbeddingSequence; +}; + +#ifndef NDEBUG +template +BidiResolver::~BidiResolver() +{ + // The owner of this resolver should have handled the isolated runs + // or should never have called enterIsolate(). + ASSERT(m_isolatedRuns.isEmpty()); + ASSERT(!m_nestedIsolateCount); +} +#endif + +template +void BidiResolver::appendRun() +{ + if (!m_emptyRun && !m_eor.atEnd()) { + unsigned startOffset = m_sor.offset(); + unsigned endOffset = m_eor.offset(); + + if (!endOfLine.atEnd() && endOffset >= endOfLine.offset()) { + m_reachedEndOfLine = true; + endOffset = endOfLine.offset(); + } + + if (endOffset >= startOffset) + m_runs.addRun(new Run(startOffset, endOffset + 1, context(), m_direction)); + + m_eor.increment(); + m_sor = m_eor; + } + + m_direction = WTF::Unicode::OtherNeutral; + m_status.eor = WTF::Unicode::OtherNeutral; +} + +template +void BidiResolver::embed(WTF::Unicode::Direction dir, BidiEmbeddingSource source) +{ + // Isolated spans compute base directionality during their own UBA run. + // Do not insert fake embed characters once we enter an isolated span. + ASSERT(!inIsolate()); + using namespace WTF::Unicode; + + ASSERT(dir == PopDirectionalFormat || dir == LeftToRightEmbedding || dir == LeftToRightOverride || dir == RightToLeftEmbedding || dir == RightToLeftOverride); + m_currentExplicitEmbeddingSequence.append(BidiEmbedding(dir, source)); +} + +template +void BidiResolver::checkDirectionInLowerRaiseEmbeddingLevel() +{ + using namespace WTF::Unicode; + + ASSERT(m_status.eor != OtherNeutral || m_eor.atEnd()); + ASSERT(m_status.last != NonSpacingMark + && m_status.last != BoundaryNeutral + && m_status.last != RightToLeftEmbedding + && m_status.last != LeftToRightEmbedding + && m_status.last != RightToLeftOverride + && m_status.last != LeftToRightOverride + && m_status.last != PopDirectionalFormat); + if (m_direction == OtherNeutral) + m_direction = m_status.lastStrong == LeftToRight ? LeftToRight : RightToLeft; +} + +template +void BidiResolver::lowerExplicitEmbeddingLevel(WTF::Unicode::Direction from) +{ + using namespace WTF::Unicode; + + if (!m_emptyRun && m_eor != m_last) { + checkDirectionInLowerRaiseEmbeddingLevel(); + // bidi.sor ... bidi.eor ... bidi.last eor; need to append the bidi.sor-bidi.eor run or extend it through bidi.last + if (from == LeftToRight) { + // bidi.sor ... bidi.eor ... bidi.last L + if (m_status.eor == EuropeanNumber) { + if (m_status.lastStrong != LeftToRight) { + m_direction = EuropeanNumber; + appendRun(); + } + } else if (m_status.eor == ArabicNumber) { + m_direction = ArabicNumber; + appendRun(); + } else if (m_status.lastStrong != LeftToRight) { + appendRun(); + m_direction = LeftToRight; + } + } else if (m_status.eor == EuropeanNumber || m_status.eor == ArabicNumber || m_status.lastStrong == LeftToRight) { + appendRun(); + m_direction = RightToLeft; + } + m_eor = m_last; + } + + appendRun(); + m_emptyRun = true; + + // sor for the new run is determined by the higher level (rule X10) + setLastDir(from); + setLastStrongDir(from); + m_eor = Iterator(); +} + +template +void BidiResolver::raiseExplicitEmbeddingLevel(WTF::Unicode::Direction from, WTF::Unicode::Direction to) +{ + using namespace WTF::Unicode; + + if (!m_emptyRun && m_eor != m_last) { + checkDirectionInLowerRaiseEmbeddingLevel(); + // bidi.sor ... bidi.eor ... bidi.last eor; need to append the bidi.sor-bidi.eor run or extend it through bidi.last + if (to == LeftToRight) { + // bidi.sor ... bidi.eor ... bidi.last L + if (m_status.eor == EuropeanNumber) { + if (m_status.lastStrong != LeftToRight) { + m_direction = EuropeanNumber; + appendRun(); + } + } else if (m_status.eor == ArabicNumber) { + m_direction = ArabicNumber; + appendRun(); + } else if (m_status.lastStrong != LeftToRight && from == LeftToRight) { + appendRun(); + m_direction = LeftToRight; + } + } else if (m_status.eor == ArabicNumber + || (m_status.eor == EuropeanNumber && (m_status.lastStrong != LeftToRight || from == RightToLeft)) + || (m_status.eor != EuropeanNumber && m_status.lastStrong == LeftToRight && from == RightToLeft)) { + appendRun(); + m_direction = RightToLeft; + } + m_eor = m_last; + } + + appendRun(); + m_emptyRun = true; + + setLastDir(to); + setLastStrongDir(to); + m_eor = Iterator(); +} + +template +bool BidiResolver::commitExplicitEmbedding() +{ + // This gets called from bidiFirst when setting up our start position. + ASSERT(!inIsolate() || m_currentExplicitEmbeddingSequence.isEmpty()); + + using namespace WTF::Unicode; + + unsigned char fromLevel = context()->level(); + RefPtr toContext = context(); + + for (size_t i = 0; i < m_currentExplicitEmbeddingSequence.size(); ++i) { + BidiEmbedding embedding = m_currentExplicitEmbeddingSequence[i]; + if (embedding.direction() == PopDirectionalFormat) { + if (BidiContext* parentContext = toContext->parent()) + toContext = parentContext; + } else { + Direction direction = (embedding.direction() == RightToLeftEmbedding || embedding.direction() == RightToLeftOverride) ? RightToLeft : LeftToRight; + bool override = embedding.direction() == LeftToRightOverride || embedding.direction() == RightToLeftOverride; + unsigned char level = toContext->level(); + if (direction == RightToLeft) + level = nextGreaterOddLevel(level); + else + level = nextGreaterEvenLevel(level); + if (level < 61) + toContext = BidiContext::create(level, direction, override, embedding.source(), toContext.get()); + } + } + + unsigned char toLevel = toContext->level(); + + if (toLevel > fromLevel) + raiseExplicitEmbeddingLevel(fromLevel % 2 ? RightToLeft : LeftToRight, toLevel % 2 ? RightToLeft : LeftToRight); + else if (toLevel < fromLevel) + lowerExplicitEmbeddingLevel(fromLevel % 2 ? RightToLeft : LeftToRight); + + setContext(toContext); + + m_currentExplicitEmbeddingSequence.clear(); + + return fromLevel != toLevel; +} + +template +inline void BidiResolver::updateStatusLastFromCurrentDirection(WTF::Unicode::Direction dirCurrent) +{ + using namespace WTF::Unicode; + switch (dirCurrent) { + case EuropeanNumberTerminator: + if (m_status.last != EuropeanNumber) + m_status.last = EuropeanNumberTerminator; + break; + case EuropeanNumberSeparator: + case CommonNumberSeparator: + case SegmentSeparator: + case WhiteSpaceNeutral: + case OtherNeutral: + switch (m_status.last) { + case LeftToRight: + case RightToLeft: + case RightToLeftArabic: + case EuropeanNumber: + case ArabicNumber: + m_status.last = dirCurrent; + break; + default: + m_status.last = OtherNeutral; + } + break; + case NonSpacingMark: + case BoundaryNeutral: + case RightToLeftEmbedding: + case LeftToRightEmbedding: + case RightToLeftOverride: + case LeftToRightOverride: + case PopDirectionalFormat: + // ignore these + break; + case EuropeanNumber: + // fall through + default: + m_status.last = dirCurrent; + } +} + +template +inline void BidiResolver::reorderRunsFromLevels() +{ + unsigned char levelLow = 128; + unsigned char levelHigh = 0; + for (Run* run = m_runs.firstRun(); run; run = run->next()) { + levelHigh = std::max(run->level(), levelHigh); + levelLow = std::min(run->level(), levelLow); + } + + // This implements reordering of the line (L2 according to Bidi spec): + // http://unicode.org/reports/tr9/#L2 + // L2. From the highest level found in the text to the lowest odd level on each line, + // reverse any contiguous sequence of characters that are at that level or higher. + + // Reversing is only done up to the lowest odd level. + if (!(levelLow % 2)) + levelLow++; + + unsigned count = m_runs.runCount() - 1; + + while (levelHigh >= levelLow) { + unsigned i = 0; + Run* run = m_runs.firstRun(); + while (i < count) { + for (;i < count && run && run->level() < levelHigh; i++) + run = run->next(); + unsigned start = i; + for (;i <= count && run && run->level() >= levelHigh; i++) + run = run->next(); + unsigned end = i - 1; + m_runs.reverseRuns(start, end); + } + levelHigh--; + } +} + +template +void BidiResolver::createBidiRunsForLine(const Iterator& end, VisualDirectionOverride override, bool hardLineBreak) +{ + using namespace WTF::Unicode; + + ASSERT(m_direction == OtherNeutral); + + if (override != NoVisualOverride) { + m_emptyRun = false; + m_sor = m_current; + m_eor = Iterator(); + while (m_current != end && !m_current.atEnd()) { + m_eor = m_current; + increment(); + } + m_direction = override == VisualLeftToRightOverride ? LeftToRight : RightToLeft; + appendRun(); + m_runs.setLogicallyLastRun(m_runs.lastRun()); + if (override == VisualRightToLeftOverride) + m_runs.reverseRuns(0, m_runs.runCount() - 1); + return; + } + + m_emptyRun = true; + + m_eor = Iterator(); + + m_last = m_current; + bool pastEnd = false; + BidiResolver stateAtEnd; + + while (true) { + Direction dirCurrent; + if (pastEnd && (hardLineBreak || m_current.atEnd())) { + BidiContext* c = context(); + if (hardLineBreak) { + // A deviation from the Unicode Bidi Algorithm in order to match + // WinIE and user expectations: hard line breaks reset bidi state + // coming from unicode bidi control characters, but not those from + // DOM nodes with specified directionality + stateAtEnd.setContext(c->copyStackRemovingUnicodeEmbeddingContexts()); + + dirCurrent = stateAtEnd.context()->dir(); + stateAtEnd.setEorDir(dirCurrent); + stateAtEnd.setLastDir(dirCurrent); + stateAtEnd.setLastStrongDir(dirCurrent); + } else { + while (c->parent()) + c = c->parent(); + dirCurrent = c->dir(); + } + } else { + dirCurrent = m_current.direction(); + if (context()->override() + && dirCurrent != RightToLeftEmbedding + && dirCurrent != LeftToRightEmbedding + && dirCurrent != RightToLeftOverride + && dirCurrent != LeftToRightOverride + && dirCurrent != PopDirectionalFormat) + dirCurrent = context()->dir(); + else if (dirCurrent == NonSpacingMark) + dirCurrent = m_status.last; + } + + // We ignore all character directionality while in unicode-bidi: isolate spans. + // We'll handle ordering the isolated characters in a second pass. + if (inIsolate()) + dirCurrent = OtherNeutral; + + ASSERT(m_status.eor != OtherNeutral || m_eor.atEnd()); + switch (dirCurrent) { + + // embedding and overrides (X1-X9 in the Bidi specs) + case RightToLeftEmbedding: + case LeftToRightEmbedding: + case RightToLeftOverride: + case LeftToRightOverride: + case PopDirectionalFormat: + embed(dirCurrent, FromUnicode); + commitExplicitEmbedding(); + break; + + // strong types + case LeftToRight: + switch(m_status.last) { + case RightToLeft: + case RightToLeftArabic: + case EuropeanNumber: + case ArabicNumber: + if (m_status.last != EuropeanNumber || m_status.lastStrong != LeftToRight) + appendRun(); + break; + case LeftToRight: + break; + case EuropeanNumberSeparator: + case EuropeanNumberTerminator: + case CommonNumberSeparator: + case BoundaryNeutral: + case BlockSeparator: + case SegmentSeparator: + case WhiteSpaceNeutral: + case OtherNeutral: + if (m_status.eor == EuropeanNumber) { + if (m_status.lastStrong != LeftToRight) { + // the numbers need to be on a higher embedding level, so let's close that run + m_direction = EuropeanNumber; + appendRun(); + if (context()->dir() != LeftToRight) { + // the neutrals take the embedding direction, which is R + m_eor = m_last; + m_direction = RightToLeft; + appendRun(); + } + } + } else if (m_status.eor == ArabicNumber) { + // Arabic numbers are always on a higher embedding level, so let's close that run + m_direction = ArabicNumber; + appendRun(); + if (context()->dir() != LeftToRight) { + // the neutrals take the embedding direction, which is R + m_eor = m_last; + m_direction = RightToLeft; + appendRun(); + } + } else if (m_status.lastStrong != LeftToRight) { + //last stuff takes embedding dir + if (context()->dir() == RightToLeft) { + m_eor = m_last; + m_direction = RightToLeft; + } + appendRun(); + } + default: + break; + } + m_eor = m_current; + m_status.eor = LeftToRight; + m_status.lastStrong = LeftToRight; + m_direction = LeftToRight; + break; + case RightToLeftArabic: + case RightToLeft: + switch (m_status.last) { + case LeftToRight: + case EuropeanNumber: + case ArabicNumber: + appendRun(); + case RightToLeft: + case RightToLeftArabic: + break; + case EuropeanNumberSeparator: + case EuropeanNumberTerminator: + case CommonNumberSeparator: + case BoundaryNeutral: + case BlockSeparator: + case SegmentSeparator: + case WhiteSpaceNeutral: + case OtherNeutral: + if (m_status.eor == EuropeanNumber) { + if (m_status.lastStrong == LeftToRight && context()->dir() == LeftToRight) + m_eor = m_last; + appendRun(); + } else if (m_status.eor == ArabicNumber) + appendRun(); + else if (m_status.lastStrong == LeftToRight) { + if (context()->dir() == LeftToRight) + m_eor = m_last; + appendRun(); + } + default: + break; + } + m_eor = m_current; + m_status.eor = RightToLeft; + m_status.lastStrong = dirCurrent; + m_direction = RightToLeft; + break; + + // weak types: + + case EuropeanNumber: + if (m_status.lastStrong != RightToLeftArabic) { + // if last strong was AL change EN to AN + switch (m_status.last) { + case EuropeanNumber: + case LeftToRight: + break; + case RightToLeft: + case RightToLeftArabic: + case ArabicNumber: + m_eor = m_last; + appendRun(); + m_direction = EuropeanNumber; + break; + case EuropeanNumberSeparator: + case CommonNumberSeparator: + if (m_status.eor == EuropeanNumber) + break; + case EuropeanNumberTerminator: + case BoundaryNeutral: + case BlockSeparator: + case SegmentSeparator: + case WhiteSpaceNeutral: + case OtherNeutral: + if (m_status.eor == EuropeanNumber) { + if (m_status.lastStrong == RightToLeft) { + // ENs on both sides behave like Rs, so the neutrals should be R. + // Terminate the EN run. + appendRun(); + // Make an R run. + m_eor = m_status.last == EuropeanNumberTerminator ? m_lastBeforeET : m_last; + m_direction = RightToLeft; + appendRun(); + // Begin a new EN run. + m_direction = EuropeanNumber; + } + } else if (m_status.eor == ArabicNumber) { + // Terminate the AN run. + appendRun(); + if (m_status.lastStrong == RightToLeft || context()->dir() == RightToLeft) { + // Make an R run. + m_eor = m_status.last == EuropeanNumberTerminator ? m_lastBeforeET : m_last; + m_direction = RightToLeft; + appendRun(); + // Begin a new EN run. + m_direction = EuropeanNumber; + } + } else if (m_status.lastStrong == RightToLeft) { + // Extend the R run to include the neutrals. + m_eor = m_status.last == EuropeanNumberTerminator ? m_lastBeforeET : m_last; + m_direction = RightToLeft; + appendRun(); + // Begin a new EN run. + m_direction = EuropeanNumber; + } + default: + break; + } + m_eor = m_current; + m_status.eor = EuropeanNumber; + if (m_direction == OtherNeutral) + m_direction = LeftToRight; + break; + } + case ArabicNumber: + dirCurrent = ArabicNumber; + switch (m_status.last) { + case LeftToRight: + if (context()->dir() == LeftToRight) + appendRun(); + break; + case ArabicNumber: + break; + case RightToLeft: + case RightToLeftArabic: + case EuropeanNumber: + m_eor = m_last; + appendRun(); + break; + case CommonNumberSeparator: + if (m_status.eor == ArabicNumber) + break; + case EuropeanNumberSeparator: + case EuropeanNumberTerminator: + case BoundaryNeutral: + case BlockSeparator: + case SegmentSeparator: + case WhiteSpaceNeutral: + case OtherNeutral: + if (m_status.eor == ArabicNumber + || (m_status.eor == EuropeanNumber && (m_status.lastStrong == RightToLeft || context()->dir() == RightToLeft)) + || (m_status.eor != EuropeanNumber && m_status.lastStrong == LeftToRight && context()->dir() == RightToLeft)) { + // Terminate the run before the neutrals. + appendRun(); + // Begin an R run for the neutrals. + m_direction = RightToLeft; + } else if (m_direction == OtherNeutral) + m_direction = m_status.lastStrong == LeftToRight ? LeftToRight : RightToLeft; + m_eor = m_last; + appendRun(); + default: + break; + } + m_eor = m_current; + m_status.eor = ArabicNumber; + if (m_direction == OtherNeutral) + m_direction = ArabicNumber; + break; + case EuropeanNumberSeparator: + case CommonNumberSeparator: + break; + case EuropeanNumberTerminator: + if (m_status.last == EuropeanNumber) { + dirCurrent = EuropeanNumber; + m_eor = m_current; + m_status.eor = dirCurrent; + } else if (m_status.last != EuropeanNumberTerminator) + m_lastBeforeET = m_emptyRun ? m_eor : m_last; + break; + + // boundary neutrals should be ignored + case BoundaryNeutral: + if (m_eor == m_last) + m_eor = m_current; + break; + // neutrals + case BlockSeparator: + // ### what do we do with newline and paragraph seperators that come to here? + break; + case SegmentSeparator: + // ### implement rule L1 + break; + case WhiteSpaceNeutral: + break; + case OtherNeutral: + break; + default: + break; + } + + if (pastEnd && m_eor == m_current) { + if (!m_reachedEndOfLine) { + m_eor = endOfLine; + switch (m_status.eor) { + case LeftToRight: + case RightToLeft: + case ArabicNumber: + m_direction = m_status.eor; + break; + case EuropeanNumber: + m_direction = m_status.lastStrong == LeftToRight ? LeftToRight : EuropeanNumber; + break; + default: + ASSERT(false); + } + appendRun(); + } + m_current = end; + m_status = stateAtEnd.m_status; + m_sor = stateAtEnd.m_sor; + m_eor = stateAtEnd.m_eor; + m_last = stateAtEnd.m_last; + m_reachedEndOfLine = stateAtEnd.m_reachedEndOfLine; + m_lastBeforeET = stateAtEnd.m_lastBeforeET; + m_emptyRun = stateAtEnd.m_emptyRun; + m_direction = OtherNeutral; + break; + } + + updateStatusLastFromCurrentDirection(dirCurrent); + m_last = m_current; + + if (m_emptyRun) { + m_sor = m_current; + m_emptyRun = false; + } + + increment(); + if (!m_currentExplicitEmbeddingSequence.isEmpty()) { + bool committed = commitExplicitEmbedding(); + if (committed && pastEnd) { + m_current = end; + m_status = stateAtEnd.m_status; + m_sor = stateAtEnd.m_sor; + m_eor = stateAtEnd.m_eor; + m_last = stateAtEnd.m_last; + m_reachedEndOfLine = stateAtEnd.m_reachedEndOfLine; + m_lastBeforeET = stateAtEnd.m_lastBeforeET; + m_emptyRun = stateAtEnd.m_emptyRun; + m_direction = OtherNeutral; + break; + } + } + + if (!pastEnd && (m_current == end || m_current.atEnd())) { + if (m_emptyRun) + break; + stateAtEnd.m_status = m_status; + stateAtEnd.m_sor = m_sor; + stateAtEnd.m_eor = m_eor; + stateAtEnd.m_last = m_last; + stateAtEnd.m_reachedEndOfLine = m_reachedEndOfLine; + stateAtEnd.m_lastBeforeET = m_lastBeforeET; + stateAtEnd.m_emptyRun = m_emptyRun; + endOfLine = m_last; + pastEnd = true; + } + } + + m_runs.setLogicallyLastRun(m_runs.lastRun()); + reorderRunsFromLevels(); + endOfLine = Iterator(); +} + +} // namespace WebCore + +#endif // BidiResolver_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/BinaryPropertyList.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/BinaryPropertyList.h new file mode 100644 index 000000000..8cbb2e15a --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/BinaryPropertyList.h @@ -0,0 +1,109 @@ +/* + * 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 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 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 BinaryPropertyList_h +#define BinaryPropertyList_h + +#include + +#include +#include + +namespace WebCore { + +// Writes a limited subset of binary property lists. +// Covers only what's needed for writing browser history as of this writing. +class BinaryPropertyListObjectStream { +public: + // Call writeBooleanTrue to write the boolean true value. + // A single shared object will be used in the serialized list. + virtual void writeBooleanTrue() = 0; + + // Call writeInteger to write an integer value. + // A single shared object will be used for each integer in the serialized list. + virtual void writeInteger(int) = 0; + + // Call writeString to write a string value. + // A single shared object will be used for each string in the serialized list. + virtual void writeString(const String&) = 0; + + // Call writeUniqueString instead of writeString when it's unlikely the + // string will be written twice in the same property list; this saves hash + // table overhead for such strings. A separate object will be used for each + // of these strings in the serialized list. + virtual void writeUniqueString(const String&) = 0; + virtual void writeUniqueString(const char*) = 0; + + // Call writeIntegerArray instead of writeArrayStart/writeArrayEnd for + // arrays entirely composed of integers. A single shared object will be used + // for each identical array in the serialized list. Warning: The integer + // pointer must remain valid until the writeBinaryPropertyList function + // returns, because these lists are put into a hash table without copying + // them -- that's OK if the client already has a Vector. + virtual void writeIntegerArray(const int*, size_t) = 0; + + // After calling writeArrayStart, write array elements. + // Then call writeArrayEnd, passing in the result from writeArrayStart. + // A separate object will be used for each of these arrays in the serialized list. + virtual size_t writeArrayStart() = 0; + virtual void writeArrayEnd(size_t resultFromWriteArrayStart) = 0; + + // After calling writeDictionaryStart, write all keys, then all values. + // Then call writeDictionaryEnd, passing in the result from writeDictionaryStart. + // A separate object will be used for each dictionary in the serialized list. + virtual size_t writeDictionaryStart() = 0; + virtual void writeDictionaryEnd(size_t resultFromWriteDictionaryStart) = 0; + +protected: + virtual ~BinaryPropertyListObjectStream() { } +}; + +class BinaryPropertyListWriter { +public: + // Calls writeObjects once to prepare for writing and determine how big a + // buffer is required. Then calls buffer to get the appropriately-sized + // buffer, then calls writeObjects a second time and writes the property list. + void writePropertyList(); + +protected: + virtual ~BinaryPropertyListWriter() { } + +private: + // Called by writePropertyList. + // Must call the object stream functions for the objects to be written + // into the property list. + virtual void writeObjects(BinaryPropertyListObjectStream&) = 0; + + // Called by writePropertyList. + // Returns the buffer that the writer should write into. + virtual UInt8* buffer(size_t) = 0; + + friend class BinaryPropertyListPlan; + friend class BinaryPropertyListSerializer; +}; + +} + +#endif diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/BitmapImage.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/BitmapImage.h new file mode 100644 index 000000000..00802f69f --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/BitmapImage.h @@ -0,0 +1,293 @@ +/* + * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com) + * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2008-2009 Torch Mobile, Inc. + * + * 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 BitmapImage_h +#define BitmapImage_h + +#include "Image.h" +#include "Color.h" +#include "IntSize.h" + +#if PLATFORM(MAC) +#include +OBJC_CLASS NSImage; +#endif + +#if PLATFORM(WIN) +typedef struct HBITMAP__ *HBITMAP; +#endif + +namespace WebCore { + struct FrameData; +} + +namespace WTF { + // FIXME: This declaration gives FrameData a default constructor that zeroes + // all its data members, even though FrameData's default constructor defined + // below does not zero all its data members. One of these must be wrong! + template<> struct VectorTraits : public SimpleClassVectorTraits { }; +} + +namespace WebCore { + +template class Timer; + +// ================================================ +// FrameData Class +// ================================================ + +struct FrameData { + WTF_MAKE_NONCOPYABLE(FrameData); +public: + FrameData() + : m_frame(0) + , m_duration(0) + , m_haveMetadata(false) + , m_isComplete(false) + , m_hasAlpha(true) + { + } + + ~FrameData() + { + clear(true); + } + + // Clear the cached image data on the frame, and (optionally) the metadata. + // Returns whether there was cached image data to clear. + bool clear(bool clearMetadata); + + NativeImagePtr m_frame; + float m_duration; + bool m_haveMetadata : 1; + bool m_isComplete : 1; + bool m_hasAlpha : 1; +}; + +// ================================================= +// BitmapImage Class +// ================================================= + +class BitmapImage : public Image { + friend class GeneratedImage; + friend class CrossfadeGeneratedImage; + friend class GeneratorGeneratedImage; + friend class GraphicsContext; +public: + static PassRefPtr create(NativeImagePtr nativeImage, ImageObserver* observer = 0) + { + return adoptRef(new BitmapImage(nativeImage, observer)); + } + static PassRefPtr create(ImageObserver* observer = 0) + { + return adoptRef(new BitmapImage(observer)); + } + ~BitmapImage(); + + virtual bool isBitmapImage() const { return true; } + + virtual bool hasSingleSecurityOrigin() const { return true; } + + virtual IntSize size() const; + IntSize currentFrameSize() const; + virtual bool getHotSpot(IntPoint&) const; + + virtual bool dataChanged(bool allDataReceived); + virtual String filenameExtension() const; + + // It may look unusual that there is no start animation call as public API. This is because + // we start and stop animating lazily. Animation begins whenever someone draws the image. It will + // automatically pause once all observers no longer want to render the image anywhere. + virtual void stopAnimation(); + virtual void resetAnimation(); + + virtual unsigned decodedSize() const { return m_decodedSize; } + +#if PLATFORM(MAC) + // Accessors for native image formats. + virtual NSImage* getNSImage(); + virtual CFDataRef getTIFFRepresentation(); +#endif + +#if USE(CG) + virtual CGImageRef getCGImageRef(); + virtual CGImageRef getFirstCGImageRefOfSize(const IntSize&); + virtual RetainPtr getCGImageArray(); +#endif + +#if PLATFORM(WIN) || (PLATFORM(QT) && OS(WINDOWS)) + static PassRefPtr create(HBITMAP); +#endif +#if PLATFORM(WIN) + virtual bool getHBITMAP(HBITMAP); + virtual bool getHBITMAPOfSize(HBITMAP, LPSIZE); +#endif + +#if PLATFORM(GTK) + virtual GdkPixbuf* getGdkPixbuf(); +#endif + + virtual NativeImagePtr nativeImageForCurrentFrame() { return frameAtIndex(currentFrame()); } + bool frameHasAlphaAtIndex(size_t); + virtual bool currentFrameHasAlpha() { return frameHasAlphaAtIndex(currentFrame()); } + +#if !ASSERT_DISABLED + virtual bool notSolidColor() + { + return size().width() != 1 || size().height() != 1 || frameCount() > 1; + } +#endif + +protected: + enum RepetitionCountStatus { + Unknown, // We haven't checked the source's repetition count. + Uncertain, // We have a repetition count, but it might be wrong (some GIFs have a count after the image data, and will report "loop once" until all data has been decoded). + Certain // The repetition count is known to be correct. + }; + + BitmapImage(NativeImagePtr, ImageObserver* = 0); + BitmapImage(ImageObserver* = 0); + +#if PLATFORM(WIN) + virtual void drawFrameMatchingSourceSize(GraphicsContext*, const FloatRect& dstRect, const IntSize& srcSize, ColorSpace styleColorSpace, CompositeOperator); +#endif + virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator); + +#if (OS(WINCE) && !PLATFORM(QT)) + virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const AffineTransform& patternTransform, + const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator, const FloatRect& destRect); +#endif + + size_t currentFrame() const { return m_currentFrame; } + size_t frameCount(); + NativeImagePtr frameAtIndex(size_t); + bool frameIsCompleteAtIndex(size_t); + float frameDurationAtIndex(size_t); + + // Decodes and caches a frame. Never accessed except internally. + void cacheFrame(size_t index); + + // Called to invalidate cached data. When |destroyAll| is true, we wipe out + // the entire frame buffer cache and tell the image source to destroy + // everything; this is used when e.g. we want to free some room in the image + // cache. If |destroyAll| is false, we only delete frames up to the current + // one; this is used while animating large images to keep memory footprint + // low without redecoding the whole image on every frame. + virtual void destroyDecodedData(bool destroyAll = true); + + // If the image is large enough, calls destroyDecodedData() and passes + // |destroyAll| along. + void destroyDecodedDataIfNecessary(bool destroyAll); + + // Generally called by destroyDecodedData(), destroys whole-image metadata + // and notifies observers that the memory footprint has (hopefully) + // decreased by |framesCleared| times the size (in bytes) of a frame. + void destroyMetadataAndNotify(int framesCleared); + + // Whether or not size is available yet. + bool isSizeAvailable(); + + // Called after asking the source for any information that may require + // decoding part of the image (e.g., the image size). We need to report + // the partially decoded data to our observer so it has an accurate + // account of the BitmapImage's memory usage. + void didDecodeProperties() const; + + // Animation. + int repetitionCount(bool imageKnownToBeComplete); // |imageKnownToBeComplete| should be set if the caller knows the entire image has been decoded. + bool shouldAnimate(); + virtual void startAnimation(bool catchUpIfNecessary = true); + void advanceAnimation(Timer*); + + // Function that does the real work of advancing the animation. When + // skippingFrames is true, we're in the middle of a loop trying to skip over + // a bunch of animation frames, so we should not do things like decode each + // one or notify our observers. + // Returns whether the animation was advanced. + bool internalAdvanceAnimation(bool skippingFrames); + + // Handle platform-specific data + void initPlatformData(); + void invalidatePlatformData(); + + // Checks to see if the image is a 1x1 solid color. We optimize these images and just do a fill rect instead. + // This check should happen regardless whether m_checkedForSolidColor is already set, as the frame may have + // changed. + void checkForSolidColor(); + + virtual bool mayFillWithSolidColor() + { + if (!m_checkedForSolidColor && frameCount() > 0) { + checkForSolidColor(); + // WINCE PORT: checkForSolidColor() doesn't set m_checkedForSolidColor until + // it gets enough information to make final decision. +#if !OS(WINCE) + ASSERT(m_checkedForSolidColor); +#endif + } + return m_isSolidColor && m_currentFrame == 0; + } + virtual Color solidColor() const { return m_solidColor; } + + ImageSource m_source; + mutable IntSize m_size; // The size to use for the overall image (will just be the size of the first image). + + size_t m_currentFrame; // The index of the current frame of animation. + Vector m_frames; // An array of the cached frames of the animation. We have to ref frames to pin them in the cache. + + Timer* m_frameTimer; + int m_repetitionCount; // How many total animation loops we should do. This will be cAnimationNone if this image type is incapable of animation. + RepetitionCountStatus m_repetitionCountStatus; + int m_repetitionsComplete; // How many repetitions we've finished. + double m_desiredFrameStartTime; // The system time at which we hope to see the next call to startAnimation(). + +#if PLATFORM(MAC) + mutable RetainPtr m_nsImage; // A cached NSImage of frame 0. Only built lazily if someone actually queries for one. + mutable RetainPtr m_tiffRep; // Cached TIFF rep for frame 0. Only built lazily if someone queries for one. +#endif + + Color m_solidColor; // If we're a 1x1 solid color, this is the color to use to fill. + + unsigned m_decodedSize; // The current size of all decoded frames. + mutable unsigned m_decodedPropertiesSize; // The size of data decoded by the source to determine image properties (e.g. size, frame count, etc). + size_t m_frameCount; + + bool m_isSolidColor : 1; // Whether or not we are a 1x1 solid image. + bool m_checkedForSolidColor : 1; // Whether we've checked the frame for solid color. + + bool m_animationFinished : 1; // Whether or not we've completed the entire animation. + + bool m_allDataReceived : 1; // Whether or not we've received all our data. + mutable bool m_haveSize : 1; // Whether or not our |m_size| member variable has the final overall image size yet. + bool m_sizeAvailable : 1; // Whether or not we can obtain the size of the first image frame yet from ImageIO. + mutable bool m_hasUniformFrameSize : 1; + mutable bool m_haveFrameCount : 1; +}; + +} + +#endif diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/BlockExceptions.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/BlockExceptions.h new file mode 100644 index 000000000..b272f7e5c --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/BlockExceptions.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2003 Apple Computer, 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. + */ + +#import + +NO_RETURN_DUE_TO_ASSERT void ReportBlockedObjCException(NSException *); + +#define BEGIN_BLOCK_OBJC_EXCEPTIONS @try { +#define END_BLOCK_OBJC_EXCEPTIONS } @catch(NSException *localException) { ReportBlockedObjCException(localException); } + diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/BorderData.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/BorderData.h new file mode 100644 index 000000000..e65628a99 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/BorderData.h @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2000 Lars Knoll (knoll@kde.org) + * (C) 2000 Antti Koivisto (koivisto@kde.org) + * (C) 2000 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef BorderData_h +#define BorderData_h + +#include "BorderValue.h" +#include "IntRect.h" +#include "LengthSize.h" +#include "NinePieceImage.h" + +namespace WebCore { + +class BorderData { +friend class RenderStyle; +public: + BorderData() : m_topLeft(Length(0, Fixed), Length(0, Fixed)) + , m_topRight(Length(0, Fixed), Length(0, Fixed)) + , m_bottomLeft(Length(0, Fixed), Length(0, Fixed)) + , m_bottomRight(Length(0, Fixed), Length(0, Fixed)) + { + } + bool hasBorder() const + { + bool haveImage = m_image.hasImage(); + return m_left.nonZero(!haveImage) || m_right.nonZero(!haveImage) || m_top.nonZero(!haveImage) || m_bottom.nonZero(!haveImage); + } + + bool hasBorderRadius() const + { + if (!m_topLeft.width().isZero()) + return true; + if (!m_topRight.width().isZero()) + return true; + if (!m_bottomLeft.width().isZero()) + return true; + if (!m_bottomRight.width().isZero()) + return true; + return false; + } + + unsigned borderLeftWidth() const + { + if (!m_image.hasImage() && (m_left.style() == BNONE || m_left.style() == BHIDDEN)) + return 0; + return m_left.width(); + } + + unsigned borderRightWidth() const + { + if (!m_image.hasImage() && (m_right.style() == BNONE || m_right.style() == BHIDDEN)) + return 0; + return m_right.width(); + } + + unsigned borderTopWidth() const + { + if (!m_image.hasImage() && (m_top.style() == BNONE || m_top.style() == BHIDDEN)) + return 0; + return m_top.width(); + } + + unsigned borderBottomWidth() const + { + if (!m_image.hasImage() && (m_bottom.style() == BNONE || m_bottom.style() == BHIDDEN)) + return 0; + return m_bottom.width(); + } + + bool operator==(const BorderData& o) const + { + return m_left == o.m_left && m_right == o.m_right && m_top == o.m_top && m_bottom == o.m_bottom && m_image == o.m_image + && m_topLeft == o.m_topLeft && m_topRight == o.m_topRight && m_bottomLeft == o.m_bottomLeft && m_bottomRight == o.m_bottomRight; + } + + bool operator!=(const BorderData& o) const + { + return !(*this == o); + } + + const BorderValue& left() const { return m_left; } + const BorderValue& right() const { return m_right; } + const BorderValue& top() const { return m_top; } + const BorderValue& bottom() const { return m_bottom; } + + const NinePieceImage& image() const { return m_image; } + + const LengthSize& topLeft() const { return m_topLeft; } + const LengthSize& topRight() const { return m_topRight; } + const LengthSize& bottomLeft() const { return m_bottomLeft; } + const LengthSize& bottomRight() const { return m_bottomRight; } + +private: + BorderValue m_left; + BorderValue m_right; + BorderValue m_top; + BorderValue m_bottom; + + NinePieceImage m_image; + + LengthSize m_topLeft; + LengthSize m_topRight; + LengthSize m_bottomLeft; + LengthSize m_bottomRight; +}; + +} // namespace WebCore + +#endif // BorderData_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/BorderValue.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/BorderValue.h new file mode 100644 index 000000000..d9d404b85 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/BorderValue.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2000 Lars Knoll (knoll@kde.org) + * (C) 2000 Antti Koivisto (koivisto@kde.org) + * (C) 2000 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef BorderValue_h +#define BorderValue_h + +#include "Color.h" +#include "RenderStyleConstants.h" + +namespace WebCore { + +class BorderValue { +friend class RenderStyle; +public: + BorderValue() + : m_width(3) + , m_style(BNONE) + , m_isAuto(AUTO_OFF) + { + } + + bool nonZero(bool checkStyle = true) const + { + return width() && (!checkStyle || m_style != BNONE); + } + + bool isTransparent() const + { + return m_color.isValid() && !m_color.alpha(); + } + + bool isVisible(bool checkStyle = true) const + { + return nonZero(checkStyle) && !isTransparent() && (!checkStyle || m_style != BHIDDEN); + } + + bool operator==(const BorderValue& o) const + { + return m_width == o.m_width && m_style == o.m_style && m_color == o.m_color; + } + + bool operator!=(const BorderValue& o) const + { + return !(*this == o); + } + + const Color& color() const { return m_color; } + unsigned width() const { return m_width; } + EBorderStyle style() const { return static_cast(m_style); } + +protected: + Color m_color; + unsigned m_width : 27; + unsigned m_style : 4; // EBorderStyle + + // This is only used by OutlineValue but moved here to keep the bits packed. + unsigned m_isAuto : 1; // OutlineIsAuto +}; + +} // namespace WebCore + +#endif // BorderValue_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/Bridge.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/Bridge.h new file mode 100644 index 000000000..ff3c7f862 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/Bridge.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2003, 2008, 2009 Apple Inc. All rights reserved. + * Copyright 2010, The Android Open Source Project + * + * 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 Bridge_h +#define Bridge_h + +#include +#include + +namespace JSC { + +namespace Bindings { + +class Method { + WTF_MAKE_NONCOPYABLE(Method); WTF_MAKE_FAST_ALLOCATED; +public: + Method() { } + virtual int numParameters() const = 0; + + virtual ~Method() { } +}; + +} // namespace Bindings + +} // namespace JSC + +#endif diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/BridgeJSC.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/BridgeJSC.h new file mode 100644 index 000000000..a9f2baed0 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/BridgeJSC.h @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2003, 2008, 2009 Apple Inc. All rights reserved. + * Copyright 2010, The Android Open Source Project + * + * 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 BridgeJSC_h +#define BridgeJSC_h + +#include "Bridge.h" +#include +#include +#include +#include + +namespace JSC { + +class ArgList; +class Identifier; +class JSGlobalObject; +class PropertyNameArray; +class RuntimeMethod; + +namespace Bindings { + +class Instance; +class Method; +class RootObject; +class RuntimeObject; + +typedef Vector MethodList; + +class Field { +public: + virtual JSValue valueFromInstance(ExecState*, const Instance*) const = 0; + virtual void setValueToInstance(ExecState*, const Instance*, JSValue) const = 0; + + virtual ~Field() { } +}; + +class Class { + WTF_MAKE_NONCOPYABLE(Class); WTF_MAKE_FAST_ALLOCATED; +public: + Class() { } + virtual MethodList methodsNamed(const Identifier&, Instance*) const = 0; + virtual Field* fieldNamed(const Identifier&, Instance*) const = 0; + virtual JSValue fallbackObject(ExecState*, Instance*, const Identifier&) { return jsUndefined(); } + + virtual ~Class() { } +}; + +typedef void (*KJSDidExecuteFunctionPtr)(ExecState*, JSObject* rootObject); + +class Instance : public RefCounted { +public: + Instance(PassRefPtr); + + static void setDidExecuteFunction(KJSDidExecuteFunctionPtr func); + static KJSDidExecuteFunctionPtr didExecuteFunction(); + + // These functions are called before and after the main entry points into + // the native implementations. They can be used to establish and cleanup + // any needed state. + void begin(); + void end(); + + virtual Class* getClass() const = 0; + JSObject* createRuntimeObject(ExecState*); + void willInvalidateRuntimeObject(); + + // Returns false if the value was not set successfully. + virtual bool setValueOfUndefinedField(ExecState*, const Identifier&, JSValue) { return false; } + + virtual JSValue getMethod(ExecState* exec, const Identifier& propertyName) = 0; + virtual JSValue invokeMethod(ExecState*, RuntimeMethod* method) = 0; + + virtual bool supportsInvokeDefaultMethod() const { return false; } + virtual JSValue invokeDefaultMethod(ExecState*) { return jsUndefined(); } + + virtual bool supportsConstruct() const { return false; } + virtual JSValue invokeConstruct(ExecState*, const ArgList&) { return JSValue(); } + + virtual void getPropertyNames(ExecState*, PropertyNameArray&) { } + + virtual JSValue defaultValue(ExecState*, PreferredPrimitiveType) const = 0; + + virtual JSValue valueOf(ExecState* exec) const = 0; + + RootObject* rootObject() const; + + virtual ~Instance(); + + virtual bool getOwnPropertySlot(JSObject*, ExecState*, const Identifier&, PropertySlot&) { return false; } + virtual bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&) { return false; } + virtual void put(JSObject*, ExecState*, const Identifier&, JSValue, PutPropertySlot&) { } + +protected: + virtual void virtualBegin() { } + virtual void virtualEnd() { } + virtual RuntimeObject* newRuntimeObject(ExecState*); + + RefPtr m_rootObject; + +private: + Weak m_runtimeObject; +}; + +class Array { + WTF_MAKE_NONCOPYABLE(Array); +public: + Array(PassRefPtr); + virtual ~Array(); + + virtual void setValueAt(ExecState*, unsigned index, JSValue) const = 0; + virtual JSValue valueAt(ExecState*, unsigned index) const = 0; + virtual unsigned int getLength() const = 0; + +protected: + RefPtr m_rootObject; +}; + +const char* signatureForParameters(const ArgList&); + +typedef HashMap, MethodList*> MethodListMap; +typedef HashMap, Method*> MethodMap; +typedef HashMap, Field*> FieldMap; + +} // namespace Bindings + +} // namespace JSC + +#endif diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSComputedStyleDeclaration.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSComputedStyleDeclaration.h new file mode 100644 index 000000000..b7e686482 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSComputedStyleDeclaration.h @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2004 Zack Rusin + * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef CSSComputedStyleDeclaration_h +#define CSSComputedStyleDeclaration_h + +#include "CSSStyleDeclaration.h" +#include "RenderStyleConstants.h" +#include +#include + +namespace WebCore { + +class Color; +class CSSMutableStyleDeclaration; +class CSSPrimitiveValue; +class CSSValueList; +class CSSValuePool; +class Node; +class RenderStyle; +class ShadowData; +class SVGPaint; + +#if ENABLE(CSS_SHADERS) +class CustomFilterNumberParameter; +class CustomFilterParameter; +#endif + +enum EUpdateLayout { DoNotUpdateLayout = false, UpdateLayout = true }; + +class CSSComputedStyleDeclaration : public CSSStyleDeclaration { +public: + friend PassRefPtr computedStyle(PassRefPtr, bool allowVisitedStyle, const String& pseudoElementName); + virtual ~CSSComputedStyleDeclaration(); + + virtual String cssText() const; + + virtual unsigned virtualLength() const; + virtual String item(unsigned index) const; + + virtual PassRefPtr getPropertyCSSValue(int propertyID) const; + virtual String getPropertyValue(int propertyID) const; + virtual bool getPropertyPriority(int propertyID) const; + virtual int getPropertyShorthand(int /*propertyID*/) const { return -1; } + virtual bool isPropertyImplicit(int /*propertyID*/) const { return false; } + + virtual PassRefPtr copy() const; + virtual PassRefPtr makeMutable(); + + PassRefPtr getPropertyCSSValue(int propertyID, EUpdateLayout) const; + PassRefPtr getFontSizeCSSValuePreferringKeyword() const; + bool useFixedFontDefaultSize() const; +#if ENABLE(SVG) + PassRefPtr getSVGPropertyCSSValue(int propertyID, EUpdateLayout) const; +#endif + +protected: + virtual bool cssPropertyMatches(const CSSProperty*) const; + +private: + CSSComputedStyleDeclaration(PassRefPtr, bool allowVisitedStyle, const String&); + + virtual void setCssText(const String&, ExceptionCode&); + + virtual String removeProperty(int propertyID, ExceptionCode&); + virtual void setProperty(int propertyId, const String& value, bool important, ExceptionCode&); + + PassRefPtr valueForShadow(const ShadowData*, int, RenderStyle*) const; + PassRefPtr currentColorOrValidColor(RenderStyle*, const Color&) const; +#if ENABLE(SVG) + PassRefPtr adjustSVGPaintForCurrentColor(PassRefPtr, RenderStyle*) const; +#endif + +#if ENABLE(CSS_SHADERS) + PassRefPtr valueForCustomFilterNumberParameter(const CustomFilterNumberParameter*) const; + PassRefPtr valueForCustomFilterParameter(const CustomFilterParameter*) const; +#endif + +#if ENABLE(CSS_FILTERS) + PassRefPtr valueForFilter(RenderStyle*) const; +#endif + + PassRefPtr getCSSPropertyValuesForShorthandProperties(const int* properties, size_t) const; + PassRefPtr getCSSPropertyValuesForSidesShorthand(const int* properties) const; + + RefPtr m_node; + PseudoId m_pseudoElementSpecifier; + bool m_allowVisitedStyle; +}; + +inline PassRefPtr computedStyle(PassRefPtr node, bool allowVisitedStyle = false, const String& pseudoElementName = String()) +{ + return adoptRef(new CSSComputedStyleDeclaration(node, allowVisitedStyle, pseudoElementName)); +} + +} // namespace WebCore + +#endif // CSSComputedStyleDeclaration_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSCursorImageValue.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSCursorImageValue.h new file mode 100644 index 000000000..cb26919e4 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSCursorImageValue.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2006 Rob Buis + * Copyright (C) 2008 Apple Inc. All right reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef CSSCursorImageValue_h +#define CSSCursorImageValue_h + +#include "CSSImageValue.h" +#include "IntPoint.h" +#include + +namespace WebCore { + +class Element; +class SVGElement; + +class CSSCursorImageValue : public CSSImageValue { +public: + static PassRefPtr create(const String& url, const IntPoint& hotSpot) + { + return adoptRef(new CSSCursorImageValue(url, hotSpot)); + } + + ~CSSCursorImageValue(); + + IntPoint hotSpot() const { return m_hotSpot; } + + bool updateIfSVGCursorIsUsed(Element*); + StyleCachedImage* cachedImage(CachedResourceLoader*); + +#if ENABLE(SVG) + void removeReferencedElement(SVGElement*); +#endif + +private: + CSSCursorImageValue(const String& url, const IntPoint& hotSpot); + + IntPoint m_hotSpot; + +#if ENABLE(SVG) + HashSet m_referencedElements; +#endif +}; + +} // namespace WebCore + +#endif // CSSCursorImageValue_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSHelper.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSHelper.h new file mode 100644 index 000000000..6f2ffca9b --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSHelper.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 1999 Lars Knoll (knoll@kde.org) + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef CSSHelper_h +#define CSSHelper_h + +#include + +namespace WebCore { + +// We always assume 96 CSS pixels in a CSS inch. This is the cold hard truth of the Web. +// At high DPI, we may scale a CSS pixel, but the ratio of the CSS pixel to the so-called +// "absolute" CSS length units like inch and pt is always fixed and never changes. +const float cssPixelsPerInch = 96; + +} // namespace WebCore + +#endif // CSSHelper_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSImageGeneratorValue.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSImageGeneratorValue.h new file mode 100644 index 000000000..877969a90 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSImageGeneratorValue.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 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. + */ + +#ifndef CSSImageGeneratorValue_h +#define CSSImageGeneratorValue_h + +#include "CSSValue.h" +#include "IntSizeHash.h" +#include +#include + +namespace WebCore { + +class CachedResourceLoader; +class Image; +class RenderObject; + +struct SizeAndCount { + SizeAndCount(IntSize newSize = IntSize(), int newCount = 0) + : size(newSize) + , count(newCount) + { + } + + IntSize size; + int count; +}; + +typedef HashMap RenderObjectSizeCountMap; + +class CSSImageGeneratorValue : public CSSValue { +public: + ~CSSImageGeneratorValue(); + + void addClient(RenderObject*, const IntSize&); + void removeClient(RenderObject*); + PassRefPtr image(RenderObject*, const IntSize&); + + bool isFixedSize() const; + IntSize fixedSize(const RenderObject*); + + bool isPending() const; + + void loadSubimages(CachedResourceLoader*); + +protected: + CSSImageGeneratorValue(ClassType); + + Image* getImage(RenderObject*, const IntSize&); + void putImage(const IntSize&, PassRefPtr); + const RenderObjectSizeCountMap& clients() const { return m_clients; } + + HashCountedSet m_sizes; // A count of how many times a given image size is in use. + RenderObjectSizeCountMap m_clients; // A map from RenderObjects (with entry count) to image sizes. + HashMap > m_images; // A cache of Image objects by image size. +}; + +} // namespace WebCore + +#endif // CSSImageGeneratorValue_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSImageValue.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSImageValue.h new file mode 100644 index 000000000..82e34de4d --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSImageValue.h @@ -0,0 +1,62 @@ +/* + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef CSSImageValue_h +#define CSSImageValue_h + +#include "CSSPrimitiveValue.h" +#include + +namespace WebCore { + +class CachedResourceLoader; +class StyleCachedImage; +class StyleImage; + +class CSSImageValue : public CSSPrimitiveValue { +public: + static PassRefPtr create() { return adoptRef(new CSSImageValue); } + static PassRefPtr create(const String& url) { return adoptRef(new CSSImageValue(url)); } + static PassRefPtr create(const String& url, StyleImage* image) { return adoptRef(new CSSImageValue(url, image)); } + ~CSSImageValue(); + + StyleCachedImage* cachedImage(CachedResourceLoader*); + // Returns a StyleCachedImage if the image is cached already, otherwise a StylePendingImage. + StyleImage* cachedOrPendingImage(); + +protected: + CSSImageValue(ClassType, const String& url); + + StyleCachedImage* cachedImage(CachedResourceLoader*, const String& url); + String cachedImageURL(); + void clearCachedImage(); + +private: + CSSImageValue(); + explicit CSSImageValue(const String& url); + explicit CSSImageValue(const String& url, StyleImage*); + + RefPtr m_image; + bool m_accessedImage; +}; + +} // namespace WebCore + +#endif // CSSImageValue_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSImportRule.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSImportRule.h new file mode 100644 index 000000000..ad15087ba --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSImportRule.h @@ -0,0 +1,88 @@ +/* + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * (C) 2002-2003 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2002, 2006, 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef CSSImportRule_h +#define CSSImportRule_h + +#include "CSSRule.h" +#include "CachedResourceHandle.h" +#include "CachedStyleSheetClient.h" +#include "MediaList.h" +#include "PlatformString.h" + +namespace WebCore { + +class CachedCSSStyleSheet; +class MediaList; + +class CSSImportRule : public CSSRule { +public: + static PassRefPtr create(CSSStyleSheet* parent, const String& href, PassRefPtr media) + { + return adoptRef(new CSSImportRule(parent, href, media)); + } + + ~CSSImportRule(); + + String href() const { return m_strHref; } + MediaList* media() const { return m_lstMedia.get(); } + CSSStyleSheet* styleSheet() const { return m_styleSheet.get(); } + + String cssText() const; + + // Not part of the CSSOM + bool isLoading() const; + + void addSubresourceStyleURLs(ListHashSet& urls); + + void requestStyleSheet(); + +private: + // NOTE: We put the CachedStyleSheetClient in a member instead of inheriting from it + // to avoid adding a vptr to CSSImportRule. + class ImportedStyleSheetClient : public CachedStyleSheetClient { + public: + ImportedStyleSheetClient(CSSImportRule* ownerRule) : m_ownerRule(ownerRule) { } + virtual ~ImportedStyleSheetClient() { } + virtual void setCSSStyleSheet(const String& href, const KURL& baseURL, const String& charset, const CachedCSSStyleSheet* sheet) + { + m_ownerRule->setCSSStyleSheet(href, baseURL, charset, sheet); + } + private: + CSSImportRule* m_ownerRule; + }; + + void setCSSStyleSheet(const String& href, const KURL& baseURL, const String& charset, const CachedCSSStyleSheet*); + friend class ImportedStyleSheetClient; + + CSSImportRule(CSSStyleSheet* parent, const String& href, PassRefPtr); + + ImportedStyleSheetClient m_styleSheetClient; + String m_strHref; + RefPtr m_lstMedia; + RefPtr m_styleSheet; + CachedResourceHandle m_cachedSheet; + bool m_loading; +}; + +} // namespace WebCore + +#endif // CSSImportRule_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSLineBoxContainValue.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSLineBoxContainValue.h new file mode 100644 index 000000000..ddc0c60f3 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSLineBoxContainValue.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2011 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 INC. 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 INC. 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 CSSLineBoxContainValue_h +#define CSSLineBoxContainValue_h + +#include "CSSValue.h" +#include +#include + +namespace WebCore { + +class CSSPrimitiveValue; + +enum LineBoxContainFlags { LineBoxContainNone = 0x0, LineBoxContainBlock = 0x1, LineBoxContainInline = 0x2, LineBoxContainFont = 0x4, LineBoxContainGlyphs = 0x8, + LineBoxContainReplaced = 0x10, LineBoxContainInlineBox = 0x20 }; +typedef unsigned LineBoxContain; + +// Used for text-CSSLineBoxContain and box-CSSLineBoxContain +class CSSLineBoxContainValue : public CSSValue { +public: + static PassRefPtr create(LineBoxContain value) + { + return adoptRef(new CSSLineBoxContainValue(value)); + } + + String customCssText() const; + + LineBoxContain value() const { return m_value; } + +private: + LineBoxContain m_value; + +private: + CSSLineBoxContainValue(LineBoxContain); +}; + +} // namespace + +#endif diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSMappedAttributeDeclaration.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSMappedAttributeDeclaration.h new file mode 100644 index 000000000..a5b755144 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSMappedAttributeDeclaration.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 1999 Lars Knoll (knoll@kde.org) + * (C) 1999 Antti Koivisto (koivisto@kde.org) + * (C) 2001 Peter Kelly (pmk@post.com) + * (C) 2001 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2011 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef CSSMappedAttributeDeclaration_h +#define CSSMappedAttributeDeclaration_h + +#include "CSSMutableStyleDeclaration.h" +#include "MappedAttributeEntry.h" +#include "QualifiedName.h" + +namespace WebCore { + +class StyledElement; + +class CSSMappedAttributeDeclaration : public CSSMutableStyleDeclaration { +public: + static PassRefPtr create() + { + return adoptRef(new CSSMappedAttributeDeclaration); + } + + virtual ~CSSMappedAttributeDeclaration(); + + void setMappedState(MappedAttributeEntry type, const QualifiedName& name, const AtomicString& val) + { + m_entryType = type; + m_attrName = name; + m_attrValue = val; + } + + void setMappedProperty(StyledElement*, int propertyId, int value); + void setMappedProperty(StyledElement*, int propertyId, const String& value); + void setMappedImageProperty(StyledElement*, int propertyId, const String& url); + + // NOTE: setMappedLengthProperty() treats integers as pixels! (Needed for conversion of HTML attributes.) + void setMappedLengthProperty(StyledElement*, int propertyId, const String& value); + + void removeMappedProperty(StyledElement*, int propertyId); + +private: + CSSMappedAttributeDeclaration() + : CSSMutableStyleDeclaration() + , m_entryType(eNone) + , m_attrName(anyQName()) + { + } + + void setNeedsStyleRecalc(StyledElement*); + + MappedAttributeEntry m_entryType; + QualifiedName m_attrName; + AtomicString m_attrValue; +}; + +} //namespace + +#endif diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSMutableStyleDeclaration.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSMutableStyleDeclaration.h new file mode 100644 index 000000000..c6813f771 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSMutableStyleDeclaration.h @@ -0,0 +1,234 @@ +/* + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef CSSMutableStyleDeclaration_h +#define CSSMutableStyleDeclaration_h + +#include "CSSStyleDeclaration.h" +#include "CSSPrimitiveValue.h" +#include "CSSProperty.h" +#include "KURLHash.h" +#include "PlatformString.h" +#include +#include + +namespace WebCore { + +class StyledElement; + +class CSSMutableStyleDeclarationConstIterator { +public: + CSSMutableStyleDeclarationConstIterator(const CSSMutableStyleDeclaration* decl, CSSProperty* current); + CSSMutableStyleDeclarationConstIterator(const CSSMutableStyleDeclarationConstIterator& o); + ~CSSMutableStyleDeclarationConstIterator(); + + const CSSProperty& operator*() const { return *m_current; } + const CSSProperty* operator->() const { return m_current; } + + bool operator!=(const CSSMutableStyleDeclarationConstIterator& o) { ASSERT(m_decl == o.m_decl); return m_current != o.m_current; } + bool operator==(const CSSMutableStyleDeclarationConstIterator& o) { ASSERT(m_decl == o.m_decl); return m_current == o.m_current; } + + CSSMutableStyleDeclarationConstIterator& operator=(const CSSMutableStyleDeclarationConstIterator& o); + + CSSMutableStyleDeclarationConstIterator& operator++(); + CSSMutableStyleDeclarationConstIterator& operator--(); + +private: + const CSSMutableStyleDeclaration* m_decl; + CSSProperty* m_current; +}; + +class CSSMutableStyleDeclaration : public CSSStyleDeclaration { +public: + virtual ~CSSMutableStyleDeclaration(); + + static PassRefPtr create() + { + return adoptRef(new CSSMutableStyleDeclaration); + } + static PassRefPtr create(CSSRule* parentRule) + { + return adoptRef(new CSSMutableStyleDeclaration(parentRule)); + } + static PassRefPtr create(CSSRule* parentRule, const CSSProperty* const* properties, int numProperties) + { + return adoptRef(new CSSMutableStyleDeclaration(parentRule, properties, numProperties)); + } + static PassRefPtr create(const Vector& properties) + { + return adoptRef(new CSSMutableStyleDeclaration(0, properties)); + } + static PassRefPtr createInline(StyledElement* element) + { + return adoptRef(new CSSMutableStyleDeclaration(element, true)); + } + static PassRefPtr createForSVGFontFaceElement(StyledElement* element) + { + return adoptRef(new CSSMutableStyleDeclaration(element, false)); + } + + // Used by StyledElement::copyNonAttributeProperties(). + void copyPropertiesFrom(const CSSMutableStyleDeclaration&); + + typedef CSSMutableStyleDeclarationConstIterator const_iterator; + + const_iterator begin() { return const_iterator(this, m_properties.begin()); } + const_iterator end() { return const_iterator(this, m_properties.end()); } + + virtual String cssText() const; + virtual void setCssText(const String&, ExceptionCode&); + + virtual unsigned virtualLength() const; + unsigned length() const { return m_properties.size(); } + + virtual String item(unsigned index) const; + + virtual PassRefPtr getPropertyCSSValue(int propertyID) const; + virtual String getPropertyValue(int propertyID) const; + virtual bool getPropertyPriority(int propertyID) const; + virtual int getPropertyShorthand(int propertyID) const; + virtual bool isPropertyImplicit(int propertyID) const; + + virtual void setProperty(int propertyId, const String& value, bool important, ExceptionCode&); + virtual String removeProperty(int propertyID, ExceptionCode&); + + virtual PassRefPtr copy() const; + + using CSSStyleDeclaration::getPropertyCSSValue; + + bool setProperty(int propertyID, int value, bool important = false) { return setProperty(propertyID, value, important, true); } + bool setProperty(int propertyId, double value, CSSPrimitiveValue::UnitTypes unit, bool important = false) { return setProperty(propertyId, value, unit, important, true); } + bool setProperty(int propertyID, const String& value, bool important = false) { return setProperty(propertyID, value, important, true); } + + void removeProperty(int propertyID) { removeProperty(propertyID, true, false); } + + // The following parses an entire new style declaration. + void parseDeclaration(const String& styleDeclaration); + + // Besides adding the properties, this also removes any existing properties with these IDs. + // It does no notification since it's called by the parser. + void addParsedProperties(const CSSProperty* const *, int numProperties); + // This does no change notifications since it's only called by createMarkup. + void addParsedProperty(const CSSProperty&); + + PassRefPtr copyBlockProperties() const; + void removeBlockProperties(); + void removePropertiesInSet(const int* set, unsigned length) { removePropertiesInSet(set, length, true); } + + void merge(const CSSMutableStyleDeclaration*, bool argOverridesOnConflict = true); + + void setStrictParsing(bool b) { m_strictParsing = b; } + bool useStrictParsing() const { return m_strictParsing; } + + void addSubresourceStyleURLs(ListHashSet&); + +protected: + CSSMutableStyleDeclaration(); + + void setPropertyInternal(const CSSProperty&, CSSProperty* slot = 0); + String removeProperty(int propertyID, bool notifyChanged, bool returnText); + +private: + CSSMutableStyleDeclaration(CSSRule* parentRule); + CSSMutableStyleDeclaration(CSSRule* parentRule, const Vector&); + CSSMutableStyleDeclaration(CSSRule* parentRule, const CSSProperty* const *, int numProperties); + CSSMutableStyleDeclaration(StyledElement*, bool isInline); + + virtual PassRefPtr makeMutable(); + + void setNeedsStyleRecalc(); + + String getShorthandValue(const int* properties, size_t) const; + String getCommonValue(const int* properties, size_t) const; + String getLayeredShorthandValue(const int* properties, size_t) const; + String get4Values(const int* properties) const; + String borderSpacingValue(const int properties[2]) const; + String fontValue() const; + bool appendFontLonghandValueIfExplicit(int propertyID, StringBuilder& result) const; + + template String getShorthandValue(const int (&properties)[size]) const { return getShorthandValue(properties, size); } + template String getCommonValue(const int (&properties)[size]) const { return getCommonValue(properties, size); } + template String getLayeredShorthandValue(const int (&properties)[size]) const { return getLayeredShorthandValue(properties, size); } + + bool setProperty(int propertyID, int value, bool important, bool notifyChanged); + bool setProperty(int propertyId, double value, CSSPrimitiveValue::UnitTypes, bool important, bool notifyChanged); + bool setProperty(int propertyID, const String& value, bool important, bool notifyChanged); + bool removeShorthandProperty(int propertyID, bool notifyChanged); + bool removePropertiesInSet(const int* set, unsigned length, bool notifyChanged); + + Vector::const_iterator findPropertyWithId(int propertyId) const; + Vector::iterator findPropertyWithId(int propertyId); + + Vector m_properties; + + friend class CSSMutableStyleDeclarationConstIterator; +}; + +inline CSSMutableStyleDeclarationConstIterator::CSSMutableStyleDeclarationConstIterator(const CSSMutableStyleDeclaration* decl, CSSProperty* current) +: m_decl(decl) +, m_current(current) +{ +#ifndef NDEBUG + const_cast(m_decl)->m_iteratorCount++; +#endif +} + +inline CSSMutableStyleDeclarationConstIterator::CSSMutableStyleDeclarationConstIterator(const CSSMutableStyleDeclarationConstIterator& o) +: m_decl(o.m_decl) +, m_current(o.m_current) +{ +#ifndef NDEBUG + const_cast(m_decl)->m_iteratorCount++; +#endif +} + +inline CSSMutableStyleDeclarationConstIterator::~CSSMutableStyleDeclarationConstIterator() +{ +#ifndef NDEBUG + const_cast(m_decl)->m_iteratorCount--; +#endif +} + +inline CSSMutableStyleDeclarationConstIterator& CSSMutableStyleDeclarationConstIterator::operator=(const CSSMutableStyleDeclarationConstIterator& o) +{ + m_decl = o.m_decl; + m_current = o.m_current; +#ifndef NDEBUG + const_cast(m_decl)->m_iteratorCount++; +#endif + return *this; +} + +inline CSSMutableStyleDeclarationConstIterator& CSSMutableStyleDeclarationConstIterator::operator++() +{ + ASSERT(m_current != const_cast(m_decl)->m_properties.end()); + ++m_current; + return *this; +} + +inline CSSMutableStyleDeclarationConstIterator& CSSMutableStyleDeclarationConstIterator::operator--() +{ + --m_current; + return *this; +} + +} // namespace WebCore + +#endif // CSSMutableStyleDeclaration_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSParserValues.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSParserValues.h new file mode 100644 index 000000000..90d26a46d --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSParserValues.h @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef CSSParserValues_h +#define CSSParserValues_h + +#include "CSSSelector.h" +#include "CSSValueList.h" +#include + +namespace WebCore { + +class CSSValue; +class QualifiedName; + +struct CSSParserString { + UChar* characters; + int length; + + void lower(); + + operator String() const { return String(characters, length); } + operator AtomicString() const { return AtomicString(characters, length); } +}; + +struct CSSParserFunction; + +struct CSSParserValue { + int id; + bool isInt; + union { + double fValue; + int iValue; + CSSParserString string; + CSSParserFunction* function; + }; + enum { + Operator = 0x100000, + Function = 0x100001, + Q_EMS = 0x100002 + }; + int unit; + + + PassRefPtr createCSSValue(); +}; + +class CSSParserValueList { + WTF_MAKE_FAST_ALLOCATED; +public: + CSSParserValueList() + : m_current(0) + { + } + ~CSSParserValueList(); + + void addValue(const CSSParserValue&); + void insertValueAt(unsigned, const CSSParserValue&); + void deleteValueAt(unsigned); + void extend(CSSParserValueList&); + + unsigned size() const { return m_values.size(); } + CSSParserValue* current() { return m_current < m_values.size() ? &m_values[m_current] : 0; } + CSSParserValue* next() { ++m_current; return current(); } + CSSParserValue* previous() + { + if (!m_current) + return 0; + --m_current; + return current(); + } + + CSSParserValue* valueAt(unsigned i) { return i < m_values.size() ? &m_values[i] : 0; } + + void clear() { m_values.clear(); } + +private: + unsigned m_current; + Vector m_values; +}; + +struct CSSParserFunction { + WTF_MAKE_FAST_ALLOCATED; +public: + CSSParserString name; + OwnPtr args; +}; + +class CSSParserSelector { + WTF_MAKE_FAST_ALLOCATED; +public: + CSSParserSelector(); + ~CSSParserSelector(); + + PassOwnPtr releaseSelector() { return m_selector.release(); } + + void setTag(const QualifiedName& value) { m_selector->setTag(value); } + void setValue(const AtomicString& value) { m_selector->setValue(value); } + void setAttribute(const QualifiedName& value) { m_selector->setAttribute(value); } + void setArgument(const AtomicString& value) { m_selector->setArgument(value); } + void setMatch(CSSSelector::Match value) { m_selector->m_match = value; } + void setRelation(CSSSelector::Relation value) { m_selector->m_relation = value; } + void setForPage() { m_selector->setForPage(); } + + void adoptSelectorVector(Vector >& selectorVector); + + CSSSelector::PseudoType pseudoType() const { return m_selector->pseudoType(); } + bool isUnknownPseudoElement() const { return m_selector->isUnknownPseudoElement(); } + bool isSimple() const { return !m_tagHistory && m_selector->isSimple(); } + bool hasShadowDescendant() const; + + CSSParserSelector* tagHistory() const { return m_tagHistory.get(); } + void setTagHistory(PassOwnPtr selector) { m_tagHistory = selector; } + void insertTagHistory(CSSSelector::Relation before, PassOwnPtr, CSSSelector::Relation after); + void appendTagHistory(CSSSelector::Relation, PassOwnPtr); + +private: + OwnPtr m_selector; + OwnPtr m_tagHistory; +}; + +inline bool CSSParserSelector::hasShadowDescendant() const +{ + return m_selector->relation() == CSSSelector::ShadowDescendant; +} + +} + +#endif diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSPrimitiveValue.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSPrimitiveValue.h new file mode 100644 index 000000000..3f15ff78d --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSPrimitiveValue.h @@ -0,0 +1,325 @@ +/* + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2007 Alexey Proskuryakov + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef CSSPrimitiveValue_h +#define CSSPrimitiveValue_h + +#include "CSSValue.h" +#include "Color.h" +#include +#include +#include + +namespace WebCore { + +class Counter; +class DashboardRegion; +class Pair; +class Quad; +class RGBColor; +class Rect; +class RenderStyle; +class CSSWrapShape; + +struct Length; + +template inline T roundForImpreciseConversion(double value) +{ + // Dimension calculations are imprecise, often resulting in values of e.g. + // 44.99998. We need to go ahead and round if we're really close to the + // next integer value. + value += (value < 0) ? -0.01 : +0.01; + return ((value > max) || (value < min)) ? 0 : static_cast(value); +} + +class CSSPrimitiveValue : public CSSValue { +public: + enum UnitTypes { + CSS_UNKNOWN = 0, + CSS_NUMBER = 1, + CSS_PERCENTAGE = 2, + CSS_EMS = 3, + CSS_EXS = 4, + CSS_PX = 5, + CSS_CM = 6, + CSS_MM = 7, + CSS_IN = 8, + CSS_PT = 9, + CSS_PC = 10, + CSS_DEG = 11, + CSS_RAD = 12, + CSS_GRAD = 13, + CSS_MS = 14, + CSS_S = 15, + CSS_HZ = 16, + CSS_KHZ = 17, + CSS_DIMENSION = 18, + CSS_STRING = 19, + CSS_URI = 20, + CSS_IDENT = 21, + CSS_ATTR = 22, + CSS_COUNTER = 23, + CSS_RECT = 24, + CSS_RGBCOLOR = 25, + CSS_PAIR = 100, // We envision this being exposed as a means of getting computed style values for pairs (border-spacing/radius, background-position, etc.) + CSS_DASHBOARD_REGION = 101, // FIXME: Dashboard region should not be a primitive value. + CSS_UNICODE_RANGE = 102, + + // These next types are just used internally to allow us to translate back and forth from CSSPrimitiveValues to CSSParserValues. + CSS_PARSER_OPERATOR = 103, + CSS_PARSER_INTEGER = 104, + CSS_PARSER_HEXCOLOR = 105, + + // This is used internally for unknown identifiers + CSS_PARSER_IDENTIFIER = 106, + + // These are from CSS3 Values and Units, but that isn't a finished standard yet + CSS_TURN = 107, + CSS_REMS = 108, + + // This is used internally for counter names (as opposed to counter values) + CSS_COUNTER_NAME = 109, + + // This is used by the CSS Exclusions draft + CSS_SHAPE = 110, + + // Used by border images. + CSS_QUAD = 111 + }; + + // This enum follows the CSSParser::Units enum augmented with UNIT_FREQUENCY for frequencies. + enum UnitCategory { + UNumber, + UPercent, + ULength, + UAngle, + UTime, + UFrequency, + UOther + }; + + bool isAngle() const + { + return m_primitiveUnitType == CSS_DEG + || m_primitiveUnitType == CSS_RAD + || m_primitiveUnitType == CSS_GRAD + || m_primitiveUnitType == CSS_TURN; + } + bool isAttr() const { return m_primitiveUnitType == CSS_ATTR; } + bool isCounter() const { return m_primitiveUnitType == CSS_COUNTER; } + bool isFontIndependentLength() const { return m_primitiveUnitType >= CSS_PX && m_primitiveUnitType <= CSS_PC; } + bool isFontRelativeLength() const + { + return m_primitiveUnitType == CSS_EMS || m_primitiveUnitType == CSS_EXS || m_primitiveUnitType == CSS_REMS; + } + bool isIdent() const { return m_primitiveUnitType == CSS_IDENT; } + bool isLength() const + { + return (m_primitiveUnitType >= CSS_EMS && m_primitiveUnitType <= CSS_PC) + || m_primitiveUnitType == CSS_REMS; + } + bool isNumber() const { return m_primitiveUnitType == CSS_NUMBER; } + bool isPercentage() const { return m_primitiveUnitType == CSS_PERCENTAGE; } + bool isPx() const { return m_primitiveUnitType == CSS_PX; } + bool isRect() const { return m_primitiveUnitType == CSS_RECT; } + bool isRGBColor() const { return m_primitiveUnitType == CSS_RGBCOLOR; } + bool isShape() const { return m_primitiveUnitType == CSS_SHAPE; } + bool isString() const { return m_primitiveUnitType == CSS_STRING; } + bool isTime() const { return m_primitiveUnitType == CSS_S || m_primitiveUnitType == CSS_MS; } + bool isURI() const { return m_primitiveUnitType == CSS_URI; } + + + static PassRefPtr createIdentifier(int identifier) { return adoptRef(new CSSPrimitiveValue(identifier)); } + static PassRefPtr createColor(unsigned rgbValue) { return adoptRef(new CSSPrimitiveValue(rgbValue)); } + static PassRefPtr create(double value, UnitTypes type) { return adoptRef(new CSSPrimitiveValue(value, type)); } + static PassRefPtr create(const String& value, UnitTypes type) { return adoptRef(new CSSPrimitiveValue(value, type)); } + + template static PassRefPtr create(T value) + { + return adoptRef(new CSSPrimitiveValue(value)); + } + + // This value is used to handle quirky margins in reflow roots (body, td, and th) like WinIE. + // The basic idea is that a stylesheet can use the value __qem (for quirky em) instead of em. + // When the quirky value is used, if you're in quirks mode, the margin will collapse away + // inside a table cell. + static PassRefPtr createAllowingMarginQuirk(double value, UnitTypes type) + { + CSSPrimitiveValue* quirkValue = new CSSPrimitiveValue(value, type); + quirkValue->m_isQuirkValue = true; + return adoptRef(quirkValue); + } + + ~CSSPrimitiveValue(); + + void cleanup(); + + unsigned short primitiveType() const { return m_primitiveUnitType; } + + double computeDegrees(); + + enum TimeUnit { Seconds, Milliseconds }; + template T computeTime() + { + if (timeUnit == Seconds && m_primitiveUnitType == CSS_S) + return getValue(); + if (timeUnit == Seconds && m_primitiveUnitType == CSS_MS) + return getValue() / 1000; + if (timeUnit == Milliseconds && m_primitiveUnitType == CSS_MS) + return getValue(); + if (timeUnit == Milliseconds && m_primitiveUnitType == CSS_S) + return getValue() * 1000; + ASSERT_NOT_REACHED(); + return 0; + } + + /* + * computes a length in pixels out of the given CSSValue. Need the RenderStyle to get + * the fontinfo in case val is defined in em or ex. + * + * The metrics have to be a bit different for screen and printer output. + * For screen output we assume 1 inch == 72 px, for printer we assume 300 dpi + * + * this is screen/printer dependent, so we probably need a config option for this, + * and some tool to calibrate. + */ + template T computeLength(RenderStyle* currStyle, RenderStyle* rootStyle, float multiplier = 1.0f, bool computingFontSize = false); + + // Converts to a Length, mapping various unit types appropriately. + template Length convertToLength(RenderStyle* currStyle, RenderStyle* rootStyle, double multiplier = 1.0, bool computingFontSize = false); + + // use with care!!! + void setPrimitiveType(unsigned short type) { m_primitiveUnitType = type; } + + double getDoubleValue(unsigned short unitType, ExceptionCode&) const; + double getDoubleValue(unsigned short unitType) const; + double getDoubleValue() const { return m_value.num; } + + void setFloatValue(unsigned short unitType, double floatValue, ExceptionCode&); + float getFloatValue(unsigned short unitType, ExceptionCode& ec) const { return getValue(unitType, ec); } + float getFloatValue(unsigned short unitType) const { return getValue(unitType); } + float getFloatValue() const { return getValue(); } + + int getIntValue(unsigned short unitType, ExceptionCode& ec) const { return getValue(unitType, ec); } + int getIntValue(unsigned short unitType) const { return getValue(unitType); } + int getIntValue() const { return getValue(); } + + template inline T getValue(unsigned short unitType, ExceptionCode& ec) const { return clampTo(getDoubleValue(unitType, ec)); } + template inline T getValue(unsigned short unitType) const { return clampTo(getDoubleValue(unitType)); } + template inline T getValue() const { return clampTo(m_value.num); } + + void setStringValue(unsigned short stringType, const String& stringValue, ExceptionCode&); + String getStringValue(ExceptionCode&) const; + String getStringValue() const; + + Counter* getCounterValue(ExceptionCode&) const; + Counter* getCounterValue() const { return m_primitiveUnitType != CSS_COUNTER ? 0 : m_value.counter; } + + Rect* getRectValue(ExceptionCode&) const; + Rect* getRectValue() const { return m_primitiveUnitType != CSS_RECT ? 0 : m_value.rect; } + + Quad* getQuadValue(ExceptionCode&) const; + Quad* getQuadValue() const { return m_primitiveUnitType != CSS_QUAD ? 0 : m_value.quad; } + + PassRefPtr getRGBColorValue(ExceptionCode&) const; + RGBA32 getRGBA32Value() const { return m_primitiveUnitType != CSS_RGBCOLOR ? 0 : m_value.rgbcolor; } + + Pair* getPairValue(ExceptionCode&) const; + Pair* getPairValue() const { return m_primitiveUnitType != CSS_PAIR ? 0 : m_value.pair; } + + DashboardRegion* getDashboardRegionValue() const { return m_primitiveUnitType != CSS_DASHBOARD_REGION ? 0 : m_value.region; } + + CSSWrapShape* getShapeValue() const { return m_primitiveUnitType != CSS_SHAPE ? 0 : m_value.shape; } + + int getIdent() const { return m_primitiveUnitType == CSS_IDENT ? m_value.ident : 0; } + + template inline operator T() const; // Defined in CSSPrimitiveValueMappings.h + + String customCssText() const; + + bool isQuirkValue() { return m_isQuirkValue; } + + void addSubresourceStyleURLs(ListHashSet&, const CSSStyleSheet*); + +protected: + CSSPrimitiveValue(ClassType, int ident); + CSSPrimitiveValue(ClassType, const String&, UnitTypes); + +private: + CSSPrimitiveValue(); + // FIXME: int vs. unsigned overloading is too subtle to distinguish the color and identifier cases. + CSSPrimitiveValue(int ident); + CSSPrimitiveValue(unsigned color); // RGB value + CSSPrimitiveValue(const Length&); + CSSPrimitiveValue(const String&, UnitTypes); + CSSPrimitiveValue(double, UnitTypes); + + template CSSPrimitiveValue(T); // Defined in CSSPrimitiveValueMappings.h + template CSSPrimitiveValue(T* val) + : CSSValue(PrimitiveClass) + { + init(PassRefPtr(val)); + } + + template CSSPrimitiveValue(PassRefPtr val) + : CSSValue(PrimitiveClass) + { + init(val); + } + + static void create(int); // compile-time guard + static void create(unsigned); // compile-time guard + template operator T*(); // compile-time guard + + static PassRefPtr createUncachedIdentifier(int identifier); + static PassRefPtr createUncachedColor(unsigned rgbValue); + static PassRefPtr createUncached(double value, UnitTypes type); + + static UnitTypes canonicalUnitTypeForCategory(UnitCategory category); + + void init(PassRefPtr); + void init(PassRefPtr); + void init(PassRefPtr); + void init(PassRefPtr); + void init(PassRefPtr); // FIXME: Dashboard region should not be a primitive value. + void init(PassRefPtr); + + bool getDoubleValueInternal(UnitTypes targetUnitType, double* result) const; + + double computeLengthDouble(RenderStyle* currentStyle, RenderStyle* rootStyle, float multiplier, bool computingFontSize); + + union { + int ident; + double num; + StringImpl* string; + Counter* counter; + Rect* rect; + Quad* quad; + unsigned rgbcolor; + Pair* pair; + DashboardRegion* region; + CSSWrapShape* shape; + } m_value; +}; + +} // namespace WebCore + +#endif // CSSPrimitiveValue_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSProperty.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSProperty.h new file mode 100644 index 000000000..2674544d1 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSProperty.h @@ -0,0 +1,76 @@ +/* + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef CSSProperty_h +#define CSSProperty_h + +#include "CSSValue.h" +#include "RenderStyleConstants.h" +#include "TextDirection.h" +#include +#include + +namespace WebCore { + +class CSSProperty { + WTF_MAKE_FAST_ALLOCATED; +public: + CSSProperty(unsigned propID, PassRefPtr value, bool important = false, int shorthandID = 0, bool implicit = false) + : m_id(propID) + , m_shorthandID(shorthandID) + , m_important(important) + , m_implicit(implicit) + , m_inherited(isInheritedProperty(propID)) + , m_value(value) + { + } + + int id() const { return m_id; } + int shorthandID() const { return m_shorthandID; } + + bool isImportant() const { return m_important; } + bool isImplicit() const { return m_implicit; } + bool isInherited() const { return m_inherited; } + + CSSValue* value() const { return m_value.get(); } + + String cssText() const; + + static int resolveDirectionAwareProperty(int propertyID, TextDirection, WritingMode); + static bool isInheritedProperty(unsigned propertyID); + + // Make sure the following fits in 4 bytes. Really. + unsigned m_id : 14; + unsigned m_shorthandID : 14; // If this property was set as part of a shorthand, gives the shorthand. + bool m_important : 1; + bool m_implicit : 1; // Whether or not the property was set implicitly as the result of a shorthand. + bool m_inherited : 1; + + RefPtr m_value; +}; + +} // namespace WebCore + +namespace WTF { + // Properties in Vector can be initialized with memset and moved using memcpy. + template<> struct VectorTraits : SimpleClassVectorTraits { }; +} + +#endif // CSSProperty_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSPropertyNames.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSPropertyNames.h new file mode 100644 index 000000000..abd86b8b1 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSPropertyNames.h @@ -0,0 +1,772 @@ +/* This file is automatically generated from CSSPropertyNames.in by makeprop, do not edit */ + +#ifndef CSSPropertyNames_h +#define CSSPropertyNames_h + +#include + +namespace WTF { +class String; +} + +namespace WebCore { + +enum CSSPropertyID { + CSSPropertyInvalid = 0, + CSSPropertyColor = 1001, + CSSPropertyDirection = 1002, + CSSPropertyDisplay = 1003, + CSSPropertyFont = 1004, + CSSPropertyFontFamily = 1005, + CSSPropertyFontSize = 1006, + CSSPropertyFontStyle = 1007, + CSSPropertyFontVariant = 1008, + CSSPropertyFontWeight = 1009, + CSSPropertyTextRendering = 1010, + CSSPropertyWebkitFontFeatureSettings = 1011, + CSSPropertyWebkitFontKerning = 1012, + CSSPropertyWebkitFontSmoothing = 1013, + CSSPropertyWebkitFontVariantLigatures = 1014, + CSSPropertyWebkitLocale = 1015, + CSSPropertyWebkitTextOrientation = 1016, + CSSPropertyWebkitTextSizeAdjust = 1017, + CSSPropertyWebkitWritingMode = 1018, + CSSPropertyZoom = 1019, + CSSPropertyLineHeight = 1020, + CSSPropertyBackground = 1021, + CSSPropertyBackgroundAttachment = 1022, + CSSPropertyBackgroundClip = 1023, + CSSPropertyBackgroundColor = 1024, + CSSPropertyBackgroundImage = 1025, + CSSPropertyBackgroundOrigin = 1026, + CSSPropertyBackgroundPosition = 1027, + CSSPropertyBackgroundPositionX = 1028, + CSSPropertyBackgroundPositionY = 1029, + CSSPropertyBackgroundRepeat = 1030, + CSSPropertyBackgroundRepeatX = 1031, + CSSPropertyBackgroundRepeatY = 1032, + CSSPropertyBackgroundSize = 1033, + CSSPropertyBorder = 1034, + CSSPropertyBorderBottom = 1035, + CSSPropertyBorderBottomColor = 1036, + CSSPropertyBorderBottomLeftRadius = 1037, + CSSPropertyBorderBottomRightRadius = 1038, + CSSPropertyBorderBottomStyle = 1039, + CSSPropertyBorderBottomWidth = 1040, + CSSPropertyBorderCollapse = 1041, + CSSPropertyBorderColor = 1042, + CSSPropertyBorderImage = 1043, + CSSPropertyBorderImageOutset = 1044, + CSSPropertyBorderImageRepeat = 1045, + CSSPropertyBorderImageSlice = 1046, + CSSPropertyBorderImageSource = 1047, + CSSPropertyBorderImageWidth = 1048, + CSSPropertyBorderLeft = 1049, + CSSPropertyBorderLeftColor = 1050, + CSSPropertyBorderLeftStyle = 1051, + CSSPropertyBorderLeftWidth = 1052, + CSSPropertyBorderRadius = 1053, + CSSPropertyBorderRight = 1054, + CSSPropertyBorderRightColor = 1055, + CSSPropertyBorderRightStyle = 1056, + CSSPropertyBorderRightWidth = 1057, + CSSPropertyBorderSpacing = 1058, + CSSPropertyBorderStyle = 1059, + CSSPropertyBorderTop = 1060, + CSSPropertyBorderTopColor = 1061, + CSSPropertyBorderTopLeftRadius = 1062, + CSSPropertyBorderTopRightRadius = 1063, + CSSPropertyBorderTopStyle = 1064, + CSSPropertyBorderTopWidth = 1065, + CSSPropertyBorderWidth = 1066, + CSSPropertyBottom = 1067, + CSSPropertyBoxShadow = 1068, + CSSPropertyBoxSizing = 1069, + CSSPropertyCaptionSide = 1070, + CSSPropertyClear = 1071, + CSSPropertyClip = 1072, + CSSPropertyContent = 1073, + CSSPropertyCounterIncrement = 1074, + CSSPropertyCounterReset = 1075, + CSSPropertyCursor = 1076, + CSSPropertyEmptyCells = 1077, + CSSPropertyFloat = 1078, + CSSPropertyFontStretch = 1079, + CSSPropertyHeight = 1080, + CSSPropertyImageRendering = 1081, + CSSPropertyLeft = 1082, + CSSPropertyLetterSpacing = 1083, + CSSPropertyListStyle = 1084, + CSSPropertyListStyleImage = 1085, + CSSPropertyListStylePosition = 1086, + CSSPropertyListStyleType = 1087, + CSSPropertyMargin = 1088, + CSSPropertyMarginBottom = 1089, + CSSPropertyMarginLeft = 1090, + CSSPropertyMarginRight = 1091, + CSSPropertyMarginTop = 1092, + CSSPropertyMaxHeight = 1093, + CSSPropertyMaxWidth = 1094, + CSSPropertyMinHeight = 1095, + CSSPropertyMinWidth = 1096, + CSSPropertyOpacity = 1097, + CSSPropertyOrphans = 1098, + CSSPropertyOutline = 1099, + CSSPropertyOutlineColor = 1100, + CSSPropertyOutlineOffset = 1101, + CSSPropertyOutlineStyle = 1102, + CSSPropertyOutlineWidth = 1103, + CSSPropertyOverflow = 1104, + CSSPropertyOverflowX = 1105, + CSSPropertyOverflowY = 1106, + CSSPropertyPadding = 1107, + CSSPropertyPaddingBottom = 1108, + CSSPropertyPaddingLeft = 1109, + CSSPropertyPaddingRight = 1110, + CSSPropertyPaddingTop = 1111, + CSSPropertyPage = 1112, + CSSPropertyPageBreakAfter = 1113, + CSSPropertyPageBreakBefore = 1114, + CSSPropertyPageBreakInside = 1115, + CSSPropertyPointerEvents = 1116, + CSSPropertyPosition = 1117, + CSSPropertyQuotes = 1118, + CSSPropertyResize = 1119, + CSSPropertyRight = 1120, + CSSPropertySize = 1121, + CSSPropertySrc = 1122, + CSSPropertySpeak = 1123, + CSSPropertyTableLayout = 1124, + CSSPropertyTextAlign = 1125, + CSSPropertyTextDecoration = 1126, + CSSPropertyTextIndent = 1127, + CSSPropertyTextLineThrough = 1128, + CSSPropertyTextLineThroughColor = 1129, + CSSPropertyTextLineThroughMode = 1130, + CSSPropertyTextLineThroughStyle = 1131, + CSSPropertyTextLineThroughWidth = 1132, + CSSPropertyTextOverflow = 1133, + CSSPropertyTextOverline = 1134, + CSSPropertyTextOverlineColor = 1135, + CSSPropertyTextOverlineMode = 1136, + CSSPropertyTextOverlineStyle = 1137, + CSSPropertyTextOverlineWidth = 1138, + CSSPropertyTextShadow = 1139, + CSSPropertyTextTransform = 1140, + CSSPropertyTextUnderline = 1141, + CSSPropertyTextUnderlineColor = 1142, + CSSPropertyTextUnderlineMode = 1143, + CSSPropertyTextUnderlineStyle = 1144, + CSSPropertyTextUnderlineWidth = 1145, + CSSPropertyTop = 1146, + CSSPropertyUnicodeBidi = 1147, + CSSPropertyUnicodeRange = 1148, + CSSPropertyVerticalAlign = 1149, + CSSPropertyVisibility = 1150, + CSSPropertyWhiteSpace = 1151, + CSSPropertyWidows = 1152, + CSSPropertyWidth = 1153, + CSSPropertyWordBreak = 1154, + CSSPropertyWordSpacing = 1155, + CSSPropertyWordWrap = 1156, + CSSPropertyZIndex = 1157, + CSSPropertyWebkitAnimation = 1158, + CSSPropertyWebkitAnimationDelay = 1159, + CSSPropertyWebkitAnimationDirection = 1160, + CSSPropertyWebkitAnimationDuration = 1161, + CSSPropertyWebkitAnimationFillMode = 1162, + CSSPropertyWebkitAnimationIterationCount = 1163, + CSSPropertyWebkitAnimationName = 1164, + CSSPropertyWebkitAnimationPlayState = 1165, + CSSPropertyWebkitAnimationTimingFunction = 1166, + CSSPropertyWebkitAppearance = 1167, + CSSPropertyWebkitAspectRatio = 1168, + CSSPropertyWebkitBackfaceVisibility = 1169, + CSSPropertyWebkitBackgroundClip = 1170, + CSSPropertyWebkitBackgroundComposite = 1171, + CSSPropertyWebkitBackgroundOrigin = 1172, + CSSPropertyWebkitBackgroundSize = 1173, + CSSPropertyWebkitBorderAfter = 1174, + CSSPropertyWebkitBorderAfterColor = 1175, + CSSPropertyWebkitBorderAfterStyle = 1176, + CSSPropertyWebkitBorderAfterWidth = 1177, + CSSPropertyWebkitBorderBefore = 1178, + CSSPropertyWebkitBorderBeforeColor = 1179, + CSSPropertyWebkitBorderBeforeStyle = 1180, + CSSPropertyWebkitBorderBeforeWidth = 1181, + CSSPropertyWebkitBorderEnd = 1182, + CSSPropertyWebkitBorderEndColor = 1183, + CSSPropertyWebkitBorderEndStyle = 1184, + CSSPropertyWebkitBorderEndWidth = 1185, + CSSPropertyWebkitBorderFit = 1186, + CSSPropertyWebkitBorderHorizontalSpacing = 1187, + CSSPropertyWebkitBorderImage = 1188, + CSSPropertyWebkitBorderRadius = 1189, + CSSPropertyWebkitBorderStart = 1190, + CSSPropertyWebkitBorderStartColor = 1191, + CSSPropertyWebkitBorderStartStyle = 1192, + CSSPropertyWebkitBorderStartWidth = 1193, + CSSPropertyWebkitBorderVerticalSpacing = 1194, + CSSPropertyWebkitBoxAlign = 1195, + CSSPropertyWebkitBoxDirection = 1196, + CSSPropertyWebkitBoxFlex = 1197, + CSSPropertyWebkitBoxFlexGroup = 1198, + CSSPropertyWebkitBoxLines = 1199, + CSSPropertyWebkitBoxOrdinalGroup = 1200, + CSSPropertyWebkitBoxOrient = 1201, + CSSPropertyWebkitBoxPack = 1202, + CSSPropertyWebkitBoxReflect = 1203, + CSSPropertyWebkitBoxShadow = 1204, + CSSPropertyWebkitColorCorrection = 1205, + CSSPropertyWebkitColumnAxis = 1206, + CSSPropertyWebkitColumnBreakAfter = 1207, + CSSPropertyWebkitColumnBreakBefore = 1208, + CSSPropertyWebkitColumnBreakInside = 1209, + CSSPropertyWebkitColumnCount = 1210, + CSSPropertyWebkitColumnGap = 1211, + CSSPropertyWebkitColumnRule = 1212, + CSSPropertyWebkitColumnRuleColor = 1213, + CSSPropertyWebkitColumnRuleStyle = 1214, + CSSPropertyWebkitColumnRuleWidth = 1215, + CSSPropertyWebkitColumnSpan = 1216, + CSSPropertyWebkitColumnWidth = 1217, + CSSPropertyWebkitColumns = 1218, + CSSPropertyWebkitFilter = 1219, + CSSPropertyWebkitFlexAlign = 1220, + CSSPropertyWebkitFlexDirection = 1221, + CSSPropertyWebkitFlexFlow = 1222, + CSSPropertyWebkitFlexItemAlign = 1223, + CSSPropertyWebkitFlexOrder = 1224, + CSSPropertyWebkitFlexPack = 1225, + CSSPropertyWebkitFlexWrap = 1226, + CSSPropertyWebkitFontSizeDelta = 1227, + CSSPropertyWebkitHighlight = 1228, + CSSPropertyWebkitHyphenateCharacter = 1229, + CSSPropertyWebkitHyphenateLimitAfter = 1230, + CSSPropertyWebkitHyphenateLimitBefore = 1231, + CSSPropertyWebkitHyphenateLimitLines = 1232, + CSSPropertyWebkitHyphens = 1233, + CSSPropertyWebkitLineBoxContain = 1234, + CSSPropertyWebkitLineBreak = 1235, + CSSPropertyWebkitLineClamp = 1236, + CSSPropertyWebkitLineGrid = 1237, + CSSPropertyWebkitLineGridSnap = 1238, + CSSPropertyWebkitLogicalWidth = 1239, + CSSPropertyWebkitLogicalHeight = 1240, + CSSPropertyWebkitMarginAfterCollapse = 1241, + CSSPropertyWebkitMarginBeforeCollapse = 1242, + CSSPropertyWebkitMarginBottomCollapse = 1243, + CSSPropertyWebkitMarginTopCollapse = 1244, + CSSPropertyWebkitMarginCollapse = 1245, + CSSPropertyWebkitMarginAfter = 1246, + CSSPropertyWebkitMarginBefore = 1247, + CSSPropertyWebkitMarginEnd = 1248, + CSSPropertyWebkitMarginStart = 1249, + CSSPropertyWebkitMarquee = 1250, + CSSPropertyWebkitMarqueeDirection = 1251, + CSSPropertyWebkitMarqueeIncrement = 1252, + CSSPropertyWebkitMarqueeRepetition = 1253, + CSSPropertyWebkitMarqueeSpeed = 1254, + CSSPropertyWebkitMarqueeStyle = 1255, + CSSPropertyWebkitMask = 1256, + CSSPropertyWebkitMaskAttachment = 1257, + CSSPropertyWebkitMaskBoxImage = 1258, + CSSPropertyWebkitMaskBoxImageOutset = 1259, + CSSPropertyWebkitMaskBoxImageRepeat = 1260, + CSSPropertyWebkitMaskBoxImageSlice = 1261, + CSSPropertyWebkitMaskBoxImageSource = 1262, + CSSPropertyWebkitMaskBoxImageWidth = 1263, + CSSPropertyWebkitMaskClip = 1264, + CSSPropertyWebkitMaskComposite = 1265, + CSSPropertyWebkitMaskImage = 1266, + CSSPropertyWebkitMaskOrigin = 1267, + CSSPropertyWebkitMaskPosition = 1268, + CSSPropertyWebkitMaskPositionX = 1269, + CSSPropertyWebkitMaskPositionY = 1270, + CSSPropertyWebkitMaskRepeat = 1271, + CSSPropertyWebkitMaskRepeatX = 1272, + CSSPropertyWebkitMaskRepeatY = 1273, + CSSPropertyWebkitMaskSize = 1274, + CSSPropertyWebkitMatchNearestMailBlockquoteColor = 1275, + CSSPropertyWebkitMaxLogicalWidth = 1276, + CSSPropertyWebkitMaxLogicalHeight = 1277, + CSSPropertyWebkitMinLogicalWidth = 1278, + CSSPropertyWebkitMinLogicalHeight = 1279, + CSSPropertyWebkitNbspMode = 1280, + CSSPropertyWebkitPaddingAfter = 1281, + CSSPropertyWebkitPaddingBefore = 1282, + CSSPropertyWebkitPaddingEnd = 1283, + CSSPropertyWebkitPaddingStart = 1284, + CSSPropertyWebkitPerspective = 1285, + CSSPropertyWebkitPerspectiveOrigin = 1286, + CSSPropertyWebkitPerspectiveOriginX = 1287, + CSSPropertyWebkitPerspectiveOriginY = 1288, + CSSPropertyWebkitPrintColorAdjust = 1289, + CSSPropertyWebkitRtlOrdering = 1290, + CSSPropertyWebkitTextCombine = 1291, + CSSPropertyWebkitTextDecorationsInEffect = 1292, + CSSPropertyWebkitTextEmphasis = 1293, + CSSPropertyWebkitTextEmphasisColor = 1294, + CSSPropertyWebkitTextEmphasisPosition = 1295, + CSSPropertyWebkitTextEmphasisStyle = 1296, + CSSPropertyWebkitTextFillColor = 1297, + CSSPropertyWebkitTextSecurity = 1298, + CSSPropertyWebkitTextStroke = 1299, + CSSPropertyWebkitTextStrokeColor = 1300, + CSSPropertyWebkitTextStrokeWidth = 1301, + CSSPropertyWebkitTransform = 1302, + CSSPropertyWebkitTransformOrigin = 1303, + CSSPropertyWebkitTransformOriginX = 1304, + CSSPropertyWebkitTransformOriginY = 1305, + CSSPropertyWebkitTransformOriginZ = 1306, + CSSPropertyWebkitTransformStyle = 1307, + CSSPropertyWebkitTransition = 1308, + CSSPropertyWebkitTransitionDelay = 1309, + CSSPropertyWebkitTransitionDuration = 1310, + CSSPropertyWebkitTransitionProperty = 1311, + CSSPropertyWebkitTransitionTimingFunction = 1312, + CSSPropertyWebkitUserDrag = 1313, + CSSPropertyWebkitUserModify = 1314, + CSSPropertyWebkitUserSelect = 1315, + CSSPropertyWebkitFlowInto = 1316, + CSSPropertyWebkitFlowFrom = 1317, + CSSPropertyWebkitRegionOverflow = 1318, + CSSPropertyWebkitWrapShapeInside = 1319, + CSSPropertyWebkitWrapShapeOutside = 1320, + CSSPropertyWebkitWrapMargin = 1321, + CSSPropertyWebkitWrapPadding = 1322, + CSSPropertyWebkitRegionBreakAfter = 1323, + CSSPropertyWebkitRegionBreakBefore = 1324, + CSSPropertyWebkitRegionBreakInside = 1325, + CSSPropertyWebkitWrapFlow = 1326, + CSSPropertyWebkitWrapThrough = 1327, + CSSPropertyWebkitWrap = 1328, + CSSPropertyWebkitGridColumns = 1329, + CSSPropertyWebkitGridRows = 1330, + CSSPropertyClipPath = 1331, + CSSPropertyClipRule = 1332, + CSSPropertyMask = 1333, + CSSPropertyEnableBackground = 1334, + CSSPropertyFilter = 1335, + CSSPropertyFloodColor = 1336, + CSSPropertyFloodOpacity = 1337, + CSSPropertyLightingColor = 1338, + CSSPropertyStopColor = 1339, + CSSPropertyStopOpacity = 1340, + CSSPropertyColorInterpolation = 1341, + CSSPropertyColorInterpolationFilters = 1342, + CSSPropertyColorProfile = 1343, + CSSPropertyColorRendering = 1344, + CSSPropertyFill = 1345, + CSSPropertyFillOpacity = 1346, + CSSPropertyFillRule = 1347, + CSSPropertyMarker = 1348, + CSSPropertyMarkerEnd = 1349, + CSSPropertyMarkerMid = 1350, + CSSPropertyMarkerStart = 1351, + CSSPropertyShapeRendering = 1352, + CSSPropertyStroke = 1353, + CSSPropertyStrokeDasharray = 1354, + CSSPropertyStrokeDashoffset = 1355, + CSSPropertyStrokeLinecap = 1356, + CSSPropertyStrokeLinejoin = 1357, + CSSPropertyStrokeMiterlimit = 1358, + CSSPropertyStrokeOpacity = 1359, + CSSPropertyStrokeWidth = 1360, + CSSPropertyAlignmentBaseline = 1361, + CSSPropertyBaselineShift = 1362, + CSSPropertyDominantBaseline = 1363, + CSSPropertyGlyphOrientationHorizontal = 1364, + CSSPropertyGlyphOrientationVertical = 1365, + CSSPropertyKerning = 1366, + CSSPropertyTextAnchor = 1367, + CSSPropertyVectorEffect = 1368, + CSSPropertyWritingMode = 1369, + CSSPropertyWebkitSvgShadow = 1370, + CSSPropertyWebkitDashboardRegion = 1371, +}; + +const int firstCSSProperty = 1001; +const int numCSSProperties = 371; +const size_t maxCSSPropertyNameLength = 43; +const char* const propertyNameStrings[371] = { +"color", +"direction", +"display", +"font", +"font-family", +"font-size", +"font-style", +"font-variant", +"font-weight", +"text-rendering", +"-webkit-font-feature-settings", +"-webkit-font-kerning", +"-webkit-font-smoothing", +"-webkit-font-variant-ligatures", +"-webkit-locale", +"-webkit-text-orientation", +"-webkit-text-size-adjust", +"-webkit-writing-mode", +"zoom", +"line-height", +"background", +"background-attachment", +"background-clip", +"background-color", +"background-image", +"background-origin", +"background-position", +"background-position-x", +"background-position-y", +"background-repeat", +"background-repeat-x", +"background-repeat-y", +"background-size", +"border", +"border-bottom", +"border-bottom-color", +"border-bottom-left-radius", +"border-bottom-right-radius", +"border-bottom-style", +"border-bottom-width", +"border-collapse", +"border-color", +"border-image", +"border-image-outset", +"border-image-repeat", +"border-image-slice", +"border-image-source", +"border-image-width", +"border-left", +"border-left-color", +"border-left-style", +"border-left-width", +"border-radius", +"border-right", +"border-right-color", +"border-right-style", +"border-right-width", +"border-spacing", +"border-style", +"border-top", +"border-top-color", +"border-top-left-radius", +"border-top-right-radius", +"border-top-style", +"border-top-width", +"border-width", +"bottom", +"box-shadow", +"box-sizing", +"caption-side", +"clear", +"clip", +"content", +"counter-increment", +"counter-reset", +"cursor", +"empty-cells", +"float", +"font-stretch", +"height", +"image-rendering", +"left", +"letter-spacing", +"list-style", +"list-style-image", +"list-style-position", +"list-style-type", +"margin", +"margin-bottom", +"margin-left", +"margin-right", +"margin-top", +"max-height", +"max-width", +"min-height", +"min-width", +"opacity", +"orphans", +"outline", +"outline-color", +"outline-offset", +"outline-style", +"outline-width", +"overflow", +"overflow-x", +"overflow-y", +"padding", +"padding-bottom", +"padding-left", +"padding-right", +"padding-top", +"page", +"page-break-after", +"page-break-before", +"page-break-inside", +"pointer-events", +"position", +"quotes", +"resize", +"right", +"size", +"src", +"speak", +"table-layout", +"text-align", +"text-decoration", +"text-indent", +"text-line-through", +"text-line-through-color", +"text-line-through-mode", +"text-line-through-style", +"text-line-through-width", +"text-overflow", +"text-overline", +"text-overline-color", +"text-overline-mode", +"text-overline-style", +"text-overline-width", +"text-shadow", +"text-transform", +"text-underline", +"text-underline-color", +"text-underline-mode", +"text-underline-style", +"text-underline-width", +"top", +"unicode-bidi", +"unicode-range", +"vertical-align", +"visibility", +"white-space", +"widows", +"width", +"word-break", +"word-spacing", +"word-wrap", +"z-index", +"-webkit-animation", +"-webkit-animation-delay", +"-webkit-animation-direction", +"-webkit-animation-duration", +"-webkit-animation-fill-mode", +"-webkit-animation-iteration-count", +"-webkit-animation-name", +"-webkit-animation-play-state", +"-webkit-animation-timing-function", +"-webkit-appearance", +"-webkit-aspect-ratio", +"-webkit-backface-visibility", +"-webkit-background-clip", +"-webkit-background-composite", +"-webkit-background-origin", +"-webkit-background-size", +"-webkit-border-after", +"-webkit-border-after-color", +"-webkit-border-after-style", +"-webkit-border-after-width", +"-webkit-border-before", +"-webkit-border-before-color", +"-webkit-border-before-style", +"-webkit-border-before-width", +"-webkit-border-end", +"-webkit-border-end-color", +"-webkit-border-end-style", +"-webkit-border-end-width", +"-webkit-border-fit", +"-webkit-border-horizontal-spacing", +"-webkit-border-image", +"-webkit-border-radius", +"-webkit-border-start", +"-webkit-border-start-color", +"-webkit-border-start-style", +"-webkit-border-start-width", +"-webkit-border-vertical-spacing", +"-webkit-box-align", +"-webkit-box-direction", +"-webkit-box-flex", +"-webkit-box-flex-group", +"-webkit-box-lines", +"-webkit-box-ordinal-group", +"-webkit-box-orient", +"-webkit-box-pack", +"-webkit-box-reflect", +"-webkit-box-shadow", +"-webkit-color-correction", +"-webkit-column-axis", +"-webkit-column-break-after", +"-webkit-column-break-before", +"-webkit-column-break-inside", +"-webkit-column-count", +"-webkit-column-gap", +"-webkit-column-rule", +"-webkit-column-rule-color", +"-webkit-column-rule-style", +"-webkit-column-rule-width", +"-webkit-column-span", +"-webkit-column-width", +"-webkit-columns", +"-webkit-filter", +"-webkit-flex-align", +"-webkit-flex-direction", +"-webkit-flex-flow", +"-webkit-flex-item-align", +"-webkit-flex-order", +"-webkit-flex-pack", +"-webkit-flex-wrap", +"-webkit-font-size-delta", +"-webkit-highlight", +"-webkit-hyphenate-character", +"-webkit-hyphenate-limit-after", +"-webkit-hyphenate-limit-before", +"-webkit-hyphenate-limit-lines", +"-webkit-hyphens", +"-webkit-line-box-contain", +"-webkit-line-break", +"-webkit-line-clamp", +"-webkit-line-grid", +"-webkit-line-grid-snap", +"-webkit-logical-width", +"-webkit-logical-height", +"-webkit-margin-after-collapse", +"-webkit-margin-before-collapse", +"-webkit-margin-bottom-collapse", +"-webkit-margin-top-collapse", +"-webkit-margin-collapse", +"-webkit-margin-after", +"-webkit-margin-before", +"-webkit-margin-end", +"-webkit-margin-start", +"-webkit-marquee", +"-webkit-marquee-direction", +"-webkit-marquee-increment", +"-webkit-marquee-repetition", +"-webkit-marquee-speed", +"-webkit-marquee-style", +"-webkit-mask", +"-webkit-mask-attachment", +"-webkit-mask-box-image", +"-webkit-mask-box-image-outset", +"-webkit-mask-box-image-repeat", +"-webkit-mask-box-image-slice", +"-webkit-mask-box-image-source", +"-webkit-mask-box-image-width", +"-webkit-mask-clip", +"-webkit-mask-composite", +"-webkit-mask-image", +"-webkit-mask-origin", +"-webkit-mask-position", +"-webkit-mask-position-x", +"-webkit-mask-position-y", +"-webkit-mask-repeat", +"-webkit-mask-repeat-x", +"-webkit-mask-repeat-y", +"-webkit-mask-size", +"-webkit-match-nearest-mail-blockquote-color", +"-webkit-max-logical-width", +"-webkit-max-logical-height", +"-webkit-min-logical-width", +"-webkit-min-logical-height", +"-webkit-nbsp-mode", +"-webkit-padding-after", +"-webkit-padding-before", +"-webkit-padding-end", +"-webkit-padding-start", +"-webkit-perspective", +"-webkit-perspective-origin", +"-webkit-perspective-origin-x", +"-webkit-perspective-origin-y", +"-webkit-print-color-adjust", +"-webkit-rtl-ordering", +"-webkit-text-combine", +"-webkit-text-decorations-in-effect", +"-webkit-text-emphasis", +"-webkit-text-emphasis-color", +"-webkit-text-emphasis-position", +"-webkit-text-emphasis-style", +"-webkit-text-fill-color", +"-webkit-text-security", +"-webkit-text-stroke", +"-webkit-text-stroke-color", +"-webkit-text-stroke-width", +"-webkit-transform", +"-webkit-transform-origin", +"-webkit-transform-origin-x", +"-webkit-transform-origin-y", +"-webkit-transform-origin-z", +"-webkit-transform-style", +"-webkit-transition", +"-webkit-transition-delay", +"-webkit-transition-duration", +"-webkit-transition-property", +"-webkit-transition-timing-function", +"-webkit-user-drag", +"-webkit-user-modify", +"-webkit-user-select", +"-webkit-flow-into", +"-webkit-flow-from", +"-webkit-region-overflow", +"-webkit-wrap-shape-inside", +"-webkit-wrap-shape-outside", +"-webkit-wrap-margin", +"-webkit-wrap-padding", +"-webkit-region-break-after", +"-webkit-region-break-before", +"-webkit-region-break-inside", +"-webkit-wrap-flow", +"-webkit-wrap-through", +"-webkit-wrap", +"-webkit-grid-columns", +"-webkit-grid-rows", +"clip-path", +"clip-rule", +"mask", +"enable-background", +"filter", +"flood-color", +"flood-opacity", +"lighting-color", +"stop-color", +"stop-opacity", +"color-interpolation", +"color-interpolation-filters", +"color-profile", +"color-rendering", +"fill", +"fill-opacity", +"fill-rule", +"marker", +"marker-end", +"marker-mid", +"marker-start", +"shape-rendering", +"stroke", +"stroke-dasharray", +"stroke-dashoffset", +"stroke-linecap", +"stroke-linejoin", +"stroke-miterlimit", +"stroke-opacity", +"stroke-width", +"alignment-baseline", +"baseline-shift", +"dominant-baseline", +"glyph-orientation-horizontal", +"glyph-orientation-vertical", +"kerning", +"text-anchor", +"vector-effect", +"writing-mode", +"-webkit-svg-shadow", +"-webkit-dashboard-region", +}; + +const char* getPropertyName(CSSPropertyID); +WTF::String getJSPropertyName(CSSPropertyID); + +} // namespace WebCore + +#endif // CSSPropertyNames_h + diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSPropertySourceData.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSPropertySourceData.h new file mode 100644 index 000000000..f20af1af8 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSPropertySourceData.h @@ -0,0 +1,100 @@ +/* + * 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. + * * 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 CSSPropertySourceData_h +#define CSSPropertySourceData_h + +#include "PlatformString.h" +#include +#include +#include +#include +#include + +namespace WebCore { + +class CSSStyleRule; + +struct SourceRange { + SourceRange(); + SourceRange(unsigned start, unsigned end); + unsigned length() const; + + unsigned start; + unsigned end; +}; + +struct CSSPropertySourceData { + static void init(); + + CSSPropertySourceData(const String& name, const String& value, bool important, bool parsedOk, const SourceRange& range); + CSSPropertySourceData(const CSSPropertySourceData& other); + CSSPropertySourceData(); + + String toString() const; + unsigned hash() const; + + String name; + String value; + bool important; + bool parsedOk; + SourceRange range; +}; + +#ifndef CSSPROPERTYSOURCEDATA_HIDE_GLOBALS +extern const CSSPropertySourceData emptyCSSPropertySourceData; +#endif + +struct CSSStyleSourceData : public RefCounted { + static PassRefPtr create() + { + return adoptRef(new CSSStyleSourceData()); + } + + // Range of the style text in the enclosing source. + SourceRange styleBodyRange; + Vector propertyData; +}; + +struct CSSRuleSourceData : public RefCounted { + static PassRefPtr create() + { + return adoptRef(new CSSRuleSourceData()); + } + + // Range of the selector list in the enclosing source. + SourceRange selectorListRange; + RefPtr styleSourceData; +}; +typedef HashMap > StyleRuleRangeMap; + +} // namespace WebCore + +#endif // CSSPropertySourceData_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSReflectValue.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSReflectValue.h new file mode 100644 index 000000000..5b03efe89 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSReflectValue.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 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 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 CSSReflectValue_h +#define CSSReflectValue_h + +#include "CSSReflectionDirection.h" +#include "CSSValue.h" +#include +#include + +namespace WebCore { + +class CSSPrimitiveValue; + +class CSSReflectValue : public CSSValue { +public: + static PassRefPtr create(CSSReflectionDirection direction, + PassRefPtr offset, PassRefPtr mask) + { + return adoptRef(new CSSReflectValue(direction, offset, mask)); + } + + CSSReflectionDirection direction() const { return m_direction; } + CSSPrimitiveValue* offset() const { return m_offset.get(); } + CSSValue* mask() const { return m_mask.get(); } + + String customCssText() const; + + void addSubresourceStyleURLs(ListHashSet&, const CSSStyleSheet*); + +private: + CSSReflectValue(CSSReflectionDirection direction, PassRefPtr offset, PassRefPtr mask) + : CSSValue(ReflectClass) + , m_direction(direction) + , m_offset(offset) + , m_mask(mask) + { + } + + CSSReflectionDirection m_direction; + RefPtr m_offset; + RefPtr m_mask; +}; + +} // namespace WebCore + +#endif // CSSReflectValue_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSReflectionDirection.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSReflectionDirection.h new file mode 100644 index 000000000..e30bc1c13 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSReflectionDirection.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 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 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 CSSReflectionDirection_h +#define CSSReflectionDirection_h + +namespace WebCore { + +enum CSSReflectionDirection { ReflectionBelow, ReflectionAbove, ReflectionLeft, ReflectionRight }; + +} // namespace WebCore + +#endif // CSSReflectionDirection_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSRule.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSRule.h new file mode 100644 index 000000000..4f3ca3b74 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSRule.h @@ -0,0 +1,146 @@ +/* + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * (C) 2002-2003 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2002, 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2011 Andreas Kling (kling@webkit.org) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef CSSRule_h +#define CSSRule_h + +#include "CSSStyleSheet.h" +#include "KURLHash.h" +#include + +namespace WebCore { + +typedef int ExceptionCode; + +class CSSRule : public RefCounted { +public: + // Override RefCounted's deref() to ensure operator delete is called on + // the appropriate subclass type. + void deref() + { + if (derefBase()) + destroy(); + } + + enum Type { + UNKNOWN_RULE, + STYLE_RULE, + CHARSET_RULE, + IMPORT_RULE, + MEDIA_RULE, + FONT_FACE_RULE, + PAGE_RULE, + // 7 used to be VARIABLES_RULE + WEBKIT_KEYFRAMES_RULE = 8, + WEBKIT_KEYFRAME_RULE, + WEBKIT_REGION_RULE + }; + + Type type() const { return static_cast(m_type); } + + bool isCharsetRule() const { return type() == CHARSET_RULE; } + bool isFontFaceRule() const { return type() == FONT_FACE_RULE; } + bool isKeyframeRule() const { return type() == WEBKIT_KEYFRAME_RULE; } + bool isKeyframesRule() const { return type() == WEBKIT_KEYFRAMES_RULE; } + bool isMediaRule() const { return type() == MEDIA_RULE; } + bool isPageRule() const { return type() == PAGE_RULE; } + bool isStyleRule() const { return type() == STYLE_RULE; } + bool isRegionRule() const { return type() == WEBKIT_REGION_RULE; } + bool isImportRule() const { return type() == IMPORT_RULE; } + + bool useStrictParsing() const + { + if (parentRule()) + return parentRule()->useStrictParsing(); + if (parentStyleSheet()) + return parentStyleSheet()->useStrictParsing(); + return true; + } + + void setParentStyleSheet(CSSStyleSheet* styleSheet) + { + m_parentIsRule = false; + m_parentStyleSheet = styleSheet; + } + + void setParentRule(CSSRule* rule) + { + m_parentIsRule = true; + m_parentRule = rule; + } + + CSSStyleSheet* parentStyleSheet() const + { + if (m_parentIsRule) + return m_parentRule ? m_parentRule->parentStyleSheet() : 0; + return m_parentStyleSheet; + } + + CSSRule* parentRule() const { return m_parentIsRule ? m_parentRule : 0; } + + String cssText() const; + void setCssText(const String&, ExceptionCode&); + + KURL baseURL() const + { + if (CSSStyleSheet* parentSheet = parentStyleSheet()) + return parentSheet->baseURL(); + return KURL(); + } + +protected: + CSSRule(CSSStyleSheet* parent, Type type) + : m_sourceLine(0) + , m_hasCachedSelectorText(false) + , m_parentIsRule(false) + , m_type(type) + , m_parentStyleSheet(parent) + { + } + + // NOTE: This class is non-virtual for memory and performance reasons. + // Don't go making it virtual again unless you know exactly what you're doing! + + ~CSSRule() { } + + int sourceLine() const { return m_sourceLine; } + void setSourceLine(int sourceLine) { m_sourceLine = sourceLine; } + bool hasCachedSelectorText() const { return m_hasCachedSelectorText; } + void setHasCachedSelectorText(bool hasCachedSelectorText) const { m_hasCachedSelectorText = hasCachedSelectorText; } + +private: + // Only used by CSSStyleRule but kept here to maximize struct packing. + signed m_sourceLine : 26; + mutable unsigned m_hasCachedSelectorText : 1; + unsigned m_parentIsRule : 1; + unsigned m_type : 4; + union { + CSSRule* m_parentRule; + CSSStyleSheet* m_parentStyleSheet; + }; + + void destroy(); +}; + +} // namespace WebCore + +#endif // CSSRule_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSRuleList.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSRuleList.h new file mode 100644 index 000000000..ea52c8607 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSRuleList.h @@ -0,0 +1,71 @@ +/* + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * (C) 2002-2003 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2002, 2006 Apple Computer, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef CSSRuleList_h +#define CSSRuleList_h + +#include +#include +#include +#include +#include + +namespace WebCore { + +class CSSRule; +class CSSStyleSheet; + +class CSSRuleList : public RefCounted { +public: + static PassRefPtr create(CSSStyleSheet* styleSheet, bool omitCharsetRules = false) + { + return adoptRef(new CSSRuleList(styleSheet, omitCharsetRules)); + } + static PassRefPtr create() + { + return adoptRef(new CSSRuleList); + } + ~CSSRuleList(); + + unsigned length() const; + CSSRule* item(unsigned index) const; + + // FIXME: Not part of the CSSOM. Only used by @media and @-webkit-keyframes rules. + unsigned insertRule(CSSRule*, unsigned index); + void deleteRule(unsigned index); + + void append(CSSRule*); + + CSSStyleSheet* styleSheet() { return m_styleSheet.get(); } + + String rulesText() const; + +private: + CSSRuleList(); + CSSRuleList(CSSStyleSheet*, bool omitCharsetRules); + + RefPtr m_styleSheet; + Vector > m_lstCSSRules; // FIXME: Want to eliminate, but used by IE rules() extension and still used by media rules. +}; + +} // namespace WebCore + +#endif // CSSRuleList_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSSelector.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSSelector.h new file mode 100644 index 000000000..afd52def9 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSSelector.h @@ -0,0 +1,374 @@ +/* + * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org) + * 1999 Waldo Bastian (bastian@kde.org) + * Copyright (C) 2004, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef CSSSelector_h +#define CSSSelector_h + +#include "QualifiedName.h" +#include "RenderStyleConstants.h" +#include +#include +#include + +namespace WebCore { + class CSSSelectorList; + + // this class represents a selector for a StyleRule + class CSSSelector { + WTF_MAKE_NONCOPYABLE(CSSSelector); WTF_MAKE_FAST_ALLOCATED; + public: + CSSSelector() + : m_relation(Descendant) + , m_match(None) + , m_pseudoType(PseudoNotParsed) + , m_parsedNth(false) + , m_isLastInSelectorList(false) + , m_isLastInTagHistory(true) + , m_hasRareData(false) + , m_isForPage(false) + , m_tag(anyQName()) + { + } + + CSSSelector(const QualifiedName& qName) + : m_relation(Descendant) + , m_match(None) + , m_pseudoType(PseudoNotParsed) + , m_parsedNth(false) + , m_isLastInSelectorList(false) + , m_isLastInTagHistory(true) + , m_hasRareData(false) + , m_isForPage(false) + , m_tag(qName) + { + } + + ~CSSSelector() + { + if (m_hasRareData) + delete m_data.m_rareData; + else if (m_data.m_value) + m_data.m_value->deref(); + } + + /** + * Re-create selector text from selector's data + */ + String selectorText() const; + + // checks if the 2 selectors (including sub selectors) agree. + bool operator==(const CSSSelector&); + + // tag == -1 means apply to all elements (Selector = *) + + unsigned specificity() const; + + /* how the attribute value has to match.... Default is Exact */ + enum Match { + None = 0, + Id, + Class, + Exact, + Set, + List, + Hyphen, + PseudoClass, + PseudoElement, + Contain, // css3: E[foo*="bar"] + Begin, // css3: E[foo^="bar"] + End, // css3: E[foo$="bar"] + PagePseudoClass + }; + + enum Relation { + Descendant = 0, + Child, + DirectAdjacent, + IndirectAdjacent, + SubSelector, + ShadowDescendant + }; + + enum PseudoType { + PseudoNotParsed = 0, + PseudoUnknown, + PseudoEmpty, + PseudoFirstChild, + PseudoFirstOfType, + PseudoLastChild, + PseudoLastOfType, + PseudoOnlyChild, + PseudoOnlyOfType, + PseudoFirstLine, + PseudoFirstLetter, + PseudoNthChild, + PseudoNthOfType, + PseudoNthLastChild, + PseudoNthLastOfType, + PseudoLink, + PseudoVisited, + PseudoAny, + PseudoAnyLink, + PseudoAutofill, + PseudoHover, + PseudoDrag, + PseudoFocus, + PseudoActive, + PseudoChecked, + PseudoEnabled, + PseudoFullPageMedia, + PseudoDefault, + PseudoDisabled, + PseudoOptional, + PseudoRequired, + PseudoReadOnly, + PseudoReadWrite, + PseudoValid, + PseudoInvalid, + PseudoIndeterminate, + PseudoTarget, + PseudoBefore, + PseudoAfter, + PseudoLang, + PseudoNot, + PseudoResizer, + PseudoRoot, + PseudoScrollbar, + PseudoScrollbarBack, + PseudoScrollbarButton, + PseudoScrollbarCorner, + PseudoScrollbarForward, + PseudoScrollbarThumb, + PseudoScrollbarTrack, + PseudoScrollbarTrackPiece, + PseudoWindowInactive, + PseudoCornerPresent, + PseudoDecrement, + PseudoIncrement, + PseudoHorizontal, + PseudoVertical, + PseudoStart, + PseudoEnd, + PseudoDoubleButton, + PseudoSingleButton, + PseudoNoButton, + PseudoSelection, + PseudoInputListButton, + PseudoLeftPage, + PseudoRightPage, + PseudoFirstPage, +#if ENABLE(FULLSCREEN_API) + PseudoFullScreen, + PseudoFullScreenDocument, + PseudoFullScreenAncestor, + PseudoAnimatingFullScreenTransition, +#endif + PseudoInRange, + PseudoOutOfRange, + }; + + enum MarginBoxType { + TopLeftCornerMarginBox, + TopLeftMarginBox, + TopCenterMarginBox, + TopRightMarginBox, + TopRightCornerMarginBox, + BottomLeftCornerMarginBox, + BottomLeftMarginBox, + BottomCenterMarginBox, + BottomRightMarginBox, + BottomRightCornerMarginBox, + LeftTopMarginBox, + LeftMiddleMarginBox, + LeftBottomMarginBox, + RightTopMarginBox, + RightMiddleMarginBox, + RightBottomMarginBox, + }; + + PseudoType pseudoType() const + { + if (m_pseudoType == PseudoNotParsed) + extractPseudoType(); + return static_cast(m_pseudoType); + } + + static PseudoType parsePseudoType(const AtomicString&); + static bool isUnknownPseudoType(const AtomicString&); + static PseudoId pseudoId(PseudoType); + + // Selectors are kept in an array by CSSSelectorList. The next component of the selector is + // the next item in the array. + CSSSelector* tagHistory() const { return m_isLastInTagHistory ? 0 : const_cast(this + 1); } + + bool hasTag() const { return m_tag != anyQName(); } + + const QualifiedName& tag() const { return m_tag; } + // AtomicString is really just an AtomicStringImpl* so the cast below is safe. + // FIXME: Perhaps call sites could be changed to accept AtomicStringImpl? + const AtomicString& value() const { return *reinterpret_cast(m_hasRareData ? &m_data.m_rareData->m_value : &m_data.m_value); } + const QualifiedName& attribute() const; + const AtomicString& argument() const { return m_hasRareData ? m_data.m_rareData->m_argument : nullAtom; } + CSSSelectorList* selectorList() const { return m_hasRareData ? m_data.m_rareData->m_selectorList.get() : 0; } + + void setTag(const QualifiedName& value) { m_tag = value; } + void setValue(const AtomicString&); + void setAttribute(const QualifiedName&); + void setArgument(const AtomicString&); + void setSelectorList(PassOwnPtr); + + bool parseNth(); + bool matchNth(int count); + + bool matchesPseudoElement() const; + bool isUnknownPseudoElement() const; + bool isSiblingSelector() const; + bool isAttributeSelector() const; + + Relation relation() const { return static_cast(m_relation); } + + bool isLastInSelectorList() const { return m_isLastInSelectorList; } + void setLastInSelectorList() { m_isLastInSelectorList = true; } + bool isLastInTagHistory() const { return m_isLastInTagHistory; } + void setNotLastInTagHistory() { m_isLastInTagHistory = false; } + + bool isSimple() const; + + bool isForPage() const { return m_isForPage; } + void setForPage() { m_isForPage = true; } + + unsigned m_relation : 3; // enum Relation + mutable unsigned m_match : 4; // enum Match + mutable unsigned m_pseudoType : 8; // PseudoType + + private: + bool m_parsedNth : 1; // Used for :nth-* + bool m_isLastInSelectorList : 1; + bool m_isLastInTagHistory : 1; + bool m_hasRareData : 1; + bool m_isForPage : 1; + + unsigned specificityForOneSelector() const; + unsigned specificityForPage() const; + void extractPseudoType() const; + + struct RareData { + WTF_MAKE_NONCOPYABLE(RareData); WTF_MAKE_FAST_ALLOCATED; + public: + RareData(PassRefPtr value); + ~RareData(); + + bool parseNth(); + bool matchNth(int count); + + AtomicStringImpl* m_value; // Plain pointer to keep things uniform with the union. + int m_a; // Used for :nth-* + int m_b; // Used for :nth-* + QualifiedName m_attribute; // used for attribute selector + AtomicString m_argument; // Used for :contains, :lang and :nth-* + OwnPtr m_selectorList; // Used for :-webkit-any and :not + }; + void createRareData(); + + union DataUnion { + DataUnion() : m_value(0) { } + AtomicStringImpl* m_value; + RareData* m_rareData; + } m_data; + + QualifiedName m_tag; + }; + +inline const QualifiedName& CSSSelector::attribute() const +{ + ASSERT(isAttributeSelector()); + ASSERT(m_hasRareData); + return m_data.m_rareData->m_attribute; +} + +inline bool CSSSelector::matchesPseudoElement() const +{ + if (m_pseudoType == PseudoUnknown) + extractPseudoType(); + return m_match == PseudoElement; +} + +inline bool CSSSelector::isUnknownPseudoElement() const +{ + return m_match == PseudoElement && m_pseudoType == PseudoUnknown; +} + +inline bool CSSSelector::isSiblingSelector() const +{ + PseudoType type = pseudoType(); + return m_relation == DirectAdjacent + || m_relation == IndirectAdjacent + || type == PseudoEmpty + || type == PseudoFirstChild + || type == PseudoFirstOfType + || type == PseudoLastChild + || type == PseudoLastOfType + || type == PseudoOnlyChild + || type == PseudoOnlyOfType + || type == PseudoNthChild + || type == PseudoNthOfType + || type == PseudoNthLastChild + || type == PseudoNthLastOfType; +} + +inline bool CSSSelector::isAttributeSelector() const +{ + return m_match == CSSSelector::Exact + || m_match == CSSSelector::Set + || m_match == CSSSelector::List + || m_match == CSSSelector::Hyphen + || m_match == CSSSelector::Contain + || m_match == CSSSelector::Begin + || m_match == CSSSelector::End; +} + +inline void CSSSelector::setValue(const AtomicString& value) +{ + // Need to do ref counting manually for the union. + if (m_hasRareData) { + if (m_data.m_rareData->m_value) + m_data.m_rareData->m_value->deref(); + m_data.m_rareData->m_value = value.impl(); + m_data.m_rareData->m_value->ref(); + return; + } + if (m_data.m_value) + m_data.m_value->deref(); + m_data.m_value = value.impl(); + m_data.m_value->ref(); +} + +inline void move(PassOwnPtr from, CSSSelector* to) +{ + memcpy(to, from.get(), sizeof(CSSSelector)); + // We want to free the memory (which was allocated with fastNew), but we + // don't want the destructor to run since it will affect the copy we've just made. + fastDeleteSkippingDestructor(from.leakPtr()); +} + +} // namespace WebCore + +#endif // CSSSelector_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSStyleDeclaration.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSStyleDeclaration.h new file mode 100644 index 000000000..8c1e84dfb --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSStyleDeclaration.h @@ -0,0 +1,119 @@ +/* + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef CSSStyleDeclaration_h +#define CSSStyleDeclaration_h + +#include "CSSRule.h" +#include + +namespace WebCore { + +class CSSMutableStyleDeclaration; +class CSSProperty; +class CSSStyleSheet; +class CSSValue; +class StyledElement; + +typedef int ExceptionCode; + +class CSSStyleDeclaration : public RefCounted { + WTF_MAKE_NONCOPYABLE(CSSStyleDeclaration); +public: + virtual ~CSSStyleDeclaration() { } + + static bool isPropertyName(const String&); + + CSSRule* parentRule() const { return m_isElementStyleDeclaration ? 0 : m_parent.rule; } + void clearParentRule() { ASSERT(!m_isElementStyleDeclaration); m_parent.rule = 0; } + + StyledElement* parentElement() const { ASSERT(m_isElementStyleDeclaration); return m_parent.element; } + void clearParentElement() { ASSERT(m_isElementStyleDeclaration); m_parent.element = 0; } + + CSSStyleSheet* parentStyleSheet() const; + + virtual String cssText() const = 0; + virtual void setCssText(const String&, ExceptionCode&) = 0; + + unsigned length() const { return virtualLength(); } + virtual unsigned virtualLength() const = 0; + bool isEmpty() const { return !length(); } + virtual String item(unsigned index) const = 0; + + PassRefPtr getPropertyCSSValue(const String& propertyName); + String getPropertyValue(const String& propertyName); + String getPropertyPriority(const String& propertyName); + String getPropertyShorthand(const String& propertyName); + bool isPropertyImplicit(const String& propertyName); + + virtual PassRefPtr getPropertyCSSValue(int propertyID) const = 0; + virtual String getPropertyValue(int propertyID) const = 0; + virtual bool getPropertyPriority(int propertyID) const = 0; + virtual int getPropertyShorthand(int propertyID) const = 0; + virtual bool isPropertyImplicit(int propertyID) const = 0; + + void setProperty(const String& propertyName, const String& value, const String& priority, ExceptionCode&); + String removeProperty(const String& propertyName, ExceptionCode&); + virtual void setProperty(int propertyId, const String& value, bool important, ExceptionCode&) = 0; + virtual String removeProperty(int propertyID, ExceptionCode&) = 0; + + virtual PassRefPtr copy() const = 0; + virtual PassRefPtr makeMutable() = 0; + + void diff(CSSMutableStyleDeclaration*) const; + + PassRefPtr copyPropertiesInSet(const int* set, unsigned length) const; + +#ifndef NDEBUG + void showStyle(); +#endif + + bool isElementStyleDeclaration() const { return m_isElementStyleDeclaration; } + bool isInlineStyleDeclaration() const { return m_isInlineStyleDeclaration; } + +protected: + CSSStyleDeclaration(CSSRule* parentRule = 0); + CSSStyleDeclaration(StyledElement* parentElement, bool isInline); + + virtual bool cssPropertyMatches(const CSSProperty*) const; + + // The bits in this section are only used by specific subclasses but kept here + // to maximize struct packing. + + // CSSMutableStyleDeclaration bits: + bool m_strictParsing : 1; +#ifndef NDEBUG + unsigned m_iteratorCount : 4; +#endif + bool m_isElementStyleDeclaration : 1; + bool m_isInlineStyleDeclaration : 1; + +private: + union Parent { + Parent(CSSRule* rule) : rule(rule) { } + Parent(StyledElement* element) : element(element) { } + CSSRule* rule; + StyledElement* element; + } m_parent; +}; + +} // namespace WebCore + +#endif // CSSStyleDeclaration_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSStyleSheet.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSStyleSheet.h new file mode 100644 index 000000000..b027365f2 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSStyleSheet.h @@ -0,0 +1,135 @@ +/* + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef CSSStyleSheet_h +#define CSSStyleSheet_h + +#include "CSSRuleList.h" +#include "StyleSheet.h" + +namespace WebCore { + +struct CSSNamespace; +class CSSParser; +class CSSRule; +class CachedResourceLoader; +class Document; + +typedef int ExceptionCode; + +class CSSStyleSheet : public StyleSheet { +public: + static PassRefPtr create() + { + return adoptRef(new CSSStyleSheet(static_cast(0), String(), KURL(), String())); + } + static PassRefPtr create(Node* ownerNode) + { + return adoptRef(new CSSStyleSheet(ownerNode, String(), KURL(), String())); + } + static PassRefPtr create(Node* ownerNode, const String& originalURL, const KURL& finalURL, const String& charset) + { + return adoptRef(new CSSStyleSheet(ownerNode, originalURL, finalURL, charset)); + } + static PassRefPtr create(CSSImportRule* ownerRule, const String& originalURL, const KURL& finalURL, const String& charset) + { + return adoptRef(new CSSStyleSheet(ownerRule, originalURL, finalURL, charset)); + } + static PassRefPtr createInline(Node* ownerNode, const KURL& finalURL) + { + return adoptRef(new CSSStyleSheet(ownerNode, finalURL.string(), finalURL, String())); + } + + virtual ~CSSStyleSheet(); + + CSSStyleSheet* parentStyleSheet() const + { + StyleSheet* parentSheet = StyleSheet::parentStyleSheet(); + ASSERT(!parentSheet || parentSheet->isCSSStyleSheet()); + return static_cast(parentSheet); + } + + PassRefPtr cssRules(bool omitCharsetRules = false); + unsigned insertRule(const String& rule, unsigned index, ExceptionCode&); + void deleteRule(unsigned index, ExceptionCode&); + + // IE Extensions + PassRefPtr rules() { return cssRules(true); } + int addRule(const String& selector, const String& style, int index, ExceptionCode&); + int addRule(const String& selector, const String& style, ExceptionCode&); + void removeRule(unsigned index, ExceptionCode& ec) { deleteRule(index, ec); } + + void addNamespace(CSSParser*, const AtomicString& prefix, const AtomicString& uri); + const AtomicString& determineNamespace(const AtomicString& prefix); + + void styleSheetChanged(); + + virtual bool parseString(const String&, bool strict = true); + + bool parseStringAtLine(const String&, bool strict, int startLineNumber); + + virtual bool isLoading(); + + void checkLoaded(); + void startLoadingDynamicSheet(); + + Node* findStyleSheetOwnerNode() const; + Document* findDocument(); + + const String& charset() const { return m_charset; } + + bool loadCompleted() const { return m_loadCompleted; } + + KURL completeURL(const String& url) const; + void addSubresourceStyleURLs(ListHashSet&); + + void setStrictParsing(bool b) { m_strictParsing = b; } + bool useStrictParsing() const { return m_strictParsing; } + + void setIsUserStyleSheet(bool b) { m_isUserStyleSheet = b; } + bool isUserStyleSheet() const { return m_isUserStyleSheet; } + void setHasSyntacticallyValidCSSHeader(bool b) { m_hasSyntacticallyValidCSSHeader = b; } + bool hasSyntacticallyValidCSSHeader() const { return m_hasSyntacticallyValidCSSHeader; } + + void append(PassRefPtr); + void remove(unsigned index); + + unsigned length() const { return m_children.size(); } + CSSRule* item(unsigned index) { return index < length() ? m_children.at(index).get() : 0; } + +private: + CSSStyleSheet(Node* ownerNode, const String& originalURL, const KURL& finalURL, const String& charset); + CSSStyleSheet(CSSImportRule* ownerRule, const String& originalURL, const KURL& finalURL, const String& charset); + + virtual bool isCSSStyleSheet() const { return true; } + virtual String type() const { return "text/css"; } + + Vector > m_children; + OwnPtr m_namespaces; + String m_charset; + bool m_loadCompleted : 1; + bool m_strictParsing : 1; + bool m_isUserStyleSheet : 1; + bool m_hasSyntacticallyValidCSSHeader : 1; +}; + +} // namespace + +#endif diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSValue.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSValue.h new file mode 100644 index 000000000..2d3324232 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSValue.h @@ -0,0 +1,189 @@ +/* + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef CSSValue_h +#define CSSValue_h + +#include "KURLHash.h" +#include +#include +#include + +namespace WebCore { + +class CSSStyleSheet; + +typedef int ExceptionCode; + +class CSSValue : public RefCounted { +public: + enum Type { + CSS_INHERIT = 0, + CSS_PRIMITIVE_VALUE = 1, + CSS_VALUE_LIST = 2, + CSS_CUSTOM = 3, + CSS_INITIAL = 4 + + }; + + // Override RefCounted's deref() to ensure operator delete is called on + // the appropriate subclass type. + void deref() + { + if (derefBase()) + destroy(); + } + + Type cssValueType() const; + + String cssText() const; + void setCssText(const String&, ExceptionCode&) { } // FIXME: Not implemented. + + bool isPrimitiveValue() const { return m_classType <= PrimitiveClass; } + bool isValueList() const { return m_classType >= ValueListClass; } + + bool isAspectRatioValue() const { return m_classType == AspectRatioClass; } + bool isBorderImageSliceValue() const { return m_classType == BorderImageSliceClass; } + bool isCursorImageValue() const { return m_classType == CursorImageClass; } + bool isFontFamilyValue() const { return m_classType == FontFamilyClass; } + bool isFontFeatureValue() const { return m_classType == FontFeatureClass; } + bool isFontValue() const { return m_classType == FontClass; } + bool isImageGeneratorValue() const { return m_classType >= CanvasClass && m_classType <= RadialGradientClass; } + bool isImageValue() const { return m_classType == ImageClass || m_classType == CursorImageClass; } + bool isImplicitInitialValue() const; + bool isInheritedValue() const { return m_classType == InheritedClass; } + bool isInitialValue() const { return m_classType == InitialClass; } + bool isReflectValue() const { return m_classType == ReflectClass; } + bool isShadowValue() const { return m_classType == ShadowClass; } + bool isTimingFunctionValue() const { return m_classType >= CubicBezierTimingFunctionClass && m_classType <= StepsTimingFunctionClass; } + bool isWebKitCSSTransformValue() const { return m_classType == WebKitCSSTransformClass; } + bool isCSSLineBoxContainValue() const { return m_classType == LineBoxContainClass; } + bool isFlexValue() const { return m_classType == FlexClass; } +#if ENABLE(CSS_FILTERS) + bool isWebKitCSSFilterValue() const { return m_classType == WebKitCSSFilterClass; } +#if ENABLE(CSS_SHADERS) + bool isWebKitCSSShaderValue() const { return m_classType == WebKitCSSShaderClass; } +#endif +#endif // ENABLE(CSS_FILTERS) +#if ENABLE(SVG) + bool isSVGColor() const { return m_classType == SVGColorClass || m_classType == SVGPaintClass; } + bool isSVGPaint() const { return m_classType == SVGPaintClass; } +#endif + + void addSubresourceStyleURLs(ListHashSet&, const CSSStyleSheet*); + +protected: + + static const size_t ClassTypeBits = 5; + enum ClassType { + // Primitive class types must appear before PrimitiveClass. + ImageClass, + CursorImageClass, + FontFamilyClass, + PrimitiveClass, + + // Image generator classes. + CanvasClass, + CrossfadeClass, + LinearGradientClass, + RadialGradientClass, + + // Timing function classes. + CubicBezierTimingFunctionClass, + LinearTimingFunctionClass, + StepsTimingFunctionClass, + + // Other class types. + AspectRatioClass, + BorderImageSliceClass, + FontFeatureClass, + FontClass, + FontFaceSrcClass, + FunctionClass, + + InheritedClass, + InitialClass, + + ReflectClass, + ShadowClass, + UnicodeRangeClass, + LineBoxContainClass, + FlexClass, +#if ENABLE(CSS_FILTERS) && ENABLE(CSS_SHADERS) + WebKitCSSShaderClass, +#endif +#if ENABLE(SVG) + SVGColorClass, + SVGPaintClass, +#endif + + // List class types must appear after ValueListClass. + ValueListClass, +#if ENABLE(CSS_FILTERS) + WebKitCSSFilterClass, +#endif + WebKitCSSTransformClass, + // Do not append non-list class types here. + }; + + static const size_t ValueListSeparatorBits = 2; + enum ValueListSeparator { + SpaceSeparator, + CommaSeparator, + SlashSeparator + }; + + ClassType classType() const { return static_cast(m_classType); } + + explicit CSSValue(ClassType classType) + : m_primitiveUnitType(0) + , m_hasCachedCSSText(false) + , m_isQuirkValue(false) + , m_valueListSeparator(SpaceSeparator) + , m_classType(classType) + { + } + + // NOTE: This class is non-virtual for memory and performance reasons. + // Don't go making it virtual again unless you know exactly what you're doing! + + ~CSSValue() { } + +private: + void destroy(); + +protected: + // The bits in this section are only used by specific subclasses but kept here + // to maximize struct packing. + + // CSSPrimitiveValue bits: + unsigned char m_primitiveUnitType : 7; // CSSPrimitiveValue::UnitTypes + mutable bool m_hasCachedCSSText : 1; + bool m_isQuirkValue : 1; + + unsigned char m_valueListSeparator : ValueListSeparatorBits; + +private: + unsigned char m_classType : ClassTypeBits; // ClassType +}; + +} // namespace WebCore + +#endif // CSSValue_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSValueList.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSValueList.h new file mode 100644 index 000000000..16d195b0d --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSValueList.h @@ -0,0 +1,105 @@ +/* + * (C) 1999-2003 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef CSSValueList_h +#define CSSValueList_h + +#include "CSSValue.h" +#include +#include + +namespace WebCore { + +class CSSParserValueList; + +class CSSValueList : public CSSValue { +public: + static PassRefPtr createCommaSeparated() + { + return adoptRef(new CSSValueList(CommaSeparator)); + } + static PassRefPtr createSpaceSeparated() + { + return adoptRef(new CSSValueList(SpaceSeparator)); + } + static PassRefPtr createSlashSeparated() + { + return adoptRef(new CSSValueList(SlashSeparator)); + } + static PassRefPtr createFromParserValueList(CSSParserValueList* list) + { + return adoptRef(new CSSValueList(list)); + } + + size_t length() const { return m_values.size(); } + CSSValue* item(size_t index) { return index < m_values.size() ? m_values[index].get() : 0; } + CSSValue* itemWithoutBoundsCheck(size_t index) { return m_values[index].get(); } + + void append(PassRefPtr); + void prepend(PassRefPtr); + bool removeAll(CSSValue*); + bool hasValue(CSSValue*) const; + PassRefPtr copy(); + + String customCssText() const; + + void addSubresourceStyleURLs(ListHashSet&, const CSSStyleSheet*); + +protected: + CSSValueList(ClassType, ValueListSeparator); + +private: + explicit CSSValueList(ValueListSeparator); + explicit CSSValueList(CSSParserValueList*); + + Vector > m_values; +}; + +// Objects of this class are intended to be stack-allocated and scoped to a single function. +// Please take care not to pass these around as they do hold onto a raw pointer. +class CSSValueListInspector { +public: + CSSValueListInspector(CSSValue* value) : m_list((value && value->isValueList()) ? static_cast(value) : 0) { } + CSSValue* item(size_t index) const { ASSERT(index < length()); return m_list->itemWithoutBoundsCheck(index); } + CSSValue* first() const { return item(0); } + CSSValue* second() const { return item(1); } + size_t length() const { return m_list ? m_list->length() : 0; } +private: + CSSValueList* m_list; +}; + +// Wrapper that can be used to iterate over any CSSValue. Non-list values and 0 behave as zero-length lists. +// Objects of this class are intended to be stack-allocated and scoped to a single function. +// Please take care not to pass these around as they do hold onto a raw pointer. +class CSSValueListIterator { +public: + CSSValueListIterator(CSSValue* value) : m_inspector(value), m_position(0) { } + bool hasMore() const { return m_position < m_inspector.length(); } + CSSValue* value() const { return m_inspector.item(m_position); } + bool isPrimitiveValue() const { return value()->isPrimitiveValue(); } + void advance() { m_position++; ASSERT(m_position <= m_inspector.length());} + size_t index() const { return m_position; } +private: + CSSValueListInspector m_inspector; + size_t m_position; +}; +} // namespace WebCore + +#endif // CSSValueList_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSWrapShapes.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSWrapShapes.h new file mode 100644 index 000000000..3ff9fab83 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CSSWrapShapes.h @@ -0,0 +1,173 @@ +/* + * Copyright 2011 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER “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 HOLDER 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 CSSWrapShapes_h +#define CSSWrapShapes_h + +#include "CSSPrimitiveValue.h" +#include "PlatformString.h" +#include "WindRule.h" +#include +#include + +namespace WebCore { + +class CSSWrapShape : public RefCounted { +public: + enum Type { + CSS_WRAP_SHAPE_RECT = 1, + CSS_WRAP_SHAPE_CIRCLE = 2, + CSS_WRAP_SHAPE_ELLIPSE = 3, + CSS_WRAP_SHAPE_POLYGON = 4, + CSS_WRAP_SHAPE_PATH = 5 + }; + + virtual Type type() = 0; + virtual String cssText() const = 0; + +public: + virtual ~CSSWrapShape() { } + +protected: + CSSWrapShape() { } +}; + +class CSSWrapShapeRect : public CSSWrapShape { +public: + static PassRefPtr create() { return adoptRef(new CSSWrapShapeRect); } + + CSSPrimitiveValue* left() const { return m_left.get(); } + CSSPrimitiveValue* top() const { return m_top.get(); } + CSSPrimitiveValue* width() const { return m_width.get(); } + CSSPrimitiveValue* height() const { return m_height.get(); } + CSSPrimitiveValue* radiusX() const { return m_radiusX.get(); } + CSSPrimitiveValue* radiusY() const { return m_radiusY.get(); } + + void setLeft(PassRefPtr left) { m_left = left; } + void setTop(PassRefPtr top) { m_top = top; } + void setWidth(PassRefPtr width) { m_width = width; } + void setHeight(PassRefPtr height) { m_height = height; } + void setRadiusX(PassRefPtr radiusX) { m_radiusX = radiusX; } + void setRadiusY(PassRefPtr radiusY) { m_radiusY = radiusY; } + + virtual Type type() { return CSS_WRAP_SHAPE_RECT; } + virtual String cssText() const; + +private: + CSSWrapShapeRect() { } + + RefPtr m_top; + RefPtr m_left; + RefPtr m_width; + RefPtr m_height; + RefPtr m_radiusX; + RefPtr m_radiusY; +}; + +class CSSWrapShapeCircle : public CSSWrapShape { +public: + static PassRefPtr create() { return adoptRef(new CSSWrapShapeCircle); } + + CSSPrimitiveValue* left() const { return m_left.get(); } + CSSPrimitiveValue* top() const { return m_top.get(); } + CSSPrimitiveValue* radius() const { return m_radius.get(); } + + void setLeft(PassRefPtr left) { m_left = left; } + void setTop(PassRefPtr top) { m_top = top; } + void setRadius(PassRefPtr radius) { m_radius = radius; } + + virtual Type type() { return CSS_WRAP_SHAPE_CIRCLE; } + virtual String cssText() const; + +private: + CSSWrapShapeCircle() { } + + RefPtr m_top; + RefPtr m_left; + RefPtr m_radius; +}; + +class CSSWrapShapeEllipse : public CSSWrapShape { +public: + static PassRefPtr create() { return adoptRef(new CSSWrapShapeEllipse); } + + CSSPrimitiveValue* left() const { return m_left.get(); } + CSSPrimitiveValue* top() const { return m_top.get(); } + CSSPrimitiveValue* radiusX() const { return m_radiusX.get(); } + CSSPrimitiveValue* radiusY() const { return m_radiusY.get(); } + + void setLeft(PassRefPtr left) { m_left = left; } + void setTop(PassRefPtr top) { m_top = top; } + void setRadiusX(PassRefPtr radiusX) { m_radiusX = radiusX; } + void setRadiusY(PassRefPtr radiusY) { m_radiusY = radiusY; } + + virtual Type type() { return CSS_WRAP_SHAPE_ELLIPSE; } + virtual String cssText() const; + +private: + CSSWrapShapeEllipse() { } + + RefPtr m_top; + RefPtr m_left; + RefPtr m_radiusX; + RefPtr m_radiusY; +}; + +class CSSWrapShapePolygon : public CSSWrapShape { +public: + static PassRefPtr create() { return adoptRef(new CSSWrapShapePolygon); } + + void appendPoint(PassRefPtr x, PassRefPtr y) + { + m_values.append(x); + m_values.append(y); + } + + PassRefPtr getXAt(unsigned i) { return m_values.at(i * 2); } + PassRefPtr getYAt(unsigned i) { return m_values.at(i * 2 + 1); } + + void setWindRule(WindRule w) { m_windRule = w; } + WindRule windRule() const { return m_windRule; } + + virtual Type type() { return CSS_WRAP_SHAPE_POLYGON; } + virtual String cssText() const; + +private: + CSSWrapShapePolygon() + : m_windRule(RULE_NONZERO) + { + } + + Vector > m_values; + WindRule m_windRule; +}; + +} // namespace WebCore + +#endif // CSSWrapShapes_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CachePolicy.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CachePolicy.h new file mode 100644 index 000000000..0b9010b63 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CachePolicy.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2003, 2006 Apple Computer, 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 CachePolicy_h +#define CachePolicy_h + +namespace WebCore { + + enum CachePolicy { + CachePolicyCache, + CachePolicyVerify, + CachePolicyRevalidate, + CachePolicyReload, + CachePolicyHistoryBuffer + }; + +} + +#endif diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CachedFrame.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CachedFrame.h new file mode 100644 index 000000000..aa1798905 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CachedFrame.h @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2009, 2010 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 CachedFrame_h +#define CachedFrame_h + +#include "KURL.h" +#include "ScriptCachedFrameData.h" +#include +#include +#include + +namespace WebCore { + +class CachedFrame; +class CachedFramePlatformData; +class Document; +class DocumentLoader; +class FrameView; +class Node; + +typedef Vector > CachedFrameVector; + +class CachedFrameBase { +public: + void restore(); + + Document* document() const { return m_document.get(); } + FrameView* view() const { return m_view.get(); } + const KURL& url() const { return m_url; } + DOMWindow* domWindow() const { return m_cachedFrameScriptData->domWindow(); } + bool isMainFrame() { return m_isMainFrame; } + +protected: + CachedFrameBase(Frame*); + ~CachedFrameBase(); + + RefPtr m_document; + RefPtr m_documentLoader; + RefPtr m_view; + RefPtr m_mousePressNode; + KURL m_url; + OwnPtr m_cachedFrameScriptData; + OwnPtr m_cachedFramePlatformData; + bool m_isMainFrame; +#if USE(ACCELERATED_COMPOSITING) + bool m_isComposited; +#endif + + CachedFrameVector m_childFrames; +}; + +class CachedFrame : public RefCounted, private CachedFrameBase { +public: + static PassRefPtr create(Frame* frame) { return adoptRef(new CachedFrame(frame)); } + + void open(); + void clear(); + void destroy(); + + void setCachedFramePlatformData(PassOwnPtr); + CachedFramePlatformData* cachedFramePlatformData(); + + using CachedFrameBase::document; + using CachedFrameBase::view; + using CachedFrameBase::url; + DocumentLoader* documentLoader() const { return m_documentLoader.get(); } + Node* mousePressNode() const { return m_mousePressNode.get(); } + + int descendantFrameCount() const; + +private: + CachedFrame(Frame*); +}; + +} // namespace WebCore + +#endif // CachedFrame_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CachedFramePlatformData.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CachedFramePlatformData.h new file mode 100644 index 000000000..01da8e5a6 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CachedFramePlatformData.h @@ -0,0 +1,45 @@ +/* + * 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. + * 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 CachedFramePlatformData_h +#define CachedFramePlatformData_h + +namespace WebCore { + +// The purpose of this class is to give each platform a vessel to store platform data when a page +// goes into the Back/Forward page cache, and perform some action with that data when the page comes out. +// Each platform should subclass this class as neccessary + +class CachedFramePlatformData { +public: + virtual ~CachedFramePlatformData() { } + virtual void clear() { } +}; + +} // namespace WebCore + +#endif // CachedFramePlatformData_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CachedImage.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CachedImage.h new file mode 100644 index 000000000..e7184e130 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CachedImage.h @@ -0,0 +1,135 @@ +/* + Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) + Copyright (C) 2001 Dirk Mueller + Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com) + Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef CachedImage_h +#define CachedImage_h + +#include "CachedResource.h" +#include "CachedResourceClient.h" +#include "SVGImageCache.h" +#include "ImageObserver.h" +#include "IntRect.h" +#include "Timer.h" +#include + +namespace WebCore { + +class CachedResourceLoader; +class FloatSize; +class MemoryCache; +class RenderObject; +struct Length; + +class CachedImage : public CachedResource, public ImageObserver { + friend class MemoryCache; + +public: + CachedImage(const ResourceRequest&); + CachedImage(Image*); + virtual ~CachedImage(); + + virtual void load(CachedResourceLoader*, const ResourceLoaderOptions&); + + Image* image(); // Returns the nullImage() if the image is not available yet. + Image* imageForRenderer(const RenderObject*); // Returns the nullImage() if the image is not available yet. + bool hasImage() const { return m_image.get(); } + + std::pair brokenImage(float deviceScaleFactor) const; // Returns an image and the image's resolution scale factor. + bool willPaintBrokenImage() const; + + bool canRender(const RenderObject* renderer, float multiplier) { return !errorOccurred() && !imageSizeForRenderer(renderer, multiplier).isEmpty(); } + + void setContainerSizeForRenderer(const RenderObject*, const IntSize&, float); + bool usesImageContainerSize() const; + bool imageHasRelativeWidth() const; + bool imageHasRelativeHeight() const; + + // This method takes a zoom multiplier that can be used to increase the natural size of the image by the zoom. + IntSize imageSizeForRenderer(const RenderObject*, float multiplier); // returns the size of the complete image. + void computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio); + + void removeClientForRenderer(RenderObject*); + virtual void didAddClient(CachedResourceClient*); + + virtual void allClientsRemoved(); + virtual void destroyDecodedData(); + + virtual void data(PassRefPtr data, bool allDataReceived); + virtual void error(CachedResource::Status); + virtual void setResponse(const ResourceResponse&); + + // For compatibility, images keep loading even if there are HTTP errors. + virtual bool shouldIgnoreHTTPStatusCodeErrors() const { return true; } + + virtual bool isImage() const { return true; } + bool stillNeedsLoad() const { return !errorOccurred() && status() == Unknown && !isLoading(); } + void load(); + + // ImageObserver + virtual void decodedSizeChanged(const Image* image, int delta); + virtual void didDraw(const Image*); + + virtual bool shouldPauseAnimation(const Image*); + virtual void animationAdvanced(const Image*); + virtual void changedInRect(const Image*, const IntRect&); + +private: + Image* lookupOrCreateImageForRenderer(const RenderObject*); + + void clear(); + + void createImage(); + size_t maximumDecodedImageSize(); + // If not null, changeRect is the changed part of the image. + void notifyObservers(const IntRect* changeRect = 0); + void decodedDataDeletionTimerFired(Timer*); + virtual PurgePriority purgePriority() const { return PurgeFirst; } + void checkShouldPaintBrokenImage(); + + RefPtr m_image; +#if ENABLE(SVG) + OwnPtr m_svgImageCache; +#endif + Timer m_decodedDataDeletionTimer; + bool m_shouldPaintBrokenImage; +}; + +class CachedImageClient : public CachedResourceClient { +public: + virtual ~CachedImageClient() { } + static CachedResourceClientType expectedType() { return ImageType; } + virtual CachedResourceClientType resourceClientType() { return expectedType(); } + + // Called whenever a frame of an image changes, either because we got more data from the network or + // because we are animating. If not null, the IntRect is the changed rect of the image. + virtual void imageChanged(CachedImage*, const IntRect* = 0) { } + + // Called to find out if this client wants to actually display the image. Used to tell when we + // can halt animation. Content nodes that hold image refs for example would not render the image, + // but RenderImages would (assuming they have visibility: visible and their render tree isn't hidden + // e.g., in the b/f cache or in a background tab). + virtual bool willRenderImage(CachedImage*) { return false; } +}; + +} + +#endif diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CachedPage.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CachedPage.h new file mode 100644 index 000000000..e5866cff1 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CachedPage.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2006, 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. + */ + +#ifndef CachedPage_h +#define CachedPage_h + +#include "CachedFrame.h" +#include + +namespace WebCore { + +class Document; +class DocumentLoader; +class Page; + +class CachedPage : public RefCounted { +public: + static PassRefPtr create(Page*); + ~CachedPage(); + + void restore(Page*); + void clear(); + void destroy(); + + Document* document() const { return m_cachedMainFrame->document(); } + DocumentLoader* documentLoader() const { return m_cachedMainFrame->documentLoader(); } + + double timeStamp() const { return m_timeStamp; } + + CachedFrame* cachedMainFrame() { return m_cachedMainFrame.get(); } + + void markForVistedLinkStyleRecalc() { m_needStyleRecalcForVisitedLinks = true; } + void markForFullStyleRecalc() { m_needsFullStyleRecalc = true; } + +private: + CachedPage(Page*); + + double m_timeStamp; + RefPtr m_cachedMainFrame; + bool m_needStyleRecalcForVisitedLinks; + bool m_needsFullStyleRecalc; +}; + +} // namespace WebCore + +#endif // CachedPage_h + diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CachedResource.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CachedResource.h new file mode 100644 index 000000000..b87da71ac --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CachedResource.h @@ -0,0 +1,329 @@ +/* + Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) + Copyright (C) 2001 Dirk Mueller + Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com) + Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef CachedResource_h +#define CachedResource_h + +#include "CachePolicy.h" +#include "FrameLoaderTypes.h" +#include "PlatformString.h" +#include "PurgePriority.h" +#include "ResourceLoaderOptions.h" +#include "ResourceLoadPriority.h" +#include "ResourceRequest.h" +#include "ResourceResponse.h" +#include +#include +#include +#include +#include + +namespace WebCore { + +class MemoryCache; +class CachedMetadata; +class CachedResourceClient; +class CachedResourceHandleBase; +class CachedResourceLoader; +class Frame; +class InspectorResource; +class PurgeableBuffer; +class SecurityOrigin; +class SubresourceLoader; + +// A resource that is held in the cache. Classes who want to use this object should derive +// from CachedResourceClient, to get the function calls in case the requested data has arrived. +// This class also does the actual communication with the loader to obtain the resource from the network. +class CachedResource { + WTF_MAKE_NONCOPYABLE(CachedResource); WTF_MAKE_FAST_ALLOCATED; + friend class MemoryCache; + friend class InspectorResource; + +public: + enum Type { + ImageResource, + CSSStyleSheet, + Script, + FontResource, + RawResource +#if ENABLE(XSLT) + , XSLStyleSheet +#endif +#if ENABLE(LINK_PREFETCH) + , LinkPrefetch + , LinkPrerender + , LinkSubresource +#endif +#if ENABLE(VIDEO_TRACK) + , TextTrackResource +#endif +#if ENABLE(CSS_SHADERS) + , ShaderResource +#endif + }; + + enum Status { + Unknown, // let cache decide what to do with it + Pending, // only partially loaded + Cached, // regular case + Canceled, + LoadError, + DecodeError + }; + + CachedResource(const ResourceRequest&, Type); + virtual ~CachedResource(); + + virtual void load(CachedResourceLoader*, const ResourceLoaderOptions&); + + virtual void setEncoding(const String&) { } + virtual String encoding() const { return String(); } + virtual void data(PassRefPtr data, bool allDataReceived); + virtual void error(CachedResource::Status); + + virtual bool shouldIgnoreHTTPStatusCodeErrors() const { return false; } + + ResourceRequest& resourceRequest() { return m_resourceRequest; } + const KURL& url() const { return m_resourceRequest.url();} + Type type() const { return static_cast(m_type); } + + ResourceLoadPriority loadPriority() const { return m_loadPriority; } + void setLoadPriority(ResourceLoadPriority); + + void addClient(CachedResourceClient*); + void removeClient(CachedResourceClient*); + bool hasClients() const { return !m_clients.isEmpty(); } + void deleteIfPossible(); + + enum PreloadResult { + PreloadNotReferenced, + PreloadReferenced, + PreloadReferencedWhileLoading, + PreloadReferencedWhileComplete + }; + PreloadResult preloadResult() const { return static_cast(m_preloadResult); } + + virtual void didAddClient(CachedResourceClient*); + virtual void allClientsRemoved() { } + + unsigned count() const { return m_clients.size(); } + + Status status() const { return static_cast(m_status); } + void setStatus(Status status) { m_status = status; } + + unsigned size() const { return encodedSize() + decodedSize() + overheadSize(); } + unsigned encodedSize() const { return m_encodedSize; } + unsigned decodedSize() const { return m_decodedSize; } + unsigned overheadSize() const; + + bool isLoaded() const { return !m_loading; } // FIXME. Method name is inaccurate. Loading might not have started yet. + + bool isLoading() const { return m_loading; } + void setLoading(bool b) { m_loading = b; } + + virtual bool isImage() const { return false; } + bool ignoreForRequestCount() const + { + return false +#if ENABLE(LINK_PREFETCH) + || type() == LinkPrefetch + || type() == LinkPrerender + || type() == LinkSubresource +#endif + || type() == RawResource; + } + + unsigned accessCount() const { return m_accessCount; } + void increaseAccessCount() { m_accessCount++; } + + // Computes the status of an object after loading. + // Updates the expire date on the cache entry file + void finish(); + + bool passesAccessControlCheck(SecurityOrigin*); + + // Called by the cache if the object has been removed from the cache + // while still being referenced. This means the object should delete itself + // if the number of clients observing it ever drops to 0. + // The resource can be brought back to cache after successful revalidation. + void setInCache(bool inCache) { m_inCache = inCache; } + bool inCache() const { return m_inCache; } + + void setInLiveDecodedResourcesList(bool b) { m_inLiveDecodedResourcesList = b; } + bool inLiveDecodedResourcesList() { return m_inLiveDecodedResourcesList; } + + void stopLoading(); + + SharedBuffer* data() const { ASSERT(!m_purgeableData); return m_data.get(); } + + virtual void willSendRequest(ResourceRequest&, const ResourceResponse&) { m_requestedFromNetworkingLayer = true; } + virtual void setResponse(const ResourceResponse&); + const ResourceResponse& response() const { return m_response; } + + // Sets the serialized metadata retrieved from the platform's cache. + void setSerializedCachedMetadata(const char*, size_t); + + // Caches the given metadata in association with this resource and suggests + // that the platform persist it. The dataTypeID is a pseudo-randomly chosen + // identifier that is used to distinguish data generated by the caller. + void setCachedMetadata(unsigned dataTypeID, const char*, size_t); + + // Returns cached metadata of the given type associated with this resource. + CachedMetadata* cachedMetadata(unsigned dataTypeID) const; + + bool canDelete() const { return !hasClients() && !m_loader && !m_preloadCount && !m_handleCount && !m_resourceToRevalidate && !m_proxyResource; } + bool hasOneHandle() const { return m_handleCount == 1; } + + bool isExpired() const; + + // List of acceptable MIME types separated by ",". + // A MIME type may contain a wildcard, e.g. "text/*". + String accept() const { return m_accept; } + void setAccept(const String& accept) { m_accept = accept; } + + bool wasCanceled() const { return m_status == Canceled; } + bool errorOccurred() const { return (m_status == LoadError || m_status == DecodeError); } + + bool sendResourceLoadCallbacks() const { return m_options.sendLoadCallbacks == SendCallbacks; } + + virtual void destroyDecodedData() { } + + void setOwningCachedResourceLoader(CachedResourceLoader* cachedResourceLoader) { m_owningCachedResourceLoader = cachedResourceLoader; } + + bool isPreloaded() const { return m_preloadCount; } + void increasePreloadCount() { ++m_preloadCount; } + void decreasePreloadCount() { ASSERT(m_preloadCount); --m_preloadCount; } + + void registerHandle(CachedResourceHandleBase* h); + void unregisterHandle(CachedResourceHandleBase* h); + + bool canUseCacheValidator() const; + bool mustRevalidateDueToCacheHeaders(CachePolicy) const; + bool isCacheValidator() const { return m_resourceToRevalidate; } + CachedResource* resourceToRevalidate() const { return m_resourceToRevalidate; } + + bool isPurgeable() const; + bool wasPurged() const; + + // This is used by the archive machinery to get at a purged resource without + // triggering a load. We should make it protected again if we can find a + // better way to handle the archive case. + bool makePurgeable(bool purgeable); + + // HTTP revalidation support methods for CachedResourceLoader. + void setResourceToRevalidate(CachedResource*); + void switchClientsToRevalidatedResource(); + void clearResourceToRevalidate(); + void updateResponseAfterRevalidation(const ResourceResponse& validatingResponse); + + virtual void didSendData(unsigned long long /* bytesSent */, unsigned long long /* totalBytesToBeSent */) { } +#if PLATFORM(CHROMIUM) + virtual void didDownloadData(int) { } +#endif + + void setLoadFinishTime(double finishTime) { m_loadFinishTime = finishTime; } + double loadFinishTime() const { return m_loadFinishTime; } + +protected: + void checkNotify(); + + void setEncodedSize(unsigned); + void setDecodedSize(unsigned); + void didAccessDecodedData(double timeStamp); + + bool isSafeToMakePurgeable() const; + + HashCountedSet m_clients; + + ResourceRequest m_resourceRequest; + String m_accept; + RefPtr m_loader; + ResourceLoaderOptions m_options; + ResourceLoadPriority m_loadPriority; + + ResourceResponse m_response; + double m_responseTimestamp; + + RefPtr m_data; + OwnPtr m_purgeableData; + +private: + void addClientToSet(CachedResourceClient*); + + virtual PurgePriority purgePriority() const { return PurgeDefault; } + + double currentAge() const; + double freshnessLifetime() const; + + RefPtr m_cachedMetadata; + + double m_lastDecodedAccessTime; // Used as a "thrash guard" in the cache + double m_loadFinishTime; + + unsigned m_encodedSize; + unsigned m_decodedSize; + unsigned m_accessCount; + unsigned m_handleCount; + unsigned m_preloadCount; + + unsigned m_preloadResult : 2; // PreloadResult + + bool m_inLiveDecodedResourcesList : 1; + bool m_requestedFromNetworkingLayer : 1; + + bool m_inCache : 1; + bool m_loading : 1; + + bool m_switchingClientsToRevalidatedResource : 1; + + unsigned m_type : 4; // Type + unsigned m_status : 3; // Status + +#ifndef NDEBUG + bool m_deleted; + unsigned m_lruIndex; +#endif + + CachedResource* m_nextInAllResourcesList; + CachedResource* m_prevInAllResourcesList; + + CachedResource* m_nextInLiveResourcesList; + CachedResource* m_prevInLiveResourcesList; + + CachedResourceLoader* m_owningCachedResourceLoader; // only non-0 for resources that are not in the cache + + // If this field is non-null we are using the resource as a proxy for checking whether an existing resource is still up to date + // using HTTP If-Modified-Since/If-None-Match headers. If the response is 304 all clients of this resource are moved + // to to be clients of m_resourceToRevalidate and the resource is deleted. If not, the field is zeroed and this + // resources becomes normal resource load. + CachedResource* m_resourceToRevalidate; + + // If this field is non-null, the resource has a proxy for checking whether it is still up to date (see m_resourceToRevalidate). + CachedResource* m_proxyResource; + + // These handles will need to be updated to point to the m_resourceToRevalidate in case we get 304 response. + HashSet m_handlesToRevalidate; +}; + +} + +#endif diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CachedResourceClient.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CachedResourceClient.h new file mode 100644 index 000000000..4aa2dd2a7 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CachedResourceClient.h @@ -0,0 +1,57 @@ +/* + Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) + Copyright (C) 2001 Dirk Mueller + Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + This class provides all functionality needed for loading images, style sheets and html + pages from the web. It has a memory cache for these objects. +*/ + +#ifndef CachedResourceClient_h +#define CachedResourceClient_h + +#include +#include + +namespace WebCore { +class CachedResource; + +class CachedResourceClient { + WTF_MAKE_FAST_ALLOCATED; +public: + enum CachedResourceClientType { + BaseResourceType, + ImageType, + FontType, + StyleSheetType, + RawResourceType + }; + + virtual ~CachedResourceClient() { } + virtual void notifyFinished(CachedResource*) { } + virtual void didReceiveData(CachedResource*) { }; + + static CachedResourceClientType expectedType() { return BaseResourceType; } + virtual CachedResourceClientType resourceClientType() { return expectedType(); } + +protected: + CachedResourceClient() { } +}; +} + +#endif diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CachedResourceHandle.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CachedResourceHandle.h new file mode 100644 index 000000000..aea410aa6 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CachedResourceHandle.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 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 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 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 CachedResourceHandle_h +#define CachedResourceHandle_h + +#include "CachedResource.h" + +namespace WebCore { + + class CachedResourceHandleBase { + public: + ~CachedResourceHandleBase() { if (m_resource) m_resource->unregisterHandle(this); } + CachedResource* get() const { return m_resource; } + + bool operator!() const { return !m_resource; } + + // This conversion operator allows implicit conversion to bool but not to other integer types. + typedef CachedResource* CachedResourceHandleBase::*UnspecifiedBoolType; + operator UnspecifiedBoolType() const { return m_resource ? &CachedResourceHandleBase::m_resource : 0; } + + protected: + CachedResourceHandleBase() : m_resource(0) {} + CachedResourceHandleBase(CachedResource* res) { m_resource = res; if (m_resource) m_resource->registerHandle(this); } + CachedResourceHandleBase(const CachedResourceHandleBase& o) : m_resource(o.m_resource) { if (m_resource) m_resource->registerHandle(this); } + + void setResource(CachedResource*); + + private: + CachedResourceHandleBase& operator=(const CachedResourceHandleBase&) { return *this; } + + friend class CachedResource; + + CachedResource* m_resource; + }; + + template class CachedResourceHandle : public CachedResourceHandleBase { + public: + CachedResourceHandle() { } + CachedResourceHandle(R* res) : CachedResourceHandleBase(res) { } + CachedResourceHandle(const CachedResourceHandle& o) : CachedResourceHandleBase(o) { } + + R* get() const { return reinterpret_cast(CachedResourceHandleBase::get()); } + R* operator->() const { return get(); } + + CachedResourceHandle& operator=(R* res) { setResource(res); return *this; } + CachedResourceHandle& operator=(const CachedResourceHandle& o) { setResource(o.get()); return *this; } + bool operator==(const CachedResourceHandleBase& o) const { return get() == o.get(); } + bool operator!=(const CachedResourceHandleBase& o) const { return get() != o.get(); } + }; + + template bool operator==(const CachedResourceHandle& h, const RR* res) + { + return h.get() == res; + } + template bool operator==(const RR* res, const CachedResourceHandle& h) + { + return h.get() == res; + } + template bool operator!=(const CachedResourceHandle& h, const RR* res) + { + return h.get() != res; + } + template bool operator!=(const RR* res, const CachedResourceHandle& h) + { + return h.get() != res; + } +} + +#endif diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CachedResourceLoader.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CachedResourceLoader.h new file mode 100644 index 000000000..86dca0e1e --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CachedResourceLoader.h @@ -0,0 +1,181 @@ +/* + Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) + Copyright (C) 2001 Dirk Mueller + Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. + Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/ + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + This class provides all functionality needed for loading images, style sheets and html + pages from the web. It has a memory cache for these objects. +*/ + +#ifndef CachedResourceLoader_h +#define CachedResourceLoader_h + +#include "CachedResource.h" +#include "CachedResourceHandle.h" +#include "CachePolicy.h" +#include "ResourceLoadPriority.h" +#include "Timer.h" +#include +#include +#include +#include +#include + +namespace WebCore { + +class CachedCSSStyleSheet; +class CachedFont; +class CachedImage; +class CachedRawResource; +class CachedScript; +class CachedShader; +class CachedTextTrack; +class CachedXSLStyleSheet; +class Document; +class Frame; +class ImageLoader; +class KURL; + +// The CachedResourceLoader manages the loading of scripts/images/stylesheets for a single document. +class CachedResourceLoader { + WTF_MAKE_NONCOPYABLE(CachedResourceLoader); WTF_MAKE_FAST_ALLOCATED; +friend class ImageLoader; +friend class ResourceCacheValidationSuppressor; + +public: + CachedResourceLoader(Document*); + ~CachedResourceLoader(); + + CachedImage* requestImage(ResourceRequest&); + CachedCSSStyleSheet* requestCSSStyleSheet(ResourceRequest&, const String& charset, ResourceLoadPriority = ResourceLoadPriorityUnresolved); + CachedCSSStyleSheet* requestUserCSSStyleSheet(ResourceRequest&, const String& charset); + CachedScript* requestScript(ResourceRequest&, const String& charset); + CachedFont* requestFont(ResourceRequest&); + CachedRawResource* requestRawResource(ResourceRequest&, const ResourceLoaderOptions&); + +#if ENABLE(XSLT) + CachedXSLStyleSheet* requestXSLStyleSheet(ResourceRequest&); +#endif +#if ENABLE(LINK_PREFETCH) + CachedResource* requestLinkResource(CachedResource::Type, ResourceRequest&, ResourceLoadPriority = ResourceLoadPriorityUnresolved); +#endif +#if ENABLE(VIDEO_TRACK) + CachedTextTrack* requestTextTrack(ResourceRequest&); +#endif +#if ENABLE(CSS_SHADERS) + CachedShader* requestShader(ResourceRequest&); +#endif + + // Logs an access denied message to the console for the specified URL. + void printAccessDeniedMessage(const KURL& url) const; + + CachedResource* cachedResource(const String& url) const; + CachedResource* cachedResource(const KURL& url) const; + + typedef HashMap > DocumentResourceMap; + const DocumentResourceMap& allCachedResources() const { return m_documentResources; } + + bool autoLoadImages() const { return m_autoLoadImages; } + void setAutoLoadImages(bool); + + CachePolicy cachePolicy() const; + + Frame* frame() const; // Can be NULL + Document* document() const { return m_document; } + + void removeCachedResource(CachedResource*) const; + + void loadFinishing() { m_loadFinishing = true; } + void loadDone(); + + void incrementRequestCount(const CachedResource*); + void decrementRequestCount(const CachedResource*); + int requestCount(); + + bool isPreloaded(const String& urlString) const; + void clearPreloads(); + void clearPendingPreloads(); + void preload(CachedResource::Type, ResourceRequest&, const String& charset, bool referencedFromBody); + void checkForPendingPreloads(); + void printPreloadStats(); + bool canRequest(CachedResource::Type, const KURL&, bool forPreload = false); + +private: + CachedResource* requestResource(CachedResource::Type, ResourceRequest&, const String& charset, const ResourceLoaderOptions&, ResourceLoadPriority = ResourceLoadPriorityUnresolved, bool isPreload = false); + CachedResource* revalidateResource(CachedResource*, ResourceLoadPriority, const ResourceLoaderOptions&); + CachedResource* loadResource(CachedResource::Type, ResourceRequest&, const String& charset, ResourceLoadPriority, const ResourceLoaderOptions&); + void requestPreload(CachedResource::Type, ResourceRequest&, const String& charset); + + enum RevalidationPolicy { Use, Revalidate, Reload, Load }; + RevalidationPolicy determineRevalidationPolicy(CachedResource::Type, ResourceRequest&, bool forPreload, CachedResource* existingResource) const; + + void notifyLoadedFromMemoryCache(CachedResource*); + bool checkInsecureContent(CachedResource::Type, const KURL&) const; + + void garbageCollectDocumentResourcesTimerFired(Timer*); + void performPostLoadActions(); + + HashSet m_validatedURLs; + mutable DocumentResourceMap m_documentResources; + Document* m_document; + + int m_requestCount; + + OwnPtr > m_preloads; + struct PendingPreload { + CachedResource::Type m_type; + ResourceRequest m_request; + String m_charset; + }; + Deque m_pendingPreloads; + + Timer m_garbageCollectDocumentResourcesTimer; + + //29 bits left + bool m_autoLoadImages : 1; + bool m_loadFinishing : 1; + bool m_allowStaleResources : 1; +}; + +class ResourceCacheValidationSuppressor { + WTF_MAKE_NONCOPYABLE(ResourceCacheValidationSuppressor); + WTF_MAKE_FAST_ALLOCATED; +public: + ResourceCacheValidationSuppressor(CachedResourceLoader* loader) + : m_loader(loader) + , m_previousState(false) + { + if (m_loader) { + m_previousState = m_loader->m_allowStaleResources; + m_loader->m_allowStaleResources = true; + } + } + ~ResourceCacheValidationSuppressor() + { + if (m_loader) + m_loader->m_allowStaleResources = m_previousState; + } +private: + CachedResourceLoader* m_loader; + bool m_previousState; +}; + +} // namespace WebCore + +#endif diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CachedStyleSheetClient.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CachedStyleSheetClient.h new file mode 100644 index 000000000..1a2925856 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CachedStyleSheetClient.h @@ -0,0 +1,45 @@ +/* + Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) + Copyright (C) 2001 Dirk Mueller + Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + Copyright (C) 2011 Google Inc. All rights reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + This class provides all functionality needed for loading images, style sheets and html + pages from the web. It has a memory cache for these objects. + */ + +#ifndef CachedStyleSheetClient_h +#define CachedStyleSheetClient_h + +#include "CachedResourceClient.h" +#include + +namespace WebCore { +class CachedCSSStyleSheet; + +class CachedStyleSheetClient : public CachedResourceClient { +public: + virtual ~CachedStyleSheetClient() { } + static CachedResourceClientType expectedType() { return StyleSheetType; } + virtual CachedResourceClientType resourceClientType() { return expectedType(); } + virtual void setCSSStyleSheet(const String& /* href */, const KURL& /* baseURL */, const String& /* charset */, const CachedCSSStyleSheet*) { } + virtual void setXSLStyleSheet(const String& /* href */, const KURL& /* baseURL */, const String& /* sheet */) { } +}; +} + +#endif // CachedStyleSheetClient_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CharacterData.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CharacterData.h new file mode 100644 index 000000000..f2aaf8153 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CharacterData.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 1999 Lars Knoll (knoll@kde.org) + * (C) 1999 Antti Koivisto (koivisto@kde.org) + * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef CharacterData_h +#define CharacterData_h + +#include "Node.h" +#include + +namespace WebCore { + +class CharacterData : public Node { +public: + String data() const { return m_data; } + void setData(const String&, ExceptionCode&); + unsigned length() const { return m_data.length(); } + String substringData(unsigned offset, unsigned count, ExceptionCode&); + void appendData(const String&, ExceptionCode&); + void insertData(unsigned offset, const String&, ExceptionCode&); + void deleteData(unsigned offset, unsigned count, ExceptionCode&); + void replaceData(unsigned offset, unsigned count, const String&, ExceptionCode&); + + bool containsOnlyWhitespace() const; + + StringImpl* dataImpl() { return m_data.impl(); } + + // Like appendData, but optimized for the parser (e.g., no mutation events). + // Returns how much could be added before length limit was met. + unsigned parserAppendData(const UChar*, unsigned dataLength, unsigned lengthLimit); + +protected: + CharacterData(Document* document, const String& text, ConstructionType type) + : Node(document, type) + , m_data(!text.isNull() ? text : emptyString()) + { + ASSERT(type == CreateComment || type == CreateText); + } + + virtual bool rendererIsNeeded(const NodeRenderingContext&); + + void setDataWithoutUpdate(const String& data) + { + ASSERT(!data.isNull()); + m_data = data; + } + void dispatchModifiedEvent(const String& oldValue); + +private: + virtual String nodeValue() const; + virtual void setNodeValue(const String&, ExceptionCode&); + virtual bool isCharacterDataNode() const { return true; } + virtual int maxCharacterOffset() const; + virtual bool offsetInCharacters() const; + void setDataAndUpdate(const String&, unsigned offsetOfReplacedData, unsigned oldLength, unsigned newLength); + void updateRenderer(unsigned offsetOfReplacedData, unsigned lengthOfReplacedData); + void checkCharDataOperation(unsigned offset, ExceptionCode&); + + String m_data; +}; + +} // namespace WebCore + +#endif // CharacterData_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CharsetData.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CharsetData.h new file mode 100644 index 000000000..458cecb50 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CharsetData.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2003, 2006 Apple Computer, 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. + */ + +namespace WebCore { + + #define kTextEncodingISOLatinThai kCFStringEncodingISOLatinThai + + struct CharsetEntry { + const char* name; + ::TextEncoding encoding; + }; + + extern const CharsetEntry CharsetTable[]; + +} diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CheckedRadioButtons.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CheckedRadioButtons.h new file mode 100644 index 000000000..f050faa48 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CheckedRadioButtons.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef CheckedRadioButtons_h +#define CheckedRadioButtons_h + +#include +#include +#include + +namespace WebCore { + +class HTMLInputElement; +class RadioButtonGroup; + +// FIXME: Rename the class. The class was a simple map from a name to a checked +// radio button. It manages RadioButtonGroup objects now. +class CheckedRadioButtons { +public: + CheckedRadioButtons(); + ~CheckedRadioButtons(); + void addButton(HTMLInputElement*); + void updateCheckedState(HTMLInputElement*); + void requiredAttributeChanged(HTMLInputElement*); + void removeButton(HTMLInputElement*); + HTMLInputElement* checkedButtonForGroup(const AtomicString& groupName) const; + bool isInRequiredGroup(HTMLInputElement*) const; + +private: + typedef HashMap > NameToGroupMap; + OwnPtr m_nameToGroupMap; +}; + +} // namespace WebCore + +#endif // CheckedRadioButtons_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/Chrome.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/Chrome.h new file mode 100644 index 000000000..d5b39bfe2 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/Chrome.h @@ -0,0 +1,193 @@ +/* + * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef Chrome_h +#define Chrome_h + +#include "Cursor.h" +#include "FocusDirection.h" +#include "HostWindow.h" +#include +#include + +#if PLATFORM(MAC) +#ifndef __OBJC__ +class NSView; +#endif +#endif + +namespace WebCore { + + class ChromeClient; +#if ENABLE(INPUT_COLOR) + class ColorChooser; + class ColorChooserClient; +#endif + class FileChooser; + class FileIconLoader; + class FloatRect; + class Frame; + class Geolocation; + class HitTestResult; + class IntRect; + class NavigationAction; + class Node; + class Page; + class PopupMenu; + class PopupMenuClient; + class SearchPopupMenu; + + struct FrameLoadRequest; + struct ViewportArguments; + struct WindowFeatures; + + class Chrome : public HostWindow { + public: + ~Chrome(); + + static PassOwnPtr create(Page*, ChromeClient*); + + ChromeClient* client() { return m_client; } + + // HostWindow methods. + + virtual void invalidateRootView(const IntRect&, bool) OVERRIDE; + virtual void invalidateContentsAndRootView(const IntRect&, bool) OVERRIDE; + virtual void invalidateContentsForSlowScroll(const IntRect&, bool); + virtual void scroll(const IntSize&, const IntRect&, const IntRect&); +#if USE(TILED_BACKING_STORE) + virtual void delegatedScrollRequested(const IntPoint& scrollPoint); +#endif + virtual IntPoint screenToRootView(const IntPoint&) const OVERRIDE; + virtual IntRect rootViewToScreen(const IntRect&) const OVERRIDE; + virtual PlatformPageClient platformPageClient() const; + virtual void scrollbarsModeDidChange() const; + virtual void setCursor(const Cursor&); + virtual void setCursorHiddenUntilMouseMoves(bool); + +#if ENABLE(REQUEST_ANIMATION_FRAME) + virtual void scheduleAnimation(); +#endif + + void scrollRectIntoView(const IntRect&) const; + + void contentsSizeChanged(Frame*, const IntSize&) const; + void layoutUpdated(Frame*) const; + + void setWindowRect(const FloatRect&) const; + FloatRect windowRect() const; + + FloatRect pageRect() const; + + void focus() const; + void unfocus() const; + + bool canTakeFocus(FocusDirection) const; + void takeFocus(FocusDirection) const; + + void focusedNodeChanged(Node*) const; + void focusedFrameChanged(Frame*) const; + + Page* createWindow(Frame*, const FrameLoadRequest&, const WindowFeatures&, const NavigationAction&) const; + void show() const; + + bool canRunModal() const; + bool canRunModalNow() const; + void runModal() const; + + void setToolbarsVisible(bool) const; + bool toolbarsVisible() const; + + void setStatusbarVisible(bool) const; + bool statusbarVisible() const; + + void setScrollbarsVisible(bool) const; + bool scrollbarsVisible() const; + + void setMenubarVisible(bool) const; + bool menubarVisible() const; + + void setResizable(bool) const; + + bool canRunBeforeUnloadConfirmPanel(); + bool runBeforeUnloadConfirmPanel(const String& message, Frame* frame); + + void closeWindowSoon(); + + void runJavaScriptAlert(Frame*, const String&); + bool runJavaScriptConfirm(Frame*, const String&); + bool runJavaScriptPrompt(Frame*, const String& message, const String& defaultValue, String& result); + void setStatusbarText(Frame*, const String&); + bool shouldInterruptJavaScript(); + +#if ENABLE(REGISTER_PROTOCOL_HANDLER) + void registerProtocolHandler(const String& scheme, const String& baseURL, const String& url, const String& title); +#endif + + IntRect windowResizerRect() const; + + void mouseDidMoveOverElement(const HitTestResult&, unsigned modifierFlags); + + void setToolTip(const HitTestResult&); + + void print(Frame*); + + // FIXME: Remove once all ports are using client-based geolocation. https://bugs.webkit.org/show_bug.cgi?id=40373 + // For client-based geolocation, these two methods have moved to GeolocationClient. https://bugs.webkit.org/show_bug.cgi?id=50061 + void requestGeolocationPermissionForFrame(Frame*, Geolocation*); + void cancelGeolocationPermissionRequestForFrame(Frame*, Geolocation*); + +#if ENABLE(INPUT_COLOR) + PassOwnPtr createColorChooser(ColorChooserClient*, const Color& initialColor); +#endif + + void runOpenPanel(Frame*, PassRefPtr); + void loadIconForFiles(const Vector&, FileIconLoader*); +#if ENABLE(DIRECTORY_UPLOAD) + void enumerateChosenDirectory(FileChooser*); +#endif + + void dispatchViewportPropertiesDidChange(const ViewportArguments&) const; + + bool requiresFullscreenForVideoPlayback(); + +#if PLATFORM(MAC) + void focusNSView(NSView*); +#endif + + bool selectItemWritingDirectionIsNatural(); + bool selectItemAlignmentFollowsMenuWritingDirection(); + bool hasOpenedPopup() const; + PassRefPtr createPopupMenu(PopupMenuClient*) const; + PassRefPtr createSearchPopupMenu(PopupMenuClient*) const; + +#if ENABLE(CONTEXT_MENUS) + void showContextMenu(); +#endif + + private: + Chrome(Page*, ChromeClient*); + + Page* m_page; + ChromeClient* m_client; + }; +} + +#endif // Chrome_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/ChromeClient.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/ChromeClient.h new file mode 100644 index 000000000..982a7cd15 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/ChromeClient.h @@ -0,0 +1,337 @@ +/* + * Copyright (C) 2006, 2007, 2008, 2009 Apple, Inc. All rights reserved. + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef ChromeClient_h +#define ChromeClient_h + +#include "AXObjectCache.h" +#include "ConsoleTypes.h" +#include "Cursor.h" +#include "FocusDirection.h" +#include "FrameLoader.h" +#include "GraphicsContext.h" +#include "HostWindow.h" +#include "PopupMenu.h" +#include "PopupMenuClient.h" +#include "ScrollTypes.h" +#include "SearchPopupMenu.h" +#include "WebCoreKeyboardUIMode.h" +#include +#include +#include +#include + +#ifndef __OBJC__ +class NSMenu; +class NSResponder; +#endif + +namespace WebCore { + + class AccessibilityObject; + class Element; + class FileChooser; + class FileIconLoader; + class FloatRect; + class Frame; + class Geolocation; + class GraphicsLayer; + class HitTestResult; + class IntRect; + class NavigationAction; + class Node; + class Page; + class PopupMenuClient; + class SecurityOrigin; + class GraphicsContext3D; + class Widget; + + struct FrameLoadRequest; + struct ViewportArguments; + struct WindowFeatures; + +#if USE(ACCELERATED_COMPOSITING) + class GraphicsLayer; +#endif + +#if ENABLE(INPUT_COLOR) + class ColorChooser; + class ColorChooserClient; +#endif + + class ChromeClient { + public: + virtual void chromeDestroyed() = 0; + + virtual void setWindowRect(const FloatRect&) = 0; + virtual FloatRect windowRect() = 0; + + virtual FloatRect pageRect() = 0; + + virtual void focus() = 0; + virtual void unfocus() = 0; + + virtual bool canTakeFocus(FocusDirection) = 0; + virtual void takeFocus(FocusDirection) = 0; + + virtual void focusedNodeChanged(Node*) = 0; + virtual void focusedFrameChanged(Frame*) = 0; + + // The Frame pointer provides the ChromeClient with context about which + // Frame wants to create the new Page. Also, the newly created window + // should not be shown to the user until the ChromeClient of the newly + // created Page has its show method called. + // The FrameLoadRequest parameter is only for ChromeClient to check if the + // request could be fulfilled. The ChromeClient should not load the request. + virtual Page* createWindow(Frame*, const FrameLoadRequest&, const WindowFeatures&, const NavigationAction&) = 0; + virtual void show() = 0; + + virtual bool canRunModal() = 0; + virtual void runModal() = 0; + + virtual void setToolbarsVisible(bool) = 0; + virtual bool toolbarsVisible() = 0; + + virtual void setStatusbarVisible(bool) = 0; + virtual bool statusbarVisible() = 0; + + virtual void setScrollbarsVisible(bool) = 0; + virtual bool scrollbarsVisible() = 0; + + virtual void setMenubarVisible(bool) = 0; + virtual bool menubarVisible() = 0; + + virtual void setResizable(bool) = 0; + + virtual void addMessageToConsole(MessageSource, MessageType, MessageLevel, const String& message, unsigned int lineNumber, const String& sourceID) = 0; + + virtual bool canRunBeforeUnloadConfirmPanel() = 0; + virtual bool runBeforeUnloadConfirmPanel(const String& message, Frame* frame) = 0; + + virtual void closeWindowSoon() = 0; + + virtual void runJavaScriptAlert(Frame*, const String&) = 0; + virtual bool runJavaScriptConfirm(Frame*, const String&) = 0; + virtual bool runJavaScriptPrompt(Frame*, const String& message, const String& defaultValue, String& result) = 0; + virtual void setStatusbarText(const String&) = 0; + virtual bool shouldInterruptJavaScript() = 0; + virtual KeyboardUIMode keyboardUIMode() = 0; + + virtual void* webView() const = 0; + +#if ENABLE(REGISTER_PROTOCOL_HANDLER) + virtual void registerProtocolHandler(const String& scheme, const String& baseURL, const String& url, const String& title) = 0; +#endif + + virtual IntRect windowResizerRect() const = 0; + + // Methods used by HostWindow. + virtual void invalidateRootView(const IntRect&, bool) = 0; + virtual void invalidateContentsAndRootView(const IntRect&, bool) = 0; + virtual void invalidateContentsForSlowScroll(const IntRect&, bool) = 0; + virtual void scroll(const IntSize&, const IntRect&, const IntRect&) = 0; +#if USE(TILED_BACKING_STORE) + virtual void delegatedScrollRequested(const IntPoint&) = 0; +#endif + virtual IntPoint screenToRootView(const IntPoint&) const = 0; + virtual IntRect rootViewToScreen(const IntRect&) const = 0; + virtual PlatformPageClient platformPageClient() const = 0; + virtual void scrollbarsModeDidChange() const = 0; + virtual void setCursor(const Cursor&) = 0; + virtual void setCursorHiddenUntilMouseMoves(bool) = 0; +#if ENABLE(REQUEST_ANIMATION_FRAME) && !USE(REQUEST_ANIMATION_FRAME_TIMER) + virtual void scheduleAnimation() = 0; +#endif + // End methods used by HostWindow. + + virtual void dispatchViewportPropertiesDidChange(const ViewportArguments&) const { } + + virtual void contentsSizeChanged(Frame*, const IntSize&) const = 0; + virtual void layoutUpdated(Frame*) const { } + virtual void scrollRectIntoView(const IntRect&) const { }; // Currently only Mac has a non empty implementation. + + virtual bool shouldMissingPluginMessageBeButton() const { return false; } + virtual void missingPluginButtonClicked(Element*) const { } + virtual void mouseDidMoveOverElement(const HitTestResult&, unsigned modifierFlags) = 0; + + virtual void setToolTip(const String&, TextDirection) = 0; + + virtual void print(Frame*) = 0; + virtual bool shouldRubberBandInDirection(ScrollDirection) const = 0; + +#if ENABLE(SQL_DATABASE) + virtual void exceededDatabaseQuota(Frame*, const String& databaseName) = 0; +#endif + + // Callback invoked when the application cache fails to save a cache object + // because storing it would grow the database file past its defined maximum + // size or past the amount of free space on the device. + // The chrome client would need to take some action such as evicting some + // old caches. + virtual void reachedMaxAppCacheSize(int64_t spaceNeeded) = 0; + + // Callback invoked when the application cache origin quota is reached. This + // means that the resources attempting to be cached via the manifest are + // more than allowed on this origin. This callback allows the chrome client + // to take action, such as prompting the user to ask to increase the quota + // for this origin. The totalSpaceNeeded parameter is the total amount of + // storage, in bytes, needed to store the new cache along with all of the + // other existing caches for the origin that would not be replaced by + // the new cache. + virtual void reachedApplicationCacheOriginQuota(SecurityOrigin*, int64_t totalSpaceNeeded) = 0; + +#if ENABLE(DASHBOARD_SUPPORT) + virtual void dashboardRegionsChanged(); +#endif + + virtual void populateVisitedLinks(); + + virtual FloatRect customHighlightRect(Node*, const AtomicString& type, const FloatRect& lineRect); + virtual void paintCustomHighlight(Node*, const AtomicString& type, const FloatRect& boxRect, const FloatRect& lineRect, + bool behindText, bool entireLine); + + virtual bool shouldReplaceWithGeneratedFileForUpload(const String& path, String& generatedFilename); + virtual String generateReplacementFile(const String& path); + + virtual bool paintCustomOverhangArea(GraphicsContext*, const IntRect&, const IntRect&, const IntRect&); + + // FIXME: Remove once all ports are using client-based geolocation. https://bugs.webkit.org/show_bug.cgi?id=40373 + // For client-based geolocation, these two methods have moved to GeolocationClient. https://bugs.webkit.org/show_bug.cgi?id=50061 + // This can be either a synchronous or asynchronous call. The ChromeClient can display UI asking the user for permission + // to use Geolocation. + virtual void requestGeolocationPermissionForFrame(Frame*, Geolocation*) = 0; + virtual void cancelGeolocationPermissionRequestForFrame(Frame*, Geolocation*) = 0; + +#if ENABLE(INPUT_COLOR) + virtual PassOwnPtr createColorChooser(ColorChooserClient*, const Color&) = 0; +#endif + + virtual void runOpenPanel(Frame*, PassRefPtr) = 0; + // Asynchronous request to load an icon for specified filenames. + virtual void loadIconForFiles(const Vector&, FileIconLoader*) = 0; + +#if ENABLE(DIRECTORY_UPLOAD) + // Asychronous request to enumerate all files in a directory chosen by the user. + virtual void enumerateChosenDirectory(FileChooser*) = 0; +#endif + + // Notification that the given form element has changed. This function + // will be called frequently, so handling should be very fast. + virtual void formStateDidChange(const Node*) = 0; + + virtual void elementDidFocus(const Node*) { }; + virtual void elementDidBlur(const Node*) { }; + +#if USE(ACCELERATED_COMPOSITING) + // Pass 0 as the GraphicsLayer to detatch the root layer. + virtual void attachRootGraphicsLayer(Frame*, GraphicsLayer*) = 0; + // Sets a flag to specify that the next time content is drawn to the window, + // the changes appear on the screen in synchrony with updates to GraphicsLayers. + virtual void setNeedsOneShotDrawingSynchronization() = 0; + // Sets a flag to specify that the view needs to be updated, so we need + // to do an eager layout before the drawing. + virtual void scheduleCompositingLayerSync() = 0; + // Returns whether or not the client can render the composited layer, + // regardless of the settings. + virtual bool allowsAcceleratedCompositing() const { return true; } + + enum CompositingTrigger { + ThreeDTransformTrigger = 1 << 0, + VideoTrigger = 1 << 1, + PluginTrigger = 1 << 2, + CanvasTrigger = 1 << 3, + AnimationTrigger = 1 << 4, + FilterTrigger = 1 << 5, + AllTriggers = 0xFFFFFFFF + }; + typedef unsigned CompositingTriggerFlags; + + // Returns a bitfield indicating conditions that can trigger the compositor. + virtual CompositingTriggerFlags allowedCompositingTriggers() const { return static_cast(AllTriggers); } +#endif + + virtual bool supportsFullscreenForNode(const Node*) { return false; } + virtual void enterFullscreenForNode(Node*) { } + virtual void exitFullscreenForNode(Node*) { } + virtual bool requiresFullscreenForVideoPlayback() { return false; } + +#if ENABLE(FULLSCREEN_API) + virtual bool supportsFullScreenForElement(const Element*, bool) { return false; } + virtual void enterFullScreenForElement(Element*) { } + virtual void exitFullScreenForElement(Element*) { } + virtual void fullScreenRendererChanged(RenderBox*) { } + virtual void setRootFullScreenLayer(GraphicsLayer*) { } +#endif + +#if USE(TILED_BACKING_STORE) + virtual IntRect visibleRectForTiledBackingStore() const { return IntRect(); } +#endif + +#if PLATFORM(MAC) + virtual NSResponder *firstResponder() { return 0; } + virtual void makeFirstResponder(NSResponder *) { } + // Focuses on the containing view associated with this page. + virtual void makeFirstResponder() { } + virtual void willPopUpMenu(NSMenu *) { } +#endif + +#if PLATFORM(WIN) + virtual void setLastSetCursorToCurrentCursor() = 0; +#endif + +#if ENABLE(TOUCH_EVENTS) + virtual void needTouchEvents(bool) = 0; +#endif + + virtual bool selectItemWritingDirectionIsNatural() = 0; + virtual bool selectItemAlignmentFollowsMenuWritingDirection() = 0; + // Checks if there is an opened popup, called by RenderMenuList::showPopup(). + virtual bool hasOpenedPopup() const = 0; + virtual PassRefPtr createPopupMenu(PopupMenuClient*) const = 0; + virtual PassRefPtr createSearchPopupMenu(PopupMenuClient*) const = 0; + +#if ENABLE(CONTEXT_MENUS) + virtual void showContextMenu() = 0; +#endif + + virtual void postAccessibilityNotification(AccessibilityObject*, AXObjectCache::AXNotification) { } + + virtual void notifyScrollerThumbIsVisibleInRect(const IntRect&) { } + virtual void recommendedScrollbarStyleDidChange(int /*newStyle*/) { } + + enum DialogType { + AlertDialog = 0, + ConfirmDialog = 1, + PromptDialog = 2, + HTMLDialog = 3 + }; + virtual bool shouldRunModalDialogDuringPageDismissal(const DialogType&, const String& dialogMessage, FrameLoader::PageDismissalType) const { UNUSED_PARAM(dialogMessage); return true; } + + virtual void numWheelEventHandlersChanged(unsigned) = 0; + + virtual bool isSVGImageChromeClient() const { return false; } + + protected: + virtual ~ChromeClient() { } + }; + +} + +#endif // ChromeClient_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/Clipboard.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/Clipboard.h new file mode 100644 index 000000000..f94727a0e --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/Clipboard.h @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2001 Peter Kelly (pmk@post.com) + * Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de) + * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com) + * Copyright (C) 2003, 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef Clipboard_h +#define Clipboard_h + +#include "CachedResourceHandle.h" +#include "ClipboardAccessPolicy.h" +#include "DragActions.h" +#include "DragImage.h" +#include "IntPoint.h" +#include "Node.h" + +namespace WebCore { + + class DataTransferItemList; + class DragData; + class FileList; + class Frame; + + // State available during IE's events for drag and drop and copy/paste + class Clipboard : public RefCounted { + public: + // Whether this clipboard is serving a drag-drop or copy-paste request. + enum ClipboardType { + CopyAndPaste, + DragAndDrop, + }; + + static PassRefPtr create(ClipboardAccessPolicy, DragData*, Frame*); + + virtual ~Clipboard() { } + + bool isForCopyAndPaste() const { return m_clipboardType == CopyAndPaste; } + bool isForDragAndDrop() const { return m_clipboardType == DragAndDrop; } + + String dropEffect() const { return dropEffectIsUninitialized() ? "none" : m_dropEffect; } + void setDropEffect(const String&); + bool dropEffectIsUninitialized() const { return m_dropEffect == "uninitialized"; } + String effectAllowed() const { return m_effectAllowed; } + void setEffectAllowed(const String&); + + virtual void clearData(const String& type) = 0; + virtual void clearAllData() = 0; + virtual String getData(const String& type, bool& success) const = 0; + virtual bool setData(const String& type, const String& data) = 0; + + // extensions beyond IE's API + virtual HashSet types() const = 0; + virtual PassRefPtr files() const = 0; + + LayoutPoint dragLocation() const { return m_dragLoc; } + CachedImage* dragImage() const { return m_dragImage.get(); } + virtual void setDragImage(CachedImage*, const LayoutPoint&) = 0; + Node* dragImageElement() const { return m_dragImageElement.get(); } + virtual void setDragImageElement(Node*, const LayoutPoint&) = 0; + + virtual DragImageRef createDragImage(LayoutPoint& dragLocation) const = 0; +#if ENABLE(DRAG_SUPPORT) + virtual void declareAndWriteDragImage(Element*, const KURL&, const String& title, Frame*) = 0; +#endif + virtual void writeURL(const KURL&, const String&, Frame*) = 0; + virtual void writeRange(Range*, Frame*) = 0; + virtual void writePlainText(const String&) = 0; + + virtual bool hasData() = 0; + + void setAccessPolicy(ClipboardAccessPolicy); + ClipboardAccessPolicy policy() const { return m_policy; } + + DragOperation sourceOperation() const; + DragOperation destinationOperation() const; + void setSourceOperation(DragOperation); + void setDestinationOperation(DragOperation); + + bool hasDropZoneType(const String&); + + void setDragHasStarted() { m_dragStarted = true; } + +#if ENABLE(DATA_TRANSFER_ITEMS) + virtual PassRefPtr items() = 0; +#endif + + protected: + Clipboard(ClipboardAccessPolicy, ClipboardType); + + bool dragStarted() const { return m_dragStarted; } + + private: + bool hasFileOfType(const String&) const; + bool hasStringOfType(const String&) const; + + ClipboardAccessPolicy m_policy; + String m_dropEffect; + String m_effectAllowed; + bool m_dragStarted; + ClipboardType m_clipboardType; + + protected: + LayoutPoint m_dragLoc; + CachedResourceHandle m_dragImage; + RefPtr m_dragImageElement; + }; + + DragOperation convertDropZoneOperationToDragOperation(const String& dragOperation); + String convertDragOperationToDropZoneOperation(DragOperation); + +} // namespace WebCore + +#endif // Clipboard_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/ClipboardAccessPolicy.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/ClipboardAccessPolicy.h new file mode 100644 index 000000000..7a54009e5 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/ClipboardAccessPolicy.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2006 Apple Computer, 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 ClipboardAccessPolicy_h +#define ClipboardAccessPolicy_h + +namespace WebCore { + +enum ClipboardAccessPolicy { + ClipboardNumb, ClipboardImageWritable, ClipboardWritable, ClipboardTypesReadable, ClipboardReadable +}; + +} // namespace + +#endif diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/ClipboardMac.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/ClipboardMac.h new file mode 100644 index 000000000..24e9b8060 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/ClipboardMac.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2004, 2006, 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. + */ + +#ifndef ClipboardMac_h +#define ClipboardMac_h + +#include "CachedImage.h" +#include "Clipboard.h" +#include + +OBJC_CLASS NSImage; +OBJC_CLASS NSPasteboard; + +namespace WebCore { + +class Frame; +class FileList; + +class ClipboardMac : public Clipboard, public CachedImageClient { + WTF_MAKE_FAST_ALLOCATED; +public: + static PassRefPtr create(ClipboardType clipboardType, NSPasteboard *pasteboard, ClipboardAccessPolicy policy, Frame* frame) + { + return adoptRef(new ClipboardMac(clipboardType, pasteboard, policy, frame)); + } + + virtual ~ClipboardMac(); + + void clearData(const String& type); + void clearAllData(); + String getData(const String& type, bool& success) const; + bool setData(const String& type, const String& data); + + virtual bool hasData(); + + // extensions beyond IE's API + virtual HashSet types() const; + virtual PassRefPtr files() const; + + void setDragImage(CachedImage*, const IntPoint&); + void setDragImageElement(Node *, const IntPoint&); + + virtual DragImageRef createDragImage(IntPoint& dragLoc) const; +#if ENABLE(DRAG_SUPPORT) + virtual void declareAndWriteDragImage(Element*, const KURL&, const String& title, Frame*); +#endif + virtual void writeRange(Range*, Frame* frame); + virtual void writeURL(const KURL&, const String&, Frame* frame); + virtual void writePlainText(const String&); + + // Methods for getting info in Cocoa's type system + NSImage *dragNSImage(NSPoint&) const; // loc converted from dragLoc, based on whole image size + NSPasteboard *pasteboard() { return m_pasteboard.get(); } + +private: + ClipboardMac(ClipboardType, NSPasteboard *, ClipboardAccessPolicy, Frame*); + + void setDragImage(CachedImage*, Node*, const IntPoint&); + + RetainPtr m_pasteboard; + int m_changeCount; + Frame* m_frame; // used on the source side to generate dragging images +}; + +} + +#endif diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CodeGenerator.pm b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CodeGenerator.pm new file mode 100644 index 000000000..2ad98e6c7 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CodeGenerator.pm @@ -0,0 +1,645 @@ +# +# WebKit IDL parser +# +# Copyright (C) 2005 Nikolas Zimmermann +# Copyright (C) 2006 Samuel Weinig +# Copyright (C) 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. +# Copyright (C) 2009 Cameron McCormack +# Copyright (C) Research In Motion Limited 2010. All rights reserved. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; see the file COPYING.LIB. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# + +package CodeGenerator; + +use strict; + +use File::Find; + +my $useDocument = ""; +my $useGenerator = ""; +my $useOutputDir = ""; +my $useOutputHeadersDir = ""; +my $useDirectories = ""; +my $useLayerOnTop = 0; +my $preprocessor; +my $writeDependencies = 0; +my $defines = ""; + +my $codeGenerator = 0; + +my $verbose = 0; + +my %numericTypeHash = ("int" => 1, "short" => 1, "long" => 1, "long long" => 1, + "unsigned int" => 1, "unsigned short" => 1, + "unsigned long" => 1, "unsigned long long" => 1, + "float" => 1, "double" => 1); + +my %primitiveTypeHash = ( "boolean" => 1, "void" => 1, "Date" => 1); + +my %stringTypeHash = ("DOMString" => 1, "AtomicString" => 1); + +my %nonPointerTypeHash = ("DOMTimeStamp" => 1, "CompareHow" => 1); + +my %svgAnimatedTypeHash = ("SVGAnimatedAngle" => 1, "SVGAnimatedBoolean" => 1, + "SVGAnimatedEnumeration" => 1, "SVGAnimatedInteger" => 1, + "SVGAnimatedLength" => 1, "SVGAnimatedLengthList" => 1, + "SVGAnimatedNumber" => 1, "SVGAnimatedNumberList" => 1, + "SVGAnimatedPreserveAspectRatio" => 1, + "SVGAnimatedRect" => 1, "SVGAnimatedString" => 1, + "SVGAnimatedTransformList" => 1); + +my %svgAttributesInHTMLHash = ("class" => 1, "id" => 1, "onabort" => 1, "onclick" => 1, + "onerror" => 1, "onload" => 1, "onmousedown" => 1, + "onmousemove" => 1, "onmouseout" => 1, "onmouseover" => 1, + "onmouseup" => 1, "onresize" => 1, "onscroll" => 1, + "onunload" => 1); + +my %svgTypeNeedingTearOff = ( + "SVGAngle" => "SVGPropertyTearOff", + "SVGLength" => "SVGPropertyTearOff", + "SVGLengthList" => "SVGListPropertyTearOff", + "SVGMatrix" => "SVGPropertyTearOff", + "SVGNumber" => "SVGPropertyTearOff", + "SVGNumberList" => "SVGListPropertyTearOff", + "SVGPathSegList" => "SVGPathSegListPropertyTearOff", + "SVGPoint" => "SVGPropertyTearOff", + "SVGPointList" => "SVGListPropertyTearOff", + "SVGPreserveAspectRatio" => "SVGPropertyTearOff", + "SVGRect" => "SVGPropertyTearOff", + "SVGStringList" => "SVGStaticListPropertyTearOff", + "SVGTransform" => "SVGPropertyTearOff", + "SVGTransformList" => "SVGTransformListPropertyTearOff" +); + +my %svgTypeWithWritablePropertiesNeedingTearOff = ( + "SVGPoint" => 1, + "SVGMatrix" => 1 +); + +# Cache of IDL file pathnames. +my $idlFiles; + +# Default constructor +sub new +{ + my $object = shift; + my $reference = { }; + + $useDirectories = shift; + $useGenerator = shift; + $useOutputDir = shift; + $useOutputHeadersDir = shift; + $useLayerOnTop = shift; + $preprocessor = shift; + $writeDependencies = shift; + $verbose = shift; + + bless($reference, $object); + return $reference; +} + +sub StripModule($) +{ + my $object = shift; + my $name = shift; + $name =~ s/[a-zA-Z0-9]*:://; + return $name; +} + +sub ProcessDocument +{ + my $object = shift; + $useDocument = shift; + $defines = shift; + + my $ifaceName = "CodeGenerator" . $useGenerator; + require $ifaceName . ".pm"; + + # Dynamically load external code generation perl module + $codeGenerator = $ifaceName->new($object, $useOutputDir, $useOutputHeadersDir, $useLayerOnTop, $preprocessor, $writeDependencies, $verbose); + unless (defined($codeGenerator)) { + my $classes = $useDocument->classes; + foreach my $class (@$classes) { + print "Skipping $useGenerator code generation for IDL interface \"" . $class->name . "\".\n" if $verbose; + } + return; + } + + # Start the actual code generation! + $codeGenerator->GenerateModule($useDocument, $defines); + + my $classes = $useDocument->classes; + foreach my $class (@$classes) { + print "Generating $useGenerator bindings code for IDL interface \"" . $class->name . "\"...\n" if $verbose; + $codeGenerator->GenerateInterface($class, $defines); + } +} + +sub FileNamePrefix +{ + my $object = shift; + + my $ifaceName = "CodeGenerator" . $useGenerator; + require $ifaceName . ".pm"; + + # Dynamically load external code generation perl module + $codeGenerator = $ifaceName->new($object, $useOutputDir, $useOutputHeadersDir, $useLayerOnTop, $preprocessor, $writeDependencies, $verbose); + return $codeGenerator->FileNamePrefix(); +} + +sub UpdateFile +{ + my $object = shift; + my $fileName = shift; + my $contents = shift; + + open FH, "> $fileName" or die "Couldn't open $fileName: $!\n"; + print FH $contents; + close FH; +} + +sub ForAllParents +{ + my $object = shift; + my $dataNode = shift; + my $beforeRecursion = shift; + my $afterRecursion = shift; + my $parentsOnly = shift; + + my $recurse; + $recurse = sub { + my $interface = shift; + + for (@{$interface->parents}) { + my $interfaceName = $object->StripModule($_); + my $parentInterface = $object->ParseInterface($interfaceName, $parentsOnly); + + if ($beforeRecursion) { + &$beforeRecursion($parentInterface) eq 'prune' and next; + } + &$recurse($parentInterface); + &$afterRecursion($parentInterface) if $afterRecursion; + } + }; + + &$recurse($dataNode); +} + +sub AddMethodsConstantsAndAttributesFromParentClasses +{ + # 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 $first = 1; + + $object->ForAllParents($dataNode, sub { + my $interface = shift; + + if ($first) { + # Ignore first parent class, already handled by the generation itself. + $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); + } + + # Prune the recursion here. + return 'prune'; + } + + # Collect the name of this additional parent. + push(@$parents, $interface->name) if $parents; + + print " | |> -> Inheriting " + . @{$interface->constants} . " constants, " + . @{$interface->functions} . " functions, " + . @{$interface->attributes} . " attributes...\n | |>\n" if $verbose; + + # Add this parent's members to $dataNode. + push(@{$dataNode->constants}, @{$interface->constants}); + push(@{$dataNode->functions}, @{$interface->functions}); + push(@{$dataNode->attributes}, @{$interface->attributes}); + }); +} + +sub GetMethodsAndAttributesFromParentClasses +{ + # For the passed interface, recursively parse all parent + # IDLs in order to find out all inherited properties/methods. + + my $object = shift; + my $dataNode = shift; + + my @parentList = (); + + $object->ForAllParents($dataNode, undef, sub { + my $interface = shift; + + my $hash = { + "name" => $interface->name, + "functions" => $interface->functions, + "attributes" => $interface->attributes + }; + + unshift(@parentList, $hash); + }); + + return @parentList; +} + +sub FindSuperMethod +{ + my ($object, $dataNode, $functionName) = @_; + my $indexer; + $object->ForAllParents($dataNode, undef, sub { + my $interface = shift; + foreach my $function (@{$interface->functions}) { + if ($function->signature->name eq $functionName) { + $indexer = $function->signature; + return 'prune'; + } + } + }); + return $indexer; +} + +sub IDLFileForInterface +{ + my $object = shift; + my $interfaceName = shift; + + unless ($idlFiles) { + my $sourceRoot = $ENV{SOURCE_ROOT}; + my @directories = map { $_ = "$sourceRoot/$_" if $sourceRoot && -d "$sourceRoot/$_"; $_ } @$useDirectories; + + $idlFiles = { }; + + my $wanted = sub { + $idlFiles->{$1} = $File::Find::name if /^([A-Z].*)\.idl$/; + $File::Find::prune = 1 if /^\../; + }; + find($wanted, @directories); + } + + return $idlFiles->{$interfaceName}; +} + +sub ParseInterface +{ + my $object = shift; + my $interfaceName = shift; + my $parentsOnly = shift; + + return undef if $interfaceName eq 'Object'; + + # 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 \"$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($filename, $defines, $preprocessor, $parentsOnly); + + foreach my $interface (@{$document->classes}) { + return $interface if $interface->name eq $interfaceName; + } + + die("Could NOT find interface definition for $interfaceName in $filename"); +} + +# Helpers for all CodeGenerator***.pm modules + +sub AvoidInclusionOfType +{ + my $object = shift; + my $type = shift; + + # Special case: SVGPoint.h / SVGNumber.h do not exist. + return 1 if $type eq "SVGPoint" or $type eq "SVGNumber"; + return 0; +} + +sub IsNumericType +{ + my $object = shift; + my $type = shift; + + return 1 if $numericTypeHash{$type}; + return 0; +} + +sub IsPrimitiveType +{ + my $object = shift; + my $type = shift; + + return 1 if $primitiveTypeHash{$type}; + return 1 if $numericTypeHash{$type}; + return 0; +} + +sub IsStringType +{ + my $object = shift; + my $type = shift; + + return 1 if $stringTypeHash{$type}; + return 0; +} + +sub IsNonPointerType +{ + my $object = shift; + my $type = shift; + + return 1 if $nonPointerTypeHash{$type} or $primitiveTypeHash{$type} or $numericTypeHash{$type}; + return 0; +} + +sub IsSVGTypeNeedingTearOff +{ + my $object = shift; + my $type = shift; + + return 1 if exists $svgTypeNeedingTearOff{$type}; + return 0; +} + +sub IsSVGTypeWithWritablePropertiesNeedingTearOff +{ + my $object = shift; + my $type = shift; + + return 1 if $svgTypeWithWritablePropertiesNeedingTearOff{$type}; + return 0; +} + +sub GetSVGTypeNeedingTearOff +{ + my $object = shift; + my $type = shift; + + return $svgTypeNeedingTearOff{$type} if exists $svgTypeNeedingTearOff{$type}; + return undef; +} + +sub GetSVGWrappedTypeNeedingTearOff +{ + my $object = shift; + my $type = shift; + + my $svgTypeNeedingTearOff = $object->GetSVGTypeNeedingTearOff($type); + return $svgTypeNeedingTearOff if not $svgTypeNeedingTearOff; + + if ($svgTypeNeedingTearOff =~ /SVGPropertyTearOff/) { + $svgTypeNeedingTearOff =~ s/SVGPropertyTearOff//; + return $svgTypeNeedingTearOff; +} + +sub IsSVGAnimatedType +{ + my $object = shift; + my $type = shift; + + return 1 if $svgAnimatedTypeHash{$type}; + return 0; +} + +# Uppercase the first letter while respecting WebKit style guidelines. +# E.g., xmlEncoding becomes XMLEncoding, but xmlllang becomes Xmllang. +sub WK_ucfirst +{ + my ($object, $param) = @_; + 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 ($object, $param) = @_; + my $ret = lcfirst($param); + $ret =~ s/hTML/html/ if $ret =~ /^hTML/; + $ret =~ s/uRL/url/ if $ret =~ /^uRL/; + $ret =~ s/jS/js/ if $ret =~ /^jS/; + $ret =~ s/xML/xml/ if $ret =~ /^xML/; + $ret =~ s/xSLT/xslt/ if $ret =~ /^xSLT/; + + # For HTML5 FileSystem API Flags attributes. + # (create is widely used to instantiate an object and must be avoided.) + $ret =~ s/^create/isCreate/ if $ret =~ /^create$/; + $ret =~ s/^exclusive/isExclusive/ if $ret =~ /^exclusive$/; + + return $ret; +} + +# Return the C++ namespace that a given attribute name string is defined in. +sub NamespaceForAttributeName +{ + my ($object, $interfaceName, $attributeName) = @_; + return "SVGNames" if $interfaceName =~ /^SVG/ && !$svgAttributesInHTMLHash{$attributeName}; + return "HTMLNames"; +} + +# Identifies overloaded functions and for each function adds an array with +# links to its respective overloads (including itself). +sub LinkOverloadedFunctions +{ + my ($object, $dataNode) = @_; + + my %nameToFunctionsMap = (); + foreach my $function (@{$dataNode->functions}) { + my $name = $function->signature->name; + $nameToFunctionsMap{$name} = [] if !exists $nameToFunctionsMap{$name}; + push(@{$nameToFunctionsMap{$name}}, $function); + $function->{overloads} = $nameToFunctionsMap{$name}; + $function->{overloadIndex} = @{$nameToFunctionsMap{$name}}; + } +} + +sub AttributeNameForGetterAndSetter +{ + my ($generator, $attribute) = @_; + + my $attributeName = $attribute->signature->name; + my $attributeType = $generator->StripModule($attribute->signature->type); + + # Avoid clash with C++ keyword. + $attributeName = "_operator" if $attributeName eq "operator"; + + # SVGAElement defines a non-virtual "String& target() const" method which clashes with "virtual String target() const" in Element. + # To solve this issue the SVGAElement method was renamed to "svgTarget", take care of that when calling this method. + $attributeName = "svgTarget" if $attributeName eq "target" and $attributeType eq "SVGAnimatedString"; + + # SVG animated types need to use a special attribute name. + # The rest of the special casing for SVG animated types is handled in the language-specific code generators. + $attributeName .= "Animated" if $generator->IsSVGAnimatedType($attributeType); + + return $attributeName; +} + +sub ContentAttributeName +{ + my ($generator, $implIncludes, $interfaceName, $attribute) = @_; + + my $contentAttributeName = $attribute->signature->extendedAttributes->{"Reflect"}; + return undef if !$contentAttributeName; + + $contentAttributeName = lc $generator->AttributeNameForGetterAndSetter($attribute) if $contentAttributeName eq "1"; + + my $namespace = $generator->NamespaceForAttributeName($interfaceName, $contentAttributeName); + + $implIncludes->{"${namespace}.h"} = 1; + return "WebCore::${namespace}::${contentAttributeName}Attr"; +} + +sub GetterExpression +{ + my ($generator, $implIncludes, $interfaceName, $attribute) = @_; + + my $contentAttributeName = $generator->ContentAttributeName($implIncludes, $interfaceName, $attribute); + + if (!$contentAttributeName) { + return ($generator->WK_lcfirst($generator->AttributeNameForGetterAndSetter($attribute))); + } + + my $functionName; + if ($attribute->signature->extendedAttributes->{"URL"}) { + if ($attribute->signature->extendedAttributes->{"NonEmpty"}) { + $functionName = "getNonEmptyURLAttribute"; + } else { + $functionName = "getURLAttribute"; + } + } elsif ($attribute->signature->type eq "boolean") { + $functionName = "hasAttribute"; + } elsif ($attribute->signature->type eq "long") { + $functionName = "getIntegralAttribute"; + } elsif ($attribute->signature->type eq "unsigned long") { + $functionName = "getUnsignedIntegralAttribute"; + } else { + $functionName = "getAttribute"; + } + + return ($functionName, $contentAttributeName); +} + +sub SetterExpression +{ + my ($generator, $implIncludes, $interfaceName, $attribute) = @_; + + my $contentAttributeName = $generator->ContentAttributeName($implIncludes, $interfaceName, $attribute); + + if (!$contentAttributeName) { + return ("set" . $generator->WK_ucfirst($generator->AttributeNameForGetterAndSetter($attribute))); + } + + my $functionName; + if ($attribute->signature->type eq "boolean") { + $functionName = "setBooleanAttribute"; + } elsif ($attribute->signature->type eq "long") { + $functionName = "setIntegralAttribute"; + } elsif ($attribute->signature->type eq "unsigned long") { + $functionName = "setUnsignedIntegralAttribute"; + } else { + $functionName = "setAttribute"; + } + + return ($functionName, $contentAttributeName); +} + +sub ShouldCheckEnums +{ + my $dataNode = shift; + return not $dataNode->extendedAttributes->{"DontCheckEnums"}; +} + +sub GenerateConditionalStringFromAttributeValue +{ + my $generator = shift; + my $conditional = shift; + + my $operator = ($conditional =~ /&/ ? '&' : ($conditional =~ /\|/ ? '|' : '')); + if ($operator) { + # Avoid duplicated conditions. + my %conditions; + map { $conditions{$_} = 1 } split('\\' . $operator, $conditional); + return "ENABLE(" . join(") $operator$operator ENABLE(", sort keys %conditions) . ")"; + } else { + return "ENABLE(" . $conditional . ")"; + } +} + +sub GenerateCompileTimeCheckForEnumsIfNeeded +{ + my ($generator, $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 $reflect = $constant->extendedAttributes->{"Reflect"}; + my $name = $reflect ? $reflect : $constant->name; + my $value = $constant->value; + my $conditional = $constant->extendedAttributes->{"Conditional"}; + + if ($conditional) { + my $conditionalString = $generator->GenerateConditionalStringFromAttributeValue($conditional); + push(@checks, "#if ${conditionalString}\n"); + } + + push(@checks, "COMPILE_ASSERT($value == ${interfaceName}::$name, ${interfaceName}Enum${name}IsWrongUseDontCheckEnums);\n"); + + if ($conditional) { + push(@checks, "#endif\n"); + } + } + push(@checks, "\n"); + } + return @checks; +} + +1; diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CollapsedBorderValue.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CollapsedBorderValue.h new file mode 100644 index 000000000..c84555e0c --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CollapsedBorderValue.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2000 Lars Knoll (knoll@kde.org) + * (C) 2000 Antti Koivisto (koivisto@kde.org) + * (C) 2000 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef CollapsedBorderValue_h +#define CollapsedBorderValue_h + +#include "BorderValue.h" + +namespace WebCore { + +class CollapsedBorderValue { +public: + CollapsedBorderValue() + : m_precedence(BOFF) + { + } + + CollapsedBorderValue(const BorderValue& b, Color c, EBorderPrecedence p) + : m_border(b) + , m_borderColor(c) + , m_precedence(p) + { + } + + int width() const { return m_border.nonZero() ? m_border.width() : 0; } + EBorderStyle style() const { return m_border.style(); } + bool exists() const { return m_precedence != BOFF; } + const Color& color() const { return m_borderColor; } + bool isTransparent() const { return m_border.isTransparent(); } + EBorderPrecedence precedence() const { return m_precedence; } + + bool isSameIgnoringColor(const CollapsedBorderValue& o) const + { + return m_border.width() == o.m_border.width() && m_border.style() == o.m_border.style() && m_precedence == o.m_precedence; + } + +private: + BorderValue m_border; + Color m_borderColor; + EBorderPrecedence m_precedence; +}; + +} // namespace WebCore + +#endif // CollapsedBorderValue_h diff --git a/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CollectionType.h b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CollectionType.h new file mode 100644 index 000000000..fa348f9c3 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/PrivateHeaders/CollectionType.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 1999 Lars Knoll (knoll@kde.org) + * (C) 1999 Antti Koivisto (koivisto@kde.org) + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef CollectionType_h +#define CollectionType_h + +namespace WebCore { + +enum CollectionType { + // unnamed collection types cached in the document + + DocImages, // all elements in the document + DocApplets, // all and elements + DocEmbeds, // all elements + DocObjects, // all elements + DocForms, // all
elements + DocLinks, // all _and_ elements with a value for href + DocAnchors, // all elements with a value for name + DocScripts, // all + + +
+
+
+
+ +
+
+
+
+
+
+
+
+ + diff --git a/frameworks/WebCore.framework/Versions/A/Resources/inspector/inspector.js b/frameworks/WebCore.framework/Versions/A/Resources/inspector/inspector.js new file mode 100644 index 000000000..0094b6d09 --- /dev/null +++ b/frameworks/WebCore.framework/Versions/A/Resources/inspector/inspector.js @@ -0,0 +1,70987 @@ +/* utilities.js */ + +/* + * 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. + * 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. + * + * Contains diff method based on Javascript Diff Algorithm By John Resig + * http://ejohn.org/files/jsdiff.js (released under the MIT license). + */ + +/** + * @param {string=} direction + */ +Node.prototype.rangeOfWord = function(offset, stopCharacters, stayWithinNode, direction) +{ + var startNode; + var startOffset = 0; + var endNode; + var endOffset = 0; + + if (!stayWithinNode) + stayWithinNode = this; + + if (!direction || direction === "backward" || direction === "both") { + var node = this; + while (node) { + if (node === stayWithinNode) { + if (!startNode) + startNode = stayWithinNode; + break; + } + + if (node.nodeType === Node.TEXT_NODE) { + var start = (node === this ? (offset - 1) : (node.nodeValue.length - 1)); + for (var i = start; i >= 0; --i) { + if (stopCharacters.indexOf(node.nodeValue[i]) !== -1) { + startNode = node; + startOffset = i + 1; + break; + } + } + } + + if (startNode) + break; + + node = node.traversePreviousNode(stayWithinNode); + } + + if (!startNode) { + startNode = stayWithinNode; + startOffset = 0; + } + } else { + startNode = this; + startOffset = offset; + } + + if (!direction || direction === "forward" || direction === "both") { + node = this; + while (node) { + if (node === stayWithinNode) { + if (!endNode) + endNode = stayWithinNode; + break; + } + + if (node.nodeType === Node.TEXT_NODE) { + var start = (node === this ? offset : 0); + for (var i = start; i < node.nodeValue.length; ++i) { + if (stopCharacters.indexOf(node.nodeValue[i]) !== -1) { + endNode = node; + endOffset = i; + break; + } + } + } + + if (endNode) + break; + + node = node.traverseNextNode(stayWithinNode); + } + + if (!endNode) { + endNode = stayWithinNode; + endOffset = stayWithinNode.nodeType === Node.TEXT_NODE ? stayWithinNode.nodeValue.length : stayWithinNode.childNodes.length; + } + } else { + endNode = this; + endOffset = offset; + } + + var result = this.ownerDocument.createRange(); + result.setStart(startNode, startOffset); + result.setEnd(endNode, endOffset); + + return result; +} + +Node.prototype.traverseNextTextNode = function(stayWithin) +{ + var node = this.traverseNextNode(stayWithin); + if (!node) + return; + + while (node && node.nodeType !== Node.TEXT_NODE) + node = node.traverseNextNode(stayWithin); + + return node; +} + +Node.prototype.rangeBoundaryForOffset = function(offset) +{ + var node = this.traverseNextTextNode(this); + while (node && offset > node.nodeValue.length) { + offset -= node.nodeValue.length; + node = node.traverseNextTextNode(this); + } + if (!node) + return { container: this, offset: 0 }; + return { container: node, offset: offset }; +} + +Element.prototype.removeStyleClass = function(className) +{ + this.classList.remove(className); +} + +Element.prototype.removeMatchingStyleClasses = function(classNameRegex) +{ + var regex = new RegExp("(^|\\s+)" + classNameRegex + "($|\\s+)"); + if (regex.test(this.className)) + this.className = this.className.replace(regex, " "); +} + +Element.prototype.addStyleClass = function(className) +{ + this.classList.add(className); +} + +Element.prototype.hasStyleClass = function(className) +{ + return this.classList.contains(className); +} + +Element.prototype.positionAt = function(x, y) +{ + this.style.left = x + "px"; + this.style.top = y + "px"; +} + +Element.prototype.pruneEmptyTextNodes = function() +{ + var sibling = this.firstChild; + while (sibling) { + var nextSibling = sibling.nextSibling; + if (sibling.nodeType === this.TEXT_NODE && sibling.nodeValue === "") + this.removeChild(sibling); + sibling = nextSibling; + } +} + +Element.prototype.isScrolledToBottom = function() +{ + // This code works only for 0-width border + return this.scrollTop + this.clientHeight === this.scrollHeight; +} + +Node.prototype.enclosingNodeOrSelfWithNodeNameInArray = function(nameArray) +{ + for (var node = this; node && node !== this.ownerDocument; node = node.parentNode) + for (var i = 0; i < nameArray.length; ++i) + if (node.nodeName.toLowerCase() === nameArray[i].toLowerCase()) + return node; + return null; +} + +Node.prototype.enclosingNodeOrSelfWithNodeName = function(nodeName) +{ + return this.enclosingNodeOrSelfWithNodeNameInArray([nodeName]); +} + +Node.prototype.enclosingNodeOrSelfWithClass = function(className) +{ + for (var node = this; node && node !== this.ownerDocument; node = node.parentNode) + if (node.nodeType === Node.ELEMENT_NODE && node.hasStyleClass(className)) + return node; + return null; +} + +Node.prototype.enclosingNodeWithClass = function(className) +{ + if (!this.parentNode) + return null; + return this.parentNode.enclosingNodeOrSelfWithClass(className); +} + +Element.prototype.query = function(query) +{ + return this.ownerDocument.evaluate(query, this, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; +} + +Element.prototype.removeChildren = function() +{ + if (this.firstChild) + this.textContent = ""; +} + +Element.prototype.isInsertionCaretInside = function() +{ + var selection = window.getSelection(); + if (!selection.rangeCount || !selection.isCollapsed) + return false; + var selectionRange = selection.getRangeAt(0); + return selectionRange.startContainer.isSelfOrDescendant(this); +} + +/** + * @param {string=} className + */ +Element.prototype.createChild = function(elementName, className) +{ + var element = this.ownerDocument.createElement(elementName); + if (className) + element.className = className; + this.appendChild(element); + return element; +} + +DocumentFragment.prototype.createChild = Element.prototype.createChild; + +/** + * @return {number} + */ +Element.prototype.totalOffsetLeft = function() +{ + var total = 0; + for (var element = this; element; element = element.offsetParent) { + total += element.offsetLeft + if (this !== element) + total += element.clientLeft - element.scrollLeft; + } + + return total; +} + +/** + * @return {number} + */ +Element.prototype.totalOffsetTop = function() +{ + var total = 0; + for (var element = this; element; element = element.offsetParent) { + total += element.offsetTop + if (this !== element) + total += element.clientTop - element.scrollTop; + } + + return total; +} + +/** + * @constructor + * @param {number=} x + * @param {number=} y + * @param {number=} width + * @param {number=} height + */ +function AnchorBox(x, y, width, height) +{ + this.x = x || 0; + this.y = y || 0; + this.width = width || 0; + this.height = height || 0; +} + +/** + * @param {Window} targetWindow + * @return {AnchorBox} + */ +Element.prototype.offsetRelativeToWindow = function(targetWindow) +{ + var elementOffset = new AnchorBox(); + var curElement = this; + var curWindow = this.ownerDocument.defaultView; + while (curWindow && curElement) { + elementOffset.x += curElement.totalOffsetLeft(); + elementOffset.y += curElement.totalOffsetTop(); + if (curWindow === targetWindow) + break; + + curElement = curWindow.frameElement; + curWindow = curWindow.parent; + } + + return elementOffset; +} + +/** + * @param {Window} targetWindow + * @return {AnchorBox} + */ +Element.prototype.boxInWindow = function(targetWindow) +{ + targetWindow = targetWindow || this.ownerDocument.defaultView; + + var anchorBox = this.offsetRelativeToWindow(window); + anchorBox.width = this.offsetWidth; + anchorBox.height = this.offsetHeight; + + return anchorBox; +} + +/** + * @param {string} text + */ +Element.prototype.setTextAndTitle = function(text) +{ + this.textContent = text; + this.title = text; +} + +KeyboardEvent.prototype.__defineGetter__("data", function() +{ + // Emulate "data" attribute from DOM 3 TextInput event. + // See http://www.w3.org/TR/DOM-Level-3-Events/#events-Events-TextEvent-data + switch (this.type) { + case "keypress": + if (!this.ctrlKey && !this.metaKey) + return String.fromCharCode(this.charCode); + else + return ""; + case "keydown": + case "keyup": + if (!this.ctrlKey && !this.metaKey && !this.altKey) + return String.fromCharCode(this.which); + else + return ""; + } +}); + +Text.prototype.select = function(start, end) +{ + start = start || 0; + end = end || this.textContent.length; + + if (start < 0) + start = end + start; + + var selection = this.ownerDocument.defaultView.getSelection(); + selection.removeAllRanges(); + var range = this.ownerDocument.createRange(); + range.setStart(this, start); + range.setEnd(this, end); + selection.addRange(range); + return this; +} + +Element.prototype.selectionLeftOffset = function() +{ + // Calculate selection offset relative to the current element. + + var selection = window.getSelection(); + if (!selection.containsNode(this, true)) + return null; + + var leftOffset = selection.anchorOffset; + var node = selection.anchorNode; + + while (node !== this) { + while (node.previousSibling) { + node = node.previousSibling; + leftOffset += node.textContent.length; + } + node = node.parentNode; + } + + return leftOffset; +} + +String.prototype.hasSubstring = function(string, caseInsensitive) +{ + if (!caseInsensitive) + return this.indexOf(string) !== -1; + return this.match(new RegExp(string.escapeForRegExp(), "i")); +} + +String.prototype.findAll = function(string) +{ + var matches = []; + var i = this.indexOf(string); + while (i !== -1) { + matches.push(i); + i = this.indexOf(string, i + string.length); + } + return matches; +} + +String.prototype.lineEndings = function() +{ + if (!this._lineEndings) { + this._lineEndings = this.findAll("\n"); + this._lineEndings.push(this.length); + } + return this._lineEndings; +} + +String.prototype.asParsedURL = function() +{ + // RegExp groups: + // 1 - scheme + // 2 - hostname + // 3 - ?port + // 4 - ?path + // 5 - ?fragment + var match = this.match(/^([^:]+):\/\/([^\/:]*)(?::([\d]+))?(?:(\/[^#]*)(?:#(.*))?)?$/i); + if (!match) + return null; + var result = {}; + result.scheme = match[1].toLowerCase(); + result.host = match[2]; + result.port = match[3]; + result.path = match[4] || "/"; + result.fragment = match[5]; + + result.lastPathComponent = ""; + if (result.path) { + // First cut the query params. + var path = result.path; + var indexOfQuery = path.indexOf("?"); + if (indexOfQuery !== -1) + path = path.substring(0, indexOfQuery); + + // Then take last path component. + var lastSlashIndex = path.lastIndexOf("/"); + if (lastSlashIndex !== -1) { + result.firstPathComponents = path.substring(0, lastSlashIndex + 1); + result.lastPathComponent = path.substring(lastSlashIndex + 1); + } + } + return result; +} + +String.prototype.escapeCharacters = function(chars) +{ + var foundChar = false; + for (var i = 0; i < chars.length; ++i) { + if (this.indexOf(chars.charAt(i)) !== -1) { + foundChar = true; + break; + } + } + + if (!foundChar) + return this; + + var result = ""; + for (var i = 0; i < this.length; ++i) { + if (chars.indexOf(this.charAt(i)) !== -1) + result += "\\"; + result += this.charAt(i); + } + + return result; +} + +String.prototype.escapeForRegExp = function() +{ + return this.escapeCharacters("^[]{}()\\.$*+?|"); +} + +String.prototype.escapeHTML = function() +{ + return this.replace(/&/g, "&").replace(//g, ">").replace(/"/g, """); //" doublequotes just for editor +} + +String.prototype.collapseWhitespace = function() +{ + return this.replace(/[\s\xA0]+/g, " "); +} + +String.prototype.trimMiddle = function(maxLength) +{ + if (this.length <= maxLength) + return this; + var leftHalf = maxLength >> 1; + var rightHalf = maxLength - leftHalf - 1; + return this.substr(0, leftHalf) + "\u2026" + this.substr(this.length - rightHalf, rightHalf); +} + +String.prototype.trimEnd = function(maxLength) +{ + if (this.length <= maxLength) + return this; + return this.substr(0, maxLength - 1) + "\u2026"; +} + +String.prototype.trimURL = function(baseURLDomain) +{ + var result = this.replace(/^(https|http|file):\/\//i, ""); + if (baseURLDomain) + result = result.replace(new RegExp("^" + baseURLDomain.escapeForRegExp(), "i"), ""); + return result; +} + +String.prototype.removeURLFragment = function() +{ + var fragmentIndex = this.indexOf("#"); + if (fragmentIndex == -1) + fragmentIndex = this.length; + return this.substring(0, fragmentIndex); +} + +Node.prototype.isAncestor = function(node) +{ + if (!node) + return false; + + var currentNode = node.parentNode; + while (currentNode) { + if (this === currentNode) + return true; + currentNode = currentNode.parentNode; + } + return false; +} + +Node.prototype.isDescendant = function(descendant) +{ + return !!descendant && descendant.isAncestor(this); +} + +Node.prototype.isSelfOrAncestor = function(node) +{ + return !!node && (node === this || this.isAncestor(node)); +} + +Node.prototype.isSelfOrDescendant = function(node) +{ + return !!node && (node === this || this.isDescendant(node)); +} + +Node.prototype.traverseNextNode = function(stayWithin) +{ + var node = this.firstChild; + if (node) + return node; + + if (stayWithin && this === stayWithin) + return null; + + node = this.nextSibling; + if (node) + return node; + + node = this; + while (node && !node.nextSibling && (!stayWithin || !node.parentNode || node.parentNode !== stayWithin)) + node = node.parentNode; + if (!node) + return null; + + return node.nextSibling; +} + +Node.prototype.traversePreviousNode = function(stayWithin) +{ + if (stayWithin && this === stayWithin) + return null; + var node = this.previousSibling; + while (node && node.lastChild) + node = node.lastChild; + if (node) + return node; + return this.parentNode; +} + +Number.constrain = function(num, min, max) +{ + if (num < min) + num = min; + else if (num > max) + num = max; + return num; +} + +Date.prototype.toISO8601Compact = function() +{ + function leadZero(x) + { + return x > 9 ? '' + x : '0' + x + } + return this.getFullYear() + + leadZero(this.getMonth() + 1) + + leadZero(this.getDate()) + 'T' + + leadZero(this.getHours()) + + leadZero(this.getMinutes()) + + leadZero(this.getSeconds()); +} + +HTMLTextAreaElement.prototype.moveCursorToEnd = function() +{ + var length = this.value.length; + this.setSelectionRange(length, length); +} + +Object.defineProperty(Array.prototype, "remove", +{ + /** + * @this {Array.<*>} + */ + value: function(value, onlyFirst) + { + if (onlyFirst) { + var index = this.indexOf(value); + if (index !== -1) + this.splice(index, 1); + return; + } + + var length = this.length; + for (var i = 0; i < length; ++i) { + if (this[i] === value) + this.splice(i, 1); + } + } +}); + +Object.defineProperty(Array.prototype, "keySet", +{ + /** + * @this {Array.<*>} + */ + value: function() + { + var keys = {}; + for (var i = 0; i < this.length; ++i) + keys[this[i]] = true; + return keys; + } +}); + +Object.defineProperty(Array.prototype, "upperBound", +{ + /** + * @this {Array.} + */ + value: function(value) + { + var first = 0; + var count = this.length; + while (count > 0) { + var step = count >> 1; + var middle = first + step; + if (value >= this[middle]) { + first = middle + 1; + count -= step + 1; + } else + count = step; + } + return first; + } +}); + +Array.diff = function(left, right) +{ + var o = left; + var n = right; + + var ns = {}; + var os = {}; + + for (var i = 0; i < n.length; i++) { + if (ns[n[i]] == null) + ns[n[i]] = { rows: [], o: null }; + ns[n[i]].rows.push(i); + } + + for (var i = 0; i < o.length; i++) { + if (os[o[i]] == null) + os[o[i]] = { rows: [], n: null }; + os[o[i]].rows.push(i); + } + + for (var i in ns) { + if (ns[i].rows.length == 1 && typeof(os[i]) != "undefined" && os[i].rows.length == 1) { + n[ns[i].rows[0]] = { text: n[ns[i].rows[0]], row: os[i].rows[0] }; + o[os[i].rows[0]] = { text: o[os[i].rows[0]], row: ns[i].rows[0] }; + } + } + + for (var i = 0; i < n.length - 1; i++) { + if (n[i].text != null && n[i + 1].text == null && n[i].row + 1 < o.length && o[n[i].row + 1].text == null && n[i + 1] == o[n[i].row + 1]) { + n[i + 1] = { text: n[i + 1], row: n[i].row + 1 }; + o[n[i].row + 1] = { text: o[n[i].row + 1], row: i + 1 }; + } + } + + for (var i = n.length - 1; i > 0; i--) { + if (n[i].text != null && n[i - 1].text == null && n[i].row > 0 && o[n[i].row - 1].text == null && + n[i - 1] == o[n[i].row - 1]) { + n[i - 1] = { text: n[i - 1], row: n[i].row - 1 }; + o[n[i].row - 1] = { text: o[n[i].row - 1], row: i - 1 }; + } + } + + return { left: o, right: n }; +} + +Array.convert = function(list) +{ + // Cast array-like object to an array. + return Array.prototype.slice.call(list); +} + +/** + * @param {string} format + * @param {...*} var_arg + */ +String.sprintf = function(format, var_arg) +{ + return String.vsprintf(format, Array.prototype.slice.call(arguments, 1)); +} + +String.tokenizeFormatString = function(format) +{ + var tokens = []; + var substitutionIndex = 0; + + function addStringToken(str) + { + tokens.push({ type: "string", value: str }); + } + + function addSpecifierToken(specifier, precision, substitutionIndex) + { + tokens.push({ type: "specifier", specifier: specifier, precision: precision, substitutionIndex: substitutionIndex }); + } + + var index = 0; + for (var precentIndex = format.indexOf("%", index); precentIndex !== -1; precentIndex = format.indexOf("%", index)) { + addStringToken(format.substring(index, precentIndex)); + index = precentIndex + 1; + + if (format[index] === "%") { + addStringToken("%"); + ++index; + continue; + } + + if (!isNaN(format[index])) { + // The first character is a number, it might be a substitution index. + var number = parseInt(format.substring(index), 10); + while (!isNaN(format[index])) + ++index; + // If the number is greater than zero and ends with a "$", + // then this is a substitution index. + if (number > 0 && format[index] === "$") { + substitutionIndex = (number - 1); + ++index; + } + } + + var precision = -1; + if (format[index] === ".") { + // This is a precision specifier. If no digit follows the ".", + // then the precision should be zero. + ++index; + precision = parseInt(format.substring(index), 10); + if (isNaN(precision)) + precision = 0; + while (!isNaN(format[index])) + ++index; + } + + addSpecifierToken(format[index], precision, substitutionIndex); + + ++substitutionIndex; + ++index; + } + + addStringToken(format.substring(index)); + + return tokens; +} + +String.standardFormatters = { + d: function(substitution) + { + return !isNaN(substitution) ? substitution : 0; + }, + + f: function(substitution, token) + { + if (substitution && token.precision > -1) + substitution = substitution.toFixed(token.precision); + return !isNaN(substitution) ? substitution : (token.precision > -1 ? Number(0).toFixed(token.precision) : 0); + }, + + s: function(substitution) + { + return substitution; + } +} + +String.vsprintf = function(format, substitutions) +{ + return String.format(format, substitutions, String.standardFormatters, "", function(a, b) { return a + b; }).formattedResult; +} + +String.format = function(format, substitutions, formatters, initialValue, append) +{ + if (!format || !substitutions || !substitutions.length) + return { formattedResult: append(initialValue, format), unusedSubstitutions: substitutions }; + + function prettyFunctionName() + { + return "String.format(\"" + format + "\", \"" + substitutions.join("\", \"") + "\")"; + } + + function warn(msg) + { + console.warn(prettyFunctionName() + ": " + msg); + } + + function error(msg) + { + console.error(prettyFunctionName() + ": " + msg); + } + + var result = initialValue; + var tokens = String.tokenizeFormatString(format); + var usedSubstitutionIndexes = {}; + + for (var i = 0; i < tokens.length; ++i) { + var token = tokens[i]; + + if (token.type === "string") { + result = append(result, token.value); + continue; + } + + if (token.type !== "specifier") { + error("Unknown token type \"" + token.type + "\" found."); + continue; + } + + if (token.substitutionIndex >= substitutions.length) { + // If there are not enough substitutions for the current substitutionIndex + // just output the format specifier literally and move on. + error("not enough substitution arguments. Had " + substitutions.length + " but needed " + (token.substitutionIndex + 1) + ", so substitution was skipped."); + result = append(result, "%" + (token.precision > -1 ? token.precision : "") + token.specifier); + continue; + } + + usedSubstitutionIndexes[token.substitutionIndex] = true; + + if (!(token.specifier in formatters)) { + // Encountered an unsupported format character, treat as a string. + warn("unsupported format character \u201C" + token.specifier + "\u201D. Treating as a string."); + result = append(result, substitutions[token.substitutionIndex]); + continue; + } + + result = append(result, formatters[token.specifier](substitutions[token.substitutionIndex], token)); + } + + var unusedSubstitutions = []; + for (var i = 0; i < substitutions.length; ++i) { + if (i in usedSubstitutionIndexes) + continue; + unusedSubstitutions.push(substitutions[i]); + } + + return { formattedResult: result, unusedSubstitutions: unusedSubstitutions }; +} + +function isEnterKey(event) { + // Check if in IME. + return event.keyCode !== 229 && event.keyIdentifier === "Enter"; +} + +/** + * @param {Element} element + * @param {number} offset + * @param {number} length + * @param {Array.=} domChanges + */ +function highlightSearchResult(element, offset, length, domChanges) +{ + var result = highlightSearchResults(element, [{offset: offset, length: length }], domChanges); + return result.length ? result[0] : null; +} + +/** + * @param {Element} element + * @param {Array.} resultRanges + * @param {Array.=} changes + */ +function highlightSearchResults(element, resultRanges, changes) +{ + return highlightRangesWithStyleClass(element, resultRanges, "webkit-search-result", changes); + +} + +/** + * @param {Element} element + * @param {Array.} resultRanges + * @param {string} styleClass + * @param {Array.=} changes + */ +function highlightRangesWithStyleClass(element, resultRanges, styleClass, changes) +{ + changes = changes || []; + var highlightNodes = []; + var lineText = element.textContent; + var ownerDocument = element.ownerDocument; + var textNodeSnapshot = ownerDocument.evaluate(".//text()", element, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); + + var snapshotLength = textNodeSnapshot.snapshotLength; + if (snapshotLength === 0) + return highlightNodes; + + var nodeRanges = []; + var rangeEndOffset = 0; + for (var i = 0; i < snapshotLength; ++i) { + var range = {}; + range.offset = rangeEndOffset; + range.length = textNodeSnapshot.snapshotItem(i).textContent.length; + rangeEndOffset = range.offset + range.length; + nodeRanges.push(range); + } + + var startIndex = 0; + for (var i = 0; i < resultRanges.length; ++i) { + var startOffset = resultRanges[i].offset; + var endOffset = startOffset + resultRanges[i].length; + + while (startIndex < snapshotLength && nodeRanges[startIndex].offset + nodeRanges[startIndex].length <= startOffset) + startIndex++; + var endIndex = startIndex; + while (endIndex < snapshotLength && nodeRanges[endIndex].offset + nodeRanges[endIndex].length < endOffset) + endIndex++; + if (endIndex === snapshotLength) + break; + + var highlightNode = ownerDocument.createElement("span"); + highlightNode.className = styleClass; + highlightNode.textContent = lineText.substring(startOffset, endOffset); + + var lastTextNode = textNodeSnapshot.snapshotItem(endIndex); + var lastText = lastTextNode.textContent; + lastTextNode.textContent = lastText.substring(endOffset - nodeRanges[endIndex].offset); + changes.push({ node: lastTextNode, type: "changed", oldText: lastText, newText: lastTextNode.textContent }); + + if (startIndex === endIndex) { + lastTextNode.parentElement.insertBefore(highlightNode, lastTextNode); + changes.push({ node: highlightNode, type: "added", nextSibling: lastTextNode, parent: lastTextNode.parentElement }); + highlightNodes.push(highlightNode); + + var prefixNode = ownerDocument.createTextNode(lastText.substring(0, startOffset - nodeRanges[startIndex].offset)); + lastTextNode.parentElement.insertBefore(prefixNode, highlightNode); + changes.push({ node: prefixNode, type: "added", nextSibling: highlightNode, parent: lastTextNode.parentElement }); + } else { + var firstTextNode = textNodeSnapshot.snapshotItem(startIndex); + var firstText = firstTextNode.textContent; + var anchorElement = firstTextNode.nextSibling; + + firstTextNode.parentElement.insertBefore(highlightNode, anchorElement); + changes.push({ node: highlightNode, type: "added", nextSibling: anchorElement, parent: firstTextNode.parentElement }); + highlightNodes.push(highlightNode); + + firstTextNode.textContent = firstText.substring(0, startOffset - nodeRanges[startIndex].offset); + changes.push({ node: firstTextNode, type: "changed", oldText: firstText, newText: firstTextNode.textContent }); + + for (var j = startIndex + 1; j < endIndex; j++) { + var textNode = textNodeSnapshot.snapshotItem(j); + var text = textNode.textContent; + textNode.textContent = ""; + changes.push({ node: textNode, type: "changed", oldText: text, newText: textNode.textContent }); + } + } + startIndex = endIndex; + nodeRanges[startIndex].offset = endOffset; + nodeRanges[startIndex].length = lastTextNode.textContent.length; + + } + return highlightNodes; +} + +function applyDomChanges(domChanges) +{ + for (var i = 0, size = domChanges.length; i < size; ++i) { + var entry = domChanges[i]; + switch (entry.type) { + case "added": + entry.parent.insertBefore(entry.node, entry.nextSibling); + break; + case "changed": + entry.node.textContent = entry.newText; + break; + } + } +} + +function revertDomChanges(domChanges) +{ + for (var i = domChanges.length - 1; i >= 0; --i) { + var entry = domChanges[i]; + switch (entry.type) { + case "added": + if (entry.node.parentElement) + entry.node.parentElement.removeChild(entry.node); + break; + case "changed": + entry.node.textContent = entry.oldText; + break; + } + } +} + +/** + * @param {string} query + * @param {boolean} caseSensitive + * @param {boolean} isRegex + * @return {RegExp} + */ +function createSearchRegex(query, caseSensitive, isRegex) +{ + var regexFlags = caseSensitive ? "g" : "gi"; + var regexObject; + + if (isRegex) { + try { + regexObject = new RegExp(query, regexFlags); + } catch (e) { + // Silent catch. + } + } + + if (!regexObject) + regexObject = createPlainTextSearchRegex(query, regexFlags); + + return regexObject; +} + +/** + * @param {string} query + * @param {string=} flags + * @return {RegExp} + */ +function createPlainTextSearchRegex(query, flags) +{ + // This should be kept the same as the one in ContentSearchUtils.cpp. + var regexSpecialCharacters = "[](){}+-*.,?\\^$|"; + var regex = ""; + for (var i = 0; i < query.length; ++i) { + var c = query.charAt(i); + if (regexSpecialCharacters.indexOf(c) != -1) + regex += "\\"; + regex += c; + } + return new RegExp(regex, flags || ""); +} + +/** + * @param {RegExp} regex + * @param {string} content + * @return {number} + */ +function countRegexMatches(regex, content) +{ + var text = content; + var result = 0; + var match; + while (text && (match = regex.exec(text))) { + if (match[0].length > 0) + ++result; + text = text.substring(match.index + 1); + } + return result; +} + +/** + * @param {number} value + * @param {number} symbolsCount + * @return {string} + */ +function numberToStringWithSpacesPadding(value, symbolsCount) +{ + var numberString = value.toString(); + var paddingLength = Math.max(0, symbolsCount - numberString.length); + var paddingString = Array(paddingLength + 1).join("\u00a0"); + return paddingString + numberString; +} + +/** + * @constructor + */ +function TextDiff() +{ + this.added = []; + this.removed = []; + this.changed = []; +} + +/** + * @param {string} baseContent + * @param {string} newContent + * @return {TextDiff} + */ +TextDiff.compute = function(baseContent, newContent) +{ + var oldLines = baseContent.split(/\r?\n/); + var newLines = newContent.split(/\r?\n/); + + var diff = Array.diff(oldLines, newLines); + + var diffData = new TextDiff(); + + var offset = 0; + var right = diff.right; + for (var i = 0; i < right.length; ++i) { + if (typeof right[i] === "string") { + if (right.length > i + 1 && right[i + 1].row === i + 1 - offset) + diffData.changed.push(i); + else { + diffData.added.push(i); + offset++; + } + } else + offset = i - right[i].row; + } + return diffData; +} + +/** + * @constructor + */ +var Map = function() +{ + this._map = {}; +} + +Map._lastObjectIdentifier = 0; + +Map.prototype = { + /** + * @param {Object} key + */ + put: function(key, value) + { + var objectIdentifier = key.__identifier; + if (!objectIdentifier) { + objectIdentifier = ++Map._lastObjectIdentifier; + key.__identifier = objectIdentifier; + } + this._map[objectIdentifier] = value; + }, + + /** + * @param {Object} key + */ + remove: function(key) + { + delete this._map[key.__identifier]; + }, + + keys: function() + { + var result = []; + for (var key in this._map) + result.push(key); + return result; + }, + + /** + * @param {Object} key + */ + get: function(key) + { + return this._map[key.__identifier]; + }, +} +/* BinarySearch.js */ + +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * 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: + * + * * 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. + */ + +/** + * @param {*} object + * @param {Array.<*>} array + * @param {function(*, *)} comparator + */ +function binarySearch(object, array, comparator) +{ + var first = 0; + var last = array.length - 1; + + while (first <= last) { + var mid = (first + last) >> 1; + var c = comparator(object, array[mid]); + if (c > 0) + first = mid + 1; + else if (c < 0) + last = mid - 1; + else + return mid; + } + + // Return the nearest lesser index, "-1" means "0, "-2" means "1", etc. + return -(first + 1); +} + +Object.defineProperty(Array.prototype, "binaryIndexOf", { value: function(value, comparator) +{ + var result = binarySearch(value, this, comparator); + return result >= 0 ? result : -1; +}}); + +/** + * @param {*} anObject + * @param {Array.<*>} aList + * @param {function(*, *)} aFunction + */ +function insertionIndexForObjectInListSortedByFunction(anObject, aList, aFunction) +{ + var index = binarySearch(anObject, aList, aFunction); + if (index < 0) + // See binarySearch implementation. + return -index - 1; + else { + // Return the first occurance of an item in the list. + while (index > 0 && aFunction(anObject, aList[index - 1]) === 0) + index--; + return index; + } +} +/* treeoutline.js */ + + /* + * 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. + * 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. + */ + +/** + * @constructor + */ +function TreeOutline(listNode) +{ + /** + * @type {Array.} + */ + this.children = []; + this.selectedTreeElement = null; + this._childrenListNode = listNode; + this._childrenListNode.removeChildren(); + this.expandTreeElementsWhenArrowing = false; + this.root = true; + this.hasChildren = false; + this.expanded = true; + this.selected = false; + this.treeOutline = this; + this.comparator = null; + this.searchable = false; + this.searchInputElement = null; + + this._childrenListNode.tabIndex = 0; + this._childrenListNode.addEventListener("keydown", this._treeKeyDown.bind(this), true); + this._childrenListNode.addEventListener("keypress", this._treeKeyPress.bind(this), true); + + this._treeElementsMap = new Map(); + this._expandedStateMap = new Map(); +} + +TreeOutline.prototype.appendChild = function(child) +{ + var insertionIndex; + if (this.treeOutline.comparator) + insertionIndex = insertionIndexForObjectInListSortedByFunction(child, this.children, this.treeOutline.comparator); + else + insertionIndex = this.children.length; + this.insertChild(child, insertionIndex); +} + +TreeOutline.prototype.insertChild = function(child, index) +{ + if (!child) + throw("child can't be undefined or null"); + + var previousChild = (index > 0 ? this.children[index - 1] : null); + if (previousChild) { + previousChild.nextSibling = child; + child.previousSibling = previousChild; + } else { + child.previousSibling = null; + } + + var nextChild = this.children[index]; + if (nextChild) { + nextChild.previousSibling = child; + child.nextSibling = nextChild; + } else { + child.nextSibling = null; + } + + this.children.splice(index, 0, child); + this.hasChildren = true; + child.parent = this; + child.treeOutline = this.treeOutline; + child.treeOutline._rememberTreeElement(child); + + var current = child.children[0]; + while (current) { + current.treeOutline = this.treeOutline; + current.treeOutline._rememberTreeElement(current); + current = current.traverseNextTreeElement(false, child, true); + } + + if (child.hasChildren && typeof(child.treeOutline._expandedStateMap.get(child.representedObject)) !== "undefined") + child.expanded = child.treeOutline._expandedStateMap.get(child.representedObject); + + if (!this._childrenListNode) { + this._childrenListNode = this.treeOutline._childrenListNode.ownerDocument.createElement("ol"); + this._childrenListNode.parentTreeElement = this; + this._childrenListNode.classList.add("children"); + if (this.hidden) + this._childrenListNode.classList.add("hidden"); + } + + child._attach(); + + if (this.treeOutline.onadd) + this.treeOutline.onadd(child); +} + +TreeOutline.prototype.removeChildAtIndex = function(childIndex) +{ + if (childIndex < 0 || childIndex >= this.children.length) + throw("childIndex out of range"); + + var child = this.children[childIndex]; + this.children.splice(childIndex, 1); + + var parent = child.parent; + if (child.deselect()) { + if (child.previousSibling) + child.previousSibling.select(); + else if (child.nextSibling) + child.nextSibling.select(); + else + parent.select(); + } + + if (child.previousSibling) + child.previousSibling.nextSibling = child.nextSibling; + if (child.nextSibling) + child.nextSibling.previousSibling = child.previousSibling; + + if (child.treeOutline) { + child.treeOutline._forgetTreeElement(child); + child.treeOutline._forgetChildrenRecursive(child); + } + + child._detach(); + child.treeOutline = null; + child.parent = null; + child.nextSibling = null; + child.previousSibling = null; +} + +TreeOutline.prototype.removeChild = function(child) +{ + if (!child) + throw("child can't be undefined or null"); + + var childIndex = this.children.indexOf(child); + if (childIndex === -1) + throw("child not found in this node's children"); + + this.removeChildAtIndex.call(this, childIndex); +} + +TreeOutline.prototype.removeChildren = function() +{ + for (var i = 0; i < this.children.length; ++i) { + var child = this.children[i]; + child.deselect(); + + if (child.treeOutline) { + child.treeOutline._forgetTreeElement(child); + child.treeOutline._forgetChildrenRecursive(child); + } + + child._detach(); + child.treeOutline = null; + child.parent = null; + child.nextSibling = null; + child.previousSibling = null; + } + + this.children = []; +} + +TreeOutline.prototype.removeChildrenRecursive = function() +{ + var childrenToRemove = this.children; + + var child = this.children[0]; + while (child) { + if (child.children.length) + childrenToRemove = childrenToRemove.concat(child.children); + child = child.traverseNextTreeElement(false, this, true); + } + + for (var i = 0; i < childrenToRemove.length; ++i) { + child = childrenToRemove[i]; + child.deselect(); + if (child.treeOutline) + child.treeOutline._forgetTreeElement(child); + child._detach(); + child.children = []; + child.treeOutline = null; + child.parent = null; + child.nextSibling = null; + child.previousSibling = null; + } + + this.children = []; +} + +TreeOutline.prototype._rememberTreeElement = function(element) +{ + if (!this._treeElementsMap.get(element.representedObject)) + this._treeElementsMap.put(element.representedObject, []); + + // check if the element is already known + var elements = this._treeElementsMap.get(element.representedObject); + if (elements.indexOf(element) !== -1) + return; + + // add the element + elements.push(element); +} + +TreeOutline.prototype._forgetTreeElement = function(element) +{ + if (this._treeElementsMap.get(element.representedObject)) + this._treeElementsMap.get(element.representedObject).remove(element, true); +} + +TreeOutline.prototype._forgetChildrenRecursive = function(parentElement) +{ + var child = parentElement.children[0]; + while (child) { + this._forgetTreeElement(child); + child = child.traverseNextTreeElement(false, this, true); + } +} + +TreeOutline.prototype.getCachedTreeElement = function(representedObject) +{ + if (!representedObject) + return null; + + var elements = this._treeElementsMap.get(representedObject); + if (elements && elements.length) + return elements[0]; + return null; +} + +TreeOutline.prototype.findTreeElement = function(representedObject, isAncestor, getParent) +{ + if (!representedObject) + return null; + + var cachedElement = this.getCachedTreeElement(representedObject); + if (cachedElement) + return cachedElement; + + // The representedObject isn't known, so we start at the top of the tree and work down to find the first + // tree element that represents representedObject or one of its ancestors. + var item; + var found = false; + for (var i = 0; i < this.children.length; ++i) { + item = this.children[i]; + if (item.representedObject === representedObject || isAncestor(item.representedObject, representedObject)) { + found = true; + break; + } + } + + if (!found) + return null; + + // Make sure the item that we found is connected to the root of the tree. + // Build up a list of representedObject's ancestors that aren't already in our tree. + var ancestors = []; + var currentObject = representedObject; + while (currentObject) { + ancestors.unshift(currentObject); + if (currentObject === item.representedObject) + break; + currentObject = getParent(currentObject); + } + + // For each of those ancestors we populate them to fill in the tree. + for (var i = 0; i < ancestors.length; ++i) { + // Make sure we don't call findTreeElement with the same representedObject + // again, to prevent infinite recursion. + if (ancestors[i] === representedObject) + continue; + // FIXME: we could do something faster than findTreeElement since we will know the next + // ancestor exists in the tree. + item = this.findTreeElement(ancestors[i], isAncestor, getParent); + if (item) + item.onpopulate(); + } + + return this.getCachedTreeElement(representedObject); +} + +TreeOutline.prototype._treeElementDidChange = function(treeElement) +{ + if (treeElement.treeOutline !== this) + return; + + if (this.onchange) + this.onchange(treeElement); +} + +TreeOutline.prototype.treeElementFromPoint = function(x, y) +{ + var node = this._childrenListNode.ownerDocument.elementFromPoint(x, y); + if (!node) + return null; + + var listNode = node.enclosingNodeOrSelfWithNodeNameInArray(["ol", "li"]); + if (listNode) + return listNode.parentTreeElement || listNode.treeElement; + return null; +} + +TreeOutline.prototype._treeKeyPress = function(event) +{ + if (!this.searchable) + return; + + var searchText = String.fromCharCode(event.charCode); + // Ignore whitespace. + if (searchText.trim() !== searchText) + return; + + this._startSearch(searchText); + event.preventDefault(); + event.stopPropagation(); +} + +TreeOutline.prototype._treeKeyDown = function(event) +{ + if (event.target !== this._childrenListNode) + return; + + if (!this.selectedTreeElement || event.shiftKey || event.metaKey || event.ctrlKey) + return; + + var handled = false; + var nextSelectedElement; + if (event.keyIdentifier === "Up" && !event.altKey) { + nextSelectedElement = this.selectedTreeElement.traversePreviousTreeElement(true); + while (nextSelectedElement && !nextSelectedElement.selectable) + nextSelectedElement = nextSelectedElement.traversePreviousTreeElement(!this.expandTreeElementsWhenArrowing); + handled = nextSelectedElement ? true : false; + } else if (event.keyIdentifier === "Down" && !event.altKey) { + nextSelectedElement = this.selectedTreeElement.traverseNextTreeElement(true); + while (nextSelectedElement && !nextSelectedElement.selectable) + nextSelectedElement = nextSelectedElement.traverseNextTreeElement(!this.expandTreeElementsWhenArrowing); + handled = nextSelectedElement ? true : false; + } else if (event.keyIdentifier === "Left") { + if (this.selectedTreeElement.expanded) { + if (event.altKey) + this.selectedTreeElement.collapseRecursively(); + else + this.selectedTreeElement.collapse(); + handled = true; + } else if (this.selectedTreeElement.parent && !this.selectedTreeElement.parent.root) { + handled = true; + if (this.selectedTreeElement.parent.selectable) { + nextSelectedElement = this.selectedTreeElement.parent; + while (nextSelectedElement && !nextSelectedElement.selectable) + nextSelectedElement = nextSelectedElement.parent; + handled = nextSelectedElement ? true : false; + } else if (this.selectedTreeElement.parent) + this.selectedTreeElement.parent.collapse(); + } + } else if (event.keyIdentifier === "Right") { + if (!this.selectedTreeElement.revealed()) { + this.selectedTreeElement.reveal(); + handled = true; + } else if (this.selectedTreeElement.hasChildren) { + handled = true; + if (this.selectedTreeElement.expanded) { + nextSelectedElement = this.selectedTreeElement.children[0]; + while (nextSelectedElement && !nextSelectedElement.selectable) + nextSelectedElement = nextSelectedElement.nextSibling; + handled = nextSelectedElement ? true : false; + } else { + if (event.altKey) + this.selectedTreeElement.expandRecursively(); + else + this.selectedTreeElement.expand(); + } + } + } else if (event.keyCode === 8 /* Backspace */ || event.keyCode === 46 /* Delete */) { + if (this.selectedTreeElement.ondelete) + handled = this.selectedTreeElement.ondelete(); + } else if (isEnterKey(event)) { + if (this.selectedTreeElement.onenter) + handled = this.selectedTreeElement.onenter(); + } + + if (nextSelectedElement) { + nextSelectedElement.reveal(); + nextSelectedElement.select(false, true); + } + + if (handled) { + event.preventDefault(); + event.stopPropagation(); + } +} + +TreeOutline.prototype.expand = function() +{ + // this is the root, do nothing +} + +TreeOutline.prototype.collapse = function() +{ + // this is the root, do nothing +} + +TreeOutline.prototype.revealed = function() +{ + return true; +} + +TreeOutline.prototype.reveal = function() +{ + // this is the root, do nothing +} + +TreeOutline.prototype.select = function() +{ + // this is the root, do nothing +} + +/** + * @param {boolean=} omitFocus + */ +TreeOutline.prototype.revealAndSelect = function(omitFocus) +{ + // this is the root, do nothing +} + +/** + * @param {string} searchText + */ +TreeOutline.prototype._startSearch = function(searchText) +{ + if (!this.searchInputElement || !this.searchable) + return; + + this._searching = true; + + if (this.searchStarted) + this.searchStarted(); + + this.searchInputElement.value = searchText; + + function focusSearchInput() + { + this.searchInputElement.focus(); + } + window.setTimeout(focusSearchInput.bind(this), 0); + this._searchTextChanged(); + this._boundSearchTextChanged = this._searchTextChanged.bind(this); + this.searchInputElement.addEventListener("paste", this._boundSearchTextChanged); + this.searchInputElement.addEventListener("cut", this._boundSearchTextChanged); + this.searchInputElement.addEventListener("keypress", this._boundSearchTextChanged); + this._boundSearchInputKeyDown = this._searchInputKeyDown.bind(this); + this.searchInputElement.addEventListener("keydown", this._boundSearchInputKeyDown); + this._boundSearchInputBlur = this._searchInputBlur.bind(this); + this.searchInputElement.addEventListener("blur", this._boundSearchInputBlur); +} + +TreeOutline.prototype._searchTextChanged = function() +{ + function updateSearch() + { + var nextSelectedElement = this._nextSearchMatch(this.searchInputElement.value, this.selectedTreeElement, false); + if (!nextSelectedElement) + nextSelectedElement = this._nextSearchMatch(this.searchInputElement.value, this.children[0], false); + this._showSearchMatchElement(nextSelectedElement); + } + + window.setTimeout(updateSearch.bind(this), 0); +} + +TreeOutline.prototype._showSearchMatchElement = function(treeElement) +{ + this._currentSearchMatchElement = treeElement; + if (treeElement) { + this._childrenListNode.classList.add("search-match-found"); + this._childrenListNode.classList.remove("search-match-not-found"); + treeElement.revealAndSelect(true); + } else { + this._childrenListNode.classList.remove("search-match-found"); + this._childrenListNode.classList.add("search-match-not-found"); + } +} + +TreeOutline.prototype._searchInputKeyDown = function(event) +{ + if (event.shiftKey || event.metaKey || event.ctrlKey || event.altKey) + return; + + var handled = false; + var nextSelectedElement; + if (event.keyIdentifier === "Down") { + nextSelectedElement = this._nextSearchMatch(this.searchInputElement.value, this.selectedTreeElement, true); + handled = true; + } else if (event.keyIdentifier === "Up") { + nextSelectedElement = this._previousSearchMatch(this.searchInputElement.value, this.selectedTreeElement); + handled = true; + } else if (event.keyCode === 27 /* Esc */) { + this._searchFinished(); + handled = true; + } else if (isEnterKey(event)) { + var lastSearchMatchElement = this._currentSearchMatchElement; + this._searchFinished(); + if (lastSearchMatchElement && lastSearchMatchElement.onenter) + lastSearchMatchElement.onenter(); + handled = true; + } + + if (nextSelectedElement) + this._showSearchMatchElement(nextSelectedElement); + + if (handled) { + event.preventDefault(); + event.stopPropagation(); + } else + window.setTimeout(this._boundSearchTextChanged, 0); +} + +/** + * @param {string} searchText + * @param {TreeElement} startTreeElement + * @param {boolean} skipStartTreeElement + */ +TreeOutline.prototype._nextSearchMatch = function(searchText, startTreeElement, skipStartTreeElement) +{ + var currentTreeElement = startTreeElement; + var skipCurrentTreeElement = skipStartTreeElement; + while (currentTreeElement && (skipCurrentTreeElement || !currentTreeElement.matchesSearchText || !currentTreeElement.matchesSearchText(searchText))) { + currentTreeElement = currentTreeElement.traverseNextTreeElement(true, null, true); + skipCurrentTreeElement = false; + } + + return currentTreeElement; +} + +/** + * @param {string} searchText + * @param {TreeElement=} startTreeElement + */ +TreeOutline.prototype._previousSearchMatch = function(searchText, startTreeElement) +{ + var currentTreeElement = startTreeElement; + var skipCurrentTreeElement = true; + while (currentTreeElement && (skipCurrentTreeElement || !currentTreeElement.matchesSearchText || !currentTreeElement.matchesSearchText(searchText))) { + currentTreeElement = currentTreeElement.traversePreviousTreeElement(true, true); + skipCurrentTreeElement = false; + } + + return currentTreeElement; +} + +TreeOutline.prototype._searchInputBlur = function(event) +{ + this._searchFinished(); +} + +TreeOutline.prototype._searchFinished = function() +{ + if (!this._searching) + return; + + delete this._searching; + this._childrenListNode.classList.remove("search-match-found"); + this._childrenListNode.classList.remove("search-match-not-found"); + delete this._currentSearchMatchElement; + + this.searchInputElement.value = ""; + this.searchInputElement.removeEventListener("paste", this._boundSearchTextChanged); + this.searchInputElement.removeEventListener("cut", this._boundSearchTextChanged); + delete this._boundSearchTextChanged; + + this.searchInputElement.removeEventListener("keydown", this._boundSearchInputKeyDown); + delete this._boundSearchInputKeyDown; + + this.searchInputElement.removeEventListener("blur", this._boundSearchInputBlur); + delete this._boundSearchInputBlur; + + if (this.searchFinished) + this.searchFinished(); + + this.treeOutline._childrenListNode.focus(); +} + +TreeOutline.prototype.stopSearch = function() +{ + this._searchFinished(); +} + +/** + * @constructor + * @param {Object=} representedObject + * @param {boolean=} hasChildren + */ +function TreeElement(title, representedObject, hasChildren) +{ + this._title = title; + this.representedObject = (representedObject || {}); + + this._hidden = false; + this._selectable = true; + this.expanded = false; + this.selected = false; + this.hasChildren = hasChildren; + this.children = []; + this.treeOutline = null; + this.parent = null; + this.previousSibling = null; + this.nextSibling = null; + this._listItemNode = null; +} + +TreeElement.prototype = { + arrowToggleWidth: 10, + + get selectable() { + if (this._hidden) + return false; + return this._selectable; + }, + + set selectable(x) { + this._selectable = x; + }, + + get listItemElement() { + return this._listItemNode; + }, + + get childrenListElement() { + return this._childrenListNode; + }, + + get title() { + return this._title; + }, + + set title(x) { + this._title = x; + this._setListItemNodeContent(); + this.didChange(); + }, + + get tooltip() { + return this._tooltip; + }, + + set tooltip(x) { + this._tooltip = x; + if (this._listItemNode) + this._listItemNode.title = x ? x : ""; + this.didChange(); + }, + + get hasChildren() { + return this._hasChildren; + }, + + set hasChildren(x) { + if (this._hasChildren === x) + return; + + this._hasChildren = x; + + if (!this._listItemNode) + return; + + if (x) + this._listItemNode.classList.add("parent"); + else { + this._listItemNode.classList.remove("parent"); + this.collapse(); + } + + this.didChange(); + }, + + get hidden() { + return this._hidden; + }, + + set hidden(x) { + if (this._hidden === x) + return; + + this._hidden = x; + + if (x) { + if (this._listItemNode) + this._listItemNode.classList.add("hidden"); + if (this._childrenListNode) + this._childrenListNode.classList.add("hidden"); + } else { + if (this._listItemNode) + this._listItemNode.classList.remove("hidden"); + if (this._childrenListNode) + this._childrenListNode.classList.remove("hidden"); + } + }, + + get shouldRefreshChildren() { + return this._shouldRefreshChildren; + }, + + set shouldRefreshChildren(x) { + this._shouldRefreshChildren = x; + if (x && this.expanded) + this.expand(); + }, + + _fireDidChange: function() + { + delete this._didChangeTimeoutIdentifier; + + if (this.treeOutline) + this.treeOutline._treeElementDidChange(this); + }, + + didChange: function() + { + if (!this.treeOutline) + return; + + // Prevent telling the TreeOutline multiple times in a row by delaying it with a timeout. + if (!this._didChangeTimeoutIdentifier) + this._didChangeTimeoutIdentifier = setTimeout(this._fireDidChange.bind(this), 0); + }, + + _setListItemNodeContent: function() + { + if (!this._listItemNode) + return; + + if (typeof this._title === "string") + this._listItemNode.textContent = this._title; + else { + this._listItemNode.removeChildren(); + if (this._title) + this._listItemNode.appendChild(this._title); + } + } +} + +TreeElement.prototype.appendChild = TreeOutline.prototype.appendChild; +TreeElement.prototype.insertChild = TreeOutline.prototype.insertChild; +TreeElement.prototype.removeChild = TreeOutline.prototype.removeChild; +TreeElement.prototype.removeChildAtIndex = TreeOutline.prototype.removeChildAtIndex; +TreeElement.prototype.removeChildren = TreeOutline.prototype.removeChildren; +TreeElement.prototype.removeChildrenRecursive = TreeOutline.prototype.removeChildrenRecursive; + +TreeElement.prototype._attach = function() +{ + if (!this._listItemNode || this.parent._shouldRefreshChildren) { + if (this._listItemNode && this._listItemNode.parentNode) + this._listItemNode.parentNode.removeChild(this._listItemNode); + + this._listItemNode = this.treeOutline._childrenListNode.ownerDocument.createElement("li"); + this._listItemNode.treeElement = this; + this._setListItemNodeContent(); + this._listItemNode.title = this._tooltip ? this._tooltip : ""; + + if (this.hidden) + this._listItemNode.classList.add("hidden"); + if (this.hasChildren) + this._listItemNode.classList.add("parent"); + if (this.expanded) + this._listItemNode.classList.add("expanded"); + if (this.selected) + this._listItemNode.classList.add("selected"); + + this._listItemNode.addEventListener("mousedown", TreeElement.treeElementMouseDown, false); + this._listItemNode.addEventListener("click", TreeElement.treeElementToggled, false); + this._listItemNode.addEventListener("dblclick", TreeElement.treeElementDoubleClicked, false); + + if (this.onattach) + this.onattach(this); + } + + var nextSibling = null; + if (this.nextSibling && this.nextSibling._listItemNode && this.nextSibling._listItemNode.parentNode === this.parent._childrenListNode) + nextSibling = this.nextSibling._listItemNode; + this.parent._childrenListNode.insertBefore(this._listItemNode, nextSibling); + if (this._childrenListNode) + this.parent._childrenListNode.insertBefore(this._childrenListNode, this._listItemNode.nextSibling); + if (this.selected) + this.select(); + if (this.expanded) + this.expand(); +} + +TreeElement.prototype._detach = function() +{ + if (this._listItemNode && this._listItemNode.parentNode) + this._listItemNode.parentNode.removeChild(this._listItemNode); + if (this._childrenListNode && this._childrenListNode.parentNode) + this._childrenListNode.parentNode.removeChild(this._childrenListNode); +} + +TreeElement.treeElementMouseDown = function(event) +{ + var element = event.currentTarget; + if (!element || !element.treeElement || !element.treeElement.selectable) + return; + + if (element.treeElement.isEventWithinDisclosureTriangle(event)) + return; + + element.treeElement.selectOnMouseDown(event); +} + +TreeElement.treeElementToggled = function(event) +{ + var element = event.currentTarget; + if (!element || !element.treeElement) + return; + + var toggleOnClick = element.treeElement.toggleOnClick && !element.treeElement.selectable; + var isInTriangle = element.treeElement.isEventWithinDisclosureTriangle(event); + if (!toggleOnClick && !isInTriangle) + return; + + if (element.treeElement.expanded) { + if (event.altKey) + element.treeElement.collapseRecursively(); + else + element.treeElement.collapse(); + } else { + if (event.altKey) + element.treeElement.expandRecursively(); + else + element.treeElement.expand(); + } + event.stopPropagation(); +} + +TreeElement.treeElementDoubleClicked = function(event) +{ + var element = event.currentTarget; + if (!element || !element.treeElement) + return; + + if (element.treeElement.ondblclick) + element.treeElement.ondblclick.call(element.treeElement, event); + else if (element.treeElement.hasChildren && !element.treeElement.expanded) + element.treeElement.expand(); +} + +TreeElement.prototype.collapse = function() +{ + if (this._listItemNode) + this._listItemNode.classList.remove("expanded"); + if (this._childrenListNode) + this._childrenListNode.classList.remove("expanded"); + + this.expanded = false; + + if (this.treeOutline) + this.treeOutline._expandedStateMap.put(this.representedObject, false); + + if (this.oncollapse) + this.oncollapse(this); +} + +TreeElement.prototype.collapseRecursively = function() +{ + var item = this; + while (item) { + if (item.expanded) + item.collapse(); + item = item.traverseNextTreeElement(false, this, true); + } +} + +TreeElement.prototype.expand = function() +{ + if (!this.hasChildren || (this.expanded && !this._shouldRefreshChildren && this._childrenListNode)) + return; + + // Set this before onpopulate. Since onpopulate can add elements and call onadd, this makes + // sure the expanded flag is true before calling those functions. This prevents the possibility + // of an infinite loop if onpopulate or onadd were to call expand. + + this.expanded = true; + if (this.treeOutline) + this.treeOutline._expandedStateMap.put(this.representedObject, true); + + if (this.treeOutline && (!this._childrenListNode || this._shouldRefreshChildren)) { + if (this._childrenListNode && this._childrenListNode.parentNode) + this._childrenListNode.parentNode.removeChild(this._childrenListNode); + + this._childrenListNode = this.treeOutline._childrenListNode.ownerDocument.createElement("ol"); + this._childrenListNode.parentTreeElement = this; + this._childrenListNode.classList.add("children"); + + if (this.hidden) + this._childrenListNode.classList.add("hidden"); + + this.onpopulate(); + + for (var i = 0; i < this.children.length; ++i) + this.children[i]._attach(); + + delete this._shouldRefreshChildren; + } + + if (this._listItemNode) { + this._listItemNode.classList.add("expanded"); + if (this._childrenListNode && this._childrenListNode.parentNode != this._listItemNode.parentNode) + this.parent._childrenListNode.insertBefore(this._childrenListNode, this._listItemNode.nextSibling); + } + + if (this._childrenListNode) + this._childrenListNode.classList.add("expanded"); + + if (this.onexpand) + this.onexpand(this); +} + +TreeElement.prototype.expandRecursively = function(maxDepth) +{ + var item = this; + var info = {}; + var depth = 0; + + // The Inspector uses TreeOutlines to represents object properties, so recursive expansion + // in some case can be infinite, since JavaScript objects can hold circular references. + // So default to a recursion cap of 3 levels, since that gives fairly good results. + if (typeof maxDepth === "undefined" || typeof maxDepth === "null") + maxDepth = 3; + + while (item) { + if (depth < maxDepth) + item.expand(); + item = item.traverseNextTreeElement(false, this, (depth >= maxDepth), info); + depth += info.depthChange; + } +} + +TreeElement.prototype.hasAncestor = function(ancestor) { + if (!ancestor) + return false; + + var currentNode = this.parent; + while (currentNode) { + if (ancestor === currentNode) + return true; + currentNode = currentNode.parent; + } + + return false; +} + +TreeElement.prototype.reveal = function() +{ + var currentAncestor = this.parent; + while (currentAncestor && !currentAncestor.root) { + if (!currentAncestor.expanded) + currentAncestor.expand(); + currentAncestor = currentAncestor.parent; + } + + if (this.onreveal) + this.onreveal(this); +} + +TreeElement.prototype.revealed = function() +{ + var currentAncestor = this.parent; + while (currentAncestor && !currentAncestor.root) { + if (!currentAncestor.expanded) + return false; + currentAncestor = currentAncestor.parent; + } + + return true; +} + +TreeElement.prototype.selectOnMouseDown = function(event) +{ + this.select(false, true); +} + +/** + * @param {boolean=} omitFocus + * @param {boolean=} selectedByUser + */ +TreeElement.prototype.select = function(omitFocus, selectedByUser) +{ + if (!this.treeOutline || !this.selectable || this.selected) + return; + + if (this.treeOutline.selectedTreeElement) + this.treeOutline.selectedTreeElement.deselect(); + + this.selected = true; + + if(!omitFocus) + this.treeOutline._childrenListNode.focus(); + + // Focusing on another node may detach "this" from tree. + if (!this.treeOutline) + return; + this.treeOutline.selectedTreeElement = this; + if (this._listItemNode) + this._listItemNode.classList.add("selected"); + + if (this.onselect) + this.onselect(this, selectedByUser); +} + +/** + * @param {boolean=} omitFocus + */ +TreeElement.prototype.revealAndSelect = function(omitFocus) +{ + this.reveal(); + this.select(omitFocus); +} + +/** + * @param {boolean=} supressOnDeselect + */ +TreeElement.prototype.deselect = function(supressOnDeselect) +{ + if (!this.treeOutline || this.treeOutline.selectedTreeElement !== this || !this.selected) + return false; + + this.selected = false; + this.treeOutline.selectedTreeElement = null; + if (this._listItemNode) + this._listItemNode.classList.remove("selected"); + + if (this.ondeselect && !supressOnDeselect) + this.ondeselect(this); + return true; +} + +TreeElement.prototype.onpopulate = function() +{ + // Overriden by subclasses. +} + +/** + * @param {boolean} skipUnrevealed + * @param {(TreeOutline|TreeElement)=} stayWithin + * @param {boolean=} dontPopulate + * @param {Object=} info + * @return {TreeElement} + */ +TreeElement.prototype.traverseNextTreeElement = function(skipUnrevealed, stayWithin, dontPopulate, info) +{ + if (!dontPopulate && this.hasChildren) + this.onpopulate(); + + if (info) + info.depthChange = 0; + + var element = skipUnrevealed ? (this.revealed() ? this.children[0] : null) : this.children[0]; + if (element && (!skipUnrevealed || (skipUnrevealed && this.expanded))) { + if (info) + info.depthChange = 1; + return element; + } + + if (this === stayWithin) + return null; + + element = skipUnrevealed ? (this.revealed() ? this.nextSibling : null) : this.nextSibling; + if (element) + return element; + + element = this; + while (element && !element.root && !(skipUnrevealed ? (element.revealed() ? element.nextSibling : null) : element.nextSibling) && element.parent !== stayWithin) { + if (info) + info.depthChange -= 1; + element = element.parent; + } + + if (!element) + return null; + + return (skipUnrevealed ? (element.revealed() ? element.nextSibling : null) : element.nextSibling); +} + +/** + * @param {boolean} skipUnrevealed + * @param {boolean=} dontPopulate + * @return {TreeElement} + */ +TreeElement.prototype.traversePreviousTreeElement = function(skipUnrevealed, dontPopulate) +{ + var element = skipUnrevealed ? (this.revealed() ? this.previousSibling : null) : this.previousSibling; + if (!dontPopulate && element && element.hasChildren) + element.onpopulate(); + + while (element && (skipUnrevealed ? (element.revealed() && element.expanded ? element.children[element.children.length - 1] : null) : element.children[element.children.length - 1])) { + if (!dontPopulate && element.hasChildren) + element.onpopulate(); + element = (skipUnrevealed ? (element.revealed() && element.expanded ? element.children[element.children.length - 1] : null) : element.children[element.children.length - 1]); + } + + if (element) + return element; + + if (!this.parent || this.parent.root) + return null; + + return this.parent; +} + +TreeElement.prototype.isEventWithinDisclosureTriangle = function(event) +{ + // FIXME: We should not use getComputedStyle(). For that we need to get rid of using ::before for disclosure triangle. (http://webk.it/74446) + var computedLeftPadding = window.getComputedStyle(this._listItemNode).getPropertyCSSValue("padding-left").getFloatValue(CSSPrimitiveValue.CSS_PX); + var left = this._listItemNode.totalOffsetLeft() + computedLeftPadding; + return event.pageX >= left && event.pageX <= left + this.arrowToggleWidth && this.hasChildren; +} +/* inspector.js */ + +/* + * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2007 Matt Lilek (pewtermoose@gmail.com). + * Copyright (C) 2009 Joseph Pecoraro + * + * 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. + */ + +var WebInspector = { + _createPanels: function() + { + this.panels = {}; + WebInspector.inspectorView = new WebInspector.InspectorView(); + var parentElement = document.getElementById("main"); + WebInspector.inspectorView.show(parentElement); + WebInspector.inspectorView.addEventListener(WebInspector.InspectorView.Events.PanelSelected, this._panelSelected, this); + + if (WebInspector.WorkerManager.isWorkerFrontend()) { + this.panels.scripts = new WebInspector.ScriptsPanel(this.debuggerPresentationModel); + this.panels.console = new WebInspector.ConsolePanel(); + return; + } + var hiddenPanels = (InspectorFrontendHost.hiddenPanels() || "").split(','); + if (hiddenPanels.indexOf("elements") === -1) + this.panels.elements = new WebInspector.ElementsPanel(); + if (hiddenPanels.indexOf("resources") === -1) + this.panels.resources = new WebInspector.ResourcesPanel(); + if (hiddenPanels.indexOf("network") === -1) + this.panels.network = new WebInspector.NetworkPanel(); + if (hiddenPanels.indexOf("scripts") === -1) + this.panels.scripts = new WebInspector.ScriptsPanel(this.debuggerPresentationModel); + if (hiddenPanels.indexOf("timeline") === -1) + this.panels.timeline = new WebInspector.TimelinePanel(); + if (hiddenPanels.indexOf("profiles") === -1) + this.panels.profiles = new WebInspector.ProfilesPanel(); + if (hiddenPanels.indexOf("audits") === -1) + this.panels.audits = new WebInspector.AuditsPanel(); + if (hiddenPanels.indexOf("console") === -1) + this.panels.console = new WebInspector.ConsolePanel(); + }, + + _panelSelected: function() + { + this._toggleConsoleButton.disabled = WebInspector.inspectorView.currentPanel() === WebInspector.panels.console; + }, + + _createGlobalStatusBarItems: function() + { + this._dockToggleButton = new WebInspector.StatusBarButton(this._dockButtonTitle(), "dock-status-bar-item"); + this._dockToggleButton.addEventListener("click", this._toggleAttach.bind(this), false); + this._dockToggleButton.toggled = !this.attached; + + this._settingsButton = new WebInspector.StatusBarButton(WebInspector.UIString("Settings"), "settings-status-bar-item"); + this._settingsButton.addEventListener("click", this._toggleSettings.bind(this), false); + + var anchoredStatusBar = document.getElementById("anchored-status-bar-items"); + anchoredStatusBar.appendChild(this._dockToggleButton.element); + + this._toggleConsoleButton = new WebInspector.StatusBarButton(WebInspector.UIString("Show console."), "console-status-bar-item"); + this._toggleConsoleButton.addEventListener("click", this._toggleConsoleButtonClicked.bind(this), false); + anchoredStatusBar.appendChild(this._toggleConsoleButton.element); + + if (this.panels.elements) + anchoredStatusBar.appendChild(this.panels.elements.nodeSearchButton.element); + anchoredStatusBar.appendChild(this._settingsButton.element); + }, + + _dockButtonTitle: function() + { + return this.attached ? WebInspector.UIString("Undock into separate window.") : WebInspector.UIString("Dock to main window."); + }, + + _toggleAttach: function() + { + if (!this._attached) { + InspectorFrontendHost.requestAttachWindow(); + WebInspector.userMetrics.WindowDocked.record(); + } else { + InspectorFrontendHost.requestDetachWindow(); + WebInspector.userMetrics.WindowUndocked.record(); + } + }, + + _toggleConsoleButtonClicked: function() + { + if (this._toggleConsoleButton.disabled) + return; + + this._toggleConsoleButton.toggled = !this._toggleConsoleButton.toggled; + + var animationType = window.event && window.event.shiftKey ? WebInspector.Drawer.AnimationType.Slow : WebInspector.Drawer.AnimationType.Normal; + if (this._toggleConsoleButton.toggled) { + this._toggleConsoleButton.title = WebInspector.UIString("Hide console."); + this.drawer.show(this.consoleView, animationType); + this._consoleWasShown = true; + } else { + this._toggleConsoleButton.title = WebInspector.UIString("Show console."); + this.drawer.hide(animationType); + delete this._consoleWasShown; + } + }, + + _escPressed: function() + { + // If drawer was open with some view other than console then just close it. + if (!this._consoleWasShown && WebInspector.drawer.visible) + this.drawer.hide(WebInspector.Drawer.AnimationType.Immediately); + else + this._toggleConsoleButtonClicked(); + }, + + /** + * @param {WebInspector.View} view + */ + showViewInDrawer: function(view) + { + this._toggleConsoleButton.title = WebInspector.UIString("Hide console."); + this._toggleConsoleButton.toggled = false; + this.drawer.show(view, WebInspector.Drawer.AnimationType.Immediately); + }, + + _toggleSettings: function() + { + this._settingsButton.toggled = !this._settingsButton.toggled; + if (this._settingsButton.toggled) + this._showSettingsScreen(); + else + this._hideSettingsScreen(); + }, + + _showSettingsScreen: function() + { + function onhide() + { + this._settingsButton.toggled = false; + delete this._settingsScreen; + } + + if (!this._settingsScreen) { + this._settingsScreen = new WebInspector.SettingsScreen(); + this._settingsScreen.show(onhide.bind(this)); + } + }, + + _hideSettingsScreen: function() + { + if (this._settingsScreen) + this._settingsScreen.hide(); + }, + + get attached() + { + return this._attached; + }, + + set attached(x) + { + if (this._attached === x) + return; + + this._attached = x; + + if (this._dockToggleButton) { + this._dockToggleButton.title = this._dockButtonTitle(); + this._dockToggleButton.toggled = !x; + } + + if (x) + document.body.removeStyleClass("detached"); + else + document.body.addStyleClass("detached"); + + this._setCompactMode(x && !WebInspector.settings.dockToRight.get()); + }, + + isCompactMode: function() + { + return this.attached && !WebInspector.settings.dockToRight.get(); + }, + + _setCompactMode: function(x) + { + var body = document.body; + if (x) + body.addStyleClass("compact"); + else + body.removeStyleClass("compact"); + + // This may be called before doLoadedDone, hence the bulk of inspector objects may + // not be created yet. + if (WebInspector.toolbar) + WebInspector.toolbar.compact = x; + + if (WebInspector.searchController) + WebInspector.searchController.updateSearchLabel(); + + if (WebInspector.drawer) + WebInspector.drawer.resize(); + }, + + _updateErrorAndWarningCounts: function() + { + var errorWarningElement = document.getElementById("error-warning-count"); + if (!errorWarningElement) + return; + + var errors = WebInspector.console.errors; + var warnings = WebInspector.console.warnings; + if (!errors && !warnings) { + errorWarningElement.addStyleClass("hidden"); + return; + } + + errorWarningElement.removeStyleClass("hidden"); + + errorWarningElement.removeChildren(); + + if (errors) { + var errorImageElement = document.createElement("img"); + errorImageElement.id = "error-count-img"; + errorWarningElement.appendChild(errorImageElement); + var errorElement = document.createElement("span"); + errorElement.id = "error-count"; + errorElement.textContent = errors; + errorWarningElement.appendChild(errorElement); + } + + if (warnings) { + var warningsImageElement = document.createElement("img"); + warningsImageElement.id = "warning-count-img"; + errorWarningElement.appendChild(warningsImageElement); + var warningsElement = document.createElement("span"); + warningsElement.id = "warning-count"; + warningsElement.textContent = warnings; + errorWarningElement.appendChild(warningsElement); + } + + if (errors) { + if (warnings) { + if (errors == 1) { + if (warnings == 1) + errorWarningElement.title = WebInspector.UIString("%d error, %d warning", errors, warnings); + else + errorWarningElement.title = WebInspector.UIString("%d error, %d warnings", errors, warnings); + } else if (warnings == 1) + errorWarningElement.title = WebInspector.UIString("%d errors, %d warning", errors, warnings); + else + errorWarningElement.title = WebInspector.UIString("%d errors, %d warnings", errors, warnings); + } else if (errors == 1) + errorWarningElement.title = WebInspector.UIString("%d error", errors); + else + errorWarningElement.title = WebInspector.UIString("%d errors", errors); + } else if (warnings == 1) + errorWarningElement.title = WebInspector.UIString("%d warning", warnings); + else if (warnings) + errorWarningElement.title = WebInspector.UIString("%d warnings", warnings); + else + errorWarningElement.title = null; + }, + + networkResourceById: function(id) + { + return this.panels.network.resourceById(id); + }, + + get inspectedPageDomain() + { + var parsedURL = WebInspector.inspectedPageURL && WebInspector.inspectedPageURL.asParsedURL(); + return parsedURL ? parsedURL.host : ""; + }, + + _initializeCapability: function(name, callback, error, result) + { + Capabilities[name] = result; + if (callback) + callback(); + } +} + +WebInspector.Events = { + InspectorClosing: "InspectorClosing" +} + +{(function parseQueryParameters() +{ + WebInspector.queryParamsObject = {}; + var queryParams = window.location.search; + if (!queryParams) + return; + var params = queryParams.substring(1).split("&"); + for (var i = 0; i < params.length; ++i) { + var pair = params[i].split("="); + WebInspector.queryParamsObject[pair[0]] = pair[1]; + } +})();} + +WebInspector.loaded = function() +{ + InspectorBackend.loadFromJSONIfNeeded(); + if ("page" in WebInspector.queryParamsObject) { + var page = WebInspector.queryParamsObject.page; + var host = "host" in WebInspector.queryParamsObject ? WebInspector.queryParamsObject.host : window.location.host; + WebInspector.socket = new WebSocket("ws://" + host + "/devtools/page/" + page); + WebInspector.socket.onmessage = function(message) { InspectorBackend.dispatch(message.data); } + WebInspector.socket.onerror = function(error) { console.error(error); } + WebInspector.socket.onopen = function() { + InspectorFrontendHost.sendMessageToBackend = WebInspector.socket.send.bind(WebInspector.socket); + WebInspector.doLoadedDone(); + } + return; + } + WebInspector.doLoadedDone(); +} + +WebInspector.doLoadedDone = function() +{ + // Install styles and themes + WebInspector.installPortStyles(); + if (WebInspector.socket) + document.body.addStyleClass("remote"); + + if (WebInspector.queryParamsObject.toolbarColor && WebInspector.queryParamsObject.textColor) + WebInspector.setToolbarColors(WebInspector.queryParamsObject.toolbarColor, WebInspector.queryParamsObject.textColor); + + InspectorFrontendHost.loaded(); + WebInspector.WorkerManager.loaded(); + + DebuggerAgent.causesRecompilation(WebInspector._initializeCapability.bind(WebInspector, "debuggerCausesRecompilation", null)); + DebuggerAgent.supportsNativeBreakpoints(WebInspector._initializeCapability.bind(WebInspector, "nativeInstrumentationEnabled", null)); + ProfilerAgent.causesRecompilation(WebInspector._initializeCapability.bind(WebInspector, "profilerCausesRecompilation", null)); + ProfilerAgent.isSampling(WebInspector._initializeCapability.bind(WebInspector, "samplingCPUProfiler", null)); + ProfilerAgent.hasHeapProfiler(WebInspector._initializeCapability.bind(WebInspector, "heapProfilerPresent", WebInspector._doLoadedDoneWithCapabilities.bind(WebInspector))); +} + +WebInspector._doLoadedDoneWithCapabilities = function() +{ + WebInspector.shortcutsScreen = new WebInspector.ShortcutsScreen(); + this._registerShortcuts(); + + // set order of some sections explicitly + WebInspector.shortcutsScreen.section(WebInspector.UIString("Console")); + WebInspector.shortcutsScreen.section(WebInspector.UIString("Elements Panel")); + + this.console = new WebInspector.ConsoleModel(); + this.console.addEventListener(WebInspector.ConsoleModel.Events.ConsoleCleared, this._updateErrorAndWarningCounts, this); + this.console.addEventListener(WebInspector.ConsoleModel.Events.MessageAdded, this._updateErrorAndWarningCounts, this); + this.console.addEventListener(WebInspector.ConsoleModel.Events.RepeatCountUpdated, this._updateErrorAndWarningCounts, this); + + this.debuggerModel = new WebInspector.DebuggerModel(); + this.debuggerPresentationModel = new WebInspector.DebuggerPresentationModel(); + + this.drawer = new WebInspector.Drawer(); + this.consoleView = new WebInspector.ConsoleView(WebInspector.WorkerManager.isWorkerFrontend()); + + this.networkManager = new WebInspector.NetworkManager(); + this.resourceTreeModel = new WebInspector.ResourceTreeModel(this.networkManager); + this.networkLog = new WebInspector.NetworkLog(); + this.domAgent = new WebInspector.DOMAgent(); + new WebInspector.JavaScriptContextManager(this.resourceTreeModel, this.consoleView); + + InspectorBackend.registerInspectorDispatcher(this); + + this.cssModel = new WebInspector.CSSStyleModel(); + this.timelineManager = new WebInspector.TimelineManager(); + InspectorBackend.registerDatabaseDispatcher(new WebInspector.DatabaseDispatcher()); + InspectorBackend.registerDOMStorageDispatcher(new WebInspector.DOMStorageDispatcher()); + + this.searchController = new WebInspector.SearchController(); + this.advancedSearchController = new WebInspector.AdvancedSearchController(); + + if (Capabilities.nativeInstrumentationEnabled) + this.domBreakpointsSidebarPane = new WebInspector.DOMBreakpointsSidebarPane(); + + this._createPanels(); + this._createGlobalStatusBarItems(); + + + this.toolbar = new WebInspector.Toolbar(); + WebInspector._installDockToRight(); + + for (var panelName in this.panels) + this.addPanel(this.panels[panelName]); + + this.addMainEventListeners(document); + + window.addEventListener("resize", this.windowResize.bind(this), true); + + var errorWarningCount = document.getElementById("error-warning-count"); + errorWarningCount.addEventListener("click", this.showConsole.bind(this), false); + this._updateErrorAndWarningCounts(); + + var autoselectPanel = WebInspector.UIString("a panel chosen automatically"); + var openAnchorLocationSetting = WebInspector.settings.createSetting("openLinkHandler", autoselectPanel); + this.openAnchorLocationRegistry = new WebInspector.HandlerRegistry(openAnchorLocationSetting); + this.openAnchorLocationRegistry.registerHandler(autoselectPanel, function() { return false; }); + + this.extensionServer.initExtensions(); + + this.console.enableAgent(); + + function showInitialPanel() + { + if (!WebInspector.inspectorView.currentPanel()) + WebInspector.showPanel(WebInspector.settings.lastActivePanel.get()); + } + + InspectorAgent.enable(showInitialPanel); + DatabaseAgent.enable(); + DOMStorageAgent.enable(); + + WebInspector.CSSCompletions.requestCSSNameCompletions(); + WebInspector.WorkerManager.loadCompleted(); + InspectorFrontendAPI.loadCompleted(); +} + +WebInspector._installDockToRight = function() +{ + // Re-use Settings infrastructure for the dock-to-right settings UI + WebInspector.settings.dockToRight.set(WebInspector.queryParamsObject.dockSide === "right"); + + if (WebInspector.settings.dockToRight.get()) + document.body.addStyleClass("dock-to-right"); + + if (WebInspector.attached) + WebInspector._setCompactMode(!WebInspector.settings.dockToRight.get()); + + WebInspector.settings.dockToRight.addChangeListener(listener.bind(this)); + + function listener(event) + { + var value = WebInspector.settings.dockToRight.get(); + if (value) { + InspectorFrontendHost.requestSetDockSide("right"); + document.body.addStyleClass("dock-to-right"); + } else { + InspectorFrontendHost.requestSetDockSide("bottom"); + document.body.removeStyleClass("dock-to-right"); + } + if (WebInspector.attached) + WebInspector._setCompactMode(!value); + } +} + +WebInspector.addPanel = function(panel) +{ + WebInspector.inspectorView.addPanel(panel); +} + +var windowLoaded = function() +{ + var localizedStringsURL = InspectorFrontendHost.localizedStringsURL(); + if (localizedStringsURL) { + var localizedStringsScriptElement = document.createElement("script"); + localizedStringsScriptElement.addEventListener("load", WebInspector.loaded.bind(WebInspector), false); + localizedStringsScriptElement.type = "text/javascript"; + localizedStringsScriptElement.src = localizedStringsURL; + document.head.appendChild(localizedStringsScriptElement); + } else + WebInspector.loaded(); + + WebInspector.setAttachedWindow(WebInspector.queryParamsObject.docked === "true"); + + window.removeEventListener("DOMContentLoaded", windowLoaded, false); + delete windowLoaded; +}; + +window.addEventListener("DOMContentLoaded", windowLoaded, false); + +// We'd like to enforce asynchronous interaction between the inspector controller and the frontend. +// It is needed to prevent re-entering the backend code. +// Also, native dispatches do not guarantee setTimeouts to be serialized, so we +// enforce serialization using 'messagesToDispatch' queue. It is also important that JSC debugger +// tests require that each command was dispatch within individual timeout callback, so we don't batch them. + +var messagesToDispatch = []; + +WebInspector.dispatchQueueIsEmpty = function() { + return messagesToDispatch.length == 0; +} + +WebInspector.dispatch = function(message) { + messagesToDispatch.push(message); + setTimeout(function() { + InspectorBackend.dispatch(messagesToDispatch.shift()); + }, 0); +} + +WebInspector.dispatchMessageFromBackend = function(messageObject) +{ + WebInspector.dispatch(messageObject); +} + +WebInspector.windowResize = function(event) +{ + WebInspector.inspectorView.doResize(); + WebInspector.drawer.resize(); + WebInspector.toolbar.resize(); +} + +WebInspector.setAttachedWindow = function(attached) +{ + this.attached = attached; +} + +WebInspector.close = function(event) +{ + if (this._isClosing) + return; + this._isClosing = true; + this.notifications.dispatchEventToListeners(WebInspector.Events.InspectorClosing); + InspectorFrontendHost.closeWindow(); +} + +WebInspector.documentClick = function(event) +{ + var anchor = event.target.enclosingNodeOrSelfWithNodeName("a"); + if (!anchor || anchor.target === "_blank") + return; + + // Prevent the link from navigating, since we don't do any navigation by following links normally. + event.preventDefault(); + event.stopPropagation(); + + function followLink() + { + if (WebInspector._showAnchorLocation(anchor)) + return; + + const profileMatch = WebInspector.ProfileType.URLRegExp.exec(anchor.href); + if (profileMatch) { + WebInspector.showProfileForURL(anchor.href); + return; + } + + var parsedURL = anchor.href.asParsedURL(); + if (parsedURL && parsedURL.scheme === "webkit-link-action") { + if (parsedURL.host === "show-panel") { + var panel = parsedURL.path.substring(1); + if (WebInspector.panels[panel]) + WebInspector.showPanel(panel); + } + return; + } + + WebInspector.showPanel("resources"); + } + + if (WebInspector.followLinkTimeout) + clearTimeout(WebInspector.followLinkTimeout); + + if (anchor.preventFollowOnDoubleClick) { + // Start a timeout if this is the first click, if the timeout is canceled + // before it fires, then a double clicked happened or another link was clicked. + if (event.detail === 1) + WebInspector.followLinkTimeout = setTimeout(followLink, 333); + return; + } + + followLink(); +} + +WebInspector.openResource = function(resourceURL, inResourcesPanel) +{ + var resource = WebInspector.resourceForURL(resourceURL); + if (inResourcesPanel && resource) { + WebInspector.panels.resources.showResource(resource); + WebInspector.showPanel("resources"); + } else + InspectorFrontendHost.openInNewTab(resourceURL); +} + +WebInspector.openRequestInNetworkPanel = function(resource) +{ + WebInspector.showPanel("network"); + WebInspector.panels.network.revealAndHighlightResource(resource); +} + +WebInspector._registerShortcuts = function() +{ + var shortcut = WebInspector.KeyboardShortcut; + var section = WebInspector.shortcutsScreen.section(WebInspector.UIString("All Panels")); + var keys = [ + shortcut.shortcutToString("]", shortcut.Modifiers.CtrlOrMeta), + shortcut.shortcutToString("[", shortcut.Modifiers.CtrlOrMeta) + ]; + section.addRelatedKeys(keys, WebInspector.UIString("Next/previous panel")); + section.addKey(shortcut.shortcutToString(shortcut.Keys.Esc), WebInspector.UIString("Toggle console")); + section.addKey(shortcut.shortcutToString("f", shortcut.Modifiers.CtrlOrMeta), WebInspector.UIString("Search")); + + var advancedSearchShortcut = WebInspector.AdvancedSearchController.createShortcut(); + section.addKey(advancedSearchShortcut.name, WebInspector.UIString("Search across all scripts")); + + if (WebInspector.isMac()) { + keys = [ + shortcut.shortcutToString("g", shortcut.Modifiers.Meta), + shortcut.shortcutToString("g", shortcut.Modifiers.Meta | shortcut.Modifiers.Shift) + ]; + section.addRelatedKeys(keys, WebInspector.UIString("Find next/previous")); + } + + var goToShortcut = WebInspector.GoToLineDialog.createShortcut(); + section.addKey(goToShortcut.name, WebInspector.UIString("Go to Line")); +} + +WebInspector.documentKeyDown = function(event) +{ + const helpKey = WebInspector.isMac() ? "U+003F" : "U+00BF"; // "?" for both platforms + + if (event.keyIdentifier === "F1" || + (event.keyIdentifier === helpKey && event.shiftKey && (!WebInspector.isInEditMode(event) || event.metaKey))) { + WebInspector.shortcutsScreen.show(); + event.stopPropagation(); + event.preventDefault(); + return; + } + + if (WebInspector.currentFocusElement() && WebInspector.currentFocusElement().handleKeyEvent) { + WebInspector.currentFocusElement().handleKeyEvent(event); + if (event.handled) { + event.preventDefault(); + return; + } + } + + if (WebInspector.inspectorView.currentPanel()) { + WebInspector.inspectorView.currentPanel().handleShortcut(event); + if (event.handled) { + event.preventDefault(); + return; + } + } + + WebInspector.searchController.handleShortcut(event); + WebInspector.advancedSearchController.handleShortcut(event); + if (event.handled) { + event.preventDefault(); + return; + } + + var isMac = WebInspector.isMac(); + switch (event.keyIdentifier) { + case "U+001B": // Escape key + if (event.target.hasStyleClass("text-prompt") || !WebInspector.isInEditMode(event)) { + event.preventDefault(); + this._escPressed(); + } + break; + case "U+0052": // R key + if (WebInspector.isInEditMode(event)) + return; + if ((event.metaKey && isMac) || (event.ctrlKey && !isMac)) { + PageAgent.reload(event.shiftKey); + event.preventDefault(); + } + break; + case "F5": + if (!isMac && !WebInspector.isInEditMode(event)) { + PageAgent.reload(event.ctrlKey || event.shiftKey); + event.preventDefault(); + } + break; + } +} + +WebInspector.documentCanCopy = function(event) +{ + if (WebInspector.inspectorView.currentPanel() && WebInspector.inspectorView.currentPanel().handleCopyEvent) + event.preventDefault(); +} + +WebInspector.documentCopy = function(event) +{ + if (WebInspector.inspectorView.currentPanel() && WebInspector.inspectorView.currentPanel().handleCopyEvent) + WebInspector.inspectorView.currentPanel().handleCopyEvent(event); +} + +WebInspector.contextMenuEventFired = function(event) +{ + if (event.handled || event.target.hasStyleClass("popup-glasspane")) + event.preventDefault(); +} + +WebInspector.toggleSearchingForNode = function() +{ + if (this.panels.elements) { + this.showPanel("elements"); + this.panels.elements.toggleSearchingForNode(); + } +} + +WebInspector.showConsole = function() +{ + if (WebInspector._toggleConsoleButton && !WebInspector._toggleConsoleButton.toggled) + WebInspector._toggleConsoleButtonClicked(); +} + +WebInspector.showPanel = function(panel) +{ + if (!(panel in this.panels)) { + if (WebInspector.WorkerManager.isWorkerFrontend()) + panel = "scripts"; + else + panel = "elements"; + } + WebInspector.inspectorView.setCurrentPanel(this.panels[panel]); +} + +WebInspector.bringToFront = function() +{ + InspectorFrontendHost.bringToFront(); +} + +WebInspector.didCreateWorker = function() +{ + var workersPane = WebInspector.panels.scripts.sidebarPanes.workers; + if (workersPane) + workersPane.addWorker.apply(workersPane, arguments); +} + +WebInspector.didDestroyWorker = function() +{ + var workersPane = WebInspector.panels.scripts.sidebarPanes.workers; + if (workersPane) + workersPane.removeWorker.apply(workersPane, arguments); +} + +/** + * @param {string=} messageLevel + * @param {boolean=} showConsole + */ +WebInspector.log = function(message, messageLevel, showConsole) +{ + // remember 'this' for setInterval() callback + var self = this; + + // return indication if we can actually log a message + function isLogAvailable() + { + return WebInspector.ConsoleMessage && WebInspector.RemoteObject && self.console; + } + + // flush the queue of pending messages + function flushQueue() + { + var queued = WebInspector.log.queued; + if (!queued) + return; + + for (var i = 0; i < queued.length; ++i) + logMessage(queued[i]); + + delete WebInspector.log.queued; + } + + // flush the queue if it console is available + // - this function is run on an interval + function flushQueueIfAvailable() + { + if (!isLogAvailable()) + return; + + clearInterval(WebInspector.log.interval); + delete WebInspector.log.interval; + + flushQueue(); + } + + // actually log the message + function logMessage(message) + { + // post the message + var msg = WebInspector.ConsoleMessage.create( + WebInspector.ConsoleMessage.MessageSource.Other, + messageLevel || WebInspector.ConsoleMessage.MessageLevel.Debug, + message); + + self.console.addMessage(msg); + if (showConsole) + WebInspector.showConsole(); + } + + // if we can't log the message, queue it + if (!isLogAvailable()) { + if (!WebInspector.log.queued) + WebInspector.log.queued = []; + + WebInspector.log.queued.push(message); + + if (!WebInspector.log.interval) + WebInspector.log.interval = setInterval(flushQueueIfAvailable, 1000); + + return; + } + + // flush the pending queue if any + flushQueue(); + + // log the message + logMessage(message); +} + +WebInspector.inspect = function(payload, hints) +{ + var object = WebInspector.RemoteObject.fromPayload(payload); + if (object.subtype === "node") { + // Request node from backend and focus it. + WebInspector.inspectorView.setCurrentPanel(WebInspector.panels.elements); + object.pushNodeToFrontend(WebInspector.updateFocusedNode.bind(WebInspector), object.release.bind(object)); + return; + } + + if (hints.databaseId) { + WebInspector.inspectorView.setCurrentPanel(WebInspector.panels.resources); + WebInspector.panels.resources.selectDatabase(hints.databaseId); + } else if (hints.domStorageId) { + WebInspector.inspectorView.setCurrentPanel(WebInspector.panels.resources); + WebInspector.panels.resources.selectDOMStorage(hints.domStorageId); + } + + object.release(); +} + +WebInspector.updateFocusedNode = function(nodeId) +{ + this.panels.elements.revealAndSelectNode(nodeId); +} + +WebInspector.populateResourceContextMenu = function(contextMenu, url, preferredLineNumber) +{ + var registry = WebInspector.openAnchorLocationRegistry; + // Skip 0th handler, as it's 'Use default panel' one. + for (var i = 1; i < registry.handlerNames.length; ++i) { + var handler = registry.handlerNames[i]; + contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Open using %s" : "Open Using %s", handler), + registry.dispatchToHandler.bind(registry, handler, { url: url, preferredLineNumber: preferredLineNumber })); + } +} + +WebInspector._showAnchorLocation = function(anchor) +{ + if (WebInspector.openAnchorLocationRegistry.dispatch({ url: anchor.href, lineNumber: anchor.lineNumber})) + return true; + var preferedPanel = this.panels[anchor.preferredPanel || "resources"]; + if (WebInspector._showAnchorLocationInPanel(anchor, preferedPanel)) + return true; + if (preferedPanel !== this.panels.resources && WebInspector._showAnchorLocationInPanel(anchor, this.panels.resources)) + return true; + return false; +} + +WebInspector._showAnchorLocationInPanel = function(anchor, panel) +{ + if (!panel.canShowAnchorLocation(anchor)) + return false; + + // FIXME: support webkit-html-external-link links here. + if (anchor.hasStyleClass("webkit-html-external-link")) { + anchor.removeStyleClass("webkit-html-external-link"); + anchor.addStyleClass("webkit-html-resource-link"); + } + + this.showPanelForAnchorNavigation(panel); + panel.showAnchorLocation(anchor); + return true; +} + +WebInspector.showPanelForAnchorNavigation = function(panel) +{ + WebInspector.searchController.disableSearchUntilExplicitAction(); + WebInspector.inspectorView.setCurrentPanel(panel); +} + +WebInspector.showProfileForURL = function(url) +{ + WebInspector.showPanel("profiles"); + WebInspector.panels.profiles.showProfileForURL(url); +} + +WebInspector.evaluateInConsole = function(expression) +{ + this.showConsole(); + this.consoleView.evaluateUsingTextPrompt(expression); +} + +WebInspector.addMainEventListeners = function(doc) +{ + doc.addEventListener("keydown", this.documentKeyDown.bind(this), false); + doc.addEventListener("beforecopy", this.documentCanCopy.bind(this), true); + doc.addEventListener("copy", this.documentCopy.bind(this), true); + doc.addEventListener("contextmenu", this.contextMenuEventFired.bind(this), true); + doc.addEventListener("click", this.documentClick.bind(this), true); +} + +WebInspector.frontendReused = function() +{ + this.resourceTreeModel.frontendReused(); +} + +WebInspector._toolbarItemClicked = function(event) +{ + var toolbarItem = event.currentTarget; + WebInspector.inspectorView.setCurrentPanel(toolbarItem.panel); +} +/* UIUtils.js */ + +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2007 Matt Lilek (pewtermoose@gmail.com). + * Copyright (C) 2009 Joseph Pecoraro + * + * 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. + */ + +WebInspector.elementDragStart = function(element, dividerDrag, elementDragEnd, event, cursor) +{ + if (WebInspector._elementDraggingEventListener || WebInspector._elementEndDraggingEventListener) + WebInspector.elementDragEnd(event); + + if (element) { + // Install glass pane + if (WebInspector._elementDraggingGlassPane) + WebInspector._elementDraggingGlassPane.parentElement.removeChild(WebInspector._elementDraggingGlassPane); + + var glassPane = document.createElement("div"); + glassPane.style.cssText = "position:absolute;top:0;bottom:0;left:0;right:0;opacity:0;z-index:1"; + glassPane.id = "glass-pane-for-drag"; + element.ownerDocument.body.appendChild(glassPane); + WebInspector._elementDraggingGlassPane = glassPane; + } + + WebInspector._elementDraggingEventListener = dividerDrag; + WebInspector._elementEndDraggingEventListener = elementDragEnd; + + var targetDocument = event.target.ownerDocument; + targetDocument.addEventListener("mousemove", dividerDrag, true); + targetDocument.addEventListener("mouseup", elementDragEnd, true); + + targetDocument.body.style.cursor = cursor; + + event.preventDefault(); +} + +WebInspector.elementDragEnd = function(event) +{ + var targetDocument = event.target.ownerDocument; + targetDocument.removeEventListener("mousemove", WebInspector._elementDraggingEventListener, true); + targetDocument.removeEventListener("mouseup", WebInspector._elementEndDraggingEventListener, true); + + targetDocument.body.style.removeProperty("cursor"); + + if (WebInspector._elementDraggingGlassPane) + WebInspector._elementDraggingGlassPane.parentElement.removeChild(WebInspector._elementDraggingGlassPane); + + delete WebInspector._elementDraggingGlassPane; + delete WebInspector._elementDraggingEventListener; + delete WebInspector._elementEndDraggingEventListener; + + event.preventDefault(); +} + +WebInspector.animateStyle = function(animations, duration, callback) +{ + var interval; + var complete = 0; + var hasCompleted = false; + + const intervalDuration = (1000 / 30); // 30 frames per second. + const animationsLength = animations.length; + const propertyUnit = {opacity: ""}; + const defaultUnit = "px"; + + function cubicInOut(t, b, c, d) + { + if ((t/=d/2) < 1) return c/2*t*t*t + b; + return c/2*((t-=2)*t*t + 2) + b; + } + + // Pre-process animations. + for (var i = 0; i < animationsLength; ++i) { + var animation = animations[i]; + var element = null, start = null, end = null, key = null; + for (key in animation) { + if (key === "element") + element = animation[key]; + else if (key === "start") + start = animation[key]; + else if (key === "end") + end = animation[key]; + } + + if (!element || !end) + continue; + + if (!start) { + var computedStyle = element.ownerDocument.defaultView.getComputedStyle(element); + start = {}; + for (key in end) + start[key] = parseInt(computedStyle.getPropertyValue(key), 10); + animation.start = start; + } else + for (key in start) + element.style.setProperty(key, start[key] + (key in propertyUnit ? propertyUnit[key] : defaultUnit)); + } + + function animateLoop() + { + if (hasCompleted) + return; + + // Advance forward. + complete += intervalDuration; + var next = complete + intervalDuration; + + // Make style changes. + for (var i = 0; i < animationsLength; ++i) { + var animation = animations[i]; + var element = animation.element; + var start = animation.start; + var end = animation.end; + if (!element || !end) + continue; + + var style = element.style; + for (key in end) { + var endValue = end[key]; + if (next < duration) { + var startValue = start[key]; + var newValue = cubicInOut(complete, startValue, endValue - startValue, duration); + style.setProperty(key, newValue + (key in propertyUnit ? propertyUnit[key] : defaultUnit)); + } else + style.setProperty(key, endValue + (key in propertyUnit ? propertyUnit[key] : defaultUnit)); + } + } + + // End condition. + if (complete >= duration) { + hasCompleted = true; + clearInterval(interval); + if (callback) + callback(); + } + } + + function forceComplete() + { + if (hasCompleted) + return; + + complete = duration; + animateLoop(); + } + + function cancel() + { + hasCompleted = true; + clearInterval(interval); + } + + interval = setInterval(animateLoop, intervalDuration); + return { + cancel: cancel, + forceComplete: forceComplete + }; +} + +WebInspector.isBeingEdited = function(element) +{ + return element.__editing; +} + +WebInspector.markBeingEdited = function(element, value) +{ + if (value) { + if (element.__editing) + return false; + element.__editing = true; + WebInspector.__editingCount = (WebInspector.__editingCount || 0) + 1; + } else { + if (!element.__editing) + return false; + delete element.__editing; + --WebInspector.__editingCount; + } + return true; +} + +WebInspector.isInEditMode = function(event) +{ + if (WebInspector.__editingCount > 0) + return true; + if (event.target.nodeName === "INPUT") + return true; + if (event.target.enclosingNodeOrSelfWithClass("text-prompt")) + return true; + return false; +} + +/** + * @constructor + * @param {function(Element,string,string,*,string)} commitHandler + * @param {function(Element,*)} cancelHandler + * @param {*=} context + */ +WebInspector.EditingConfig = function(commitHandler, cancelHandler, context) +{ + this.commitHandler = commitHandler; + this.cancelHandler = cancelHandler + this.context = context; + + /** + * Handles the "paste" event, return values are the same as those for customFinishHandler + * @type {function(Element)|undefined} + */ + this.pasteHandler; + + /** + * Whether the edited element is multiline + * @type {boolean|undefined} + */ + this.multiline; + + /** + * Custom finish handler for the editing session (invoked on keydown) + * @type {function(Element,*)|undefined} + */ + this.customFinishHandler; +} + +WebInspector.EditingConfig.prototype = { + setPasteHandler: function(pasteHandler) + { + this.pasteHandler = pasteHandler; + }, + + setMultiline: function(multiline) + { + this.multiline = multiline; + }, + + setCustomFinishHandler: function(customFinishHandler) + { + this.customFinishHandler = customFinishHandler; + } +} + +/** + * @param {Element} element + * @param {WebInspector.EditingConfig=} config + */ +WebInspector.startEditing = function(element, config) +{ + if (!WebInspector.markBeingEdited(element, true)) + return; + + config = config || new WebInspector.EditingConfig(function() {}, function() {}); + var committedCallback = config.commitHandler; + var cancelledCallback = config.cancelHandler; + var pasteCallback = config.pasteHandler; + var context = config.context; + var oldText = getContent(element); + var moveDirection = ""; + + element.addStyleClass("editing"); + + var oldTabIndex = element.tabIndex; + if (element.tabIndex < 0) + element.tabIndex = 0; + + function blurEventListener() { + editingCommitted.call(element); + } + + function getContent(element) { + if (element.tagName === "INPUT" && element.type === "text") + return element.value; + else + return element.textContent; + } + + /** @this {Element} */ + function cleanUpAfterEditing() + { + WebInspector.markBeingEdited(element, false); + + this.removeStyleClass("editing"); + this.tabIndex = oldTabIndex; + this.scrollTop = 0; + this.scrollLeft = 0; + + element.removeEventListener("blur", blurEventListener, false); + element.removeEventListener("keydown", keyDownEventListener, true); + if (pasteCallback) + element.removeEventListener("paste", pasteEventListener, true); + + WebInspector.restoreFocusFromElement(element); + } + + /** @this {Element} */ + function editingCancelled() + { + if (this.tagName === "INPUT" && this.type === "text") + this.value = oldText; + else + this.textContent = oldText; + + cleanUpAfterEditing.call(this); + + cancelledCallback(this, context); + } + + /** @this {Element} */ + function editingCommitted() + { + cleanUpAfterEditing.call(this); + + committedCallback(this, getContent(this), oldText, context, moveDirection); + } + + function defaultFinishHandler(event) + { + var isMetaOrCtrl = WebInspector.isMac() ? + event.metaKey && !event.shiftKey && !event.ctrlKey && !event.altKey : + event.ctrlKey && !event.shiftKey && !event.metaKey && !event.altKey; + if (isEnterKey(event) && (event.isMetaOrCtrlForTest || !config.multiline || isMetaOrCtrl)) + return "commit"; + else if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Esc.code || event.keyIdentifier === "U+001B") + return "cancel"; + else if (event.keyIdentifier === "U+0009") // Tab key + return "move-" + (event.shiftKey ? "backward" : "forward"); + } + + function handleEditingResult(result, event) + { + if (result === "commit") { + editingCommitted.call(element); + event.preventDefault(); + event.stopPropagation(); + } else if (result === "cancel") { + editingCancelled.call(element); + event.preventDefault(); + event.stopPropagation(); + } else if (result && result.indexOf("move-") === 0) { + moveDirection = result.substring(5); + if (event.keyIdentifier !== "U+0009") + blurEventListener(); + } + } + + function pasteEventListener(event) + { + var result = pasteCallback(event); + handleEditingResult(result, event); + } + + function keyDownEventListener(event) + { + var handler = config.customFinishHandler || defaultFinishHandler; + var result = handler(event); + handleEditingResult(result, event); + } + + element.addEventListener("blur", blurEventListener, false); + element.addEventListener("keydown", keyDownEventListener, true); + if (pasteCallback) + element.addEventListener("paste", pasteEventListener, true); + + WebInspector.setCurrentFocusElement(element); + return { + cancel: editingCancelled.bind(element), + commit: editingCommitted.bind(element) + }; +} + +/** + * @param {boolean=} higherResolution + */ +Number.secondsToString = function(seconds, higherResolution) +{ + if (seconds === 0) + return "0"; + + var ms = seconds * 1000; + if (higherResolution && ms < 1000) + return WebInspector.UIString("%.3fms", ms); + else if (ms < 1000) + return WebInspector.UIString("%.0fms", ms); + + if (seconds < 60) + return WebInspector.UIString("%.2fs", seconds); + + var minutes = seconds / 60; + if (minutes < 60) + return WebInspector.UIString("%.1fmin", minutes); + + var hours = minutes / 60; + if (hours < 24) + return WebInspector.UIString("%.1fhrs", hours); + + var days = hours / 24; + return WebInspector.UIString("%.1f days", days); +} + +/** + * @param {boolean=} higherResolution + */ +Number.bytesToString = function(bytes, higherResolution) +{ + if (typeof higherResolution === "undefined") + higherResolution = true; + + if (bytes < 1024) + return WebInspector.UIString("%.0fB", bytes); + + var kilobytes = bytes / 1024; + if (higherResolution && kilobytes < 1024) + return WebInspector.UIString("%.2fKB", kilobytes); + else if (kilobytes < 1024) + return WebInspector.UIString("%.0fKB", kilobytes); + + var megabytes = kilobytes / 1024; + if (higherResolution) + return WebInspector.UIString("%.2fMB", megabytes); + else + return WebInspector.UIString("%.0fMB", megabytes); +} + +WebInspector._missingLocalizedStrings = {}; + +/** + * @param {string} string + * @param {...*} vararg + */ +WebInspector.UIString = function(string, vararg) +{ + if (Preferences.localizeUI) { + if (window.localizedStrings && string in window.localizedStrings) + string = window.localizedStrings[string]; + else { + if (!(string in WebInspector._missingLocalizedStrings)) { + console.warn("Localized string \"" + string + "\" not found."); + WebInspector._missingLocalizedStrings[string] = true; + } + + if (Preferences.showMissingLocalizedStrings) + string += " (not localized)"; + } + } + return String.vsprintf(string, Array.prototype.slice.call(arguments, 1)); +} + +WebInspector.useLowerCaseMenuTitles = function() +{ + return WebInspector.platform() === "windows" && Preferences.useLowerCaseMenuTitlesOnWindows; +} + +WebInspector.formatLocalized = function(format, substitutions, formatters, initialValue, append) +{ + return String.format(WebInspector.UIString(format), substitutions, formatters, initialValue, append); +} + +WebInspector.openLinkExternallyLabel = function() +{ + return WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Open link in new tab" : "Open Link in New Tab"); +} + +WebInspector.openInNetworkPanelLabel = function() +{ + return WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Open in network panel" : "Open in Network Panel"); +} + +WebInspector.copyLinkAddressLabel = function() +{ + return WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Copy link address" : "Copy Link Address"); +} + +WebInspector.platform = function() +{ + if (!WebInspector._platform) + WebInspector._platform = InspectorFrontendHost.platform(); + return WebInspector._platform; +} + +WebInspector.isMac = function() +{ + if (typeof WebInspector._isMac === "undefined") + WebInspector._isMac = WebInspector.platform() === "mac"; + + return WebInspector._isMac; +} + +WebInspector.PlatformFlavor = { + WindowsVista: "windows-vista", + MacTiger: "mac-tiger", + MacLeopard: "mac-leopard", + MacSnowLeopard: "mac-snowleopard" +} + +WebInspector.platformFlavor = function() +{ + function detectFlavor() + { + const userAgent = navigator.userAgent; + + if (WebInspector.platform() === "windows") { + var match = userAgent.match(/Windows NT (\d+)\.(?:\d+)/); + if (match && match[1] >= 6) + return WebInspector.PlatformFlavor.WindowsVista; + return null; + } else if (WebInspector.platform() === "mac") { + var match = userAgent.match(/Mac OS X\s*(?:(\d+)_(\d+))?/); + if (!match || match[1] != 10) + return WebInspector.PlatformFlavor.MacSnowLeopard; + switch (Number(match[2])) { + case 4: + return WebInspector.PlatformFlavor.MacTiger; + case 5: + return WebInspector.PlatformFlavor.MacLeopard; + case 6: + default: + return WebInspector.PlatformFlavor.MacSnowLeopard; + } + } + } + + if (!WebInspector._platformFlavor) + WebInspector._platformFlavor = detectFlavor(); + + return WebInspector._platformFlavor; +} + +WebInspector.port = function() +{ + if (!WebInspector._port) + WebInspector._port = InspectorFrontendHost.port(); + + return WebInspector._port; +} + +WebInspector.installPortStyles = function() +{ + var platform = WebInspector.platform(); + document.body.addStyleClass("platform-" + platform); + var flavor = WebInspector.platformFlavor(); + if (flavor) + document.body.addStyleClass("platform-" + flavor); + var port = WebInspector.port(); + document.body.addStyleClass("port-" + port); +} + +WebInspector._windowFocused = function(event) +{ + if (event.target.document.nodeType === Node.DOCUMENT_NODE) + document.body.removeStyleClass("inactive"); +} + +WebInspector._windowBlurred = function(event) +{ + if (event.target.document.nodeType === Node.DOCUMENT_NODE) + document.body.addStyleClass("inactive"); +} + +WebInspector.previousFocusElement = function() +{ + return WebInspector._previousFocusElement; +} + +WebInspector.currentFocusElement = function() +{ + return WebInspector._currentFocusElement; +} + +WebInspector._focusChanged = function(event) +{ + WebInspector.setCurrentFocusElement(event.target); +} + +WebInspector._textInputTypes = ["text", "search", "tel", "url", "email", "password"].keySet(); +WebInspector._isTextEditingElement = function(element) +{ + if (element instanceof HTMLInputElement) + return element.type in WebInspector._textInputTypes; + + if (element instanceof HTMLTextAreaElement) + return true; + + return false; +} + +WebInspector.setCurrentFocusElement = function(x) +{ + if (WebInspector._currentFocusElement !== x) + WebInspector._previousFocusElement = WebInspector._currentFocusElement; + WebInspector._currentFocusElement = x; + + if (WebInspector._currentFocusElement) { + WebInspector._currentFocusElement.focus(); + + // Make a caret selection inside the new element if there isn't a range selection and there isn't already a caret selection inside. + // This is needed (at least) to remove caret from console when focus is moved to some element in the panel. + // The code below should not be applied to text fields and text areas, hence _isTextEditingElement check. + var selection = window.getSelection(); + if (!WebInspector._isTextEditingElement(WebInspector._currentFocusElement) && selection.isCollapsed && !WebInspector._currentFocusElement.isInsertionCaretInside()) { + var selectionRange = WebInspector._currentFocusElement.ownerDocument.createRange(); + selectionRange.setStart(WebInspector._currentFocusElement, 0); + selectionRange.setEnd(WebInspector._currentFocusElement, 0); + + selection.removeAllRanges(); + selection.addRange(selectionRange); + } + } else if (WebInspector._previousFocusElement) + WebInspector._previousFocusElement.blur(); +} + +WebInspector.restoreFocusFromElement = function(element) +{ + if (element && element.isSelfOrAncestor(WebInspector.currentFocusElement())) + WebInspector.setCurrentFocusElement(WebInspector.previousFocusElement()); +} + +WebInspector.setToolbarColors = function(backgroundColor, color) +{ + if (!WebInspector._themeStyleElement) { + WebInspector._themeStyleElement = document.createElement("style"); + document.head.appendChild(WebInspector._themeStyleElement); + } + WebInspector._themeStyleElement.textContent = + "#toolbar {\ + background-image: none !important;\ + background-color: " + backgroundColor + " !important;\ + }\ + \ + .toolbar-label {\ + color: " + color + " !important;\ + text-shadow: none;\ + }"; +} + +WebInspector.resetToolbarColors = function() +{ + if (WebInspector._themeStyleElement) + WebInspector._themeStyleElement.textContent = ""; +} + +/** + * @param {WebInspector.ContextMenu} contextMenu + * @param {Node} contextNode + * @param {Event} event + */ +WebInspector.populateHrefContextMenu = function(contextMenu, contextNode, event) +{ + var anchorElement = event.target.enclosingNodeOrSelfWithClass("webkit-html-resource-link") || event.target.enclosingNodeOrSelfWithClass("webkit-html-external-link"); + if (!anchorElement) + return false; + + var resourceURL = WebInspector.resourceURLForRelatedNode(contextNode, anchorElement.href); + if (!resourceURL) + return false; + + // Add resource-related actions. + contextMenu.appendItem(WebInspector.openLinkExternallyLabel(), WebInspector.openResource.bind(WebInspector, resourceURL, false)); + if (WebInspector.resourceForURL(resourceURL)) + contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Open link in Resources panel" : "Open Link in Resources Panel"), WebInspector.openResource.bind(null, resourceURL, true)); + contextMenu.appendItem(WebInspector.copyLinkAddressLabel(), InspectorFrontendHost.copyText.bind(InspectorFrontendHost, resourceURL)); + return true; +} + +;(function() { + +function windowLoaded() +{ + window.addEventListener("focus", WebInspector._windowFocused, false); + window.addEventListener("blur", WebInspector._windowBlurred, false); + document.addEventListener("focus", WebInspector._focusChanged.bind(this), true); + window.removeEventListener("DOMContentLoaded", windowLoaded, false); +} + +window.addEventListener("DOMContentLoaded", windowLoaded, false); + +})(); +/* InspectorBackend.js */ + +/* + * Copyright (C) 2011 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. + */ + +/** + * @constructor + */ +function InspectorBackendClass() +{ + this._lastCallbackId = 1; + this._pendingResponsesCount = 0; + this._callbacks = {}; + this._domainDispatchers = {}; + this._eventArgs = {}; + this._replyArgs = {}; + + this.dumpInspectorTimeStats = false; + this.dumpInspectorProtocolMessages = false; + this._initialized = false; +} + +InspectorBackendClass.prototype = { + _wrap: function(callback, method) + { + var callbackId = this._lastCallbackId++; + if (!callback) + callback = function() {}; + + this._callbacks[callbackId] = callback; + callback.methodName = method; + if (this.dumpInspectorTimeStats) + callback.sendRequestTime = Date.now(); + + return callbackId; + }, + + registerCommand: function(method, signature, replyArgs) + { + var domainAndMethod = method.split("."); + var agentName = domainAndMethod[0] + "Agent"; + if (!window[agentName]) + window[agentName] = {}; + + window[agentName][domainAndMethod[1]] = this._sendMessageToBackend.bind(this, method, signature); + window[agentName][domainAndMethod[1]]["invoke"] = this._invoke.bind(this, method, signature); + this._replyArgs[method] = replyArgs; + + this._initialized = true; + }, + + registerEvent: function(eventName, params) + { + this._eventArgs[eventName] = params; + + this._initialized = true; + }, + + _invoke: function(method, signature, args, callback) + { + this._wrapCallbackAndSendMessageObject(method, args, callback); + }, + + _sendMessageToBackend: function(method, signature, vararg) + { + var args = Array.prototype.slice.call(arguments, 2); + var callback = (args.length && typeof args[args.length - 1] === "function") ? args.pop() : null; + + var params = {}; + var hasParams = false; + for (var i = 0; i < signature.length; ++i) { + var param = signature[i]; + var paramName = param["name"]; + var typeName = param["type"]; + var optionalFlag = param["optional"]; + + if (!args.length && !optionalFlag) { + console.error("Protocol Error: Invalid number of arguments for method '" + method + "' call. It must have the following arguments '" + JSON.stringify(signature) + "'."); + return; + } + + var value = args.shift(); + if (optionalFlag && typeof value === "undefined") { + continue; + } + + if (typeof value !== typeName) { + console.error("Protocol Error: Invalid type of argument '" + paramName + "' for method '" + method + "' call. It must be '" + typeName + "' but it is '" + typeof value + "'."); + return; + } + + params[paramName] = value; + hasParams = true; + } + + if (args.length === 1 && !callback) { + if (typeof args[0] !== "undefined") { + console.error("Protocol Error: Optional callback argument for method '" + method + "' call must be a function but its type is '" + typeof args[0] + "'."); + return; + } + } + + this._wrapCallbackAndSendMessageObject(method, hasParams ? params : null, callback); + }, + + _wrapCallbackAndSendMessageObject: function(method, params, callback) + { + var messageObject = {}; + messageObject.method = method; + if (params) + messageObject.params = params; + messageObject.id = this._wrap(callback, method); + + if (this.dumpInspectorProtocolMessages) + console.log("frontend: " + JSON.stringify(messageObject)); + + ++this._pendingResponsesCount; + this.sendMessageObjectToBackend(messageObject); + }, + + sendMessageObjectToBackend: function(messageObject) + { + var message = JSON.stringify(messageObject); + InspectorFrontendHost.sendMessageToBackend(message); + }, + + registerDomainDispatcher: function(domain, dispatcher) + { + this._domainDispatchers[domain] = dispatcher; + }, + + dispatch: function(message) + { + if (this.dumpInspectorProtocolMessages) + console.log("backend: " + ((typeof message === "string") ? message : JSON.stringify(message))); + + var messageObject = (typeof message === "string") ? JSON.parse(message) : message; + + if ("id" in messageObject) { // just a response for some request + if (messageObject.error) { + messageObject.error.__proto__ = { + getDescription: function() + { + switch(this.code) { + case -32700: return "Parse error"; + case -32600: return "Invalid Request"; + case -32601: return "Method not found"; + case -32602: return "Invalid params"; + case -32603: return "Internal error";; + case -32000: return "Server error"; + } + }, + + toString: function() + { + var description ="Unknown error code"; + return this.getDescription() + "(" + this.code + "): " + this.message + "." + (this.data ? " " + this.data.join(" ") : ""); + }, + + getMessage: function() + { + return this.message; + } + } + + if (messageObject.error.code !== -32000) + this.reportProtocolError(messageObject); + } + + var callback = this._callbacks[messageObject.id]; + if (callback) { + var argumentsArray = []; + if (messageObject.result) { + var paramNames = this._replyArgs[callback.methodName]; + if (paramNames) { + for (var i = 0; i < paramNames.length; ++i) + argumentsArray.push(messageObject.result[paramNames[i]]); + } + } + + var processingStartTime; + if (this.dumpInspectorTimeStats && callback.methodName) + processingStartTime = Date.now(); + + argumentsArray.unshift(messageObject.error); + callback.apply(null, argumentsArray); + --this._pendingResponsesCount; + delete this._callbacks[messageObject.id]; + + if (this.dumpInspectorTimeStats && callback.methodName) + console.log("time-stats: " + callback.methodName + " = " + (processingStartTime - callback.sendRequestTime) + " + " + (Date.now() - processingStartTime)); + } + + if (this._scripts && !this._pendingResponsesCount) + this.runAfterPendingDispatches(); + + return; + } else { + var method = messageObject.method.split("."); + var domainName = method[0]; + var functionName = method[1]; + if (!(domainName in this._domainDispatchers)) { + console.error("Protocol Error: the message is for non-existing domain '" + domainName + "'"); + return; + } + var dispatcher = this._domainDispatchers[domainName]; + if (!(functionName in dispatcher)) { + console.error("Protocol Error: Attempted to dispatch an unimplemented method '" + messageObject.method + "'"); + return; + } + + if (!this._eventArgs[messageObject.method]) { + console.error("Protocol Error: Attempted to dispatch an unspecified method '" + messageObject.method + "'"); + return; + } + + var params = []; + if (messageObject.params) { + var paramNames = this._eventArgs[messageObject.method]; + for (var i = 0; i < paramNames.length; ++i) + params.push(messageObject.params[paramNames[i]]); + } + + var processingStartTime; + if (this.dumpInspectorTimeStats) + processingStartTime = Date.now(); + + dispatcher[functionName].apply(dispatcher, params); + + if (this.dumpInspectorTimeStats) + console.log("time-stats: " + messageObject.method + " = " + (Date.now() - processingStartTime)); + } + }, + + reportProtocolError: function(messageObject) + { + console.error("Request with id = " + messageObject.id + " failed. " + messageObject.error); + }, + + /** + * @param {string=} script + */ + runAfterPendingDispatches: function(script) + { + if (!this._scripts) + this._scripts = []; + + if (script) + this._scripts.push(script); + + if (!this._pendingResponsesCount) { + var scripts = this._scripts; + this._scripts = [] + for (var id = 0; id < scripts.length; ++id) + scripts[id].call(this); + } + }, + + loadFromJSONIfNeeded: function() + { + if (this._initialized) + return; + + var xhr = new XMLHttpRequest(); + xhr.open("GET", "../Inspector.json", false); + xhr.send(null); + + var schema = JSON.parse(xhr.responseText); + var jsTypes = { integer: "number", array: "object" }; + var rawTypes = {}; + + var domains = schema["domains"]; + for (var i = 0; i < domains.length; ++i) { + var domain = domains[i]; + for (var j = 0; domain.types && j < domain.types.length; ++j) { + var type = domain.types[j]; + rawTypes[domain.domain + "." + type.id] = jsTypes[type.type] || type.type; + } + } + + var result = []; + for (var i = 0; i < domains.length; ++i) { + var domain = domains[i]; + + var commands = domain["commands"] || []; + for (var j = 0; j < commands.length; ++j) { + var command = commands[j]; + var parameters = command["parameters"]; + var paramsText = []; + for (var k = 0; parameters && k < parameters.length; ++k) { + var parameter = parameters[k]; + + var type; + if (parameter.type) + type = jsTypes[parameter.type] || parameter.type; + else { + var ref = parameter["$ref"]; + if (ref.indexOf(".") !== -1) + type = rawTypes[ref]; + else + type = rawTypes[domain.domain + "." + ref]; + } + + var text = "{\"name\": \"" + parameter.name + "\", \"type\": \"" + type + "\", \"optional\": " + (parameter.optional ? "true" : "false") + "}"; + paramsText.push(text); + } + + var returnsText = []; + var returns = command["returns"] || []; + for (var k = 0; k < returns.length; ++k) { + var parameter = returns[k]; + returnsText.push("\"" + parameter.name + "\""); + } + result.push("InspectorBackend.registerCommand(\"" + domain.domain + "." + command.name + "\", [" + paramsText.join(", ") + "], [" + returnsText.join(", ") + "]);"); + } + + for (var j = 0; domain.events && j < domain.events.length; ++j) { + var event = domain.events[j]; + var paramsText = []; + for (var k = 0; event.parameters && k < event.parameters.length; ++k) { + var parameter = event.parameters[k]; + paramsText.push("\"" + parameter.name + "\""); + } + result.push("InspectorBackend.registerEvent(\"" + domain.domain + "." + event.name + "\", [" + paramsText.join(", ") + "]);"); + } + + result.push("InspectorBackend.register" + domain.domain + "Dispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, \"" + domain.domain + "\");"); + } + eval(result.join("\n")); + } +} + +InspectorBackend = new InspectorBackendClass(); +/* InspectorBackendStub.js */ + +// File is generated by WebCore/WebCore/inspector/CodeGeneratorInspector.py + +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +// Inspector. +InspectorBackend.registerInspectorDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Inspector"); +InspectorBackend.registerEvent("Inspector.evaluateForTestInFrontend", ["testCallId", "script"]); +InspectorBackend.registerEvent("Inspector.inspect", ["object", "hints"]); +InspectorBackend.registerEvent("Inspector.didCreateWorker", ["id", "url", "isShared"]); +InspectorBackend.registerEvent("Inspector.didDestroyWorker", ["id"]); +InspectorBackend.registerCommand("Inspector.enable", [], []); +InspectorBackend.registerCommand("Inspector.disable", [], []); + +// Memory. +InspectorBackend.registerMemoryDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Memory"); +InspectorBackend.registerCommand("Memory.getDOMNodeCount", [], ["domGroups", "strings"]); + +// Page. +InspectorBackend.registerPageDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Page"); +InspectorBackend.registerEvent("Page.domContentEventFired", ["timestamp"]); +InspectorBackend.registerEvent("Page.loadEventFired", ["timestamp"]); +InspectorBackend.registerEvent("Page.frameNavigated", ["frame"]); +InspectorBackend.registerEvent("Page.frameDetached", ["frameId"]); +InspectorBackend.registerCommand("Page.enable", [], []); +InspectorBackend.registerCommand("Page.disable", [], []); +InspectorBackend.registerCommand("Page.addScriptToEvaluateOnLoad", [{"name": "scriptSource", "type": "string", "optional": false}], ["identifier"]); +InspectorBackend.registerCommand("Page.removeScriptToEvaluateOnLoad", [{"name": "identifier", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("Page.reload", [{"name": "ignoreCache", "type": "boolean", "optional": true}, {"name": "scriptToEvaluateOnLoad", "type": "string", "optional": true}], []); +InspectorBackend.registerCommand("Page.navigate", [{"name": "url", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("Page.getCookies", [], ["cookies", "cookiesString"]); +InspectorBackend.registerCommand("Page.deleteCookie", [{"name": "cookieName", "type": "string", "optional": false}, {"name": "domain", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("Page.getResourceTree", [], ["frameTree"]); +InspectorBackend.registerCommand("Page.getResourceContent", [{"name": "frameId", "type": "string", "optional": false}, {"name": "url", "type": "string", "optional": false}], ["content", "base64Encoded"]); +InspectorBackend.registerCommand("Page.searchInResource", [{"name": "frameId", "type": "string", "optional": false}, {"name": "url", "type": "string", "optional": false}, {"name": "query", "type": "string", "optional": false}, {"name": "caseSensitive", "type": "boolean", "optional": true}, {"name": "isRegex", "type": "boolean", "optional": true}], ["result"]); +InspectorBackend.registerCommand("Page.searchInResources", [{"name": "text", "type": "string", "optional": false}, {"name": "caseSensitive", "type": "boolean", "optional": true}, {"name": "isRegex", "type": "boolean", "optional": true}], ["result"]); +InspectorBackend.registerCommand("Page.setDocumentContent", [{"name": "frameId", "type": "string", "optional": false}, {"name": "html", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("Page.setScreenSizeOverride", [{"name": "width", "type": "number", "optional": false}, {"name": "height", "type": "number", "optional": false}], []); + +// Runtime. +InspectorBackend.registerCommand("Runtime.evaluate", [{"name": "expression", "type": "string", "optional": false}, {"name": "objectGroup", "type": "string", "optional": true}, {"name": "includeCommandLineAPI", "type": "boolean", "optional": true}, {"name": "doNotPauseOnExceptions", "type": "boolean", "optional": true}, {"name": "frameId", "type": "string", "optional": true}, {"name": "returnByValue", "type": "boolean", "optional": true}], ["result", "wasThrown"]); +InspectorBackend.registerCommand("Runtime.callFunctionOn", [{"name": "objectId", "type": "string", "optional": false}, {"name": "functionDeclaration", "type": "string", "optional": false}, {"name": "arguments", "type": "object", "optional": true}, {"name": "returnByValue", "type": "boolean", "optional": true}], ["result", "wasThrown"]); +InspectorBackend.registerCommand("Runtime.getProperties", [{"name": "objectId", "type": "string", "optional": false}, {"name": "ownProperties", "type": "boolean", "optional": true}], ["result"]); +InspectorBackend.registerCommand("Runtime.releaseObject", [{"name": "objectId", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("Runtime.releaseObjectGroup", [{"name": "objectGroup", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("Runtime.run", [], []); + +// Console. +InspectorBackend.registerConsoleDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Console"); +InspectorBackend.registerEvent("Console.messageAdded", ["message"]); +InspectorBackend.registerEvent("Console.messageRepeatCountUpdated", ["count"]); +InspectorBackend.registerEvent("Console.messagesCleared", []); +InspectorBackend.registerCommand("Console.enable", [], []); +InspectorBackend.registerCommand("Console.disable", [], []); +InspectorBackend.registerCommand("Console.clearMessages", [], []); +InspectorBackend.registerCommand("Console.setMonitoringXHREnabled", [{"name": "enabled", "type": "boolean", "optional": false}], []); +InspectorBackend.registerCommand("Console.addInspectedNode", [{"name": "nodeId", "type": "number", "optional": false}], []); + +// Network. +InspectorBackend.registerNetworkDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Network"); +InspectorBackend.registerEvent("Network.requestWillBeSent", ["requestId", "frameId", "loaderId", "documentURL", "request", "timestamp", "initiator", "stackTrace", "redirectResponse"]); +InspectorBackend.registerEvent("Network.requestServedFromCache", ["requestId"]); +InspectorBackend.registerEvent("Network.responseReceived", ["requestId", "frameId", "loaderId", "timestamp", "type", "response"]); +InspectorBackend.registerEvent("Network.dataReceived", ["requestId", "timestamp", "dataLength", "encodedDataLength"]); +InspectorBackend.registerEvent("Network.loadingFinished", ["requestId", "timestamp"]); +InspectorBackend.registerEvent("Network.loadingFailed", ["requestId", "timestamp", "errorText", "canceled"]); +InspectorBackend.registerEvent("Network.requestServedFromMemoryCache", ["requestId", "frameId", "loaderId", "documentURL", "timestamp", "initiator", "resource"]); +InspectorBackend.registerEvent("Network.webSocketWillSendHandshakeRequest", ["requestId", "timestamp", "request"]); +InspectorBackend.registerEvent("Network.webSocketHandshakeResponseReceived", ["requestId", "timestamp", "response"]); +InspectorBackend.registerEvent("Network.webSocketCreated", ["requestId", "url"]); +InspectorBackend.registerEvent("Network.webSocketClosed", ["requestId", "timestamp"]); +InspectorBackend.registerCommand("Network.enable", [], []); +InspectorBackend.registerCommand("Network.disable", [], []); +InspectorBackend.registerCommand("Network.setUserAgentOverride", [{"name": "userAgent", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("Network.setExtraHTTPHeaders", [{"name": "headers", "type": "object", "optional": false}], []); +InspectorBackend.registerCommand("Network.getResponseBody", [{"name": "requestId", "type": "string", "optional": false}], ["body", "base64Encoded"]); +InspectorBackend.registerCommand("Network.canClearBrowserCache", [], ["result"]); +InspectorBackend.registerCommand("Network.clearBrowserCache", [], []); +InspectorBackend.registerCommand("Network.canClearBrowserCookies", [], ["result"]); +InspectorBackend.registerCommand("Network.clearBrowserCookies", [], []); +InspectorBackend.registerCommand("Network.setCacheDisabled", [{"name": "cacheDisabled", "type": "boolean", "optional": false}], []); + +// Database. +InspectorBackend.registerDatabaseDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Database"); +InspectorBackend.registerEvent("Database.addDatabase", ["database"]); +InspectorBackend.registerEvent("Database.sqlTransactionSucceeded", ["transactionId", "columnNames", "values"]); +InspectorBackend.registerEvent("Database.sqlTransactionFailed", ["transactionId", "sqlError"]); +InspectorBackend.registerCommand("Database.enable", [], []); +InspectorBackend.registerCommand("Database.disable", [], []); +InspectorBackend.registerCommand("Database.getDatabaseTableNames", [{"name": "databaseId", "type": "number", "optional": false}], ["tableNames"]); +InspectorBackend.registerCommand("Database.executeSQL", [{"name": "databaseId", "type": "number", "optional": false}, {"name": "query", "type": "string", "optional": false}], ["success", "transactionId"]); + +// IndexedDB. +InspectorBackend.registerIndexedDBDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "IndexedDB"); +InspectorBackend.registerEvent("IndexedDB.databaseNamesLoaded", ["requestId", "securityOriginWithDatabaseNames"]); +InspectorBackend.registerCommand("IndexedDB.enable", [], []); +InspectorBackend.registerCommand("IndexedDB.disable", [], []); +InspectorBackend.registerCommand("IndexedDB.requestDatabaseNamesForFrame", [{"name": "requestId", "type": "number", "optional": false}, {"name": "frameId", "type": "string", "optional": false}], []); + +// DOMStorage. +InspectorBackend.registerDOMStorageDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "DOMStorage"); +InspectorBackend.registerEvent("DOMStorage.addDOMStorage", ["storage"]); +InspectorBackend.registerEvent("DOMStorage.updateDOMStorage", ["storageId"]); +InspectorBackend.registerCommand("DOMStorage.enable", [], []); +InspectorBackend.registerCommand("DOMStorage.disable", [], []); +InspectorBackend.registerCommand("DOMStorage.getDOMStorageEntries", [{"name": "storageId", "type": "number", "optional": false}], ["entries"]); +InspectorBackend.registerCommand("DOMStorage.setDOMStorageItem", [{"name": "storageId", "type": "number", "optional": false}, {"name": "key", "type": "string", "optional": false}, {"name": "value", "type": "string", "optional": false}], ["success"]); +InspectorBackend.registerCommand("DOMStorage.removeDOMStorageItem", [{"name": "storageId", "type": "number", "optional": false}, {"name": "key", "type": "string", "optional": false}], ["success"]); + +// ApplicationCache. +InspectorBackend.registerApplicationCacheDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "ApplicationCache"); +InspectorBackend.registerEvent("ApplicationCache.applicationCacheStatusUpdated", ["frameId", "manifestURL", "status"]); +InspectorBackend.registerEvent("ApplicationCache.networkStateUpdated", ["isNowOnline"]); +InspectorBackend.registerCommand("ApplicationCache.getFramesWithManifests", [], ["frameIds"]); +InspectorBackend.registerCommand("ApplicationCache.enable", [], []); +InspectorBackend.registerCommand("ApplicationCache.getManifestForFrame", [{"name": "frameId", "type": "string", "optional": false}], ["manifestURL"]); +InspectorBackend.registerCommand("ApplicationCache.getApplicationCacheForFrame", [{"name": "frameId", "type": "string", "optional": false}], ["applicationCache"]); + +// FileSystem. +InspectorBackend.registerFileSystemDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "FileSystem"); +InspectorBackend.registerCommand("FileSystem.enable", [], []); +InspectorBackend.registerCommand("FileSystem.disable", [], []); + +// DOM. +InspectorBackend.registerDOMDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "DOM"); +InspectorBackend.registerEvent("DOM.documentUpdated", []); +InspectorBackend.registerEvent("DOM.setChildNodes", ["parentId", "nodes"]); +InspectorBackend.registerEvent("DOM.attributeModified", ["nodeId", "name", "value"]); +InspectorBackend.registerEvent("DOM.attributeRemoved", ["nodeId", "name"]); +InspectorBackend.registerEvent("DOM.inlineStyleInvalidated", ["nodeIds"]); +InspectorBackend.registerEvent("DOM.characterDataModified", ["nodeId", "characterData"]); +InspectorBackend.registerEvent("DOM.childNodeCountUpdated", ["nodeId", "childNodeCount"]); +InspectorBackend.registerEvent("DOM.childNodeInserted", ["parentNodeId", "previousNodeId", "node"]); +InspectorBackend.registerEvent("DOM.childNodeRemoved", ["parentNodeId", "nodeId"]); +InspectorBackend.registerCommand("DOM.getDocument", [], ["root"]); +InspectorBackend.registerCommand("DOM.requestChildNodes", [{"name": "nodeId", "type": "number", "optional": false}], []); +InspectorBackend.registerCommand("DOM.querySelector", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "selector", "type": "string", "optional": false}], ["nodeId"]); +InspectorBackend.registerCommand("DOM.querySelectorAll", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "selector", "type": "string", "optional": false}], ["nodeIds"]); +InspectorBackend.registerCommand("DOM.setNodeName", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "name", "type": "string", "optional": false}], ["nodeId"]); +InspectorBackend.registerCommand("DOM.setNodeValue", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "value", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("DOM.removeNode", [{"name": "nodeId", "type": "number", "optional": false}], []); +InspectorBackend.registerCommand("DOM.setAttributeValue", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "name", "type": "string", "optional": false}, {"name": "value", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("DOM.setAttributesAsText", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "text", "type": "string", "optional": false}, {"name": "name", "type": "string", "optional": true}], []); +InspectorBackend.registerCommand("DOM.removeAttribute", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "name", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("DOM.getEventListenersForNode", [{"name": "nodeId", "type": "number", "optional": false}], ["listeners"]); +InspectorBackend.registerCommand("DOM.getOuterHTML", [{"name": "nodeId", "type": "number", "optional": false}], ["outerHTML"]); +InspectorBackend.registerCommand("DOM.setOuterHTML", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "outerHTML", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("DOM.performSearch", [{"name": "query", "type": "string", "optional": false}], ["searchId", "resultCount"]); +InspectorBackend.registerCommand("DOM.getSearchResults", [{"name": "searchId", "type": "string", "optional": false}, {"name": "fromIndex", "type": "number", "optional": false}, {"name": "toIndex", "type": "number", "optional": false}], ["nodeIds"]); +InspectorBackend.registerCommand("DOM.discardSearchResults", [{"name": "searchId", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("DOM.requestNode", [{"name": "objectId", "type": "string", "optional": false}], ["nodeId"]); +InspectorBackend.registerCommand("DOM.setInspectModeEnabled", [{"name": "enabled", "type": "boolean", "optional": false}, {"name": "highlightConfig", "type": "object", "optional": true}], []); +InspectorBackend.registerCommand("DOM.highlightRect", [{"name": "x", "type": "number", "optional": false}, {"name": "y", "type": "number", "optional": false}, {"name": "width", "type": "number", "optional": false}, {"name": "height", "type": "number", "optional": false}, {"name": "color", "type": "object", "optional": true}, {"name": "outlineColor", "type": "object", "optional": true}], []); +InspectorBackend.registerCommand("DOM.highlightNode", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "highlightConfig", "type": "object", "optional": false}], []); +InspectorBackend.registerCommand("DOM.hideHighlight", [], []); +InspectorBackend.registerCommand("DOM.highlightFrame", [{"name": "frameId", "type": "string", "optional": false}, {"name": "contentColor", "type": "object", "optional": true}, {"name": "contentOutlineColor", "type": "object", "optional": true}], []); +InspectorBackend.registerCommand("DOM.pushNodeByPathToFrontend", [{"name": "path", "type": "string", "optional": false}], ["nodeId"]); +InspectorBackend.registerCommand("DOM.resolveNode", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "objectGroup", "type": "string", "optional": true}], ["object"]); +InspectorBackend.registerCommand("DOM.getAttributes", [{"name": "nodeId", "type": "number", "optional": false}], ["attributes"]); +InspectorBackend.registerCommand("DOM.moveTo", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "targetNodeId", "type": "number", "optional": false}, {"name": "insertBeforeNodeId", "type": "number", "optional": true}], ["nodeId"]); + +// CSS. +InspectorBackend.registerCSSDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "CSS"); +InspectorBackend.registerEvent("CSS.mediaQueryResultChanged", []); +InspectorBackend.registerCommand("CSS.enable", [], []); +InspectorBackend.registerCommand("CSS.disable", [], []); +InspectorBackend.registerCommand("CSS.getMatchedStylesForNode", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "forcedPseudoClasses", "type": "object", "optional": true}, {"name": "includePseudo", "type": "boolean", "optional": true}, {"name": "includeInherited", "type": "boolean", "optional": true}], ["matchedCSSRules", "pseudoElements", "inherited"]); +InspectorBackend.registerCommand("CSS.getInlineStylesForNode", [{"name": "nodeId", "type": "number", "optional": false}], ["inlineStyle", "styleAttributes"]); +InspectorBackend.registerCommand("CSS.getComputedStyleForNode", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "forcedPseudoClasses", "type": "object", "optional": true}], ["computedStyle"]); +InspectorBackend.registerCommand("CSS.getAllStyleSheets", [], ["headers"]); +InspectorBackend.registerCommand("CSS.getStyleSheet", [{"name": "styleSheetId", "type": "string", "optional": false}], ["styleSheet"]); +InspectorBackend.registerCommand("CSS.getStyleSheetText", [{"name": "styleSheetId", "type": "string", "optional": false}], ["text"]); +InspectorBackend.registerCommand("CSS.setStyleSheetText", [{"name": "styleSheetId", "type": "string", "optional": false}, {"name": "text", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("CSS.setPropertyText", [{"name": "styleId", "type": "object", "optional": false}, {"name": "propertyIndex", "type": "number", "optional": false}, {"name": "text", "type": "string", "optional": false}, {"name": "overwrite", "type": "boolean", "optional": false}], ["style"]); +InspectorBackend.registerCommand("CSS.toggleProperty", [{"name": "styleId", "type": "object", "optional": false}, {"name": "propertyIndex", "type": "number", "optional": false}, {"name": "disable", "type": "boolean", "optional": false}], ["style"]); +InspectorBackend.registerCommand("CSS.setRuleSelector", [{"name": "ruleId", "type": "object", "optional": false}, {"name": "selector", "type": "string", "optional": false}], ["rule"]); +InspectorBackend.registerCommand("CSS.addRule", [{"name": "contextNodeId", "type": "number", "optional": false}, {"name": "selector", "type": "string", "optional": false}], ["rule"]); +InspectorBackend.registerCommand("CSS.getSupportedCSSProperties", [], ["cssProperties"]); +InspectorBackend.registerCommand("CSS.startSelectorProfiler", [], []); +InspectorBackend.registerCommand("CSS.stopSelectorProfiler", [], ["profile"]); + +// Timeline. +InspectorBackend.registerTimelineDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Timeline"); +InspectorBackend.registerEvent("Timeline.eventRecorded", ["record"]); +InspectorBackend.registerCommand("Timeline.start", [{"name": "maxCallStackDepth", "type": "number", "optional": true}], []); +InspectorBackend.registerCommand("Timeline.stop", [], []); + +// Debugger. +InspectorBackend.registerDebuggerDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Debugger"); +InspectorBackend.registerEvent("Debugger.globalObjectCleared", []); +InspectorBackend.registerEvent("Debugger.scriptParsed", ["scriptId", "url", "startLine", "startColumn", "endLine", "endColumn", "isContentScript", "sourceMapURL"]); +InspectorBackend.registerEvent("Debugger.scriptFailedToParse", ["url", "scriptSource", "startLine", "errorLine", "errorMessage"]); +InspectorBackend.registerEvent("Debugger.breakpointResolved", ["breakpointId", "location"]); +InspectorBackend.registerEvent("Debugger.paused", ["callFrames", "reason", "data"]); +InspectorBackend.registerEvent("Debugger.resumed", []); +InspectorBackend.registerCommand("Debugger.causesRecompilation", [], ["result"]); +InspectorBackend.registerCommand("Debugger.supportsNativeBreakpoints", [], ["result"]); +InspectorBackend.registerCommand("Debugger.enable", [], []); +InspectorBackend.registerCommand("Debugger.disable", [], []); +InspectorBackend.registerCommand("Debugger.setBreakpointsActive", [{"name": "active", "type": "boolean", "optional": false}], []); +InspectorBackend.registerCommand("Debugger.setBreakpointByUrl", [{"name": "lineNumber", "type": "number", "optional": false}, {"name": "url", "type": "string", "optional": true}, {"name": "urlRegex", "type": "string", "optional": true}, {"name": "columnNumber", "type": "number", "optional": true}, {"name": "condition", "type": "string", "optional": true}], ["breakpointId", "locations"]); +InspectorBackend.registerCommand("Debugger.setBreakpoint", [{"name": "location", "type": "object", "optional": false}, {"name": "condition", "type": "string", "optional": true}], ["breakpointId", "actualLocation"]); +InspectorBackend.registerCommand("Debugger.removeBreakpoint", [{"name": "breakpointId", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("Debugger.continueToLocation", [{"name": "location", "type": "object", "optional": false}], []); +InspectorBackend.registerCommand("Debugger.stepOver", [], []); +InspectorBackend.registerCommand("Debugger.stepInto", [], []); +InspectorBackend.registerCommand("Debugger.stepOut", [], []); +InspectorBackend.registerCommand("Debugger.pause", [], []); +InspectorBackend.registerCommand("Debugger.resume", [], []); +InspectorBackend.registerCommand("Debugger.searchInContent", [{"name": "scriptId", "type": "string", "optional": false}, {"name": "query", "type": "string", "optional": false}, {"name": "caseSensitive", "type": "boolean", "optional": true}, {"name": "isRegex", "type": "boolean", "optional": true}], ["result"]); +InspectorBackend.registerCommand("Debugger.canSetScriptSource", [], ["result"]); +InspectorBackend.registerCommand("Debugger.setScriptSource", [{"name": "scriptId", "type": "string", "optional": false}, {"name": "scriptSource", "type": "string", "optional": false}, {"name": "preview", "type": "boolean", "optional": true}], ["callFrames", "result"]); +InspectorBackend.registerCommand("Debugger.getScriptSource", [{"name": "scriptId", "type": "string", "optional": false}], ["scriptSource"]); +InspectorBackend.registerCommand("Debugger.getFunctionLocation", [{"name": "functionId", "type": "string", "optional": false}], ["location"]); +InspectorBackend.registerCommand("Debugger.setPauseOnExceptions", [{"name": "state", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("Debugger.evaluateOnCallFrame", [{"name": "callFrameId", "type": "string", "optional": false}, {"name": "expression", "type": "string", "optional": false}, {"name": "objectGroup", "type": "string", "optional": true}, {"name": "includeCommandLineAPI", "type": "boolean", "optional": true}, {"name": "returnByValue", "type": "boolean", "optional": true}], ["result", "wasThrown"]); + +// DOMDebugger. +InspectorBackend.registerCommand("DOMDebugger.setDOMBreakpoint", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "type", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("DOMDebugger.removeDOMBreakpoint", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "type", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("DOMDebugger.setEventListenerBreakpoint", [{"name": "eventName", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("DOMDebugger.removeEventListenerBreakpoint", [{"name": "eventName", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("DOMDebugger.setXHRBreakpoint", [{"name": "url", "type": "string", "optional": false}], []); +InspectorBackend.registerCommand("DOMDebugger.removeXHRBreakpoint", [{"name": "url", "type": "string", "optional": false}], []); + +// Profiler. +InspectorBackend.registerProfilerDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Profiler"); +InspectorBackend.registerEvent("Profiler.addProfileHeader", ["header"]); +InspectorBackend.registerEvent("Profiler.addHeapSnapshotChunk", ["uid", "chunk"]); +InspectorBackend.registerEvent("Profiler.finishHeapSnapshot", ["uid"]); +InspectorBackend.registerEvent("Profiler.setRecordingProfile", ["isProfiling"]); +InspectorBackend.registerEvent("Profiler.resetProfiles", []); +InspectorBackend.registerEvent("Profiler.reportHeapSnapshotProgress", ["done", "total"]); +InspectorBackend.registerCommand("Profiler.causesRecompilation", [], ["result"]); +InspectorBackend.registerCommand("Profiler.isSampling", [], ["result"]); +InspectorBackend.registerCommand("Profiler.hasHeapProfiler", [], ["result"]); +InspectorBackend.registerCommand("Profiler.enable", [], []); +InspectorBackend.registerCommand("Profiler.disable", [], []); +InspectorBackend.registerCommand("Profiler.start", [], []); +InspectorBackend.registerCommand("Profiler.stop", [], []); +InspectorBackend.registerCommand("Profiler.getProfileHeaders", [], ["headers"]); +InspectorBackend.registerCommand("Profiler.getProfile", [{"name": "type", "type": "string", "optional": false}, {"name": "uid", "type": "number", "optional": false}], ["profile"]); +InspectorBackend.registerCommand("Profiler.removeProfile", [{"name": "type", "type": "string", "optional": false}, {"name": "uid", "type": "number", "optional": false}], []); +InspectorBackend.registerCommand("Profiler.clearProfiles", [], []); +InspectorBackend.registerCommand("Profiler.takeHeapSnapshot", [], []); +InspectorBackend.registerCommand("Profiler.collectGarbage", [], []); +InspectorBackend.registerCommand("Profiler.getObjectByHeapObjectId", [{"name": "objectId", "type": "number", "optional": false}], ["result"]); + +// Worker. +InspectorBackend.registerWorkerDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Worker"); +InspectorBackend.registerEvent("Worker.workerCreated", ["workerId", "url", "inspectorConnected"]); +InspectorBackend.registerEvent("Worker.workerTerminated", ["workerId"]); +InspectorBackend.registerEvent("Worker.dispatchMessageFromWorker", ["workerId", "message"]); +InspectorBackend.registerEvent("Worker.disconnectedFromWorker", []); +InspectorBackend.registerCommand("Worker.setWorkerInspectionEnabled", [{"name": "value", "type": "boolean", "optional": false}], []); +InspectorBackend.registerCommand("Worker.sendMessageToWorker", [{"name": "workerId", "type": "number", "optional": false}, {"name": "message", "type": "object", "optional": false}], []); +InspectorBackend.registerCommand("Worker.connectToWorker", [{"name": "workerId", "type": "number", "optional": false}], []); +InspectorBackend.registerCommand("Worker.disconnectFromWorker", [{"name": "workerId", "type": "number", "optional": false}], []); +InspectorBackend.registerCommand("Worker.setAutoconnectToWorkers", [{"name": "value", "type": "boolean", "optional": false}], []); + + +/* ExtensionRegistryStub.js */ + +/* + * 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. + * * 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. + */ + +if (!window.InspectorExtensionRegistry) { + +/** + * @constructor + */ +WebInspector.InspectorExtensionRegistryStub = function() +{ +} + +WebInspector.InspectorExtensionRegistryStub.prototype = { + getExtensionsAsync: function() + { + } +} + +var InspectorExtensionRegistry = new WebInspector.InspectorExtensionRegistryStub(); + +} +/* InspectorFrontendAPI.js */ + +/* + * Copyright (C) 2011 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. + */ + +InspectorFrontendAPI = { + _pendingCommands: [], + + isDebuggingEnabled: function() + { + return WebInspector.panels.scripts.debuggingEnabled; + }, + + setDebuggingEnabled: function(enabled) + { + if (enabled) { + WebInspector.panels.scripts.enableDebugging(); + WebInspector.inspectorView.setCurrentPanel(WebInspector.panels.scripts); + } else + WebInspector.panels.scripts.disableDebugging(); + }, + + isTimelineProfilingEnabled: function() + { + return WebInspector.panels.timeline.timelineProfilingEnabled; + }, + + setTimelineProfilingEnabled: function(enabled) + { + WebInspector.panels.timeline.setTimelineProfilingEnabled(enabled); + }, + + isProfilingJavaScript: function() + { + return WebInspector.CPUProfileType.instance && WebInspector.CPUProfileType.instance.isRecordingProfile(); + }, + + startProfilingJavaScript: function() + { + WebInspector.panels.profiles.enableProfiler(); + WebInspector.inspectorView.setCurrentPanel(WebInspector.panels.profiles); + if (WebInspector.CPUProfileType.instance) + WebInspector.CPUProfileType.instance.startRecordingProfile(); + }, + + stopProfilingJavaScript: function() + { + if (WebInspector.CPUProfileType.instance) + WebInspector.CPUProfileType.instance.stopRecordingProfile(); + WebInspector.inspectorView.setCurrentPanel(WebInspector.panels.profiles); + }, + + setAttachedWindow: function(attached) + { + WebInspector.attached = attached; + }, + + showConsole: function() + { + WebInspector.inspectorView.setCurrentPanel(WebInspector.panels.console); + }, + + dispatch: function(signature) + { + if (WebInspector.panels) { + var methodName = signature.shift(); + return InspectorFrontendAPI[methodName].apply(InspectorFrontendAPI, signature); + } + InspectorFrontendAPI._pendingCommands.push(signature); + }, + + loadCompleted: function() + { + for (var i = 0; i < InspectorFrontendAPI._pendingCommands.length; ++i) + InspectorFrontendAPI.dispatch(InspectorFrontendAPI._pendingCommands[i]); + InspectorFrontendAPI._pendingCommands = []; + } +} +/* Object.js */ + +/* + * Copyright (C) 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 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 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. + */ + +/** + * @constructor + */ +WebInspector.Object = function() { +} + +WebInspector.Object.prototype = { + /** + * @param {string} eventType + * @param {function(WebInspector.Event)} listener + * @param {Object=} thisObject + */ + addEventListener: function(eventType, listener, thisObject) + { + console.assert(listener); + + if (!this._listeners) + this._listeners = {}; + if (!this._listeners[eventType]) + this._listeners[eventType] = []; + this._listeners[eventType].push({ thisObject: thisObject, listener: listener }); + }, + + /** + * @param {string} eventType + * @param {function(WebInspector.Event)} listener + * @param {Object=} thisObject + */ + removeEventListener: function(eventType, listener, thisObject) + { + console.assert(listener); + + if (!this._listeners || !this._listeners[eventType]) + return; + var listeners = this._listeners[eventType]; + for (var i = 0; i < listeners.length; ++i) { + if (listener && listeners[i].listener === listener && listeners[i].thisObject === thisObject) + listeners.splice(i, 1); + else if (!listener && thisObject && listeners[i].thisObject === thisObject) + listeners.splice(i, 1); + } + + if (!listeners.length) + delete this._listeners[eventType]; + }, + + removeAllListeners: function() + { + delete this._listeners; + }, + + /** + * @param {string} eventType + * @return {boolean} + */ + hasEventListeners: function(eventType) + { + if (!this._listeners || !this._listeners[eventType]) + return false; + return true; + }, + + /** + * @param {string} eventType + * @param {*=} eventData + * @return {boolean} + */ + dispatchEventToListeners: function(eventType, eventData) + { + if (!this._listeners || !this._listeners[eventType]) + return false; + + var event = new WebInspector.Event(this, eventType, eventData); + var listeners = this._listeners[eventType].slice(0); + for (var i = 0; i < listeners.length; ++i) { + listeners[i].listener.call(listeners[i].thisObject, event); + if (event._stoppedPropagation) + break; + } + + return event.defaultPrevented; + } +} + +/** + * @constructor + * @param {WebInspector.Object} target + * @param {string} type + * @param {*=} data + */ +WebInspector.Event = function(target, type, data) +{ + this.target = target; + this.type = type; + this.data = data; + this.defaultPrevented = false; + this._stoppedPropagation = false; +} + +WebInspector.Event.prototype = { + stopPropagation: function() + { + this._stoppedPropagation = true; + }, + + preventDefault: function() + { + this.defaultPrevented = true; + } +} + +WebInspector.notifications = new WebInspector.Object(); +/* Settings.js */ + +/* + * 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. + */ + + +var Preferences = { + maxInlineTextChildLength: 80, + minConsoleHeight: 75, + minSidebarWidth: 100, + minElementsSidebarWidth: 200, + minScriptsSidebarWidth: 200, + styleRulesExpandedState: {}, + showMissingLocalizedStrings: false, + useLowerCaseMenuTitlesOnWindows: false, + sharedWorkersDebugNote: undefined, + localizeUI: true, + exposeDisableCache: false, + exposeWorkersInspection: false, + applicationTitle: "Web Inspector - %s", + showHeapSnapshotObjectsHiddenProperties: false, + showDockToRight: false +} + +var Capabilities = { + samplingCPUProfiler: false, + debuggerCausesRecompilation: true, + profilerCausesRecompilation: true, + nativeInstrumentationEnabled: false, + heapProfilerPresent: false +} + +/** + * @constructor + */ +WebInspector.Settings = function() +{ + this._eventSupport = new WebInspector.Object(); + + this.colorFormat = this.createSetting("colorFormat", "hex"); + this.consoleHistory = this.createSetting("consoleHistory", []); + this.debuggerEnabled = this.createSetting("debuggerEnabled", false); + this.domWordWrap = this.createSetting("domWordWrap", true); + this.profilerEnabled = this.createSetting("profilerEnabled", false); + this.eventListenersFilter = this.createSetting("eventListenersFilter", "all"); + this.lastActivePanel = this.createSetting("lastActivePanel", "elements"); + this.lastViewedScriptFile = this.createSetting("lastViewedScriptFile", "application"); + this.monitoringXHREnabled = this.createSetting("monitoringXHREnabled", false); + this.preserveConsoleLog = this.createSetting("preserveConsoleLog", false); + this.resourcesLargeRows = this.createSetting("resourcesLargeRows", true); + this.resourcesSortOptions = this.createSetting("resourcesSortOptions", {timeOption: "responseTime", sizeOption: "transferSize"}); + this.resourceViewTab = this.createSetting("resourceViewTab", "preview"); + this.showInheritedComputedStyleProperties = this.createSetting("showInheritedComputedStyleProperties", false); + this.showUserAgentStyles = this.createSetting("showUserAgentStyles", true); + this.watchExpressions = this.createSetting("watchExpressions", []); + this.breakpoints = this.createSetting("breakpoints", []); + this.eventListenerBreakpoints = this.createSetting("eventListenerBreakpoints", []); + this.domBreakpoints = this.createSetting("domBreakpoints", []); + this.xhrBreakpoints = this.createSetting("xhrBreakpoints", []); + this.sourceMapsEnabled = this.createSetting("sourceMapsEnabled", false); + this.cacheDisabled = this.createSetting("cacheDisabled", false); + this.overrideUserAgent = this.createSetting("overrideUserAgent", ""); + this.userAgent = this.createSetting("userAgent", ""); + this.showScriptFolders = this.createSetting("showScriptFolders", true); + this.dockToRight = this.createSetting("dockToRight", false); + + // If there are too many breakpoints in a storage, it is likely due to a recent bug that caused + // periodical breakpoints duplication leading to inspector slowness. + if (window.localStorage.breakpoints && window.localStorage.breakpoints.length > 500000) + delete window.localStorage.breakpoints; +} + +WebInspector.Settings.prototype = { + /** + * @return {WebInspector.Setting} + */ + createSetting: function(key, defaultValue) + { + return new WebInspector.Setting(key, defaultValue, this._eventSupport); + } +} + +/** + * @constructor + */ +WebInspector.Setting = function(name, defaultValue, eventSupport) +{ + this._name = name; + this._defaultValue = defaultValue; + this._eventSupport = eventSupport; +} + +WebInspector.Setting.prototype = { + addChangeListener: function(listener, thisObject) + { + this._eventSupport.addEventListener(this._name, listener, thisObject); + }, + + removeChangeListener: function(listener, thisObject) + { + this._eventSupport.removeEventListener(this._name, listener, thisObject); + }, + + get name() + { + return this._name; + }, + + get: function() + { + var value = this._defaultValue; + if (window.localStorage != null && this._name in window.localStorage) { + try { + value = JSON.parse(window.localStorage[this._name]); + } catch(e) { + window.localStorage.removeItem(this._name); + } + } + return value; + }, + + set: function(value) + { + if (window.localStorage != null) { + try { + window.localStorage[this._name] = JSON.stringify(value); + } catch(e) { + console.error("Error saving setting with name:" + this._name); + } + } + this._eventSupport.dispatchEventToListeners(this._name, value); + } +} + +/** + * @constructor + */ +WebInspector.ExperimentsSettings = function() +{ + this._setting = WebInspector.settings.createSetting("experiments", {}); + this._experiments = []; + this._enabledForTest = {}; + + // Add currently running experiments here. + // FIXME: Move out from experiments once navigator is production-ready. + this.useScriptsNavigator = this._createExperiment("useScriptsNavigator", "Use file navigator and tabbed editor container in scripts panel"); + this.sourceFrameAlwaysEditable = this._createExperiment("sourceFrameAlwaysEditable", "Make resources always editable"); + this.freeFlowDOMEditing = this._createExperiment("freeFlowDOMEditing", "Enable free flow DOM editing"); + + this._cleanUpSetting(); +} + +WebInspector.ExperimentsSettings.prototype = { + /** + * @type {Array.} + */ + get experiments() + { + return this._experiments.slice(); + }, + + /** + * @type {boolean} + */ + get experimentsEnabled() + { + return "experiments" in WebInspector.queryParamsObject; + }, + + /** + * @param {string} experimentName + * @param {string} experimentTitle + * @return {WebInspector.Experiment} + */ + _createExperiment: function(experimentName, experimentTitle) + { + var experiment = new WebInspector.Experiment(this, experimentName, experimentTitle); + this._experiments.push(experiment); + return experiment; + }, + + /** + * @param {string} experimentName + * @return {boolean} + */ + isEnabled: function(experimentName) + { + if (this._enabledForTest[experimentName]) + return true; + + if (!this.experimentsEnabled) + return false; + + var experimentsSetting = this._setting.get(); + return experimentsSetting[experimentName]; + }, + + /** + * @param {string} experimentName + * @param {boolean} enabled + */ + setEnabled: function(experimentName, enabled) + { + var experimentsSetting = this._setting.get(); + experimentsSetting[experimentName] = enabled; + this._setting.set(experimentsSetting); + }, + + /** + * @param {string} experimentName + */ + _enableForTest: function(experimentName) + { + this._enabledForTest[experimentName] = true; + }, + + _cleanUpSetting: function() + { + var experimentsSetting = this._setting.get(); + var cleanedUpExperimentSetting = {}; + for (var i = 0; i < this._experiments.length; ++i) { + var experimentName = this._experiments[i].name; + if (experimentsSetting[experimentName]) + cleanedUpExperimentSetting[experimentName] = true; + } + this._setting.set(cleanedUpExperimentSetting); + } +} + +/** + * @constructor + * @param {WebInspector.ExperimentsSettings} experimentsSettings + * @param {string} name + * @param {string} title + */ +WebInspector.Experiment = function(experimentsSettings, name, title) +{ + this._name = name; + this._title = title; + this._experimentsSettings = experimentsSettings; +} + +WebInspector.Experiment.prototype = { + /** + * @return {string} + */ + get name() + { + return this._name; + }, + + /** + * @return {string} + */ + get title() + { + return this._title; + }, + + /** + * @return {boolean} + */ + isEnabled: function() + { + return this._experimentsSettings.isEnabled(this._name); + }, + + /** + * @param {boolean} enabled + */ + setEnabled: function(enabled) + { + return this._experimentsSettings.setEnabled(this._name, enabled); + }, + + enableForTest: function() + { + this._experimentsSettings._enableForTest(this._name); + } +} + +WebInspector.settings = new WebInspector.Settings(); +WebInspector.experimentsSettings = new WebInspector.ExperimentsSettings(); +/* InspectorFrontendHostStub.js */ + +/* + * 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. + */ + +if (!window.InspectorFrontendHost) { + +/** + * @constructor + */ +WebInspector.InspectorFrontendHostStub = function() +{ + this._attachedWindowHeight = 0; +} + +WebInspector.InspectorFrontendHostStub.prototype = { + platform: function() + { + var match = navigator.userAgent.match(/Windows NT/); + if (match) + return "windows"; + match = navigator.userAgent.match(/Mac OS X/); + if (match) + return "mac"; + return "linux"; + }, + + port: function() + { + return "unknown"; + }, + + bringToFront: function() + { + this._windowVisible = true; + }, + + closeWindow: function() + { + this._windowVisible = false; + }, + + requestAttachWindow: function() + { + }, + + requestDetachWindow: function() + { + }, + + requestSetDockSide: function() + { + }, + + search: function(sourceRow, query) + { + }, + + setAttachedWindowHeight: function(height) + { + }, + + moveWindowBy: function(x, y) + { + }, + + setInjectedScriptForOrigin: function(origin, script) + { + }, + + loaded: function() + { + }, + + localizedStringsURL: function() + { + return undefined; + }, + + hiddenPanels: function() + { + return ""; + }, + + inspectedURLChanged: function(url) + { + document.title = WebInspector.UIString(Preferences.applicationTitle, url); + }, + + copyText: function() + { + }, + + openInNewTab: function(url) + { + window.open(url, "_blank"); + }, + + canSaveAs: function(fileName, content) + { + return true; + }, + + saveAs: function(fileName, content) + { + var builder = new WebKitBlobBuilder(); + builder.append(content); + var blob = builder.getBlob("application/octet-stream"); + + var fr = new FileReader(); + fr.onload = function(e) { + // Force download + window.location = this.result; + } + fr.readAsDataURL(blob); + }, + + canAttachWindow: function() + { + return false; + }, + + sendMessageToBackend: function(message) + { + }, + + recordActionTaken: function(actionCode) + { + }, + + recordPanelShown: function(panelCode) + { + }, + + recordSettingChanged: function(settingCode) + { + }, + + loadResourceSynchronously: function(url) + { + return ""; + } +} + +var InspectorFrontendHost = new WebInspector.InspectorFrontendHostStub(); +Preferences.localizeUI = false; + +} +/* Checkbox.js */ + +/* + * 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: + * 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 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 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. + */ + +/** + * @constructor + * @param {string=} tooltip + */ +WebInspector.Checkbox = function(label, className, tooltip) +{ + this.element = document.createElement('label'); + this._inputElement = document.createElement('input'); + this._inputElement.type = "checkbox"; + + this.element.className = className; + this.element.appendChild(this._inputElement); + this.element.appendChild(document.createTextNode(label)); + if (tooltip) + this.element.title = tooltip; +} + +WebInspector.Checkbox.prototype = { + set checked(checked) + { + this._inputElement.checked = checked; + }, + + get checked() + { + return this._inputElement.checked; + }, + + addEventListener: function(listener) + { + function listenerWrapper(event) + { + if (listener) + listener(event); + event.stopPropagation(); + return true; + } + + this._inputElement.addEventListener("click", listenerWrapper, false); + this.element.addEventListener("click", listenerWrapper, false); + } +} +/* ContextMenu.js */ + +/* + * 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. + */ + +/** + * @constructor + */ +WebInspector.ContextMenu = function() { + this._items = []; + this._handlers = {}; +} + +WebInspector.ContextMenu.prototype = { + show: function(event) + { + // Remove trailing separator. + while (this._items.length > 0 && !("id" in this._items[this._items.length - 1])) + this._items.splice(this._items.length - 1, 1); + + if (this._items.length) { + WebInspector._contextMenu = this; + InspectorFrontendHost.showContextMenu(event, this._items); + } + event.stopPropagation(); + }, + + /** + * @param {boolean=} disabled + */ + appendItem: function(label, handler, disabled) + { + var id = this._items.length; + this._items.push({type: "item", id: id, label: label, enabled: !disabled}); + this._handlers[id] = handler; + }, + + /** + * @param {boolean=} disabled + */ + appendCheckboxItem: function(label, handler, checked, disabled) + { + var id = this._items.length; + this._items.push({type: "checkbox", id: id, label: label, checked: !!checked, enabled: !disabled}); + this._handlers[id] = handler; + }, + + appendSeparator: function() + { + // No separator dupes allowed. + if (this._items.length === 0) + return; + if (!("id" in this._items[this._items.length - 1])) + return; + this._items.push({type: "separator"}); + }, + + _itemSelected: function(id) + { + if (this._handlers[id]) + this._handlers[id].call(this); + } +} + +WebInspector.contextMenuItemSelected = function(id) +{ + if (WebInspector._contextMenu) + WebInspector._contextMenu._itemSelected(id); +} + +WebInspector.contextMenuCleared = function() +{ + // FIXME: Unfortunately, contextMenuCleared is invoked between show and item selected + // so we can't delete last menu object from WebInspector. Fix the contract. +} +/* SoftContextMenu.js */ + +/* + * Copyright (C) 2011 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: + * 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 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 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. + */ + +if (!InspectorFrontendHost.showContextMenu) { + +/** + * @constructor + */ +WebInspector.SoftContextMenu = function(items) +{ + this._items = items; +} + +WebInspector.SoftContextMenu.prototype = { + show: function(event) + { + this._x = event.x; + this._y = event.y; + this._time = new Date().getTime(); + + // Absolutely position menu for iframes. + var absoluteX = event.pageX; + var absoluteY = event.pageY; + var targetElement = event.target; + while (targetElement && window !== targetElement.ownerDocument.defaultView) { + var frameElement = targetElement.ownerDocument.defaultView.frameElement; + absoluteY += frameElement.totalOffsetTop(); + absoluteX += frameElement.totalOffsetLeft(); + targetElement = frameElement; + } + + // Install glass pane capturing events. + this._glassPaneElement = document.createElement("div"); + this._glassPaneElement.className = "soft-context-menu-glass-pane"; + this._glassPaneElement.tabIndex = 0; + this._glassPaneElement.addEventListener("mouseup", this._glassPaneMouseUp.bind(this), false); + + // Create context menu. + this._contextMenuElement = document.createElement("div"); + this._contextMenuElement.className = "soft-context-menu"; + this._contextMenuElement.tabIndex = 0; + this._contextMenuElement.style.top = absoluteY + "px"; + this._contextMenuElement.style.left = absoluteX + "px"; + + this._contextMenuElement.addEventListener("mousedown", this._discardMenu.bind(this), false); + this._contextMenuElement.addEventListener("keydown", this._menuKeyDown.bind(this), false); + this._contextMenuElement.addEventListener("blur", this._discardMenu.bind(this), false); + + for (var i = 0; i < this._items.length; ++i) + this._contextMenuElement.appendChild(this._createMenuItem(this._items[i])); + + this._glassPaneElement.appendChild(this._contextMenuElement); + document.body.appendChild(this._glassPaneElement); + this._contextMenuElement.focus(); + + // Re-position menu in case it does not fit. + if (document.body.offsetWidth < this._contextMenuElement.offsetLeft + this._contextMenuElement.offsetWidth) + this._contextMenuElement.style.left = (absoluteX - this._contextMenuElement.offsetWidth) + "px"; + if (document.body.offsetHeight < this._contextMenuElement.offsetTop + this._contextMenuElement.offsetHeight) + this._contextMenuElement.style.top = (document.body.offsetHeight - this._contextMenuElement.offsetHeight) + "px"; + + event.stopPropagation(); + event.preventDefault(); + }, + + _createMenuItem: function(item) + { + if (item.type === "separator") + return this._createSeparator(); + + var menuItemElement = document.createElement("div"); + menuItemElement.className = "soft-context-menu-item"; + + var checkMarkElement = document.createElement("span"); + checkMarkElement.textContent = "\u2713 "; // Checkmark Unicode symbol + checkMarkElement.className = "soft-context-menu-item-checkmark"; + if (!item.checked) + checkMarkElement.style.opacity = "0"; + + menuItemElement.appendChild(checkMarkElement); + menuItemElement.appendChild(document.createTextNode(item.label)); + + menuItemElement.addEventListener("mousedown", this._menuItemMouseDown.bind(this), false); + menuItemElement.addEventListener("mouseup", this._menuItemMouseUp.bind(this), false); + + // Manually manage hover highlight since :hover does not work in case of click-and-hold menu invocation. + menuItemElement.addEventListener("mouseover", this._menuItemMouseOver.bind(this), false); + menuItemElement.addEventListener("mouseout", this._menuItemMouseOut.bind(this), false); + + menuItemElement._actionId = item.id; + return menuItemElement; + }, + + _createSeparator: function() + { + var separatorElement = document.createElement("div"); + separatorElement.className = "soft-context-menu-separator"; + separatorElement._isSeparator = true; + return separatorElement; + }, + + _menuItemMouseDown: function(event) + { + // Do not let separator's mouse down hit menu's handler - we need to receive mouse up! + event.stopPropagation(); + event.preventDefault(); + }, + + _menuItemMouseUp: function(event) + { + this._triggerAction(event.target, event); + }, + + _triggerAction: function(menuItemElement, event) + { + this._discardMenu(event); + if (typeof menuItemElement._actionId !== "undefined") { + WebInspector.contextMenuItemSelected(menuItemElement._actionId); + delete menuItemElement._actionId; + } + }, + + _menuItemMouseOver: function(event) + { + this._highlightMenuItem(event.target); + }, + + _menuItemMouseOut: function(event) + { + this._highlightMenuItem(null); + }, + + _highlightMenuItem: function(menuItemElement) + { + if (this._highlightedMenuItemElement) + this._highlightedMenuItemElement.removeStyleClass("soft-context-menu-item-mouse-over"); + this._highlightedMenuItemElement = menuItemElement; + if (this._highlightedMenuItemElement) + this._highlightedMenuItemElement.addStyleClass("soft-context-menu-item-mouse-over"); + }, + + _highlightPrevious: function() + { + var menuItemElement = this._highlightedMenuItemElement ? this._highlightedMenuItemElement.previousSibling : this._contextMenuElement.lastChild; + while (menuItemElement && menuItemElement._isSeparator) + menuItemElement = menuItemElement.previousSibling; + if (menuItemElement) + this._highlightMenuItem(menuItemElement); + }, + + _highlightNext: function() + { + var menuItemElement = this._highlightedMenuItemElement ? this._highlightedMenuItemElement.nextSibling : this._contextMenuElement.firstChild; + while (menuItemElement && menuItemElement._isSeparator) + menuItemElement = menuItemElement.nextSibling; + if (menuItemElement) + this._highlightMenuItem(menuItemElement); + }, + + _menuKeyDown: function(event) + { + switch (event.keyIdentifier) { + case "Up": + this._highlightPrevious(); break; + case "Down": + this._highlightNext(); break; + case "U+001B": // Escape + this._discardMenu(event); break; + case "Enter": + if (!isEnterKey(event)) + break; + // Fall through + case "U+0020": // Space + if (this._highlightedMenuItemElement) + this._triggerAction(this._highlightedMenuItemElement, event); + break; + } + event.stopPropagation(); + event.preventDefault(); + }, + + _glassPaneMouseUp: function(event) + { + // Return if this is simple 'click', since dispatched on glass pane, can't use 'click' event. + if (event.x === this._x && event.y === this._y && new Date().getTime() - this._time < 300) + return; + this._discardMenu(event); + }, + + _discardMenu: function(event) + { + if (this._glassPaneElement) { + var glassPane = this._glassPaneElement; + delete this._glassPaneElement; + // This can re-enter discardMenu due to blur. + document.body.removeChild(glassPane); + + event.stopPropagation(); + event.preventDefault(); + } + } +} + +InspectorFrontendHost.showContextMenu = function(event, items) +{ + new WebInspector.SoftContextMenu(items).show(event); +} + +} +/* KeyboardShortcut.js */ + +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * 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: + * + * 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. + */ + +/** + * @constructor + */ +WebInspector.KeyboardShortcut = function() +{ +} + +/** + * Constants for encoding modifier key set as a bit mask. + * @see #_makeKeyFromCodeAndModifiers + */ +WebInspector.KeyboardShortcut.Modifiers = { + None: 0, // Constant for empty modifiers set. + Shift: 1, + Ctrl: 2, + Alt: 4, + Meta: 8, // Command key on Mac, Win key on other platforms. + get CtrlOrMeta() + { + // "default" command/ctrl key for platform, Command on Mac, Ctrl on other platforms + return WebInspector.isMac() ? this.Meta : this.Ctrl; + } +}; + +WebInspector.KeyboardShortcut.Keys = { + Backspace: { code: 8, name: "\u21a4" }, + Tab: { code: 9, name: { mac: "\u21e5", other: "" } }, + Enter: { code: 13, name: { mac: "\u21a9", other: "" } }, + Esc: { code: 27, name: { mac: "\u238b", other: "" } }, + Space: { code: 32, name: "" }, + PageUp: { code: 33, name: { mac: "\u21de", other: "" } }, // also NUM_NORTH_EAST + PageDown: { code: 34, name: { mac: "\u21df", other: "" } }, // also NUM_SOUTH_EAST + End: { code: 35, name: { mac: "\u2197", other: "" } }, // also NUM_SOUTH_WEST + Home: { code: 36, name: { mac: "\u2196", other: "" } }, // also NUM_NORTH_WEST + Left: { code: 37, name: "\u2190" }, // also NUM_WEST + Up: { code: 38, name: "\u2191" }, // also NUM_NORTH + Right: { code: 39, name: "\u2192" }, // also NUM_EAST + Down: { code: 40, name: "\u2193" }, // also NUM_SOUTH + Delete: { code: 46, name: "" }, + Zero: { code: 48, name: "0" }, + F1: { code: 112, name: "F1" }, + F2: { code: 113, name: "F2" }, + F3: { code: 114, name: "F3" }, + F4: { code: 115, name: "F4" }, + F5: { code: 116, name: "F5" }, + F6: { code: 117, name: "F6" }, + F7: { code: 118, name: "F7" }, + F8: { code: 119, name: "F8" }, + F9: { code: 120, name: "F9" }, + F10: { code: 121, name: "F10" }, + F11: { code: 122, name: "F11" }, + F12: { code: 123, name: "F12" }, + Semicolon: { code: 186, name: ";" }, + Plus: { code: 187, name: "+" }, + Comma: { code: 188, name: "," }, + Minus: { code: 189, name: "-" }, + Period: { code: 190, name: "." }, + Slash: { code: 191, name: "/" }, + Apostrophe: { code: 192, name: "`" }, + SingleQuote: { code: 222, name: "\'" } +}; + +/** + * Creates a number encoding keyCode in the lower 8 bits and modifiers mask in the higher 8 bits. + * It is useful for matching pressed keys. + * keyCode is the Code of the key, or a character "a-z" which is converted to a keyCode value. + * @param {number=} modifiers Optional list of modifiers passed as additional paramerters. + */ +WebInspector.KeyboardShortcut.makeKey = function(keyCode, modifiers) +{ + if (typeof keyCode === "string") + keyCode = keyCode.charCodeAt(0) - 32; + modifiers = modifiers || WebInspector.KeyboardShortcut.Modifiers.None; + return WebInspector.KeyboardShortcut._makeKeyFromCodeAndModifiers(keyCode, modifiers); +} + +WebInspector.KeyboardShortcut.makeKeyFromEvent = function(keyboardEvent) +{ + var modifiers = WebInspector.KeyboardShortcut.Modifiers.None; + if (keyboardEvent.shiftKey) + modifiers |= WebInspector.KeyboardShortcut.Modifiers.Shift; + if (keyboardEvent.ctrlKey) + modifiers |= WebInspector.KeyboardShortcut.Modifiers.Ctrl; + if (keyboardEvent.altKey) + modifiers |= WebInspector.KeyboardShortcut.Modifiers.Alt; + if (keyboardEvent.metaKey) + modifiers |= WebInspector.KeyboardShortcut.Modifiers.Meta; + return WebInspector.KeyboardShortcut._makeKeyFromCodeAndModifiers(keyboardEvent.keyCode, modifiers); +} + +WebInspector.KeyboardShortcut.eventHasCtrlOrMeta = function(event) +{ + return WebInspector.isMac() ? event.metaKey && !event.ctrlKey : event.ctrlKey && !event.metaKey; +} + +/** + * @param {number=} modifiers + */ +WebInspector.KeyboardShortcut.makeDescriptor = function(key, modifiers) +{ + return { + key: WebInspector.KeyboardShortcut.makeKey(typeof key === "string" ? key : key.code, modifiers), + name: WebInspector.KeyboardShortcut.shortcutToString(key, modifiers) + }; +} + +/** + * @param {number=} modifiers + */ +WebInspector.KeyboardShortcut.shortcutToString = function(key, modifiers) +{ + return WebInspector.KeyboardShortcut._modifiersToString(modifiers) + WebInspector.KeyboardShortcut._keyName(key); +} + +WebInspector.KeyboardShortcut._keyName = function(key) +{ + if (typeof key === "string") + return key.toUpperCase(); + if (typeof key.name === "string") + return key.name; + return key.name[WebInspector.platform()] || key.name.other; +} + +WebInspector.KeyboardShortcut._makeKeyFromCodeAndModifiers = function(keyCode, modifiers) +{ + return (keyCode & 255) | (modifiers << 8); +}; + +WebInspector.KeyboardShortcut._modifiersToString = function(modifiers) +{ + const cmdKey = "\u2318"; + const optKey = "\u2325"; + const shiftKey = "\u21e7"; + const ctrlKey = "\u2303"; + + var isMac = WebInspector.isMac(); + var res = ""; + if (modifiers & WebInspector.KeyboardShortcut.Modifiers.Ctrl) + res += isMac ? ctrlKey : " + "; + if (modifiers & WebInspector.KeyboardShortcut.Modifiers.Alt) + res += isMac ? optKey : " + "; + if (modifiers & WebInspector.KeyboardShortcut.Modifiers.Shift) + res += isMac ? shiftKey : " + "; + if (modifiers & WebInspector.KeyboardShortcut.Modifiers.Meta) + res += isMac ? cmdKey : " + "; + + return res; +}; +/* TextPrompt.js */ + +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2011 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: + * + * 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. + */ + +/** + * @constructor + * @extends WebInspector.Object + * @param {function(Range, boolean, function(Array.=))} completions + * @param {string} stopCharacters + */ +WebInspector.TextPrompt = function(completions, stopCharacters) +{ + /** + * @type {Element|undefined} + */ + this._proxyElement; + this._proxyElementDisplay = "inline-block"; + this._loadCompletions = completions; + this._completionStopCharacters = stopCharacters; + this._suggestForceable = true; +} + +WebInspector.TextPrompt.Events = { + ItemApplied: "text-prompt-item-applied", + ItemAccepted: "text-prompt-item-accepted" +}; + +WebInspector.TextPrompt.prototype = { + get proxyElement() + { + return this._proxyElement; + }, + + setSuggestForceable: function(x) + { + this._suggestForceable = x; + }, + + setSuggestBoxEnabled: function(className) + { + this._suggestBoxClassName = className; + }, + + renderAsBlock: function() + { + this._proxyElementDisplay = "block"; + }, + + /** + * Clients should never attach any event listeners to the |element|. Instead, + * they should use the result of this method to attach listeners for bubbling events. + * + * @param {Element} element + */ + attach: function(element) + { + return this._attachInternal(element); + }, + + /** + * Clients should never attach any event listeners to the |element|. Instead, + * they should use the result of this method to attach listeners for bubbling events + * or the |blurListener| parameter to register a "blur" event listener on the |element| + * (since the "blur" event does not bubble.) + * + * @param {Element} element + * @param {function(Event)} blurListener + */ + attachAndStartEditing: function(element, blurListener) + { + this._attachInternal(element); + this._startEditing(blurListener); + return this.proxyElement; + }, + + _attachInternal: function(element) + { + if (this.proxyElement) + throw "Cannot attach an attached TextPrompt"; + this._element = element; + + this._boundOnKeyDown = this.onKeyDown.bind(this); + this._boundSelectStart = this._selectStart.bind(this); + this._proxyElement = element.ownerDocument.createElement("span"); + this._proxyElement.style.display = this._proxyElementDisplay; + element.parentElement.insertBefore(this.proxyElement, element); + this.proxyElement.appendChild(element); + this._element.addStyleClass("text-prompt"); + this._element.addEventListener("keydown", this._boundOnKeyDown, false); + this._element.addEventListener("selectstart", this._selectStart.bind(this), false); + + if (typeof this._suggestBoxClassName === "string") + this._suggestBox = new WebInspector.TextPrompt.SuggestBox(this, this._element, this._suggestBoxClassName); + + return this.proxyElement; + }, + + detach: function() + { + this._removeFromElement(); + this.proxyElement.parentElement.insertBefore(this._element, this.proxyElement); + this.proxyElement.parentElement.removeChild(this.proxyElement); + delete this._proxyElement; + WebInspector.restoreFocusFromElement(this._element); + }, + + get text() + { + return this._element.textContent; + }, + + set text(x) + { + this._removeSuggestionAids(); + if (!x) { + // Append a break element instead of setting textContent to make sure the selection is inside the prompt. + this._element.removeChildren(); + this._element.appendChild(document.createElement("br")); + } else + this._element.textContent = x; + + this.moveCaretToEndOfPrompt(); + this._element.scrollIntoView(); + }, + + _removeFromElement: function() + { + this.clearAutoComplete(true); + this._element.removeEventListener("keydown", this._boundOnKeyDown, false); + this._element.removeEventListener("selectstart", this._boundSelectStart, false); + if (this._isEditing) + this._stopEditing(); + if (this._suggestBox) + this._suggestBox.removeFromElement(); + }, + + _startEditing: function(blurListener) + { + if (!WebInspector.markBeingEdited(this._element, true)) + return; + this._isEditing = true; + this._element.addStyleClass("editing"); + if (blurListener) { + this._blurListener = blurListener; + this._element.addEventListener("blur", this._blurListener, false); + } + this._oldTabIndex = this._element.tabIndex; + if (this._element.tabIndex < 0) + this._element.tabIndex = 0; + WebInspector.setCurrentFocusElement(this._element); + }, + + _stopEditing: function() + { + this._element.tabIndex = this._oldTabIndex; + if (this._blurListener) + this._element.removeEventListener("blur", this._blurListener, false); + this._element.removeStyleClass("editing"); + delete this._isEditing; + WebInspector.markBeingEdited(this._element, false); + }, + + _removeSuggestionAids: function() + { + this.clearAutoComplete(); + this.hideSuggestBox(); + }, + + _selectStart: function(event) + { + if (this._selectionTimeout) + clearTimeout(this._selectionTimeout); + + this._removeSuggestionAids(); + + function moveBackIfOutside() + { + delete this._selectionTimeout; + if (!this.isCaretInsidePrompt() && window.getSelection().isCollapsed) { + this.moveCaretToEndOfPrompt(); + this.autoCompleteSoon(); + } + } + + this._selectionTimeout = setTimeout(moveBackIfOutside.bind(this), 100); + }, + + /** + * @param {boolean=} force + */ + defaultKeyHandler: function(event, force) + { + this.clearAutoComplete(); + this.autoCompleteSoon(force); + return false; + }, + + onKeyDown: function(event) + { + var handled = false; + var invokeDefault = true; + + switch (event.keyIdentifier) { + case "Up": + handled = this.upKeyPressed(event); + break; + case "Down": + handled = this.downKeyPressed(event); + break; + case "PageUp": + handled = this.pageUpKeyPressed(event); + break; + case "PageDown": + handled = this.pageDownKeyPressed(event); + break; + case "U+0009": // Tab + handled = this.tabKeyPressed(event); + break; + case "Enter": + handled = this.enterKeyPressed(event); + break; + case "Left": + case "Home": + this._removeSuggestionAids(); + invokeDefault = false; + break; + case "Right": + case "End": + if (this.isCaretAtEndOfPrompt()) + handled = this.acceptAutoComplete(); + else + this._removeSuggestionAids(); + invokeDefault = false; + break; + case "U+001B": // Esc + if (this.isSuggestBoxVisible()) { + this._suggestBox.hide(); + handled = true; + } + break; + case "U+0020": // Space + if (this._suggestForceable && event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey) { + this.defaultKeyHandler(event, true); + handled = true; + } + break; + case "Alt": + case "Meta": + case "Shift": + case "Control": + invokeDefault = false; + break; + } + + if (!handled && invokeDefault) + handled = this.defaultKeyHandler(event); + + if (handled) { + event.preventDefault(); + event.stopPropagation(); + } + + return handled; + }, + + acceptAutoComplete: function() + { + var result = false; + if (this.isSuggestBoxVisible()) + result = this._suggestBox.acceptSuggestion(); + if (!result) + result = this.acceptSuggestion(); + + return result; + }, + + /** + * @param {boolean=} includeTimeout + */ + clearAutoComplete: function(includeTimeout) + { + if (includeTimeout && this._completeTimeout) { + clearTimeout(this._completeTimeout); + delete this._completeTimeout; + } + + if (!this.autoCompleteElement) + return; + + if (this.autoCompleteElement.parentNode) + this.autoCompleteElement.parentNode.removeChild(this.autoCompleteElement); + delete this.autoCompleteElement; + + if (!this._userEnteredRange || !this._userEnteredText) + return; + + this._userEnteredRange.deleteContents(); + this._element.pruneEmptyTextNodes(); + + var userTextNode = document.createTextNode(this._userEnteredText); + this._userEnteredRange.insertNode(userTextNode); + + var selectionRange = document.createRange(); + selectionRange.setStart(userTextNode, this._userEnteredText.length); + selectionRange.setEnd(userTextNode, this._userEnteredText.length); + + var selection = window.getSelection(); + selection.removeAllRanges(); + selection.addRange(selectionRange); + + delete this._userEnteredRange; + delete this._userEnteredText; + }, + + /** + * @param {boolean=} force + */ + autoCompleteSoon: function(force) + { + var immediately = this.isSuggestBoxVisible() || force; + if (!this._completeTimeout) + this._completeTimeout = setTimeout(this.complete.bind(this, true, force), immediately ? 0 : 250); + }, + + /** + * @param {boolean=} reverse + */ + complete: function(auto, force, reverse) + { + this.clearAutoComplete(true); + var selection = window.getSelection(); + if (!selection.rangeCount) + return; + + var selectionRange = selection.getRangeAt(0); + var isEmptyInput = selectionRange.commonAncestorContainer === this._element; // this._element has no child Text nodes. + + var shouldExit; + + // Do not attempt to auto-complete an empty input in the auto mode (only on demand). + if (auto && isEmptyInput && !force) + shouldExit = true; + else if (!auto && !isEmptyInput && !selectionRange.commonAncestorContainer.isDescendant(this._element)) + shouldExit = true; + else if (auto && !force && !this.isCaretAtEndOfPrompt() && !this.isSuggestBoxVisible()) + shouldExit = true; + else if (!selection.isCollapsed) + shouldExit = true; + else if (!force) { + // BUG72018: Do not show suggest box if caret is followed by a non-stop character. + var wordSuffixRange = selectionRange.startContainer.rangeOfWord(selectionRange.endOffset, this._completionStopCharacters, this._element, "forward"); + if (wordSuffixRange.toString().length) + shouldExit = true; + } + if (shouldExit) { + this.hideSuggestBox(); + return; + } + + var wordPrefixRange = selectionRange.startContainer.rangeOfWord(selectionRange.startOffset, this._completionStopCharacters, this._element, "backward"); + this._loadCompletions(wordPrefixRange, force, this._completionsReady.bind(this, selection, auto, wordPrefixRange, !!reverse)); + }, + + _boxForAnchorAtStart: function(selection, textRange) + { + var rangeCopy = selection.getRangeAt(0).cloneRange(); + var anchorElement = document.createElement("span"); + anchorElement.textContent = "\u200B"; + textRange.insertNode(anchorElement); + var box = anchorElement.boxInWindow(window); + anchorElement.parentElement.removeChild(anchorElement); + selection.removeAllRanges(); + selection.addRange(rangeCopy); + return box; + }, + + /** + * @param {Selection} selection + * @param {boolean} auto + * @param {Range} originalWordPrefixRange + * @param {boolean} reverse + * @param {Array.=} completions + */ + _completionsReady: function(selection, auto, originalWordPrefixRange, reverse, completions) + { + if (!completions || !completions.length) { + this.hideSuggestBox(); + return; + } + + var selectionRange = selection.getRangeAt(0); + + var fullWordRange = document.createRange(); + fullWordRange.setStart(originalWordPrefixRange.startContainer, originalWordPrefixRange.startOffset); + fullWordRange.setEnd(selectionRange.endContainer, selectionRange.endOffset); + + if (originalWordPrefixRange.toString() + selectionRange.toString() != fullWordRange.toString()) + return; + + this._userEnteredRange = fullWordRange; + this._userEnteredText = fullWordRange.toString(); + + if (this._suggestBox) + this._suggestBox.updateSuggestions(this._boxForAnchorAtStart(selection, fullWordRange), completions, !this.isCaretAtEndOfPrompt()); + + var wordPrefixLength = originalWordPrefixRange.toString().length; + + if (auto) + var completionText = completions[0]; + else { + if (completions.length === 1) { + var completionText = completions[0]; + wordPrefixLength = completionText.length; + } else { + var commonPrefix = completions[0]; + for (var i = 0; i < completions.length; ++i) { + var completion = completions[i]; + var lastIndex = Math.min(commonPrefix.length, completion.length); + for (var j = wordPrefixLength; j < lastIndex; ++j) { + if (commonPrefix[j] !== completion[j]) { + commonPrefix = commonPrefix.substr(0, j); + break; + } + } + } + wordPrefixLength = commonPrefix.length; + + if (selection.isCollapsed) + var completionText = completions[0]; + else { + var currentText = fullWordRange.toString(); + + var foundIndex = null; + for (var i = 0; i < completions.length; ++i) { + if (completions[i] === currentText) + foundIndex = i; + } + + var nextIndex = foundIndex + (reverse ? -1 : 1); + if (foundIndex === null || nextIndex >= completions.length) + var completionText = completions[0]; + else if (nextIndex < 0) + var completionText = completions[completions.length - 1]; + else + var completionText = completions[nextIndex]; + } + } + } + + if (auto) { + if (this.isCaretAtEndOfPrompt()) { + this._userEnteredRange.deleteContents(); + this._element.pruneEmptyTextNodes(); + var finalSelectionRange = document.createRange(); + var prefixText = completionText.substring(0, wordPrefixLength); + var suffixText = completionText.substring(wordPrefixLength); + + var prefixTextNode = document.createTextNode(prefixText); + fullWordRange.insertNode(prefixTextNode); + + this.autoCompleteElement = document.createElement("span"); + this.autoCompleteElement.className = "auto-complete-text"; + this.autoCompleteElement.textContent = suffixText; + + prefixTextNode.parentNode.insertBefore(this.autoCompleteElement, prefixTextNode.nextSibling); + + finalSelectionRange.setStart(prefixTextNode, wordPrefixLength); + finalSelectionRange.setEnd(prefixTextNode, wordPrefixLength); + selection.removeAllRanges(); + selection.addRange(finalSelectionRange); + } + } else + this.applySuggestion(completionText, completions.length > 1, originalWordPrefixRange); + }, + + /** + * @param {Range=} originalPrefixRange + */ + applySuggestion: function(completionText, isIntermediateSuggestion, originalPrefixRange) + { + var wordPrefixLength; + if (originalPrefixRange) + wordPrefixLength = originalPrefixRange.toString().length; + else + wordPrefixLength = this._userEnteredText ? this._userEnteredText.length : 0; + + this._userEnteredRange.deleteContents(); + this._element.pruneEmptyTextNodes(); + var finalSelectionRange = document.createRange(); + var completionTextNode = document.createTextNode(completionText); + this._userEnteredRange.insertNode(completionTextNode); + if (this.autoCompleteElement && this.autoCompleteElement.parentNode) { + this.autoCompleteElement.parentNode.removeChild(this.autoCompleteElement); + delete this.autoCompleteElement; + } + + if (isIntermediateSuggestion) + finalSelectionRange.setStart(completionTextNode, wordPrefixLength); + else + finalSelectionRange.setStart(completionTextNode, completionText.length); + + finalSelectionRange.setEnd(completionTextNode, completionText.length); + + var selection = window.getSelection(); + selection.removeAllRanges(); + selection.addRange(finalSelectionRange); + if (isIntermediateSuggestion) + this.dispatchEventToListeners(WebInspector.TextPrompt.Events.ItemApplied, { itemText: completionText }); + }, + + acceptSuggestion: function() + { + if (this._isAcceptingSuggestion) + return false; + + if (!this.autoCompleteElement || !this.autoCompleteElement.parentNode) + return false; + + var text = this.autoCompleteElement.textContent; + var textNode = document.createTextNode(text); + this.autoCompleteElement.parentNode.replaceChild(textNode, this.autoCompleteElement); + delete this.autoCompleteElement; + + var finalSelectionRange = document.createRange(); + finalSelectionRange.setStart(textNode, text.length); + finalSelectionRange.setEnd(textNode, text.length); + + var selection = window.getSelection(); + selection.removeAllRanges(); + selection.addRange(finalSelectionRange); + + this.hideSuggestBox(); + this.dispatchEventToListeners(WebInspector.TextPrompt.Events.ItemAccepted); + + return true; + }, + + hideSuggestBox: function() + { + if (this.isSuggestBoxVisible()) + this._suggestBox.hide(); + }, + + isSuggestBoxVisible: function() + { + return this._suggestBox && this._suggestBox.visible; + }, + + isCaretInsidePrompt: function() + { + return this._element.isInsertionCaretInside(); + }, + + isCaretAtEndOfPrompt: function() + { + var selection = window.getSelection(); + if (!selection.rangeCount || !selection.isCollapsed) + return false; + + var selectionRange = selection.getRangeAt(0); + var node = selectionRange.startContainer; + if (!node.isSelfOrDescendant(this._element)) + return false; + + if (node.nodeType === Node.TEXT_NODE && selectionRange.startOffset < node.nodeValue.length) + return false; + + var foundNextText = false; + while (node) { + if (node.nodeType === Node.TEXT_NODE && node.nodeValue.length) { + if (foundNextText && (!this.autoCompleteElement || !this.autoCompleteElement.isAncestor(node))) + return false; + foundNextText = true; + } + + node = node.traverseNextNode(this._element); + } + + return true; + }, + + isCaretOnFirstLine: function() + { + var selection = window.getSelection(); + var focusNode = selection.focusNode; + if (!focusNode || focusNode.nodeType !== Node.TEXT_NODE || focusNode.parentNode !== this._element) + return true; + + if (focusNode.textContent.substring(0, selection.focusOffset).indexOf("\n") !== -1) + return false; + focusNode = focusNode.previousSibling; + + while (focusNode) { + if (focusNode.nodeType !== Node.TEXT_NODE) + return true; + if (focusNode.textContent.indexOf("\n") !== -1) + return false; + focusNode = focusNode.previousSibling; + } + + return true; + }, + + isCaretOnLastLine: function() + { + var selection = window.getSelection(); + var focusNode = selection.focusNode; + if (!focusNode || focusNode.nodeType !== Node.TEXT_NODE || focusNode.parentNode !== this._element) + return true; + + if (focusNode.textContent.substring(selection.focusOffset).indexOf("\n") !== -1) + return false; + focusNode = focusNode.nextSibling; + + while (focusNode) { + if (focusNode.nodeType !== Node.TEXT_NODE) + return true; + if (focusNode.textContent.indexOf("\n") !== -1) + return false; + focusNode = focusNode.nextSibling; + } + + return true; + }, + + moveCaretToEndOfPrompt: function() + { + var selection = window.getSelection(); + var selectionRange = document.createRange(); + + var offset = this._element.childNodes.length; + selectionRange.setStart(this._element, offset); + selectionRange.setEnd(this._element, offset); + + selection.removeAllRanges(); + selection.addRange(selectionRange); + }, + + tabKeyPressed: function(event) + { + // Just consume the key. + return true; + }, + + enterKeyPressed: function(event) + { + if (this.isSuggestBoxVisible()) + return this._suggestBox.enterKeyPressed(event); + + return false; + }, + + upKeyPressed: function(event) + { + if (this.isSuggestBoxVisible()) + return this._suggestBox.upKeyPressed(event); + + return false; + }, + + downKeyPressed: function(event) + { + if (this.isSuggestBoxVisible()) + return this._suggestBox.downKeyPressed(event); + + return false; + }, + + pageUpKeyPressed: function(event) + { + if (this.isSuggestBoxVisible()) + return this._suggestBox.pageUpKeyPressed(event); + + return false; + }, + + pageDownKeyPressed: function(event) + { + if (this.isSuggestBoxVisible()) + return this._suggestBox.pageDownKeyPressed(event); + + return false; + }, +} + +WebInspector.TextPrompt.prototype.__proto__ = WebInspector.Object.prototype; + +/** + * @constructor + * @extends {WebInspector.TextPrompt} + * @param {function(Range, boolean, function(Array.=))} completions + * @param {string} stopCharacters + */ +WebInspector.TextPromptWithHistory = function(completions, stopCharacters) +{ + WebInspector.TextPrompt.call(this, completions, stopCharacters); + + /** + * @type {Array.} + */ + this._data = []; + + /** + * 1-based entry in the history stack. + * @type {number} + */ + this._historyOffset = 1; + + /** + * Whether to coalesce duplicate items in the history, default is true. + * @type {boolean} + */ + this._coalesceHistoryDupes = true; +} + +WebInspector.TextPromptWithHistory.prototype = { + get historyData() + { + // FIXME: do we need to copy this? + return this._data; + }, + + setCoalesceHistoryDupes: function(x) + { + this._coalesceHistoryDupes = x; + }, + + /** + * @param {Array.} data + */ + setHistoryData: function(data) + { + this._data = [].concat(data); + this._historyOffset = 1; + }, + + /** + * Pushes a committed text into the history. + * @param {string} text + */ + pushHistoryItem: function(text) + { + if (this._uncommittedIsTop) { + this._data.pop(); + delete this._uncommittedIsTop; + } + + this._historyOffset = 1; + if (this._coalesceHistoryDupes && text === this._currentHistoryItem()) + return; + this._data.push(text); + }, + + /** + * Pushes the current (uncommitted) text into the history. + */ + _pushCurrentText: function() + { + if (this._uncommittedIsTop) + this._data.pop(); // Throw away obsolete uncommitted text. + this._uncommittedIsTop = true; + this.clearAutoComplete(true); + this._data.push(this.text); + }, + + /** + * @return {string|undefined} + */ + _previous: function() + { + if (this._historyOffset > this._data.length) + return undefined; + if (this._historyOffset === 1) + this._pushCurrentText(); + ++this._historyOffset; + return this._currentHistoryItem(); + }, + + /** + * @return {string|undefined} + */ + _next: function() + { + if (this._historyOffset === 1) + return undefined; + --this._historyOffset; + return this._currentHistoryItem(); + }, + + _currentHistoryItem: function() + { + return this._data[this._data.length - this._historyOffset]; + }, + + /** + * @override + */ + defaultKeyHandler: function(event, force) + { + var newText; + var isPrevious; + + switch (event.keyIdentifier) { + case "Up": + if (!this.isCaretOnFirstLine()) + break; + newText = this._previous(); + isPrevious = true; + break; + case "Down": + if (!this.isCaretOnLastLine()) + break; + newText = this._next(); + break; + case "U+0050": // Ctrl+P = Previous + if (WebInspector.isMac() && event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey) { + newText = this._previous(); + isPrevious = true; + } + break; + case "U+004E": // Ctrl+N = Next + if (WebInspector.isMac() && event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey) + newText = this._next(); + break; + } + + if (newText !== undefined) { + event.stopPropagation(); + event.preventDefault(); + this.text = newText; + + if (isPrevious) { + var firstNewlineIndex = this.text.indexOf("\n"); + if (firstNewlineIndex === -1) + this.moveCaretToEndOfPrompt(); + else { + var selection = window.getSelection(); + var selectionRange = document.createRange(); + + selectionRange.setStart(this._element.firstChild, firstNewlineIndex); + selectionRange.setEnd(this._element.firstChild, firstNewlineIndex); + + selection.removeAllRanges(); + selection.addRange(selectionRange); + } + } + + return true; + } + + return WebInspector.TextPrompt.prototype.defaultKeyHandler.apply(this, arguments); + } +} + +WebInspector.TextPromptWithHistory.prototype.__proto__ = WebInspector.TextPrompt.prototype; + +/** + * @constructor + */ +WebInspector.TextPrompt.SuggestBox = function(textPrompt, inputElement, className) +{ + this._textPrompt = textPrompt; + this._inputElement = inputElement; + this._selectedElement = null; + this._boundOnScroll = this._onscrollresize.bind(this, true); + this._boundOnResize = this._onscrollresize.bind(this, false); + window.addEventListener("scroll", this._boundOnScroll, true); + window.addEventListener("resize", this._boundOnResize, true); + + var bodyElement = inputElement.ownerDocument.body; + this._element = bodyElement.createChild("div", "suggest-box " + (className || "")); + this._element.addEventListener("mousedown", this._onboxmousedown.bind(this), true); + this.containerElement = this._element.createChild("div", "container"); + this.contentElement = this.containerElement.createChild("div", "content"); +} + +WebInspector.TextPrompt.SuggestBox.prototype = { + get visible() + { + return this._element.hasStyleClass("visible"); + }, + + get hasSelection() + { + return !!this._selectedElement; + }, + + _onscrollresize: function(isScroll, event) + { + if (isScroll && this._element.isAncestor(event.target) || !this.visible) + return; + this._updateBoxPositionWithExistingAnchor(); + }, + + _updateBoxPositionWithExistingAnchor: function() + { + this._updateBoxPosition(this._anchorBox); + }, + + /** + * @param {AnchorBox} anchorBox + */ + _updateBoxPosition: function(anchorBox) + { + // Measure the content element box. + this.contentElement.style.display = "inline-block"; + document.body.appendChild(this.contentElement); + this.contentElement.positionAt(0, 0); + var contentWidth = this.contentElement.offsetWidth; + var contentHeight = this.contentElement.offsetHeight; + this.contentElement.style.display = "block"; + this.containerElement.appendChild(this.contentElement); + + // Lay out the suggest-box relative to the anchorBox. + this._anchorBox = anchorBox; + const spacer = 6; + + const suggestBoxPaddingX = 21; + var maxWidth = document.body.offsetWidth - anchorBox.x - spacer; + var width = Math.min(contentWidth, maxWidth - suggestBoxPaddingX) + suggestBoxPaddingX; + var paddedWidth = contentWidth + suggestBoxPaddingX; + var boxX = anchorBox.x; + if (width < paddedWidth) { + // Shift the suggest box to the left to accommodate the content without trimming to the BODY edge. + maxWidth = document.body.offsetWidth - spacer; + width = Math.min(contentWidth, maxWidth - suggestBoxPaddingX) + suggestBoxPaddingX; + boxX = document.body.offsetWidth - width; + } + + const suggestBoxPaddingY = 2; + var boxY; + var aboveHeight = anchorBox.y; + var underHeight = document.body.offsetHeight - anchorBox.y - anchorBox.height; + var maxHeight = Math.max(underHeight, aboveHeight) - spacer; + var height = Math.min(contentHeight, maxHeight - suggestBoxPaddingY) + suggestBoxPaddingY; + if (underHeight >= aboveHeight) { + // Locate the suggest box under the anchorBox. + boxY = anchorBox.y + anchorBox.height; + this._element.removeStyleClass("above-anchor"); + this._element.addStyleClass("under-anchor"); + } else { + // Locate the suggest box above the anchorBox. + boxY = anchorBox.y - height; + this._element.removeStyleClass("under-anchor"); + this._element.addStyleClass("above-anchor"); + } + + this._element.positionAt(boxX, boxY); + this._element.style.width = width + "px"; + this._element.style.height = height + "px"; + }, + + _onboxmousedown: function(event) + { + event.preventDefault(); + }, + + hide: function() + { + if (!this.visible) + return; + + this._element.removeStyleClass("visible"); + delete this._selectedElement; + }, + + removeFromElement: function() + { + window.removeEventListener("scroll", this._boundOnScroll, true); + window.removeEventListener("resize", this._boundOnResize, true); + this._element.parentElement.removeChild(this._element); + }, + + /** + * @param {string=} text + * @param {boolean=} isIntermediateSuggestion + */ + _applySuggestion: function(text, isIntermediateSuggestion) + { + if (!this.visible || !(text || this._selectedElement)) + return false; + + var suggestion = text || this._selectedElement.textContent; + if (!suggestion) + return false; + + this._textPrompt.applySuggestion(suggestion, isIntermediateSuggestion); + return true; + }, + + /** + * @param {string=} text + */ + acceptSuggestion: function(text) + { + var result = this._applySuggestion(text, false); + this.hide(); + if (!result) + return false; + + this._textPrompt.acceptSuggestion(); + + return true; + }, + + _onNextItem: function(event, isPageScroll) + { + var children = this.contentElement.childNodes; + if (!children.length) + return false; + + if (!this._selectedElement) + this._selectedElement = this.contentElement.firstChild; + else { + if (!isPageScroll) + this._selectedElement = this._selectedElement.nextSibling || this.contentElement.firstChild; + else { + var candidate = this._selectedElement; + + for (var itemsLeft = this._rowCountPerViewport; itemsLeft; --itemsLeft) { + if (candidate.nextSibling) + candidate = candidate.nextSibling; + else + break; + } + + this._selectedElement = candidate; + } + } + this._updateSelection(); + this._applySuggestion(undefined, true); + return true; + }, + + _onPreviousItem: function(event, isPageScroll) + { + var children = this.contentElement.childNodes; + if (!children.length) + return false; + + if (!this._selectedElement) + this._selectedElement = this.contentElement.lastChild; + else { + if (!isPageScroll) + this._selectedElement = this._selectedElement.previousSibling || this.contentElement.lastChild; + else { + var candidate = this._selectedElement; + + for (var itemsLeft = this._rowCountPerViewport; itemsLeft; --itemsLeft) { + if (candidate.previousSibling) + candidate = candidate.previousSibling; + else + break; + } + + this._selectedElement = candidate; + } + } + this._updateSelection(); + this._applySuggestion(undefined, true); + return true; + }, + + /** + * @param {AnchorBox} anchorBox + * @param {Array.=} completions + * @param {boolean=} canShowForSingleItem + */ + updateSuggestions: function(anchorBox, completions, canShowForSingleItem) + { + if (this._suggestTimeout) { + clearTimeout(this._suggestTimeout); + delete this._suggestTimeout; + } + this._completionsReady(anchorBox, completions, canShowForSingleItem); + }, + + _onItemMouseDown: function(text, event) + { + this.acceptSuggestion(text); + event.stopPropagation(); + event.preventDefault(); + }, + + _createItemElement: function(prefix, text) + { + var element = document.createElement("div"); + element.className = "suggest-box-content-item source-code"; + element.tabIndex = -1; + if (prefix && prefix.length && !text.indexOf(prefix)) { + var prefixElement = element.createChild("span", "prefix"); + prefixElement.textContent = prefix; + var suffixElement = element.createChild("span", "suffix"); + suffixElement.textContent = text.substring(prefix.length); + } else { + var suffixElement = element.createChild("span", "suffix"); + suffixElement.textContent = text; + } + element.addEventListener("mousedown", this._onItemMouseDown.bind(this, text), false); + return element; + }, + + /** + * @param {boolean=} canShowForSingleItem + */ + _updateItems: function(items, canShowForSingleItem) + { + this.contentElement.removeChildren(); + + var userEnteredText = this._textPrompt._userEnteredText; + for (var i = 0; i < items.length; ++i) { + var item = items[i]; + var currentItemElement = this._createItemElement(userEnteredText, item); + this.contentElement.appendChild(currentItemElement); + } + + this._selectedElement = canShowForSingleItem ? this.contentElement.firstChild : null; + this._updateSelection(); + }, + + _updateSelection: function() + { + // FIXME: might want some optimization if becomes a bottleneck. + for (var child = this.contentElement.firstChild; child; child = child.nextSibling) { + if (child !== this._selectedElement) + child.removeStyleClass("selected"); + } + if (this._selectedElement) { + this._selectedElement.addStyleClass("selected"); + this._selectedElement.scrollIntoViewIfNeeded(false); + } + }, + + /** + * @param {Array.=} completions + * @param {boolean=} canShowForSingleItem + */ + _canShowBox: function(completions, canShowForSingleItem) + { + if (!completions || !completions.length) + return false; + + if (completions.length > 1) + return true; + + // Do not show a single suggestion if it is the same as user-entered prefix, even if allowed to show single-item suggest boxes. + return canShowForSingleItem && completions[0] !== this._textPrompt._userEnteredText; + }, + + _rememberRowCountPerViewport: function() + { + if (!this.contentElement.firstChild) + return; + + this._rowCountPerViewport = Math.floor(this.containerElement.offsetHeight / this.contentElement.firstChild.offsetHeight); + }, + + /** + * @param {AnchorBox} anchorBox + * @param {Array.=} completions + * @param {boolean=} canShowForSingleItem + */ + _completionsReady: function(anchorBox, completions, canShowForSingleItem) + { + if (this._canShowBox(completions, canShowForSingleItem)) { + this._updateItems(completions, canShowForSingleItem); + this._updateBoxPosition(anchorBox); + this._element.addStyleClass("visible"); + this._rememberRowCountPerViewport(); + } else + this.hide(); + }, + + upKeyPressed: function(event) + { + return this._onPreviousItem(event, false); + }, + + downKeyPressed: function(event) + { + return this._onNextItem(event, false); + }, + + pageUpKeyPressed: function(event) + { + return this._onPreviousItem(event, true); + }, + + pageDownKeyPressed: function(event) + { + return this._onNextItem(event, true); + }, + + enterKeyPressed: function(event) + { + var hasSelectedItem = !!this._selectedElement; + this.acceptSuggestion(); + + // Report the event as non-handled if there is no selected item, + // to commit the input or handle it otherwise. + return hasSelectedItem; + }, + + tabKeyPressed: function(event) + { + return this.enterKeyPressed(event); + } +} +/* Popover.js */ + +/* + * 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. + */ + +/** + * @constructor + * @param {WebInspector.PopoverHelper=} popoverHelper + */ +WebInspector.Popover = function(popoverHelper) +{ + this.element = document.createElement("div"); + this.element.className = "popover custom-popup-vertical-scroll custom-popup-horizontal-scroll"; + + this._popupArrowElement = document.createElement("div"); + this._popupArrowElement.className = "arrow"; + this.element.appendChild(this._popupArrowElement); + + this._contentDiv = document.createElement("div"); + this._contentDiv.className = "content"; + this._visible = false; + this._popoverHelper = popoverHelper; +} + +WebInspector.Popover.prototype = { + show: function(contentElement, anchor, preferredWidth, preferredHeight) + { + if (this._disposed) + return; + this.contentElement = contentElement; + + // This should not happen, but we hide previous popup to be on the safe side. + if (WebInspector.Popover._popoverElement) + document.body.removeChild(WebInspector.Popover._popoverElement); + WebInspector.Popover._popoverElement = this.element; + + // Temporarily attach in order to measure preferred dimensions. + this.contentElement.positionAt(0, 0); + document.body.appendChild(this.contentElement); + preferredWidth = preferredWidth || this.contentElement.offsetWidth; + preferredHeight = preferredHeight || this.contentElement.offsetHeight; + + this._contentDiv.appendChild(this.contentElement); + this.element.appendChild(this._contentDiv); + document.body.appendChild(this.element); + this._positionElement(anchor, preferredWidth, preferredHeight); + this._visible = true; + if (this._popoverHelper) + contentElement.addEventListener("mousemove", this._popoverHelper._killHidePopoverTimer.bind(this._popoverHelper), true); + }, + + hide: function() + { + if (WebInspector.Popover._popoverElement) { + delete WebInspector.Popover._popoverElement; + document.body.removeChild(this.element); + } + this._visible = false; + }, + + get visible() + { + return this._visible; + }, + + get disposed() + { + return this._disposed; + }, + + dispose: function() + { + if (this.visible) + this.hide(); + this._disposed = true; + }, + + _positionElement: function(anchorElement, preferredWidth, preferredHeight) + { + const borderWidth = 25; + const scrollerWidth = 11; + const arrowHeight = 15; + const arrowOffset = 10; + const borderRadius = 10; + + // Skinny tooltips are not pretty, their arrow location is not nice. + preferredWidth = Math.max(preferredWidth, 50); + const totalWidth = window.innerWidth; + const totalHeight = window.innerHeight; + + var anchorBox = anchorElement.boxInWindow(window); + var newElementPosition = { x: 0, y: 0, width: preferredWidth + scrollerWidth, height: preferredHeight }; + + var verticalAlignment; + var roomAbove = anchorBox.y; + var roomBelow = totalHeight - anchorBox.y - anchorBox.height; + + if (roomAbove > roomBelow) { + // Positioning above the anchor. + if (anchorBox.y > newElementPosition.height + arrowHeight + borderRadius) + newElementPosition.y = anchorBox.y - newElementPosition.height - arrowHeight; + else { + newElementPosition.y = borderRadius * 2; + newElementPosition.height = anchorBox.y - borderRadius * 2 - arrowHeight; + } + verticalAlignment = "bottom"; + } else { + // Positioning below the anchor. + newElementPosition.y = anchorBox.y + anchorBox.height + arrowHeight; + if (newElementPosition.y + newElementPosition.height + arrowHeight - borderWidth >= totalHeight) + newElementPosition.height = totalHeight - anchorBox.y - anchorBox.height - borderRadius * 2 - arrowHeight; + // Align arrow. + verticalAlignment = "top"; + } + + var horizontalAlignment; + if (anchorBox.x + newElementPosition.width < totalWidth) { + newElementPosition.x = Math.max(borderRadius, anchorBox.x - borderRadius - arrowOffset); + horizontalAlignment = "left"; + } else if (newElementPosition.width + borderRadius * 2 < totalWidth) { + newElementPosition.x = totalWidth - newElementPosition.width - borderRadius; + horizontalAlignment = "right"; + // Position arrow accurately. + var arrowRightPosition = Math.max(0, totalWidth - anchorBox.x - anchorBox.width - borderRadius - arrowOffset); + arrowRightPosition += anchorBox.width / 2; + this._popupArrowElement.style.right = arrowRightPosition + "px"; + } else { + newElementPosition.x = borderRadius; + newElementPosition.width = totalWidth - borderRadius * 2; + newElementPosition.height += scrollerWidth; + horizontalAlignment = "left"; + if (verticalAlignment === "bottom") + newElementPosition.y -= scrollerWidth; + // Position arrow accurately. + this._popupArrowElement.style.left = Math.max(0, anchorBox.x - borderRadius * 2 - arrowOffset) + "px"; + this._popupArrowElement.style.left += anchorBox.width / 2; + } + + this.element.className = "popover custom-popup-vertical-scroll custom-popup-horizontal-scroll " + verticalAlignment + "-" + horizontalAlignment + "-arrow"; + this.element.positionAt(newElementPosition.x - borderWidth, newElementPosition.y - borderWidth); + this.element.style.width = newElementPosition.width + borderWidth * 2 + "px"; + this.element.style.height = newElementPosition.height + borderWidth * 2 + "px"; + } +} + +/** + * @constructor + * @param {function()=} onHide + * @param {boolean=} disableOnClick + */ +WebInspector.PopoverHelper = function(panelElement, getAnchor, showPopover, onHide, disableOnClick) +{ + this._panelElement = panelElement; + this._getAnchor = getAnchor; + this._showPopover = showPopover; + this._onHide = onHide; + this._disableOnClick = !!disableOnClick; + panelElement.addEventListener("mousedown", this._mouseDown.bind(this), false); + panelElement.addEventListener("mousemove", this._mouseMove.bind(this), false); + this.setTimeout(1000); +} + +WebInspector.PopoverHelper.prototype = { + setTimeout: function(timeout) + { + this._timeout = timeout; + }, + + _mouseDown: function(event) + { + if (this._disableOnClick) + this.hidePopover(); + else { + this._killHidePopoverTimer(); + this._handleMouseAction(event, true); + } + }, + + _mouseMove: function(event) + { + // Pretend that nothing has happened. + if (event.target.isSelfOrDescendant(this._hoverElement)) + return; + + // User has 500ms (this._timeout / 2) to reach the popup. + if (this._popover && !this._hidePopoverTimer) { + var self = this; + function doHide() + { + self._hidePopover(); + delete self._hidePopoverTimer; + } + this._hidePopoverTimer = setTimeout(doHide, this._timeout / 2); + } + + this._handleMouseAction(event, false); + }, + + _handleMouseAction: function(event, isMouseDown) + { + this._resetHoverTimer(); + if (event.which && this._disableOnClick) + return; + this._hoverElement = this._getAnchor(event.target); + if (!this._hoverElement) + return; + const toolTipDelay = isMouseDown ? 0 : (this._popup ? this._timeout * 0.6 : this._timeout); + this._hoverTimer = setTimeout(this._mouseHover.bind(this, this._hoverElement), toolTipDelay); + }, + + _resetHoverTimer: function() + { + if (this._hoverTimer) { + clearTimeout(this._hoverTimer); + delete this._hoverTimer; + } + }, + + hidePopover: function() + { + this._resetHoverTimer(); + this._hidePopover(); + }, + + _hidePopover: function() + { + if (!this._popover) + return; + + if (this._onHide) + this._onHide(); + + this._popover.dispose(); + delete this._popover; + }, + + _mouseHover: function(element) + { + delete this._hoverTimer; + + this._hidePopover(); + this._popover = new WebInspector.Popover(this); + this._showPopover(element, this._popover); + }, + + _killHidePopoverTimer: function() + { + if (this._hidePopoverTimer) { + clearTimeout(this._hidePopoverTimer); + delete this._hidePopoverTimer; + + // We know that we reached the popup, but we might have moved over other elements. + // Discard pending command. + this._resetHoverTimer(); + } + } +} +/* Placard.js */ + +/* + * Copyright (C) 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 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 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. + */ + +/** + * @constructor + * @param {string} title + * @param {string} subtitle + */ +WebInspector.Placard = function(title, subtitle) +{ + this.element = document.createElement("div"); + this.element.className = "placard"; + this.element.placard = this; + + this.titleElement = document.createElement("div"); + this.titleElement.className = "title"; + + this.subtitleElement = document.createElement("div"); + this.subtitleElement.className = "subtitle"; + + this.element.appendChild(this.subtitleElement); + this.element.appendChild(this.titleElement); + + this.title = title; + this.subtitle = subtitle; + this.selected = false; +} + +WebInspector.Placard.prototype = { + /** @return {string} */ + get title() + { + return this._title; + }, + + set title(x) + { + if (this._title === x) + return; + this._title = x; + this.titleElement.textContent = x; + }, + + /** @return {string} */ + get subtitle() + { + return this._subtitle; + }, + + set subtitle(x) + { + if (this._subtitle === x) + return; + this._subtitle = x; + this.subtitleElement.textContent = x; + }, + + /** @return {boolean} */ + get selected() + { + return this._selected; + }, + + set selected(x) + { + if (x) + this.select(); + else + this.deselect(); + }, + + select: function() + { + if (this._selected) + return; + this._selected = true; + this.element.addStyleClass("selected"); + }, + + deselect: function() + { + if (!this._selected) + return; + this._selected = false; + this.element.removeStyleClass("selected"); + }, + + toggleSelected: function() + { + this.selected = !this.selected; + }, + + discard: function() + { + } +} +/* View.js */ + +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2011 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: + * 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 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 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. + */ + +/** + * @constructor + * @extends {WebInspector.Object} + */ +WebInspector.View = function() +{ + this.element = document.createElement("div"); + this.element.__view = this; + this._visible = true; + this._isRoot = false; + this._isShowing = false; + this._children = []; + this._hideOnDetach = false; + this._cssFiles = []; +} + +WebInspector.View._cssFileToVisibleViewCount = {}; +WebInspector.View._cssFileToStyleElement = {}; + +WebInspector.View.prototype = { + markAsRoot: function() + { + this._isRoot = true; + }, + + isShowing: function() + { + return this._isShowing; + }, + + setHideOnDetach: function() + { + this._hideOnDetach = true; + }, + + _parentIsShowing: function() + { + return this._isRoot || (this._parentView && this._parentView.isShowing()); + }, + + _callOnVisibleChildren: function(method) + { + for (var i = 0; i < this._children.length; ++i) + if (this._children[i]._visible) + method.call(this._children[i]); + }, + + _processWillShow: function() + { + this._loadCSSIfNeeded(); + this._callOnVisibleChildren(this._processWillShow); + }, + + _processWasShown: function() + { + this._isShowing = true; + this.restoreScrollPositions(); + + this.wasShown(); + this.onResize(); + + this._callOnVisibleChildren(this._processWasShown); + }, + + _processWillHide: function() + { + this.storeScrollPositions(); + + this._callOnVisibleChildren(this._processWillHide); + + this.willHide(); + this._isShowing = false; + }, + + _processWasHidden: function() + { + this._disableCSSIfNeeded(); + this._callOnVisibleChildren(this._processWasHidden); + }, + + _processOnResize: function() + { + if (!this.isShowing()) + return; + + this.onResize(); + this._callOnVisibleChildren(this._processOnResize); + }, + + wasShown: function() + { + }, + + willHide: function() + { + }, + + onResize: function() + { + }, + + /** + * @param {Element} parentElement + * @param {Element=} insertBefore + */ + show: function(parentElement, insertBefore) + { + WebInspector.View._assert(parentElement, "Attempt to attach view with no parent element"); + + // Update view hierarchy + if (this.element.parentElement !== parentElement) { + var currentParent = parentElement; + while (currentParent && !currentParent.__view) + currentParent = currentParent.parentElement; + + if (currentParent) { + this._parentView = currentParent.__view; + this._parentView._children.push(this); + this._isRoot = false; + } else + WebInspector.View._assert(this._isRoot, "Attempt to attach view to orphan node"); + } else if (this._visible) + return; + + this._visible = true; + if (this._parentIsShowing()) + this._processWillShow(); + + this.element.addStyleClass("visible"); + + // Reparent + if (this.element.parentElement !== parentElement) { + WebInspector.View._incrementViewCounter(parentElement, this.element); + if (insertBefore) + WebInspector.View._originalInsertBefore.call(parentElement, this.element, insertBefore); + else + WebInspector.View._originalAppendChild.call(parentElement, this.element); + } + + if (this._parentIsShowing()) + this._processWasShown(); + }, + + /** + * @param {boolean=} overrideHideOnDetach + */ + detach: function(overrideHideOnDetach) + { + var parentElement = this.element.parentElement; + if (!parentElement) + return; + + if (this._parentIsShowing()) + this._processWillHide(); + + if (this._hideOnDetach && !overrideHideOnDetach) { + this.element.removeStyleClass("visible"); + this._visible = false; + if (this._parentIsShowing()) + this._processWasHidden(); + return; + } + + // Force legal removal + WebInspector.View._decrementViewCounter(parentElement, this.element); + WebInspector.View._originalRemoveChild.call(parentElement, this.element); + + this._visible = false; + if (this._parentIsShowing()) + this._processWasHidden(); + + // Update view hierarchy + if (this._parentView) { + var childIndex = this._parentView._children.indexOf(this); + WebInspector.View._assert(childIndex >= 0, "Attempt to remove non-child view"); + this._parentView._children.splice(childIndex, 1); + this._parentView = null; + } else + WebInspector.View._assert(this._isRoot, "Removing non-root view from DOM"); + }, + + detachChildViews: function() + { + var children = this._children.slice(); + for (var i = 0; i < children.length; ++i) + children[i].detach(); + }, + + elementsToRestoreScrollPositionsFor: function() + { + return [this.element]; + }, + + storeScrollPositions: function() + { + var elements = this.elementsToRestoreScrollPositionsFor(); + for (var i = 0; i < elements.length; ++i) { + var container = elements[i]; + container._scrollTop = container.scrollTop; + container._scrollLeft = container.scrollLeft; + } + }, + + restoreScrollPositions: function() + { + var elements = this.elementsToRestoreScrollPositionsFor(); + for (var i = 0; i < elements.length; ++i) { + var container = elements[i]; + if (container._scrollTop) + container.scrollTop = container._scrollTop; + if (container._scrollLeft) + container.scrollLeft = container._scrollLeft; + } + }, + + canHighlightLine: function() + { + return false; + }, + + highlightLine: function(line) + { + }, + + doResize: function() + { + this._processOnResize(); + }, + + registerRequiredCSS: function(cssFile) + { + this._cssFiles.push(cssFile); + }, + + _loadCSSIfNeeded: function() + { + for (var i = 0; i < this._cssFiles.length; ++i) { + var cssFile = this._cssFiles[i]; + + var viewsWithCSSFile = WebInspector.View._cssFileToVisibleViewCount[cssFile]; + WebInspector.View._cssFileToVisibleViewCount[cssFile] = (viewsWithCSSFile || 0) + 1; + if (!viewsWithCSSFile) + this._doLoadCSS(cssFile); + } + }, + + _doLoadCSS: function(cssFile) + { + var styleElement = WebInspector.View._cssFileToStyleElement[cssFile]; + if (styleElement) { + styleElement.disabled = false; + return; + } + + var xhr = new XMLHttpRequest(); + xhr.open("GET", cssFile, false); + xhr.send(null); + + styleElement = document.createElement("style"); + styleElement.type = "text/css"; + styleElement.textContent = xhr.responseText; + document.head.insertBefore(styleElement, document.head.firstChild); + + WebInspector.View._cssFileToStyleElement[cssFile] = styleElement; + }, + + _disableCSSIfNeeded: function() + { + for (var i = 0; i < this._cssFiles.length; ++i) { + var cssFile = this._cssFiles[i]; + + var viewsWithCSSFile = WebInspector.View._cssFileToVisibleViewCount[cssFile]; + viewsWithCSSFile--; + WebInspector.View._cssFileToVisibleViewCount[cssFile] = viewsWithCSSFile; + + if (!viewsWithCSSFile) + this._doUnloadCSS(cssFile); + } + }, + + _doUnloadCSS: function(cssFile) + { + var styleElement = WebInspector.View._cssFileToStyleElement[cssFile]; + styleElement.disabled = true; + }, + + printViewHierarchy: function() + { + var lines = []; + this._collectViewHierarchy("", lines); + console.log(lines.join("\n")); + }, + + _collectViewHierarchy: function(prefix, lines) + { + lines.push(prefix + "[" + this.element.className + "]" + (this._children.length ? " {" : "")); + + for (var i = 0; i < this._children.length; ++i) + this._children[i]._collectViewHierarchy(prefix + " ", lines); + + if (this._children.length) + lines.push(prefix + "}"); + } +} + +WebInspector.View.prototype.__proto__ = WebInspector.Object.prototype; + +WebInspector.View._originalAppendChild = Element.prototype.appendChild; +WebInspector.View._originalInsertBefore = Element.prototype.insertBefore; +WebInspector.View._originalRemoveChild = Element.prototype.removeChild; +WebInspector.View._originalRemoveChildren = Element.prototype.removeChildren; + +WebInspector.View._incrementViewCounter = function(parentElement, childElement) +{ + var count = (childElement.__viewCounter || 0) + (childElement.__view ? 1 : 0); + if (!count) + return; + + while (parentElement) { + parentElement.__viewCounter = (parentElement.__viewCounter || 0) + count; + parentElement = parentElement.parentElement; + } +} + +WebInspector.View._decrementViewCounter = function(parentElement, childElement) +{ + var count = (childElement.__viewCounter || 0) + (childElement.__view ? 1 : 0); + if (!count) + return; + + while (parentElement) { + parentElement.__viewCounter -= count; + parentElement = parentElement.parentElement; + } +} + +WebInspector.View._assert = function(condition, message) +{ + if (!condition) { + console.trace(); + throw new Error(message); + } +} + +Element.prototype.appendChild = function(child) +{ + WebInspector.View._assert(!child.__view, "Attempt to add view via regular DOM operation."); + return WebInspector.View._originalAppendChild.call(this, child); +} + +Element.prototype.insertBefore = function(child, anchor) +{ + WebInspector.View._assert(!child.__view, "Attempt to add view via regular DOM operation."); + return WebInspector.View._originalInsertBefore.call(this, child, anchor); +} + + +Element.prototype.removeChild = function(child) +{ + WebInspector.View._assert(!child.__viewCounter && !child.__view, "Attempt to remove element containing view via regular DOM operation"); + return WebInspector.View._originalRemoveChild.call(this, child); +} + +Element.prototype.removeChildren = function() +{ + WebInspector.View._assert(!this.__viewCounter, "Attempt to remove element containing view via regular DOM operation"); + WebInspector.View._originalRemoveChildren.call(this); +} +/* TabbedPane.js */ + +/* + * 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. + * * 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. + */ + +/** + * @extends {WebInspector.View} + * @constructor + */ +WebInspector.TabbedPane = function() +{ + WebInspector.View.call(this); + this.registerRequiredCSS("tabbedPane.css"); + this.element.addStyleClass("tabbed-pane"); + this._headerElement = this.element.createChild("div", "tabbed-pane-header"); + this._headerContentsElement = this._headerElement.createChild("div", "tabbed-pane-header-contents"); + this._tabsElement = this._headerContentsElement.createChild("div", "tabbed-pane-header-tabs"); + this._contentElement = this.element.createChild("div", "tabbed-pane-content"); + this._tabs = []; + this._tabsHistory = []; + this._tabsById = {}; + + this._dropDownButton = this._createDropDownButton(); +} + +WebInspector.TabbedPane.EventTypes = { + TabSelected: "TabSelected", + TabClosed: "TabClosed" +} + +WebInspector.TabbedPane.prototype = { + /** + * @type {WebInspector.View} + */ + get visibleView() + { + return this._currentTab ? this._currentTab.view : null; + }, + + /** + * @type {string} + */ + get selectedTabId() + { + return this._currentTab ? this._currentTab.id : null; + }, + + /** + * @type {boolean} shrinkableTabs + */ + set shrinkableTabs(shrinkableTabs) + { + this._shrinkableTabs = shrinkableTabs; + }, + + /** + * @type {boolean} shrinkableTabs + */ + set closeableTabs(closeableTabs) + { + this._closeableTabs = closeableTabs; + }, + + /** + * @param {string} id + * @param {string} tabTitle + * @param {WebInspector.View} view + * @param {string=} tabTooltip + */ + appendTab: function(id, tabTitle, view, tabTooltip) + { + var tab = new WebInspector.TabbedPaneTab(this, this._tabsElement, id, tabTitle, this._closeableTabs, view, tabTooltip); + + this._tabs.push(tab); + this._tabsById[id] = tab; + this._tabsHistory.push(tab); + this._updateTabElements(); + }, + + /** + * @param {string} id + * @param {boolean=} userGesture + */ + closeTab: function(id, userGesture) + { + if (this._currentTab && this._currentTab.id === id) + this._hideCurrentTab(); + + var tab = this._tabsById[id]; + delete this._tabsById[id]; + + this._tabsHistory.splice(this._tabsHistory.indexOf(tab), 1); + this._tabs.splice(this._tabs.indexOf(tab), 1); + if (tab.shown) + this._hideTabElement(tab); + + if (this._tabsHistory.length) + this.selectTab(this._tabsHistory[0].id); + else + this._updateTabElements(); + + var eventData = { tabId: id, view: tab.view, isUserGesture: userGesture }; + this.dispatchEventToListeners(WebInspector.TabbedPane.EventTypes.TabClosed, eventData); + return true; + }, + + closeAllTabs: function() + { + var tabs = this._tabs.slice(); + for (var i = 0; i < tabs.length; ++i) + this.closeTab(tabs[i].id, false); + }, + + /** + * @param {string} id + * @param {boolean=} userGesture + */ + selectTab: function(id, userGesture) + { + var tab = this._tabsById[id]; + if (!tab) + return; + if (this._currentTab && this._currentTab.id === id) + return; + + this._hideCurrentTab(); + this._showTab(tab); + this._currentTab = tab; + + this._tabsHistory.splice(this._tabsHistory.indexOf(tab), 1); + this._tabsHistory.splice(0, 0, tab); + + this._updateTabElements(); + + var eventData = { tabId: id, view: tab.view, isUserGesture: userGesture }; + this.dispatchEventToListeners(WebInspector.TabbedPane.EventTypes.TabSelected, eventData); + return true; + }, + + /** + * @param {string} id + * @param {string} tabTitle + */ + changeTabTitle: function(id, tabTitle) + { + var tab = this._tabsById[id]; + tab.title = tabTitle; + this._updateTabElements(); + }, + + /** + * @param {string} id + * @param {WebInspector.View} view + */ + changeTabView: function(id, view) + { + var tab = this._tabsById[id]; + if (this._currentTab && this._currentTab.id === tab.id) { + this._hideTab(tab); + tab.view = view; + this._showTab(tab); + } else + tab.view = view; + }, + + /** + * @param {string} id + * @param {string=} tabTooltip + */ + changeTabTooltip: function(id, tabTooltip) + { + var tab = this._tabsById[id]; + tab.tooltip = tabTooltip; + }, + + onResize: function() + { + this._updateTabElements(); + }, + + _updateTabElements: function() + { + if (!this.isShowing()) + return; + + if (!this._tabs.length) + this._contentElement.addStyleClass("has-no-tabs"); + else + this._contentElement.removeStyleClass("has-no-tabs"); + + if (!this._measuredDropDownButtonWidth) + this._measureDropDownButton(); + + if (this._shrinkableTabs) + this._updateWidths(); + + this._updateTabsDropDown(); + }, + + /** + * @param {number} index + * @param {WebInspector.TabbedPaneTab} tab + */ + _showTabElement: function(index, tab) + { + if (index >= this._tabsElement.children.length) + this._tabsElement.appendChild(tab.tabElement); + else + this._tabsElement.insertBefore(tab.tabElement, this._tabsElement.children[index]); + tab.shown = true; + }, + + /** + * @param {WebInspector.TabbedPaneTab} tab + */ + _hideTabElement: function(tab) + { + this._tabsElement.removeChild(tab.tabElement); + tab.shown = false; + }, + + _createDropDownButton: function() + { + var dropDownContainer = document.createElement("div"); + dropDownContainer.addStyleClass("tabbed-pane-header-tabs-drop-down-container"); + var dropDownButton = dropDownContainer.createChild("div", "tabbed-pane-header-tabs-drop-down"); + dropDownButton.appendChild(document.createTextNode("\u00bb")); + this._tabsSelect = dropDownButton.createChild("select", "tabbed-pane-header-tabs-drop-down-select"); + this._tabsSelect.addEventListener("change", this._tabsSelectChanged.bind(this), false); + return dropDownContainer; + }, + + _updateTabsDropDown: function() + { + var tabsToShowIndexes = this._tabsToShowIndexes(this._tabs, this._tabsHistory, this._headerContentsElement.offsetWidth, this._measuredDropDownButtonWidth); + + for (var i = 0; i < this._tabs.length; ++i) { + if (this._tabs[i].shown && tabsToShowIndexes.indexOf(i) === -1) + this._hideTabElement(this._tabs[i]); + } + for (var i = 0; i < tabsToShowIndexes.length; ++i) { + var tab = this._tabs[tabsToShowIndexes[i]]; + if (!tab.shown) + this._showTabElement(i, tab); + } + + this._populateDropDownFromIndex(); + }, + + _populateDropDownFromIndex: function() + { + if (this._dropDownButton.parentElement) + this._headerContentsElement.removeChild(this._dropDownButton); + + this._tabsSelect.removeChildren(); + for (var i = 0; i < this._tabs.length; ++i) { + if (this._tabs[i].shown) + continue; + + var option = new Option(this._tabs[i].title); + option.tab = this._tabs[i]; + this._tabsSelect.appendChild(option); + } + if (this._tabsSelect.options.length) { + this._headerContentsElement.appendChild(this._dropDownButton); + this._tabsSelect.selectedIndex = -1; + } + }, + + _tabsSelectChanged: function() + { + var options = this._tabsSelect.options; + var selectedOption = options[this._tabsSelect.selectedIndex]; + this.selectTab(selectedOption.tab.id); + }, + + _measureDropDownButton: function() + { + this._dropDownButton.addStyleClass("measuring"); + this._headerContentsElement.appendChild(this._dropDownButton); + this._measuredDropDownButtonWidth = this._dropDownButton.offsetWidth; + this._headerContentsElement.removeChild(this._dropDownButton); + this._dropDownButton.removeStyleClass("measuring"); + }, + + _updateWidths: function() + { + var measuredWidths = []; + for (var tabId in this._tabs) + measuredWidths.push(this._tabs[tabId].measuredWidth); + + var maxWidth = this._calculateMaxWidth(measuredWidths, this._headerContentsElement.offsetWidth); + + for (var tabId in this._tabs) { + var tab = this._tabs[tabId]; + tab.width = Math.min(tab.measuredWidth, maxWidth); + } + }, + + /** + * @param {Array.} measuredWidths + * @param {number} totalWidth + */ + _calculateMaxWidth: function(measuredWidths, totalWidth) + { + if (!measuredWidths.length) + return 0; + + measuredWidths.sort(function(x, y) { return x - y }); + + var totalMeasuredWidth = 0; + for (var i = 0; i < measuredWidths.length; ++i) + totalMeasuredWidth += measuredWidths[i]; + + if (totalWidth >= totalMeasuredWidth) + return measuredWidths[measuredWidths.length - 1]; + + var totalExtraWidth = 0; + for (var i = measuredWidths.length - 1; i > 0; --i) { + var extraWidth = measuredWidths[i] - measuredWidths[i - 1]; + totalExtraWidth += (measuredWidths.length - i) * extraWidth; + + if (totalWidth + totalExtraWidth >= totalMeasuredWidth) + return measuredWidths[i - 1] + (totalWidth + totalExtraWidth - totalMeasuredWidth) / (measuredWidths.length - i); + } + + return totalWidth / measuredWidths.length; + }, + + /** + * @param {Array.} tabsOrdered + * @param {Array.} tabsHistory + * @param {number} totalWidth + * @param {number} measuredDropDownButtonWidth + * @return {Array.} + */ + _tabsToShowIndexes: function(tabsOrdered, tabsHistory, totalWidth, measuredDropDownButtonWidth) + { + var tabsToShowIndexes = []; + + var totalTabsWidth = 0; + for (var i = 0; i < tabsHistory.length; ++i) { + totalTabsWidth += tabsHistory[i].width; + var minimalRequiredWidth = totalTabsWidth; + if (i !== tabsHistory.length - 1) + minimalRequiredWidth += measuredDropDownButtonWidth; + if (minimalRequiredWidth > totalWidth) + break; + tabsToShowIndexes.push(tabsOrdered.indexOf(tabsHistory[i])); + } + + tabsToShowIndexes.sort(function(x, y) { return x - y }); + + return tabsToShowIndexes; + }, + + _hideCurrentTab: function() + { + if (!this._currentTab) + return; + + this._hideTab(this._currentTab); + delete this._currentTab; + }, + + /** + * @param {WebInspector.TabbedPaneTab} tab + */ + _showTab: function(tab) + { + tab.tabElement.addStyleClass("selected"); + tab.view.show(this._contentElement); + }, + + /** + * @param {WebInspector.TabbedPaneTab} tab + */ + _hideTab: function(tab) + { + tab.tabElement.removeStyleClass("selected"); + tab.view.detach(); + }, + + canHighlightLine: function() + { + return this._currentTab && this._currentTab.view && this._currentTab.view.canHighlightLine(); + }, + + highlightLine: function(line) + { + if (this.canHighlightLine()) + this._currentTab.view.highlightLine(line); + }, + + /** + * @return {Array.} + */ + elementsToRestoreScrollPositionsFor: function() + { + return [ this._contentElement ]; + } +} + +WebInspector.TabbedPane.prototype.__proto__ = WebInspector.View.prototype; + + +/** + * @constructor + * @param {WebInspector.TabbedPane} tabbedPane + * @param {Element} measureElement + * @param {string} id + * @param {string} title + * @param {boolean} closeable + * @param {WebInspector.View} view + * @param {string=} tooltip + */ +WebInspector.TabbedPaneTab = function(tabbedPane, measureElement, id, title, closeable, view, tooltip) +{ + this._closeable = closeable; + this._tabbedPane = tabbedPane; + this._measureElement = measureElement; + this._id = id; + this._title = title; + this._tooltip = tooltip; + this._view = view; + this.shown = false; +} + +WebInspector.TabbedPaneTab.prototype = { + /** + * @type {string} + */ + get id() + { + return this._id; + }, + + /** + * @type {string} + */ + get title() + { + return this._title; + }, + + set title(title) + { + this._title = title; + if (this._titleElement) + this._titleElement.textContent = title; + delete this._measuredWidth; + }, + + /** + * @type {WebInspector.View} + */ + get view() + { + return this._view; + }, + + set view(view) + { + this._view = view; + }, + + /** + * @type {string|undefined} + */ + get tooltip() + { + return this._tooltip; + }, + + set tooltip(tooltip) + { + this._tooltip = tooltip; + if (this._titleElement) + this._titleElement.title = tooltip || ""; + }, + + /** + * @type {Element} + */ + get tabElement() + { + if (typeof(this._tabElement) !== "undefined") + return this._tabElement; + + this._createTabElement(false); + return this._tabElement; + }, + + /** + * @type {number} + */ + get measuredWidth() + { + if (typeof(this._measuredWidth) !== "undefined") + return this._measuredWidth; + + this._measure(); + return this._measuredWidth; + }, + + /** + * @type {number} + */ + get width() + { + return this._width || this.measuredWidth; + }, + + set width(width) + { + this.tabElement.style.width = width + "px"; + this._width = width; + }, + + /** + * @param {boolean} measuring + */ + _createTabElement: function(measuring) + { + var tabElement = document.createElement("div"); + tabElement.addStyleClass("tabbed-pane-header-tab"); + + var titleElement = tabElement.createChild("span", "tabbed-pane-header-tab-title"); + titleElement.textContent = this.title; + titleElement.title = this.tooltip || ""; + if (!measuring) + this._titleElement = titleElement; + + if (this._closeable) { + var closeButtonSpan = tabElement.createChild("span", "tabbed-pane-header-tab-close-button"); + closeButtonSpan.textContent = "\u00D7"; // 'MULTIPLICATION SIGN' + } + + if (measuring) + tabElement.addStyleClass("measuring"); + else { + this._tabElement = tabElement; + tabElement.addEventListener("click", this._tabSelected.bind(this), false); + if (this._closeable) + closeButtonSpan.addEventListener("click", this._tabClosed.bind(this), false); + } + + return tabElement; + }, + + _measure: function() + { + var measuringTabElement = this._createTabElement(true); + this._measureElement.appendChild(measuringTabElement); + this._measuredWidth = measuringTabElement.offsetWidth; + this._measureElement.removeChild(measuringTabElement); + }, + + _tabSelected: function() + { + this._tabbedPane.selectTab(this.id, true); + }, + + _tabClosed: function() + { + this._tabbedPane.closeTab(this.id, true); + } +}/* Drawer.js */ + +/* + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2009 Joseph Pecoraro + * + * 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. + */ + +/** + * @constructor + */ +WebInspector.Drawer = function() +{ + this.element = document.getElementById("drawer"); + this._savedHeight = 200; // Default. + this._mainElement = document.getElementById("main"); + this._toolbarElement = document.getElementById("toolbar"); + this._mainStatusBar = document.getElementById("main-status-bar"); + this._mainStatusBar.addEventListener("mousedown", this._startStatusBarDragging.bind(this), true); + this._counters = document.getElementById("counters"); + + this._drawerContentsElement = document.createElement("div"); + this._drawerContentsElement.id = "drawer-contents"; + this._drawerContentsElement.className = "drawer-contents"; + this.element.appendChild(this._drawerContentsElement); + + this._drawerStatusBar = document.createElement("div"); + this._drawerStatusBar.id = "drawer-status-bar"; + this._drawerStatusBar.className = "status-bar"; + this.element.appendChild(this._drawerStatusBar); + + this._viewStatusBar = document.createElement("div"); + this._drawerStatusBar.appendChild(this._viewStatusBar); +} + +WebInspector.Drawer.AnimationType = { + Immediately: 0, + Normal: 1, + Slow: 2 +} + +WebInspector.Drawer.prototype = { + get visible() + { + return !!this._view; + }, + + _constrainHeight: function(height) + { + return Number.constrain(height, Preferences.minConsoleHeight, window.innerHeight - this._mainElement.totalOffsetTop() - Preferences.minConsoleHeight); + }, + + show: function(view, animationType) + { + this.immediatelyFinishAnimation(); + if (this._view && this._view.counterElement) + this._view.counterElement.parentNode.removeChild(this._view.counterElement); + + var drawerWasVisible = this.visible; + + if (this._view) { + this._view.detach(); + this._drawerContentsElement.removeChildren(); + } + + this._view = view; + + var statusBarItems = this._view.statusBarItems || []; + this._viewStatusBar.removeChildren(); + for (var i = 0; i < statusBarItems.length; ++i) + this._viewStatusBar.appendChild(statusBarItems[i]); + + if (this._view.counterElement) + this._counters.insertBefore(this._view.counterElement, this._counters.firstChild); + + document.body.addStyleClass("drawer-visible"); + this._view.markAsRoot(); + this._view.show(this._drawerContentsElement); + + if (drawerWasVisible) + return; + + var anchoredItems = document.getElementById("anchored-status-bar-items"); + var height = this._constrainHeight(this._savedHeight || this.element.offsetHeight); + var animations = [ + {element: this.element, end: {height: height}}, + {element: this._mainElement, end: {bottom: height}}, + {element: this._mainStatusBar, start: {"padding-left": anchoredItems.offsetWidth - 1}, end: {"padding-left": 0}}, + {element: this._viewStatusBar, start: {opacity: 0}, end: {opacity: 1}} + ]; + + this._drawerStatusBar.insertBefore(anchoredItems, this._drawerStatusBar.firstChild); + + if (this._currentPanelCounters) { + var oldRight = this._drawerStatusBar.clientWidth - (this._counters.offsetLeft + this._currentPanelCounters.offsetWidth); + var newRight = WebInspector.Panel.counterRightMargin; + var rightPadding = (oldRight - newRight); + animations.push({element: this._currentPanelCounters, start: {"padding-right": rightPadding}, end: {"padding-right": 0}}); + this._currentPanelCounters.parentNode.removeChild(this._currentPanelCounters); + this._mainStatusBar.appendChild(this._currentPanelCounters); + } + + function animationFinished() + { + WebInspector.inspectorView.currentPanel().statusBarResized(); + if (this._view && this._view.afterShow) + this._view.afterShow(); + delete this._currentAnimation; + if (this._currentPanelCounters) + this._currentPanelCounters.removeAttribute("style"); + } + + this._currentAnimation = WebInspector.animateStyle(animations, this._animationDuration(animationType), animationFinished.bind(this)); + if (animationType === WebInspector.Drawer.AnimationType.Immediately) + this._currentAnimation.forceComplete(); + }, + + hide: function(animationType) + { + this.immediatelyFinishAnimation(); + if (!this.visible) + return; + + this._savedHeight = this.element.offsetHeight; + + WebInspector.restoreFocusFromElement(this.element); + + var anchoredItems = document.getElementById("anchored-status-bar-items"); + + // Temporarily set properties and classes to mimic the post-animation values so panels + // like Elements in their updateStatusBarItems call will size things to fit the final location. + this._mainStatusBar.style.setProperty("padding-left", (anchoredItems.offsetWidth - 1) + "px"); + document.body.removeStyleClass("drawer-visible"); + WebInspector.inspectorView.currentPanel().statusBarResized(); + document.body.addStyleClass("drawer-visible"); + + var animations = [ + {element: this._mainElement, end: {bottom: 0}}, + {element: this._mainStatusBar, start: {"padding-left": 0}, end: {"padding-left": anchoredItems.offsetWidth - 1}}, + {element: this._viewStatusBar, start: {opacity: 1}, end: {opacity: 0}} + ]; + + if (this._currentPanelCounters) { + var newRight = this._drawerStatusBar.clientWidth - this._counters.offsetLeft; + var oldRight = this._mainStatusBar.clientWidth - (this._currentPanelCounters.offsetLeft + this._currentPanelCounters.offsetWidth); + var rightPadding = (newRight - oldRight); + animations.push({element: this._currentPanelCounters, start: {"padding-right": 0}, end: {"padding-right": rightPadding}}); + } + + function animationFinished() + { + WebInspector.inspectorView.currentPanel().doResize(); + this._mainStatusBar.insertBefore(anchoredItems, this._mainStatusBar.firstChild); + this._mainStatusBar.style.removeProperty("padding-left"); + + if (this._view.counterElement) + this._view.counterElement.parentNode.removeChild(this._view.counterElement); + + if (this._currentPanelCounters) { + this._currentPanelCounters.setAttribute("style", null); + this._currentPanelCounters.parentNode.removeChild(this._currentPanelCounters); + this._counters.insertBefore(this._currentPanelCounters, this._counters.firstChild); + } + + this._view.detach(); + delete this._view; + this._drawerContentsElement.removeChildren(); + document.body.removeStyleClass("drawer-visible"); + delete this._currentAnimation; + } + + this._currentAnimation = WebInspector.animateStyle(animations, this._animationDuration(animationType), animationFinished.bind(this)); + if (animationType === WebInspector.Drawer.AnimationType.Immediately) + this._currentAnimation.forceComplete(); + }, + + resize: function() + { + if (!this.visible) + return; + + this._view.storeScrollPositions(); + var height = this._constrainHeight(parseInt(this.element.style.height, 10)); + this._mainElement.style.bottom = height + "px"; + this.element.style.height = height + "px"; + this._view.doResize(); + }, + + immediatelyFinishAnimation: function() + { + if (this._currentAnimation) + this._currentAnimation.forceComplete(); + }, + + set currentPanelCounters(x) + { + if (!x) { + if (this._currentPanelCounters) + this._currentPanelCounters.parentElement.removeChild(this._currentPanelCounters); + delete this._currentPanelCounters; + return; + } + + this._currentPanelCounters = x; + if (this.visible) + this._mainStatusBar.appendChild(x); + else + this._counters.insertBefore(x, this._counters.firstChild); + }, + + _animationDuration: function(animationType) + { + switch (animationType) { + case WebInspector.Drawer.AnimationType.Slow: + return 2000; + case WebInspector.Drawer.AnimationType.Normal: + return 250; + default: + return 0; + } + }, + + _startStatusBarDragging: function(event) + { + if (!this.visible || event.target !== this._mainStatusBar) + return; + + this._view.storeScrollPositions(); + WebInspector.elementDragStart(this._mainStatusBar, this._statusBarDragging.bind(this), this._endStatusBarDragging.bind(this), event, "row-resize"); + + this._statusBarDragOffset = event.pageY - this.element.totalOffsetTop(); + + event.stopPropagation(); + }, + + _statusBarDragging: function(event) + { + var height = window.innerHeight - event.pageY + this._statusBarDragOffset; + height = Number.constrain(height, Preferences.minConsoleHeight, window.innerHeight - this._mainElement.totalOffsetTop() - Preferences.minConsoleHeight); + + this._mainElement.style.bottom = height + "px"; + this.element.style.height = height + "px"; + if (WebInspector.inspectorView.currentPanel()) + WebInspector.inspectorView.currentPanel().doResize(); + this._view.doResize(); + + event.preventDefault(); + event.stopPropagation(); + }, + + _endStatusBarDragging: function(event) + { + WebInspector.elementDragEnd(event); + + this._savedHeight = this.element.offsetHeight; + delete this._statusBarDragOffset; + + event.stopPropagation(); + } +} + +/** + * @type {WebInspector.Drawer} + */ +WebInspector.drawer = null; +/* ConsoleModel.js */ + +/* + * Copyright (C) 2011 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. + */ + +/** + * @constructor + * @extends {WebInspector.Object} + */ +WebInspector.ConsoleModel = function() +{ + this.messages = []; + this.warnings = 0; + this.errors = 0; + this._interruptRepeatCount = false; + InspectorBackend.registerConsoleDispatcher(new WebInspector.ConsoleDispatcher(this)); +} + +WebInspector.ConsoleModel.Events = { + ConsoleCleared: "console-cleared", + MessageAdded: "console-message-added", + RepeatCountUpdated: "repeat-count-updated" +} + +WebInspector.ConsoleModel.prototype = { + enableAgent: function() + { + if (WebInspector.settings.monitoringXHREnabled.get()) + ConsoleAgent.setMonitoringXHREnabled(true); + + ConsoleAgent.enable(); + }, + + /** + * @param {WebInspector.ConsoleMessage} msg + */ + addMessage: function(msg) + { + this.messages.push(msg); + this._previousMessage = msg; + this._incrementErrorWarningCount(msg); + this.dispatchEventToListeners(WebInspector.ConsoleModel.Events.MessageAdded, msg); + this._interruptRepeatCount = false; + }, + + /** + * @param {WebInspector.ConsoleMessage} msg + */ + _incrementErrorWarningCount: function(msg) + { + switch (msg.level) { + case WebInspector.ConsoleMessage.MessageLevel.Warning: + this.warnings += msg.repeatDelta; + break; + case WebInspector.ConsoleMessage.MessageLevel.Error: + this.errors += msg.repeatDelta; + break; + } + }, + + requestClearMessages: function() + { + ConsoleAgent.clearMessages(); + this.clearMessages(); + }, + + clearMessages: function() + { + this.messages = []; + + this.errors = 0; + this.warnings = 0; + + this.dispatchEventToListeners(WebInspector.ConsoleModel.Events.ConsoleCleared); + }, + + interruptRepeatCount: function() + { + this._interruptRepeatCount = true; + }, + + /** + * @param {number} count + */ + _messageRepeatCountUpdated: function(count) + { + var msg = this._previousMessage; + if (!msg) + return; + + var prevRepeatCount = msg.totalRepeatCount; + + if (!this._interruptRepeatCount) { + msg.repeatDelta = count - prevRepeatCount; + msg.repeatCount = msg.repeatCount + msg.repeatDelta; + msg.totalRepeatCount = count; + msg.updateRepeatCount(); + + this._incrementErrorWarningCount(msg); + this.dispatchEventToListeners(WebInspector.ConsoleModel.Events.RepeatCountUpdated, msg); + } else { + var msgCopy = msg.clone(); + msgCopy.totalRepeatCount = count; + msgCopy.repeatCount = (count - prevRepeatCount) || 1; + msgCopy.repeatDelta = msgCopy.repeatCount; + this.addMessage(msgCopy); + } + } +} + +WebInspector.ConsoleModel.prototype.__proto__ = WebInspector.Object.prototype; + +/** + * @constructor + * @param {string} source + * @param {string} level + * @param {string=} url + * @param {number=} line + * @param {number=} repeatCount + */ +WebInspector.ConsoleMessage = function(source, level, url, line, repeatCount) +{ + this.source = source; + this.level = level; + this.url = url || null; + this.line = line || 0; + + repeatCount = repeatCount || 1; + this.repeatCount = repeatCount; + this.repeatDelta = repeatCount; + this.totalRepeatCount = repeatCount; +} + +WebInspector.ConsoleMessage.prototype = { + /** + * @return {boolean} + */ + isErrorOrWarning: function() + { + return (this.level === WebInspector.ConsoleMessage.MessageLevel.Warning || this.level === WebInspector.ConsoleMessage.MessageLevel.Error); + }, + + updateRepeatCount: function() + { + // Implemented by concrete instances + }, + + /** + * @return {WebInspector.ConsoleMessage} + */ + clone: function() + { + // Implemented by concrete instances + } +} + +/** + * @param {string} source + * @param {string} level + * @param {string} message + * @param {string=} type + * @param {string=} url + * @param {number=} line + * @param {number=} repeatCount + * @param {Array.=} parameters + * @param {ConsoleAgent.StackTrace=} stackTrace + * @param {WebInspector.Resource=} request + * + * @return {WebInspector.ConsoleMessage} + */ +WebInspector.ConsoleMessage.create = function(source, level, message, type, url, line, repeatCount, parameters, stackTrace, request) +{ +} + +// Note: Keep these constants in sync with the ones in Console.h +WebInspector.ConsoleMessage.MessageSource = { + HTML: "html", + XML: "xml", + JS: "javascript", + Network: "network", + ConsoleAPI: "console-api", + Other: "other" +} + +WebInspector.ConsoleMessage.MessageType = { + Log: "log", + Dir: "dir", + DirXML: "dirxml", + Trace: "trace", + StartGroup: "startGroup", + StartGroupCollapsed: "startGroupCollapsed", + EndGroup: "endGroup", + Assert: "assert", + Result: "result" +} + +WebInspector.ConsoleMessage.MessageLevel = { + Tip: "tip", + Log: "log", + Warning: "warning", + Error: "error", + Debug: "debug" +} + + +/** + * @constructor + * @implements {ConsoleAgent.Dispatcher} + * @param {WebInspector.ConsoleModel} console + */ +WebInspector.ConsoleDispatcher = function(console) +{ + this._console = console; +} + +WebInspector.ConsoleDispatcher.prototype = { + /** + * @param {ConsoleAgent.ConsoleMessage} payload + */ + messageAdded: function(payload) + { + var consoleMessage = WebInspector.ConsoleMessage.create( + payload.source, + payload.level, + payload.text, + payload.type, + payload.url, + payload.line, + payload.repeatCount, + payload.parameters, + payload.stackTrace, + payload.networkRequestId ? WebInspector.networkResourceById(payload.networkRequestId) : undefined); + this._console.addMessage(consoleMessage); + }, + + /** + * @param {number} count + */ + messageRepeatCountUpdated: function(count) + { + this._console._messageRepeatCountUpdated(count); + }, + + messagesCleared: function() + { + if (!WebInspector.settings.preserveConsoleLog.get()) + this._console.clearMessages(); + } +} + +/** + * @type {?WebInspector.ConsoleModel} + */ +WebInspector.console = null; +/* ConsoleMessage.js */ + +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2009 Joseph Pecoraro + * + * 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. + */ + +/** + * @constructor + * @extends {WebInspector.ConsoleMessage} + * + * @param {string} source + * @param {string} level + * @param {string} message + * @param {WebInspector.DebuggerPresentationModel.Linkifier} linkifier + * @param {string=} type + * @param {string=} url + * @param {number=} line + * @param {number=} repeatCount + * @param {Array.=} parameters + * @param {ConsoleAgent.StackTrace=} stackTrace + * @param {WebInspector.Resource=} request + */ +WebInspector.ConsoleMessageImpl = function(source, level, message, linkifier, type, url, line, repeatCount, parameters, stackTrace, request) +{ + WebInspector.ConsoleMessage.call(this, source, level, url, line, repeatCount); + + this._linkifier = linkifier; + this.type = type || WebInspector.ConsoleMessage.MessageType.Log; + this._messageText = message; + this._parameters = parameters; + this._stackTrace = stackTrace; + this._request = request; + + this._customFormatters = { + "object": this._formatParameterAsObject, + "array": this._formatParameterAsArray, + "node": this._formatParameterAsNode, + "string": this._formatParameterAsString + }; +} + +WebInspector.ConsoleMessageImpl.prototype = { + _formatMessage: function() + { + this._formattedMessage = document.createElement("span"); + this._formattedMessage.className = "console-message-text source-code"; + + if (this.source === WebInspector.ConsoleMessage.MessageSource.ConsoleAPI) { + switch (this.type) { + case WebInspector.ConsoleMessage.MessageType.Trace: + this._messageElement = document.createTextNode("console.trace()"); + break; + case WebInspector.ConsoleMessage.MessageType.Assert: + var args = [WebInspector.UIString("Assertion failed:")]; + if (this._parameters) + args = args.concat(this._parameters); + this._messageElement = this._format(args); + break; + case WebInspector.ConsoleMessage.MessageType.Dir: + var obj = this._parameters ? this._parameters[0] : undefined; + var args = ["%O", obj]; + this._messageElement = this._format(args); + break; + default: + var args = this._parameters || [this._messageText]; + this._messageElement = this._format(args); + } + } else if (this.source === WebInspector.ConsoleMessage.MessageSource.Network) { + if (this._request) { + this._stackTrace = this._request.stackTrace; + if (this._request.initiator && this._request.initiator.url) { + this.url = this._request.initiator.url; + this.line = this._request.initiator.lineNumber; + } + this._messageElement = document.createElement("span"); + if (this.level === WebInspector.ConsoleMessage.MessageLevel.Error) { + this._messageElement.appendChild(document.createTextNode(this._request.requestMethod + " ")); + this._messageElement.appendChild(WebInspector.linkifyRequestAsNode(this._request)); + if (this._request.failed) + this._messageElement.appendChild(document.createTextNode(" " + this._request.localizedFailDescription)); + else + this._messageElement.appendChild(document.createTextNode(" " + this._request.statusCode + " (" + this._request.statusText + ")")); + } else { + var fragment = WebInspector.linkifyStringAsFragmentWithCustomLinkifier(this._messageText, WebInspector.linkifyRequestAsNode.bind(null, this._request, "")); + this._messageElement.appendChild(fragment); + } + } else { + if (this.url) { + var isExternal = !WebInspector.resourceForURL(this.url); + this._anchorElement = WebInspector.linkifyURLAsNode(this.url, this.url, "console-message-url", isExternal); + } + this._messageElement = this._format([this._messageText]); + } + } else { + var args = this._parameters || [this._messageText]; + this._messageElement = this._format(args); + } + + if (this.source !== WebInspector.ConsoleMessage.MessageSource.Network || this._request) { + if (this._stackTrace && this._stackTrace.length && this._stackTrace[0].url) { + this._anchorElement = this._linkifyCallFrame(this._stackTrace[0]); + } else if (this.url && this.url !== "undefined") { + this._anchorElement = this._linkifyLocation(this.url, this.line, 0); + } + } + + if (this._anchorElement) + this._formattedMessage.appendChild(this._anchorElement); + this._formattedMessage.appendChild(this._messageElement); + + var dumpStackTrace = !!this._stackTrace && this._stackTrace.length && (this.source === WebInspector.ConsoleMessage.MessageSource.Network || this.level === WebInspector.ConsoleMessage.MessageLevel.Error || this.type === WebInspector.ConsoleMessage.MessageType.Trace); + if (dumpStackTrace) { + var ol = document.createElement("ol"); + ol.className = "outline-disclosure"; + var treeOutline = new TreeOutline(ol); + + var content = this._formattedMessage; + var root = new TreeElement(content, null, true); + content.treeElementForTest = root; + treeOutline.appendChild(root); + if (this.type === WebInspector.ConsoleMessage.MessageType.Trace) + root.expand(); + + this._populateStackTraceTreeElement(root); + this._formattedMessage = ol; + } + + // This is used for inline message bubbles in SourceFrames, or other plain-text representations. + this._message = this._messageElement.textContent; + }, + + get message() + { + // force message formatting + var formattedMessage = this.formattedMessage; + return this._message; + }, + + get formattedMessage() + { + if (!this._formattedMessage) + this._formatMessage(); + return this._formattedMessage; + }, + + _linkifyLocation: function(url, lineNumber, columnNumber) + { + // FIXME(62725): stack trace line/column numbers are one-based. + lineNumber = lineNumber ? lineNumber - 1 : 0; + columnNumber = columnNumber ? columnNumber - 1 : 0; + return this._linkifier.linkifyLocation(url, lineNumber, columnNumber, "console-message-url"); + }, + + _linkifyCallFrame: function(callFrame) + { + return this._linkifyLocation(callFrame.url, callFrame.lineNumber, callFrame.columnNumber); + }, + + isErrorOrWarning: function() + { + return (this.level === WebInspector.ConsoleMessage.MessageLevel.Warning || this.level === WebInspector.ConsoleMessage.MessageLevel.Error); + }, + + _format: function(parameters) + { + // This node is used like a Builder. Values are continually appended onto it. + var formattedResult = document.createElement("span"); + if (!parameters.length) + return formattedResult; + + // Formatting code below assumes that parameters are all wrappers whereas frontend console + // API allows passing arbitrary values as messages (strings, numbers, etc.). Wrap them here. + for (var i = 0; i < parameters.length; ++i) { + // FIXME: Only pass runtime wrappers here. + if (parameters[i] instanceof WebInspector.RemoteObject) + continue; + + if (typeof parameters[i] === "object") + parameters[i] = WebInspector.RemoteObject.fromPayload(parameters[i]); + else + parameters[i] = WebInspector.RemoteObject.fromPrimitiveValue(parameters[i]); + } + + // There can be string log and string eval result. We distinguish between them based on message type. + var shouldFormatMessage = WebInspector.RemoteObject.type(parameters[0]) === "string" && this.type !== WebInspector.ConsoleMessage.MessageType.Result; + + // Multiple parameters with the first being a format string. Save unused substitutions. + if (shouldFormatMessage) { + // Multiple parameters with the first being a format string. Save unused substitutions. + var result = this._formatWithSubstitutionString(parameters, formattedResult); + parameters = result.unusedSubstitutions; + if (parameters.length) + formattedResult.appendChild(document.createTextNode(" ")); + } + + // Single parameter, or unused substitutions from above. + for (var i = 0; i < parameters.length; ++i) { + // Inline strings when formatting. + if (shouldFormatMessage && parameters[i].type === "string") + formattedResult.appendChild(document.createTextNode(parameters[i].description)); + else + formattedResult.appendChild(this._formatParameter(parameters[i])); + if (i < parameters.length - 1) + formattedResult.appendChild(document.createTextNode(" ")); + } + return formattedResult; + }, + + /** + * @param {boolean=} forceObjectFormat + */ + _formatParameter: function(output, forceObjectFormat) + { + var type; + if (forceObjectFormat) + type = "object"; + else if (output instanceof WebInspector.RemoteObject) + type = output.subtype || output.type; + else + type = typeof output; + + var formatter = this._customFormatters[type]; + if (!formatter) { + formatter = this._formatParameterAsValue; + output = output.description; + } + + var span = document.createElement("span"); + span.className = "console-formatted-" + type + " source-code"; + formatter.call(this, output, span); + return span; + }, + + _formatParameterAsValue: function(val, elem) + { + elem.appendChild(document.createTextNode(val)); + }, + + _formatParameterAsObject: function(obj, elem) + { + elem.appendChild(new WebInspector.ObjectPropertiesSection(obj, obj.description).element); + }, + + _formatParameterAsNode: function(object, elem) + { + function printNode(nodeId) + { + if (!nodeId) { + // Sometimes DOM is loaded after the sync message is being formatted, so we get no + // nodeId here. So we fall back to object formatting here. + this._formatParameterAsObject(object, elem); + return; + } + var treeOutline = new WebInspector.ElementsTreeOutline(false, false, true); + treeOutline.setVisible(true); + treeOutline.rootDOMNode = WebInspector.domAgent.nodeForId(nodeId); + treeOutline.element.addStyleClass("outline-disclosure"); + if (!treeOutline.children[0].hasChildren) + treeOutline.element.addStyleClass("single-node"); + elem.appendChild(treeOutline.element); + } + object.pushNodeToFrontend(printNode.bind(this)); + }, + + _formatParameterAsArray: function(arr, elem) + { + arr.getOwnProperties(this._printArray.bind(this, elem)); + }, + + _formatParameterAsString: function(output, elem) + { + var span = document.createElement("span"); + span.className = "console-formatted-string source-code"; + span.appendChild(WebInspector.linkifyStringAsFragment(output.description)); + + // Make black quotes. + elem.removeStyleClass("console-formatted-string"); + elem.appendChild(document.createTextNode("\"")); + elem.appendChild(span); + elem.appendChild(document.createTextNode("\"")); + }, + + _printArray: function(elem, properties) + { + if (!properties) + return; + + var elements = []; + for (var i = 0; i < properties.length; ++i) { + var name = properties[i].name; + if (name == parseInt(name, 10)) + elements[name] = this._formatAsArrayEntry(properties[i].value); + } + + elem.appendChild(document.createTextNode("[")); + for (var i = 0; i < elements.length; ++i) { + var element = elements[i]; + if (element) + elem.appendChild(element); + else + elem.appendChild(document.createTextNode("undefined")) + if (i < elements.length - 1) + elem.appendChild(document.createTextNode(", ")); + } + elem.appendChild(document.createTextNode("]")); + }, + + _formatAsArrayEntry: function(output) + { + // Prevent infinite expansion of cross-referencing arrays. + return this._formatParameter(output, output.subtype && output.subtype === "array"); + }, + + _formatWithSubstitutionString: function(parameters, formattedResult) + { + var formatters = {} + + function parameterFormatter(force, obj) + { + return this._formatParameter(obj, force); + } + + function valueFormatter(obj) + { + return obj.description; + } + + // Firebug uses %o for formatting objects. + formatters.o = parameterFormatter.bind(this, false); + formatters.s = valueFormatter; + formatters.f = valueFormatter; + // Firebug allows both %i and %d for formatting integers. + formatters.i = valueFormatter; + formatters.d = valueFormatter; + + // Support %O to force object formatting, instead of the type-based %o formatting. + formatters.O = parameterFormatter.bind(this, true); + + function append(a, b) + { + if (!(b instanceof Node)) + a.appendChild(WebInspector.linkifyStringAsFragment(b.toString())); + else + a.appendChild(b); + return a; + } + + // String.format does treat formattedResult like a Builder, result is an object. + return String.format(parameters[0].description, parameters.slice(1), formatters, formattedResult, append); + }, + + clearHighlight: function() + { + if (!this._formattedMessage) + return; + + var highlightedMessage = this._formattedMessage; + delete this._formattedMessage; + delete this._anchorElement; + delete this._messageElement; + this._formatMessage(); + this._element.replaceChild(this._formattedMessage, highlightedMessage); + }, + + highlightSearchResults: function(regexObject) + { + if (!this._formattedMessage) + return; + + this._highlightSearchResultsInElement(regexObject, this._messageElement); + if (this._anchorElement) + this._highlightSearchResultsInElement(regexObject, this._anchorElement); + + this._element.scrollIntoViewIfNeeded(); + }, + + _highlightSearchResultsInElement: function(regexObject, element) + { + regexObject.lastIndex = 0; + var text = element.textContent; + var match = regexObject.exec(text); + var offset = 0; + var matchRanges = []; + while (match) { + matchRanges.push({ offset: match.index, length: match[0].length }); + match = regexObject.exec(text); + } + highlightSearchResults(element, matchRanges); + }, + + matchesRegex: function(regexObject) + { + return regexObject.test(this._message) || (this._anchorElement && regexObject.test(this._anchorElement.textContent)); + }, + + toMessageElement: function() + { + if (this._element) + return this._element; + + var element = document.createElement("div"); + element.message = this; + element.className = "console-message"; + + this._element = element; + + switch (this.level) { + case WebInspector.ConsoleMessage.MessageLevel.Tip: + element.addStyleClass("console-tip-level"); + break; + case WebInspector.ConsoleMessage.MessageLevel.Log: + element.addStyleClass("console-log-level"); + break; + case WebInspector.ConsoleMessage.MessageLevel.Debug: + element.addStyleClass("console-debug-level"); + break; + case WebInspector.ConsoleMessage.MessageLevel.Warning: + element.addStyleClass("console-warning-level"); + break; + case WebInspector.ConsoleMessage.MessageLevel.Error: + element.addStyleClass("console-error-level"); + break; + } + + if (this.type === WebInspector.ConsoleMessage.MessageType.StartGroup || this.type === WebInspector.ConsoleMessage.MessageType.StartGroupCollapsed) + element.addStyleClass("console-group-title"); + + element.appendChild(this.formattedMessage); + + if (this.repeatCount > 1) + this.updateRepeatCount(); + + return element; + }, + + _populateStackTraceTreeElement: function(parentTreeElement) + { + for (var i = 0; i < this._stackTrace.length; i++) { + var frame = this._stackTrace[i]; + + var content = document.createElement("div"); + var messageTextElement = document.createElement("span"); + messageTextElement.className = "console-message-text source-code"; + var functionName = frame.functionName || WebInspector.UIString("(anonymous function)"); + messageTextElement.appendChild(document.createTextNode(functionName)); + content.appendChild(messageTextElement); + + if (frame.url) { + var urlElement = this._linkifyCallFrame(frame); + content.appendChild(urlElement); + } + + var treeElement = new TreeElement(content); + parentTreeElement.appendChild(treeElement); + } + }, + + updateRepeatCount: function() { + if (!this.repeatCountElement) { + this.repeatCountElement = document.createElement("span"); + this.repeatCountElement.className = "bubble"; + + this._element.insertBefore(this.repeatCountElement, this._element.firstChild); + this._element.addStyleClass("repeated-message"); + } + this.repeatCountElement.textContent = this.repeatCount; + }, + + toString: function() + { + var sourceString; + switch (this.source) { + case WebInspector.ConsoleMessage.MessageSource.HTML: + sourceString = "HTML"; + break; + case WebInspector.ConsoleMessage.MessageSource.XML: + sourceString = "XML"; + break; + case WebInspector.ConsoleMessage.MessageSource.JS: + sourceString = "JS"; + break; + case WebInspector.ConsoleMessage.MessageSource.Network: + sourceString = "Network"; + break; + case WebInspector.ConsoleMessage.MessageSource.ConsoleAPI: + sourceString = "ConsoleAPI"; + break; + case WebInspector.ConsoleMessage.MessageSource.Other: + sourceString = "Other"; + break; + } + + var typeString; + switch (this.type) { + case WebInspector.ConsoleMessage.MessageType.Log: + typeString = "Log"; + break; + case WebInspector.ConsoleMessage.MessageType.Dir: + typeString = "Dir"; + break; + case WebInspector.ConsoleMessage.MessageType.DirXML: + typeString = "Dir XML"; + break; + case WebInspector.ConsoleMessage.MessageType.Trace: + typeString = "Trace"; + break; + case WebInspector.ConsoleMessage.MessageType.StartGroupCollapsed: + case WebInspector.ConsoleMessage.MessageType.StartGroup: + typeString = "Start Group"; + break; + case WebInspector.ConsoleMessage.MessageType.EndGroup: + typeString = "End Group"; + break; + case WebInspector.ConsoleMessage.MessageType.Assert: + typeString = "Assert"; + break; + case WebInspector.ConsoleMessage.MessageType.Result: + typeString = "Result"; + break; + } + + var levelString; + switch (this.level) { + case WebInspector.ConsoleMessage.MessageLevel.Tip: + levelString = "Tip"; + break; + case WebInspector.ConsoleMessage.MessageLevel.Log: + levelString = "Log"; + break; + case WebInspector.ConsoleMessage.MessageLevel.Warning: + levelString = "Warning"; + break; + case WebInspector.ConsoleMessage.MessageLevel.Debug: + levelString = "Debug"; + break; + case WebInspector.ConsoleMessage.MessageLevel.Error: + levelString = "Error"; + break; + } + + return sourceString + " " + typeString + " " + levelString + ": " + this.formattedMessage.textContent + "\n" + this.url + " line " + this.line; + }, + + get text() + { + return this._messageText; + }, + + isEqual: function(msg) + { + if (!msg) + return false; + + if (this._stackTrace) { + if (!msg._stackTrace) + return false; + var l = this._stackTrace; + var r = msg._stackTrace; + for (var i = 0; i < l.length; i++) { + if (l[i].url !== r[i].url || + l[i].functionName !== r[i].functionName || + l[i].lineNumber !== r[i].lineNumber || + l[i].columnNumber !== r[i].columnNumber) + return false; + } + } + + return (this.source === msg.source) + && (this.type === msg.type) + && (this.level === msg.level) + && (this.line === msg.line) + && (this.url === msg.url) + && (this.message === msg.message) + && (this._request === msg._request); + }, + + get stackTrace() + { + return this._stackTrace; + }, + + /** + * @return {WebInspector.ConsoleMessage} + */ + clone: function() + { + return WebInspector.ConsoleMessage.create(this.source, this.level, this._messageText, this.type, this.url, this.line, this.repeatCount, this._parameters, this._stackTrace, this._request); + } +} + +WebInspector.ConsoleMessageImpl.prototype.__proto__ = WebInspector.ConsoleMessage.prototype; +/* ConsoleView.js */ + +/* + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2009 Joseph Pecoraro + * + * 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. + */ + +const ExpressionStopCharacters = " =:[({;,!+-*/&|^<>"; + +/** + * @extends {WebInspector.View} + * @constructor + * @param {boolean} hideContextSelector + */ +WebInspector.ConsoleView = function(hideContextSelector) +{ + WebInspector.View.call(this); + + this.element.id = "console-view"; + this.messages = []; + + this._clearConsoleButton = new WebInspector.StatusBarButton(WebInspector.UIString("Clear console log."), "clear-status-bar-item"); + this._clearConsoleButton.addEventListener("click", this._requestClearMessages, this); + + this._contextSelectElement = document.createElement("select"); + this._contextSelectElement.id = "console-context"; + this._contextSelectElement.className = "status-bar-item"; + + if (hideContextSelector) + this._contextSelectElement.addStyleClass("hidden"); + + this.messagesElement = document.createElement("div"); + this.messagesElement.id = "console-messages"; + this.messagesElement.className = "monospace"; + this.messagesElement.addEventListener("click", this._messagesClicked.bind(this), true); + this.element.appendChild(this.messagesElement); + this._scrolledToBottom = true; + + this.promptElement = document.createElement("div"); + this.promptElement.id = "console-prompt"; + this.promptElement.className = "source-code"; + this.promptElement.spellcheck = false; + this.messagesElement.appendChild(this.promptElement); + this.messagesElement.appendChild(document.createElement("br")); + + this.topGroup = new WebInspector.ConsoleGroup(null); + this.messagesElement.insertBefore(this.topGroup.element, this.promptElement); + this.currentGroup = this.topGroup; + + this._filterBarElement = document.createElement("div"); + this._filterBarElement.id = "console-filter"; + this._filterBarElement.className = "scope-bar status-bar-item"; + + function createDividerElement() { + var dividerElement = document.createElement("div"); + dividerElement.addStyleClass("scope-bar-divider"); + this._filterBarElement.appendChild(dividerElement); + } + + var updateFilterHandler = this._updateFilter.bind(this); + function createFilterElement(category, label) { + var categoryElement = document.createElement("li"); + categoryElement.category = category; + categoryElement.className = category; + categoryElement.addEventListener("click", updateFilterHandler, false); + categoryElement.textContent = label; + + this._filterBarElement.appendChild(categoryElement); + + return categoryElement; + } + + this.allElement = createFilterElement.call(this, "all", WebInspector.UIString("All")); + createDividerElement.call(this); + this.errorElement = createFilterElement.call(this, "errors", WebInspector.UIString("Errors")); + this.warningElement = createFilterElement.call(this, "warnings", WebInspector.UIString("Warnings")); + this.logElement = createFilterElement.call(this, "logs", WebInspector.UIString("Logs")); + + this.filter(this.allElement, false); + this._registerShortcuts(); + this.registerRequiredCSS("textPrompt.css"); + + this.messagesElement.addEventListener("contextmenu", this._handleContextMenuEvent.bind(this), false); + + WebInspector.settings.monitoringXHREnabled.addChangeListener(this._monitoringXHREnabledSettingChanged.bind(this)); + + WebInspector.console.addEventListener(WebInspector.ConsoleModel.Events.MessageAdded, this._consoleMessageAdded, this); + WebInspector.console.addEventListener(WebInspector.ConsoleModel.Events.ConsoleCleared, this._consoleCleared, this); + + this._linkifier = WebInspector.debuggerPresentationModel.createLinkifier(); + + this.prompt = new WebInspector.TextPromptWithHistory(this.completions.bind(this), ExpressionStopCharacters + "."); + this.prompt.setSuggestBoxEnabled("generic-suggest"); + this.prompt.renderAsBlock(); + this.prompt.attach(this.promptElement); + this.prompt.proxyElement.addEventListener("keydown", this._promptKeyDown.bind(this), false); + this.prompt.setHistoryData(WebInspector.settings.consoleHistory.get()); +} + +WebInspector.ConsoleView.Events = { + ConsoleCleared: "console-cleared", + EntryAdded: "console-entry-added", +} + +WebInspector.ConsoleView.prototype = { + get statusBarItems() + { + return [this._clearConsoleButton.element, this._contextSelectElement, this._filterBarElement]; + }, + + addContext: function(context) + { + var option = document.createElement("option"); + option.text = context.displayName; + option.title = context.url; + option._context = context; + context._consoleOption = option; + this._contextSelectElement.appendChild(option); + context.addEventListener(WebInspector.FrameEvaluationContext.EventTypes.Updated, this._contextUpdated, this); + }, + + removeContext: function(context) + { + this._contextSelectElement.removeChild(context._consoleOption); + }, + + _contextUpdated: function(event) + { + var context = event.data; + var option= context._consoleOption; + option.text = context.displayName; + option.title = context.url; + }, + + _currentEvaluationContextId: function() + { + if (this._contextSelectElement.selectedIndex === -1) + return undefined; + return this._contextSelectElement[this._contextSelectElement.selectedIndex]._context.frameId; + }, + + _updateFilter: function(e) + { + var isMac = WebInspector.isMac(); + var selectMultiple = false; + if (isMac && e.metaKey && !e.ctrlKey && !e.altKey && !e.shiftKey) + selectMultiple = true; + if (!isMac && e.ctrlKey && !e.metaKey && !e.altKey && !e.shiftKey) + selectMultiple = true; + + this.filter(e.target, selectMultiple); + }, + + filter: function(target, selectMultiple) + { + function unselectAll() + { + this.allElement.removeStyleClass("selected"); + this.errorElement.removeStyleClass("selected"); + this.warningElement.removeStyleClass("selected"); + this.logElement.removeStyleClass("selected"); + + this.messagesElement.removeStyleClass("filter-all"); + this.messagesElement.removeStyleClass("filter-errors"); + this.messagesElement.removeStyleClass("filter-warnings"); + this.messagesElement.removeStyleClass("filter-logs"); + } + + var targetFilterClass = "filter-" + target.category; + + if (target.category === "all") { + if (target.hasStyleClass("selected")) { + // We can't unselect all, so we break early here + return; + } + + unselectAll.call(this); + } else { + // Something other than all is being selected, so we want to unselect all + if (this.allElement.hasStyleClass("selected")) { + this.allElement.removeStyleClass("selected"); + this.messagesElement.removeStyleClass("filter-all"); + } + } + + if (!selectMultiple) { + // If multiple selection is off, we want to unselect everything else + // and just select ourselves. + unselectAll.call(this); + + target.addStyleClass("selected"); + this.messagesElement.addStyleClass(targetFilterClass); + + return; + } + + if (target.hasStyleClass("selected")) { + // If selectMultiple is turned on, and we were selected, we just + // want to unselect ourselves. + target.removeStyleClass("selected"); + this.messagesElement.removeStyleClass(targetFilterClass); + } else { + // If selectMultiple is turned on, and we weren't selected, we just + // want to select ourselves. + target.addStyleClass("selected"); + this.messagesElement.addStyleClass(targetFilterClass); + } + }, + + willHide: function() + { + this.prompt.hideSuggestBox(); + this.prompt.clearAutoComplete(true); + }, + + wasShown: function() + { + if (!this.prompt.isCaretInsidePrompt()) + this.prompt.moveCaretToEndOfPrompt(); + }, + + afterShow: function() + { + WebInspector.setCurrentFocusElement(this.promptElement); + }, + + storeScrollPositions: function() + { + WebInspector.View.prototype.storeScrollPositions.call(this); + this._scrolledToBottom = this.messagesElement.isScrolledToBottom(); + }, + + restoreScrollPositions: function() + { + if (this._scrolledToBottom) + this._immediatelyScrollIntoView(); + else + WebInspector.View.prototype.restoreScrollPositions.call(this); + }, + + onResize: function() + { + this.restoreScrollPositions(); + }, + + _isScrollIntoViewScheduled: function() + { + return !!this._scrollIntoViewTimer; + }, + + _scheduleScrollIntoView: function() + { + if (this._scrollIntoViewTimer) + return; + + function scrollIntoView() + { + delete this._scrollIntoViewTimer; + this.promptElement.scrollIntoView(true); + } + this._scrollIntoViewTimer = setTimeout(scrollIntoView.bind(this), 20); + }, + + _immediatelyScrollIntoView: function() + { + this.promptElement.scrollIntoView(true); + this._cancelScheduledScrollIntoView(); + }, + + _cancelScheduledScrollIntoView: function() + { + if (!this._isScrollIntoViewScheduled()) + return; + + clearTimeout(this._scrollIntoViewTimer); + delete this._scrollIntoViewTimer; + }, + + _consoleMessageAdded: function(event) + { + this._appendConsoleMessage(event.data); + }, + + _appendConsoleMessage: function(msg) + { + // this.messagesElement.isScrolledToBottom() is forcing style recalculation. + // We just skip it if the scroll action has been scheduled. + if (!this._isScrollIntoViewScheduled() && ((msg instanceof WebInspector.ConsoleCommandResult) || this.messagesElement.isScrolledToBottom())) + this._scheduleScrollIntoView(); + + this.messages.push(msg); + + if (msg.type === WebInspector.ConsoleMessage.MessageType.EndGroup) { + var parentGroup = this.currentGroup.parentGroup + if (parentGroup) + this.currentGroup = parentGroup; + } else { + if (msg.type === WebInspector.ConsoleMessage.MessageType.StartGroup || msg.type === WebInspector.ConsoleMessage.MessageType.StartGroupCollapsed) { + var group = new WebInspector.ConsoleGroup(this.currentGroup); + this.currentGroup.messagesElement.appendChild(group.element); + this.currentGroup = group; + } + + this.currentGroup.addMessage(msg); + } + + this.dispatchEventToListeners(WebInspector.ConsoleView.Events.EntryAdded, msg); + }, + + _consoleCleared: function() + { + this._scrolledToBottom = true; + this.messages = []; + + this.currentGroup = this.topGroup; + this.topGroup.messagesElement.removeChildren(); + + this.dispatchEventToListeners(WebInspector.ConsoleView.Events.ConsoleCleared); + + this._linkifier.reset(); + }, + + completions: function(wordRange, force, completionsReadyCallback) + { + // Pass less stop characters to rangeOfWord so the range will be a more complete expression. + var expressionRange = wordRange.startContainer.rangeOfWord(wordRange.startOffset, ExpressionStopCharacters, this.promptElement, "backward"); + var expressionString = expressionRange.toString(); + var prefix = wordRange.toString(); + this._completions(expressionString, prefix, force, completionsReadyCallback); + }, + + _completions: function(expressionString, prefix, force, completionsReadyCallback) + { + var lastIndex = expressionString.length - 1; + + var dotNotation = (expressionString[lastIndex] === "."); + var bracketNotation = (expressionString[lastIndex] === "["); + + if (dotNotation || bracketNotation) + expressionString = expressionString.substr(0, lastIndex); + + if (expressionString && parseInt(expressionString, 10) == expressionString) { + // User is entering float value, do not suggest anything. + completionsReadyCallback([]); + return; + } + + if (!prefix && !expressionString && !force) { + completionsReadyCallback([]); + return; + } + + if (!expressionString && WebInspector.debuggerPresentationModel.paused) + WebInspector.debuggerPresentationModel.getSelectedCallFrameVariables(receivedPropertyNames.bind(this)); + else + this.evalInInspectedWindow(expressionString, "completion", true, true, false, evaluated.bind(this)); + + function evaluated(result, wasThrown) + { + if (!result || wasThrown) { + completionsReadyCallback([]); + return; + } + + function getCompletions(primitiveType) + { + var object; + if (primitiveType === "string") + object = new String(""); + else if (primitiveType === "number") + object = new Number(0); + else if (primitiveType === "boolean") + object = new Boolean(false); + else + object = this; + + var resultSet = {}; + for (var o = object; o; o = o.__proto__) { + try { + var names = Object.getOwnPropertyNames(o); + for (var i = 0; i < names.length; ++i) + resultSet[names[i]] = true; + } catch (e) { + } + } + return resultSet; + } + + if (result.type === "object" || result.type === "function") + result.callFunctionJSON(getCompletions, receivedPropertyNames.bind(this)); + else if (result.type === "string" || result.type === "number" || result.type === "boolean") + this.evalInInspectedWindow("(" + getCompletions + ")(\"" + result.type + "\")", "completion", false, true, true, receivedPropertyNamesFromEval.bind(this)); + } + + function receivedPropertyNamesFromEval(notRelevant, wasThrown, result) + { + if (result && !wasThrown) + receivedPropertyNames.call(this, result.value); + else + completionsReadyCallback([]); + } + + function receivedPropertyNames(propertyNames) + { + RuntimeAgent.releaseObjectGroup("completion"); + if (!propertyNames) { + completionsReadyCallback([]); + return; + } + var includeCommandLineAPI = (!dotNotation && !bracketNotation); + if (includeCommandLineAPI) { + const commandLineAPI = ["dir", "dirxml", "keys", "values", "profile", "profileEnd", "monitorEvents", "unmonitorEvents", "inspect", "copy", "clear"]; + for (var i = 0; i < commandLineAPI.length; ++i) + propertyNames[commandLineAPI[i]] = true; + } + this._reportCompletions(completionsReadyCallback, dotNotation, bracketNotation, expressionString, prefix, Object.keys(propertyNames)); + } + }, + + _reportCompletions: function(completionsReadyCallback, dotNotation, bracketNotation, expressionString, prefix, properties) { + if (bracketNotation) { + if (prefix.length && prefix[0] === "'") + var quoteUsed = "'"; + else + var quoteUsed = "\""; + } + + var results = []; + + if (!expressionString) { + const keywords = ["break", "case", "catch", "continue", "default", "delete", "do", "else", "finally", "for", "function", "if", "in", + "instanceof", "new", "return", "switch", "this", "throw", "try", "typeof", "var", "void", "while", "with"]; + properties = properties.concat(keywords); + } + + properties.sort(); + + for (var i = 0; i < properties.length; ++i) { + var property = properties[i]; + + if (dotNotation && !/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(property)) + continue; + + if (bracketNotation) { + if (!/^[0-9]+$/.test(property)) + property = quoteUsed + property.escapeCharacters(quoteUsed + "\\") + quoteUsed; + property += "]"; + } + + if (property.length < prefix.length) + continue; + if (prefix.length && property.indexOf(prefix) !== 0) + continue; + + results.push(property); + } + completionsReadyCallback(results); + }, + + _handleContextMenuEvent: function(event) + { + if (!window.getSelection().isCollapsed) { + // If there is a selection, we want to show our normal context menu + // (with Copy, etc.), and not Clear Console. + return; + } + + var contextMenu = new WebInspector.ContextMenu(); + + if (WebInspector.populateHrefContextMenu(contextMenu, null, event)) + contextMenu.appendSeparator(); + + function monitoringXHRItemAction() + { + WebInspector.settings.monitoringXHREnabled.set(!WebInspector.settings.monitoringXHREnabled.get()); + } + contextMenu.appendCheckboxItem(WebInspector.UIString("Log XMLHttpRequests"), monitoringXHRItemAction.bind(this), WebInspector.settings.monitoringXHREnabled.get()); + + function preserveLogItemAction() + { + WebInspector.settings.preserveConsoleLog.set(!WebInspector.settings.preserveConsoleLog.get()); + } + contextMenu.appendCheckboxItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Preserve log upon navigation" : "Preserve Log upon Navigation"), preserveLogItemAction.bind(this), WebInspector.settings.preserveConsoleLog.get()); + + contextMenu.appendSeparator(); + contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Clear console" : "Clear Console"), this._requestClearMessages.bind(this)); + contextMenu.show(event); + }, + + _monitoringXHREnabledSettingChanged: function(event) + { + ConsoleAgent.setMonitoringXHREnabled(event.data); + }, + + _messagesClicked: function(event) + { + if (!this.prompt.isCaretInsidePrompt() && window.getSelection().isCollapsed) + this.prompt.moveCaretToEndOfPrompt(); + }, + + _registerShortcuts: function() + { + this._shortcuts = {}; + + var shortcut = WebInspector.KeyboardShortcut; + + if (WebInspector.isMac()) { + var shortcutK = shortcut.makeDescriptor("k", WebInspector.KeyboardShortcut.Modifiers.Meta); + this._shortcuts[shortcutK.key] = this._requestClearMessages.bind(this); + } + + var shortcutL = shortcut.makeDescriptor("l", WebInspector.KeyboardShortcut.Modifiers.Ctrl); + this._shortcuts[shortcutL.key] = this._requestClearMessages.bind(this); + + var shortcutM = shortcut.makeDescriptor("m", WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta | WebInspector.KeyboardShortcut.Modifiers.Shift); + this._shortcuts[shortcutM.key] = this._dumpMemory.bind(this); + + var section = WebInspector.shortcutsScreen.section(WebInspector.UIString("Console")); + var keys = WebInspector.isMac() ? [ shortcutK.name, shortcutL.name ] : [ shortcutL.name ]; + section.addAlternateKeys(keys, WebInspector.UIString("Clear Console")); + + keys = [ + shortcut.shortcutToString(shortcut.Keys.Tab), + shortcut.shortcutToString(shortcut.Keys.Tab, shortcut.Modifiers.Shift) + ]; + section.addRelatedKeys(keys, WebInspector.UIString("Next/previous suggestion")); + section.addKey(shortcut.shortcutToString(shortcut.Keys.Right), WebInspector.UIString("Accept suggestion")); + keys = [ + shortcut.shortcutToString(shortcut.Keys.Down), + shortcut.shortcutToString(shortcut.Keys.Up) + ]; + section.addRelatedKeys(keys, WebInspector.UIString("Next/previous line")); + keys = [ + shortcut.shortcutToString("N", shortcut.Modifiers.Alt), + shortcut.shortcutToString("P", shortcut.Modifiers.Alt) + ]; + if (WebInspector.isMac()) + section.addRelatedKeys(keys, WebInspector.UIString("Next/previous command")); + section.addKey(shortcut.shortcutToString(shortcut.Keys.Enter), WebInspector.UIString("Execute command")); + }, + + _requestClearMessages: function() + { + WebInspector.console.requestClearMessages(); + }, + + _promptKeyDown: function(event) + { + if (isEnterKey(event)) { + this._enterKeyPressed(event); + return; + } + + var shortcut = WebInspector.KeyboardShortcut.makeKeyFromEvent(event); + var handler = this._shortcuts[shortcut]; + if (handler) { + handler(); + event.preventDefault(); + return; + } + }, + + /** + * @param {string} expression + * @param {string} objectGroup + * @param {boolean} includeCommandLineAPI + * @param {boolean} doNotPauseOnExceptions + * @param {boolean} returnByValue + * @param {function(?WebInspector.RemoteObject, boolean, RuntimeAgent.RemoteObject=)} callback + */ + evalInInspectedWindow: function(expression, objectGroup, includeCommandLineAPI, doNotPauseOnExceptions, returnByValue, callback) + { + if (WebInspector.debuggerPresentationModel.paused) { + WebInspector.debuggerPresentationModel.evaluateInSelectedCallFrame(expression, objectGroup, includeCommandLineAPI, returnByValue, callback); + return; + } + + if (!expression) { + // There is no expression, so the completion should happen against global properties. + expression = "this"; + } + + function evalCallback(error, result, wasThrown) + { + if (error) { + console.error(error); + callback(null, false); + return; + } + + if (returnByValue) + callback(null, wasThrown, wasThrown ? null : result); + else + callback(WebInspector.RemoteObject.fromPayload(result), wasThrown); + } + RuntimeAgent.evaluate(expression, objectGroup, includeCommandLineAPI, doNotPauseOnExceptions, this._currentEvaluationContextId(), returnByValue, evalCallback); + }, + + evaluateUsingTextPrompt: function(expression) + { + this._appendCommand(expression, this.prompt.text); + }, + + _enterKeyPressed: function(event) + { + if (event.altKey || event.ctrlKey || event.shiftKey) + return; + + event.preventDefault(); + event.stopPropagation(); + + this.prompt.clearAutoComplete(true); + + var str = this.prompt.text; + if (!str.length) + return; + this._appendCommand(str, ""); + }, + + _appendCommand: function(text, newPromptText) + { + var commandMessage = new WebInspector.ConsoleCommand(text); + WebInspector.console.interruptRepeatCount(); + this._appendConsoleMessage(commandMessage); + + function printResult(result, wasThrown) + { + if (!result) + return; + + this.prompt.pushHistoryItem(text); + this.prompt.text = newPromptText; + + WebInspector.settings.consoleHistory.set(this.prompt.historyData.slice(-30)); + + this._appendConsoleMessage(new WebInspector.ConsoleCommandResult(result, wasThrown, commandMessage, this._linkifier)); + } + this.evalInInspectedWindow(text, "console", true, false, false, printResult.bind(this)); + + WebInspector.userMetrics.ConsoleEvaluated.record(); + }, + + elementsToRestoreScrollPositionsFor: function() + { + return [this.messagesElement]; + }, + + _dumpMemory: function() + { + function comparator(a, b) + { + if (a.size < b.size) + return 1; + if (a.size > b.size) + return -1; + return a.title.localeCompare(b.title); + } + + function callback(error, groups) + { + var titles = []; + groups.sort(comparator); + for (var i = 0; i < groups.length; ++i) { + var suffix = groups[i].size > 0 ? " [" + groups[i].size + "]" : ""; + titles.push(groups[i].title + suffix + (groups[i].documentURI ? " (" + groups[i].documentURI + ")" : "")); + } + + var counter = 1; + var previousTitle = null; + for (var i = 0; i < titles.length; ++i) { + var title = titles[i]; + if (title === previousTitle) { + counter++; + continue; + } + if (previousTitle) + WebInspector.log(counter > 1 ? counter + " x " + previousTitle : previousTitle); + previousTitle = title; + counter = 1; + } + WebInspector.log(counter > 1 ? counter + " x " + previousTitle : previousTitle); + } + MemoryAgent.getDOMNodeCount(callback); + } +} + +WebInspector.ConsoleView.prototype.__proto__ = WebInspector.View.prototype; + +/** + * @constructor + */ +WebInspector.ConsoleCommand = function(command) +{ + this.command = command; +} + +WebInspector.ConsoleCommand.prototype = { + clearHighlight: function() + { + var highlightedMessage = this._formattedCommand; + delete this._formattedCommand; + this._formatCommand(); + this._element.replaceChild(this._formattedCommand, highlightedMessage); + }, + + highlightSearchResults: function(regexObject) + { + regexObject.lastIndex = 0; + var text = this.command; + var match = regexObject.exec(text); + var offset = 0; + var matchRanges = []; + while (match) { + matchRanges.push({ offset: match.index, length: match[0].length }); + match = regexObject.exec(text); + } + highlightSearchResults(this._formattedCommand, matchRanges); + this._element.scrollIntoViewIfNeeded(); + }, + + matchesRegex: function(regexObject) + { + return regexObject.test(this.command); + }, + + toMessageElement: function() + { + if (!this._element) { + this._element = document.createElement("div"); + this._element.command = this; + this._element.className = "console-user-command"; + + this._formatCommand(); + this._element.appendChild(this._formattedCommand); + } + return this._element; + }, + + _formatCommand: function() + { + this._formattedCommand = document.createElement("span"); + this._formattedCommand.className = "console-message-text source-code"; + this._formattedCommand.textContent = this.command; + }, +} + +/** + * @extends {WebInspector.ConsoleMessageImpl} + * @constructor + * @param {WebInspector.DebuggerPresentationModel.Linkifier} linkifier + */ +WebInspector.ConsoleCommandResult = function(result, wasThrown, originatingCommand, linkifier) +{ + var level = (wasThrown ? WebInspector.ConsoleMessage.MessageLevel.Error : WebInspector.ConsoleMessage.MessageLevel.Log); + this.originatingCommand = originatingCommand; + WebInspector.ConsoleMessageImpl.call(this, WebInspector.ConsoleMessage.MessageSource.JS, level, "", linkifier, WebInspector.ConsoleMessage.MessageType.Result, undefined, undefined, undefined, [result]); +} + +WebInspector.ConsoleCommandResult.prototype = { + toMessageElement: function() + { + var element = WebInspector.ConsoleMessageImpl.prototype.toMessageElement.call(this); + element.addStyleClass("console-user-command-result"); + return element; + } +} + +WebInspector.ConsoleCommandResult.prototype.__proto__ = WebInspector.ConsoleMessageImpl.prototype; + +/** + * @constructor + */ +WebInspector.ConsoleGroup = function(parentGroup) +{ + this.parentGroup = parentGroup; + + var element = document.createElement("div"); + element.className = "console-group"; + element.group = this; + this.element = element; + + if (parentGroup) { + var bracketElement = document.createElement("div"); + bracketElement.className = "console-group-bracket"; + element.appendChild(bracketElement); + } + + var messagesElement = document.createElement("div"); + messagesElement.className = "console-group-messages"; + element.appendChild(messagesElement); + this.messagesElement = messagesElement; +} + +WebInspector.ConsoleGroup.prototype = { + addMessage: function(msg) + { + var element = msg.toMessageElement(); + + if (msg.type === WebInspector.ConsoleMessage.MessageType.StartGroup || msg.type === WebInspector.ConsoleMessage.MessageType.StartGroupCollapsed) { + this.messagesElement.parentNode.insertBefore(element, this.messagesElement); + element.addEventListener("click", this._titleClicked.bind(this), false); + var groupElement = element.enclosingNodeOrSelfWithClass("console-group"); + if (groupElement && msg.type === WebInspector.ConsoleMessage.MessageType.StartGroupCollapsed) + groupElement.addStyleClass("collapsed"); + } else + this.messagesElement.appendChild(element); + + if (element.previousSibling && msg.originatingCommand && element.previousSibling.command === msg.originatingCommand) + element.previousSibling.addStyleClass("console-adjacent-user-command-result"); + }, + + _titleClicked: function(event) + { + var groupTitleElement = event.target.enclosingNodeOrSelfWithClass("console-group-title"); + if (groupTitleElement) { + var groupElement = groupTitleElement.enclosingNodeOrSelfWithClass("console-group"); + if (groupElement) + if (groupElement.hasStyleClass("collapsed")) + groupElement.removeStyleClass("collapsed"); + else + groupElement.addStyleClass("collapsed"); + groupTitleElement.scrollIntoViewIfNeeded(true); + } + + event.stopPropagation(); + event.preventDefault(); + } +} + +/** + * @type {?WebInspector.ConsoleView} + */ +WebInspector.consoleView = null; + +WebInspector.ConsoleMessage.create = function(source, level, message, type, url, line, repeatCount, parameters, stackTrace, request) +{ + return new WebInspector.ConsoleMessageImpl(source, level, message, WebInspector.consoleView._linkifier, type, url, line, repeatCount, parameters, stackTrace, request); +} +/* Panel.js */ + +/* + * 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. + * 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. + */ + +/** + * @extends {WebInspector.View} + * @constructor + */ +WebInspector.Panel = function(name) +{ + WebInspector.View.call(this); + + this.element.addStyleClass("panel"); + this.element.addStyleClass(name); + this._panelName = name; + + this._shortcuts = {}; + + WebInspector.settings[this._sidebarWidthSettingName()] = WebInspector.settings.createSetting(this._sidebarWidthSettingName(), undefined); +} + +// Should by in sync with style declarations. +WebInspector.Panel.counterRightMargin = 25; + +WebInspector.Panel.prototype = { + get toolbarItem() + { + if (this._toolbarItem) + return this._toolbarItem; + + this._toolbarItem = WebInspector.Toolbar.createPanelToolbarItem(this); + return this._toolbarItem; + }, + + get name() + { + return this._panelName; + }, + + show: function() + { + WebInspector.View.prototype.show.call(this, WebInspector.inspectorView.element); + }, + + wasShown: function() + { + var statusBarItems = this.statusBarItems; + if (statusBarItems) { + this._statusBarItemContainer = document.createElement("div"); + for (var i = 0; i < statusBarItems.length; ++i) + this._statusBarItemContainer.appendChild(statusBarItems[i]); + document.getElementById("main-status-bar").appendChild(this._statusBarItemContainer); + } + + if ("_toolbarItem" in this) + this._toolbarItem.addStyleClass("toggled-on"); + + WebInspector.setCurrentFocusElement(this.defaultFocusedElement); + }, + + willHide: function() + { + if (this._statusBarItemContainer && this._statusBarItemContainer.parentNode) + this._statusBarItemContainer.parentNode.removeChild(this._statusBarItemContainer); + delete this._statusBarItemContainer; + if ("_toolbarItem" in this) + this._toolbarItem.removeStyleClass("toggled-on"); + }, + + reset: function() + { + this.searchCanceled(); + }, + + get defaultFocusedElement() + { + return this.sidebarTreeElement || this.element; + }, + + searchCanceled: function() + { + WebInspector.searchController.updateSearchMatchesCount(0, this); + }, + + performSearch: function(query) + { + // Call searchCanceled since it will reset everything we need before doing a new search. + this.searchCanceled(); + }, + + jumpToNextSearchResult: function() + { + }, + + jumpToPreviousSearchResult: function() + { + }, + + /** + * @param {Element=} parentElement + * @param {string=} position + * @param {number=} defaultWidth + */ + createSplitView: function(parentElement, position, defaultWidth) + { + if (this.splitView) + return; + + if (!parentElement) + parentElement = this.element; + + this.splitView = new WebInspector.SplitView(position || WebInspector.SplitView.SidebarPosition.Left, this._sidebarWidthSettingName(), defaultWidth); + this.splitView.show(parentElement); + this.splitView.addEventListener(WebInspector.SplitView.EventTypes.Resized, this.sidebarResized.bind(this)); + + this.sidebarElement = this.splitView.sidebarElement; + }, + + /** + * @param {Element=} parentElement + * @param {string=} position + * @param {number=} defaultWidth + */ + createSplitViewWithSidebarTree: function(parentElement, position, defaultWidth) + { + if (this.splitView) + return; + + this.createSplitView(parentElement, position); + + this.sidebarTreeElement = document.createElement("ol"); + this.sidebarTreeElement.className = "sidebar-tree"; + this.splitView.sidebarElement.appendChild(this.sidebarTreeElement); + this.splitView.sidebarElement.addStyleClass("sidebar"); + + this.sidebarTree = new TreeOutline(this.sidebarTreeElement); + this.sidebarTree.panel = this; + }, + + _sidebarWidthSettingName: function() + { + return this._panelName + "SidebarWidth"; + }, + + // Should be implemented by ancestors. + + get toolbarItemLabel() + { + }, + + get statusBarItems() + { + }, + + sidebarResized: function(width) + { + }, + + statusBarResized: function() + { + }, + + canShowAnchorLocation: function(anchor) + { + return false; + }, + + showAnchorLocation: function(anchor) + { + return false; + }, + + elementsToRestoreScrollPositionsFor: function() + { + return []; + }, + + handleShortcut: function(event) + { + var shortcutKey = WebInspector.KeyboardShortcut.makeKeyFromEvent(event); + var handler = this._shortcuts[shortcutKey]; + if (handler) { + handler(event); + event.handled = true; + } + }, + + registerShortcut: function(key, handler) + { + this._shortcuts[key] = handler; + } +} + +WebInspector.Panel.prototype.__proto__ = WebInspector.View.prototype; +/* InspectorView.js */ + +/* + * Copyright (C) 2011 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. + */ + +/** + * @constructor + * @extends {WebInspector.View} + */ +WebInspector.InspectorView = function() +{ + WebInspector.View.call(this); + this.markAsRoot(); + this.element.id = "main-panels"; + this.element.setAttribute("spellcheck", false); + this._history = []; + this._historyIterator = -1; + document.addEventListener("keydown", this._keyDown.bind(this), false); + this._panelOrder = []; +} + +WebInspector.InspectorView.Events = { + PanelSelected: "panel-selected" +} + +WebInspector.InspectorView.prototype = { + addPanel: function(panel) + { + this._panelOrder.push(panel); + WebInspector.toolbar.addPanel(panel); + }, + + currentPanel: function() + { + return this._currentPanel; + }, + + setCurrentPanel: function(x) + { + if (this._currentPanel === x) + return; + + if (this._currentPanel) + this._currentPanel.detach(); + + this._currentPanel = x; + + if (x) { + x.show(); + this.dispatchEventToListeners(WebInspector.InspectorView.Events.PanelSelected); + // FIXME: remove search controller. + WebInspector.searchController.activePanelChanged(); + } + for (var panelName in WebInspector.panels) { + if (WebInspector.panels[panelName] === x) { + WebInspector.settings.lastActivePanel.set(panelName); + this._pushToHistory(panelName); + WebInspector.userMetrics.panelShown(panelName); + } + } + }, + + _keyDown: function(event) + { + switch (event.keyIdentifier) { + case "Left": + var isBackKey = !event.shiftKey && WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event) && !WebInspector.isInEditMode(event); + if (isBackKey && this._canGoBackInHistory()) { + this._goBackInHistory(); + event.preventDefault(); + } + break; + + case "Right": + var isForwardKey = !event.shiftKey && WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event) && !WebInspector.isInEditMode(event); + if (isForwardKey && this._canGoForwardInHistory()) { + this._goForwardInHistory(); + event.preventDefault(); + } + break; + + // Windows and Mac have two different definitions of [, so accept both. + case "U+005B": + case "U+00DB": // [ key + var isRotateLeft = WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event) && !event.shiftKey && !event.altKey; + if (isRotateLeft) { + var index = this._panelOrder.indexOf(this.currentPanel()); + index = (index === 0) ? this._panelOrder.length - 1 : index - 1; + this._panelOrder[index].toolbarItem.click(); + event.preventDefault(); + } + break; + + // Windows and Mac have two different definitions of ], so accept both. + case "U+005D": + case "U+00DD": // ] key + var isRotateRight = WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event) && !event.shiftKey && !event.altKey; + if (isRotateRight) { + var index = this._panelOrder.indexOf(this.currentPanel()); + index = (index + 1) % this._panelOrder.length; + this._panelOrder[index].toolbarItem.click(); + event.preventDefault(); + } + + break; + } + }, + + _canGoBackInHistory: function() + { + return this._historyIterator > 0; + }, + + _goBackInHistory: function() + { + this._inHistory = true; + this.setCurrentPanel(WebInspector.panels[this._history[--this._historyIterator]]); + delete this._inHistory; + }, + + _canGoForwardInHistory: function() + { + return this._historyIterator < this._history.length - 1; + }, + + _goForwardInHistory: function() + { + this._inHistory = true; + this.setCurrentPanel(WebInspector.panels[this._history[++this._historyIterator]]); + delete this._inHistory; + }, + + _pushToHistory: function(panelName) + { + if (this._inHistory) + return; + + this._history.splice(this._historyIterator + 1, this._history.length - this._historyIterator - 1); + if (!this._history.length || this._history[this._history.length - 1] !== panelName) + this._history.push(panelName); + this._historyIterator = this._history.length - 1; + } +} + +WebInspector.InspectorView.prototype.__proto__ = WebInspector.View.prototype; + +/** + * @type {WebInspector.InspectorView} + */ +WebInspector.inspectorView = null; +/* AdvancedSearchController.js */ + +/* + * Copyright (C) 2011 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: + * + * 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 GOOGLE INC. 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 GOOGLE INC. + * 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. + */ + +/** + * @constructor + */ +WebInspector.AdvancedSearchController = function() +{ + this._shortcut = WebInspector.AdvancedSearchController.createShortcut(); + this._searchId = 0; + + WebInspector.settings.advancedSearchConfig = WebInspector.settings.createSetting("advancedSearchConfig", new WebInspector.SearchConfig("", true, false)); + + WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameNavigated, this._frameNavigated, this); +} + +WebInspector.AdvancedSearchController.createShortcut = function() +{ + if (WebInspector.isMac()) + return WebInspector.KeyboardShortcut.makeDescriptor("f", WebInspector.KeyboardShortcut.Modifiers.Meta | WebInspector.KeyboardShortcut.Modifiers.Alt); + else + return WebInspector.KeyboardShortcut.makeDescriptor("f", WebInspector.KeyboardShortcut.Modifiers.Ctrl | WebInspector.KeyboardShortcut.Modifiers.Shift); +} + +WebInspector.AdvancedSearchController.prototype = { + /** + * @param {Event} event + */ + handleShortcut: function(event) + { + if (WebInspector.KeyboardShortcut.makeKeyFromEvent(event) === this._shortcut.key) { + this.show(); + event.handled = true; + } + }, + + _frameNavigated: function() + { + this.resetSearch(); + }, + + /** + * @param {WebInspector.SearchScope} searchScope + */ + registerSearchScope: function(searchScope) + { + // FIXME: implement multiple search scopes. + this._searchScope = searchScope; + }, + + show: function() + { + if (!this._searchView) + this._searchView = new WebInspector.SearchView(this); + + if (this._searchView.isShowing()) + this._searchView.focus(); + else + WebInspector.showViewInDrawer(this._searchView); + }, + + /** + * @param {number} searchId + * @param {Object} searchResult + */ + _onSearchResult: function(searchId, searchResult) + { + if (searchId !== this._searchId) + return; + + this._searchView.addSearchResult(searchResult); + if (!searchResult.searchMatches.length) + return; + + if (!this._searchResultsPane) + this._searchResultsPane = this._currentSearchScope.createSearchResultsPane(this._searchConfig); + this._searchView.resultsPane = this._searchResultsPane; + this._searchResultsPane.addSearchResult(searchResult); + }, + + /** + * @param {number} searchId + * @param {boolean} finished + */ + _onSearchFinished: function(searchId, finished) + { + if (searchId !== this._searchId) + return; + + if (!this._searchResultsPane) + this._searchView.nothingFound(); + + this._searchView.searchFinished(finished); + }, + + /** + * @param {WebInspector.SearchConfig} searchConfig + */ + startSearch: function(searchConfig) + { + this.resetSearch(); + ++this._searchId; + + this._searchConfig = searchConfig; + // FIXME: this._currentSearchScope should be initialized based on searchConfig + this._currentSearchScope = this._searchScope; + + var totalSearchResultsCount = this._currentSearchScope.performSearch(searchConfig, this._onSearchResult.bind(this, this._searchId), this._onSearchFinished.bind(this, this._searchId)); + this._searchView.searchStarted(totalSearchResultsCount); + }, + + resetSearch: function() + { + this.stopSearch(); + + if (this._searchResultsPane) { + this._searchView.resetResults(); + delete this._searchResultsPane; + } + }, + + stopSearch: function() + { + if (this._currentSearchScope) + this._currentSearchScope.stopSearch(); + } +} + +/** + * @constructor + * @extends {WebInspector.View} + * @param {WebInspector.AdvancedSearchController} controller + */ +WebInspector.SearchView = function(controller) +{ + WebInspector.View.call(this); + this.registerRequiredCSS("textViewer.css"); + + this._controller = controller; + + this.element.className = "search-view"; + + this._searchPanelElement = this.element.createChild("div"); + this._searchPanelElement.tabIndex = 0; + this._searchPanelElement.className = "search-panel"; + this._searchPanelElement.addEventListener("keydown", this._onKeyDown.bind(this), false); + + this._searchResultsElement = this.element.createChild("div"); + this._searchResultsElement.className = "search-results"; + + this._search = this._searchPanelElement.createChild("input"); + this._search.setAttribute("type", "search"); + this._search.addStyleClass("search-config-search"); + this._search.setAttribute("results", "0"); + this._search.setAttribute("size", 20); + + this._ignoreCaseLabel = this._searchPanelElement.createChild("label"); + this._ignoreCaseLabel.addStyleClass("search-config-label"); + this._ignoreCaseCheckbox = this._ignoreCaseLabel.createChild("input"); + this._ignoreCaseCheckbox.setAttribute("type", "checkbox"); + this._ignoreCaseCheckbox.addStyleClass("search-config-checkbox"); + this._ignoreCaseLabel.appendChild(document.createTextNode(WebInspector.UIString("Ignore case"))); + + this._regexLabel = this._searchPanelElement.createChild("label"); + this._regexLabel.addStyleClass("search-config-label"); + this._regexCheckbox = this._regexLabel.createChild("input"); + this._regexCheckbox.setAttribute("type", "checkbox"); + this._regexCheckbox.addStyleClass("search-config-checkbox"); + this._regexLabel.appendChild(document.createTextNode(WebInspector.UIString("Regular expression"))); + + this._searchStatusBarElement = document.createElement("div"); + this._searchStatusBarElement.className = "search-status-bar-item"; + this._searchMessageElement = this._searchStatusBarElement.createChild("div"); + this._searchMessageElement.className = "search-status-bar-message"; + this._searchProgressElement = document.createElement("progress"); + this._searchProgressElement.className = "search-status-bar-progress"; + + this._searchStopButtonItem = document.createElement("div"); + this._searchStopButtonItem.className = "search-status-bar-stop-button-item"; + this._searchStopStatusBarButton = new WebInspector.StatusBarButton(WebInspector.UIString("Stop search"), "search-status-bar-stop-button"); + this._searchStopButtonItem.appendChild(this._searchStopStatusBarButton.element); + this._searchStopStatusBarButton.addEventListener("click", this._searchStopButtonPressed, this); + + this._searchResultsMessageElement = document.createElement("span"); + this._searchResultsMessageElement.className = "search-results-status-bar-message"; + + this._load(); +} + +// Number of recent search queries to store. +WebInspector.SearchView.maxQueriesCount = 20; + +WebInspector.SearchView.prototype = { + /** + * @type {Array.} + */ + get statusBarItems() + { + return [this._searchStatusBarElement]; + }, + + /** + * @type {Element} + */ + get counterElement() + { + return this._searchResultsMessageElement; + }, + + /** + * @type {WebInspector.SearchConfig} + */ + get searchConfig() + { + var searchConfig = {}; + searchConfig.query = this._search.value; + searchConfig.ignoreCase = this._ignoreCaseCheckbox.checked; + searchConfig.isRegex = this._regexCheckbox.checked; + return searchConfig; + }, + + /** + * @type {WebInspector.SearchResultsPane} + */ + set resultsPane(resultsPane) + { + this.resetResults(); + this._searchResultsElement.appendChild(resultsPane.element); + }, + + /** + * @param {number} totalSearchResultsCount + */ + searchStarted: function(totalSearchResultsCount) + { + this.resetResults(); + this._resetCounters(); + + this._totalSearchResultsCount = totalSearchResultsCount; + + this._searchMessageElement.textContent = WebInspector.UIString("Searching..."); + this._searchStatusBarElement.appendChild(this._searchProgressElement); + this._searchStatusBarElement.appendChild(this._searchStopButtonItem); + this._updateSearchProgress(); + + this._updateSearchResultsMessage(); + + if (!this._searchingView) + this._searchingView = new WebInspector.EmptyView(WebInspector.UIString("Searching...")); + this._searchingView.show(this._searchResultsElement); + }, + + _updateSearchResultsMessage: function() + { + if (this._searchMatchesCount && this._searchResultsCount) + this._searchResultsMessageElement.textContent = WebInspector.UIString("Found %d matches in %d files.", this._searchMatchesCount, this._nonEmptySearchResultsCount); + else + this._searchResultsMessageElement.textContent = ""; + }, + + _updateSearchProgress: function() + { + this._searchProgressElement.setAttribute("max", this._totalSearchResultsCount); + this._searchProgressElement.setAttribute("value", this._searchResultsCount); + }, + + resetResults: function() + { + if (this._searchingView) + this._searchingView.detach(); + if (this._notFoundView) + this._notFoundView.detach(); + this._searchResultsElement.removeChildren(); + }, + + _resetCounters: function() + { + this._searchMatchesCount = 0; + this._searchResultsCount = 0; + this._nonEmptySearchResultsCount = 0; + }, + + nothingFound: function() + { + this.resetResults(); + + if (!this._notFoundView) + this._notFoundView = new WebInspector.EmptyView(WebInspector.UIString("No matches found.")); + this._notFoundView.show(this._searchResultsElement); + this._searchResultsMessageElement.textContent = WebInspector.UIString("No matches found."); + }, + + /** + * @param {Object} searchResult + */ + addSearchResult: function(searchResult) + { + this._searchMatchesCount += searchResult.searchMatches.length; + this._searchResultsCount++; + if (searchResult.searchMatches.length) + this._nonEmptySearchResultsCount++; + this._updateSearchResultsMessage(); + this._updateSearchProgress(); + }, + + /** + * @param {boolean} finished + */ + searchFinished: function(finished) + { + this._searchMessageElement.textContent = finished ? WebInspector.UIString("Search finished.") : WebInspector.UIString("Search interrupted."); + this._searchStatusBarElement.removeChild(this._searchProgressElement); + this._searchStatusBarElement.removeChild(this._searchStopButtonItem); + }, + + focus: function() + { + WebInspector.setCurrentFocusElement(this._search); + this._search.select(); + }, + + wasShown: function() + { + this.focus(); + }, + + wasHidden: function() + { + this._controller.stopSearch(); + }, + + /** + * @param {Event} event + */ + _onKeyDown: function(event) + { + if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Enter.code) + this._onAction(); + }, + + _save: function() + { + var searchConfig = new WebInspector.SearchConfig(this.searchConfig.query, this.searchConfig.ignoreCase, this.searchConfig.isRegex); + WebInspector.settings.advancedSearchConfig.set(searchConfig); + }, + + _load: function() + { + var searchConfig = WebInspector.settings.advancedSearchConfig.get(); + this._search.value = searchConfig.query; + this._ignoreCaseCheckbox.checked = searchConfig.ignoreCase; + this._regexCheckbox.checked = searchConfig.isRegex; + }, + + _searchStopButtonPressed: function() + { + this._controller.stopSearch(); + this.focus(); + }, + + _onAction: function() + { + if (!this.searchConfig.query || !this.searchConfig.query.length) + return; + + this._save(); + this._controller.startSearch(this.searchConfig); + } +} + +WebInspector.SearchView.prototype.__proto__ = WebInspector.View.prototype; + +/** + * @constructor + * @param {string} query + * @param {boolean} ignoreCase + * @param {boolean} isRegex + */ +WebInspector.SearchConfig = function(query, ignoreCase, isRegex) +{ + this.query = query; + this.ignoreCase = ignoreCase; + this.isRegex = isRegex; +} + +/** + * @interface + */ +WebInspector.SearchScope = function() +{ +} + +WebInspector.SearchScope.prototype = { + /** + * @param {WebInspector.SearchConfig} searchConfig + * @param {function(Object)} searchResultCallback + * @param {function(boolean)} searchFinishedCallback + */ + performSearch: function(searchConfig, searchResultCallback, searchFinishedCallback) { }, + + stopSearch: function() { }, + + /** + * @param {WebInspector.SearchConfig} searchConfig + * @return WebInspector.SearchResultsPane} + */ + createSearchResultsPane: function(searchConfig) { } +} + +/** + * @constructor + * @param {WebInspector.SearchConfig} searchConfig + */ +WebInspector.SearchResultsPane = function(searchConfig) +{ + this._searchConfig = searchConfig; + this.element = document.createElement("div"); +} + +WebInspector.SearchResultsPane.prototype = { + /** + * @type {WebInspector.SearchConfig} + */ + get searchConfig() + { + return this._searchConfig; + }, + + /** + * @param {Object} searchResult + */ + addSearchResult: function(searchResult) { } +} + +/** + * @constructor + * @extends {WebInspector.SearchResultsPane} + * @param {WebInspector.SearchConfig} searchConfig + */ +WebInspector.FileBasedSearchResultsPane = function(searchConfig) +{ + WebInspector.SearchResultsPane.call(this, searchConfig); + + this._searchResults = []; + + this.element.id ="search-results-pane-file-based"; + + this._treeOutlineElement = document.createElement("ol"); + this._treeOutlineElement.className = "outline-disclosure"; + this._treeOutlineElement.addStyleClass("search-results-outline-disclosure"); + this.element.appendChild(this._treeOutlineElement); + this._treeOutline = new TreeOutline(this._treeOutlineElement); + + this._matchesExpandedCount = 0; +} + +WebInspector.FileBasedSearchResultsPane.matchesExpandedByDefaultCount = 20; +WebInspector.FileBasedSearchResultsPane.fileMatchesShownAtOnce = 20; + +WebInspector.FileBasedSearchResultsPane.prototype = { + /** + * @param {Object} file + * @param {number} lineNumber + * @param {number} columnNumber + * @return {Element} + */ + createAnchor: function(file, lineNumber, columnNumber) { }, + + /** + * @param {Object} file + * @return {string} + */ + fileName: function(file) { }, + + /** + * @param {Object} searchResult + */ + addSearchResult: function(searchResult) + { + this._searchResults.push(searchResult); + var file = searchResult.file; + var fileName = this.fileName(file); + var searchMatches = searchResult.searchMatches; + + var fileTreeElement = this._addFileTreeElement(fileName, searchMatches.length, this._searchResults.length - 1); + }, + + /** + * @param {Object} searchResult + * @param {TreeElement} fileTreeElement + */ + _fileTreeElementExpanded: function(searchResult, fileTreeElement) + { + if (fileTreeElement._initialized) + return; + + var toIndex = Math.min(searchResult.searchMatches.length, WebInspector.FileBasedSearchResultsPane.fileMatchesShownAtOnce); + if (toIndex < searchResult.searchMatches.length) { + this._appendSearchMatches(fileTreeElement, searchResult, 0, toIndex - 1); + this._appendShowMoreMatchesElement(fileTreeElement, searchResult, toIndex - 1); + } else + this._appendSearchMatches(fileTreeElement, searchResult, 0, toIndex); + + fileTreeElement._initialized = true; + }, + + /** + * @param {TreeElement} fileTreeElement + * @param {Object} searchResult + * @param {number} fromIndex + * @param {number} toIndex + */ + _appendSearchMatches: function(fileTreeElement, searchResult, fromIndex, toIndex) + { + var file = searchResult.file; + var fileName = this.fileName(file); + var searchMatches = searchResult.searchMatches; + + var regex = createSearchRegex(this._searchConfig.query, !this._searchConfig.ignoreCase, this._searchConfig.isRegex); + for (var i = fromIndex; i < toIndex; ++i) { + var lineNumber = searchMatches[i].lineNumber; + var lineContent = searchMatches[i].lineContent; + var matchRanges = this._regexMatchRanges(lineContent, regex); + + var anchor = this.createAnchor(file, lineNumber, matchRanges[0].offset); + + var numberString = numberToStringWithSpacesPadding(lineNumber + 1, 4); + var lineNumberSpan = document.createElement("span"); + lineNumberSpan.addStyleClass("webkit-line-number"); + lineNumberSpan.addStyleClass("search-match-line-number"); + lineNumberSpan.textContent = numberString; + anchor.appendChild(lineNumberSpan); + + var contentSpan = this._createContentSpan(lineContent, matchRanges); + anchor.appendChild(contentSpan); + + var searchMatchElement = new TreeElement("", null, false); + fileTreeElement.appendChild(searchMatchElement); + searchMatchElement.listItemElement.className = "search-match"; + searchMatchElement.listItemElement.appendChild(anchor); + } + }, + + /** + * @param {TreeElement} fileTreeElement + * @param {Object} searchResult + * @param {number} startMatchIndex + */ + _appendShowMoreMatchesElement: function(fileTreeElement, searchResult, startMatchIndex) + { + var matchesLeftCount = searchResult.searchMatches.length - startMatchIndex; + var showMoreMatchesText = WebInspector.UIString("Show all matches (%d more).", matchesLeftCount); + var showMoreMatchesElement = new TreeElement(showMoreMatchesText, null, false); + fileTreeElement.appendChild(showMoreMatchesElement); + showMoreMatchesElement.listItemElement.addStyleClass("show-more-matches"); + showMoreMatchesElement.onselect = this._showMoreMatchesElementSelected.bind(this, searchResult, startMatchIndex); + }, + + /** + * @param {Object} searchResult + * @param {number} startMatchIndex + * @param {TreeElement} showMoreMatchesElement + */ + _showMoreMatchesElementSelected: function(searchResult, startMatchIndex, showMoreMatchesElement) + { + var fileTreeElement = showMoreMatchesElement.parent; + fileTreeElement.removeChild(showMoreMatchesElement); + this._appendSearchMatches(fileTreeElement, searchResult, startMatchIndex, searchResult.searchMatches.length); + }, + + /** + * @param {string} fileName + * @param {number} searchMatchesCount + * @param {number} searchResultIndex + */ + _addFileTreeElement: function(fileName, searchMatchesCount, searchResultIndex) + { + var fileTreeElement = new TreeElement("", null, true); + fileTreeElement.toggleOnClick = true; + fileTreeElement.selectable = false; + + this._treeOutline.appendChild(fileTreeElement); + fileTreeElement.listItemElement.addStyleClass("search-result"); + + var fileNameSpan = document.createElement("span"); + fileNameSpan.className = "search-result-file-name"; + fileNameSpan.textContent = fileName; + fileTreeElement.listItemElement.appendChild(fileNameSpan); + + var matchesCountSpan = document.createElement("span"); + matchesCountSpan.className = "search-result-matches-count"; + if (searchMatchesCount === 1) + matchesCountSpan.textContent = WebInspector.UIString("(%d match)", searchMatchesCount); + else + matchesCountSpan.textContent = WebInspector.UIString("(%d matches)", searchMatchesCount); + + fileTreeElement.listItemElement.appendChild(matchesCountSpan); + + var searchResult = this._searchResults[searchResultIndex]; + fileTreeElement.onexpand = this._fileTreeElementExpanded.bind(this, searchResult); + + // Expand until at least certain amount of matches is expanded. + if (this._matchesExpandedCount < WebInspector.FileBasedSearchResultsPane.matchesExpandedByDefaultCount) + fileTreeElement.expand(); + this._matchesExpandedCount += searchResult.searchMatches.length; + + return fileTreeElement; + }, + + /** + * @param {string} lineContent + * @param {RegExp} regex + * @return {Array.} + */ + _regexMatchRanges: function(lineContent, regex) + { + regex.lastIndex = 0; + var match; + var offset = 0; + var matchRanges = []; + while ((regex.lastIndex < lineContent.length) && (match = regex.exec(lineContent))) + matchRanges.push({ offset: match.index, length: match[0].length }); + + return matchRanges; + }, + + /** + * @param {string} lineContent + * @param {Array.} matchRanges + */ + _createContentSpan: function(lineContent, matchRanges) + { + var contentSpan = document.createElement("span"); + contentSpan.className = "search-match-content"; + contentSpan.textContent = lineContent; + highlightRangesWithStyleClass(contentSpan, matchRanges, "highlighted-match"); + return contentSpan; + } +} + +WebInspector.FileBasedSearchResultsPane.prototype.__proto__ = WebInspector.SearchResultsPane.prototype; + +/** + * @constructor + * @param {Object} file + * @param {Array.} searchMatches + */ +WebInspector.FileBasedSearchResultsPane.SearchResult = function(file, searchMatches) { + this.file = file; + this.searchMatches = searchMatches; +} + +/** + * @type {WebInspector.AdvancedSearchController} + */ +WebInspector.advancedSearchController = null;/* TimelineGrid.js */ + +/* + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009 Anthony Ricaud + * 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: + * + * 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. + */ + +/** + * @constructor + */ +WebInspector.TimelineGrid = function() +{ + this.element = document.createElement("div"); + + this._itemsGraphsElement = document.createElement("div"); + this._itemsGraphsElement.id = "resources-graphs"; + this.element.appendChild(this._itemsGraphsElement); + + this._dividersElement = document.createElement("div"); + this._dividersElement.className = "resources-dividers"; + this.element.appendChild(this._dividersElement); + + this._eventDividersElement = document.createElement("div"); + this._eventDividersElement.className = "resources-event-dividers"; + this.element.appendChild(this._eventDividersElement); + + this._dividersLabelBarElement = document.createElement("div"); + this._dividersLabelBarElement.className = "resources-dividers-label-bar"; + this.element.appendChild(this._dividersLabelBarElement); +} + +WebInspector.TimelineGrid.prototype = { + get itemsGraphsElement() + { + return this._itemsGraphsElement; + }, + + /** + * @param {number=} paddingLeft + */ + updateDividers: function(force, calculator, paddingLeft) + { + var dividerCount = Math.round(this._dividersElement.offsetWidth / 64); + var slice = calculator.boundarySpan / dividerCount; + if (!force && this._currentDividerSlice === slice) + return false; + + if (typeof paddingLeft !== "number") + paddingLeft = 0; + this._currentDividerSlice = slice; + + // Reuse divider elements and labels. + var divider = this._dividersElement.firstChild; + var dividerLabelBar = this._dividersLabelBarElement.firstChild; + + var dividersLabelBarElementClientWidth = this._dividersLabelBarElement.clientWidth; + var clientWidth = dividersLabelBarElementClientWidth - paddingLeft; + for (var i = paddingLeft ? 0 : 1; i <= dividerCount; ++i) { + if (!divider) { + divider = document.createElement("div"); + divider.className = "resources-divider"; + this._dividersElement.appendChild(divider); + + dividerLabelBar = document.createElement("div"); + dividerLabelBar.className = "resources-divider"; + var label = document.createElement("div"); + label.className = "resources-divider-label"; + dividerLabelBar._labelElement = label; + dividerLabelBar.appendChild(label); + this._dividersLabelBarElement.appendChild(dividerLabelBar); + dividersLabelBarElementClientWidth = this._dividersLabelBarElement.clientWidth; + } + + if (i === (paddingLeft ? 0 : 1)) { + divider.addStyleClass("first"); + dividerLabelBar.addStyleClass("first"); + } else { + divider.removeStyleClass("first"); + dividerLabelBar.removeStyleClass("first"); + } + + if (i === dividerCount) { + divider.addStyleClass("last"); + dividerLabelBar.addStyleClass("last"); + } else { + divider.removeStyleClass("last"); + dividerLabelBar.removeStyleClass("last"); + } + + var left = paddingLeft + clientWidth * (i / dividerCount); + var percentLeft = 100 * left / dividersLabelBarElementClientWidth; + this._setDividerAndBarLeft(divider, dividerLabelBar, percentLeft); + + if (!isNaN(slice)) + dividerLabelBar._labelElement.textContent = calculator.formatValue(slice * i); + else + dividerLabelBar._labelElement.textContent = ""; + + divider = divider.nextSibling; + dividerLabelBar = dividerLabelBar.nextSibling; + } + + // Remove extras. + while (divider) { + var nextDivider = divider.nextSibling; + this._dividersElement.removeChild(divider); + divider = nextDivider; + } + while (dividerLabelBar) { + var nextDivider = dividerLabelBar.nextSibling; + this._dividersLabelBarElement.removeChild(dividerLabelBar); + dividerLabelBar = nextDivider; + } + return true; + }, + + _setDividerAndBarLeft: function(divider, dividerLabelBar, percentLeft) + { + var percentStyleLeft = parseFloat(divider.style.left); + if (!isNaN(percentStyleLeft) && Math.abs(percentStyleLeft - percentLeft) < 0.1) + return; + divider.style.left = percentLeft + "%"; + dividerLabelBar.style.left = percentLeft + "%"; + }, + + addEventDivider: function(divider) + { + this._eventDividersElement.appendChild(divider); + }, + + addEventDividers: function(dividers) + { + this.element.removeChild(this._eventDividersElement); + for (var i = 0; i < dividers.length; ++i) + if (dividers[i]) + this._eventDividersElement.appendChild(dividers[i]); + this.element.appendChild(this._eventDividersElement); + }, + + removeEventDividers: function() + { + this._eventDividersElement.removeChildren(); + }, + + hideEventDividers: function() + { + this._eventDividersElement.addStyleClass("hidden"); + }, + + showEventDividers: function() + { + this._eventDividersElement.removeStyleClass("hidden"); + }, + + setScrollAndDividerTop: function(scrollTop, dividersTop) + { + this._dividersElement.style.top = scrollTop + "px"; + this._eventDividersElement.style.top = scrollTop + "px"; + this._dividersLabelBarElement.style.top = dividersTop + "px"; + } +} +/* Resource.js */ + +/* + * 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. + * 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. + */ + +// This table maps MIME types to the Resource.Types which are valid for them. +// The following line: +// "text/html": {0: 1}, +// means that text/html is a valid MIME type for resources that have type +// WebInspector.Resource.Type.Document (which has a value of 0). +WebInspector.MIMETypes = { + "text/html": {0: true}, + "text/xml": {0: true}, + "text/plain": {0: true}, + "application/xhtml+xml": {0: true}, + "text/css": {1: true}, + "text/xsl": {1: true}, + "image/jpeg": {2: true}, + "image/png": {2: true}, + "image/gif": {2: true}, + "image/bmp": {2: true}, + "image/svg+xml": {2: true}, + "image/vnd.microsoft.icon": {2: true}, + "image/webp": {2: true}, + "image/x-icon": {2: true}, + "image/x-xbitmap": {2: true}, + "font/ttf": {3: true}, + "font/opentype": {3: true}, + "application/x-font-type1": {3: true}, + "application/x-font-ttf": {3: true}, + "application/x-font-woff": {3: true}, + "application/x-truetype-font": {3: true}, + "text/javascript": {4: true}, + "text/ecmascript": {4: true}, + "application/javascript": {4: true}, + "application/ecmascript": {4: true}, + "application/x-javascript": {4: true}, + "application/json": {4: true}, + "text/javascript1.1": {4: true}, + "text/javascript1.2": {4: true}, + "text/javascript1.3": {4: true}, + "text/jscript": {4: true}, + "text/livescript": {4: true}, +} + +/** + * @constructor + * @extends {WebInspector.Object} + * + * @param {NetworkAgent.RequestId} requestId + * @param {string} url + * @param {string} frameId + * @param {?NetworkAgent.LoaderId} loaderId + */ +WebInspector.Resource = function(requestId, url, frameId, loaderId) +{ + this.requestId = requestId; + this.url = url; + this.frameId = frameId; + this.loaderId = loaderId; + this._startTime = -1; + this._endTime = -1; + this._category = WebInspector.resourceCategories.other; + this._pendingContentCallbacks = []; + this.history = []; + /** @type {number} */ + this.statusCode = 0; + this.statusText = ""; + this.requestMethod = ""; + this.requestTime = 0; + this.receiveHeadersEnd = 0; +} + +/** + * @param {string} url + * @return {string} + */ +WebInspector.Resource.displayName = function(url) +{ + return new WebInspector.Resource("fake-transient-resource", url, "", null).displayName; +} + +// Keep these in sync with WebCore::InspectorResource::Type +WebInspector.Resource.Type = { + Document: 0, + Stylesheet: 1, + Image: 2, + Font: 3, + Script: 4, + XHR: 5, + WebSocket: 7, + Other: 8, + + /** + * @param {number} type + * @return {boolean} + */ + isTextType: function(type) + { + return (type === WebInspector.Resource.Type.Document) || (type === WebInspector.Resource.Type.Stylesheet) || (type === WebInspector.Resource.Type.Script) || (type === WebInspector.Resource.Type.XHR); + }, + + /** + * @param {number} type + * @return {string} + */ + toUIString: function(type) + { + switch (type) { + case WebInspector.Resource.Type.Document: + return WebInspector.UIString("Document"); + case WebInspector.Resource.Type.Stylesheet: + return WebInspector.UIString("Stylesheet"); + case WebInspector.Resource.Type.Image: + return WebInspector.UIString("Image"); + case WebInspector.Resource.Type.Font: + return WebInspector.UIString("Font"); + case WebInspector.Resource.Type.Script: + return WebInspector.UIString("Script"); + case WebInspector.Resource.Type.XHR: + return WebInspector.UIString("XHR"); + case WebInspector.Resource.Type.WebSocket: + return WebInspector.UIString("WebSocket"); + case WebInspector.Resource.Type.Other: + default: + return WebInspector.UIString("Other"); + } + }, + + /** + * Returns locale-independent string identifier of resource type (primarily for use in extension API). + * The IDs need to be kept in sync with webInspector.resoureces.Types object in ExtensionAPI.js. + * @param {number} type + * @return {string} + */ + toString: function(type) + { + switch (type) { + case WebInspector.Resource.Type.Document: + return "document"; + case WebInspector.Resource.Type.Stylesheet: + return "stylesheet"; + case WebInspector.Resource.Type.Image: + return "image"; + case WebInspector.Resource.Type.Font: + return "font"; + case WebInspector.Resource.Type.Script: + return "script"; + case WebInspector.Resource.Type.XHR: + return "xhr"; + case WebInspector.Resource.Type.WebSocket: + return "websocket"; + case WebInspector.Resource.Type.Other: + default: + return "other"; + } + } +} + +WebInspector.Resource._domainModelBindings = []; + +/** + * @param {number} type + * @param {WebInspector.ResourceDomainModelBinding} binding + */ +WebInspector.Resource.registerDomainModelBinding = function(type, binding) +{ + WebInspector.Resource._domainModelBindings[type] = binding; +} + +WebInspector.Resource._resourceRevisionRegistry = function() +{ + if (!WebInspector.Resource._resourceRevisionRegistryObject) { + if (window.localStorage) { + var resourceHistory = window.localStorage["resource-history"]; + try { + WebInspector.Resource._resourceRevisionRegistryObject = resourceHistory ? JSON.parse(resourceHistory) : {}; + } catch (e) { + WebInspector.Resource._resourceRevisionRegistryObject = {}; + } + } else + WebInspector.Resource._resourceRevisionRegistryObject = {}; + } + return WebInspector.Resource._resourceRevisionRegistryObject; +} + +WebInspector.Resource.restoreRevisions = function() +{ + var registry = WebInspector.Resource._resourceRevisionRegistry(); + var filteredRegistry = {}; + for (var url in registry) { + var historyItems = registry[url]; + var resource = WebInspector.resourceForURL(url); + + var filteredHistoryItems = []; + for (var i = 0; historyItems && i < historyItems.length; ++i) { + var historyItem = historyItems[i]; + if (resource && historyItem.loaderId === resource.loaderId) { + resource.addRevision(window.localStorage[historyItem.key], new Date(historyItem.timestamp), true); + filteredHistoryItems.push(historyItem); + filteredRegistry[url] = filteredHistoryItems; + } else + delete window.localStorage[historyItem.key]; + } + } + WebInspector.Resource._resourceRevisionRegistryObject = filteredRegistry; + + function persist() + { + window.localStorage["resource-history"] = JSON.stringify(filteredRegistry); + } + + // Schedule async storage. + setTimeout(persist, 0); +} + +/** + * @param {WebInspector.Resource} resource + */ +WebInspector.Resource.persistRevision = function(resource) +{ + if (!window.localStorage) + return; + + var url = resource.url; + var loaderId = resource.loaderId; + var timestamp = resource._contentTimestamp.getTime(); + var key = "resource-history|" + url + "|" + loaderId + "|" + timestamp; + var content = resource._content; + + var registry = WebInspector.Resource._resourceRevisionRegistry(); + + var historyItems = registry[resource.url]; + if (!historyItems) { + historyItems = []; + registry[resource.url] = historyItems; + } + historyItems.push({url: url, loaderId: loaderId, timestamp: timestamp, key: key}); + + function persist() + { + window.localStorage[key] = content; + window.localStorage["resource-history"] = JSON.stringify(registry); + } + + // Schedule async storage. + setTimeout(persist, 0); +} + +WebInspector.Resource.Events = { + RevisionAdded: "revision-added", + MessageAdded: "message-added", + MessagesCleared: "messages-cleared", +} + +WebInspector.Resource.prototype = { + /** + * @return {string} + */ + get url() + { + return this._url; + }, + + set url(x) + { + if (this._url === x) + return; + + this._url = x; + delete this._parsedQueryParameters; + + var parsedURL = x.asParsedURL(); + this.domain = parsedURL ? parsedURL.host : ""; + this.path = parsedURL ? parsedURL.path : ""; + this.urlFragment = parsedURL ? parsedURL.fragment : ""; + this.lastPathComponent = parsedURL ? parsedURL.lastPathComponent : ""; + this.lastPathComponentLowerCase = this.lastPathComponent.toLowerCase(); + }, + + /** + * @return {string} + */ + get documentURL() + { + return this._documentURL; + }, + + set documentURL(x) + { + this._documentURL = x; + }, + + /** + * @return {string} + */ + get displayName() + { + if (this._displayName) + return this._displayName; + this._displayName = this.lastPathComponent; + if (!this._displayName) + this._displayName = this.displayDomain; + if (!this._displayName && this.url) + this._displayName = this.url.trimURL(WebInspector.inspectedPageDomain ? WebInspector.inspectedPageDomain : ""); + if (this._displayName === "/") + this._displayName = this.url; + return this._displayName; + }, + + /** + * @return {string} + */ + get folder() + { + var path = this.path; + var indexOfQuery = path.indexOf("?"); + if (indexOfQuery !== -1) + path = path.substring(0, indexOfQuery); + var lastSlashIndex = path.lastIndexOf("/"); + return lastSlashIndex !== -1 ? path.substring(0, lastSlashIndex) : ""; + }, + + /** + * @return {string} + */ + get displayDomain() + { + // WebInspector.Database calls this, so don't access more than this.domain. + if (this.domain && (!WebInspector.inspectedPageDomain || (WebInspector.inspectedPageDomain && this.domain !== WebInspector.inspectedPageDomain))) + return this.domain; + return ""; + }, + + /** + * @return {number} + */ + get startTime() + { + return this._startTime || -1; + }, + + set startTime(x) + { + this._startTime = x; + }, + + /** + * @return {number} + */ + get responseReceivedTime() + { + return this._responseReceivedTime || -1; + }, + + set responseReceivedTime(x) + { + this._responseReceivedTime = x; + }, + + /** + * @return {number} + */ + get endTime() + { + return this._endTime || -1; + }, + + set endTime(x) + { + if (this.timing && this.timing.requestTime) { + // Check against accurate responseReceivedTime. + this._endTime = Math.max(x, this.responseReceivedTime); + } else { + // Prefer endTime since it might be from the network stack. + this._endTime = x; + if (this._responseReceivedTime > x) + this._responseReceivedTime = x; + } + }, + + /** + * @return {number} + */ + get duration() + { + if (this._endTime === -1 || this._startTime === -1) + return -1; + return this._endTime - this._startTime; + }, + + /** + * @return {number} + */ + get latency() + { + if (this._responseReceivedTime === -1 || this._startTime === -1) + return -1; + return this._responseReceivedTime - this._startTime; + }, + + /** + * @return {number} + */ + get receiveDuration() + { + if (this._endTime === -1 || this._responseReceivedTime === -1) + return -1; + return this._endTime - this._responseReceivedTime; + }, + + /** + * @return {number} + */ + get resourceSize() + { + return this._resourceSize || 0; + }, + + set resourceSize(x) + { + this._resourceSize = x; + }, + + /** + * @return {number} + */ + get transferSize() + { + if (this.cached) + return 0; + if (this.statusCode === 304) // Not modified + return this.responseHeadersSize; + if (this._transferSize !== undefined) + return this._transferSize; + // If we did not receive actual transfer size from network + // stack, we prefer using Content-Length over resourceSize as + // resourceSize may differ from actual transfer size if platform's + // network stack performed decoding (e.g. gzip decompression). + // The Content-Length, though, is expected to come from raw + // response headers and will reflect actual transfer length. + // This won't work for chunked content encoding, so fall back to + // resourceSize when we don't have Content-Length. This still won't + // work for chunks with non-trivial encodings. We need a way to + // get actual transfer size from the network stack. + var bodySize = Number(this.responseHeaders["Content-Length"] || this.resourceSize); + return this.responseHeadersSize + bodySize; + }, + + /** + * @param {number} x + */ + increaseTransferSize: function(x) + { + this._transferSize = (this._transferSize || 0) + x; + }, + + /** + * @return {boolean} + */ + get finished() + { + return this._finished; + }, + + set finished(x) + { + if (this._finished === x) + return; + + this._finished = x; + + if (x) { + this.dispatchEventToListeners("finished"); + if (this._pendingContentCallbacks.length) + this._innerRequestContent(); + } + }, + + /** + * @return {boolean} + */ + get failed() + { + return this._failed; + }, + + set failed(x) + { + this._failed = x; + }, + + /** + * @return {boolean} + */ + get canceled() + { + return this._canceled; + }, + + set canceled(x) + { + this._canceled = x; + }, + + /** + * @return {WebInspector.ResourceCategory} + */ + get category() + { + return this._category; + }, + + set category(x) + { + this._category = x; + }, + + /** + * @return {boolean} + */ + get cached() + { + return this._cached; + }, + + set cached(x) + { + this._cached = x; + if (x) + delete this._timing; + }, + + /** + * @return {NetworkAgent.ResourceTiming|undefined} + */ + get timing() + { + return this._timing; + }, + + set timing(x) + { + if (x && !this._cached) { + // Take startTime and responseReceivedTime from timing data for better accuracy. + // Timing's requestTime is a baseline in seconds, rest of the numbers there are ticks in millis. + this._startTime = x.requestTime; + this._responseReceivedTime = x.requestTime + x.receiveHeadersEnd / 1000.0; + + this._timing = x; + this.dispatchEventToListeners("timing changed"); + } + }, + + /** + * @return {string} + */ + get mimeType() + { + return this._mimeType; + }, + + set mimeType(x) + { + this._mimeType = x; + }, + + /** + * @return {number} + */ + get type() + { + return this._type; + }, + + set type(x) + { + if (this._type === x) + return; + + this._type = x; + + switch (x) { + case WebInspector.Resource.Type.Document: + this.category = WebInspector.resourceCategories.documents; + break; + case WebInspector.Resource.Type.Stylesheet: + this.category = WebInspector.resourceCategories.stylesheets; + break; + case WebInspector.Resource.Type.Script: + this.category = WebInspector.resourceCategories.scripts; + break; + case WebInspector.Resource.Type.Image: + this.category = WebInspector.resourceCategories.images; + break; + case WebInspector.Resource.Type.Font: + this.category = WebInspector.resourceCategories.fonts; + break; + case WebInspector.Resource.Type.XHR: + this.category = WebInspector.resourceCategories.xhr; + break; + case WebInspector.Resource.Type.WebSocket: + this.category = WebInspector.resourceCategories.websockets; + break; + case WebInspector.Resource.Type.Other: + default: + this.category = WebInspector.resourceCategories.other; + break; + } + }, + + /** + * @return {WebInspector.Resource|undefined} + */ + get redirectSource() + { + if (this.redirects && this.redirects.length > 0) + return this.redirects[this.redirects.length - 1]; + return this._redirectSource; + }, + + set redirectSource(x) + { + this._redirectSource = x; + }, + + /** + * @return {Object} + */ + get requestHeaders() + { + return this._requestHeaders || {}; + }, + + set requestHeaders(x) + { + this._requestHeaders = x; + delete this._sortedRequestHeaders; + delete this._requestCookies; + + this.dispatchEventToListeners("requestHeaders changed"); + }, + + /** + * @return {string} + */ + get requestHeadersText() + { + if (this._requestHeadersText === undefined) { + this._requestHeadersText = this.requestMethod + " " + this.url + " HTTP/1.1\r\n"; + for (var key in this.requestHeaders) + this._requestHeadersText += key + ": " + this.requestHeaders[key] + "\r\n"; + } + return this._requestHeadersText; + }, + + set requestHeadersText(x) + { + this._requestHeadersText = x; + + this.dispatchEventToListeners("requestHeaders changed"); + }, + + /** + * @return {number} + */ + get requestHeadersSize() + { + return this.requestHeadersText.length; + }, + + /** + * @return {Array.} + */ + get sortedRequestHeaders() + { + if (this._sortedRequestHeaders !== undefined) + return this._sortedRequestHeaders; + + this._sortedRequestHeaders = []; + for (var key in this.requestHeaders) + this._sortedRequestHeaders.push({header: key, value: this.requestHeaders[key]}); + this._sortedRequestHeaders.sort(function(a,b) { return a.header.localeCompare(b.header) }); + + return this._sortedRequestHeaders; + }, + + /** + * @param {string} headerName + * @return {string|undefined} + */ + requestHeaderValue: function(headerName) + { + return this._headerValue(this.requestHeaders, headerName); + }, + + /** + * @type {Array.} + */ + get requestCookies() + { + if (!this._requestCookies) + this._requestCookies = WebInspector.CookieParser.parseCookie(this.requestHeaderValue("Cookie")); + return this._requestCookies; + }, + + /** + * @type {string|undefined} + */ + get requestFormData() + { + return this._requestFormData; + }, + + set requestFormData(x) + { + this._requestFormData = x; + delete this._parsedFormParameters; + }, + + /** + * @type {string|undefined} + */ + get requestHttpVersion() + { + var firstLine = this.requestHeadersText.split(/\r\n/)[0]; + var match = firstLine.match(/(HTTP\/\d+\.\d+)$/); + return match ? match[1] : undefined; + }, + + /** + * @type {Object} + */ + get responseHeaders() + { + return this._responseHeaders || {}; + }, + + set responseHeaders(x) + { + this._responseHeaders = x; + delete this._sortedResponseHeaders; + delete this._responseCookies; + + this.dispatchEventToListeners("responseHeaders changed"); + }, + + /** + * @type {string} + */ + get responseHeadersText() + { + if (this._responseHeadersText === undefined) { + this._responseHeadersText = "HTTP/1.1 " + this.statusCode + " " + this.statusText + "\r\n"; + for (var key in this.responseHeaders) + this._responseHeadersText += key + ": " + this.responseHeaders[key] + "\r\n"; + } + return this._responseHeadersText; + }, + + set responseHeadersText(x) + { + this._responseHeadersText = x; + + this.dispatchEventToListeners("responseHeaders changed"); + }, + + /** + * @type {number} + */ + get responseHeadersSize() + { + return this.responseHeadersText.length; + }, + + /** + * @type {Array.} + */ + get sortedResponseHeaders() + { + if (this._sortedResponseHeaders !== undefined) + return this._sortedResponseHeaders; + + this._sortedResponseHeaders = []; + for (var key in this.responseHeaders) + this._sortedResponseHeaders.push({header: key, value: this.responseHeaders[key]}); + this._sortedResponseHeaders.sort(function(a,b) { return a.header.localeCompare(b.header) }); + + return this._sortedResponseHeaders; + }, + + /** + * @param {string} headerName + * @return {string|undefined} + */ + responseHeaderValue: function(headerName) + { + return this._headerValue(this.responseHeaders, headerName); + }, + + /** + * @type {Array.} + */ + get responseCookies() + { + if (!this._responseCookies) + this._responseCookies = WebInspector.CookieParser.parseSetCookie(this.responseHeaderValue("Set-Cookie")); + return this._responseCookies; + }, + + /** + * @type {?Array.} + */ + get queryParameters() + { + if (this._parsedQueryParameters) + return this._parsedQueryParameters; + var queryString = this.url.split("?", 2)[1]; + if (!queryString) + return null; + queryString = queryString.split("#", 2)[0]; + this._parsedQueryParameters = this._parseParameters(queryString); + return this._parsedQueryParameters; + }, + + /** + * @type {?Array.} + */ + get formParameters() + { + if (this._parsedFormParameters) + return this._parsedFormParameters; + if (!this.requestFormData) + return null; + var requestContentType = this.requestContentType(); + if (!requestContentType || !requestContentType.match(/^application\/x-www-form-urlencoded\s*(;.*)?$/i)) + return null; + this._parsedFormParameters = this._parseParameters(this.requestFormData); + return this._parsedFormParameters; + }, + + /** + * @type {string|undefined} + */ + get responseHttpVersion() + { + var match = this.responseHeadersText.match(/^(HTTP\/\d+\.\d+)/); + return match ? match[1] : undefined; + }, + + /** + * @param {string} queryString + * @return {Array.} + */ + _parseParameters: function(queryString) + { + function parseNameValue(pair) + { + var parameter = {}; + var splitPair = pair.split("=", 2); + + parameter.name = splitPair[0]; + if (splitPair.length === 1) + parameter.value = ""; + else + parameter.value = splitPair[1]; + return parameter; + } + return queryString.split("&").map(parseNameValue); + }, + + /** + * @param {Object} headers + * @param {string} headerName + * @return {string|undefined} + */ + _headerValue: function(headers, headerName) + { + headerName = headerName.toLowerCase(); + for (var header in headers) { + if (header.toLowerCase() === headerName) + return headers[header]; + } + }, + + /** + * @type {Array.} + */ + get messages() + { + return this._messages || []; + }, + + /** + * @param {WebInspector.ConsoleMessage} msg + */ + addMessage: function(msg) + { + if (!msg.isErrorOrWarning() || !msg.message) + return; + + if (!this._messages) + this._messages = []; + this._messages.push(msg); + this.dispatchEventToListeners(WebInspector.Resource.Events.MessageAdded, msg); + }, + + /** + * @type {number} + */ + get errors() + { + return this._errors || 0; + }, + + set errors(x) + { + this._errors = x; + }, + + /** + * @type {number} + */ + get warnings() + { + return this._warnings || 0; + }, + + set warnings(x) + { + this._warnings = x; + }, + + clearErrorsAndWarnings: function() + { + this._messages = []; + this._warnings = 0; + this._errors = 0; + this.dispatchEventToListeners(WebInspector.Resource.Events.MessagesCleared); + }, + + /** + * @type {string} + */ + get content() + { + return this._content; + }, + + /** + * @type {string} + */ + get contentEncoded() + { + return this._contentEncoded; + }, + + /** + * @type {number} + */ + get contentTimestamp() + { + return this._contentTimestamp; + }, + + /** + * @return {boolean} + */ + isEditable: function() + { + if (this._actualResource) + return false; + var binding = WebInspector.Resource._domainModelBindings[this.type]; + return binding && binding.canSetContent(this); + }, + + /** + * @param {string} newContent + * @param {boolean} majorChange + * @param {function(string=)} callback + */ + setContent: function(newContent, majorChange, callback) + { + if (!this.isEditable()) { + if (callback) + callback("Resource is not editable"); + return; + } + var binding = WebInspector.Resource._domainModelBindings[this.type]; + binding.setContent(this, newContent, majorChange, callback); + }, + + /** + * @param {string} newContent + * @param {Date=} timestamp + * @param {boolean=} restoringHistory + */ + addRevision: function(newContent, timestamp, restoringHistory) + { + var revision = new WebInspector.ResourceRevision(this, this._content, this._contentTimestamp); + this.history.push(revision); + + this._content = newContent; + this._contentTimestamp = timestamp || new Date(); + + this.dispatchEventToListeners(WebInspector.Resource.Events.RevisionAdded, revision); + if (!restoringHistory) + this._persistRevision(); + WebInspector.resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.ResourceContentCommitted, { resource: this, content: newContent }); + }, + + _persistRevision: function() + { + WebInspector.Resource.persistRevision(this); + }, + + /** + * @param {function(?string, ?string)} callback + */ + requestContent: function(callback) + { + // We do not support content retrieval for WebSockets at the moment. + // Since WebSockets are potentially long-living, fail requests immediately + // to prevent caller blocking until resource is marked as finished. + if (this.type === WebInspector.Resource.Type.WebSocket) { + callback(null, null); + return; + } + if (typeof this._content !== "undefined") { + callback(this.content, this._contentEncoded); + return; + } + this._pendingContentCallbacks.push(callback); + if (this.finished) + this._innerRequestContent(); + }, + + /** + * @param {string} query + * @param {boolean} caseSensitive + * @param {boolean} isRegex + * @param {function(Array.)} callback + */ + searchInContent: function(query, caseSensitive, isRegex, callback) + { + /** + * @param {?Protocol.Error} error + * @param {Array.} searchMatches + */ + function callbackWrapper(error, searchMatches) + { + callback(searchMatches || []); + } + + if (this.frameId) + PageAgent.searchInResource(this.frameId, this.url, query, caseSensitive, isRegex, callbackWrapper); + else + callback([]); + }, + + /** + * @param {Element} image + */ + populateImageSource: function(image) + { + function onResourceContent() + { + image.src = this._contentURL(); + } + + this.requestContent(onResourceContent.bind(this)); + }, + + /** + * @return {boolean} + */ + isHttpFamily: function() + { + return !!this.url.match(/^https?:/i); + }, + + /** + * @return {string|undefined} + */ + requestContentType: function() + { + return this.requestHeaderValue("Content-Type"); + }, + + /** + * @return {boolean} + */ + isPingRequest: function() + { + return "text/ping" === this.requestContentType(); + }, + + /** + * @return {boolean} + */ + hasErrorStatusCode: function() + { + return this.statusCode >= 400; + }, + + /** + * @return {string} + */ + _contentURL: function() + { + const maxDataUrlSize = 1024 * 1024; + // If resource content is not available or won't fit a data URL, fall back to using original URL. + if (this._content == null || this._content.length > maxDataUrlSize) + return this.url; + + return "data:" + this.mimeType + (this._contentEncoded ? ";base64," : ",") + this._content; + }, + + _innerRequestContent: function() + { + if (this._contentRequested) + return; + this._contentRequested = true; + + function onResourceContent(data, contentEncoded) + { + this._contentEncoded = contentEncoded; + this._content = data; + this._originalContent = data; + var callbacks = this._pendingContentCallbacks.slice(); + for (var i = 0; i < callbacks.length; ++i) + callbacks[i](this._content, this._contentEncoded); + this._pendingContentCallbacks.length = 0; + delete this._contentRequested; + } + WebInspector.networkManager.requestContent(this, onResourceContent.bind(this)); + } +} + +WebInspector.Resource.prototype.__proto__ = WebInspector.Object.prototype; + +/** + * @constructor + * @param {WebInspector.Resource} resource + * @param {string} content + * @param {number} timestamp + */ +WebInspector.ResourceRevision = function(resource, content, timestamp) +{ + this._resource = resource; + this._content = content; + this._timestamp = timestamp; +} + +WebInspector.ResourceRevision.prototype = { + /** + * @type {WebInspector.Resource} + */ + get resource() + { + return this._resource; + }, + + /** + * @type {number} + */ + get timestamp() + { + return this._timestamp; + }, + + /** + * @type {string} + */ + get content() + { + return this._content; + }, + + revertToThis: function() + { + function revert(content) + { + this._resource.setContent(content, true); + } + this.requestContent(revert.bind(this)); + }, + + /** + * @param {function(string)} callback + */ + requestContent: function(callback) + { + if (typeof this._content === "string") { + callback(this._content); + return; + } + + // If we are here, this is initial revision. First, look up content fetched over the wire. + if (typeof this.resource._originalContent === "string") { + this._content = this._resource._originalContent; + callback(this._content); + return; + } + + // If unsuccessful, request the content. + function mycallback(content) + { + this._content = content; + callback(content); + } + WebInspector.networkManager.requestContent(this._resource, mycallback.bind(this)); + } +} + +/** + * @interface + */ +WebInspector.ResourceDomainModelBinding = function() { } + +WebInspector.ResourceDomainModelBinding.prototype = { + /** + * @return {boolean} + */ + canSetContent: function() { return true; }, + + /** + * @param {WebInspector.Resource} resource + * @param {string} content + * @param {boolean} majorChange + * @param {function(?string)} callback + */ + setContent: function(resource, content, majorChange, callback) { } +} +/* CSSStyleModel.js */ + +/* + * 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. + * * 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. + */ + +/** + * @constructor + * @extends {WebInspector.Object} + */ +WebInspector.CSSStyleModel = function() +{ + new WebInspector.CSSStyleModelResourceBinding(this); + InspectorBackend.registerCSSDispatcher(new WebInspector.CSSDispatcher(this)); + CSSAgent.enable(); +} + +WebInspector.CSSStyleModel.parseRuleArrayPayload = function(ruleArray) +{ + var result = []; + for (var i = 0; i < ruleArray.length; ++i) + result.push(WebInspector.CSSRule.parsePayload(ruleArray[i])); + return result; +} + +WebInspector.CSSStyleModel.Events = { + StyleSheetChanged: "StyleSheetChanged", + MediaQueryResultChanged: "MediaQueryResultChanged" +} + +WebInspector.CSSStyleModel.prototype = { + /** + * @param {DOMAgent.NodeId} nodeId + * @param {?Array.|undefined} forcedPseudoClasses + * @param {boolean} needPseudo + * @param {boolean} needInherited + * @param {function(?*)} userCallback + */ + getMatchedStylesAsync: function(nodeId, forcedPseudoClasses, needPseudo, needInherited, userCallback) + { + /** + * @param {function(?*)} userCallback + * @param {?Protocol.Error} error + * @param {Array.=} matchedPayload + * @param {Array.=} pseudoPayload + * @param {Array.=} inheritedPayload + */ + function callback(userCallback, error, matchedPayload, pseudoPayload, inheritedPayload) + { + if (error) { + if (userCallback) + userCallback(null); + return; + } + + var result = {}; + if (matchedPayload) + result.matchedCSSRules = WebInspector.CSSStyleModel.parseRuleArrayPayload(matchedPayload); + + if (pseudoPayload) { + result.pseudoElements = []; + for (var i = 0; i < pseudoPayload.length; ++i) { + var entryPayload = pseudoPayload[i]; + result.pseudoElements.push({ pseudoId: entryPayload.pseudoId, rules: WebInspector.CSSStyleModel.parseRuleArrayPayload(entryPayload.rules) }); + } + } + + if (inheritedPayload) { + result.inherited = []; + for (var i = 0; i < inheritedPayload.length; ++i) { + var entryPayload = inheritedPayload[i]; + var entry = {}; + if (entryPayload.inlineStyle) + entry.inlineStyle = WebInspector.CSSStyleDeclaration.parsePayload(entryPayload.inlineStyle); + if (entryPayload.matchedCSSRules) + entry.matchedCSSRules = WebInspector.CSSStyleModel.parseRuleArrayPayload(entryPayload.matchedCSSRules); + result.inherited.push(entry); + } + } + + if (userCallback) + userCallback(result); + } + + CSSAgent.getMatchedStylesForNode(nodeId, forcedPseudoClasses || [], needPseudo, needInherited, callback.bind(null, userCallback)); + }, + + /** + * @param {DOMAgent.NodeId} nodeId + * @param {?Array.|undefined} forcedPseudoClasses + * @param {function(?WebInspector.CSSStyleDeclaration)} userCallback + */ + getComputedStyleAsync: function(nodeId, forcedPseudoClasses, userCallback) + { + /** + * @param {function(?WebInspector.CSSStyleDeclaration)} userCallback + */ + function callback(userCallback, error, computedPayload) + { + if (error || !computedPayload) + userCallback(null); + else + userCallback(WebInspector.CSSStyleDeclaration.parseComputedStylePayload(computedPayload)); + } + + CSSAgent.getComputedStyleForNode(nodeId, forcedPseudoClasses || [], callback.bind(null, userCallback)); + }, + + /** + * @param {DOMAgent.NodeId} nodeId + * @param {function(?WebInspector.CSSStyleDeclaration, ?Object.)} userCallback + */ + getInlineStylesAsync: function(nodeId, userCallback) + { + /** + * @param {function(?WebInspector.CSSStyleDeclaration, ?Object.)} userCallback + */ + function callback(userCallback, error, inlinePayload, attributesPayload) + { + if (error || !inlinePayload) + userCallback(null, null); + else { + var styleAttributes; + if (attributesPayload) { + styleAttributes = {}; + for (var i = 0; i < attributesPayload.length; ++i) { + var name = attributesPayload[i].name; + styleAttributes[name] = WebInspector.CSSStyleDeclaration.parsePayload(attributesPayload[i].style); + } + } + userCallback(WebInspector.CSSStyleDeclaration.parsePayload(inlinePayload), styleAttributes || null); + } + } + + CSSAgent.getInlineStylesForNode(nodeId, callback.bind(null, userCallback)); + }, + + /** + * @param {CSSAgent.CSSRuleId} ruleId + * @param {DOMAgent.NodeId} nodeId + * @param {string} newSelector + * @param {function(WebInspector.CSSRule, boolean)} successCallback + * @param {function()} failureCallback + */ + setRuleSelector: function(ruleId, nodeId, newSelector, successCallback, failureCallback) + { + /** + * @param {DOMAgent.NodeId} nodeId + * @param {function(WebInspector.CSSRule, boolean)} successCallback + * @param {*} rulePayload + * @param {?Array.} selectedNodeIds + */ + function checkAffectsCallback(nodeId, successCallback, rulePayload, selectedNodeIds) + { + if (!selectedNodeIds) + return; + var doesAffectSelectedNode = (selectedNodeIds.indexOf(nodeId) >= 0); + var rule = WebInspector.CSSRule.parsePayload(rulePayload); + successCallback(rule, doesAffectSelectedNode); + this._fireStyleSheetChanged(rule.id.styleSheetId, true); + } + + /** + * @param {DOMAgent.NodeId} nodeId + * @param {function(WebInspector.CSSRule, boolean)} successCallback + * @param {function()} failureCallback + * @param {?Protocol.Error} error + * @param {string} newSelector + * @param {*=} rulePayload + */ + function callback(nodeId, successCallback, failureCallback, newSelector, error, rulePayload) + { + if (error) + failureCallback(); + else { + var ownerDocumentId = this._ownerDocumentId(nodeId); + if (ownerDocumentId) + WebInspector.domAgent.querySelectorAll(ownerDocumentId, newSelector, checkAffectsCallback.bind(this, nodeId, successCallback, rulePayload)); + else + failureCallback(); + } + } + + CSSAgent.setRuleSelector(ruleId, newSelector, callback.bind(this, nodeId, successCallback, failureCallback, newSelector)); + }, + + /** + * @param {DOMAgent.NodeId} nodeId + * @param {string} selector + * @param {function(WebInspector.CSSRule, boolean)} successCallback + * @param {function()} failureCallback + */ + addRule: function(nodeId, selector, successCallback, failureCallback) + { + function checkAffectsCallback(nodeId, successCallback, rulePayload, selectedNodeIds) + { + if (!selectedNodeIds) + return; + + var doesAffectSelectedNode = (selectedNodeIds.indexOf(nodeId) >= 0); + var rule = WebInspector.CSSRule.parsePayload(rulePayload); + successCallback(rule, doesAffectSelectedNode); + this._fireStyleSheetChanged(rule.id.styleSheetId, true); + } + + /** + * @param {function(WebInspector.CSSRule, boolean)} successCallback + * @param {function()} failureCallback + * @param {string} selector + * @param {?Protocol.Error} error + * @param {?CSSAgent.CSSRule} rulePayload + */ + function callback(successCallback, failureCallback, selector, error, rulePayload) + { + if (error) { + // Invalid syntax for a selector + failureCallback(); + } else { + var ownerDocumentId = this._ownerDocumentId(nodeId); + if (ownerDocumentId) + WebInspector.domAgent.querySelectorAll(ownerDocumentId, selector, checkAffectsCallback.bind(this, nodeId, successCallback, rulePayload)); + else + failureCallback(); + } + } + + CSSAgent.addRule(nodeId, selector, callback.bind(this, successCallback, failureCallback, selector)); + }, + + mediaQueryResultChanged: function() + { + this.dispatchEventToListeners(WebInspector.CSSStyleModel.Events.MediaQueryResultChanged); + }, + + _ownerDocumentId: function(nodeId) + { + var node = WebInspector.domAgent.nodeForId(nodeId); + if (!node) + return null; + return node.ownerDocument ? node.ownerDocument.id : null; + }, + + /** + * @param {function()=} callback + */ + _fireStyleSheetChanged: function(styleSheetId, majorChange, callback) + { + callback = callback || function() {}; + + if (!majorChange || !styleSheetId || !this.hasEventListeners(WebInspector.CSSStyleModel.Events.StyleSheetChanged)) { + callback(); + return; + } + + function mycallback(error, content) + { + if (!error) + this.dispatchEventToListeners(WebInspector.CSSStyleModel.Events.StyleSheetChanged, { styleSheetId: styleSheetId, content: content, majorChange: majorChange }); + callback(); + } + + CSSAgent.getStyleSheetText(styleSheetId, mycallback.bind(this)); + }, + + setStyleSheetText: function(styleSheetId, newText, majorChange, userCallback) + { + function callback(error) + { + if (!error) + this._fireStyleSheetChanged(styleSheetId, majorChange, userCallback ? userCallback.bind(this, error) : null); + } + CSSAgent.setStyleSheetText(styleSheetId, newText, callback.bind(this)); + } +} + +WebInspector.CSSStyleModel.prototype.__proto__ = WebInspector.Object.prototype; + +/** + * @constructor + * @param {*} payload + */ +WebInspector.CSSStyleDeclaration = function(payload) +{ + this.id = payload.styleId; + this.width = payload.width; + this.height = payload.height; + this.range = payload.range; + this._shorthandValues = WebInspector.CSSStyleDeclaration.buildShorthandValueMap(payload.shorthandEntries); + this._livePropertyMap = {}; // LIVE properties (source-based or style-based) : { name -> CSSProperty } + this._allProperties = []; // ALL properties: [ CSSProperty ] + this._longhandProperties = {}; // shorthandName -> [ CSSProperty ] + this.__disabledProperties = {}; // DISABLED properties: { index -> CSSProperty } + var payloadPropertyCount = payload.cssProperties.length; + + var propertyIndex = 0; + for (var i = 0; i < payloadPropertyCount; ++i) { + var property = WebInspector.CSSProperty.parsePayload(this, i, payload.cssProperties[i]); + this._allProperties.push(property); + if (property.disabled) + this.__disabledProperties[i] = property; + if (!property.active && !property.styleBased) + continue; + var name = property.name; + this[propertyIndex] = name; + this._livePropertyMap[name] = property; + + // Index longhand properties. + if (property.shorthand) { // only for parsed + var longhands = this._longhandProperties[property.shorthand]; + if (!longhands) { + longhands = []; + this._longhandProperties[property.shorthand] = longhands; + } + longhands.push(property); + } + ++propertyIndex; + } + this.length = propertyIndex; + if ("cssText" in payload) + this.cssText = payload.cssText; +} + +WebInspector.CSSStyleDeclaration.buildShorthandValueMap = function(shorthandEntries) +{ + var result = {}; + for (var i = 0; i < shorthandEntries.length; ++i) + result[shorthandEntries[i].name] = shorthandEntries[i].value; + return result; +} + +WebInspector.CSSStyleDeclaration.parsePayload = function(payload) +{ + return new WebInspector.CSSStyleDeclaration(payload); +} + +WebInspector.CSSStyleDeclaration.parseComputedStylePayload = function(payload) +{ + var newPayload = { cssProperties: [], shorthandEntries: [], width: "", height: "" }; + if (payload) + newPayload.cssProperties = payload; + + return new WebInspector.CSSStyleDeclaration(newPayload); +} + +WebInspector.CSSStyleDeclaration.prototype = { + get allProperties() + { + return this._allProperties; + }, + + getLiveProperty: function(name) + { + return this._livePropertyMap[name]; + }, + + getPropertyValue: function(name) + { + var property = this._livePropertyMap[name]; + return property ? property.value : ""; + }, + + getPropertyPriority: function(name) + { + var property = this._livePropertyMap[name]; + return property ? property.priority : ""; + }, + + getPropertyShorthand: function(name) + { + var property = this._livePropertyMap[name]; + return property ? property.shorthand : ""; + }, + + isPropertyImplicit: function(name) + { + var property = this._livePropertyMap[name]; + return property ? property.implicit : ""; + }, + + styleTextWithShorthands: function() + { + var cssText = ""; + var foundProperties = {}; + for (var i = 0; i < this.length; ++i) { + var individualProperty = this[i]; + var shorthandProperty = this.getPropertyShorthand(individualProperty); + var propertyName = (shorthandProperty || individualProperty); + + if (propertyName in foundProperties) + continue; + + if (shorthandProperty) { + var value = this.getShorthandValue(shorthandProperty); + var priority = this.getShorthandPriority(shorthandProperty); + } else { + var value = this.getPropertyValue(individualProperty); + var priority = this.getPropertyPriority(individualProperty); + } + + foundProperties[propertyName] = true; + + cssText += propertyName + ": " + value; + if (priority) + cssText += " !" + priority; + cssText += "; "; + } + + return cssText; + }, + + getLonghandProperties: function(name) + { + return this._longhandProperties[name] || []; + }, + + getShorthandValue: function(shorthandProperty) + { + var property = this.getLiveProperty(shorthandProperty); + return property ? property.value : this._shorthandValues[shorthandProperty]; + }, + + getShorthandPriority: function(shorthandProperty) + { + var priority = this.getPropertyPriority(shorthandProperty); + if (priority) + return priority; + + var longhands = this._longhandProperties[shorthandProperty]; + return longhands ? this.getPropertyPriority(longhands[0]) : null; + }, + + propertyAt: function(index) + { + return (index < this.allProperties.length) ? this.allProperties[index] : null; + }, + + pastLastSourcePropertyIndex: function() + { + for (var i = this.allProperties.length - 1; i >= 0; --i) { + var property = this.allProperties[i]; + if (property.active || property.disabled) + return i + 1; + } + return 0; + }, + + newBlankProperty: function() + { + return new WebInspector.CSSProperty(this, this.pastLastSourcePropertyIndex(), "", "", "", "active", true, false, false, ""); + }, + + insertPropertyAt: function(index, name, value, userCallback) + { + function callback(userCallback, error, payload) + { + if (!userCallback) + return; + + if (error) { + console.error(JSON.stringify(error)); + userCallback(null); + } else { + userCallback(WebInspector.CSSStyleDeclaration.parsePayload(payload)); + WebInspector.cssModel._fireStyleSheetChanged(this.id.styleSheetId, true); + } + } + + CSSAgent.setPropertyText(this.id, index, name + ": " + value + ";", false, callback.bind(this, userCallback)); + }, + + appendProperty: function(name, value, userCallback) + { + this.insertPropertyAt(this.allProperties.length, name, value, userCallback); + } +} + +/** + * @constructor + */ +WebInspector.CSSRule = function(payload) +{ + this.id = payload.ruleId; + this.selectorText = payload.selectorText; + this.sourceLine = payload.sourceLine; + this.sourceURL = payload.sourceURL; + this.origin = payload.origin; + this.style = WebInspector.CSSStyleDeclaration.parsePayload(payload.style); + this.style.parentRule = this; + this.selectorRange = payload.selectorRange; + if (payload.media) + this.media = WebInspector.CSSMedia.parseMediaArrayPayload(payload.media); +} + +WebInspector.CSSRule.parsePayload = function(payload) +{ + return new WebInspector.CSSRule(payload); +} + +WebInspector.CSSRule.prototype = { + get isUserAgent() + { + return this.origin === "user-agent"; + }, + + get isUser() + { + return this.origin === "user"; + }, + + get isViaInspector() + { + return this.origin === "inspector"; + }, + + get isRegular() + { + return this.origin === "regular"; + } +} + +/** + * @constructor + */ +WebInspector.CSSProperty = function(ownerStyle, index, name, value, priority, status, parsedOk, implicit, shorthand, text) +{ + this.ownerStyle = ownerStyle; + this.index = index; + this.name = name; + this.value = value; + this.priority = priority; + this.status = status; + this.parsedOk = parsedOk; + this.implicit = implicit; + this.shorthand = shorthand; + this.text = text; +} + +WebInspector.CSSProperty.parsePayload = function(ownerStyle, index, payload) +{ + // The following default field values are used in the payload: + // priority: "" + // parsedOk: true + // implicit: false + // status: "style" + // shorthandName: "" + var result = new WebInspector.CSSProperty( + ownerStyle, index, payload.name, payload.value, payload.priority || "", payload.status || "style", ("parsedOk" in payload) ? payload.parsedOk : true, !!payload.implicit, payload.shorthandName || "", payload.text); + return result; +} + +WebInspector.CSSProperty.prototype = { + get propertyText() + { + if (this.text !== undefined) + return this.text; + + if (this.name === "") + return ""; + return this.name + ": " + this.value + (this.priority ? " !" + this.priority : "") + ";"; + }, + + get isLive() + { + return this.active || this.styleBased; + }, + + get active() + { + return this.status === "active"; + }, + + get styleBased() + { + return this.status === "style"; + }, + + get inactive() + { + return this.status === "inactive"; + }, + + get disabled() + { + return this.status === "disabled"; + }, + + // Replaces "propertyName: propertyValue [!important];" in the stylesheet by an arbitrary propertyText. + setText: function(propertyText, majorChange, userCallback) + { + function enabledCallback(style) + { + if (style) + WebInspector.cssModel._fireStyleSheetChanged(style.id.styleSheetId, majorChange, userCallback ? userCallback.bind(null, style) : null); + else if (userCallback) + userCallback(style); + } + + function callback(error, stylePayload) + { + if (!error) { + this.text = propertyText; + var style = WebInspector.CSSStyleDeclaration.parsePayload(stylePayload); + var newProperty = style.allProperties[this.index]; + + if (newProperty && this.disabled && !propertyText.match(/^\s*$/)) { + newProperty.setDisabled(false, enabledCallback); + return; + } + + WebInspector.cssModel._fireStyleSheetChanged(style.id.styleSheetId, majorChange, userCallback ? userCallback.bind(null, style) : null); + } else { + if (userCallback) + userCallback(null); + } + } + + if (!this.ownerStyle) + throw "No ownerStyle for property"; + + // An index past all the properties adds a new property to the style. + CSSAgent.setPropertyText(this.ownerStyle.id, this.index, propertyText, this.index < this.ownerStyle.pastLastSourcePropertyIndex(), callback.bind(this)); + }, + + setValue: function(newValue, majorChange, userCallback) + { + var text = this.name + ": " + newValue + (this.priority ? " !" + this.priority : "") + ";" + this.setText(text, majorChange, userCallback); + }, + + setDisabled: function(disabled, userCallback) + { + if (!this.ownerStyle && userCallback) + userCallback(null); + if (disabled === this.disabled && userCallback) + userCallback(this.ownerStyle); + + function callback(error, stylePayload) + { + if (error) { + if (userCallback) + userCallback(null); + return; + } + if (userCallback) { + var style = WebInspector.CSSStyleDeclaration.parsePayload(stylePayload); + userCallback(style); + } + WebInspector.cssModel._fireStyleSheetChanged(this.ownerStyle.id.styleSheetId, false); + } + + CSSAgent.toggleProperty(this.ownerStyle.id, this.index, disabled, callback.bind(this)); + } +} + +/** + * @constructor + * @param {*} payload + */ +WebInspector.CSSMedia = function(payload) +{ + this.text = payload.text; + this.source = payload.source; + this.sourceURL = payload.sourceURL || ""; + this.sourceLine = typeof payload.sourceLine === "undefined" || this.source === "linkedSheet" ? -1 : payload.sourceLine; +} + +WebInspector.CSSMedia.Source = { + LINKED_SHEET: "linkedSheet", + INLINE_SHEET: "inlineSheet", + MEDIA_RULE: "mediaRule", + IMPORT_RULE: "importRule" +}; + +WebInspector.CSSMedia.parsePayload = function(payload) +{ + return new WebInspector.CSSMedia(payload); +} + +WebInspector.CSSMedia.parseMediaArrayPayload = function(payload) +{ + var result = []; + for (var i = 0; i < payload.length; ++i) + result.push(WebInspector.CSSMedia.parsePayload(payload[i])); + return result; +} + +/** + * @constructor + */ +WebInspector.CSSStyleSheet = function(payload) +{ + this.id = payload.styleSheetId; + this.rules = []; + this.styles = {}; + for (var i = 0; i < payload.rules.length; ++i) { + var rule = WebInspector.CSSRule.parsePayload(payload.rules[i]); + this.rules.push(rule); + if (rule.style) + this.styles[rule.style.id] = rule.style; + } + if ("text" in payload) + this._text = payload.text; +} + +WebInspector.CSSStyleSheet.createForId = function(styleSheetId, userCallback) +{ + function callback(error, styleSheetPayload) + { + if (error) + userCallback(null); + else + userCallback(new WebInspector.CSSStyleSheet(styleSheetPayload)); + } + CSSAgent.getStyleSheet(styleSheetId, callback.bind(this)); +} + +WebInspector.CSSStyleSheet.prototype = { + getText: function() + { + return this._text; + }, + + setText: function(newText, majorChange, userCallback) + { + function callback(error) + { + if (userCallback) + userCallback(error); + if (!error) + WebInspector.cssModel._fireStyleSheetChanged(this.id, majorChange); + } + + CSSAgent.setStyleSheetText(this.id, newText, callback.bind(this)); + } +} + +/** + * @constructor + * @implements {WebInspector.ResourceDomainModelBinding} + */ +WebInspector.CSSStyleModelResourceBinding = function(cssModel) +{ + this._cssModel = cssModel; + this._urlToStyleSheetId = {}; + this._styleSheetIdToURL = {}; + this._cssModel.addEventListener(WebInspector.CSSStyleModel.Events.StyleSheetChanged, this._styleSheetChanged, this); + WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.InspectedURLChanged, this._inspectedURLChanged, this); + WebInspector.Resource.registerDomainModelBinding(WebInspector.Resource.Type.Stylesheet, this); +} + +WebInspector.CSSStyleModelResourceBinding.prototype = { + setContent: function(resource, content, majorChange, userCallback) + { + if (this._urlToStyleSheetId[resource.url]) { + this._innerSetContent(resource.url, content, majorChange, userCallback, null); + return; + } + this._loadStyleSheetHeaders(this._innerSetContent.bind(this, resource.url, content, majorChange, userCallback)); + }, + + canSetContent: function() + { + return true; + }, + + _inspectedURLChanged: function(event) + { + // Main frame navigation - clear history. + this._urlToStyleSheetId = {}; + this._styleSheetIdToURL = {}; + }, + + _innerSetContent: function(url, content, majorChange, userCallback, error) + { + if (error) { + userCallback(error); + return; + } + + var styleSheetId = this._urlToStyleSheetId[url]; + if (!styleSheetId) { + if (userCallback) + userCallback("No stylesheet found: " + url); + return; + } + this._cssModel.setStyleSheetText(styleSheetId, content, majorChange, userCallback); + }, + + _loadStyleSheetHeaders: function(callback) + { + function didGetAllStyleSheets(error, infos) + { + if (error) { + callback(error); + return; + } + + for (var i = 0; i < infos.length; ++i) { + var info = infos[i]; + this._urlToStyleSheetId[info.sourceURL] = info.styleSheetId; + this._styleSheetIdToURL[info.styleSheetId] = info.sourceURL; + } + callback(); + } + CSSAgent.getAllStyleSheets(didGetAllStyleSheets.bind(this)); + }, + + _styleSheetChanged: function(event) + { + var styleSheetId = event.data.styleSheetId; + function setContent() + { + var url = this._styleSheetIdToURL[styleSheetId]; + if (!url) + return; + + var resource = WebInspector.resourceForURL(url); + if (!resource) + return; + + var majorChange = event.data.majorChange; + if (majorChange) + resource.addRevision(event.data.content); + } + + if (!this._styleSheetIdToURL[styleSheetId]) { + this._loadStyleSheetHeaders(setContent.bind(this)); + return; + } + setContent.call(this); + } +} + +WebInspector.CSSStyleModelResourceBinding.prototype.__proto__ = WebInspector.ResourceDomainModelBinding.prototype; + +/** + * @constructor + * @implements {CSSAgent.Dispatcher} + * @param {WebInspector.CSSStyleModel} cssModel + */ +WebInspector.CSSDispatcher = function(cssModel) +{ + this._cssModel = cssModel; +} + +WebInspector.CSSDispatcher.prototype = { + mediaQueryResultChanged: function() + { + this._cssModel.mediaQueryResultChanged(); + } +} + +/** + * @type {WebInspector.CSSStyleModel} + */ +WebInspector.cssModel = null; +/* NetworkManager.js */ + +/* + * Copyright (C) 2011 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. + */ + +/** + * @constructor + * @extends {WebInspector.Object} + */ +WebInspector.NetworkManager = function() +{ + WebInspector.Object.call(this); + this._dispatcher = new WebInspector.NetworkDispatcher(this); + if (WebInspector.settings.cacheDisabled.get()) + NetworkAgent.setCacheDisabled(true); + + NetworkAgent.enable(); + + WebInspector.settings.cacheDisabled.addChangeListener(this._cacheDisabledSettingChanged, this); + + if (WebInspector.settings.userAgent.get()) + this._userAgentSettingChanged(); + WebInspector.settings.userAgent.addChangeListener(this._userAgentSettingChanged, this); +} + +WebInspector.NetworkManager.EventTypes = { + ResourceTrackingEnabled: "ResourceTrackingEnabled", + ResourceTrackingDisabled: "ResourceTrackingDisabled", + ResourceStarted: "ResourceStarted", + ResourceUpdated: "ResourceUpdated", + ResourceFinished: "ResourceFinished", + ResourceUpdateDropped: "ResourceUpdateDropped" +} + +WebInspector.NetworkManager.prototype = { + /** + * @param {WebInspector.Resource} resource + * @param {function(?string, boolean)} callback + */ + requestContent: function(resource, callback) + { + function callbackWrapper(error, content, contentEncoded) + { + if (error) + callback(null, false); + else + callback(content, content && contentEncoded); + } + // FIXME: https://bugs.webkit.org/show_bug.cgi?id=61363 We should separate NetworkResource (NetworkPanel resource) + // from ResourceRevision (ResourcesPanel/ScriptsPanel resource) and request content accordingly. + if (resource.requestId) + NetworkAgent.getResponseBody(resource.requestId, callbackWrapper); + else + PageAgent.getResourceContent(resource.frameId, resource.url, callbackWrapper); + }, + + enableResourceTracking: function() + { + function callback(error) + { + this.dispatchEventToListeners(WebInspector.NetworkManager.EventTypes.ResourceTrackingEnabled); + } + NetworkAgent.enable(callback.bind(this)); + }, + + disableResourceTracking: function() + { + function callback(error) + { + this.dispatchEventToListeners(WebInspector.NetworkManager.EventTypes.ResourceTrackingDisabled); + } + NetworkAgent.disable(callback.bind(this)); + }, + + /** + * @param {string} url + * @return {WebInspector.Resource} + */ + inflightResourceForURL: function(url) + { + return this._dispatcher._inflightResourcesByURL[url]; + }, + + /** + * @param {WebInspector.Event} event + */ + _cacheDisabledSettingChanged: function(event) + { + var enabled = /** @type {boolean} */ event.data; + NetworkAgent.setCacheDisabled(enabled); + }, + + _userAgentSettingChanged: function() + { + NetworkAgent.setUserAgentOverride(WebInspector.settings.userAgent.get()); + } +} + +WebInspector.NetworkManager.prototype.__proto__ = WebInspector.Object.prototype; + +/** + * @constructor + * @implements {NetworkAgent.Dispatcher} + */ +WebInspector.NetworkDispatcher = function(manager) +{ + this._manager = manager; + this._inflightResourcesById = {}; + this._inflightResourcesByURL = {}; + InspectorBackend.registerNetworkDispatcher(this); +} + +WebInspector.NetworkDispatcher.prototype = { + /** + * @param {WebInspector.Resource} resource + * @param {NetworkAgent.Request} request + */ + _updateResourceWithRequest: function(resource, request) + { + resource.requestMethod = request.method; + resource.requestHeaders = request.headers; + resource.requestFormData = request.postData; + }, + + /** + * @param {WebInspector.Resource} resource + * @param {NetworkAgent.Response=} response + */ + _updateResourceWithResponse: function(resource, response) + { + if (!response) + return; + + if (response.url && resource.url !== response.url) + resource.url = response.url; + resource.mimeType = response.mimeType; + resource.statusCode = response.status; + resource.statusText = response.statusText; + resource.responseHeaders = response.headers; + if (response.headersText) + resource.responseHeadersText = response.headersText; + if (response.requestHeaders) + resource.requestHeaders = response.requestHeaders; + if (response.requestHeadersText) + resource.requestHeadersText = response.requestHeadersText; + + resource.connectionReused = response.connectionReused; + resource.connectionId = response.connectionId; + + if (response.fromDiskCache) + resource.cached = true; + else + resource.timing = response.timing; + + if (!this._mimeTypeIsConsistentWithType(resource)) { + WebInspector.console.addMessage(WebInspector.ConsoleMessage.create(WebInspector.ConsoleMessage.MessageSource.Network, + WebInspector.ConsoleMessage.MessageLevel.Warning, + WebInspector.UIString("Resource interpreted as %s but transferred with MIME type %s: \"%s\".", WebInspector.Resource.Type.toUIString(resource.type), resource.mimeType, resource.url), + WebInspector.ConsoleMessage.MessageType.Log, + "", + 0, + 1, + [], + null, + resource)); + } + }, + + /** + * @param {WebInspector.Resource} resource + * @return {boolean} + */ + _mimeTypeIsConsistentWithType: function(resource) + { + // If status is an error, content is likely to be of an inconsistent type, + // as it's going to be an error message. We do not want to emit a warning + // for this, though, as this will already be reported as resource loading failure. + // Also, if a URL like http://localhost/wiki/load.php?debug=true&lang=en produces text/css and gets reloaded, + // it is 304 Not Modified and its guessed mime-type is text/php, which is wrong. + // Don't check for mime-types in 304-resources. + if (resource.hasErrorStatusCode() || resource.statusCode === 304) + return true; + + if (typeof resource.type === "undefined" + || resource.type === WebInspector.Resource.Type.Other + || resource.type === WebInspector.Resource.Type.XHR + || resource.type === WebInspector.Resource.Type.WebSocket) + return true; + + if (!resource.mimeType) + return true; // Might be not known for cached resources with null responses. + + if (resource.mimeType in WebInspector.MIMETypes) + return resource.type in WebInspector.MIMETypes[resource.mimeType]; + + return false; + }, + + /** + * @param {WebInspector.Resource} resource + * @param {?NetworkAgent.CachedResource} cachedResource + */ + _updateResourceWithCachedResource: function(resource, cachedResource) + { + resource.type = WebInspector.Resource.Type[cachedResource.type]; + resource.resourceSize = cachedResource.bodySize; + this._updateResourceWithResponse(resource, cachedResource.response); + }, + + /** + * @param {NetworkAgent.Response} response + * @return {boolean} + */ + _isNull: function(response) + { + if (!response) + return true; + return !response.status && !response.mimeType && (!response.headers || !Object.keys(response.headers).length); + }, + + /** + * @param {NetworkAgent.RequestId} requestId + * @param {NetworkAgent.FrameId} frameId + * @param {NetworkAgent.LoaderId} loaderId + * @param {string} documentURL + * @param {NetworkAgent.Request} request + * @param {NetworkAgent.Timestamp} time + * @param {NetworkAgent.Initiator} initiator + * @param {ConsoleAgent.StackTrace=} stackTrace + * @param {NetworkAgent.Response=} redirectResponse + */ + requestWillBeSent: function(requestId, frameId, loaderId, documentURL, request, time, initiator, stackTrace, redirectResponse) + { + var resource = this._inflightResourcesById[requestId]; + if (resource) { + // FIXME: move this check to the backend. + if (!redirectResponse) + return; + this.responseReceived(requestId, frameId, loaderId, time, "Other", redirectResponse); + resource = this._appendRedirect(requestId, time, request.url); + } else + resource = this._createResource(requestId, frameId, loaderId, request.url, documentURL, initiator, stackTrace); + resource.hasNetworkData = true; + this._updateResourceWithRequest(resource, request); + resource.startTime = time; + + this._startResource(resource); + }, + + /** + * @param {NetworkAgent.RequestId} requestId + */ + requestServedFromCache: function(requestId) + { + var resource = this._inflightResourcesById[requestId]; + if (!resource) + return; + + resource.cached = true; + }, + + /** + * @param {NetworkAgent.RequestId} requestId + * @param {NetworkAgent.FrameId} frameId + * @param {NetworkAgent.LoaderId} loaderId + * @param {NetworkAgent.Timestamp} time + * @param {PageAgent.ResourceType} resourceType + * @param {NetworkAgent.Response} response + */ + responseReceived: function(requestId, frameId, loaderId, time, resourceType, response) + { + // FIXME: move this check to the backend. + if (this._isNull(response)) + return; + + var resource = this._inflightResourcesById[requestId]; + if (!resource) { + // We missed the requestWillBeSent. + var eventData = {}; + eventData.url = response.url; + eventData.frameId = frameId; + eventData.loaderId = loaderId; + eventData.resourceType = resourceType; + eventData.mimeType = response.mimeType; + this._manager.dispatchEventToListeners(WebInspector.NetworkManager.EventTypes.ResourceUpdateDropped, eventData); + return; + } + + resource.responseReceivedTime = time; + resource.type = WebInspector.Resource.Type[resourceType]; + + this._updateResourceWithResponse(resource, response); + + this._updateResource(resource); + }, + + /** + * @param {NetworkAgent.RequestId} requestId + * @param {NetworkAgent.Timestamp} time + * @param {number} dataLength + * @param {number} encodedDataLength + */ + dataReceived: function(requestId, time, dataLength, encodedDataLength) + { + var resource = this._inflightResourcesById[requestId]; + if (!resource) + return; + + resource.resourceSize += dataLength; + if (encodedDataLength != -1) + resource.increaseTransferSize(encodedDataLength); + resource.endTime = time; + + this._updateResource(resource); + }, + + /** + * @param {NetworkAgent.RequestId} requestId + * @param {NetworkAgent.Timestamp} finishTime + */ + loadingFinished: function(requestId, finishTime) + { + var resource = this._inflightResourcesById[requestId]; + if (!resource) + return; + this._finishResource(resource, finishTime); + }, + + /** + * @param {NetworkAgent.RequestId} requestId + * @param {NetworkAgent.Timestamp} time + * @param {string} localizedDescription + * @param {boolean=} canceled + */ + loadingFailed: function(requestId, time, localizedDescription, canceled) + { + var resource = this._inflightResourcesById[requestId]; + if (!resource) + return; + + resource.failed = true; + resource.canceled = canceled; + resource.localizedFailDescription = localizedDescription; + this._finishResource(resource, time); + }, + + /** + * @param {NetworkAgent.RequestId} requestId + * @param {NetworkAgent.FrameId} frameId + * @param {NetworkAgent.LoaderId} loaderId + * @param {string} documentURL + * @param {NetworkAgent.Timestamp} time + * @param {NetworkAgent.Initiator} initiator + * @param {NetworkAgent.CachedResource} cachedResource + */ + requestServedFromMemoryCache: function(requestId, frameId, loaderId, documentURL, time, initiator, cachedResource) + { + var resource = this._createResource(requestId, frameId, loaderId, cachedResource.url, documentURL, initiator, null); + this._updateResourceWithCachedResource(resource, cachedResource); + resource.cached = true; + resource.requestMethod = "GET"; + this._startResource(resource); + resource.startTime = resource.responseReceivedTime = time; + this._finishResource(resource, time); + }, + + /** + * @param {NetworkAgent.RequestId} requestId + * @param {string} requestURL + */ + webSocketCreated: function(requestId, requestURL) + { + var resource = new WebInspector.Resource(requestId, requestURL, "", null); + resource.type = WebInspector.Resource.Type.WebSocket; + this._startResource(resource); + }, + + /** + * @param {NetworkAgent.RequestId} requestId + * @param {NetworkAgent.Timestamp} time + * @param {NetworkAgent.WebSocketRequest} request + */ + webSocketWillSendHandshakeRequest: function(requestId, time, request) + { + var resource = this._inflightResourcesById[requestId]; + if (!resource) + return; + + resource.requestMethod = "GET"; + resource.requestHeaders = request.headers; + resource.webSocketRequestKey3 = request.requestKey3; + resource.startTime = time; + + this._updateResource(resource); + }, + + /** + * @param {NetworkAgent.RequestId} requestId + * @param {NetworkAgent.Timestamp} time + * @param {NetworkAgent.WebSocketResponse} response + */ + webSocketHandshakeResponseReceived: function(requestId, time, response) + { + var resource = this._inflightResourcesById[requestId]; + if (!resource) + return; + + resource.statusCode = response.status; + resource.statusText = response.statusText; + resource.responseHeaders = response.headers; + resource.webSocketChallengeResponse = response.challengeResponse; + resource.responseReceivedTime = time; + + this._updateResource(resource); + }, + + /** + * @param {NetworkAgent.RequestId} requestId + * @param {NetworkAgent.Timestamp} time + */ + webSocketClosed: function(requestId, time) + { + var resource = this._inflightResourcesById[requestId]; + if (!resource) + return; + this._finishResource(resource, time); + }, + + /** + * @param {NetworkAgent.RequestId} requestId + * @param {NetworkAgent.Timestamp} time + * @param {string} redirectURL + */ + _appendRedirect: function(requestId, time, redirectURL) + { + var originalResource = this._inflightResourcesById[requestId]; + var previousRedirects = originalResource.redirects || []; + originalResource.requestId = "redirected:" + requestId + "." + previousRedirects.length; + delete originalResource.redirects; + if (previousRedirects.length > 0) + originalResource.redirectSource = previousRedirects[previousRedirects.length - 1]; + this._finishResource(originalResource, time); + var newResource = this._createResource(requestId, originalResource.frameId, originalResource.loaderId, + redirectURL, originalResource.documentURL, originalResource.initiator, originalResource.stackTrace); + newResource.redirects = previousRedirects.concat(originalResource); + return newResource; + }, + + /** + * @param {WebInspector.Resource} resource + */ + _startResource: function(resource) + { + this._inflightResourcesById[resource.requestId] = resource; + this._inflightResourcesByURL[resource.url] = resource; + this._dispatchEventToListeners(WebInspector.NetworkManager.EventTypes.ResourceStarted, resource); + }, + + /** + * @param {WebInspector.Resource} resource + */ + _updateResource: function(resource) + { + this._dispatchEventToListeners(WebInspector.NetworkManager.EventTypes.ResourceUpdated, resource); + }, + + /** + * @param {WebInspector.Resource} resource + * @param {NetworkAgent.Timestamp} finishTime + */ + _finishResource: function(resource, finishTime) + { + resource.endTime = finishTime; + resource.finished = true; + this._dispatchEventToListeners(WebInspector.NetworkManager.EventTypes.ResourceFinished, resource); + delete this._inflightResourcesById[resource.requestId]; + delete this._inflightResourcesByURL[resource.url]; + }, + + /** + * @param {string} eventType + * @param {WebInspector.Resource} resource + */ + _dispatchEventToListeners: function(eventType, resource) + { + this._manager.dispatchEventToListeners(eventType, resource); + }, + + /** + * @param {NetworkAgent.RequestId} requestId + * @param {string} frameId + * @param {NetworkAgent.LoaderId} loaderId + * @param {string} url + * @param {string} documentURL + * @param {NetworkAgent.Initiator} initiator + * @param {ConsoleAgent.StackTrace=} stackTrace + */ + _createResource: function(requestId, frameId, loaderId, url, documentURL, initiator, stackTrace) + { + var resource = new WebInspector.Resource(requestId, url, frameId, loaderId); + resource.documentURL = documentURL; + resource.initiator = initiator; + resource.stackTrace = stackTrace; + return resource; + } +} + +/** + * @type {?WebInspector.NetworkManager} + */ +WebInspector.networkManager = null; +/* NetworkLog.js */ + +/* + * Copyright (C) 2011 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. + */ + +/** + * @constructor + */ +WebInspector.NetworkLog = function() +{ + this._resources = []; + WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceStarted, this._onResourceStarted, this); + WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, this._onMainFrameNavigated, this); + WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.OnLoad, this._onLoad, this); + WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.DOMContentLoaded, this._onDOMContentLoaded, this); +} + +WebInspector.NetworkLog.prototype = { + /** + * @return {Array.} + */ + get resources() + { + return this._resources; + }, + + /** + * @param {WebInspector.Resource} resource + * @return {WebInspector.PageLoad} + */ + pageLoadForResource: function(resource) + { + return resource.__page; + }, + + /** + * @param {WebInspector.Event} event + */ + _onMainFrameNavigated: function(event) + { + var mainFrame = /** type {WebInspector.ResourceTreeFrame} */ event.data; + // Preserve resources from the new session. + this._currentPageLoad = null; + var oldResources = this._resources.splice(0, this._resources.length); + for (var i = 0; i < oldResources.length; ++i) { + var resource = oldResources[i]; + if (resource.loaderId === mainFrame.loaderId) { + if (!this._currentPageLoad) + this._currentPageLoad = new WebInspector.PageLoad(resource); + this._resources.push(resource); + resource.__page = this._currentPageLoad; + } + } + }, + + /** + * @param {WebInspector.Event} event + */ + _onResourceStarted: function(event) + { + var resource = /** @type {WebInspector.Resource} */ event.data; + this._resources.push(resource); + resource.__page = this._currentPageLoad; + }, + + /** + * @param {WebInspector.Event} event + */ + _onDOMContentLoaded: function(event) + { + if (this._currentPageLoad) + this._currentPageLoad.contentLoadTime = event.data; + }, + + /** + * @param {WebInspector.Event} event + */ + _onLoad: function(event) + { + if (this._currentPageLoad) + this._currentPageLoad.loadTime = event.data; + }, + +} + +/** + * @type {WebInspector.NetworkLog} + */ +WebInspector.networkLog = null; + +/** + * @constructor + * @param {WebInspector.Resource} mainResource + */ +WebInspector.PageLoad = function(mainResource) +{ + this.id = ++WebInspector.PageLoad._lastIdentifier; + this.url = mainResource.url; + this.startTime = mainResource.startTime; +} + +WebInspector.PageLoad._lastIdentifier = 0; +/* ResourceTreeModel.js */ + +/* + * Copyright (C) 2011 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. + */ + +/** + * @constructor + * @extends {WebInspector.Object} + * @param {WebInspector.NetworkManager} networkManager + */ +WebInspector.ResourceTreeModel = function(networkManager) +{ + networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceTrackingEnabled, this._onResourceTrackingEnabled, this); + networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceUpdated, this._onResourceUpdated, this); + networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceFinished, this._onResourceUpdated, this); + networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceUpdateDropped, this._onResourceUpdateDropped, this); + + WebInspector.console.addEventListener(WebInspector.ConsoleModel.Events.MessageAdded, this._consoleMessageAdded, this); + WebInspector.console.addEventListener(WebInspector.ConsoleModel.Events.RepeatCountUpdated, this._consoleMessageAdded, this); + WebInspector.console.addEventListener(WebInspector.ConsoleModel.Events.ConsoleCleared, this._consoleCleared, this); + + PageAgent.enable(); + + NetworkAgent.enable(); + this._fetchResourceTree(); + + InspectorBackend.registerPageDispatcher(new WebInspector.PageDispatcher(this)); + + this._pendingConsoleMessages = {}; +} + +WebInspector.ResourceTreeModel.EventTypes = { + FrameAdded: "FrameAdded", + FrameNavigated: "FrameNavigated", + FrameDetached: "FrameDetached", + MainFrameNavigated: "MainFrameNavigated", + ResourceAdded: "ResourceAdded", + ResourceContentCommitted: "resource-content-committed", + WillLoadCachedResources: "WillLoadCachedResources", + CachedResourcesLoaded: "CachedResourcesLoaded", + DOMContentLoaded: "DOMContentLoaded", + OnLoad: "OnLoad", + InspectedURLChanged: "InspectedURLChanged" +} + +WebInspector.ResourceTreeModel.prototype = { + _onResourceTrackingEnabled: function() + { + this._fetchResourceTree(); + }, + + _fetchResourceTree: function() + { + this._frames = {}; + delete this._cachedResourcesProcessed; + PageAgent.getResourceTree(this._processCachedResources.bind(this)); + }, + + _processCachedResources: function(error, mainFramePayload) + { + if (error) { + console.error(JSON.stringify(error)); + return; + } + + this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.WillLoadCachedResources); + WebInspector.inspectedPageURL = mainFramePayload.frame.url; + this._addFramesRecursively(null, mainFramePayload); + this._dispatchInspectedURLChanged(); + this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.CachedResourcesLoaded); + WebInspector.Resource.restoreRevisions(); + + this._cachedResourcesProcessed = true; + }, + + _dispatchInspectedURLChanged: function() + { + InspectorFrontendHost.inspectedURLChanged(WebInspector.inspectedPageURL); + this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.InspectedURLChanged, WebInspector.inspectedPageURL); + }, + + /** + * @param {WebInspector.ResourceTreeFrame} frame + */ + _addFrame: function(frame) + { + this._frames[frame.id] = frame; + if (frame.isMainFrame()) + this.mainFrame = frame; + this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.FrameAdded, frame); + }, + + /** + * @param {PageAgent.Frame} framePayload + */ + _frameNavigated: function(framePayload) + { + if (this._frontendReused(framePayload)) + return; + + // Do nothing unless cached resource tree is processed - it will overwrite everything. + if (!this._cachedResourcesProcessed) + return; + var frame = this._frames[framePayload.id]; + if (frame) { + // Navigation within existing frame. + frame._navigate(framePayload); + } else { + // Either a new frame or a main frame navigation to the new backend process. + var parentFrame = this._frames[framePayload.parentId]; + frame = new WebInspector.ResourceTreeFrame(this, parentFrame, framePayload); + if (frame.isMainFrame() && this.mainFrame) { + // Definitely a navigation to the new backend process. + this._frameDetached(this.mainFrame.id); + } + this._addFrame(frame); + } + + if (frame.isMainFrame()) + WebInspector.inspectedPageURL = frame.url; + + this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.FrameNavigated, frame); + if (frame.isMainFrame()) + this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, frame); + + // Fill frame with retained resources (the ones loaded using new loader). + var resources = frame.resources(); + for (var i = 0; i < resources.length; ++i) + this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.ResourceAdded, resources[i]); + + if (frame.isMainFrame()) + this._dispatchInspectedURLChanged(); + }, + + /** + * @param {PageAgent.Frame} framePayload + * @return {boolean} + */ + _frontendReused: function(framePayload) + { + if (!framePayload.parentId && !WebInspector.networkLog.resources.length) { + // We are navigating main frame to the existing loaded backend (no provisioual loaded resources are there). + this._fetchResourceTree(); + return true; + } + return false; + }, + + /** + * @param {NetworkAgent.FrameId} frameId + */ + _frameDetached: function(frameId) + { + // Do nothing unless cached resource tree is processed - it will overwrite everything. + if (!this._cachedResourcesProcessed) + return; + + var frame = this._frames[frameId]; + if (!frame) + return; + + if (frame.parentFrame) + frame.parentFrame._removeChildFrame(frame); + else + frame._remove(); + }, + + /** + * @param {WebInspector.Event} event + */ + _onResourceUpdated: function(event) + { + if (!this._cachedResourcesProcessed) + return; + + var resource = /** @type {WebInspector.Resource} */ event.data; + this._addPendingConsoleMessagesToResource(resource); + + if (resource.failed || resource.type === WebInspector.Resource.Type.XHR) + return; + + var frame = this._frames[resource.frameId]; + if (frame) + frame._addResource(resource); + }, + + /** + * @param {WebInspector.Event} event + */ + _onResourceUpdateDropped: function(event) + { + if (!this._cachedResourcesProcessed) + return; + + var frameId = event.data.frameId; + var frame = this._frames[frameId]; + if (!frame) + return; + + var url = event.data.url; + if (frame._resourcesMap[url]) + return; + + var resource = this._createResource(url, frame.url, frameId, event.data.loaderId); + resource.type = WebInspector.Resource.Type[event.data.resourceType]; + resource.mimeType = event.data.mimeType; + resource.finished = true; + frame._addResource(resource); + }, + + /** + * @param {NetworkAgent.FrameId} frameId + */ + frameForId: function(frameId) + { + return this._frames[frameId]; + }, + + /** + * @param {function(WebInspector.Resource)} callback + * @return {boolean} + */ + forAllResources: function(callback) + { + if (this.mainFrame) + return this.mainFrame._callForFrameResources(callback); + return false; + }, + + /** + * @param {WebInspector.Event} event + */ + _consoleMessageAdded: function(event) + { + var msg = /** @type {WebInspector.ConsoleMessage} */ event.data; + var resource = msg.url ? this.resourceForURL(msg.url) : null; + if (resource) + this._addConsoleMessageToResource(msg, resource); + else + this._addPendingConsoleMessage(msg); + }, + + /** + * @param {WebInspector.ConsoleMessage} msg + */ + _addPendingConsoleMessage: function(msg) + { + if (!msg.url) + return; + if (!this._pendingConsoleMessages[msg.url]) + this._pendingConsoleMessages[msg.url] = []; + this._pendingConsoleMessages[msg.url].push(msg); + }, + + /** + * @param {WebInspector.Resource} resource + */ + _addPendingConsoleMessagesToResource: function(resource) + { + var messages = this._pendingConsoleMessages[resource.url]; + if (messages) { + for (var i = 0; i < messages.length; i++) + this._addConsoleMessageToResource(messages[i], resource); + delete this._pendingConsoleMessages[resource.url]; + } + }, + + /** + * @param {WebInspector.ConsoleMessage} msg + * @param {WebInspector.Resource} resource + */ + _addConsoleMessageToResource: function(msg, resource) + { + switch (msg.level) { + case WebInspector.ConsoleMessage.MessageLevel.Warning: + resource.warnings += msg.repeatDelta; + break; + case WebInspector.ConsoleMessage.MessageLevel.Error: + resource.errors += msg.repeatDelta; + break; + } + resource.addMessage(msg); + }, + + _consoleCleared: function() + { + function callback(resource) + { + resource.clearErrorsAndWarnings(); + } + + this._pendingConsoleMessages = {}; + this.forAllResources(callback); + }, + + /** + * @param {string} url + * @return {WebInspector.Resource} + */ + resourceForURL: function(url) + { + // Workers call into this with no frames available. + return this.mainFrame ? this.mainFrame.resourceForURL(url) : null; + }, + + /** + * @param {WebInspector.ResourceTreeFrame} parentFrame + * @param {PageAgent.FrameResourceTree} frameTreePayload + */ + _addFramesRecursively: function(parentFrame, frameTreePayload) + { + var framePayload = frameTreePayload.frame; + var frame = new WebInspector.ResourceTreeFrame(this, parentFrame, framePayload); + + // Create frame resource. + var frameResource = this._createResourceFromFramePayload(framePayload, framePayload.url); + frameResource.mimeType = framePayload.mimeType; + frameResource.type = WebInspector.Resource.Type.Document; + frameResource.finished = true; + + if (frame.isMainFrame()) + WebInspector.inspectedPageURL = frameResource.url; + + this._addFrame(frame); + frame._addResource(frameResource); + + for (var i = 0; frameTreePayload.childFrames && i < frameTreePayload.childFrames.length; ++i) + this._addFramesRecursively(frame, frameTreePayload.childFrames[i]); + + if (!frameTreePayload.resources) + return; + + // Create frame subresources. + for (var i = 0; i < frameTreePayload.resources.length; ++i) { + var subresource = frameTreePayload.resources[i]; + var resource = this._createResourceFromFramePayload(framePayload, subresource.url); + resource.type = WebInspector.Resource.Type[subresource.type]; + resource.mimeType = subresource.mimeType; + resource.finished = true; + frame._addResource(resource); + } + }, + + /** + * @param {PageAgent.Frame} frame + * @param {string} url + * @return {WebInspector.Resource} + */ + _createResourceFromFramePayload: function(frame, url) + { + return this._createResource(url, frame.url, frame.id, frame.loaderId); + }, + + /** + * @param {string} url + * @param {string} documentURL + * @param {NetworkAgent.FrameId} frameId + * @param {NetworkAgent.LoaderId} loaderId + * @return {WebInspector.Resource} + */ + _createResource: function(url, documentURL, frameId, loaderId) + { + var resource = new WebInspector.Resource("", url, frameId, loaderId); + resource.documentURL = documentURL; + return resource; + } +} + +WebInspector.ResourceTreeModel.prototype.__proto__ = WebInspector.Object.prototype; + +/** + * @constructor + * @param {WebInspector.ResourceTreeModel} model + * @param {?WebInspector.ResourceTreeFrame} parentFrame + * @param {PageAgent.Frame} payload + */ +WebInspector.ResourceTreeFrame = function(model, parentFrame, payload) +{ + this._model = model; + this._parentFrame = parentFrame; + + this._id = payload.id; + this._loaderId = payload.loaderId; + this._name = payload.name; + this._url = payload.url; + this._securityOrigin = payload.securityOrigin; + this._mimeType = payload.mimeType; + + /** + * @type {Array.} + */ + this._childFrames = []; + + /** + * @type {Object.} + */ + this._resourcesMap = {}; + + if (this._parentFrame) + this._parentFrame._childFrames.push(this); +} + +WebInspector.ResourceTreeFrame.prototype = { + /** + * @type {string} + */ + get id() + { + return this._id; + }, + + /** + * @type {string} + */ + get name() + { + return this._name || ""; + }, + + /** + * @type {string} + */ + get url() + { + return this._url; + }, + + /** + * @type {string} + */ + get securityOrigin() + { + return this._securityOrigin; + }, + + /** + * @type {string} + */ + get loaderId() + { + return this._loaderId; + }, + + /** + * @type {WebInspector.ResourceTreeFrame} + */ + get parentFrame() + { + return this._parentFrame; + }, + + /** + * @type {Array.} + */ + get childFrames() + { + return this._childFrames; + }, + + /** + * @return {boolean} + */ + isMainFrame: function() + { + return !this._parentFrame; + }, + + /** + * @param {PageAgent.Frame} framePayload + */ + _navigate: function(framePayload) + { + this._loaderId = framePayload.loaderId; + this._name = framePayload.name; + this._url = framePayload.url; + this._securityOrigin = framePayload.securityOrigin; + this._mimeType = framePayload.mimeType; + + var mainResource = this._resourcesMap[this._url]; + this._resourcesMap = {}; + this._removeChildFrames(); + if (mainResource && mainResource.loaderId === this._loaderId) + this._addResource(mainResource); + }, + + /** + * @type {WebInspector.Resource} + */ + get mainResource() + { + return this._resourcesMap[this._url]; + }, + + /** + * @param {WebInspector.ResourceTreeFrame} frame + */ + _removeChildFrame: function(frame) + { + this._childFrames.remove(frame); + frame._remove(); + }, + + _removeChildFrames: function() + { + var copy = this._childFrames.slice(); + for (var i = 0; i < copy.length; ++i) + this._removeChildFrame(copy[i]); + }, + + _remove: function() + { + this._removeChildFrames(); + delete this._model._frames[this.id]; + this._model.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.FrameDetached, this); + }, + + /** + * @param {WebInspector.Resource} resource + */ + _addResource: function(resource) + { + if (this._resourcesMap[resource.url] === resource) { + // Already in the tree, we just got an extra update. + return; + } + this._resourcesMap[resource.url] = resource; + this._model.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.ResourceAdded, resource); + }, + + /** + * @return {Array.} + */ + resources: function() + { + var result = []; + for (var url in this._resourcesMap) + result.push(this._resourcesMap[url]); + return result; + }, + + /** + * @param {string} url + * @return {?WebInspector.Resource} + */ + resourceForURL: function(url) + { + var result; + function filter(resource) + { + if (resource.url === url) { + result = resource; + return true; + } + } + this._callForFrameResources(filter); + return result; + }, + + /** + * @param {function(WebInspector.Resource)} callback + * @return {boolean} + */ + _callForFrameResources: function(callback) + { + for (var url in this._resourcesMap) { + if (callback(this._resourcesMap[url])) + return true; + } + + for (var i = 0; i < this._childFrames.length; ++i) { + if (this._childFrames[i]._callForFrameResources(callback)) + return true; + } + return false; + } +} + +/** + * @constructor + * @implements {PageAgent.Dispatcher} + */ +WebInspector.PageDispatcher = function(resourceTreeModel) +{ + this._resourceTreeModel = resourceTreeModel; +} + +WebInspector.PageDispatcher.prototype = { + domContentEventFired: function(time) + { + this._resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.DOMContentLoaded, time); + }, + + loadEventFired: function(time) + { + this._resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.OnLoad, time); + }, + + frameNavigated: function(frame) + { + this._resourceTreeModel._frameNavigated(frame); + }, + + frameDetached: function(frameId) + { + this._resourceTreeModel._frameDetached(frameId); + } +} + +/** + * @type {WebInspector.ResourceTreeModel} + */ +WebInspector.resourceTreeModel = null; +/* ResourceUtils.js */ + +/* + * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2007 Matt Lilek (pewtermoose@gmail.com). + * Copyright (C) 2009 Joseph Pecoraro + * + * 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. + */ + +/** + * @param {string} url + * @return {?WebInspector.Resource} + */ +WebInspector.resourceForURL = function(url) +{ + return WebInspector.resourceTreeModel.resourceForURL(url); +} + +/** + * @param {function(WebInspector.Resource)} callback + */ +WebInspector.forAllResources = function(callback) +{ + WebInspector.resourceTreeModel.forAllResources(callback); +} + +/** + * @param {string} url + * @return {string} + */ +WebInspector.displayNameForURL = function(url) +{ + if (!url) + return ""; + + var resource = WebInspector.resourceForURL(url); + if (resource) + return resource.displayName; + + if (!WebInspector.inspectedPageURL) + return url.trimURL(""); + + var parsedURL = WebInspector.inspectedPageURL.asParsedURL(); + var lastPathComponent = parsedURL.lastPathComponent; + var index = WebInspector.inspectedPageURL.indexOf(lastPathComponent); + if (index !== -1 && index + lastPathComponent.length === WebInspector.inspectedPageURL.length) { + var baseURL = WebInspector.inspectedPageURL.substring(0, index); + if (url.indexOf(baseURL) === 0) + return url.substring(index); + } + + return url.trimURL(parsedURL.host); +} + +/** + * @param {string} string + * @param {function(string,string,string=):Node} linkifier + * @return {DocumentFragment} + */ +WebInspector.linkifyStringAsFragmentWithCustomLinkifier = function(string, linkifier) +{ + var container = document.createDocumentFragment(); + var linkStringRegEx = /(?:[a-zA-Z][a-zA-Z0-9+.-]{2,}:\/\/|www\.)[\w$\-_+*'=\|\/\\(){}[\]%@&#~,:;.!?]{2,}[\w$\-_+*=\|\/\\({%@&#~]/; + var lineColumnRegEx = /:(\d+)(:(\d+))?$/; + + while (string) { + var linkString = linkStringRegEx.exec(string); + if (!linkString) + break; + + linkString = linkString[0]; + var linkIndex = string.indexOf(linkString); + var nonLink = string.substring(0, linkIndex); + container.appendChild(document.createTextNode(nonLink)); + + var title = linkString; + var realURL = (linkString.indexOf("www.") === 0 ? "http://" + linkString : linkString); + var lineColumnMatch = lineColumnRegEx.exec(realURL); + if (lineColumnMatch) + realURL = realURL.substring(0, realURL.length - lineColumnMatch[0].length); + + var linkNode = linkifier(title, realURL, lineColumnMatch ? lineColumnMatch[1] : undefined); + container.appendChild(linkNode); + string = string.substring(linkIndex + linkString.length, string.length); + } + + if (string) + container.appendChild(document.createTextNode(string)); + + return container; +} + +WebInspector._linkifierPlugins = []; + +/** + * @param {function(string):string} plugin + */ +WebInspector.registerLinkifierPlugin = function(plugin) +{ + WebInspector._linkifierPlugins.push(plugin); +} + +/** + * @param {string} string + * @return {DocumentFragment} + */ +WebInspector.linkifyStringAsFragment = function(string) +{ + function linkifier(title, url, lineNumber) + { + for (var i = 0; i < WebInspector._linkifierPlugins.length; ++i) + title = WebInspector._linkifierPlugins[i](title); + + var isExternal = !WebInspector.resourceForURL(url); + var urlNode = WebInspector.linkifyURLAsNode(url, title, undefined, isExternal); + if (typeof(lineNumber) !== "undefined") { + urlNode.lineNumber = lineNumber; + urlNode.preferredPanel = "scripts"; + } + + return urlNode; + } + + return WebInspector.linkifyStringAsFragmentWithCustomLinkifier(string, linkifier); +} + +/** + * @param {string} url + * @param {string=} linkText + * @param {string=} classes + * @param {boolean=} isExternal + * @param {string=} tooltipText + * @return {Element} + */ +WebInspector.linkifyURLAsNode = function(url, linkText, classes, isExternal, tooltipText) +{ + if (!linkText) + linkText = url; + classes = (classes ? classes + " " : ""); + classes += isExternal ? "webkit-html-external-link" : "webkit-html-resource-link"; + + var a = document.createElement("a"); + a.href = url; + a.className = classes; + if (typeof tooltipText === "undefined") + a.title = url; + else if (typeof tooltipText !== "string" || tooltipText.length) + a.title = tooltipText; + a.textContent = linkText; + a.style.maxWidth = "100%"; + if (isExternal) + a.setAttribute("target", "_blank"); + + return a; +} + +/** + * @param {string} url + * @param {number=} lineNumber + * @return {string} + */ +WebInspector.formatLinkText = function(url, lineNumber) +{ + var text = WebInspector.displayNameForURL(url); + if (typeof lineNumber === "number") + text += ":" + (lineNumber + 1); + return text; +} + +/** + * @param {string} url + * @param {number} lineNumber + * @param {string=} classes + * @param {string=} tooltipText + * @return {Element} + */ +WebInspector.linkifyResourceAsNode = function(url, lineNumber, classes, tooltipText) +{ + var linkText = WebInspector.formatLinkText(url, lineNumber); + var anchor = WebInspector.linkifyURLAsNode(url, linkText, classes, false, tooltipText); + anchor.preferredPanel = "resources"; + anchor.lineNumber = lineNumber; + return anchor; +} + +/** + * @param {WebInspector.Resource} request + * @param {string=} classes + * @return {Element} + */ +WebInspector.linkifyRequestAsNode = function(request, classes) +{ + var anchor = WebInspector.linkifyURLAsNode(request.url); + anchor.preferredPanel = "network"; + anchor.requestId = request.requestId; + return anchor; +} + +/** + * @return {?string} null if the specified resource MUST NOT have a URL (e.g. "javascript:...") + */ +WebInspector.resourceURLForRelatedNode = function(node, url) +{ + if (!url || url.indexOf("://") > 0) + return url; + + if (url.trim().indexOf("javascript:") === 0) + return null; // Do not provide a resource URL for security. + + for (var frameOwnerCandidate = node; frameOwnerCandidate; frameOwnerCandidate = frameOwnerCandidate.parentNode) { + if (frameOwnerCandidate.documentURL) { + var result = WebInspector.completeURL(frameOwnerCandidate.documentURL, url); + if (result) + return result; + break; + } + } + + // documentURL not found or has bad value + var resourceURL = url; + function callback(resource) + { + if (resource.path === url) { + resourceURL = resource.url; + return true; + } + } + WebInspector.forAllResources(callback); + return resourceURL; +} + +/** + * @param {string} baseURL + * @param {string} href + * @return {?string} + */ +WebInspector.completeURL = function(baseURL, href) +{ + if (href) { + // Return absolute URLs as-is. + var parsedHref = href.asParsedURL(); + if (parsedHref && parsedHref.scheme) + return href; + + // Return special URLs as-is. + var trimmedHref = href.trim(); + if (trimmedHref.indexOf("data:") === 0 || trimmedHref.indexOf("javascript:") === 0) + return href; + } + + var parsedURL = baseURL.asParsedURL(); + if (parsedURL) { + var path = href; + if (path.charAt(0) !== "/") { + var basePath = parsedURL.path; + // A href of "?foo=bar" implies "basePath?foo=bar". + // With "basePath?a=b" and "?foo=bar" we should get "basePath?foo=bar". + var prefix; + if (path.charAt(0) === "?") { + var basePathCutIndex = basePath.indexOf("?"); + if (basePathCutIndex !== -1) + prefix = basePath.substring(0, basePathCutIndex); + else + prefix = basePath; + } else + prefix = basePath.substring(0, basePath.lastIndexOf("/")) + "/"; + + path = prefix + path; + } else if (path.length > 1 && path.charAt(1) === "/") { + // href starts with "//" which is a full URL with the protocol dropped (use the baseURL protocol). + return parsedURL.scheme + ":" + path; + } + return parsedURL.scheme + "://" + parsedURL.host + (parsedURL.port ? (":" + parsedURL.port) : "") + path; + } + return null; +} +/* ResourceCategory.js */ + +/* + * 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. + * 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. + */ + +/** + * @constructor + */ +WebInspector.ResourceCategory = function(name, title, color) +{ + this.name = name; + this._title = title; + this.color = color; +} + +WebInspector.ResourceCategory.prototype = { + /** + * @return {string} + */ + toString: function() + { + return this.title; + }, + + /** + * @return {string} + */ + get title() + { + return WebInspector.UIString(this._title); + } +} + +WebInspector.resourceCategories = { + documents: new WebInspector.ResourceCategory("documents", "Documents", "rgb(47,102,236)"), + stylesheets: new WebInspector.ResourceCategory("stylesheets", "Stylesheets", "rgb(157,231,119)"), + images: new WebInspector.ResourceCategory("images", "Images", "rgb(164,60,255)"), + scripts: new WebInspector.ResourceCategory("scripts", "Scripts", "rgb(255,121,0)"), + xhr: new WebInspector.ResourceCategory("xhr", "XHR", "rgb(231,231,10)"), + fonts: new WebInspector.ResourceCategory("fonts", "Fonts", "rgb(255,82,62)"), + websockets: new WebInspector.ResourceCategory("websockets", "WebSockets", "rgb(186,186,186)"), // FIXME: Decide the color. + other: new WebInspector.ResourceCategory("other", "Other", "rgb(186,186,186)") +} +/* TimelineManager.js */ + +/* + * Copyright (C) 2011 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. + */ + +/** + * @constructor + * @extends {WebInspector.Object} + */ +WebInspector.TimelineManager = function() +{ + WebInspector.Object.call(this); + this._dispatcher = new WebInspector.TimelineDispatcher(this); + this._enablementCount = 0; +} + +WebInspector.TimelineManager.EventTypes = { + TimelineStarted: "TimelineStarted", + TimelineStopped: "TimelineStopped", + TimelineEventRecorded: "TimelineEventRecorded" +} + +WebInspector.TimelineManager.prototype = { + /** + * @param {number=} maxCallStackDepth + */ + start: function(maxCallStackDepth) + { + this._enablementCount++; + if (this._enablementCount === 1) + TimelineAgent.start(maxCallStackDepth, this._started.bind(this)); + }, + + stop: function() + { + if (!this._enablementCount) { + console.error("WebInspector.TimelineManager start/stop calls are unbalanced"); + return; + } + this._enablementCount--; + if (!this._enablementCount) + TimelineAgent.stop(this._stopped.bind(this)); + }, + + _started: function() + { + this.dispatchEventToListeners(WebInspector.TimelineManager.EventTypes.TimelineStarted); + }, + + _stopped: function() + { + this.dispatchEventToListeners(WebInspector.TimelineManager.EventTypes.TimelineStopped); + } +} + +WebInspector.TimelineManager.prototype.__proto__ = WebInspector.Object.prototype; + +/** + * @constructor + * @implements {TimelineAgent.Dispatcher} + */ +WebInspector.TimelineDispatcher = function(manager) +{ + this._manager = manager; + InspectorBackend.registerTimelineDispatcher(this); +} + +WebInspector.TimelineDispatcher.prototype = { + eventRecorded: function(record) + { + this._manager.dispatchEventToListeners(WebInspector.TimelineManager.EventTypes.TimelineEventRecorded, record); + } +} + +/** + * @type {WebInspector.TimelineManager} + */ +WebInspector.timelineManager; +/* Database.js */ + +/* + * 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. + * 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. + */ + +/** + * @constructor + */ +WebInspector.Database = function(id, domain, name, version) +{ + this._id = id; + this._domain = domain; + this._name = name; + this._version = version; +} + +WebInspector.Database.prototype = { + /** @return {string} */ + get id() + { + return this._id; + }, + + /** @return {string} */ + get name() + { + return this._name; + }, + + set name(x) + { + this._name = x; + }, + + /** @return {string} */ + get version() + { + return this._version; + }, + + set version(x) + { + this._version = x; + }, + + /** @return {string} */ + get domain() + { + return this._domain; + }, + + set domain(x) + { + this._domain = x; + }, + + /** @return {string} */ + get displayDomain() + { + return WebInspector.Resource.prototype.__lookupGetter__("displayDomain").call(this); + }, + + /** + * @param {function(Array.)} callback + */ + getTableNames: function(callback) + { + function sortingCallback(error, names) + { + if (!error) + callback(names.sort()); + } + DatabaseAgent.getDatabaseTableNames(this._id, sortingCallback); + }, + + /** + * @param {string} query + * @param {function(Array., Array.<*>)} onSuccess + * @param {function(DatabaseAgent.Error)} onError + */ + executeSql: function(query, onSuccess, onError) + { + function callback(error, success, transactionId) + { + if (error) { + onError(error); + return; + } + if (!success) { + onError(WebInspector.UIString("Database not found.")); + return; + } + WebInspector.DatabaseDispatcher._callbacks[transactionId] = {"onSuccess": onSuccess, "onError": onError}; + } + DatabaseAgent.executeSQL(this._id, query, callback); + } +} + +/** + * @constructor + * @implements {DatabaseAgent.Dispatcher} + */ +WebInspector.DatabaseDispatcher = function() +{ +} + +WebInspector.DatabaseDispatcher._callbacks = {}; + +WebInspector.DatabaseDispatcher.prototype = { + /** + * @param {DatabaseAgent.Database} payload + */ + addDatabase: function(payload) + { + var database = new WebInspector.Database( + payload.id, + payload.domain, + payload.name, + payload.version); + WebInspector.panels.resources.addDatabase(database); + }, + + /** + * @param {number} transactionId + * @param {Array.} columnNames + * @param {Array.<*>} values + */ + sqlTransactionSucceeded: function(transactionId, columnNames, values) + { + if (!WebInspector.DatabaseDispatcher._callbacks[transactionId]) + return; + + var callback = WebInspector.DatabaseDispatcher._callbacks[transactionId]["onSuccess"]; + delete WebInspector.DatabaseDispatcher._callbacks[transactionId]; + if (callback) + callback(columnNames, values); + }, + + /** + * @param {number} transactionId + * @param {?DatabaseAgent.Error} errorObj + */ + sqlTransactionFailed: function(transactionId, errorObj) + { + if (!WebInspector.DatabaseDispatcher._callbacks[transactionId]) + return; + + var callback = WebInspector.DatabaseDispatcher._callbacks[transactionId]["onError"]; + delete WebInspector.DatabaseDispatcher._callbacks[transactionId]; + if (callback) + callback(errorObj); + } +} +/* DOMStorage.js */ + +/* + * Copyright (C) 2008 Nokia 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 "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. + */ + +/** + * @constructor + */ +WebInspector.DOMStorage = function(id, domain, isLocalStorage) +{ + this._id = id; + this._domain = domain; + this._isLocalStorage = isLocalStorage; +} + +WebInspector.DOMStorage.prototype = { + /** @return {string} */ + get id() + { + return this._id; + }, + + /** @return {string} */ + get domain() + { + return this._domain; + }, + + /** @return {boolean} */ + get isLocalStorage() + { + return this._isLocalStorage; + }, + + /** + * @param {function(?Protocol.Error, Array.):void=} callback + */ + getEntries: function(callback) + { + DOMStorageAgent.getDOMStorageEntries(this._id, callback); + }, + + /** + * @param {string} key + * @param {string} value + * @param {function(?Protocol.Error, boolean):void=} callback + */ + setItem: function(key, value, callback) + { + DOMStorageAgent.setDOMStorageItem(this._id, key, value, callback); + }, + + /** + * @param {string} key + * @param {function(?Protocol.Error, boolean):void=} callback + */ + removeItem: function(key, callback) + { + DOMStorageAgent.removeDOMStorageItem(this._id, key, callback); + } +} + +/** + * @constructor + * @implements {DOMStorageAgent.Dispatcher} + */ +WebInspector.DOMStorageDispatcher = function() +{ +} + +WebInspector.DOMStorageDispatcher.prototype = { + + /** + * @param {DOMStorageAgent.Entry} payload + */ + addDOMStorage: function(payload) + { + var domStorage = new WebInspector.DOMStorage( + payload.id, + payload.host, + payload.isLocalStorage); + WebInspector.panels.resources.addDOMStorage(domStorage); + }, + + /** + * @param {number} storageId + */ + updateDOMStorage: function(storageId) + { + WebInspector.panels.resources.updateDOMStorage(storageId); + } +} +/* DOMStorageItemsView.js */ + +/* + * Copyright (C) 2008 Nokia 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 ``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 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. + */ + +/** + * @constructor + * @extends {WebInspector.View} + */ +WebInspector.DOMStorageItemsView = function(domStorage) +{ + WebInspector.View.call(this); + + this.domStorage = domStorage; + + this.element.addStyleClass("storage-view"); + this.element.addStyleClass("table"); + + this.deleteButton = new WebInspector.StatusBarButton(WebInspector.UIString("Delete"), "delete-storage-status-bar-item"); + this.deleteButton.visible = false; + this.deleteButton.addEventListener("click", this._deleteButtonClicked, this); + + this.refreshButton = new WebInspector.StatusBarButton(WebInspector.UIString("Refresh"), "refresh-storage-status-bar-item"); + this.refreshButton.addEventListener("click", this._refreshButtonClicked, this); +} + +WebInspector.DOMStorageItemsView.prototype = { + get statusBarItems() + { + return [this.refreshButton.element, this.deleteButton.element]; + }, + + wasShown: function() + { + this.update(); + }, + + willHide: function() + { + this.deleteButton.visible = false; + }, + + update: function() + { + this.detachChildViews(); + this.domStorage.getEntries(this._showDOMStorageEntries.bind(this)); + }, + + _showDOMStorageEntries: function(error, entries) + { + if (error) + return; + + this._dataGrid = this._dataGridForDOMStorageEntries(entries); + this._dataGrid.show(this.element); + this._dataGrid.autoSizeColumns(10); + this.deleteButton.visible = true; + }, + + _dataGridForDOMStorageEntries: function(entries) + { + var columns = {}; + columns[0] = {}; + columns[1] = {}; + columns[0].title = WebInspector.UIString("Key"); + columns[1].title = WebInspector.UIString("Value"); + + var nodes = []; + + var keys = []; + var length = entries.length; + for (var i = 0; i < entries.length; i++) { + var data = {}; + + var key = entries[i][0]; + data[0] = key; + var value = entries[i][1]; + data[1] = value; + var node = new WebInspector.DataGridNode(data, false); + node.selectable = true; + nodes.push(node); + keys.push(key); + } + + var dataGrid = new WebInspector.DataGrid(columns, this._editingCallback.bind(this), this._deleteCallback.bind(this)); + length = nodes.length; + for (var i = 0; i < length; ++i) + dataGrid.appendChild(nodes[i]); + dataGrid.addCreationNode(false); + if (length > 0) + nodes[0].selected = true; + return dataGrid; + }, + + _deleteButtonClicked: function(event) + { + if (!this._dataGrid || !this._dataGrid.selectedNode) + return; + + this._deleteCallback(this._dataGrid.selectedNode); + }, + + _refreshButtonClicked: function(event) + { + this.update(); + }, + + _editingCallback: function(editingNode, columnIdentifier, oldText, newText) + { + var domStorage = this.domStorage; + if (columnIdentifier === 0) { + if (oldText) + domStorage.removeItem(oldText); + + domStorage.setItem(newText, editingNode.data[1]); + } else { + domStorage.setItem(editingNode.data[0], newText); + } + + this.update(); + }, + + _deleteCallback: function(node) + { + if (!node || node.isCreationNode) + return; + + if (this.domStorage) + this.domStorage.removeItem(node.data[0]); + + this.update(); + } +} + +WebInspector.DOMStorageItemsView.prototype.__proto__ = WebInspector.View.prototype; +/* DataGrid.js */ + +/* + * Copyright (C) 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 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 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. + */ + +/** + * @constructor + * @extends {WebInspector.View} + * @param {function(WebInspector.DataGridNode, number, string, string)=} editCallback + * @param {function(WebInspector.DataGridNode)=} deleteCallback + */ +WebInspector.DataGrid = function(columns, editCallback, deleteCallback) +{ + WebInspector.View.call(this); + this.registerRequiredCSS("dataGrid.css"); + + this.element.className = "data-grid"; + this.element.tabIndex = 0; + this.element.addEventListener("keydown", this._keyDown.bind(this), false); + + this._headerTable = document.createElement("table"); + this._headerTable.className = "header"; + this._headerTableHeaders = {}; + + this._dataTable = document.createElement("table"); + this._dataTable.className = "data"; + + this._dataTable.addEventListener("mousedown", this._mouseDownInDataTable.bind(this), true); + this._dataTable.addEventListener("click", this._clickInDataTable.bind(this), true); + + this._dataTable.addEventListener("contextmenu", this._contextMenuInDataTable.bind(this), true); + + // FIXME: Add a createCallback which is different from editCallback and has different + // behavior when creating a new node. + if (editCallback) { + this._dataTable.addEventListener("dblclick", this._ondblclick.bind(this), false); + this._editCallback = editCallback; + } + if (deleteCallback) + this._deleteCallback = deleteCallback; + + this.aligned = {}; + + this._scrollContainer = document.createElement("div"); + this._scrollContainer.className = "data-container"; + this._scrollContainer.appendChild(this._dataTable); + + this.element.appendChild(this._headerTable); + this.element.appendChild(this._scrollContainer); + + var headerRow = document.createElement("tr"); + var columnGroup = document.createElement("colgroup"); + this._columnCount = 0; + + for (var columnIdentifier in columns) { + var column = columns[columnIdentifier]; + if (column.disclosure) + this.disclosureColumnIdentifier = columnIdentifier; + + var col = document.createElement("col"); + if (column.width) + col.style.width = column.width; + column.element = col; + columnGroup.appendChild(col); + + var cell = document.createElement("th"); + cell.className = columnIdentifier + "-column"; + cell.columnIdentifier = columnIdentifier; + this._headerTableHeaders[columnIdentifier] = cell; + + var div = document.createElement("div"); + if (column.titleDOMFragment) + div.appendChild(column.titleDOMFragment); + else + div.textContent = column.title; + cell.appendChild(div); + + if (column.sort) { + cell.addStyleClass("sort-" + column.sort); + this._sortColumnCell = cell; + } + + if (column.sortable) { + cell.addEventListener("click", this._clickInHeaderCell.bind(this), false); + cell.addStyleClass("sortable"); + } + + if (column.aligned) + this.aligned[columnIdentifier] = column.aligned; + + headerRow.appendChild(cell); + + ++this._columnCount; + } + + columnGroup.span = this._columnCount; + + var cell = document.createElement("th"); + cell.className = "corner"; + headerRow.appendChild(cell); + + this._headerTableColumnGroup = columnGroup; + this._headerTable.appendChild(this._headerTableColumnGroup); + this.headerTableBody.appendChild(headerRow); + + var fillerRow = document.createElement("tr"); + fillerRow.className = "filler"; + + for (var columnIdentifier in columns) { + var column = columns[columnIdentifier]; + var td = document.createElement("td"); + td.className = columnIdentifier + "-column"; + fillerRow.appendChild(td); + } + + this._dataTableColumnGroup = columnGroup.cloneNode(true); + this._dataTable.appendChild(this._dataTableColumnGroup); + this.dataTableBody.appendChild(fillerRow); + + this.columns = columns || {}; + this._columnsArray = []; + for (var columnIdentifier in columns) { + columns[columnIdentifier].ordinal = this._columnsArray.length; + columns[columnIdentifier].identifier = columnIdentifier; + this._columnsArray.push(columns[columnIdentifier]); + } + + for (var i = 0; i < this._columnsArray.length; ++i) + this._columnsArray[i].bodyElement = this._dataTableColumnGroup.children[i]; + + this.children = []; + this.selectedNode = null; + this.expandNodesWhenArrowing = false; + this.root = true; + this.hasChildren = false; + this.expanded = true; + this.revealed = true; + this.selected = false; + this.dataGrid = this; + this.indentWidth = 15; + this.resizers = []; + this._columnWidthsInitialized = false; +} + +/** + * @param {Array.} columnNames + * @param {Array.} values + */ +WebInspector.DataGrid.createSortableDataGrid = function(columnNames, values) +{ + var numColumns = columnNames.length; + if (!numColumns) + return null; + + var columns = {}; + + for (var i = 0; i < columnNames.length; ++i) { + var column = {}; + column.width = columnNames[i].length; + column.title = columnNames[i]; + column.sortable = true; + + columns[columnNames[i]] = column; + } + + var nodes = []; + for (var i = 0; i < values.length / numColumns; ++i) { + var data = {}; + for (var j = 0; j < columnNames.length; ++j) + data[columnNames[j]] = values[numColumns * i + j]; + + var node = new WebInspector.DataGridNode(data, false); + node.selectable = false; + nodes.push(node); + } + + var dataGrid = new WebInspector.DataGrid(columns); + var length = nodes.length; + for (var i = 0; i < length; ++i) + dataGrid.appendChild(nodes[i]); + + dataGrid.addEventListener("sorting changed", sortDataGrid, this); + + function sortDataGrid() + { + var nodes = dataGrid.children.slice(); + var sortColumnIdentifier = dataGrid.sortColumnIdentifier; + var sortDirection = dataGrid.sortOrder === "ascending" ? 1 : -1; + var columnIsNumeric = true; + + for (var i = 0; i < nodes.length; i++) { + if (isNaN(Number(nodes[i].data[sortColumnIdentifier]))) + columnIsNumeric = false; + } + + function comparator(dataGridNode1, dataGridNode2) + { + var item1 = dataGridNode1.data[sortColumnIdentifier]; + var item2 = dataGridNode2.data[sortColumnIdentifier]; + + var comparison; + if (columnIsNumeric) { + // Sort numbers based on comparing their values rather than a lexicographical comparison. + var number1 = parseFloat(item1); + var number2 = parseFloat(item2); + comparison = number1 < number2 ? -1 : (number1 > number2 ? 1 : 0); + } else + comparison = item1 < item2 ? -1 : (item1 > item2 ? 1 : 0); + + return sortDirection * comparison; + } + + nodes.sort(comparator); + dataGrid.removeChildren(); + for (var i = 0; i < nodes.length; i++) + dataGrid.appendChild(nodes[i]); + } + return dataGrid; +} + +WebInspector.DataGrid.prototype = { + get refreshCallback() + { + return this._refreshCallback; + }, + + set refreshCallback(refreshCallback) + { + this._refreshCallback = refreshCallback; + }, + + _ondblclick: function(event) + { + if (this._editing || this._editingNode) + return; + + this._startEditing(event.target); + }, + + _startEditingColumnOfDataGridNode: function(node, column) + { + this._editing = true; + this._editingNode = node; + this._editingNode.select(); + + var element = this._editingNode._element.children[column]; + WebInspector.startEditing(element, this._startEditingConfig(element)); + window.getSelection().setBaseAndExtent(element, 0, element, 1); + }, + + _startEditing: function(target) + { + var element = target.enclosingNodeOrSelfWithNodeName("td"); + if (!element) + return; + + this._editingNode = this.dataGridNodeFromNode(target); + if (!this._editingNode) { + if (!this.creationNode) + return; + this._editingNode = this.creationNode; + } + + // Force editing the 1st column when editing the creation node + if (this._editingNode.isCreationNode) + return this._startEditingColumnOfDataGridNode(this._editingNode, 0); + + this._editing = true; + WebInspector.startEditing(element, this._startEditingConfig(element)); + + window.getSelection().setBaseAndExtent(element, 0, element, 1); + }, + + + _startEditingConfig: function(element) + { + return new WebInspector.EditingConfig(this._editingCommitted.bind(this), this._editingCancelled.bind(this), element.textContent); + }, + + _editingCommitted: function(element, newText, oldText, context, moveDirection) + { + // FIXME: We need more column identifiers here throughout this function. + // Not needed yet since only editable DataGrid is DOM Storage, which is Key - Value. + + // FIXME: Better way to do this than regular expressions? + var columnIdentifier = parseInt(element.className.match(/\b(\d+)-column\b/)[1], 10); + + var textBeforeEditing = this._editingNode.data[columnIdentifier]; + var currentEditingNode = this._editingNode; + + function moveToNextIfNeeded(wasChange) { + if (!moveDirection) + return; + + if (moveDirection === "forward") { + if (currentEditingNode.isCreationNode && columnIdentifier === 0 && !wasChange) + return; + + if (columnIdentifier === 0) + return this._startEditingColumnOfDataGridNode(currentEditingNode, 1); + + var nextDataGridNode = currentEditingNode.traverseNextNode(true, null, true); + if (nextDataGridNode) + return this._startEditingColumnOfDataGridNode(nextDataGridNode, 0); + if (currentEditingNode.isCreationNode && wasChange) { + this.addCreationNode(false); + return this._startEditingColumnOfDataGridNode(this.creationNode, 0); + } + return; + } + + if (moveDirection === "backward") { + if (columnIdentifier === 1) + return this._startEditingColumnOfDataGridNode(currentEditingNode, 0); + var nextDataGridNode = currentEditingNode.traversePreviousNode(true, null, true); + + if (nextDataGridNode) + return this._startEditingColumnOfDataGridNode(nextDataGridNode, 1); + return; + } + } + + if (textBeforeEditing == newText) { + this._editingCancelled(element); + moveToNextIfNeeded.call(this, false); + return; + } + + // Update the text in the datagrid that we typed + this._editingNode.data[columnIdentifier] = newText; + + // Make the callback - expects an editing node (table row), the column number that is being edited, + // the text that used to be there, and the new text. + this._editCallback(this._editingNode, columnIdentifier, textBeforeEditing, newText); + + if (this._editingNode.isCreationNode) + this.addCreationNode(false); + + this._editingCancelled(element); + moveToNextIfNeeded.call(this, true); + }, + + _editingCancelled: function(element) + { + delete this._editing; + this._editingNode = null; + }, + + get sortColumnIdentifier() + { + if (!this._sortColumnCell) + return null; + return this._sortColumnCell.columnIdentifier; + }, + + get sortOrder() + { + if (!this._sortColumnCell || this._sortColumnCell.hasStyleClass("sort-ascending")) + return "ascending"; + if (this._sortColumnCell.hasStyleClass("sort-descending")) + return "descending"; + return null; + }, + + get headerTableBody() + { + if ("_headerTableBody" in this) + return this._headerTableBody; + + this._headerTableBody = this._headerTable.getElementsByTagName("tbody")[0]; + if (!this._headerTableBody) { + this._headerTableBody = this.element.ownerDocument.createElement("tbody"); + this._headerTable.insertBefore(this._headerTableBody, this._headerTable.tFoot); + } + + return this._headerTableBody; + }, + + get dataTableBody() + { + if ("_dataTableBody" in this) + return this._dataTableBody; + + this._dataTableBody = this._dataTable.getElementsByTagName("tbody")[0]; + if (!this._dataTableBody) { + this._dataTableBody = this.element.ownerDocument.createElement("tbody"); + this._dataTable.insertBefore(this._dataTableBody, this._dataTable.tFoot); + } + + return this._dataTableBody; + }, + + /** + * @param {number=} maxDescentLevel + */ + autoSizeColumns: function(minPercent, maxPercent, maxDescentLevel) + { + if (minPercent) + minPercent = Math.min(minPercent, Math.floor(100 / this._columnCount)); + var widths = {}; + var columns = this.columns; + for (var columnIdentifier in columns) + widths[columnIdentifier] = (columns[columnIdentifier].title || "").length; + + var children = maxDescentLevel ? this._enumerateChildren(this, [], maxDescentLevel + 1) : this.children; + for (var i = 0; i < children.length; ++i) { + var node = children[i]; + for (var columnIdentifier in columns) { + var text = node.data[columnIdentifier] || ""; + if (text.length > widths[columnIdentifier]) + widths[columnIdentifier] = text.length; + } + } + + var totalColumnWidths = 0; + for (var columnIdentifier in columns) + totalColumnWidths += widths[columnIdentifier]; + + var recoupPercent = 0; + for (var columnIdentifier in columns) { + var width = Math.round(100 * widths[columnIdentifier] / totalColumnWidths); + if (minPercent && width < minPercent) { + recoupPercent += (minPercent - width); + width = minPercent; + } else if (maxPercent && width > maxPercent) { + recoupPercent -= (width - maxPercent); + width = maxPercent; + } + widths[columnIdentifier] = width; + } + + while (minPercent && recoupPercent > 0) { + for (var columnIdentifier in columns) { + if (widths[columnIdentifier] > minPercent) { + --widths[columnIdentifier]; + --recoupPercent; + if (!recoupPercent) + break; + } + } + } + + while (maxPercent && recoupPercent < 0) { + for (var columnIdentifier in columns) { + if (widths[columnIdentifier] < maxPercent) { + ++widths[columnIdentifier]; + ++recoupPercent; + if (!recoupPercent) + break; + } + } + } + + for (var columnIdentifier in columns) + columns[columnIdentifier].element.style.width = widths[columnIdentifier] + "%"; + this._columnWidthsInitialized = false; + this.updateWidths(); + }, + + _enumerateChildren: function(rootNode, result, maxLevel) + { + if (!rootNode.root) + result.push(rootNode); + if (!maxLevel) + return; + for (var i = 0; i < rootNode.children.length; ++i) + this._enumerateChildren(rootNode.children[i], result, maxLevel - 1); + return result; + }, + + onResize: function() + { + this.updateWidths(); + }, + + // Updates the widths of the table, including the positions of the column + // resizers. + // + // IMPORTANT: This function MUST be called once after the element of the + // DataGrid is attached to its parent element and every subsequent time the + // width of the parent element is changed in order to make it possible to + // resize the columns. + // + // If this function is not called after the DataGrid is attached to its + // parent element, then the DataGrid's columns will not be resizable. + updateWidths: function() + { + var headerTableColumns = this._headerTableColumnGroup.children; + + var tableWidth = this._dataTable.offsetWidth; + var numColumns = headerTableColumns.length; + + // Do not attempt to use offsetes if we're not attached to the document tree yet. + if (!this._columnWidthsInitialized && this.element.offsetWidth) { + // Give all the columns initial widths now so that during a resize, + // when the two columns that get resized get a percent value for + // their widths, all the other columns already have percent values + // for their widths. + for (var i = 0; i < numColumns; i++) { + var columnWidth = this.headerTableBody.rows[0].cells[i].offsetWidth; + var percentWidth = ((columnWidth / tableWidth) * 100) + "%"; + this._headerTableColumnGroup.children[i].style.width = percentWidth; + this._dataTableColumnGroup.children[i].style.width = percentWidth; + } + this._columnWidthsInitialized = true; + } + this._positionResizers(); + this.dispatchEventToListeners("width changed"); + }, + + columnWidthsMap: function() + { + var result = {}; + for (var i = 0; i < this._columnsArray.length; ++i) { + var width = this._headerTableColumnGroup.children[i].style.width; + result[this._columnsArray[i].columnIdentifier] = parseFloat(width); + } + return result; + }, + + applyColumnWidthsMap: function(columnWidthsMap) + { + for (var columnIdentifier in this.columns) { + var column = this.columns[columnIdentifier]; + var width = (columnWidthsMap[columnIdentifier] || 0) + "%"; + this._headerTableColumnGroup.children[column.ordinal].style.width = width; + this._dataTableColumnGroup.children[column.ordinal].style.width = width; + } + + // Normalize widths + delete this._columnWidthsInitialized; + this.updateWidths(); + }, + + isColumnVisible: function(columnIdentifier) + { + var column = this.columns[columnIdentifier]; + var columnElement = column.element; + return !columnElement.hidden; + }, + + showColumn: function(columnIdentifier) + { + var column = this.columns[columnIdentifier]; + var columnElement = column.element; + if (!columnElement.hidden) + return; + + columnElement.hidden = false; + columnElement.removeStyleClass("hidden"); + + var columnBodyElement = column.bodyElement; + columnBodyElement.hidden = false; + columnBodyElement.removeStyleClass("hidden"); + }, + + hideColumn: function(columnIdentifier) + { + var column = this.columns[columnIdentifier]; + var columnElement = column.element; + if (columnElement.hidden) + return; + + var oldWidth = parseFloat(columnElement.style.width); + + columnElement.hidden = true; + columnElement.addStyleClass("hidden"); + columnElement.style.width = 0; + + var columnBodyElement = column.bodyElement; + columnBodyElement.hidden = true; + columnBodyElement.addStyleClass("hidden"); + columnBodyElement.style.width = 0; + + this._columnWidthsInitialized = false; + }, + + get scrollContainer() + { + return this._scrollContainer; + }, + + isScrolledToLastRow: function() + { + return this._scrollContainer.isScrolledToBottom(); + }, + + scrollToLastRow: function() + { + this._scrollContainer.scrollTop = this._scrollContainer.scrollHeight - this._scrollContainer.offsetHeight; + }, + + _positionResizers: function() + { + var headerTableColumns = this._headerTableColumnGroup.children; + var numColumns = headerTableColumns.length; + var left = 0; + var previousResizer = null; + + // Make n - 1 resizers for n columns. + for (var i = 0; i < numColumns - 1; i++) { + var resizer = this.resizers[i]; + + if (!resizer) { + // This is the first call to updateWidth, so the resizers need + // to be created. + resizer = document.createElement("div"); + resizer.addStyleClass("data-grid-resizer"); + // This resizer is associated with the column to its right. + resizer.addEventListener("mousedown", this._startResizerDragging.bind(this), false); + this.element.appendChild(resizer); + this.resizers[i] = resizer; + } + + // Get the width of the cell in the first (and only) row of the + // header table in order to determine the width of the column, since + // it is not possible to query a column for its width. + left += this.headerTableBody.rows[0].cells[i].offsetWidth; + + var columnIsVisible = !this._headerTableColumnGroup.children[i].hidden; + if (columnIsVisible) { + resizer.style.removeProperty("display"); + resizer.style.left = left + "px"; + resizer.leftNeighboringColumnID = i; + if (previousResizer) + previousResizer.rightNeighboringColumnID = i; + previousResizer = resizer; + } else { + resizer.style.setProperty("display", "none"); + resizer.leftNeighboringColumnID = 0; + resizer.rightNeighboringColumnID = 0; + } + } + if (previousResizer) + previousResizer.rightNeighboringColumnID = numColumns - 1; + }, + + addCreationNode: function(hasChildren) + { + if (this.creationNode) + this.creationNode.makeNormal(); + + var emptyData = {}; + for (var column in this.columns) + emptyData[column] = ''; + this.creationNode = new WebInspector.CreationDataGridNode(emptyData, hasChildren); + this.appendChild(this.creationNode); + }, + + appendChild: function(child) + { + this.insertChild(child, this.children.length); + }, + + insertChild: function(child, index) + { + if (!child) + throw("insertChild: Node can't be undefined or null."); + if (child.parent === this) + throw("insertChild: Node is already a child of this node."); + + if (child.parent) + child.parent.removeChild(child); + + this.children.splice(index, 0, child); + this.hasChildren = true; + + child.parent = this; + child.dataGrid = this.dataGrid; + child._recalculateSiblings(index); + + delete child._depth; + delete child._revealed; + delete child._attached; + child._shouldRefreshChildren = true; + + var current = child.children[0]; + while (current) { + current.dataGrid = this.dataGrid; + delete current._depth; + delete current._revealed; + delete current._attached; + current._shouldRefreshChildren = true; + current = current.traverseNextNode(false, child, true); + } + + if (this.expanded) + child._attach(); + }, + + removeChild: function(child) + { + if (!child) + throw("removeChild: Node can't be undefined or null."); + if (child.parent !== this) + throw("removeChild: Node is not a child of this node."); + + child.deselect(); + child._detach(); + + this.children.remove(child, true); + + if (child.previousSibling) + child.previousSibling.nextSibling = child.nextSibling; + if (child.nextSibling) + child.nextSibling.previousSibling = child.previousSibling; + + child.dataGrid = null; + child.parent = null; + child.nextSibling = null; + child.previousSibling = null; + + if (this.children.length <= 0) + this.hasChildren = false; + }, + + removeChildren: function() + { + for (var i = 0; i < this.children.length; ++i) { + var child = this.children[i]; + child.deselect(); + child._detach(); + + child.dataGrid = null; + child.parent = null; + child.nextSibling = null; + child.previousSibling = null; + } + + this.children = []; + this.hasChildren = false; + }, + + removeChildrenRecursive: function() + { + var childrenToRemove = this.children; + + var child = this.children[0]; + while (child) { + if (child.children.length) + childrenToRemove = childrenToRemove.concat(child.children); + child = child.traverseNextNode(false, this, true); + } + + for (var i = 0; i < childrenToRemove.length; ++i) { + child = childrenToRemove[i]; + child.deselect(); + child._detach(); + + child.children = []; + child.dataGrid = null; + child.parent = null; + child.nextSibling = null; + child.previousSibling = null; + } + + this.children = []; + }, + + sortNodes: function(comparator, reverseMode) + { + function comparatorWrapper(a, b) + { + if (a._dataGridNode._data.summaryRow) + return 1; + if (b._dataGridNode._data.summaryRow) + return -1; + + var aDataGirdNode = a._dataGridNode; + var bDataGirdNode = b._dataGridNode; + return reverseMode ? comparator(bDataGirdNode, aDataGirdNode) : comparator(aDataGirdNode, bDataGirdNode); + } + + var tbody = this.dataTableBody; + var tbodyParent = tbody.parentElement; + tbodyParent.removeChild(tbody); + + var childNodes = tbody.childNodes; + var fillerRow = childNodes[childNodes.length - 1]; + + var sortedRows = Array.prototype.slice.call(childNodes, 0, childNodes.length - 1); + sortedRows.sort(comparatorWrapper); + var sortedRowsLength = sortedRows.length; + + tbody.removeChildren(); + var previousSiblingNode = null; + for (var i = 0; i < sortedRowsLength; ++i) { + var row = sortedRows[i]; + var node = row._dataGridNode; + node.previousSibling = previousSiblingNode; + if (previousSiblingNode) + previousSiblingNode.nextSibling = node; + tbody.appendChild(row); + previousSiblingNode = node; + } + if (previousSiblingNode) + previousSiblingNode.nextSibling = null; + + tbody.appendChild(fillerRow); + tbodyParent.appendChild(tbody); + }, + + _keyDown: function(event) + { + if (!this.selectedNode || event.shiftKey || event.metaKey || event.ctrlKey || this._editing) + return; + + var handled = false; + var nextSelectedNode; + if (event.keyIdentifier === "Up" && !event.altKey) { + nextSelectedNode = this.selectedNode.traversePreviousNode(true); + while (nextSelectedNode && !nextSelectedNode.selectable) + nextSelectedNode = nextSelectedNode.traversePreviousNode(true); + handled = nextSelectedNode ? true : false; + } else if (event.keyIdentifier === "Down" && !event.altKey) { + nextSelectedNode = this.selectedNode.traverseNextNode(true); + while (nextSelectedNode && !nextSelectedNode.selectable) + nextSelectedNode = nextSelectedNode.traverseNextNode(true); + handled = nextSelectedNode ? true : false; + } else if (event.keyIdentifier === "Left") { + if (this.selectedNode.expanded) { + if (event.altKey) + this.selectedNode.collapseRecursively(); + else + this.selectedNode.collapse(); + handled = true; + } else if (this.selectedNode.parent && !this.selectedNode.parent.root) { + handled = true; + if (this.selectedNode.parent.selectable) { + nextSelectedNode = this.selectedNode.parent; + handled = nextSelectedNode ? true : false; + } else if (this.selectedNode.parent) + this.selectedNode.parent.collapse(); + } + } else if (event.keyIdentifier === "Right") { + if (!this.selectedNode.revealed) { + this.selectedNode.reveal(); + handled = true; + } else if (this.selectedNode.hasChildren) { + handled = true; + if (this.selectedNode.expanded) { + nextSelectedNode = this.selectedNode.children[0]; + handled = nextSelectedNode ? true : false; + } else { + if (event.altKey) + this.selectedNode.expandRecursively(); + else + this.selectedNode.expand(); + } + } + } else if (event.keyCode === 8 || event.keyCode === 46) { + if (this._deleteCallback) { + handled = true; + this._deleteCallback(this.selectedNode); + } + } else if (isEnterKey(event)) { + if (this._editCallback) { + handled = true; + // The first child of the selected element is the , + // and that's what we want to edit. + this._startEditing(this.selectedNode._element.children[0]); + } + } + + if (nextSelectedNode) { + nextSelectedNode.reveal(); + nextSelectedNode.select(); + } + + if (handled) { + event.preventDefault(); + event.stopPropagation(); + } + }, + + expand: function() + { + // This is the root, do nothing. + }, + + collapse: function() + { + // This is the root, do nothing. + }, + + reveal: function() + { + // This is the root, do nothing. + }, + + revealAndSelect: function() + { + // This is the root, do nothing. + }, + + dataGridNodeFromNode: function(target) + { + var rowElement = target.enclosingNodeOrSelfWithNodeName("tr"); + return rowElement && rowElement._dataGridNode; + }, + + dataGridNodeFromPoint: function(x, y) + { + var node = this._dataTable.ownerDocument.elementFromPoint(x, y); + var rowElement = node.enclosingNodeOrSelfWithNodeName("tr"); + return rowElement && rowElement._dataGridNode; + }, + + _clickInHeaderCell: function(event) + { + var cell = event.target.enclosingNodeOrSelfWithNodeName("th"); + if (!cell || !cell.columnIdentifier || !cell.hasStyleClass("sortable")) + return; + + var sortOrder = this.sortOrder; + + if (this._sortColumnCell) + this._sortColumnCell.removeMatchingStyleClasses("sort-\\w+"); + + if (cell == this._sortColumnCell) { + if (sortOrder === "ascending") + sortOrder = "descending"; + else + sortOrder = "ascending"; + } + + this._sortColumnCell = cell; + + cell.addStyleClass("sort-" + sortOrder); + + this.dispatchEventToListeners("sorting changed"); + }, + + markColumnAsSortedBy: function(columnIdentifier, sortOrder) + { + if (this._sortColumnCell) + this._sortColumnCell.removeMatchingStyleClasses("sort-\\w+"); + this._sortColumnCell = this._headerTableHeaders[columnIdentifier]; + this._sortColumnCell.addStyleClass("sort-" + sortOrder); + }, + + headerTableHeader: function(columnIdentifier) + { + return this._headerTableHeaders[columnIdentifier]; + }, + + _mouseDownInDataTable: function(event) + { + var gridNode = this.dataGridNodeFromNode(event.target); + if (!gridNode || !gridNode.selectable) + return; + + if (gridNode.isEventWithinDisclosureTriangle(event)) + return; + + if (event.metaKey) { + if (gridNode.selected) + gridNode.deselect(); + else + gridNode.select(); + } else + gridNode.select(); + }, + + _contextMenuInDataTable: function(event) + { + var contextMenu = new WebInspector.ContextMenu(); + + var gridNode = this.dataGridNodeFromNode(event.target); + if (this.dataGrid._refreshCallback && (!gridNode || gridNode !== this.creationNode)) + contextMenu.appendItem(WebInspector.UIString("Refresh"), this._refreshCallback.bind(this)); + + if (gridNode && gridNode.selectable && !gridNode.isEventWithinDisclosureTriangle(event)) { + // FIXME: Use the column names for Editing, instead of just "Edit". + if (this.dataGrid._editCallback) { + if (gridNode === this.creationNode) + contextMenu.appendItem(WebInspector.UIString("Add New"), this._startEditing.bind(this, event.target)); + else + contextMenu.appendItem(WebInspector.UIString("Edit"), this._startEditing.bind(this, event.target)); + } + if (this.dataGrid._deleteCallback && gridNode !== this.creationNode) + contextMenu.appendItem(WebInspector.UIString("Delete"), this._deleteCallback.bind(this, gridNode)); + } + + contextMenu.show(event); + }, + + _clickInDataTable: function(event) + { + var gridNode = this.dataGridNodeFromNode(event.target); + if (!gridNode || !gridNode.hasChildren) + return; + + if (!gridNode.isEventWithinDisclosureTriangle(event)) + return; + + if (gridNode.expanded) { + if (event.altKey) + gridNode.collapseRecursively(); + else + gridNode.collapse(); + } else { + if (event.altKey) + gridNode.expandRecursively(); + else + gridNode.expand(); + } + }, + + get resizeMethod() + { + if (typeof this._resizeMethod === "undefined") + return WebInspector.DataGrid.ResizeMethod.Nearest; + return this._resizeMethod; + }, + + set resizeMethod(method) + { + this._resizeMethod = method; + }, + + _startResizerDragging: function(event) + { + this._currentResizer = event.target; + if (!this._currentResizer.rightNeighboringColumnID) + return; + WebInspector.elementDragStart(this._currentResizer, this._resizerDragging.bind(this), + this._endResizerDragging.bind(this), event, "col-resize"); + }, + + _resizerDragging: function(event) + { + var resizer = this._currentResizer; + if (!resizer) + return; + + // Constrain the dragpoint to be within the containing div of the + // datagrid. + var dragPoint = event.clientX - this.element.totalOffsetLeft(); + // Constrain the dragpoint to be within the space made up by the + // column directly to the left and the column directly to the right. + var leftCellIndex = resizer.leftNeighboringColumnID; + var rightCellIndex = resizer.rightNeighboringColumnID; + var firstRowCells = this.headerTableBody.rows[0].cells; + var leftEdgeOfPreviousColumn = 0; + for (var i = 0; i < leftCellIndex; i++) + leftEdgeOfPreviousColumn += firstRowCells[i].offsetWidth; + + // Differences for other resize methods + if (this.resizeMethod == WebInspector.DataGrid.ResizeMethod.Last) { + rightCellIndex = this.resizers.length; + } else if (this.resizeMethod == WebInspector.DataGrid.ResizeMethod.First) { + leftEdgeOfPreviousColumn += firstRowCells[leftCellIndex].offsetWidth - firstRowCells[0].offsetWidth; + leftCellIndex = 0; + } + + var rightEdgeOfNextColumn = leftEdgeOfPreviousColumn + firstRowCells[leftCellIndex].offsetWidth + firstRowCells[rightCellIndex].offsetWidth; + + // Give each column some padding so that they don't disappear. + var leftMinimum = leftEdgeOfPreviousColumn + this.ColumnResizePadding; + var rightMaximum = rightEdgeOfNextColumn - this.ColumnResizePadding; + + dragPoint = Number.constrain(dragPoint, leftMinimum, rightMaximum); + + resizer.style.left = (dragPoint - this.CenterResizerOverBorderAdjustment) + "px"; + + var percentLeftColumn = (((dragPoint - leftEdgeOfPreviousColumn) / this._dataTable.offsetWidth) * 100) + "%"; + this._headerTableColumnGroup.children[leftCellIndex].style.width = percentLeftColumn; + this._dataTableColumnGroup.children[leftCellIndex].style.width = percentLeftColumn; + + var percentRightColumn = (((rightEdgeOfNextColumn - dragPoint) / this._dataTable.offsetWidth) * 100) + "%"; + this._headerTableColumnGroup.children[rightCellIndex].style.width = percentRightColumn; + this._dataTableColumnGroup.children[rightCellIndex].style.width = percentRightColumn; + + this._positionResizers(); + event.preventDefault(); + this.dispatchEventToListeners("width changed"); + }, + + _endResizerDragging: function(event) + { + WebInspector.elementDragEnd(event); + this._currentResizer = null; + this.dispatchEventToListeners("width changed"); + }, + + ColumnResizePadding: 10, + + CenterResizerOverBorderAdjustment: 3, +} + +WebInspector.DataGrid.ResizeMethod = { + Nearest: "nearest", + First: "first", + Last: "last" +} + +WebInspector.DataGrid.prototype.__proto__ = WebInspector.View.prototype; + +/** + * @constructor + * @extends {WebInspector.Object} + * @param {boolean=} hasChildren + */ +WebInspector.DataGridNode = function(data, hasChildren) +{ + this._expanded = false; + this._selected = false; + this._shouldRefreshChildren = true; + this._data = data || {}; + this.hasChildren = hasChildren || false; + this.children = []; + this.dataGrid = null; + this.parent = null; + this.previousSibling = null; + this.nextSibling = null; + this.disclosureToggleWidth = 10; +} + +WebInspector.DataGridNode.prototype = { + selectable: true, + + get element() + { + if (this._element) + return this._element; + + if (!this.dataGrid) + return null; + + this._element = document.createElement("tr"); + this._element._dataGridNode = this; + + if (this.hasChildren) + this._element.addStyleClass("parent"); + if (this.expanded) + this._element.addStyleClass("expanded"); + if (this.selected) + this._element.addStyleClass("selected"); + if (this.revealed) + this._element.addStyleClass("revealed"); + + this.createCells(); + return this._element; + }, + + createCells: function() + { + for (var columnIdentifier in this.dataGrid.columns) { + var cell = this.createCell(columnIdentifier); + this._element.appendChild(cell); + } + }, + + get data() + { + return this._data; + }, + + set data(x) + { + this._data = x || {}; + this.refresh(); + }, + + get revealed() + { + if ("_revealed" in this) + return this._revealed; + + var currentAncestor = this.parent; + while (currentAncestor && !currentAncestor.root) { + if (!currentAncestor.expanded) { + this._revealed = false; + return false; + } + + currentAncestor = currentAncestor.parent; + } + + this._revealed = true; + return true; + }, + + set hasChildren(x) + { + if (this._hasChildren === x) + return; + + this._hasChildren = x; + + if (!this._element) + return; + + if (this._hasChildren) + { + this._element.addStyleClass("parent"); + if (this.expanded) + this._element.addStyleClass("expanded"); + } + else + { + this._element.removeStyleClass("parent"); + this._element.removeStyleClass("expanded"); + } + }, + + get hasChildren() + { + return this._hasChildren; + }, + + set revealed(x) + { + if (this._revealed === x) + return; + + this._revealed = x; + + if (this._element) { + if (this._revealed) + this._element.addStyleClass("revealed"); + else + this._element.removeStyleClass("revealed"); + } + + for (var i = 0; i < this.children.length; ++i) + this.children[i].revealed = x && this.expanded; + }, + + get depth() + { + if ("_depth" in this) + return this._depth; + if (this.parent && !this.parent.root) + this._depth = this.parent.depth + 1; + else + this._depth = 0; + return this._depth; + }, + + get leftPadding() + { + if (typeof(this._leftPadding) === "number") + return this._leftPadding; + + this._leftPadding = this.depth * this.dataGrid.indentWidth; + return this._leftPadding; + }, + + get shouldRefreshChildren() + { + return this._shouldRefreshChildren; + }, + + set shouldRefreshChildren(x) + { + this._shouldRefreshChildren = x; + if (x && this.expanded) + this.expand(); + }, + + get selected() + { + return this._selected; + }, + + set selected(x) + { + if (x) + this.select(); + else + this.deselect(); + }, + + get expanded() + { + return this._expanded; + }, + + set expanded(x) + { + if (x) + this.expand(); + else + this.collapse(); + }, + + refresh: function() + { + if (!this._element || !this.dataGrid) + return; + + this._element.removeChildren(); + this.createCells(); + }, + + createCell: function(columnIdentifier) + { + var cell = document.createElement("td"); + cell.className = columnIdentifier + "-column"; + + var alignment = this.dataGrid.aligned[columnIdentifier]; + if (alignment) + cell.addStyleClass(alignment); + + var div = document.createElement("div"); + div.textContent = this.data[columnIdentifier]; + cell.appendChild(div); + + if (columnIdentifier === this.dataGrid.disclosureColumnIdentifier) { + cell.addStyleClass("disclosure"); + if (this.leftPadding) + cell.style.setProperty("padding-left", this.leftPadding + "px"); + } + + return cell; + }, + + // Share these functions with DataGrid. They are written to work with a DataGridNode this object. + appendChild: WebInspector.DataGrid.prototype.appendChild, + insertChild: WebInspector.DataGrid.prototype.insertChild, + removeChild: WebInspector.DataGrid.prototype.removeChild, + removeChildren: WebInspector.DataGrid.prototype.removeChildren, + removeChildrenRecursive: WebInspector.DataGrid.prototype.removeChildrenRecursive, + + _recalculateSiblings: function(myIndex) + { + if (!this.parent) + return; + + var previousChild = (myIndex > 0 ? this.parent.children[myIndex - 1] : null); + + if (previousChild) { + previousChild.nextSibling = this; + this.previousSibling = previousChild; + } else + this.previousSibling = null; + + var nextChild = this.parent.children[myIndex + 1]; + + if (nextChild) { + nextChild.previousSibling = this; + this.nextSibling = nextChild; + } else + this.nextSibling = null; + }, + + collapse: function() + { + if (this._element) + this._element.removeStyleClass("expanded"); + + this._expanded = false; + + for (var i = 0; i < this.children.length; ++i) + this.children[i].revealed = false; + + this.dispatchEventToListeners("collapsed"); + }, + + collapseRecursively: function() + { + var item = this; + while (item) { + if (item.expanded) + item.collapse(); + item = item.traverseNextNode(false, this, true); + } + }, + + expand: function() + { + if (!this.hasChildren || this.expanded) + return; + + if (this.revealed && !this._shouldRefreshChildren) + for (var i = 0; i < this.children.length; ++i) + this.children[i].revealed = true; + + if (this._shouldRefreshChildren) { + for (var i = 0; i < this.children.length; ++i) + this.children[i]._detach(); + + this.dispatchEventToListeners("populate"); + + if (this._attached) { + for (var i = 0; i < this.children.length; ++i) { + var child = this.children[i]; + if (this.revealed) + child.revealed = true; + child._attach(); + } + } + + delete this._shouldRefreshChildren; + } + + if (this._element) + this._element.addStyleClass("expanded"); + + this._expanded = true; + + this.dispatchEventToListeners("expanded"); + }, + + expandRecursively: function() + { + var item = this; + while (item) { + item.expand(); + item = item.traverseNextNode(false, this); + } + }, + + reveal: function() + { + var currentAncestor = this.parent; + while (currentAncestor && !currentAncestor.root) { + if (!currentAncestor.expanded) + currentAncestor.expand(); + currentAncestor = currentAncestor.parent; + } + + this.element.scrollIntoViewIfNeeded(false); + + this.dispatchEventToListeners("revealed"); + }, + + /** + * @param {boolean=} supressSelectedEvent + */ + select: function(supressSelectedEvent) + { + if (!this.dataGrid || !this.selectable || this.selected) + return; + + if (this.dataGrid.selectedNode) + this.dataGrid.selectedNode.deselect(); + + this._selected = true; + this.dataGrid.selectedNode = this; + + if (this._element) + this._element.addStyleClass("selected"); + + if (!supressSelectedEvent) + this.dispatchEventToListeners("selected"); + }, + + revealAndSelect: function() + { + this.reveal(); + this.select(); + }, + + /** + * @param {boolean=} supressDeselectedEvent + */ + deselect: function(supressDeselectedEvent) + { + if (!this.dataGrid || this.dataGrid.selectedNode !== this || !this.selected) + return; + + this._selected = false; + this.dataGrid.selectedNode = null; + + if (this._element) + this._element.removeStyleClass("selected"); + + if (!supressDeselectedEvent) + this.dispatchEventToListeners("deselected"); + }, + + traverseNextNode: function(skipHidden, stayWithin, dontPopulate, info) + { + if (!dontPopulate && this.hasChildren) + this.dispatchEventToListeners("populate"); + + if (info) + info.depthChange = 0; + + var node = (!skipHidden || this.revealed) ? this.children[0] : null; + if (node && (!skipHidden || this.expanded)) { + if (info) + info.depthChange = 1; + return node; + } + + if (this === stayWithin) + return null; + + node = (!skipHidden || this.revealed) ? this.nextSibling : null; + if (node) + return node; + + node = this; + while (node && !node.root && !((!skipHidden || node.revealed) ? node.nextSibling : null) && node.parent !== stayWithin) { + if (info) + info.depthChange -= 1; + node = node.parent; + } + + if (!node) + return null; + + return (!skipHidden || node.revealed) ? node.nextSibling : null; + }, + + traversePreviousNode: function(skipHidden, dontPopulate) + { + var node = (!skipHidden || this.revealed) ? this.previousSibling : null; + if (!dontPopulate && node && node.hasChildren) + node.dispatchEventToListeners("populate"); + + while (node && ((!skipHidden || (node.revealed && node.expanded)) ? node.children[node.children.length - 1] : null)) { + if (!dontPopulate && node.hasChildren) + node.dispatchEventToListeners("populate"); + node = ((!skipHidden || (node.revealed && node.expanded)) ? node.children[node.children.length - 1] : null); + } + + if (node) + return node; + + if (!this.parent || this.parent.root) + return null; + + return this.parent; + }, + + isEventWithinDisclosureTriangle: function(event) + { + if (!this.hasChildren) + return false; + var cell = event.target.enclosingNodeOrSelfWithNodeName("td"); + if (!cell.hasStyleClass("disclosure")) + return false; + + var left = cell.totalOffsetLeft() + this.leftPadding; + return event.pageX >= left && event.pageX <= left + this.disclosureToggleWidth; + }, + + _attach: function() + { + if (!this.dataGrid || this._attached) + return; + + this._attached = true; + + var nextNode = null; + var previousNode = this.traversePreviousNode(true, true); + if (previousNode && previousNode.element.parentNode && previousNode.element.nextSibling) + nextNode = previousNode.element.nextSibling; + if (!nextNode) + nextNode = this.dataGrid.dataTableBody.lastChild; + this.dataGrid.dataTableBody.insertBefore(this.element, nextNode); + + if (this.expanded) + for (var i = 0; i < this.children.length; ++i) + this.children[i]._attach(); + }, + + _detach: function() + { + if (!this._attached) + return; + + this._attached = false; + + if (this._element && this._element.parentNode) + this._element.parentNode.removeChild(this._element); + + for (var i = 0; i < this.children.length; ++i) + this.children[i]._detach(); + }, + + savePosition: function() + { + if (this._savedPosition) + return; + + if (!this.parent) + throw("savePosition: Node must have a parent."); + this._savedPosition = { + parent: this.parent, + index: this.parent.children.indexOf(this) + }; + }, + + restorePosition: function() + { + if (!this._savedPosition) + return; + + if (this.parent !== this._savedPosition.parent) + this._savedPosition.parent.insertChild(this, this._savedPosition.index); + + delete this._savedPosition; + } +} + +WebInspector.DataGridNode.prototype.__proto__ = WebInspector.Object.prototype; + +/** + * @constructor + * @extends {WebInspector.DataGridNode} + */ +WebInspector.CreationDataGridNode = function(data, hasChildren) +{ + WebInspector.DataGridNode.call(this, data, hasChildren); + this.isCreationNode = true; +} + +WebInspector.CreationDataGridNode.prototype = { + makeNormal: function() + { + delete this.isCreationNode; + delete this.makeNormal; + } +} + +WebInspector.CreationDataGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype; +/* ShowMoreDataGridNode.js */ + +/* + * Copyright (C) 2011 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. + */ + +/** + * @constructor + * @extends {WebInspector.DataGridNode} + */ +WebInspector.ShowMoreDataGridNode = function(callback, nextCount, allCount) +{ + function populate(count) + { + var index = this.parent.children.indexOf(this); + this.parent.removeChild(this); + callback(count, index); + } + + this.showNext = document.createElement("button"); + this.showNext.setAttribute("type", "button"); + this.showNext.textContent = WebInspector.UIString("Show next %d", nextCount); + this.showNext.addEventListener("click", populate.bind(this, nextCount), false); + + if (allCount) { + this.showAll = document.createElement("button"); + this.showAll.setAttribute("type", "button"); + this.showAll.textContent = WebInspector.UIString("Show all %d", allCount); + this.showAll.addEventListener("click", populate.bind(this, allCount), false); + } + + WebInspector.DataGridNode.call(this, {summaryRow:true}, false); + this.selectable = false; +} + +WebInspector.ShowMoreDataGridNode.prototype = { + createCells: function() + { + var cell = document.createElement("td"); + if (this.depth) + cell.style.setProperty("padding-left", (this.depth * this.dataGrid.indentWidth) + "px"); + cell.appendChild(this.showNext); + if (this.showAll) + cell.appendChild(this.showAll); + this._element.appendChild(cell); + + var columns = this.dataGrid.columns; + var count = 0; + for (var c in columns) + ++count; + while (--count > 0) { + cell = document.createElement("td"); + this._element.appendChild(cell); + } + } +}; + +WebInspector.ShowMoreDataGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype; +/* CookiesTable.js */ + +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2009 Joseph Pecoraro + * 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: + * + * 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. + */ + +/** + * @constructor + * @extends {WebInspector.View} + * @param {function(PageAgent.Cookie)=} deleteCallback + * @param {function()=} refreshCallback + */ +WebInspector.CookiesTable = function(cookieDomain, expandable, deleteCallback, refreshCallback) +{ + WebInspector.View.call(this); + this.element.className = "fill"; + + this._cookieDomain = cookieDomain; + + var columns = { 0: {}, 1: {}, 2: {}, 3: {}, 4: {}, 5: {}, 6: {}, 7: {} }; + columns[0].title = WebInspector.UIString("Name"); + columns[0].sortable = true; + columns[0].disclosure = expandable; + columns[0].width = "24%"; + columns[1].title = WebInspector.UIString("Value"); + columns[1].sortable = true; + columns[1].width = "34%"; + columns[2].title = WebInspector.UIString("Domain"); + columns[2].sortable = true; + columns[2].width = "7%"; + columns[3].title = WebInspector.UIString("Path"); + columns[3].sortable = true; + columns[3].width = "7%"; + columns[4].title = WebInspector.UIString("Expires"); + columns[4].sortable = true; + columns[4].width = "7%"; + columns[5].title = WebInspector.UIString("Size"); + columns[5].aligned = "right"; + columns[5].sortable = true; + columns[5].width = "7%"; + columns[6].title = WebInspector.UIString("HTTP"); + columns[6].aligned = "centered"; + columns[6].sortable = true; + columns[6].width = "7%"; + columns[7].title = WebInspector.UIString("Secure"); + columns[7].aligned = "centered"; + columns[7].sortable = true; + columns[7].width = "7%"; + + this._dataGrid = new WebInspector.DataGrid(columns, undefined, deleteCallback ? this._onDeleteFromGrid.bind(this, deleteCallback) : undefined); + this._dataGrid.addEventListener("sorting changed", this._rebuildTable, this); + this._dataGrid.refreshCallback = refreshCallback; + + this._dataGrid.show(this.element); + this._data = []; +} + +WebInspector.CookiesTable.prototype = { + updateWidths: function() + { + if (this._dataGrid) + this._dataGrid.updateWidths(); + }, + + setCookies: function(cookies) + { + this._data = [{cookies: cookies}]; + this._rebuildTable(); + }, + + addCookiesFolder: function(folderName, cookies) + { + this._data.push({cookies: cookies, folderName: folderName}); + this._rebuildTable(); + }, + + get selectedCookie() + { + var node = this._dataGrid.selectedNode; + return node ? node.cookie : null; + }, + + _rebuildTable: function() + { + this._dataGrid.removeChildren(); + for (var i = 0; i < this._data.length; ++i) { + var item = this._data[i]; + if (item.folderName) { + var groupData = [ item.folderName, "", "", "", "", this._totalSize(item.cookies), "", "" ]; + var groupNode = new WebInspector.DataGridNode(groupData); + groupNode.selectable = true; + this._dataGrid.appendChild(groupNode); + groupNode.element.addStyleClass("row-group"); + this._populateNode(groupNode, item.cookies); + groupNode.expand(); + } else + this._populateNode(this._dataGrid, item.cookies); + } + }, + + _populateNode: function(parentNode, cookies) + { + var selectedCookie = this.selectedCookie; + parentNode.removeChildren(); + if (!cookies) + return; + + this._sortCookies(cookies); + for (var i = 0; i < cookies.length; ++i) { + var cookieNode = this._createGridNode(cookies[i]); + parentNode.appendChild(cookieNode); + if (selectedCookie === cookies[i]) + cookieNode.selected = true; + } + }, + + _totalSize: function(cookies) + { + var totalSize = 0; + for (var i = 0; cookies && i < cookies.length; ++i) + totalSize += cookies[i].size; + return totalSize; + }, + + _sortCookies: function(cookies) + { + var sortDirection = this._dataGrid.sortOrder === "ascending" ? 1 : -1; + + function localeCompare(field, cookie1, cookie2) + { + return sortDirection * (cookie1[field] + "").localeCompare(cookie2[field] + "") + } + + function numberCompare(field, cookie1, cookie2) + { + return sortDirection * (cookie1[field] - cookie2[field]); + } + + function expiresCompare(cookie1, cookie2) + { + if (cookie1.session !== cookie2.session) + return sortDirection * (cookie1.session ? 1 : -1); + + if (cookie1.session) + return 0; + + return sortDirection * (cookie1.expires - cookie2.expires); + } + + var comparator; + switch (parseInt(this._dataGrid.sortColumnIdentifier, 10)) { + case 0: comparator = localeCompare.bind(this, "name"); break; + case 1: comparator = localeCompare.bind(this, "value"); break; + case 2: comparator = localeCompare.bind(this, "domain"); break; + case 3: comparator = localeCompare.bind(this, "path"); break; + case 4: comparator = expiresCompare; break; + case 5: comparator = numberCompare.bind(this, "size"); break; + case 6: comparator = localeCompare.bind(this, "httpOnly"); break; + case 7: comparator = localeCompare.bind(this, "secure"); break; + default: localeCompare.bind(this, "name"); + } + + cookies.sort(comparator); + }, + + /** + * @param {PageAgent.Cookie} cookie + */ + _createGridNode: function(cookie) + { + var data = {}; + data[0] = cookie.name; + data[1] = cookie.value; + data[2] = cookie.domain || ""; + data[3] = cookie.path || ""; + data[4] = cookie.type === WebInspector.Cookie.Type.Request ? "" : + (cookie.session ? WebInspector.UIString("Session") : new Date(cookie.expires).toGMTString()); + data[5] = cookie.size; + const checkmark = "\u2713"; + data[6] = (cookie.httpOnly ? checkmark : ""); + data[7] = (cookie.secure ? checkmark : ""); + + var node = new WebInspector.DataGridNode(data); + node.cookie = cookie; + node.selectable = true; + return node; + }, + + _onDeleteFromGrid: function(deleteCallback, node) + { + deleteCallback(node.cookie); + } +} + +WebInspector.CookiesTable.prototype.__proto__ = WebInspector.View.prototype; +/* CookieItemsView.js */ + +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2009 Joseph Pecoraro + * + * 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. + */ + +/** + * @constructor + * @extends {WebInspector.View} + */ +WebInspector.CookieItemsView = function(treeElement, cookieDomain) +{ + WebInspector.View.call(this); + + this.element.addStyleClass("storage-view"); + + this._deleteButton = new WebInspector.StatusBarButton(WebInspector.UIString("Delete"), "delete-storage-status-bar-item"); + this._deleteButton.visible = false; + this._deleteButton.addEventListener("click", this._deleteButtonClicked, this); + + this._refreshButton = new WebInspector.StatusBarButton(WebInspector.UIString("Refresh"), "refresh-storage-status-bar-item"); + this._refreshButton.addEventListener("click", this._refreshButtonClicked, this); + + this._treeElement = treeElement; + this._cookieDomain = cookieDomain; + + this._emptyView = new WebInspector.EmptyView(WebInspector.UIString("This site has no cookies.")); + this._emptyView.show(this.element); + + this.element.addEventListener("contextmenu", this._contextMenu.bind(this), true); +} + +WebInspector.CookieItemsView.prototype = { + get statusBarItems() + { + return [this._refreshButton.element, this._deleteButton.element]; + }, + + wasShown: function() + { + this._update(); + }, + + willHide: function() + { + this._deleteButton.visible = false; + }, + + _update: function() + { + WebInspector.Cookies.getCookiesAsync(this._updateWithCookies.bind(this)); + }, + + _updateWithCookies: function(allCookies, isAdvanced) + { + this._cookies = isAdvanced ? this._filterCookiesForDomain(allCookies) : allCookies; + + if (!this._cookies.length) { + // Nothing to show. + this._emptyView.show(this.element); + this._deleteButton.visible = false; + if (this._cookiesTable) + this._cookiesTable.detach(); + return; + } + + if (!this._cookiesTable) + this._cookiesTable = isAdvanced ? new WebInspector.CookiesTable(this._cookieDomain, false, this._deleteCookie.bind(this), this._update.bind(this)) : new WebInspector.SimpleCookiesTable(); + + this._cookiesTable.setCookies(this._cookies); + this._emptyView.detach(); + this._cookiesTable.show(this.element); + if (isAdvanced) { + this._treeElement.subtitle = String.sprintf(WebInspector.UIString("%d cookies (%s)"), this._cookies.length, + Number.bytesToString(this._totalSize)); + this._deleteButton.visible = true; + } + }, + + _filterCookiesForDomain: function(allCookies) + { + var cookies = []; + var resourceURLsForDocumentURL = []; + this._totalSize = 0; + + function populateResourcesForDocuments(resource) + { + var url = resource.documentURL.asParsedURL(); + if (url && url.host == this._cookieDomain) + resourceURLsForDocumentURL.push(resource.url); + } + WebInspector.forAllResources(populateResourcesForDocuments.bind(this)); + + for (var i = 0; i < allCookies.length; ++i) { + var pushed = false; + var size = allCookies[i].size; + for (var j = 0; j < resourceURLsForDocumentURL.length; ++j) { + var resourceURL = resourceURLsForDocumentURL[j]; + if (WebInspector.Cookies.cookieMatchesResourceURL(allCookies[i], resourceURL)) { + this._totalSize += size; + if (!pushed) { + pushed = true; + cookies.push(allCookies[i]); + } + } + } + } + return cookies; + }, + + _deleteCookie: function(cookie) + { + PageAgent.deleteCookie(cookie.name, this._cookieDomain); + this._update(); + }, + + _deleteButtonClicked: function() + { + if (this._cookiesTable.selectedCookie) + this._deleteCookie(this._cookiesTable.selectedCookie); + }, + + _refreshButtonClicked: function(event) + { + this._update(); + }, + + _contextMenu: function(event) + { + if (!this._cookies.length) { + var contextMenu = new WebInspector.ContextMenu(); + contextMenu.appendItem(WebInspector.UIString("Refresh"), this._update.bind(this)); + contextMenu.show(event); + } + } +} + +WebInspector.CookieItemsView.prototype.__proto__ = WebInspector.View.prototype; + +/** + * @constructor + * @extends {WebInspector.View} + */ +WebInspector.SimpleCookiesTable = function() +{ + WebInspector.View.call(this); + + var columns = {}; + columns[0] = {}; + columns[1] = {}; + columns[0].title = WebInspector.UIString("Name"); + columns[1].title = WebInspector.UIString("Value"); + + this._dataGrid = new WebInspector.DataGrid(columns); + this._dataGrid.autoSizeColumns(20, 80); + this._dataGrid.show(this.element); +} + +WebInspector.SimpleCookiesTable.prototype = { + setCookies: function(cookies) + { + this._dataGrid.removeChildren(); + var addedCookies = {}; + for (var i = 0; i < cookies.length; ++i) { + if (addedCookies[cookies[i].name]) + continue; + addedCookies[cookies[i].name] = true; + var data = {}; + data[0] = cookies[i].name; + data[1] = cookies[i].value; + + var node = new WebInspector.DataGridNode(data, false); + node.selectable = true; + this._dataGrid.appendChild(node); + } + this._dataGrid.children[0].selected = true; + } +} + +WebInspector.SimpleCookiesTable.prototype.__proto__ = WebInspector.View.prototype; + +WebInspector.Cookies = {} + +WebInspector.Cookies.getCookiesAsync = function(callback) +{ + function mycallback(error, cookies, cookiesString) + { + if (error) + return; + if (cookiesString) + callback(WebInspector.Cookies.buildCookiesFromString(cookiesString), false); + else + callback(cookies, true); + } + + PageAgent.getCookies(mycallback); +} + +WebInspector.Cookies.buildCookiesFromString = function(rawCookieString) +{ + var rawCookies = rawCookieString.split(/;\s*/); + var cookies = []; + + if (!(/^\s*$/.test(rawCookieString))) { + for (var i = 0; i < rawCookies.length; ++i) { + var cookie = rawCookies[i]; + var delimIndex = cookie.indexOf("="); + var name = cookie.substring(0, delimIndex); + var value = cookie.substring(delimIndex + 1); + var size = name.length + value.length; + cookies.push({ name: name, value: value, size: size }); + } + } + + return cookies; +} + +WebInspector.Cookies.cookieMatchesResourceURL = function(cookie, resourceURL) +{ + var url = resourceURL.asParsedURL(); + if (!url || !WebInspector.Cookies.cookieDomainMatchesResourceDomain(cookie.domain, url.host)) + return false; + return (url.path.indexOf(cookie.path) === 0 + && (!cookie.port || url.port == cookie.port) + && (!cookie.secure || url.scheme === "https")); +} + +WebInspector.Cookies.cookieDomainMatchesResourceDomain = function(cookieDomain, resourceDomain) +{ + if (cookieDomain.charAt(0) !== '.') + return resourceDomain === cookieDomain; + return !!resourceDomain.match(new RegExp("^([^\\.]+\\.)?" + cookieDomain.substring(1).escapeForRegExp() + "$"), "i"); +} +/* ApplicationCacheModel.js */ + +/* + * Copyright (C) 2011 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: + * + * 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 GOOGLE INC. 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 GOOGLE INC. + * 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. + */ + +/** + * @constructor + * @extends {WebInspector.Object} + */ +WebInspector.ApplicationCacheModel = function() +{ + ApplicationCacheAgent.enable(); + InspectorBackend.registerApplicationCacheDispatcher(new WebInspector.ApplicationCacheDispatcher(this)); + + WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameNavigated, this._frameNavigated, this); + WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameDetached, this._frameDetached, this); + + this._statuses = {}; + this._manifestURLsByFrame = {}; + + this._mainFrameNavigated(); + + this._onLine = true; +} + +WebInspector.ApplicationCacheModel.EventTypes = { + FrameManifestStatusUpdated: "FrameManifestStatusUpdated", + FrameManifestAdded: "FrameManifestAdded", + FrameManifestRemoved: "FrameManifestRemoved", + NetworkStateChanged: "NetworkStateChanged" +} + +WebInspector.ApplicationCacheModel.prototype = { + _frameNavigated: function(event) + { + var frame = /** @type {WebInspector.ResourceTreeFrame} */ event.data; + if (frame.isMainFrame()) { + this._mainFrameNavigated(); + return; + } + + ApplicationCacheAgent.getManifestForFrame(frame.id, this._manifestForFrameLoaded.bind(this, frame.id)); + }, + + /** + * @param {WebInspector.Event} event + */ + _frameDetached: function(event) + { + var frame = /** @type {WebInspector.ResourceTreeFrame} */ event.data; + this._frameManifestRemoved(frame.id); + }, + + _mainFrameNavigated: function() + { + ApplicationCacheAgent.getFramesWithManifests(this._framesWithManifestsLoaded.bind(this)); + }, + + /** + * @param {string} frameId + * @param {?Protocol.Error} error + * @param {string} manifestURL + */ + _manifestForFrameLoaded: function(frameId, error, manifestURL) + { + if (error) { + console.error(error); + return; + } + + if (!manifestURL) + this._frameManifestRemoved(frameId); + }, + + /** + * @param {?Protocol.Error} error + * @param {Array.} framesWithManifests + */ + _framesWithManifestsLoaded: function(error, framesWithManifests) + { + if (error) { + console.error(error); + return; + } + + for (var i = 0; i < framesWithManifests.length; ++i) + this._frameManifestUpdated(framesWithManifests[i].frameId, framesWithManifests[i].manifestURL, framesWithManifests[i].status); + }, + + /** + * @param {string} frameId + * @param {string} manifestURL + * @param {number} status + */ + _frameManifestUpdated: function(frameId, manifestURL, status) + { + if (status === applicationCache.UNCACHED) { + this._frameManifestRemoved(frameId); + return; + } + + if (!manifestURL) + return; + + if (this._manifestURLsByFrame[frameId] && manifestURL !== this._manifestURLsByFrame[frameId]) + this._frameManifestRemoved(frameId); + + var statusChanged = this._statuses[frameId] !== status; + this._statuses[frameId] = status; + + if (!this._manifestURLsByFrame[frameId]) { + this._manifestURLsByFrame[frameId] = manifestURL; + this.dispatchEventToListeners(WebInspector.ApplicationCacheModel.EventTypes.FrameManifestAdded, frameId); + } + + if (statusChanged) + this.dispatchEventToListeners(WebInspector.ApplicationCacheModel.EventTypes.FrameManifestStatusUpdated, frameId); + }, + + /** + * @param {string} frameId + */ + _frameManifestRemoved: function(frameId) + { + if (!this._manifestURLsByFrame[frameId]) + return; + + var manifestURL = this._manifestURLsByFrame[frameId]; + delete this._manifestURLsByFrame[frameId]; + delete this._statuses[frameId]; + + this.dispatchEventToListeners(WebInspector.ApplicationCacheModel.EventTypes.FrameManifestRemoved, frameId); + }, + + /** + * @param {string} frameId + * @return {string} + */ + frameManifestURL: function(frameId) + { + return this._manifestURLsByFrame[frameId] || ""; + }, + + /** + * @param {string} frameId + * @return {number} + */ + frameManifestStatus: function(frameId) + { + return this._statuses[frameId] || applicationCache.UNCACHED; + }, + + /** + * @return {boolean} + */ + get onLine() + { + return this._onLine; + }, + + /** + * @param {string} frameId + * @param {string} manifestURL + * @param {number} status + */ + _statusUpdated: function(frameId, manifestURL, status) + { + this._frameManifestUpdated(frameId, manifestURL, status); + }, + + /** + * @param {string} frameId + * @param {function(Object)} callback + */ + requestApplicationCache: function(frameId, callback) + { + function callbackWrapper(error, applicationCache) + { + if (error) { + console.error(error); + callback(null); + return; + } + + callback(applicationCache); + } + + ApplicationCacheAgent.getApplicationCacheForFrame(frameId, callbackWrapper.bind(this)); + }, + + /** + * @param {boolean} isNowOnline + */ + _networkStateUpdated: function(isNowOnline) + { + this._onLine = isNowOnline; + this.dispatchEventToListeners(WebInspector.ApplicationCacheModel.EventTypes.NetworkStateChanged, isNowOnline); + } +} + +WebInspector.ApplicationCacheModel.prototype.__proto__ = WebInspector.Object.prototype; + +/** + * @constructor + * @implements {ApplicationCacheAgent.Dispatcher} + */ +WebInspector.ApplicationCacheDispatcher = function(applicationCacheModel) +{ + this._applicationCacheModel = applicationCacheModel; +} + +WebInspector.ApplicationCacheDispatcher.prototype = { + /** + * @param {string} frameId + * @param {string} manifestURL + * @param {number} status + */ + applicationCacheStatusUpdated: function(frameId, manifestURL, status) + { + this._applicationCacheModel._statusUpdated(frameId, manifestURL, status); + }, + + /** + * @param {boolean} isNowOnline + */ + networkStateUpdated: function(isNowOnline) + { + this._applicationCacheModel._networkStateUpdated(isNowOnline); + } +} +/* ApplicationCacheItemsView.js */ + +/* + * Copyright (C) 2010 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 INC. 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 INC. 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. + */ + +/** + * @constructor + * @extends {WebInspector.View} + */ +WebInspector.ApplicationCacheItemsView = function(model, frameId) +{ + WebInspector.View.call(this); + + this._model = model; + + this.element.addStyleClass("storage-view"); + this.element.addStyleClass("table"); + + // FIXME: Needs better tooltip. (Localized) + this.deleteButton = new WebInspector.StatusBarButton(WebInspector.UIString("Delete"), "delete-storage-status-bar-item"); + this.deleteButton.visible = false; + this.deleteButton.addEventListener("click", this._deleteButtonClicked, this); + + this.connectivityIcon = document.createElement("img"); + this.connectivityIcon.className = "storage-application-cache-connectivity-icon"; + this.connectivityIcon.src = ""; + this.connectivityMessage = document.createElement("span"); + this.connectivityMessage.className = "storage-application-cache-connectivity"; + this.connectivityMessage.textContent = ""; + + this.divider = document.createElement("span"); + this.divider.className = "status-bar-item status-bar-divider"; + + this.statusIcon = document.createElement("img"); + this.statusIcon.className = "storage-application-cache-status-icon"; + this.statusIcon.src = ""; + this.statusMessage = document.createElement("span"); + this.statusMessage.className = "storage-application-cache-status"; + this.statusMessage.textContent = ""; + + this._frameId = frameId; + + this._emptyView = new WebInspector.EmptyView(WebInspector.UIString("No Application Cache information available.")); + this._emptyView.show(this.element); + + this._markDirty(); + + var status = this._model.frameManifestStatus(frameId); + this.updateStatus(status); + + this.updateNetworkState(this._model.onLine); + + // FIXME: Status bar items don't work well enough yet, so they are being hidden. + // http://webkit.org/b/41637 Web Inspector: Give Semantics to "Refresh" and "Delete" Buttons in ApplicationCache DataGrid + this.deleteButton.element.style.display = "none"; +} + +WebInspector.ApplicationCacheItemsView.prototype = { + get statusBarItems() + { + return [ + this.deleteButton.element, + this.connectivityIcon, this.connectivityMessage, this.divider, + this.statusIcon, this.statusMessage + ]; + }, + + wasShown: function() + { + this._maybeUpdate(); + }, + + willHide: function() + { + this.deleteButton.visible = false; + }, + + _maybeUpdate: function() + { + if (!this.isShowing() || !this._viewDirty) + return; + + this._update(); + this._viewDirty = false; + }, + + _markDirty: function() + { + this._viewDirty = true; + }, + + /** + * @param {number} status + */ + updateStatus: function(status) + { + var oldStatus = this._status; + this._status = status; + + var statusInformation = {}; + // We should never have UNCACHED status, since we remove frames with UNCACHED application cache status from the tree. + statusInformation[applicationCache.UNCACHED] = { src: "Images/errorRedDot.png", text: "UNCACHED" }; + statusInformation[applicationCache.IDLE] = { src: "Images/successGreenDot.png", text: "IDLE" }; + statusInformation[applicationCache.CHECKING] = { src: "Images/warningOrangeDot.png", text: "CHECKING" }; + statusInformation[applicationCache.DOWNLOADING] = { src: "Images/warningOrangeDot.png", text: "DOWNLOADING" }; + statusInformation[applicationCache.UPDATEREADY] = { src: "Images/successGreenDot.png", text: "UPDATEREADY" }; + statusInformation[applicationCache.OBSOLETE] = { src: "Images/errorRedDot.png", text: "OBSOLETE" }; + + var info = statusInformation[status] || statusInformation[applicationCache.UNCACHED]; + + this.statusIcon.src = info.src; + this.statusMessage.textContent = info.text; + + if (this.isShowing() && this._status === applicationCache.IDLE && (oldStatus === applicationCache.UPDATEREADY || !this._resources)) + this._markDirty(); + this._maybeUpdate(); + }, + + /** + * @param {boolean} isNowOnline + */ + updateNetworkState: function(isNowOnline) + { + if (isNowOnline) { + this.connectivityIcon.src = "Images/successGreenDot.png"; + this.connectivityMessage.textContent = WebInspector.UIString("Online"); + } else { + this.connectivityIcon.src = "Images/errorRedDot.png"; + this.connectivityMessage.textContent = WebInspector.UIString("Offline"); + } + }, + + _update: function() + { + this._model.requestApplicationCache(this._frameId, this._updateCallback.bind(this)); + }, + + /** + * @param {Object} applicationCache + */ + _updateCallback: function(applicationCache) + { + if (!applicationCache || !applicationCache.manifestURL) { + delete this._manifest; + delete this._creationTime; + delete this._updateTime; + delete this._size; + delete this._resources; + + this._emptyView.show(this.element); + this.deleteButton.visible = false; + if (this._dataGrid) + this._dataGrid.element.addStyleClass("hidden"); + return; + } + // FIXME: are these variables needed anywhere else? + this._manifest = applicationCache.manifestURL; + this._creationTime = applicationCache.creationTime; + this._updateTime = applicationCache.updateTime; + this._size = applicationCache.size; + this._resources = applicationCache.resources; + + var lastPathComponent = applicationCache.lastPathComponent; + + if (!this._dataGrid) + this._createDataGrid(); + + this._populateDataGrid(); + this._dataGrid.autoSizeColumns(20, 80); + this._dataGrid.element.removeStyleClass("hidden"); + this._emptyView.detach(); + this.deleteButton.visible = true; + + // FIXME: For Chrome, put creationTime and updateTime somewhere. + // NOTE: localizedString has not yet been added. + // WebInspector.UIString("(%s) Created: %s Updated: %s", this._size, this._creationTime, this._updateTime); + }, + + _createDataGrid: function() + { + var columns = { 0: {}, 1: {}, 2: {} }; + columns[0].title = WebInspector.UIString("Resource"); + columns[0].sort = "ascending"; + columns[0].sortable = true; + columns[1].title = WebInspector.UIString("Type"); + columns[1].sortable = true; + columns[2].title = WebInspector.UIString("Size"); + columns[2].aligned = "right"; + columns[2].sortable = true; + this._dataGrid = new WebInspector.DataGrid(columns); + this._dataGrid.show(this.element); + this._dataGrid.addEventListener("sorting changed", this._populateDataGrid, this); + }, + + _populateDataGrid: function() + { + var selectedResource = this._dataGrid.selectedNode ? this._dataGrid.selectedNode.resource : null; + var sortDirection = this._dataGrid.sortOrder === "ascending" ? 1 : -1; + + function numberCompare(field, resource1, resource2) + { + return sortDirection * (resource1[field] - resource2[field]); + } + function localeCompare(field, resource1, resource2) + { + return sortDirection * (resource1[field] + "").localeCompare(resource2[field] + "") + } + + var comparator; + switch (parseInt(this._dataGrid.sortColumnIdentifier, 10)) { + case 0: comparator = localeCompare.bind(this, "name"); break; + case 1: comparator = localeCompare.bind(this, "type"); break; + case 2: comparator = numberCompare.bind(this, "size"); break; + default: localeCompare.bind(this, "resource"); // FIXME: comparator = ? + } + + this._resources.sort(comparator); + this._dataGrid.removeChildren(); + + var nodeToSelect; + for (var i = 0; i < this._resources.length; ++i) { + var data = {}; + var resource = this._resources[i]; + data[0] = resource.url; + data[1] = resource.type; + data[2] = Number.bytesToString(resource.size); + var node = new WebInspector.DataGridNode(data); + node.resource = resource; + node.selectable = true; + this._dataGrid.appendChild(node); + if (resource === selectedResource) { + nodeToSelect = node; + nodeToSelect.selected = true; + } + } + + if (!nodeToSelect && this._dataGrid.children.length) + this._dataGrid.children[0].selected = true; + }, + + _deleteButtonClicked: function(event) + { + if (!this._dataGrid || !this._dataGrid.selectedNode) + return; + + // FIXME: Delete Button semantics are not yet defined. (Delete a single, or all?) + this._deleteCallback(this._dataGrid.selectedNode); + }, + + _deleteCallback: function(node) + { + // FIXME: Should we delete a single (selected) resource or all resources? + // InspectorBackend.deleteCachedResource(...) + // this._update(); + }, +} + +WebInspector.ApplicationCacheItemsView.prototype.__proto__ = WebInspector.View.prototype; +/* IndexedDBModel.js */ + +/* + * Copyright (C) 2012 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. + */ + +/** + * @constructor + * @extends {WebInspector.Object} + */ +WebInspector.IndexedDBModel = function() +{ + this._indexedDBAgent = new WebInspector.IndexedDBRequestManager(); + + WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameNavigated, this._frameNavigated, this); + WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameDetached, this._frameDetached, this); + + this._securityOriginByFrameId = {}; + this._frameIdsBySecurityOrigin = {}; + this._databaseNamesBySecurityOrigin = {}; + + this.refreshDatabaseNames(); +} + +WebInspector.IndexedDBModel.prototype = { + refreshDatabaseNames: function() + { + this._reset(); + this._framesNavigatedRecursively(WebInspector.resourceTreeModel.mainFrame); + }, + + /** + * @param {WebInspector.ResourceTreeFrame} resourceTreeFrame + */ + _framesNavigatedRecursively: function(resourceTreeFrame) + { + this._processFrameNavigated(resourceTreeFrame); + for (var i = 0; i < resourceTreeFrame.childFrames.length; ++i) + this._framesNavigatedRecursively(resourceTreeFrame.childFrames[i]); + }, + + /** + * @param {WebInspector.Event} event + */ + _frameNavigated: function(event) + { + var resourceTreeFrame = /** @type {WebInspector.ResourceTreeFrame} */ event.data; + this._processFrameNavigated(resourceTreeFrame); + }, + + /** + * @param {WebInspector.Event} event + */ + _frameDetached: function(event) + { + var resourceTreeFrame = /** @type {WebInspector.ResourceTreeFrame} */ event.data; + this._originRemovedFromFrame(resourceTreeFrame.id); + this._indexedDBAgent._frameDetached(resourceTreeFrame.id); + }, + + _reset: function() + { + this._securityOriginByFrameId = {}; + this._frameIdsBySecurityOrigin = {}; + this._databaseNamesBySecurityOrigin = {}; + this._indexedDBAgent._reset(); + // FIXME: dispatch events? + }, + + /** + * @param {WebInspector.ResourceTreeFrame} resourceTreeFrame + */ + _processFrameNavigated: function(resourceTreeFrame) + { + if (resourceTreeFrame.securityOrigin === "null") + return; + if (this._frameIdsBySecurityOrigin[resourceTreeFrame.securityOrigin]) + this._originAddedToFrame(resourceTreeFrame.id, resourceTreeFrame.securityOrigin); + else + this._loadDatabaseNamesForFrame(resourceTreeFrame.id); + }, + + /** + * @param {string} frameId + * @param {string} securityOrigin + */ + _originAddedToFrame: function(frameId, securityOrigin) + { + if (!this._frameIdsBySecurityOrigin[securityOrigin]) { + this._frameIdsBySecurityOrigin[securityOrigin] = []; + this._frameIdsBySecurityOrigin[securityOrigin].push(frameId); + this._databaseNamesBySecurityOrigin[securityOrigin] = []; + // FIXME: dispatch origin added event. + } + this._securityOriginByFrameId[frameId] = securityOrigin; + }, + + /** + * @param {string} frameId + */ + _originRemovedFromFrame: function(frameId) + { + var currentSecurityOrigin = this._securityOriginByFrameId[frameId]; + if (!currentSecurityOrigin) + return; + + delete this._securityOriginByFrameId[frameId]; + + var frameIdsForOrigin = this._frameIdsBySecurityOrigin[currentSecurityOrigin]; + for (var i = 0; i < frameIdsForOrigin; ++i) { + if (frameIdsForOrigin[i] === frameId) { + frameIdsForOrigin.splice(i, 1); + break; + } + } + if (!frameIdsForOrigin.length) + this._originRemoved(currentSecurityOrigin); + }, + + /** + * @param {string} securityOrigin + */ + _originRemoved: function(securityOrigin) + { + var frameIdsForOrigin = this._frameIdsBySecurityOrigin[securityOrigin]; + for (var i = 0; i < frameIdsForOrigin; ++i) + delete this._securityOriginByFrameId[frameIdsForOrigin[i]] + delete this._frameIdsBySecurityOrigin[securityOrigin]; + for (var i = 0; i < this._databaseNamesBySecurityOrigin[securityOrigin]; ++i) + this._databaseRemoved(securityOrigin, this._databaseNamesBySecurityOrigin[securityOrigin][i]); + delete this._databaseNamesBySecurityOrigin[securityOrigin]; + // FIXME: dispatch origin removed event. + }, + + /** + * @param {string} securityOrigin + * @param {Array.} databaseNames + */ + _updateOriginDatabaseNames: function(securityOrigin, databaseNames) + { + var newDatabaseNames = {}; + for (var i = 0; i < databaseNames.length; ++i) + newDatabaseNames[databaseNames[i]] = true; + var oldDatabaseNames = {}; + for (var i = 0; i < this._databaseNamesBySecurityOrigin[securityOrigin].length; ++i) + oldDatabaseNames[databaseNames[i]] = true; + + this._databaseNamesBySecurityOrigin[securityOrigin] = databaseNames; + + for (var databaseName in oldDatabaseNames) { + if (!newDatabaseNames[databaseName]) + this._databaseRemoved(securityOrigin, databaseName); + } + for (var databaseName in newDatabaseNames) { + if (!oldDatabaseNames[databaseName]) + this._databaseAdded(securityOrigin, databaseName); + } + + if (!this._databaseNamesBySecurityOrigin[securityOrigin].length) + this._originRemoved(securityOrigin); + }, + + /** + * @param {string} securityOrigin + * @param {string} databaseName + */ + _databaseAdded: function(securityOrigin, databaseName) + { + // FIXME: dispatch database added event. + }, + + /** + * @param {string} securityOrigin + * @param {string} databaseName + */ + _databaseRemoved: function(securityOrigin, databaseName) + { + // FIXME: dispatch database removed event. + }, + + /** + * @param {string} frameId + */ + _loadDatabaseNamesForFrame: function(frameId) + { + /** + * @param {IndexedDBAgent.SecurityOriginWithDatabaseNames} securityOriginWithDatabaseNames + */ + function callback(securityOriginWithDatabaseNames) + { + var databaseNames = securityOriginWithDatabaseNames.databaseNames; + var oldSecurityOrigin = this._securityOriginByFrameId[frameId]; + if (oldSecurityOrigin && oldSecurityOrigin === securityOriginWithDatabaseNames.securityOrigin) + this._updateOriginDatabaseNames(securityOriginWithDatabaseNames.securityOrigin, securityOriginWithDatabaseNames.databaseNames); + else { + this._originRemovedFromFrame(frameId); + this._originAddedToFrame(frameId, securityOriginWithDatabaseNames.securityOrigin); + this._updateOriginDatabaseNames(securityOriginWithDatabaseNames.securityOrigin, securityOriginWithDatabaseNames.databaseNames); + } + } + + this._indexedDBAgent.requestDatabaseNamesForFrame(frameId, callback.bind(this)); + } +} + +WebInspector.IndexedDBModel.prototype.__proto__ = WebInspector.Object.prototype; + +/** + * @constructor + */ +WebInspector.IndexedDBRequestManager = function() +{ + this._lastRequestId = 0; + this._requestDatabaseNamesForFrameCallbacks = {}; + + IndexedDBAgent.enable(); + InspectorBackend.registerIndexedDBDispatcher(new WebInspector.IndexedDBDispatcher(this)); +} + +WebInspector.IndexedDBRequestManager.prototype = { + /** + * @param {string} frameId + * @param {function(IndexedDBAgent.SecurityOriginWithDatabaseNames)} callback + */ + requestDatabaseNamesForFrame: function(frameId, callback) + { + var requestId = this._requestId(); + var request = new WebInspector.IndexedDBRequestManager.DatabasesForFrameRequest(frameId, callback); + this._requestDatabaseNamesForFrameCallbacks[requestId] = request; + + function innerCallback(error) + { + if (error) { + console.error("IndexedDBAgent error: " + error); + return; + } + } + + IndexedDBAgent.requestDatabaseNamesForFrame(requestId, frameId, innerCallback); + }, + + /** + * @param {number} requestId + * @param {IndexedDBAgent.SecurityOriginWithDatabaseNames} securityOriginWithDatabaseNames + */ + _databaseNamesLoaded: function(requestId, securityOriginWithDatabaseNames) + { + var request = this._requestDatabaseNamesForFrameCallbacks[requestId]; + if (!request.callback) + return; + + request.callback(securityOriginWithDatabaseNames); + }, + + /** + * @return {number} + */ + _requestId: function() + { + return ++this._lastRequestId; + }, + + /** + * @param {string} frameId + */ + _frameDetached: function(frameId) + { + for (var requestId in this._requestDatabaseNamesForFrameCallbacks) { + if (this._requestDatabaseNamesForFrameCallbacks[requestId].frameId === frameId) + delete this._requestDatabaseNamesForFrameCallbacks[requestId]; + } + }, + + _reset: function() + { + this._requestDatabaseNamesForFrameCallbacks = {}; + } +} + +/** + * @constructor + */ +WebInspector.IndexedDBRequestManager.DatabasesForFrameRequest = function(frameId, callback) +{ + this.frameId = frameId; + this.callback = callback; +} + +/** + * @constructor + * @implements {IndexedDBAgent.Dispatcher} + * @param {WebInspector.IndexedDBRequestManager} indexedDBRequestManager + */ +WebInspector.IndexedDBDispatcher = function(indexedDBRequestManager) +{ + this._agentWrapper = indexedDBRequestManager; +} + +WebInspector.IndexedDBDispatcher.prototype = { + /** + * @param {number} requestId + * @param {IndexedDBAgent.SecurityOriginWithDatabaseNames} securityOriginWithDatabaseNames + */ + databaseNamesLoaded: function(requestId, securityOriginWithDatabaseNames) + { + this._agentWrapper._databaseNamesLoaded(requestId, securityOriginWithDatabaseNames); + } +} +/* Script.js */ + +/* + * Copyright (C) 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 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 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. + */ + +/** + * @constructor + * @param {string} scriptId + * @param {string} sourceURL + * @param {number} startLine + * @param {number} startColumn + * @param {number} endLine + * @param {number} endColumn + * @param {boolean} isContentScript + * @param {string=} sourceMapURL + */ +WebInspector.Script = function(scriptId, sourceURL, startLine, startColumn, endLine, endColumn, isContentScript, sourceMapURL) +{ + this.scriptId = scriptId; + this.sourceURL = sourceURL; + this.lineOffset = startLine; + this.columnOffset = startColumn; + this.endLine = endLine; + this.endColumn = endColumn; + this.isContentScript = isContentScript; + this.sourceMapURL = sourceMapURL; +} + +WebInspector.Script.prototype = { + /** + * @param {function(string)} callback + */ + requestSource: function(callback) + { + if (this._source) { + callback(this._source); + return; + } + + /** + * @this {WebInspector.Script} + * @param {?Protocol.Error} error + * @param {string} source + */ + function didGetScriptSource(error, source) + { + this._source = error ? "" : source; + callback(this._source); + } + if (this.scriptId) { + // Script failed to parse. + DebuggerAgent.getScriptSource(this.scriptId, didGetScriptSource.bind(this)); + } else + callback(""); + }, + + /** + * @param {string} query + * @param {boolean} caseSensitive + * @param {boolean} isRegex + * @param {function(Array.)} callback + */ + searchInContent: function(query, caseSensitive, isRegex, callback) + { + /** + * @this {WebInspector.Script} + * @param {?Protocol.Error} error + * @param {Array.} searchMatches + */ + function innerCallback(error, searchMatches) + { + if (error) + console.error(error); + var result = []; + for (var i = 0; i < searchMatches.length; ++i) { + var searchMatch = new WebInspector.ContentProvider.SearchMatch(searchMatches[i].lineNumber, searchMatches[i].lineContent); + result.push(searchMatch); + } + callback(result || []); + } + + if (this.scriptId) { + // Script failed to parse. + DebuggerAgent.searchInContent(this.scriptId, query, caseSensitive, isRegex, innerCallback.bind(this)); + } else + callback([]); + }, + + /** + * @param {string} newSource + * @param {function(?Protocol.Error, Array.=)} callback + */ + editSource: function(newSource, callback) + { + /** + * @this {WebInspector.Script} + * @param {?Protocol.Error} error + * @param {Array.|undefined} callFrames + */ + function didEditScriptSource(error, callFrames) + { + if (!error) + this._source = newSource; + callback(error, callFrames); + } + if (this.scriptId) { + // Script failed to parse. + DebuggerAgent.setScriptSource(this.scriptId, newSource, undefined, didEditScriptSource.bind(this)); + } else + callback("Script failed to parse"); + }, + + /** + * @return {boolean} + */ + isInlineScript: function() + { + return !!this.sourceURL && this.lineOffset !== 0 && this.columnOffset !== 0; + } +} +/* SidebarPane.js */ + +/* + * 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. + * 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. + */ + +/** + * @constructor + * @extends {WebInspector.Object} + */ +WebInspector.SidebarPane = function(title) +{ + this.element = document.createElement("div"); + this.element.className = "pane"; + + this.titleElement = document.createElement("div"); + this.titleElement.className = "title"; + this.titleElement.tabIndex = 0; + this.titleElement.addEventListener("click", this.toggleExpanded.bind(this), false); + this.titleElement.addEventListener("keydown", this._onTitleKeyDown.bind(this), false); + + this.bodyElement = document.createElement("div"); + this.bodyElement.className = "body"; + + this.element.appendChild(this.titleElement); + this.element.appendChild(this.bodyElement); + + this.title = title; + this.growbarVisible = false; + this.expanded = false; +} + +WebInspector.SidebarPane.prototype = { + get title() + { + return this._title; + }, + + set title(x) + { + if (this._title === x) + return; + this._title = x; + this.titleElement.textContent = x; + }, + + get growbarVisible() + { + return this._growbarVisible; + }, + + set growbarVisible(x) + { + if (this._growbarVisible === x) + return; + + this._growbarVisible = x; + + if (x && !this._growbarElement) { + this._growbarElement = document.createElement("div"); + this._growbarElement.className = "growbar"; + this.element.appendChild(this._growbarElement); + } else if (!x && this._growbarElement) { + if (this._growbarElement.parentNode) + this._growbarElement.parentNode(this._growbarElement); + delete this._growbarElement; + } + }, + + get expanded() + { + return this._expanded; + }, + + set expanded(x) + { + if (x) + this.expand(); + else + this.collapse(); + }, + + expand: function() + { + if (this._expanded) + return; + this._expanded = true; + this.element.addStyleClass("expanded"); + if (this.onexpand) + this.onexpand(this); + }, + + collapse: function() + { + if (!this._expanded) + return; + this._expanded = false; + this.element.removeStyleClass("expanded"); + if (this.oncollapse) + this.oncollapse(this); + }, + + toggleExpanded: function() + { + this.expanded = !this.expanded; + }, + + _onTitleKeyDown: function(event) + { + if (isEnterKey(event) || event.keyCode === WebInspector.KeyboardShortcut.Keys.Space.code) + this.toggleExpanded(); + } +} + +WebInspector.SidebarPane.prototype.__proto__ = WebInspector.Object.prototype; +/* ElementsTreeOutline.js */ + +/* + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008 Matt Lilek + * Copyright (C) 2009 Joseph Pecoraro + * + * 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. + */ + +/** + * @constructor + * @extends {TreeOutline} + * @param {boolean=} omitRootDOMNode + * @param {boolean=} selectEnabled + * @param {boolean=} showInElementsPanelEnabled + * @param {function(WebInspector.ContextMenu, WebInspector.DOMNode)=} contextMenuCallback + */ +WebInspector.ElementsTreeOutline = function(omitRootDOMNode, selectEnabled, showInElementsPanelEnabled, contextMenuCallback) +{ + this.element = document.createElement("ol"); + this.element.addEventListener("mousedown", this._onmousedown.bind(this), false); + this.element.addEventListener("mousemove", this._onmousemove.bind(this), false); + this.element.addEventListener("mouseout", this._onmouseout.bind(this), false); + this.element.addEventListener("dragstart", this._ondragstart.bind(this), false); + this.element.addEventListener("dragover", this._ondragover.bind(this), false); + this.element.addEventListener("dragleave", this._ondragleave.bind(this), false); + this.element.addEventListener("drop", this._ondrop.bind(this), false); + this.element.addEventListener("dragend", this._ondragend.bind(this), false); + + TreeOutline.call(this, this.element); + + this._includeRootDOMNode = !omitRootDOMNode; + this._selectEnabled = selectEnabled; + this._showInElementsPanelEnabled = showInElementsPanelEnabled; + this._rootDOMNode = null; + this._selectDOMNode = null; + this._eventSupport = new WebInspector.Object(); + this._editing = false; + + this._visible = false; + + this.element.addEventListener("contextmenu", this._contextMenuEventFired.bind(this), true); + this._contextMenuCallback = contextMenuCallback; +} + +WebInspector.ElementsTreeOutline.Events = { + SelectedNodeChanged: "SelectedNodeChanged" +} + +WebInspector.ElementsTreeOutline.prototype = { + wireToDomAgent: function() + { + this._elementsTreeUpdater = new WebInspector.ElementsTreeUpdater(this); + }, + + setVisible: function(visible) + { + this._visible = visible; + if (!this._visible) + return; + + this._updateModifiedNodes(); + if (this._selectedDOMNode) + this._revealAndSelectNode(this._selectedDOMNode, false); + }, + + addEventListener: function(eventType, listener, thisObject) + { + this._eventSupport.addEventListener(eventType, listener, thisObject); + }, + + removeEventListener: function(eventType, listener, thisObject) + { + this._eventSupport.removeEventListener(eventType, listener, thisObject); + }, + + get rootDOMNode() + { + return this._rootDOMNode; + }, + + set rootDOMNode(x) + { + if (this._rootDOMNode === x) + return; + + this._rootDOMNode = x; + + this._isXMLMimeType = x && x.isXMLNode(); + + this.update(); + }, + + get isXMLMimeType() + { + return this._isXMLMimeType; + }, + + selectedDOMNode: function() + { + return this._selectedDOMNode; + }, + + selectDOMNode: function(node, focus) + { + if (this._selectedDOMNode === node) { + this._revealAndSelectNode(node, !focus); + return; + } + + this._selectedDOMNode = node; + this._revealAndSelectNode(node, !focus); + + // The _revealAndSelectNode() method might find a different element if there is inlined text, + // and the select() call would change the selectedDOMNode and reenter this setter. So to + // avoid calling _selectedNodeChanged() twice, first check if _selectedDOMNode is the same + // node as the one passed in. + if (this._selectedDOMNode === node) + this._selectedNodeChanged(); + }, + + get editing() + { + return this._editing; + }, + + update: function() + { + var selectedNode = this.selectedTreeElement ? this.selectedTreeElement.representedObject : null; + + this.removeChildren(); + + if (!this.rootDOMNode) + return; + + var treeElement; + if (this._includeRootDOMNode) { + treeElement = new WebInspector.ElementsTreeElement(this.rootDOMNode); + treeElement.selectable = this._selectEnabled; + this.appendChild(treeElement); + } else { + // FIXME: this could use findTreeElement to reuse a tree element if it already exists + var node = this.rootDOMNode.firstChild; + while (node) { + treeElement = new WebInspector.ElementsTreeElement(node); + treeElement.selectable = this._selectEnabled; + this.appendChild(treeElement); + node = node.nextSibling; + } + } + + if (selectedNode) + this._revealAndSelectNode(selectedNode, true); + }, + + updateSelection: function() + { + if (!this.selectedTreeElement) + return; + var element = this.treeOutline.selectedTreeElement; + element.updateSelection(); + }, + + _selectedNodeChanged: function() + { + this._eventSupport.dispatchEventToListeners(WebInspector.ElementsTreeOutline.Events.SelectedNodeChanged, this._selectedDOMNode); + }, + + findTreeElement: function(node) + { + function isAncestorNode(ancestor, node) + { + return ancestor.isAncestor(node); + } + + function parentNode(node) + { + return node.parentNode; + } + + var treeElement = TreeOutline.prototype.findTreeElement.call(this, node, isAncestorNode, parentNode); + if (!treeElement && node.nodeType() === Node.TEXT_NODE) { + // The text node might have been inlined if it was short, so try to find the parent element. + treeElement = TreeOutline.prototype.findTreeElement.call(this, node.parentNode, isAncestorNode, parentNode); + } + + return treeElement; + }, + + createTreeElementFor: function(node) + { + var treeElement = this.findTreeElement(node); + if (treeElement) + return treeElement; + if (!node.parentNode) + return null; + + treeElement = this.createTreeElementFor(node.parentNode); + if (treeElement && treeElement.showChild(node.index)) + return treeElement.children[node.index]; + + return null; + }, + + set suppressRevealAndSelect(x) + { + if (this._suppressRevealAndSelect === x) + return; + this._suppressRevealAndSelect = x; + }, + + _revealAndSelectNode: function(node, omitFocus) + { + if (!node || this._suppressRevealAndSelect) + return; + + var treeElement = this.createTreeElementFor(node); + if (!treeElement) + return; + + treeElement.revealAndSelect(omitFocus); + }, + + _treeElementFromEvent: function(event) + { + var scrollContainer = this.element.parentElement; + + // We choose this X coordinate based on the knowledge that our list + // items extend at least to the right edge of the outer
    container. + // In the no-word-wrap mode the outer
      may be wider than the tree container + // (and partially hidden), in which case we are left to use only its right boundary. + var x = scrollContainer.totalOffsetLeft() + scrollContainer.offsetWidth - 36; + + var y = event.pageY; + + // Our list items have 1-pixel cracks between them vertically. We avoid + // the cracks by checking slightly above and slightly below the mouse + // and seeing if we hit the same element each time. + var elementUnderMouse = this.treeElementFromPoint(x, y); + var elementAboveMouse = this.treeElementFromPoint(x, y - 2); + var element; + if (elementUnderMouse === elementAboveMouse) + element = elementUnderMouse; + else + element = this.treeElementFromPoint(x, y + 2); + + return element; + }, + + _onmousedown: function(event) + { + var element = this._treeElementFromEvent(event); + + if (!element || element.isEventWithinDisclosureTriangle(event)) + return; + + element.select(); + }, + + _onmousemove: function(event) + { + var element = this._treeElementFromEvent(event); + if (element && this._previousHoveredElement === element) + return; + + if (this._previousHoveredElement) { + this._previousHoveredElement.hovered = false; + delete this._previousHoveredElement; + } + + if (element) { + element.hovered = true; + this._previousHoveredElement = element; + + // Lazily compute tag-specific tooltips. + if (element.representedObject && !element.tooltip) + element._createTooltipForNode(); + } + + WebInspector.domAgent.highlightDOMNode(element ? element.representedObject.id : 0); + }, + + _onmouseout: function(event) + { + var nodeUnderMouse = document.elementFromPoint(event.pageX, event.pageY); + if (nodeUnderMouse && nodeUnderMouse.isDescendant(this.element)) + return; + + if (this._previousHoveredElement) { + this._previousHoveredElement.hovered = false; + delete this._previousHoveredElement; + } + + WebInspector.domAgent.hideDOMNodeHighlight(); + }, + + _ondragstart: function(event) + { + var treeElement = this._treeElementFromEvent(event); + if (!treeElement) + return false; + + if (!this._isValidDragSourceOrTarget(treeElement)) + return false; + + if (treeElement.representedObject.nodeName() === "BODY" || treeElement.representedObject.nodeName() === "HEAD") + return false; + + event.dataTransfer.setData("text/plain", treeElement.listItemElement.textContent); + event.dataTransfer.effectAllowed = "copyMove"; + this._nodeBeingDragged = treeElement.representedObject; + + WebInspector.domAgent.hideDOMNodeHighlight(); + + return true; + }, + + _ondragover: function(event) + { + if (!this._nodeBeingDragged) + return false; + + var treeElement = this._treeElementFromEvent(event); + if (!this._isValidDragSourceOrTarget(treeElement)) + return false; + + var node = treeElement.representedObject; + while (node) { + if (node === this._nodeBeingDragged) + return false; + node = node.parentNode; + } + + treeElement.updateSelection(); + treeElement.listItemElement.addStyleClass("elements-drag-over"); + this._dragOverTreeElement = treeElement; + event.preventDefault(); + event.dataTransfer.dropEffect = 'move'; + return false; + }, + + _ondragleave: function(event) + { + this._clearDragOverTreeElementMarker(); + event.preventDefault(); + return false; + }, + + _isValidDragSourceOrTarget: function(treeElement) + { + if (!treeElement) + return false; + + var node = treeElement.representedObject; + if (!(node instanceof WebInspector.DOMNode)) + return false; + + if (!node.parentNode || node.parentNode.nodeType() !== Node.ELEMENT_NODE) + return false; + + return true; + }, + + _ondrop: function(event) + { + event.preventDefault(); + var treeElement = this._treeElementFromEvent(event); + if (this._nodeBeingDragged && treeElement) { + var parentNode; + var anchorNode; + + if (treeElement._elementCloseTag) { + // Drop onto closing tag -> insert as last child. + parentNode = treeElement.representedObject; + } else { + var dragTargetNode = treeElement.representedObject; + parentNode = dragTargetNode.parentNode; + anchorNode = dragTargetNode; + } + + function callback(error, newNodeId) + { + if (error) + return; + + this._updateModifiedNodes(); + var newNode = WebInspector.domAgent.nodeForId(newNodeId); + if (newNode) + this.selectDOMNode(newNode, true); + } + this._nodeBeingDragged.moveTo(parentNode, anchorNode, callback.bind(this)); + } + + delete this._nodeBeingDragged; + }, + + _ondragend: function(event) + { + event.preventDefault(); + this._clearDragOverTreeElementMarker(); + delete this._nodeBeingDragged; + }, + + _clearDragOverTreeElementMarker: function() + { + if (this._dragOverTreeElement) { + this._dragOverTreeElement.updateSelection(); + this._dragOverTreeElement.listItemElement.removeStyleClass("elements-drag-over"); + delete this._dragOverTreeElement; + } + }, + + _contextMenuEventFired: function(event) + { + if (!this._showInElementsPanelEnabled) + return; + + var treeElement = this._treeElementFromEvent(event); + if (!treeElement) + return; + + function focusElement() + { + WebInspector.domAgent.inspectElement(treeElement.representedObject.id); + } + var contextMenu = new WebInspector.ContextMenu(); + contextMenu.appendItem(WebInspector.UIString("Reveal in Elements Panel"), focusElement.bind(this)); + contextMenu.show(event); + }, + + populateContextMenu: function(contextMenu, event) + { + var treeElement = this._treeElementFromEvent(event); + if (!treeElement) + return false; + + var tag = event.target.enclosingNodeOrSelfWithClass("webkit-html-tag"); + var textNode = event.target.enclosingNodeOrSelfWithClass("webkit-html-text-node"); + var commentNode = event.target.enclosingNodeOrSelfWithClass("webkit-html-comment"); + var populated = WebInspector.populateHrefContextMenu(contextMenu, this.selectedDOMNode(), event); + if (tag && treeElement._populateTagContextMenu) { + if (populated) + contextMenu.appendSeparator(); + treeElement._populateTagContextMenu(contextMenu, event); + populated = true; + } else if (textNode && treeElement._populateTextContextMenu) { + if (populated) + contextMenu.appendSeparator(); + treeElement._populateTextContextMenu(contextMenu, textNode); + populated = true; + } else if (commentNode && treeElement._populateNodeContextMenu) { + if (populated) + contextMenu.appendSeparator(); + treeElement._populateNodeContextMenu(contextMenu, textNode); + populated = true; + } + + return populated; + }, + + adjustCollapsedRange: function() + { + }, + + _updateModifiedNodes: function() + { + if (this._elementsTreeUpdater) + this._elementsTreeUpdater._updateModifiedNodes(); + }, + + _populateContextMenu: function(contextMenu, node) + { + if (this._contextMenuCallback) + this._contextMenuCallback(contextMenu, node); + } +} + +WebInspector.ElementsTreeOutline.prototype.__proto__ = TreeOutline.prototype; + +/** + * @constructor + * @extends {TreeElement} + * @param {boolean=} elementCloseTag + */ +WebInspector.ElementsTreeElement = function(node, elementCloseTag) +{ + this._elementCloseTag = elementCloseTag; + var hasChildrenOverride = !elementCloseTag && node.hasChildNodes() && !this._showInlineText(node); + + // The title will be updated in onattach. + TreeElement.call(this, "", node, hasChildrenOverride); + + if (this.representedObject.nodeType() == Node.ELEMENT_NODE && !elementCloseTag) + this._canAddAttributes = true; + this._searchQuery = null; + this._expandedChildrenLimit = WebInspector.ElementsTreeElement.InitialChildrenLimit; +} + +WebInspector.ElementsTreeElement.InitialChildrenLimit = 500; + +// A union of HTML4 and HTML5-Draft elements that explicitly +// or implicitly (for HTML5) forbid the closing tag. +// FIXME: Revise once HTML5 Final is published. +WebInspector.ElementsTreeElement.ForbiddenClosingTagElements = [ + "area", "base", "basefont", "br", "canvas", "col", "command", "embed", "frame", + "hr", "img", "input", "isindex", "keygen", "link", "meta", "param", "source" +].keySet(); + +// These tags we do not allow editing their tag name. +WebInspector.ElementsTreeElement.EditTagBlacklist = [ + "html", "head", "body" +].keySet(); + +WebInspector.ElementsTreeElement.prototype = { + highlightSearchResults: function(searchQuery) + { + if (this._searchQuery !== searchQuery) { + this._updateSearchHighlight(false); + delete this._highlightResult; // A new search query. + } + + this._searchQuery = searchQuery; + this._searchHighlightsVisible = true; + this.updateTitle(true); + }, + + hideSearchHighlights: function() + { + delete this._searchHighlightsVisible; + this._updateSearchHighlight(false); + }, + + _updateSearchHighlight: function(show) + { + if (!this._highlightResult) + return; + + function updateEntryShow(entry) + { + switch (entry.type) { + case "added": + entry.parent.insertBefore(entry.node, entry.nextSibling); + break; + case "changed": + entry.node.textContent = entry.newText; + break; + } + } + + function updateEntryHide(entry) + { + switch (entry.type) { + case "added": + if (entry.node.parentElement) + entry.node.parentElement.removeChild(entry.node); + break; + case "changed": + entry.node.textContent = entry.oldText; + break; + } + } + + var updater = show ? updateEntryShow : updateEntryHide; + + for (var i = 0, size = this._highlightResult.length; i < size; ++i) + updater(this._highlightResult[i]); + }, + + get hovered() + { + return this._hovered; + }, + + set hovered(x) + { + if (this._hovered === x) + return; + + this._hovered = x; + + if (this.listItemElement) { + if (x) { + this.updateSelection(); + this.listItemElement.addStyleClass("hovered"); + } else { + this.listItemElement.removeStyleClass("hovered"); + } + } + }, + + get expandedChildrenLimit() + { + return this._expandedChildrenLimit; + }, + + set expandedChildrenLimit(x) + { + if (this._expandedChildrenLimit === x) + return; + + this._expandedChildrenLimit = x; + if (this.treeOutline && !this._updateChildrenInProgress) + this._updateChildren(true); + }, + + get expandedChildCount() + { + var count = this.children.length; + if (count && this.children[count - 1]._elementCloseTag) + count--; + if (count && this.children[count - 1].expandAllButton) + count--; + return count; + }, + + showChild: function(index) + { + if (this._elementCloseTag) + return; + + if (index >= this.expandedChildrenLimit) { + this._expandedChildrenLimit = index + 1; + this._updateChildren(true); + } + + // Whether index-th child is visible in the children tree + return this.expandedChildCount > index; + }, + + _createTooltipForNode: function() + { + var node = /** @type {WebInspector.DOMNode} */ this.representedObject; + if (!node.nodeName() || node.nodeName().toLowerCase() !== "img") + return; + + function setTooltip(result) + { + if (!result || result.type !== "string") + return; + + try { + var properties = JSON.parse(result.description); + var offsetWidth = properties[0]; + var offsetHeight = properties[1]; + var naturalWidth = properties[2]; + var naturalHeight = properties[3]; + if (offsetHeight === naturalHeight && offsetWidth === naturalWidth) + this.tooltip = WebInspector.UIString("%d \xd7 %d pixels", offsetWidth, offsetHeight); + else + this.tooltip = WebInspector.UIString("%d \xd7 %d pixels (Natural: %d \xd7 %d pixels)", offsetWidth, offsetHeight, naturalWidth, naturalHeight); + } catch (e) { + console.error(e); + } + } + + function resolvedNode(object) + { + if (!object) + return; + + function dimensions() + { + return "[" + this.offsetWidth + "," + this.offsetHeight + "," + this.naturalWidth + "," + this.naturalHeight + "]"; + } + + object.callFunction(dimensions, setTooltip.bind(this)); + object.release(); + } + WebInspector.RemoteObject.resolveNode(node, "", resolvedNode.bind(this)); + }, + + updateSelection: function() + { + var listItemElement = this.listItemElement; + if (!listItemElement) + return; + + if (document.body.offsetWidth <= 0) { + // The stylesheet hasn't loaded yet or the window is closed, + // so we can't calculate what is need. Return early. + return; + } + + if (!this.selectionElement) { + this.selectionElement = document.createElement("div"); + this.selectionElement.className = "selection selected"; + listItemElement.insertBefore(this.selectionElement, listItemElement.firstChild); + } + + this.selectionElement.style.height = listItemElement.offsetHeight + "px"; + }, + + onattach: function() + { + if (this._hovered) { + this.updateSelection(); + this.listItemElement.addStyleClass("hovered"); + } + + this.updateTitle(); + this._preventFollowingLinksOnDoubleClick(); + this.listItemElement.draggable = true; + }, + + _preventFollowingLinksOnDoubleClick: function() + { + var links = this.listItemElement.querySelectorAll("li > .webkit-html-tag > .webkit-html-attribute > .webkit-html-external-link, li > .webkit-html-tag > .webkit-html-attribute > .webkit-html-resource-link"); + if (!links) + return; + + for (var i = 0; i < links.length; ++i) + links[i].preventFollowOnDoubleClick = true; + }, + + onpopulate: function() + { + if (this.children.length || this._showInlineText(this.representedObject) || this._elementCloseTag) + return; + + this.updateChildren(); + }, + + /** + * @param {boolean=} fullRefresh + */ + updateChildren: function(fullRefresh) + { + if (this._elementCloseTag) + return; + this.representedObject.getChildNodes(this._updateChildren.bind(this, fullRefresh)); + }, + + /** + * @param {boolean=} closingTag + */ + insertChildElement: function(child, index, closingTag) + { + var newElement = new WebInspector.ElementsTreeElement(child, closingTag); + newElement.selectable = this.treeOutline._selectEnabled; + this.insertChild(newElement, index); + return newElement; + }, + + moveChild: function(child, targetIndex) + { + var wasSelected = child.selected; + this.removeChild(child); + this.insertChild(child, targetIndex); + if (wasSelected) + child.select(); + }, + + /** + * @param {boolean=} fullRefresh + */ + _updateChildren: function(fullRefresh) + { + if (this._updateChildrenInProgress || !this.treeOutline._visible) + return; + + this._updateChildrenInProgress = true; + var selectedNode = this.treeOutline.selectedDOMNode(); + var originalScrollTop = 0; + if (fullRefresh) { + var treeOutlineContainerElement = this.treeOutline.element.parentNode; + originalScrollTop = treeOutlineContainerElement.scrollTop; + var selectedTreeElement = this.treeOutline.selectedTreeElement; + if (selectedTreeElement && selectedTreeElement.hasAncestor(this)) + this.select(); + this.removeChildren(); + } + + var treeElement = this; + var treeChildIndex = 0; + var elementToSelect; + + function updateChildrenOfNode(node) + { + var treeOutline = treeElement.treeOutline; + var child = node.firstChild; + while (child) { + var currentTreeElement = treeElement.children[treeChildIndex]; + if (!currentTreeElement || currentTreeElement.representedObject !== child) { + // Find any existing element that is later in the children list. + var existingTreeElement = null; + for (var i = (treeChildIndex + 1), size = treeElement.expandedChildCount; i < size; ++i) { + if (treeElement.children[i].representedObject === child) { + existingTreeElement = treeElement.children[i]; + break; + } + } + + if (existingTreeElement && existingTreeElement.parent === treeElement) { + // If an existing element was found and it has the same parent, just move it. + treeElement.moveChild(existingTreeElement, treeChildIndex); + } else { + // No existing element found, insert a new element. + if (treeChildIndex < treeElement.expandedChildrenLimit) { + var newElement = treeElement.insertChildElement(child, treeChildIndex); + if (child === selectedNode) + elementToSelect = newElement; + if (treeElement.expandedChildCount > treeElement.expandedChildrenLimit) + treeElement.expandedChildrenLimit++; + } + } + } + + child = child.nextSibling; + ++treeChildIndex; + } + } + + // Remove any tree elements that no longer have this node (or this node's contentDocument) as their parent. + for (var i = (this.children.length - 1); i >= 0; --i) { + var currentChild = this.children[i]; + var currentNode = currentChild.representedObject; + var currentParentNode = currentNode.parentNode; + + if (currentParentNode === this.representedObject) + continue; + + var selectedTreeElement = this.treeOutline.selectedTreeElement; + if (selectedTreeElement && (selectedTreeElement === currentChild || selectedTreeElement.hasAncestor(currentChild))) + this.select(); + + this.removeChildAtIndex(i); + } + + updateChildrenOfNode(this.representedObject); + this.adjustCollapsedRange(); + + var lastChild = this.children[this.children.length - 1]; + if (this.representedObject.nodeType() == Node.ELEMENT_NODE && (!lastChild || !lastChild._elementCloseTag)) + this.insertChildElement(this.representedObject, this.children.length, true); + + // We want to restore the original selection and tree scroll position after a full refresh, if possible. + if (fullRefresh && elementToSelect) { + elementToSelect.select(); + if (treeOutlineContainerElement && originalScrollTop <= treeOutlineContainerElement.scrollHeight) + treeOutlineContainerElement.scrollTop = originalScrollTop; + } + + delete this._updateChildrenInProgress; + }, + + adjustCollapsedRange: function() + { + // Ensure precondition: only the tree elements for node children are found in the tree + // (not the Expand All button or the closing tag). + if (this.expandAllButtonElement && this.expandAllButtonElement.__treeElement.parent) + this.removeChild(this.expandAllButtonElement.__treeElement); + + const node = this.representedObject; + if (!node.children) + return; + const childNodeCount = node.children.length; + + // In case some nodes from the expanded range were removed, pull some nodes from the collapsed range into the expanded range at the bottom. + for (var i = this.expandedChildCount, limit = Math.min(this.expandedChildrenLimit, childNodeCount); i < limit; ++i) + this.insertChildElement(node.children[i], i); + + const expandedChildCount = this.expandedChildCount; + if (childNodeCount > this.expandedChildCount) { + var targetButtonIndex = expandedChildCount; + if (!this.expandAllButtonElement) { + var button = document.createElement("button"); + button.className = "show-all-nodes"; + button.value = ""; + var item = new TreeElement(button, null, false); + item.selectable = false; + item.expandAllButton = true; + this.insertChild(item, targetButtonIndex); + this.expandAllButtonElement = item.listItemElement.firstChild; + this.expandAllButtonElement.__treeElement = item; + this.expandAllButtonElement.addEventListener("click", this.handleLoadAllChildren.bind(this), false); + } else if (!this.expandAllButtonElement.__treeElement.parent) + this.insertChild(this.expandAllButtonElement.__treeElement, targetButtonIndex); + this.expandAllButtonElement.textContent = WebInspector.UIString("Show All Nodes (%d More)", childNodeCount - expandedChildCount); + } else if (this.expandAllButtonElement) + delete this.expandAllButtonElement; + }, + + handleLoadAllChildren: function() + { + this.expandedChildrenLimit = Math.max(this.representedObject._childNodeCount, this.expandedChildrenLimit + WebInspector.ElementsTreeElement.InitialChildrenLimit); + }, + + onexpand: function() + { + if (this._elementCloseTag) + return; + + this.updateTitle(); + this.treeOutline.updateSelection(); + }, + + oncollapse: function() + { + if (this._elementCloseTag) + return; + + this.updateTitle(); + this.treeOutline.updateSelection(); + }, + + onreveal: function() + { + if (this.listItemElement) { + var tagSpans = this.listItemElement.getElementsByClassName("webkit-html-tag-name"); + if (tagSpans.length) + tagSpans[0].scrollIntoViewIfNeeded(false); + else + this.listItemElement.scrollIntoViewIfNeeded(false); + } + }, + + onselect: function(treeElement, selectedByUser) + { + this.treeOutline.suppressRevealAndSelect = true; + this.treeOutline.selectDOMNode(this.representedObject, selectedByUser); + if (selectedByUser) + WebInspector.domAgent.highlightDOMNode(this.representedObject.id); + this.updateSelection(); + this.treeOutline.suppressRevealAndSelect = false; + }, + + ondelete: function() + { + var startTagTreeElement = this.treeOutline.findTreeElement(this.representedObject); + startTagTreeElement ? startTagTreeElement.remove() : this.remove(); + return true; + }, + + onenter: function() + { + // On Enter or Return start editing the first attribute + // or create a new attribute on the selected element. + if (this.treeOutline.editing) + return false; + + this._startEditing(); + + // prevent a newline from being immediately inserted + return true; + }, + + selectOnMouseDown: function(event) + { + TreeElement.prototype.selectOnMouseDown.call(this, event); + + if (this._editing) + return; + + if (this.treeOutline._showInElementsPanelEnabled) { + WebInspector.showPanel("elements"); + this.treeOutline.selectDOMNode(this.representedObject, true); + } + + // Prevent selecting the nearest word on double click. + if (event.detail >= 2) + event.preventDefault(); + }, + + ondblclick: function(event) + { + if (this._editing || this._elementCloseTag) + return; + + if (this._startEditingTarget(event.target)) + return; + + if (this.hasChildren && !this.expanded) + this.expand(); + }, + + _insertInLastAttributePosition: function(tag, node) + { + if (tag.getElementsByClassName("webkit-html-attribute").length > 0) + tag.insertBefore(node, tag.lastChild); + else { + var nodeName = tag.textContent.match(/^<(.*?)>$/)[1]; + tag.textContent = ''; + tag.appendChild(document.createTextNode('<'+nodeName)); + tag.appendChild(node); + tag.appendChild(document.createTextNode('>')); + } + + this.updateSelection(); + }, + + _startEditingTarget: function(eventTarget) + { + if (this.treeOutline.selectedDOMNode() != this.representedObject) + return; + + if (this.representedObject.nodeType() != Node.ELEMENT_NODE && this.representedObject.nodeType() != Node.TEXT_NODE) + return false; + + var textNode = eventTarget.enclosingNodeOrSelfWithClass("webkit-html-text-node"); + if (textNode) + return this._startEditingTextNode(textNode); + + var attribute = eventTarget.enclosingNodeOrSelfWithClass("webkit-html-attribute"); + if (attribute) + return this._startEditingAttribute(attribute, eventTarget); + + var tagName = eventTarget.enclosingNodeOrSelfWithClass("webkit-html-tag-name"); + if (tagName) + return this._startEditingTagName(tagName); + + var newAttribute = eventTarget.enclosingNodeOrSelfWithClass("add-attribute"); + if (newAttribute) + return this._addNewAttribute(); + + return false; + }, + + _populateTagContextMenu: function(contextMenu, event) + { + var attribute = event.target.enclosingNodeOrSelfWithClass("webkit-html-attribute"); + var newAttribute = event.target.enclosingNodeOrSelfWithClass("add-attribute"); + + // Add attribute-related actions. + contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Add attribute" : "Add Attribute"), this._addNewAttribute.bind(this)); + if (attribute && !newAttribute) + contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Edit attribute" : "Edit Attribute"), this._startEditingAttribute.bind(this, attribute, event.target)); + contextMenu.appendSeparator(); + + this._populateNodeContextMenu(contextMenu); + this.treeOutline._populateContextMenu(contextMenu, this.representedObject); + }, + + _populateTextContextMenu: function(contextMenu, textNode) + { + contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Edit text" : "Edit Text"), this._startEditingTextNode.bind(this, textNode)); + this._populateNodeContextMenu(contextMenu); + }, + + _populateNodeContextMenu: function(contextMenu) + { + // Add free-form node-related actions. + contextMenu.appendItem(WebInspector.UIString("Edit as HTML"), this._editAsHTML.bind(this)); + contextMenu.appendItem(WebInspector.UIString("Copy as HTML"), this._copyHTML.bind(this)); + contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Delete node" : "Delete Node"), this.remove.bind(this)); + }, + + _startEditing: function() + { + if (this.treeOutline.selectedDOMNode() !== this.representedObject) + return; + + var listItem = this._listItemNode; + + if (this._canAddAttributes) { + var attribute = listItem.getElementsByClassName("webkit-html-attribute")[0]; + if (attribute) + return this._startEditingAttribute(attribute, attribute.getElementsByClassName("webkit-html-attribute-value")[0]); + + return this._addNewAttribute(); + } + + if (this.representedObject.nodeType() === Node.TEXT_NODE) { + var textNode = listItem.getElementsByClassName("webkit-html-text-node")[0]; + if (textNode) + return this._startEditingTextNode(textNode); + return; + } + }, + + _addNewAttribute: function() + { + // Cannot just convert the textual html into an element without + // a parent node. Use a temporary span container for the HTML. + var container = document.createElement("span"); + this._buildAttributeDOM(container, " ", ""); + var attr = container.firstChild; + attr.style.marginLeft = "2px"; // overrides the .editing margin rule + attr.style.marginRight = "2px"; // overrides the .editing margin rule + + var tag = this.listItemElement.getElementsByClassName("webkit-html-tag")[0]; + this._insertInLastAttributePosition(tag, attr); + return this._startEditingAttribute(attr, attr); + }, + + _triggerEditAttribute: function(attributeName) + { + var attributeElements = this.listItemElement.getElementsByClassName("webkit-html-attribute-name"); + for (var i = 0, len = attributeElements.length; i < len; ++i) { + if (attributeElements[i].textContent === attributeName) { + for (var elem = attributeElements[i].nextSibling; elem; elem = elem.nextSibling) { + if (elem.nodeType !== Node.ELEMENT_NODE) + continue; + + if (elem.hasStyleClass("webkit-html-attribute-value")) + return this._startEditingAttribute(elem.parentNode, elem); + } + } + } + }, + + _startEditingAttribute: function(attribute, elementForSelection) + { + if (WebInspector.isBeingEdited(attribute)) + return true; + + var attributeNameElement = attribute.getElementsByClassName("webkit-html-attribute-name")[0]; + if (!attributeNameElement) + return false; + + var attributeName = attributeNameElement.textContent; + + function removeZeroWidthSpaceRecursive(node) + { + if (node.nodeType === Node.TEXT_NODE) { + node.nodeValue = node.nodeValue.replace(/\u200B/g, ""); + return; + } + + if (node.nodeType !== Node.ELEMENT_NODE) + return; + + for (var child = node.firstChild; child; child = child.nextSibling) + removeZeroWidthSpaceRecursive(child); + } + + // Remove zero-width spaces that were added by nodeTitleInfo. + removeZeroWidthSpaceRecursive(attribute); + + var config = new WebInspector.EditingConfig(this._attributeEditingCommitted.bind(this), this._editingCancelled.bind(this), attributeName); + this._editing = WebInspector.startEditing(attribute, config); + + window.getSelection().setBaseAndExtent(elementForSelection, 0, elementForSelection, 1); + + return true; + }, + + _startEditingTextNode: function(textNode) + { + if (WebInspector.isBeingEdited(textNode)) + return true; + + var config = new WebInspector.EditingConfig(this._textNodeEditingCommitted.bind(this), this._editingCancelled.bind(this)); + this._editing = WebInspector.startEditing(textNode, config); + window.getSelection().setBaseAndExtent(textNode, 0, textNode, 1); + + return true; + }, + + _startEditingTagName: function(tagNameElement) + { + if (!tagNameElement) { + tagNameElement = this.listItemElement.getElementsByClassName("webkit-html-tag-name")[0]; + if (!tagNameElement) + return false; + } + + var tagName = tagNameElement.textContent; + if (WebInspector.ElementsTreeElement.EditTagBlacklist[tagName.toLowerCase()]) + return false; + + if (WebInspector.isBeingEdited(tagNameElement)) + return true; + + var closingTagElement = this._distinctClosingTagElement(); + + function keyupListener(event) + { + if (closingTagElement) + closingTagElement.textContent = ""; + } + + function editingComitted(element, newTagName) + { + tagNameElement.removeEventListener('keyup', keyupListener, false); + this._tagNameEditingCommitted.apply(this, arguments); + } + + function editingCancelled() + { + tagNameElement.removeEventListener('keyup', keyupListener, false); + this._editingCancelled.apply(this, arguments); + } + + tagNameElement.addEventListener('keyup', keyupListener, false); + + var config = new WebInspector.EditingConfig(editingComitted.bind(this), editingCancelled.bind(this), tagName); + this._editing = WebInspector.startEditing(tagNameElement, config); + window.getSelection().setBaseAndExtent(tagNameElement, 0, tagNameElement, 1); + return true; + }, + + _startEditingAsHTML: function(commitCallback, error, initialValue) + { + if (error) + return; + if (this._htmlEditElement && WebInspector.isBeingEdited(this._htmlEditElement)) + return; + + this._htmlEditElement = document.createElement("div"); + this._htmlEditElement.className = "source-code elements-tree-editor"; + this._htmlEditElement.textContent = initialValue; + + // Hide header items. + var child = this.listItemElement.firstChild; + while (child) { + child.style.display = "none"; + child = child.nextSibling; + } + // Hide children item. + if (this._childrenListNode) + this._childrenListNode.style.display = "none"; + // Append editor. + this.listItemElement.appendChild(this._htmlEditElement); + + this.updateSelection(); + + function commit() + { + commitCallback(this._htmlEditElement.textContent); + dispose.call(this); + } + + function dispose() + { + this._editing = false; + + // Remove editor. + this.listItemElement.removeChild(this._htmlEditElement); + delete this._htmlEditElement; + // Unhide children item. + if (this._childrenListNode) + this._childrenListNode.style.removeProperty("display"); + // Unhide header items. + var child = this.listItemElement.firstChild; + while (child) { + child.style.removeProperty("display"); + child = child.nextSibling; + } + + this.updateSelection(); + } + + var config = new WebInspector.EditingConfig(commit.bind(this), dispose.bind(this)); + config.setMultiline(true); + this._editing = WebInspector.startEditing(this._htmlEditElement, config); + }, + + _attributeEditingCommitted: function(element, newText, oldText, attributeName, moveDirection) + { + this._editing = false; + + var treeOutline = this.treeOutline; + /** + * @param {Protocol.Error=} error + */ + function moveToNextAttributeIfNeeded(error) + { + if (error) + this._editingCancelled(element, attributeName); + + if (!moveDirection) + return; + + treeOutline._updateModifiedNodes(); + + // Search for the attribute's position, and then decide where to move to. + var attributes = this.representedObject.attributes(); + for (var i = 0; i < attributes.length; ++i) { + if (attributes[i].name !== attributeName) + continue; + + if (moveDirection === "backward") { + if (i === 0) + this._startEditingTagName(); + else + this._triggerEditAttribute(attributes[i - 1].name); + } else { + if (i === attributes.length - 1) + this._addNewAttribute(); + else + this._triggerEditAttribute(attributes[i + 1].name); + } + return; + } + + // Moving From the "New Attribute" position. + if (moveDirection === "backward") { + if (newText === " ") { + // Moving from "New Attribute" that was not edited + if (attributes.length > 0) + this._triggerEditAttribute(attributes[attributes.length - 1].name); + } else { + // Moving from "New Attribute" that holds new value + if (attributes.length > 1) + this._triggerEditAttribute(attributes[attributes.length - 2].name); + } + } else if (moveDirection === "forward") { + if (!/^\s*$/.test(newText)) + this._addNewAttribute(); + else + this._startEditingTagName(); + } + } + + if (oldText !== newText) + this.representedObject.setAttribute(attributeName, newText, moveToNextAttributeIfNeeded.bind(this)); + else + moveToNextAttributeIfNeeded.call(this); + }, + + _tagNameEditingCommitted: function(element, newText, oldText, tagName, moveDirection) + { + this._editing = false; + var self = this; + + function cancel() + { + var closingTagElement = self._distinctClosingTagElement(); + if (closingTagElement) + closingTagElement.textContent = ""; + + self._editingCancelled(element, tagName); + moveToNextAttributeIfNeeded.call(self); + } + + function moveToNextAttributeIfNeeded() + { + if (moveDirection !== "forward") { + this._addNewAttribute(); + return; + } + + var attributes = this.representedObject.attributes(); + if (attributes.length > 0) + this._triggerEditAttribute(attributes[0].name); + else + this._addNewAttribute(); + } + + newText = newText.trim(); + if (newText === oldText) { + cancel(); + return; + } + + var treeOutline = this.treeOutline; + var wasExpanded = this.expanded; + + function changeTagNameCallback(error, nodeId) + { + if (error || !nodeId) { + cancel(); + return; + } + + var node = WebInspector.domAgent.nodeForId(nodeId); + + // Select it and expand if necessary. We force tree update so that it processes dom events and is up to date. + treeOutline._updateModifiedNodes(); + treeOutline.selectDOMNode(node, true); + + var newTreeItem = treeOutline.findTreeElement(node); + if (wasExpanded) + newTreeItem.expand(); + + moveToNextAttributeIfNeeded.call(newTreeItem); + } + + this.representedObject.setNodeName(newText, changeTagNameCallback); + }, + + _textNodeEditingCommitted: function(element, newText) + { + this._editing = false; + + var textNode; + if (this.representedObject.nodeType() === Node.ELEMENT_NODE) { + // We only show text nodes inline in elements if the element only + // has a single child, and that child is a text node. + textNode = this.representedObject.firstChild; + } else if (this.representedObject.nodeType() == Node.TEXT_NODE) + textNode = this.representedObject; + + textNode.setNodeValue(newText, this.updateTitle.bind(this)); + }, + + _editingCancelled: function(element, context) + { + this._editing = false; + + // Need to restore attributes structure. + this.updateTitle(); + }, + + _distinctClosingTagElement: function() + { + // FIXME: Improve the Tree Element / Outline Abstraction to prevent crawling the DOM + + // For an expanded element, it will be the last element with class "close" + // in the child element list. + if (this.expanded) { + var closers = this._childrenListNode.querySelectorAll(".close"); + return closers[closers.length-1]; + } + + // Remaining cases are single line non-expanded elements with a closing + // tag, or HTML elements without a closing tag (such as
      ). Return + // null in the case where there isn't a closing tag. + var tags = this.listItemElement.getElementsByClassName("webkit-html-tag"); + return (tags.length === 1 ? null : tags[tags.length-1]); + }, + + /** + * @param {boolean=} onlySearchQueryChanged + */ + updateTitle: function(onlySearchQueryChanged) + { + // If we are editing, return early to prevent canceling the edit. + // After editing is committed updateTitle will be called. + if (this._editing) + return; + + if (onlySearchQueryChanged) { + if (this._highlightResult) + this._updateSearchHighlight(false); + } else { + var highlightElement = document.createElement("span"); + highlightElement.className = "highlight"; + highlightElement.appendChild(this._nodeTitleInfo(WebInspector.linkifyURLAsNode).titleDOM); + this.title = highlightElement; + delete this._highlightResult; + } + + delete this.selectionElement; + this.updateSelection(); + this._preventFollowingLinksOnDoubleClick(); + this._highlightSearchResults(); + }, + + /** + * @param {WebInspector.DOMNode=} node + * @param {function(string, string, string, boolean=, string=)=} linkify + */ + _buildAttributeDOM: function(parentElement, name, value, node, linkify) + { + var hasText = (value.length > 0); + var attrSpanElement = parentElement.createChild("span", "webkit-html-attribute"); + var attrNameElement = attrSpanElement.createChild("span", "webkit-html-attribute-name"); + attrNameElement.textContent = name; + + if (hasText) + attrSpanElement.appendChild(document.createTextNode("=\u200B\"")); + + if (linkify && (name === "src" || name === "href")) { + var rewrittenHref = WebInspector.resourceURLForRelatedNode(node, value); + value = value.replace(/([\/;:\)\]\}])/g, "$1\u200B"); + if (rewrittenHref === null) { + var attrValueElement = attrSpanElement.createChild("span", "webkit-html-attribute-value"); + attrValueElement.textContent = value; + } else { + if (value.indexOf("data:") === 0) + value = value.trimMiddle(60); + attrSpanElement.appendChild(linkify(rewrittenHref, value, "webkit-html-attribute-value", node.nodeName().toLowerCase() === "a")); + } + } else { + value = value.replace(/([\/;:\)\]\}])/g, "$1\u200B"); + var attrValueElement = attrSpanElement.createChild("span", "webkit-html-attribute-value"); + attrValueElement.textContent = value; + } + + if (hasText) + attrSpanElement.appendChild(document.createTextNode("\"")); + }, + + /** + * @param {function(string, string, string, boolean=, string=)=} linkify + */ + _buildTagDOM: function(parentElement, tagName, isClosingTag, isDistinctTreeElement, linkify) + { + var node = /** @type WebInspector.DOMNode */ this.representedObject; + var classes = [ "webkit-html-tag" ]; + if (isClosingTag && isDistinctTreeElement) + classes.push("close"); + var tagElement = parentElement.createChild("span", classes.join(" ")); + tagElement.appendChild(document.createTextNode("<")); + var tagNameElement = tagElement.createChild("span", isClosingTag ? "" : "webkit-html-tag-name"); + tagNameElement.textContent = (isClosingTag ? "/" : "") + tagName; + if (!isClosingTag && node.hasAttributes()) { + var attributes = node.attributes(); + for (var i = 0; i < attributes.length; ++i) { + var attr = attributes[i]; + tagElement.appendChild(document.createTextNode(" ")); + this._buildAttributeDOM(tagElement, attr.name, attr.value, node, linkify); + } + } + tagElement.appendChild(document.createTextNode(">")); + parentElement.appendChild(document.createTextNode("\u200B")); + }, + + _nodeTitleInfo: function(linkify) + { + var node = this.representedObject; + var info = {titleDOM: document.createDocumentFragment(), hasChildren: this.hasChildren}; + + switch (node.nodeType()) { + case Node.DOCUMENT_FRAGMENT_NODE: + info.titleDOM.appendChild(document.createTextNode("Document Fragment")); + break; + + case Node.ATTRIBUTE_NODE: + var value = node.value || "\u200B"; // Zero width space to force showing an empty value. + this._buildAttributeDOM(info.titleDOM, node.name, value); + break; + + case Node.ELEMENT_NODE: + var tagName = node.nodeNameInCorrectCase(); + if (this._elementCloseTag) { + this._buildTagDOM(info.titleDOM, tagName, true, true); + info.hasChildren = false; + break; + } + + this._buildTagDOM(info.titleDOM, tagName, false, false, linkify); + + var textChild = this._singleTextChild(node); + var showInlineText = textChild && textChild.nodeValue().length < Preferences.maxInlineTextChildLength; + + if (!this.expanded && (!showInlineText && (this.treeOutline.isXMLMimeType || !WebInspector.ElementsTreeElement.ForbiddenClosingTagElements[tagName]))) { + if (this.hasChildren) { + var textNodeElement = info.titleDOM.createChild("span", "webkit-html-text-node"); + textNodeElement.textContent = "\u2026"; + info.titleDOM.appendChild(document.createTextNode("\u200B")); + } + this._buildTagDOM(info.titleDOM, tagName, true, false); + } + + // If this element only has a single child that is a text node, + // just show that text and the closing tag inline rather than + // create a subtree for them + if (showInlineText) { + var textNodeElement = info.titleDOM.createChild("span", "webkit-html-text-node"); + textNodeElement.textContent = textChild.nodeValue(); + info.titleDOM.appendChild(document.createTextNode("\u200B")); + this._buildTagDOM(info.titleDOM, tagName, true, false); + info.hasChildren = false; + } + break; + + case Node.TEXT_NODE: + if (node.parentNode && node.parentNode.nodeName().toLowerCase() === "script") { + var newNode = info.titleDOM.createChild("span", "webkit-html-text-node webkit-html-js-node"); + newNode.textContent = node.nodeValue(); + + var javascriptSyntaxHighlighter = new WebInspector.DOMSyntaxHighlighter("text/javascript", true); + javascriptSyntaxHighlighter.syntaxHighlightNode(newNode); + } else if (node.parentNode && node.parentNode.nodeName().toLowerCase() === "style") { + var newNode = info.titleDOM.createChild("span", "webkit-html-text-node webkit-html-css-node"); + newNode.textContent = node.nodeValue(); + + var cssSyntaxHighlighter = new WebInspector.DOMSyntaxHighlighter("text/css", true); + cssSyntaxHighlighter.syntaxHighlightNode(newNode); + } else { + info.titleDOM.appendChild(document.createTextNode("\"")); + var textNodeElement = info.titleDOM.createChild("span", "webkit-html-text-node"); + textNodeElement.textContent = node.nodeValue(); + info.titleDOM.appendChild(document.createTextNode("\"")); + } + break; + + case Node.COMMENT_NODE: + var commentElement = info.titleDOM.createChild("span", "webkit-html-comment"); + commentElement.appendChild(document.createTextNode("")); + break; + + case Node.DOCUMENT_TYPE_NODE: + var docTypeElement = info.titleDOM.createChild("span", "webkit-html-doctype"); + docTypeElement.appendChild(document.createTextNode("")); + break; + + case Node.CDATA_SECTION_NODE: + var cdataElement = info.titleDOM.createChild("span", "webkit-html-text-node"); + cdataElement.appendChild(document.createTextNode("")); + break; + default: + var defaultElement = info.titleDOM.appendChild(document.createTextNode(node.nodeNameInCorrectCase().collapseWhitespace())); + } + + return info; + }, + + _singleTextChild: function(node) + { + if (!node) + return null; + + var firstChild = node.firstChild; + if (!firstChild || firstChild.nodeType() !== Node.TEXT_NODE) + return null; + + var sibling = firstChild.nextSibling; + return sibling ? null : firstChild; + }, + + _showInlineText: function(node) + { + if (node.nodeType() === Node.ELEMENT_NODE) { + var textChild = this._singleTextChild(node); + if (textChild && textChild.nodeValue().length < Preferences.maxInlineTextChildLength) + return true; + } + return false; + }, + + remove: function() + { + var parentElement = this.parent; + if (!parentElement) + return; + + var self = this; + function removeNodeCallback(error, removedNodeId) + { + if (error) + return; + + parentElement.removeChild(self); + parentElement.adjustCollapsedRange(); + } + + this.representedObject.removeNode(removeNodeCallback); + }, + + _editAsHTML: function() + { + var treeOutline = this.treeOutline; + var node = this.representedObject; + var parentNode = node.parentNode; + var index = node.index; + var wasExpanded = this.expanded; + + function selectNode(error, nodeId) + { + if (error) + return; + + // Select it and expand if necessary. We force tree update so that it processes dom events and is up to date. + treeOutline._updateModifiedNodes(); + + var newNode = parentNode ? parentNode.children[index] || parentNode : null; + if (!newNode) + return; + + treeOutline.selectDOMNode(newNode, true); + + if (wasExpanded) { + var newTreeItem = treeOutline.findTreeElement(newNode); + if (newTreeItem) + newTreeItem.expand(); + } + } + + function commitChange(value) + { + node.setOuterHTML(value, selectNode); + } + + node.getOuterHTML(this._startEditingAsHTML.bind(this, commitChange)); + }, + + _copyHTML: function() + { + this.representedObject.copyNode(); + }, + + _highlightSearchResults: function() + { + if (!this._searchQuery || !this._searchHighlightsVisible) + return; + if (this._highlightResult) { + this._updateSearchHighlight(true); + return; + } + + var text = this.listItemElement.textContent; + var regexObject = createPlainTextSearchRegex(this._searchQuery, "gi"); + + var offset = 0; + var match = regexObject.exec(text); + var matchRanges = []; + while (match) { + matchRanges.push({ offset: match.index, length: match[0].length }); + match = regexObject.exec(text); + } + + // Fall back for XPath, etc. matches. + if (!matchRanges.length) + matchRanges.push({ offset: 0, length: text.length }); + + this._highlightResult = []; + highlightSearchResults(this.listItemElement, matchRanges, this._highlightResult); + } +} + +WebInspector.ElementsTreeElement.prototype.__proto__ = TreeElement.prototype; + +/** + * @constructor + */ +WebInspector.ElementsTreeUpdater = function(treeOutline) +{ + WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.NodeInserted, this._nodeInserted, this); + WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.NodeRemoved, this._nodeRemoved, this); + WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.AttrModified, this._attributesUpdated, this); + WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.AttrRemoved, this._attributesUpdated, this); + WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.CharacterDataModified, this._characterDataModified, this); + WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.DocumentUpdated, this._documentUpdated, this); + WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.ChildNodeCountUpdated, this._childNodeCountUpdated, this); + + this._treeOutline = treeOutline; + this._recentlyModifiedNodes = []; +} + +WebInspector.ElementsTreeUpdater.prototype = { + _documentUpdated: function(event) + { + var inspectedRootDocument = event.data; + + this._reset(); + + if (!inspectedRootDocument) + return; + + this._treeOutline.rootDOMNode = inspectedRootDocument; + }, + + _attributesUpdated: function(event) + { + this._recentlyModifiedNodes.push({node: event.data.node, updated: true}); + if (this._treeOutline._visible) + this._updateModifiedNodesSoon(); + }, + + _characterDataModified: function(event) + { + this._recentlyModifiedNodes.push({node: event.data, updated: true}); + if (this._treeOutline._visible) + this._updateModifiedNodesSoon(); + }, + + _nodeInserted: function(event) + { + this._recentlyModifiedNodes.push({node: event.data, parent: event.data.parentNode, inserted: true}); + if (this._treeOutline._visible) + this._updateModifiedNodesSoon(); + }, + + _nodeRemoved: function(event) + { + this._recentlyModifiedNodes.push({node: event.data.node, parent: event.data.parent, removed: true}); + if (this._treeOutline._visible) + this._updateModifiedNodesSoon(); + }, + + _childNodeCountUpdated: function(event) + { + var treeElement = this._treeOutline.findTreeElement(event.data); + if (treeElement) + treeElement.hasChildren = event.data.hasChildNodes(); + }, + + _updateModifiedNodesSoon: function() + { + if (this._updateModifiedNodesTimeout) + return; + this._updateModifiedNodesTimeout = setTimeout(this._updateModifiedNodes.bind(this), 0); + }, + + _updateModifiedNodes: function() + { + if (this._updateModifiedNodesTimeout) { + clearTimeout(this._updateModifiedNodesTimeout); + delete this._updateModifiedNodesTimeout; + } + + var updatedParentTreeElements = []; + + for (var i = 0; i < this._recentlyModifiedNodes.length; ++i) { + var parent = this._recentlyModifiedNodes[i].parent; + var node = this._recentlyModifiedNodes[i].node; + + if (this._recentlyModifiedNodes[i].updated) { + var nodeItem = this._treeOutline.findTreeElement(node); + if (nodeItem) + nodeItem.updateTitle(); + continue; + } + + if (!parent) + continue; + + var parentNodeItem = this._treeOutline.findTreeElement(parent); + if (parentNodeItem && !parentNodeItem.alreadyUpdatedChildren) { + parentNodeItem.updateChildren(); + parentNodeItem.alreadyUpdatedChildren = true; + updatedParentTreeElements.push(parentNodeItem); + } + } + + for (var i = 0; i < updatedParentTreeElements.length; ++i) + delete updatedParentTreeElements[i].alreadyUpdatedChildren; + + this._recentlyModifiedNodes = []; + }, + + _reset: function() + { + this._treeOutline.rootDOMNode = null; + this._treeOutline.selectDOMNode(null, false); + WebInspector.domAgent.hideDOMNodeHighlight(); + this._recentlyModifiedNodes = []; + } +} +/* DOMPresentationUtils.js */ + +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008 Matt Lilek + * Copyright (C) 2009 Joseph Pecoraro + * + * 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. + */ + +WebInspector.DOMPresentationUtils = {} + +WebInspector.DOMPresentationUtils.decorateNodeLabel = function(node, parentElement) +{ + var title = node.nodeNameInCorrectCase(); + + var nameElement = document.createElement("span"); + nameElement.textContent = title; + parentElement.appendChild(nameElement); + + var idAttribute = node.getAttribute("id"); + if (idAttribute) { + var idElement = document.createElement("span"); + parentElement.appendChild(idElement); + + var part = "#" + idAttribute; + title += part; + idElement.appendChild(document.createTextNode(part)); + + // Mark the name as extra, since the ID is more important. + nameElement.className = "extra"; + } + + var classAttribute = node.getAttribute("class"); + if (classAttribute) { + var classes = classAttribute.split(/\s+/); + var foundClasses = {}; + + if (classes.length) { + var classesElement = document.createElement("span"); + classesElement.className = "extra"; + parentElement.appendChild(classesElement); + + for (var i = 0; i < classes.length; ++i) { + var className = classes[i]; + if (className && !(className in foundClasses)) { + var part = "." + className; + title += part; + classesElement.appendChild(document.createTextNode(part)); + foundClasses[className] = true; + } + } + } + } + parentElement.title = title; +} + +WebInspector.DOMPresentationUtils.linkifyNodeReference = function(node) +{ + var link = document.createElement("span"); + link.className = "node-link"; + WebInspector.DOMPresentationUtils.decorateNodeLabel(node, link); + + link.addEventListener("click", WebInspector.domAgent.inspectElement.bind(WebInspector.domAgent, node.id), false); + link.addEventListener("mouseover", WebInspector.domAgent.highlightDOMNode.bind(WebInspector.domAgent, node.id, ""), false); + link.addEventListener("mouseout", WebInspector.domAgent.hideDOMNodeHighlight.bind(WebInspector.domAgent), false); + + return link; +} + +WebInspector.DOMPresentationUtils.linkifyNodeById = function(nodeId) +{ + var node = WebInspector.domAgent.nodeForId(nodeId); + if (!node) + return document.createTextNode(WebInspector.UIString("")); + return WebInspector.DOMPresentationUtils.linkifyNodeReference(node); +} +/* SidebarTreeElement.js */ + +/* + * Copyright (C) 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 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 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. + */ + +/** + * @constructor + * @extends {TreeElement} + */ +WebInspector.SidebarSectionTreeElement = function(title, representedObject, hasChildren) +{ + TreeElement.call(this, title.escapeHTML(), representedObject || {}, hasChildren); + this.expand(); +} + +WebInspector.SidebarSectionTreeElement.prototype = { + selectable: false, + + collapse: function() + { + // Should not collapse as it is not selectable. + }, + + get smallChildren() + { + return this._smallChildren; + }, + + set smallChildren(x) + { + if (this._smallChildren === x) + return; + + this._smallChildren = x; + + if (this._smallChildren) + this._childrenListNode.addStyleClass("small"); + else + this._childrenListNode.removeStyleClass("small"); + }, + + onattach: function() + { + this._listItemNode.addStyleClass("sidebar-tree-section"); + }, + + onreveal: function() + { + if (this.listItemElement) + this.listItemElement.scrollIntoViewIfNeeded(false); + } +} + +WebInspector.SidebarSectionTreeElement.prototype.__proto__ = TreeElement.prototype; + +/** + * @constructor + * @extends {TreeElement} + * @param {string=} subtitle + * @param {Object=} representedObject + * @param {boolean=} hasChildren + */ +WebInspector.SidebarTreeElement = function(className, title, subtitle, representedObject, hasChildren) +{ + TreeElement.call(this, "", representedObject, hasChildren); + + if (hasChildren) { + this.disclosureButton = document.createElement("button"); + this.disclosureButton.className = "disclosure-button"; + } + + if (!this.iconElement) { + this.iconElement = document.createElement("img"); + this.iconElement.className = "icon"; + } + + this.statusElement = document.createElement("div"); + this.statusElement.className = "status"; + + this.titlesElement = document.createElement("div"); + this.titlesElement.className = "titles"; + + this.titleElement = document.createElement("span"); + this.titleElement.className = "title"; + this.titlesElement.appendChild(this.titleElement); + + this.subtitleElement = document.createElement("span"); + this.subtitleElement.className = "subtitle"; + this.titlesElement.appendChild(this.subtitleElement); + + this.className = className; + this.mainTitle = title; + this.subtitle = subtitle; +} + +WebInspector.SidebarTreeElement.prototype = { + get small() + { + return this._small; + }, + + set small(x) + { + this._small = x; + + if (this._listItemNode) { + if (this._small) + this._listItemNode.addStyleClass("small"); + else + this._listItemNode.removeStyleClass("small"); + } + }, + + get mainTitle() + { + return this._mainTitle; + }, + + set mainTitle(x) + { + this._mainTitle = x; + this.refreshTitles(); + }, + + get subtitle() + { + return this._subtitle; + }, + + set subtitle(x) + { + this._subtitle = x; + this.refreshTitles(); + }, + + get bubbleText() + { + return this._bubbleText; + }, + + set bubbleText(x) + { + if (!this.bubbleElement) { + this.bubbleElement = document.createElement("div"); + this.bubbleElement.className = "bubble"; + this.statusElement.appendChild(this.bubbleElement); + } + + this._bubbleText = x; + this.bubbleElement.textContent = x; + }, + + set wait(x) + { + if (x) + this._listItemNode.addStyleClass("wait"); + else + this._listItemNode.removeStyleClass("wait"); + }, + + refreshTitles: function() + { + var mainTitle = this.mainTitle; + if (this.titleElement.textContent !== mainTitle) + this.titleElement.textContent = mainTitle; + + var subtitle = this.subtitle; + if (subtitle) { + if (this.subtitleElement.textContent !== subtitle) + this.subtitleElement.textContent = subtitle; + this.titlesElement.removeStyleClass("no-subtitle"); + } else { + this.subtitleElement.textContent = ""; + this.titlesElement.addStyleClass("no-subtitle"); + } + }, + + isEventWithinDisclosureTriangle: function(event) + { + return event.target === this.disclosureButton; + }, + + onattach: function() + { + this._listItemNode.addStyleClass("sidebar-tree-item"); + + if (this.className) + this._listItemNode.addStyleClass(this.className); + + if (this.small) + this._listItemNode.addStyleClass("small"); + + if (this.hasChildren && this.disclosureButton) + this._listItemNode.appendChild(this.disclosureButton); + + this._listItemNode.appendChild(this.iconElement); + this._listItemNode.appendChild(this.statusElement); + this._listItemNode.appendChild(this.titlesElement); + }, + + onreveal: function() + { + if (this._listItemNode) + this._listItemNode.scrollIntoViewIfNeeded(false); + } +} + +WebInspector.SidebarTreeElement.prototype.__proto__ = TreeElement.prototype; +/* Section.js */ + +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * 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: + * + * 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. + */ + +/** + * @constructor + * @param {string=} subtitle + */ +WebInspector.Section = function(title, subtitle) +{ + this.element = document.createElement("div"); + this.element.className = "section"; + this.element._section = this; + + this.headerElement = document.createElement("div"); + this.headerElement.className = "header"; + + this.titleElement = document.createElement("div"); + this.titleElement.className = "title"; + + this.subtitleElement = document.createElement("div"); + this.subtitleElement.className = "subtitle"; + + this.headerElement.appendChild(this.subtitleElement); + this.headerElement.appendChild(this.titleElement); + + this.headerElement.addEventListener("click", this.handleClick.bind(this), false); + this.element.appendChild(this.headerElement); + + this.title = title; + this.subtitle = subtitle; + this._expanded = false; +} + +WebInspector.Section.prototype = { + get title() + { + return this._title; + }, + + set title(x) + { + if (this._title === x) + return; + this._title = x; + + if (x instanceof Node) { + this.titleElement.removeChildren(); + this.titleElement.appendChild(x); + } else + this.titleElement.textContent = x; + }, + + get subtitle() + { + return this._subtitle; + }, + + set subtitle(x) + { + if (this._subtitle === x) + return; + this._subtitle = x; + this.subtitleElement.textContent = x; + }, + + get subtitleAsTextForTest() + { + var result = this.subtitleElement.textContent; + var child = this.subtitleElement.querySelector("[data-uncopyable]"); + if (child) { + var linkData = child.getAttribute("data-uncopyable"); + if (linkData) + result += linkData; + } + return result; + }, + + get expanded() + { + return this._expanded; + }, + + set expanded(x) + { + if (x) + this.expand(); + else + this.collapse(); + }, + + get populated() + { + return this._populated; + }, + + set populated(x) + { + this._populated = x; + if (!x && this._expanded) { + this.onpopulate(); + this._populated = true; + } + }, + + onpopulate: function() + { + // Overriden by subclasses. + }, + + get firstSibling() + { + var parent = this.element.parentElement; + if (!parent) + return null; + + var childElement = parent.firstChild; + while (childElement) { + if (childElement._section) + return childElement._section; + childElement = childElement.nextSibling; + } + + return null; + }, + + get lastSibling() + { + var parent = this.element.parentElement; + if (!parent) + return null; + + var childElement = parent.lastChild; + while (childElement) { + if (childElement._section) + return childElement._section; + childElement = childElement.previousSibling; + } + + return null; + }, + + get nextSibling() + { + var curElement = this.element; + do { + curElement = curElement.nextSibling; + } while (curElement && !curElement._section); + + return curElement ? curElement._section : null; + }, + + get previousSibling() + { + var curElement = this.element; + do { + curElement = curElement.previousSibling; + } while (curElement && !curElement._section); + + return curElement ? curElement._section : null; + }, + + expand: function() + { + if (this._expanded) + return; + this._expanded = true; + this.element.addStyleClass("expanded"); + + if (!this._populated) { + this.onpopulate(); + this._populated = true; + } + }, + + collapse: function() + { + if (!this._expanded) + return; + this._expanded = false; + this.element.removeStyleClass("expanded"); + }, + + toggleExpanded: function() + { + this.expanded = !this.expanded; + }, + + handleClick: function(e) + { + this.toggleExpanded(); + e.stopPropagation(); + } +} +/* PropertiesSection.js */ + +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * 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: + * + * 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. + */ + +/** + * @constructor + * @extends {WebInspector.Section} + * @param {string=} subtitle + */ +WebInspector.PropertiesSection = function(title, subtitle) +{ + WebInspector.Section.call(this, title, subtitle); + + this.headerElement.addStyleClass("monospace"); + this.propertiesElement = document.createElement("ol"); + this.propertiesElement.className = "properties properties-tree monospace"; + this.propertiesElement.tabIndex = 0; + this.propertiesTreeOutline = new TreeOutline(this.propertiesElement); + this.propertiesTreeOutline.section = this; + + this.element.appendChild(this.propertiesElement); +} + +WebInspector.PropertiesSection.prototype.__proto__ = WebInspector.Section.prototype; +/* RemoteObject.js */ + +/* + * 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. + */ + +/** + * @constructor + * @param {string|undefined} objectId + * @param {string} type + * @param {string|undefined} subtype + * @param {*} value + * @param {string=} description + */ +WebInspector.RemoteObject = function(objectId, type, subtype, value, description) +{ + this._type = type; + this._subtype = subtype; + if (objectId) { + // handle + this._objectId = objectId; + this._description = description; + this._hasChildren = true; + } else { + // Primitive or null object. + console.assert(type !== "object" || value === null); + this._description = description || (value + ""); + this._hasChildren = false; + this.value = value; + } +} + +/** + * @param {number|string|boolean} value + * @return {WebInspector.RemoteObject} + */ +WebInspector.RemoteObject.fromPrimitiveValue = function(value) +{ + return new WebInspector.RemoteObject(undefined, typeof value, undefined, value); +} + +/** + * @param {Object} value + * @return {WebInspector.RemoteObject} + */ +WebInspector.RemoteObject.fromLocalObject = function(value) +{ + return new WebInspector.LocalJSONObject(value); +} + +/** + * @param {WebInspector.DOMNode} node + * @param {string} objectGroup + * @param {function(?WebInspector.RemoteObject)} callback + */ +WebInspector.RemoteObject.resolveNode = function(node, objectGroup, callback) +{ + /** + * @param {?Protocol.Error} error + * @param {RuntimeAgent.RemoteObject} object + */ + function mycallback(error, object) + { + if (!callback) + return; + + if (error || !object) + callback(null); + else + callback(WebInspector.RemoteObject.fromPayload(object)); + } + DOMAgent.resolveNode(node.id, objectGroup, mycallback); +} + +/** + * @param {RuntimeAgent.RemoteObject} payload + * @return {WebInspector.RemoteObject} + */ +WebInspector.RemoteObject.fromPayload = function(payload) +{ + console.assert(typeof payload === "object", "Remote object payload should only be an object"); + + return new WebInspector.RemoteObject(payload.objectId, payload.type, payload.subtype, payload.value, payload.description); +} + +/** + * @param {WebInspector.RemoteObject} remoteObject + * @return {string} + */ +WebInspector.RemoteObject.type = function(remoteObject) +{ + if (remoteObject === null) + return "null"; + + var type = typeof remoteObject; + if (type !== "object" && type !== "function") + return type; + + return remoteObject.type; +} + +WebInspector.RemoteObject.prototype = { + /** @return {RuntimeAgent.RemoteObjectId} */ + get objectId() + { + return this._objectId; + }, + + /** @return {string} */ + get type() + { + return this._type; + }, + + /** @return {string|undefined} */ + get subtype() + { + return this._subtype; + }, + + /** @return {string|undefined} */ + get description() + { + return this._description; + }, + + /** @return {boolean} */ + get hasChildren() + { + return this._hasChildren; + }, + + /** + * @param {function(Array.)} callback + */ + getOwnProperties: function(callback) + { + this._getProperties(true, callback); + }, + + /** + * @param {function(Array.)} callback + */ + getAllProperties: function(callback) + { + this._getProperties(false, callback); + }, + + /** + * @param {boolean} ownProperties + * @param {function(Array.)} callback + */ + _getProperties: function(ownProperties, callback) + { + if (!this._objectId) { + callback([]); + return; + } + + /** + * @param {?Protocol.Error} error + * @param {Array.} properties + */ + function remoteObjectBinder(error, properties) + { + if (error) { + callback(null); + return; + } + var result = []; + for (var i = 0; properties && i < properties.length; ++i) { + var property = properties[i]; + if (property.get || property.set) { + if (property.get) + result.push(new WebInspector.RemoteObjectProperty("get " + property.name, WebInspector.RemoteObject.fromPayload(property.get), property)); + if (property.set) + result.push(new WebInspector.RemoteObjectProperty("set " + property.name, WebInspector.RemoteObject.fromPayload(property.set), property)); + } else + result.push(new WebInspector.RemoteObjectProperty(property.name, WebInspector.RemoteObject.fromPayload(property.value), property)); + } + callback(result); + } + RuntimeAgent.getProperties(this._objectId, ownProperties, remoteObjectBinder); + }, + + /** + * @param {string} name + * @param {string} value + * @param {function(string=)} callback + */ + setPropertyValue: function(name, value, callback) + { + if (!this._objectId) { + callback("Can't set a property of non-object."); + return; + } + + RuntimeAgent.evaluate.invoke({expression:value, doNotPauseOnExceptions:true}, evaluatedCallback.bind(this)); + + /** + * @param {?Protocol.Error} error + * @param {RuntimeAgent.RemoteObject} result + * @param {boolean=} wasThrown + */ + function evaluatedCallback(error, result, wasThrown) + { + if (error || wasThrown) { + callback(error || result.description); + return; + } + + function setPropertyValue(propertyName, propertyValue) + { + this[propertyName] = propertyValue; + } + + delete result.description; // Optimize on traffic. + RuntimeAgent.callFunctionOn(this._objectId, setPropertyValue.toString(), [{ value:name }, result], undefined, propertySetCallback.bind(this)); + if (result._objectId) + RuntimeAgent.releaseObject(result._objectId); + } + + /** + * @param {?Protocol.Error} error + * @param {RuntimeAgent.RemoteObject} result + * @param {boolean=} wasThrown + */ + function propertySetCallback(error, result, wasThrown) + { + if (error || wasThrown) { + callback(error || result.description); + return; + } + callback(); + } + }, + + /** + * @param {function(DOMAgent.NodeId)} callback + */ + pushNodeToFrontend: function(callback) + { + if (this._objectId) + WebInspector.domAgent.pushNodeToFrontend(this._objectId, callback); + else + callback(0); + }, + + /** + * @param {string} functionDeclaration + * @param {function(?WebInspector.RemoteObject)} callback + */ + callFunction: function(functionDeclaration, callback) + { + function mycallback(error, result, wasThrown) + { + callback((error || wasThrown) ? null : WebInspector.RemoteObject.fromPayload(result)); + } + + RuntimeAgent.callFunctionOn(this._objectId, functionDeclaration.toString(), undefined, undefined, mycallback); + }, + + /** + * @param {string} functionDeclaration + * @param {function(*)} callback + */ + callFunctionJSON: function(functionDeclaration, callback) + { + function mycallback(error, result, wasThrown) + { + callback((error || wasThrown) ? null : result.value); + } + + RuntimeAgent.callFunctionOn(this._objectId, functionDeclaration.toString(), undefined, true, mycallback); + }, + + release: function() + { + RuntimeAgent.releaseObject(this._objectId); + } +} + +/** + * @constructor + * @param {string} name + * @param {WebInspector.RemoteObject} value + * @param {Object=} descriptor + */ +WebInspector.RemoteObjectProperty = function(name, value, descriptor) +{ + this.name = name; + this.value = value; + this.enumerable = descriptor ? !!descriptor.enumerable : true; + this.writable = descriptor ? !!descriptor.writable : true; + if (descriptor && descriptor.wasThrown) + this.wasThrown = true; +} + +/** + * @param {string} name + * @param {string} value + * @return {WebInspector.RemoteObjectProperty} + */ +WebInspector.RemoteObjectProperty.fromPrimitiveValue = function(name, value) +{ + return new WebInspector.RemoteObjectProperty(name, WebInspector.RemoteObject.fromPrimitiveValue(value)); +} + +// The below is a wrapper around a local object that provides an interface comaptible +// with RemoteObject, to be used by the UI code (primarily ObjectPropertiesSection). +// Note that only JSON-compliant objects are currently supported, as there's no provision +// for traversing prototypes, extracting class names via constuctor, handling properties +// or functions. + +/** + * @constructor + * @extends {WebInspector.RemoteObject} + * @param {Object} value + */ +WebInspector.LocalJSONObject = function(value) +{ + this._value = value; +} + +WebInspector.LocalJSONObject.prototype = { + /** + * @return {string} + */ + get description() + { + if (this._cachedDescription) + return this._cachedDescription; + + if (this.type === "object") { + switch (this.subtype) { + case "array": + function formatArrayItem(property) + { + return property.value.description; + } + this._cachedDescription = this._concatenate("[", "]", formatArrayItem); + break; + case "null": + this._cachedDescription = "null"; + break; + default: + function formatObjectItem(property) + { + return property.name + ":" + property.value.description; + } + this._cachedDescription = this._concatenate("{", "}", formatObjectItem); + } + } else + this._cachedDescription = String(this._value); + + return this._cachedDescription; + }, + + /** + * @param {string} prefix + * @param {string} suffix + * @return {string} + */ + _concatenate: function(prefix, suffix, formatProperty) + { + const previewChars = 100; + + var buffer = prefix; + var children = this._children(); + for (var i = 0; i < children.length; ++i) { + var itemDescription = formatProperty(children[i]); + if (buffer.length + itemDescription.length > previewChars) { + buffer += ",\u2026"; + break; + } + if (i) + buffer += ", "; + buffer += itemDescription; + } + buffer += suffix; + return buffer; + }, + + /** + * @return {string} + */ + get type() + { + return typeof this._value; + }, + + /** + * @return {string|undefined} + */ + get subtype() + { + if (this._value === null) + return "null"; + + if (this._value instanceof Array) + return "array"; + + return undefined; + }, + + /** + * @return {boolean} + */ + get hasChildren() + { + return typeof this._value === "object" && this._value !== null && !!Object.keys(this._value).length; + }, + + /** + * @param {function(Array.)} callback + */ + getOwnProperties: function(callback) + { + callback(this._children()); + }, + + /** + * @param {function(Array.)} callback + */ + getAllProperties: function(callback) + { + callback(this._children()); + }, + + /** + * @return {Array.} + */ + _children: function() + { + if (!this.hasChildren) + return []; + + function buildProperty(propName) + { + return new WebInspector.RemoteObjectProperty(propName, new WebInspector.LocalJSONObject(this._value[propName])); + } + if (!this._cachedChildren) + this._cachedChildren = Object.keys(this._value || {}).map(buildProperty.bind(this)); + return this._cachedChildren; + }, + + /** + * @return {boolean} + */ + isError: function() + { + return false; + } +} +/* ObjectPropertiesSection.js */ + +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2009 Joseph Pecoraro + * + * 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 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 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. + */ + +/** + * @constructor + * @extends {WebInspector.PropertiesSection} + * @param {*=} object + * @param {string=} title + * @param {string=} subtitle + * @param {string=} emptyPlaceholder + * @param {boolean=} ignoreHasOwnProperty + * @param {Array.=} extraProperties + * @param {function()=} treeElementConstructor + */ +WebInspector.ObjectPropertiesSection = function(object, title, subtitle, emptyPlaceholder, ignoreHasOwnProperty, extraProperties, treeElementConstructor) +{ + this.emptyPlaceholder = (emptyPlaceholder || WebInspector.UIString("No Properties")); + this.object = object; + this.ignoreHasOwnProperty = ignoreHasOwnProperty; + this.extraProperties = extraProperties; + this.treeElementConstructor = treeElementConstructor || WebInspector.ObjectPropertyTreeElement; + this.editable = true; + + WebInspector.PropertiesSection.call(this, title, subtitle); +} + +WebInspector.ObjectPropertiesSection.prototype = { + onpopulate: function() + { + this.update(); + }, + + update: function() + { + var self = this; + function callback(properties) + { + if (!properties) + return; + self.updateProperties(properties); + } + if (this.ignoreHasOwnProperty) + this.object.getAllProperties(callback); + else + this.object.getOwnProperties(callback); + }, + + updateProperties: function(properties, rootTreeElementConstructor, rootPropertyComparer) + { + if (!rootTreeElementConstructor) + rootTreeElementConstructor = this.treeElementConstructor; + + if (!rootPropertyComparer) + rootPropertyComparer = WebInspector.ObjectPropertiesSection.CompareProperties; + + if (this.extraProperties) + for (var i = 0; i < this.extraProperties.length; ++i) + properties.push(this.extraProperties[i]); + + properties.sort(rootPropertyComparer); + + this.propertiesTreeOutline.removeChildren(); + + for (var i = 0; i < properties.length; ++i) { + properties[i].parentObject = this.object; + this.propertiesTreeOutline.appendChild(new rootTreeElementConstructor(properties[i])); + } + + if (!this.propertiesTreeOutline.children.length) { + var title = document.createElement("div"); + title.className = "info"; + title.textContent = this.emptyPlaceholder; + var infoElement = new TreeElement(title, null, false); + this.propertiesTreeOutline.appendChild(infoElement); + } + this.propertiesForTest = properties; + } +} + +WebInspector.ObjectPropertiesSection.prototype.__proto__ = WebInspector.PropertiesSection.prototype; + +WebInspector.ObjectPropertiesSection.CompareProperties = function(propertyA, propertyB) +{ + var a = propertyA.name; + var b = propertyB.name; + if (a === "__proto__") + return 1; + if (b === "__proto__") + return -1; + + // if used elsewhere make sure to + // - convert a and b to strings (not needed here, properties are all strings) + // - check if a == b (not needed here, no two properties can be the same) + + var diff = 0; + var chunk = /^\d+|^\D+/; + var chunka, chunkb, anum, bnum; + while (diff === 0) { + if (!a && b) + return -1; + if (!b && a) + return 1; + chunka = a.match(chunk)[0]; + chunkb = b.match(chunk)[0]; + anum = !isNaN(chunka); + bnum = !isNaN(chunkb); + if (anum && !bnum) + return -1; + if (bnum && !anum) + return 1; + if (anum && bnum) { + diff = chunka - chunkb; + if (diff === 0 && chunka.length !== chunkb.length) { + if (!+chunka && !+chunkb) // chunks are strings of all 0s (special case) + return chunka.length - chunkb.length; + else + return chunkb.length - chunka.length; + } + } else if (chunka !== chunkb) + return (chunka < chunkb) ? -1 : 1; + a = a.substring(chunka.length); + b = b.substring(chunkb.length); + } + return diff; +} + +/** + * @constructor + * @extends {TreeElement} + */ +WebInspector.ObjectPropertyTreeElement = function(property) +{ + this.property = property; + + // Pass an empty title, the title gets made later in onattach. + TreeElement.call(this, "", null, false); + this.toggleOnClick = true; + this.selectable = false; +} + +WebInspector.ObjectPropertyTreeElement.prototype = { + onpopulate: function() + { + if (this.children.length && !this.shouldRefreshChildren) + return; + + var callback = function(properties) { + this.removeChildren(); + if (!properties) + return; + + properties.sort(WebInspector.ObjectPropertiesSection.CompareProperties); + for (var i = 0; i < properties.length; ++i) { + this.appendChild(new this.treeOutline.section.treeElementConstructor(properties[i])); + } + }; + this.property.value.getOwnProperties(callback.bind(this)); + }, + + ondblclick: function(event) + { + if (this.property.writable) + this.startEditing(); + }, + + onattach: function() + { + this.update(); + }, + + update: function() + { + this.nameElement = document.createElement("span"); + this.nameElement.className = "name"; + this.nameElement.textContent = this.property.name; + if (!this.property.enumerable) + this.nameElement.addStyleClass("dimmed"); + + var separatorElement = document.createElement("span"); + separatorElement.className = "separator"; + separatorElement.textContent = ": "; + + this.valueElement = document.createElement("span"); + this.valueElement.className = "value"; + + var description = this.property.value.description; + // Render \n as a nice unicode cr symbol. + if (this.property.wasThrown) + this.valueElement.textContent = "[Exception: " + description + "]"; + else if (this.property.value.type === "string" && typeof description === "string") { + this.valueElement.textContent = "\"" + description.replace(/\n/g, "\u21B5") + "\""; + this.valueElement._originalTextContent = "\"" + description + "\""; + } else if (this.property.value.type === "function" && typeof description === "string") { + this.valueElement.textContent = /.*/.exec(description)[0].replace(/ +$/g, ""); + this.valueElement._originalTextContent = description; + } else + this.valueElement.textContent = description; + + if (this.property.value.type === "function") + this.valueElement.addEventListener("contextmenu", this._functionContextMenuEventFired.bind(this), false); + + if (this.property.wasThrown) + this.valueElement.addStyleClass("error"); + if (this.property.value.subtype) + this.valueElement.addStyleClass("console-formatted-" + this.property.value.subtype); + else if (this.property.value.type) + this.valueElement.addStyleClass("console-formatted-" + this.property.value.type); + if (this.property.value.subtype === "node") + this.valueElement.addEventListener("contextmenu", this._contextMenuEventFired.bind(this), false); + + this.listItemElement.removeChildren(); + + this.listItemElement.appendChild(this.nameElement); + this.listItemElement.appendChild(separatorElement); + this.listItemElement.appendChild(this.valueElement); + this.hasChildren = this.property.value.hasChildren && !this.property.wasThrown; + }, + + _contextMenuEventFired: function(event) + { + function selectNode(nodeId) + { + if (nodeId) + WebInspector.domAgent.inspectElement(nodeId); + } + + function revealElement() + { + this.property.value.pushNodeToFrontend(selectNode); + } + + var contextMenu = new WebInspector.ContextMenu(); + contextMenu.appendItem(WebInspector.UIString("Reveal in Elements Panel"), revealElement.bind(this)); + contextMenu.show(event); + }, + + _functionContextMenuEventFired: function(event) + { + function didGetLocation(error, response) + { + if (error) { + console.error(error); + return; + } + WebInspector.panels.scripts.showFunctionDefinition(response); + } + + function revealFunction() + { + DebuggerAgent.getFunctionLocation(this.property.value.objectId, didGetLocation.bind(this)); + } + + var contextMenu = new WebInspector.ContextMenu(); + contextMenu.appendItem(WebInspector.UIString("Show function definition"), revealFunction.bind(this)); + contextMenu.show(event); + }, + + updateSiblings: function() + { + if (this.parent.root) + this.treeOutline.section.update(); + else + this.parent.shouldRefreshChildren = true; + }, + + startEditing: function() + { + if (WebInspector.isBeingEdited(this.valueElement) || !this.treeOutline.section.editable) + return; + + var context = { expanded: this.expanded }; + + // Lie about our children to prevent expanding on double click and to collapse subproperties. + this.hasChildren = false; + + this.listItemElement.addStyleClass("editing-sub-part"); + + // Edit original source. + if (typeof this.valueElement._originalTextContent === "string") + this.valueElement.textContent = this.valueElement._originalTextContent; + + var config = new WebInspector.EditingConfig(this.editingCommitted.bind(this), this.editingCancelled.bind(this), context); + WebInspector.startEditing(this.valueElement, config); + }, + + editingEnded: function(context) + { + this.listItemElement.scrollLeft = 0; + this.listItemElement.removeStyleClass("editing-sub-part"); + if (context.expanded) + this.expand(); + }, + + editingCancelled: function(element, context) + { + this.update(); + this.editingEnded(context); + }, + + editingCommitted: function(element, userInput, previousContent, context) + { + if (userInput === previousContent) + return this.editingCancelled(element, context); // nothing changed, so cancel + + this.applyExpression(userInput, true); + + this.editingEnded(context); + }, + + applyExpression: function(expression, updateInterface) + { + expression = expression.trim(); + var expressionLength = expression.length; + function callback(error) + { + if (!updateInterface) + return; + + if (error) + this.update(); + + if (!expressionLength) { + // The property was deleted, so remove this tree element. + this.parent.removeChild(this); + } else { + // Call updateSiblings since their value might be based on the value that just changed. + this.updateSiblings(); + } + }; + this.property.parentObject.setPropertyValue(this.property.name, expression.trim(), callback.bind(this)); + } +} + +WebInspector.ObjectPropertyTreeElement.prototype.__proto__ = TreeElement.prototype; +/* ObjectPopoverHelper.js */ + +/* + * Copyright (C) 2011 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. + */ + +/** + * @constructor + * @extends {WebInspector.PopoverHelper} + */ +WebInspector.ObjectPopoverHelper = function(panelElement, getAnchor, queryObject, onHide, disableOnClick) +{ + WebInspector.PopoverHelper.call(this, panelElement, getAnchor, this._showObjectPopover.bind(this), onHide, disableOnClick); + this._queryObject = queryObject; + panelElement.addEventListener("scroll", this.hidePopover.bind(this), true); +}; + +WebInspector.ObjectPopoverHelper.prototype = { + _showObjectPopover: function(element, popover) + { + function showObjectPopover(result, wasThrown) + { + if (popover.disposed) + return; + if (wasThrown) { + this.hidePopover(); + return; + } + var popoverContentElement = null; + if (result.type !== "object") { + popoverContentElement = document.createElement("span"); + popoverContentElement.className = "monospace console-formatted-" + result.type; + popoverContentElement.style.whiteSpace = "pre"; + popoverContentElement.textContent = result.description; + if (result.type === "string") + popoverContentElement.textContent = "\"" + popoverContentElement.textContent + "\""; + popover.show(popoverContentElement, element); + } else { + popoverContentElement = document.createElement("div"); + + this._titleElement = document.createElement("div"); + this._titleElement.className = "source-frame-popover-title monospace"; + this._titleElement.textContent = result.description; + popoverContentElement.appendChild(this._titleElement); + + var section = new WebInspector.ObjectPropertiesSection(result); + // For HTML DOM wrappers, append "#id" to title, if not empty. + if (result.description.substr(0, 4) === "HTML") { + this._sectionUpdateProperties = section.updateProperties.bind(section); + section.updateProperties = this._updateHTMLId.bind(this); + } + section.expanded = true; + section.element.addStyleClass("source-frame-popover-tree"); + section.headerElement.addStyleClass("hidden"); + popoverContentElement.appendChild(section.element); + + const popoverWidth = 300; + const popoverHeight = 250; + popover.show(popoverContentElement, element, popoverWidth, popoverHeight); + } + } + this._queryObject(element, showObjectPopover.bind(this)); + }, + + _updateHTMLId: function(properties, rootTreeElementConstructor, rootPropertyComparer) + { + for (var i = 0; i < properties.length; ++i) { + if (properties[i].name === "id") { + if (properties[i].value.description) + this._titleElement.textContent += "#" + properties[i].value.description; + break; + } + } + this._sectionUpdateProperties(properties, rootTreeElementConstructor, rootPropertyComparer); + } +} + +WebInspector.ObjectPopoverHelper.prototype.__proto__ = WebInspector.PopoverHelper.prototype; +/* BreakpointsSidebarPane.js */ + +/* + * Copyright (C) 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 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 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. + */ + +/** + * @constructor + * @extends {WebInspector.SidebarPane} + */ +WebInspector.JavaScriptBreakpointsSidebarPane = function(model, showSourceLineDelegate) +{ + WebInspector.SidebarPane.call(this, WebInspector.UIString("Breakpoints")); + + this._model = model; + this._showSourceLineDelegate = showSourceLineDelegate; + + this.listElement = document.createElement("ol"); + this.listElement.className = "breakpoint-list"; + + this.emptyElement = document.createElement("div"); + this.emptyElement.className = "info"; + this.emptyElement.textContent = WebInspector.UIString("No Breakpoints"); + + this.bodyElement.appendChild(this.emptyElement); + this.bodyElement.addEventListener("contextmenu", this._contextMenu.bind(this), false); + + this._items = {}; +} + +WebInspector.JavaScriptBreakpointsSidebarPane.prototype = { + addBreakpoint: function(breakpoint) + { + var breakpointItemId = this._createBreakpointItemId(breakpoint.uiSourceCode, breakpoint.lineNumber); + if (breakpointItemId in this._items) + return; + + var element = document.createElement("li"); + element.addStyleClass("cursor-pointer"); + element.addEventListener("contextmenu", this._breakpointContextMenu.bind(this, breakpoint), true); + element.addEventListener("click", this._breakpointClicked.bind(this, breakpoint), false); + + var checkbox = document.createElement("input"); + checkbox.className = "checkbox-elem"; + checkbox.type = "checkbox"; + checkbox.checked = breakpoint.enabled; + checkbox.addEventListener("click", this._breakpointCheckboxClicked.bind(this, breakpoint), false); + element.appendChild(checkbox); + + var url = breakpoint.uiSourceCode.url; + var displayName = url ? WebInspector.displayNameForURL(url) : WebInspector.UIString("(program)"); + var labelElement = document.createTextNode(displayName + ":" + (breakpoint.lineNumber + 1)); + element.appendChild(labelElement); + + var snippetElement = document.createElement("div"); + snippetElement.className = "source-text monospace"; + element.appendChild(snippetElement); + function didRequestContent(mimeType, content) + { + var lineEndings = content.lineEndings(); + if (breakpoint.lineNumber < lineEndings.length) + snippetElement.textContent = content.substring(lineEndings[breakpoint.lineNumber - 1], lineEndings[breakpoint.lineNumber]); + } + breakpoint.uiSourceCode.requestContent(didRequestContent.bind(this)); + + element._data = breakpoint; + var currentElement = this.listElement.firstChild; + while (currentElement) { + if (currentElement._data && this._compareBreakpoints(currentElement._data, element._data) > 0) + break; + currentElement = currentElement.nextSibling; + } + this._addListElement(element, currentElement); + + var breakpointItem = {}; + breakpointItem.element = element; + breakpointItem.checkbox = checkbox; + this._items[breakpointItemId] = breakpointItem; + + if (!this.expanded) + this.expanded = true; + }, + + removeBreakpoint: function(uiSourceCode, lineNumber) + { + var breakpointItemId = this._createBreakpointItemId(uiSourceCode, lineNumber); + var breakpointItem = this._items[breakpointItemId]; + if (!breakpointItem) + return; + delete this._items[breakpointItemId]; + this._removeListElement(breakpointItem.element); + }, + + highlightBreakpoint: function(uiSourceCode, lineNumber) + { + var breakpointItem = this._items[this._createBreakpointItemId(uiSourceCode, lineNumber)]; + if (!breakpointItem) + return; + breakpointItem.element.addStyleClass("breakpoint-hit"); + this._highlightedBreakpointItem = breakpointItem; + }, + + clearBreakpointHighlight: function() + { + if (this._highlightedBreakpointItem) { + this._highlightedBreakpointItem.element.removeStyleClass("breakpoint-hit"); + delete this._highlightedBreakpointItem; + } + }, + + _createBreakpointItemId: function(uiSourceCode, lineNumber) + { + return uiSourceCode.id + ":" + lineNumber; + }, + + _breakpointClicked: function(breakpoint, event) + { + this._showSourceLineDelegate(breakpoint.uiSourceCode, breakpoint.lineNumber); + }, + + _breakpointCheckboxClicked: function(breakpoint, event) + { + // Breakpoint element has it's own click handler. + event.stopPropagation(); + + this._model.setBreakpointEnabled(breakpoint.uiSourceCode, breakpoint.lineNumber, event.target.checked); + }, + + _breakpointContextMenu: function(breakpoint, event) + { + var contextMenu = new WebInspector.ContextMenu(); + + var removeHandler = this._model.removeBreakpoint.bind(this._model, breakpoint.uiSourceCode, breakpoint.lineNumber); + contextMenu.appendItem(WebInspector.UIString("Remove Breakpoint"), removeHandler); + var removeAllTitle = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Remove all JavaScript breakpoints" : "Remove All JavaScript Breakpoints"); + contextMenu.appendItem(removeAllTitle, this._model.removeAllBreakpoints.bind(this._model)); + + contextMenu.show(event); + }, + + _contextMenu: function(event) + { + var contextMenu = new WebInspector.ContextMenu(); + var removeAllTitle = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Remove all JavaScript breakpoints" : "Remove All JavaScript Breakpoints"); + contextMenu.appendItem(removeAllTitle, this._model.removeAllBreakpoints.bind(this._model)); + contextMenu.show(event); + }, + + _addListElement: function(element, beforeElement) + { + if (beforeElement) + this.listElement.insertBefore(element, beforeElement); + else { + if (!this.listElement.firstChild) { + this.bodyElement.removeChild(this.emptyElement); + this.bodyElement.appendChild(this.listElement); + } + this.listElement.appendChild(element); + } + }, + + _removeListElement: function(element) + { + this.listElement.removeChild(element); + if (!this.listElement.firstChild) { + this.bodyElement.removeChild(this.listElement); + this.bodyElement.appendChild(this.emptyElement); + } + }, + + _compare: function(x, y) + { + if (x !== y) + return x < y ? -1 : 1; + return 0; + }, + + _compareBreakpoints: function(b1, b2) + { + return this._compare(b1.url, b2.url) || this._compare(b1.lineNumber, b2.lineNumber); + }, + + reset: function() + { + this.listElement.removeChildren(); + if (this.listElement.parentElement) { + this.bodyElement.removeChild(this.listElement); + this.bodyElement.appendChild(this.emptyElement); + } + this._items = {}; + } +} + +WebInspector.JavaScriptBreakpointsSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype; + +/** + * @constructor + * @extends {WebInspector.SidebarPane} + */ +WebInspector.NativeBreakpointsSidebarPane = function(title) +{ + WebInspector.SidebarPane.call(this, title); + + this.listElement = document.createElement("ol"); + this.listElement.className = "breakpoint-list"; + + this.emptyElement = document.createElement("div"); + this.emptyElement.className = "info"; + this.emptyElement.textContent = WebInspector.UIString("No Breakpoints"); + + this.bodyElement.appendChild(this.emptyElement); +} + +WebInspector.NativeBreakpointsSidebarPane.prototype = { + _addListElement: function(element, beforeElement) + { + if (beforeElement) + this.listElement.insertBefore(element, beforeElement); + else { + if (!this.listElement.firstChild) { + this.bodyElement.removeChild(this.emptyElement); + this.bodyElement.appendChild(this.listElement); + } + this.listElement.appendChild(element); + } + }, + + _removeListElement: function(element) + { + this.listElement.removeChild(element); + if (!this.listElement.firstChild) { + this.bodyElement.removeChild(this.listElement); + this.bodyElement.appendChild(this.emptyElement); + } + }, + + _reset: function() + { + this.listElement.removeChildren(); + if (this.listElement.parentElement) { + this.bodyElement.removeChild(this.listElement); + this.bodyElement.appendChild(this.emptyElement); + } + } +} + +WebInspector.NativeBreakpointsSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype; + +/** + * @constructor + * @extends {WebInspector.NativeBreakpointsSidebarPane} + */ +WebInspector.XHRBreakpointsSidebarPane = function() +{ + WebInspector.NativeBreakpointsSidebarPane.call(this, WebInspector.UIString("XHR Breakpoints")); + + this._breakpointElements = {}; + + var addButton = document.createElement("button"); + addButton.className = "pane-title-button add"; + addButton.addEventListener("click", this._addButtonClicked.bind(this), false); + this.titleElement.appendChild(addButton); + + this._restoreBreakpoints(); +} + +WebInspector.XHRBreakpointsSidebarPane.prototype = { + _addButtonClicked: function(event) + { + event.stopPropagation(); + + this.expanded = true; + + var inputElementContainer = document.createElement("p"); + inputElementContainer.className = "breakpoint-condition"; + var inputElement = document.createElement("span"); + inputElementContainer.textContent = WebInspector.UIString("Break when URL contains:"); + inputElement.className = "editing"; + inputElement.id = "breakpoint-condition-input"; + inputElementContainer.appendChild(inputElement); + this._addListElement(inputElementContainer, this.listElement.firstChild); + + function finishEditing(accept, e, text) + { + this._removeListElement(inputElementContainer); + if (accept) { + this._setBreakpoint(text, true); + this._saveBreakpoints(); + } + } + + var config = new WebInspector.EditingConfig(finishEditing.bind(this, true), finishEditing.bind(this, false)); + WebInspector.startEditing(inputElement, config); + }, + + _setBreakpoint: function(url, enabled) + { + if (url in this._breakpointElements) + return; + + var element = document.createElement("li"); + element._url = url; + element.addEventListener("contextmenu", this._contextMenu.bind(this, url), true); + + var checkboxElement = document.createElement("input"); + checkboxElement.className = "checkbox-elem"; + checkboxElement.type = "checkbox"; + checkboxElement.checked = enabled; + checkboxElement.addEventListener("click", this._checkboxClicked.bind(this, url), false); + element._checkboxElement = checkboxElement; + element.appendChild(checkboxElement); + + var labelElement = document.createElement("span"); + if (!url) + labelElement.textContent = WebInspector.UIString("Any XHR"); + else + labelElement.textContent = WebInspector.UIString("URL contains \"%s\"", url); + labelElement.addStyleClass("cursor-auto"); + labelElement.addEventListener("dblclick", this._labelClicked.bind(this, url), false); + element.appendChild(labelElement); + + var currentElement = this.listElement.firstChild; + while (currentElement) { + if (currentElement._url && currentElement._url < element._url) + break; + currentElement = currentElement.nextSibling; + } + this._addListElement(element, currentElement); + this._breakpointElements[url] = element; + if (enabled) + DOMDebuggerAgent.setXHRBreakpoint(url); + }, + + _removeBreakpoint: function(url) + { + var element = this._breakpointElements[url]; + if (!element) + return; + + this._removeListElement(element); + delete this._breakpointElements[url]; + if (element._checkboxElement.checked) + DOMDebuggerAgent.removeXHRBreakpoint(url); + }, + + _contextMenu: function(url, event) + { + var contextMenu = new WebInspector.ContextMenu(); + function removeBreakpoint() + { + this._removeBreakpoint(url); + this._saveBreakpoints(); + } + contextMenu.appendItem(WebInspector.UIString("Remove Breakpoint"), removeBreakpoint.bind(this)); + contextMenu.show(event); + }, + + _checkboxClicked: function(url, event) + { + if (event.target.checked) + DOMDebuggerAgent.setXHRBreakpoint(url); + else + DOMDebuggerAgent.removeXHRBreakpoint(url); + this._saveBreakpoints(); + }, + + _labelClicked: function(url) + { + var element = this._breakpointElements[url]; + var inputElement = document.createElement("span"); + inputElement.className = "breakpoint-condition editing"; + inputElement.textContent = url; + this.listElement.insertBefore(inputElement, element); + element.addStyleClass("hidden"); + + function finishEditing(accept, e, text) + { + this._removeListElement(inputElement); + if (accept) { + this._removeBreakpoint(url); + this._setBreakpoint(text, element._checkboxElement.checked); + this._saveBreakpoints(); + } else + element.removeStyleClass("hidden"); + } + + WebInspector.startEditing(inputElement, new WebInspector.EditingConfig(finishEditing.bind(this, true), finishEditing.bind(this, false))); + }, + + highlightBreakpoint: function(url) + { + var element = this._breakpointElements[url]; + if (!element) + return; + this.expanded = true; + element.addStyleClass("breakpoint-hit"); + this._highlightedElement = element; + }, + + clearBreakpointHighlight: function() + { + if (this._highlightedElement) { + this._highlightedElement.removeStyleClass("breakpoint-hit"); + delete this._highlightedElement; + } + }, + + _saveBreakpoints: function() + { + var breakpoints = []; + for (var url in this._breakpointElements) + breakpoints.push({ url: url, enabled: this._breakpointElements[url]._checkboxElement.checked }); + WebInspector.settings.xhrBreakpoints.set(breakpoints); + }, + + _restoreBreakpoints: function() + { + var breakpoints = WebInspector.settings.xhrBreakpoints.get(); + for (var i = 0; i < breakpoints.length; ++i) { + var breakpoint = breakpoints[i]; + if (breakpoint && typeof breakpoint.url === "string") + this._setBreakpoint(breakpoint.url, breakpoint.enabled); + } + } +} + +WebInspector.XHRBreakpointsSidebarPane.prototype.__proto__ = WebInspector.NativeBreakpointsSidebarPane.prototype; + +/** + * @constructor + * @extends {WebInspector.SidebarPane} + */ +WebInspector.EventListenerBreakpointsSidebarPane = function() +{ + WebInspector.SidebarPane.call(this, WebInspector.UIString("Event Listener Breakpoints")); + + this.categoriesElement = document.createElement("ol"); + this.categoriesElement.tabIndex = 0; + this.categoriesElement.addStyleClass("properties-tree"); + this.categoriesElement.addStyleClass("event-listener-breakpoints"); + this.categoriesTreeOutline = new TreeOutline(this.categoriesElement); + this.bodyElement.appendChild(this.categoriesElement); + + this._breakpointItems = {}; + this._createCategory(WebInspector.UIString("Keyboard"), "listener", ["keydown", "keyup", "keypress", "textInput"]); + this._createCategory(WebInspector.UIString("Mouse"), "listener", ["click", "dblclick", "mousedown", "mouseup", "mouseover", "mousemove", "mouseout", "mousewheel"]); + // FIXME: uncomment following once inspector stops being drop targer in major ports. + // Otherwise, inspector page reacts on drop event and tries to load the event data. + // this._createCategory(WebInspector.UIString("Drag"), "listener", ["drag", "drop", "dragstart", "dragend", "dragenter", "dragleave", "dragover"]); + this._createCategory(WebInspector.UIString("Control"), "listener", ["resize", "scroll", "zoom", "focus", "blur", "select", "change", "submit", "reset"]); + this._createCategory(WebInspector.UIString("Clipboard"), "listener", ["copy", "cut", "paste", "beforecopy", "beforecut", "beforepaste"]); + this._createCategory(WebInspector.UIString("Load"), "listener", ["load", "unload", "abort", "error"]); + this._createCategory(WebInspector.UIString("DOM Mutation"), "listener", ["DOMActivate", "DOMFocusIn", "DOMFocusOut", "DOMAttrModified", "DOMCharacterDataModified", "DOMNodeInserted", "DOMNodeInsertedIntoDocument", "DOMNodeRemoved", "DOMNodeRemovedFromDocument", "DOMSubtreeModified", "DOMContentLoaded"]); + this._createCategory(WebInspector.UIString("Device"), "listener", ["deviceorientation", "devicemotion"]); + this._createCategory(WebInspector.UIString("Timer"), "instrumentation", ["setTimer", "clearTimer", "timerFired"]); + this._createCategory(WebInspector.UIString("Touch"), "instrumentation", ["touchstart", "touchmove", "touchend", "touchcancel"]); + + this._restoreBreakpoints(); +} + +WebInspector.EventListenerBreakpointsSidebarPane.eventNameForUI = function(eventName) +{ + if (!WebInspector.EventListenerBreakpointsSidebarPane._eventNamesForUI) { + WebInspector.EventListenerBreakpointsSidebarPane._eventNamesForUI = { + "instrumentation:setTimer": WebInspector.UIString("Set Timer"), + "instrumentation:clearTimer": WebInspector.UIString("Clear Timer"), + "instrumentation:timerFired": WebInspector.UIString("Timer Fired") + }; + } + return WebInspector.EventListenerBreakpointsSidebarPane._eventNamesForUI[eventName] || eventName.substring(eventName.indexOf(":") + 1); +} + +WebInspector.EventListenerBreakpointsSidebarPane.prototype = { + _createCategory: function(name, type, eventNames) + { + var categoryItem = {}; + categoryItem.element = new TreeElement(name); + this.categoriesTreeOutline.appendChild(categoryItem.element); + categoryItem.element.listItemElement.addStyleClass("event-category"); + categoryItem.element.selectable = true; + + categoryItem.checkbox = this._createCheckbox(categoryItem.element); + categoryItem.checkbox.addEventListener("click", this._categoryCheckboxClicked.bind(this, categoryItem), true); + + categoryItem.children = {}; + for (var i = 0; i < eventNames.length; ++i) { + var eventName = type + ":" + eventNames[i]; + + var breakpointItem = {}; + var title = WebInspector.EventListenerBreakpointsSidebarPane.eventNameForUI(eventName); + breakpointItem.element = new TreeElement(title); + categoryItem.element.appendChild(breakpointItem.element); + var hitMarker = document.createElement("div"); + hitMarker.className = "breakpoint-hit-marker"; + breakpointItem.element.listItemElement.appendChild(hitMarker); + breakpointItem.element.listItemElement.addStyleClass("source-code"); + breakpointItem.element.selectable = true; + + breakpointItem.checkbox = this._createCheckbox(breakpointItem.element); + breakpointItem.checkbox.addEventListener("click", this._breakpointCheckboxClicked.bind(this, eventName), true); + breakpointItem.parent = categoryItem; + + this._breakpointItems[eventName] = breakpointItem; + categoryItem.children[eventName] = breakpointItem; + } + }, + + _createCheckbox: function(treeElement) + { + var checkbox = document.createElement("input"); + checkbox.className = "checkbox-elem"; + checkbox.type = "checkbox"; + treeElement.listItemElement.insertBefore(checkbox, treeElement.listItemElement.firstChild); + return checkbox; + }, + + _categoryCheckboxClicked: function(categoryItem) + { + var checked = categoryItem.checkbox.checked; + for (var eventName in categoryItem.children) { + var breakpointItem = categoryItem.children[eventName]; + if (breakpointItem.checkbox.checked === checked) + continue; + if (checked) + this._setBreakpoint(eventName); + else + this._removeBreakpoint(eventName); + } + this._saveBreakpoints(); + }, + + _breakpointCheckboxClicked: function(eventName, event) + { + if (event.target.checked) + this._setBreakpoint(eventName); + else + this._removeBreakpoint(eventName); + this._saveBreakpoints(); + }, + + _setBreakpoint: function(eventName) + { + var breakpointItem = this._breakpointItems[eventName]; + if (!breakpointItem) + return; + breakpointItem.checkbox.checked = true; + DOMDebuggerAgent.setEventListenerBreakpoint(eventName); + this._updateCategoryCheckbox(breakpointItem.parent); + }, + + _removeBreakpoint: function(eventName) + { + var breakpointItem = this._breakpointItems[eventName]; + if (!breakpointItem) + return; + breakpointItem.checkbox.checked = false; + DOMDebuggerAgent.removeEventListenerBreakpoint(eventName); + this._updateCategoryCheckbox(breakpointItem.parent); + }, + + _updateCategoryCheckbox: function(categoryItem) + { + var hasEnabled = false, hasDisabled = false; + for (var eventName in categoryItem.children) { + var breakpointItem = categoryItem.children[eventName]; + if (breakpointItem.checkbox.checked) + hasEnabled = true; + else + hasDisabled = true; + } + categoryItem.checkbox.checked = hasEnabled; + categoryItem.checkbox.indeterminate = hasEnabled && hasDisabled; + }, + + highlightBreakpoint: function(eventName) + { + var breakpointItem = this._breakpointItems[eventName]; + if (!breakpointItem) + return; + this.expanded = true; + breakpointItem.parent.element.expand(); + breakpointItem.element.listItemElement.addStyleClass("breakpoint-hit"); + this._highlightedElement = breakpointItem.element.listItemElement; + }, + + clearBreakpointHighlight: function() + { + if (this._highlightedElement) { + this._highlightedElement.removeStyleClass("breakpoint-hit"); + delete this._highlightedElement; + } + }, + + _saveBreakpoints: function() + { + var breakpoints = []; + for (var eventName in this._breakpointItems) { + if (this._breakpointItems[eventName].checkbox.checked) + breakpoints.push({ eventName: eventName }); + } + WebInspector.settings.eventListenerBreakpoints.set(breakpoints); + }, + + _restoreBreakpoints: function() + { + var breakpoints = WebInspector.settings.eventListenerBreakpoints.get(); + for (var i = 0; i < breakpoints.length; ++i) { + var breakpoint = breakpoints[i]; + if (breakpoint && typeof breakpoint.eventName === "string") + this._setBreakpoint(breakpoint.eventName); + } + } +} + +WebInspector.EventListenerBreakpointsSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype; +/* DOMBreakpointsSidebarPane.js */ + +/* + * Copyright (C) 2011 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. + */ + +/** + * @constructor + * @extends {WebInspector.NativeBreakpointsSidebarPane} + */ +WebInspector.DOMBreakpointsSidebarPane = function() +{ + WebInspector.NativeBreakpointsSidebarPane.call(this, WebInspector.UIString("DOM Breakpoints")); + + this._breakpointElements = {}; + + this._breakpointTypes = { + SubtreeModified: "subtree-modified", + AttributeModified: "attribute-modified", + NodeRemoved: "node-removed" + }; + this._breakpointTypeLabels = {}; + this._breakpointTypeLabels[this._breakpointTypes.SubtreeModified] = WebInspector.UIString("Subtree Modified"); + this._breakpointTypeLabels[this._breakpointTypes.AttributeModified] = WebInspector.UIString("Attribute Modified"); + this._breakpointTypeLabels[this._breakpointTypes.NodeRemoved] = WebInspector.UIString("Node Removed"); + + this._contextMenuLabels = {}; + this._contextMenuLabels[this._breakpointTypes.SubtreeModified] = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Break on subtree modifications" : "Break on Subtree Modifications"); + this._contextMenuLabels[this._breakpointTypes.AttributeModified] = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Break on attributes modifications" : "Break on Attributes Modifications"); + this._contextMenuLabels[this._breakpointTypes.NodeRemoved] = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Break on node removal" : "Break on Node Removal"); + + WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.InspectedURLChanged, this._inspectedURLChanged, this); + WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.NodeRemoved, this._nodeRemoved, this); +} + +WebInspector.DOMBreakpointsSidebarPane.prototype = { + _inspectedURLChanged: function(event) + { + this._breakpointElements = {}; + this._reset(); + var url = event.data; + this._inspectedURL = url.removeURLFragment(); + }, + + populateNodeContextMenu: function(node, contextMenu) + { + var nodeBreakpoints = {}; + for (var id in this._breakpointElements) { + var element = this._breakpointElements[id]; + if (element._node === node) + nodeBreakpoints[element._type] = true; + } + + function toggleBreakpoint(type) + { + if (!nodeBreakpoints[type]) + this._setBreakpoint(node, type, true); + else + this._removeBreakpoint(node, type); + this._saveBreakpoints(); + } + + for (var key in this._breakpointTypes) { + var type = this._breakpointTypes[key]; + var label = this._contextMenuLabels[type]; + contextMenu.appendCheckboxItem(label, toggleBreakpoint.bind(this, type), nodeBreakpoints[type]); + } + }, + + createBreakpointHitStatusMessage: function(auxData, callback) + { + if (auxData.type === this._breakpointTypes.SubtreeModified) { + var targetNodeObject = WebInspector.RemoteObject.fromPayload(auxData["targetNode"]); + function didPushNodeToFrontend(targetNodeId) + { + if (targetNodeId) + targetNodeObject.release(); + this._doCreateBreakpointHitStatusMessage(auxData, targetNodeId, callback); + } + targetNodeObject.pushNodeToFrontend(didPushNodeToFrontend.bind(this)); + } else + this._doCreateBreakpointHitStatusMessage(auxData, null, callback); + }, + + _doCreateBreakpointHitStatusMessage: function (auxData, targetNodeId, callback) + { + var message; + var typeLabel = this._breakpointTypeLabels[auxData.type]; + var linkifiedNode = WebInspector.DOMPresentationUtils.linkifyNodeById(auxData.nodeId); + var substitutions = [typeLabel, linkifiedNode]; + var targetNode = ""; + if (targetNodeId) + targetNode = WebInspector.DOMPresentationUtils.linkifyNodeById(targetNodeId); + + if (auxData.type === this._breakpointTypes.SubtreeModified) { + if (auxData.insertion) { + if (targetNodeId !== auxData.nodeId) { + message = "Paused on a \"%s\" breakpoint set on %s, because a new child was added to its descendant %s."; + substitutions.push(targetNode); + } else + message = "Paused on a \"%s\" breakpoint set on %s, because a new child was added to that node."; + } else { + message = "Paused on a \"%s\" breakpoint set on %s, because its descendant %s was removed."; + substitutions.push(targetNode); + } + } else + message = "Paused on a \"%s\" breakpoint set on %s."; + + var element = document.createElement("span"); + var formatters = { + s: function(substitution) + { + return substitution; + } + }; + function append(a, b) + { + if (typeof b === "string") + b = document.createTextNode(b); + element.appendChild(b); + } + WebInspector.formatLocalized(message, substitutions, formatters, "", append); + + callback(element); + }, + + _nodeRemoved: function(event) + { + var node = event.data.node; + this._removeBreakpointsForNode(event.data.node); + if (!node.children) + return; + for (var i = 0; i < node.children.length; ++i) + this._removeBreakpointsForNode(node.children[i]); + this._saveBreakpoints(); + }, + + _removeBreakpointsForNode: function(node) + { + for (var id in this._breakpointElements) { + var element = this._breakpointElements[id]; + if (element._node === node) + this._removeBreakpoint(element._node, element._type); + } + }, + + _setBreakpoint: function(node, type, enabled) + { + var breakpointId = this._createBreakpointId(node.id, type); + if (breakpointId in this._breakpointElements) + return; + + var element = document.createElement("li"); + element._node = node; + element._type = type; + element.addEventListener("contextmenu", this._contextMenu.bind(this, node, type), true); + + var checkboxElement = document.createElement("input"); + checkboxElement.className = "checkbox-elem"; + checkboxElement.type = "checkbox"; + checkboxElement.checked = enabled; + checkboxElement.addEventListener("click", this._checkboxClicked.bind(this, node, type), false); + element._checkboxElement = checkboxElement; + element.appendChild(checkboxElement); + + var labelElement = document.createElement("span"); + element.appendChild(labelElement); + + var linkifiedNode = WebInspector.DOMPresentationUtils.linkifyNodeById(node.id); + linkifiedNode.addStyleClass("monospace"); + labelElement.appendChild(linkifiedNode); + + var description = document.createElement("div"); + description.className = "source-text"; + description.textContent = this._breakpointTypeLabels[type]; + labelElement.appendChild(description); + + var currentElement = this.listElement.firstChild; + while (currentElement) { + if (currentElement._type && currentElement._type < element._type) + break; + currentElement = currentElement.nextSibling; + } + this._addListElement(element, currentElement); + this._breakpointElements[breakpointId] = element; + if (enabled) + DOMDebuggerAgent.setDOMBreakpoint(node.id, type); + }, + + _removeBreakpoint: function(node, type) + { + var breakpointId = this._createBreakpointId(node.id, type); + var element = this._breakpointElements[breakpointId]; + if (!element) + return; + + this._removeListElement(element); + delete this._breakpointElements[breakpointId]; + if (element._checkboxElement.checked) + DOMDebuggerAgent.removeDOMBreakpoint(node.id, type); + }, + + _contextMenu: function(node, type, event) + { + var contextMenu = new WebInspector.ContextMenu(); + function removeBreakpoint() + { + this._removeBreakpoint(node, type); + this._saveBreakpoints(); + } + contextMenu.appendItem(WebInspector.UIString("Remove Breakpoint"), removeBreakpoint.bind(this)); + contextMenu.show(event); + }, + + _checkboxClicked: function(node, type, event) + { + if (event.target.checked) + DOMDebuggerAgent.setDOMBreakpoint(node.id, type); + else + DOMDebuggerAgent.removeDOMBreakpoint(node.id, type); + this._saveBreakpoints(); + }, + + highlightBreakpoint: function(auxData) + { + var breakpointId = this._createBreakpointId(auxData.nodeId, auxData.type); + var element = this._breakpointElements[breakpointId]; + if (!element) + return; + this.expanded = true; + element.addStyleClass("breakpoint-hit"); + this._highlightedElement = element; + }, + + clearBreakpointHighlight: function() + { + if (this._highlightedElement) { + this._highlightedElement.removeStyleClass("breakpoint-hit"); + delete this._highlightedElement; + } + }, + + _createBreakpointId: function(nodeId, type) + { + return nodeId + ":" + type; + }, + + _saveBreakpoints: function() + { + var breakpoints = []; + var storedBreakpoints = WebInspector.settings.domBreakpoints.get(); + for (var i = 0; i < storedBreakpoints.length; ++i) { + var breakpoint = storedBreakpoints[i]; + if (breakpoint.url !== this._inspectedURL) + breakpoints.push(breakpoint); + } + for (var id in this._breakpointElements) { + var element = this._breakpointElements[id]; + breakpoints.push({ url: this._inspectedURL, path: element._node.path(), type: element._type, enabled: element._checkboxElement.checked }); + } + WebInspector.settings.domBreakpoints.set(breakpoints); + }, + + restoreBreakpoints: function() + { + var pathToBreakpoints = {}; + + function didPushNodeByPathToFrontend(path, nodeId) + { + var node = WebInspector.domAgent.nodeForId(nodeId); + if (!node) + return; + + var breakpoints = pathToBreakpoints[path]; + for (var i = 0; i < breakpoints.length; ++i) + this._setBreakpoint(node, breakpoints[i].type, breakpoints[i].enabled); + } + + var breakpoints = WebInspector.settings.domBreakpoints.get(); + for (var i = 0; i < breakpoints.length; ++i) { + var breakpoint = breakpoints[i]; + if (breakpoint.url !== this._inspectedURL) + continue; + var path = breakpoint.path; + if (!pathToBreakpoints[path]) { + pathToBreakpoints[path] = []; + WebInspector.domAgent.pushNodeByPathToFrontend(path, didPushNodeByPathToFrontend.bind(this, path)); + } + pathToBreakpoints[path].push(breakpoint); + } + } +} + +WebInspector.DOMBreakpointsSidebarPane.prototype.__proto__ = WebInspector.NativeBreakpointsSidebarPane.prototype; +/* CallStackSidebarPane.js */ + +/* + * Copyright (C) 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 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 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. + */ + +/** + * @constructor + * @extends {WebInspector.SidebarPane} + */ +WebInspector.CallStackSidebarPane = function(model) +{ + WebInspector.SidebarPane.call(this, WebInspector.UIString("Call Stack")); + this._model = model; + + this.bodyElement.addEventListener("contextmenu", this._contextMenu.bind(this), true); +} + +WebInspector.CallStackSidebarPane.prototype = { + update: function(callFrames) + { + this.bodyElement.removeChildren(); + + if (this.placards) { + for (var i = 0; i < this.placards.length; ++i) + this.placards[i].discard(); + } + this.placards = []; + + if (!callFrames) { + var infoElement = document.createElement("div"); + infoElement.className = "info"; + infoElement.textContent = WebInspector.UIString("Not Paused"); + this.bodyElement.appendChild(infoElement); + return; + } + + for (var i = 0; i < callFrames.length; ++i) { + var callFrame = callFrames[i]; + var placard = this._model.createPlacard(callFrame); + placard.callFrame = callFrame; + placard.element.addEventListener("click", this._placardSelected.bind(this, placard), false); + this.placards.push(placard); + this.bodyElement.appendChild(placard.element); + } + }, + + set selectedCallFrame(x) + { + for (var i = 0; i < this.placards.length; ++i) { + var placard = this.placards[i]; + placard.selected = (placard.callFrame === x); + } + }, + + _selectNextCallFrameOnStack: function() + { + var index = this._selectedCallFrameIndex(); + if (index == -1) + return; + this._selectedPlacardByIndex(index + 1); + }, + + _selectPreviousCallFrameOnStack: function() + { + var index = this._selectedCallFrameIndex(); + if (index == -1) + return; + this._selectedPlacardByIndex(index - 1); + }, + + _selectedPlacardByIndex: function(index) + { + if (index < 0 || index >= this.placards.length) + return; + this._placardSelected(this.placards[index]) + }, + + _selectedCallFrameIndex: function() + { + if (!this._model.selectedCallFrame) + return -1; + for (var i = 0; i < this.placards.length; ++i) { + var placard = this.placards[i]; + if (placard.callFrame === this._model.selectedCallFrame) + return i; + } + return -1; + }, + + _placardSelected: function(placard) + { + this._model.selectedCallFrame = placard.callFrame; + }, + + _contextMenu: function(event) + { + if (!this.placards.length) + return; + + var contextMenu = new WebInspector.ContextMenu(); + contextMenu.appendItem(WebInspector.UIString("Copy Stack Trace"), this._copyStackTrace.bind(this)); + contextMenu.show(event); + }, + + _copyStackTrace: function() + { + var text = ""; + for (var i = 0; i < this.placards.length; ++i) + text += this.placards[i]._text + "\n"; + InspectorFrontendHost.copyText(text); + }, + + registerShortcuts: function(section, registerShortcutDelegate) + { + var nextCallFrame = WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.Period, + WebInspector.KeyboardShortcut.Modifiers.Ctrl); + registerShortcutDelegate(nextCallFrame.key, this._selectNextCallFrameOnStack.bind(this)); + + var prevCallFrame = WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.Comma, + WebInspector.KeyboardShortcut.Modifiers.Ctrl); + registerShortcutDelegate(prevCallFrame.key, this._selectPreviousCallFrameOnStack.bind(this)); + + section.addRelatedKeys([ nextCallFrame.name, prevCallFrame.name ], WebInspector.UIString("Next/previous call frame")); + }, + + setStatus: function(status) + { + var statusMessageElement = document.createElement("div"); + statusMessageElement.className = "info"; + if (typeof status === "string") + statusMessageElement.textContent = status; + else + statusMessageElement.appendChild(status); + this.bodyElement.appendChild(statusMessageElement); + } +} + +WebInspector.CallStackSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype; +/* ScopeChainSidebarPane.js */ + +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2011 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: + * 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 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 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. + */ + +/** + * @constructor + * @extends {WebInspector.SidebarPane} + */ +WebInspector.ScopeChainSidebarPane = function() +{ + WebInspector.SidebarPane.call(this, WebInspector.UIString("Scope Variables")); + this._sections = []; + this._expandedSections = {}; + this._expandedProperties = []; +} + +WebInspector.ScopeChainSidebarPane.prototype = { + update: function(callFrame) + { + this.bodyElement.removeChildren(); + + if (!callFrame) { + var infoElement = document.createElement("div"); + infoElement.className = "info"; + infoElement.textContent = WebInspector.UIString("Not Paused"); + this.bodyElement.appendChild(infoElement); + return; + } + + for (var i = 0; i < this._sections.length; ++i) { + var section = this._sections[i]; + if (!section.title) + continue; + if (section.expanded) + this._expandedSections[section.title] = true; + else + delete this._expandedSections[section.title]; + } + + this._sections = []; + + var foundLocalScope = false; + var scopeChain = callFrame.scopeChain; + for (var i = 0; i < scopeChain.length; ++i) { + var scope = scopeChain[i]; + var title = null; + var subtitle = scope.object.description; + var emptyPlaceholder = null; + var extraProperties = null; + + switch (scope.type) { + case "local": + foundLocalScope = true; + title = WebInspector.UIString("Local"); + emptyPlaceholder = WebInspector.UIString("No Variables"); + subtitle = null; + if (callFrame.this) + extraProperties = [ new WebInspector.RemoteObjectProperty("this", WebInspector.RemoteObject.fromPayload(callFrame.this)) ]; + if (i == 0) { + var details = WebInspector.debuggerModel.debuggerPausedDetails; + var exception = details.reason === WebInspector.DebuggerModel.BreakReason.Exception ? details.auxData : 0; + if (exception) { + extraProperties = extraProperties || []; + var exceptionObject = /** @type {RuntimeAgent.RemoteObject} */ exception; + extraProperties.push(new WebInspector.RemoteObjectProperty("", WebInspector.RemoteObject.fromPayload(exceptionObject))); + } + } + break; + case "closure": + title = WebInspector.UIString("Closure"); + emptyPlaceholder = WebInspector.UIString("No Variables"); + subtitle = null; + break; + case "catch": + title = WebInspector.UIString("Catch"); + break; + case "with": + title = WebInspector.UIString("With Block"); + break; + case "global": + title = WebInspector.UIString("Global"); + break; + } + + if (!title || title === subtitle) + subtitle = null; + + var section = new WebInspector.ObjectPropertiesSection(WebInspector.RemoteObject.fromPayload(scope.object), title, subtitle, emptyPlaceholder, true, extraProperties, WebInspector.ScopeVariableTreeElement); + section.editInSelectedCallFrameWhenPaused = true; + section.pane = this; + + if (!foundLocalScope || scope.type === "local" || title in this._expandedSections) + section.expanded = true; + + this._sections.push(section); + this.bodyElement.appendChild(section.element); + } + } +} + +WebInspector.ScopeChainSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype; + +/** + * @constructor + * @extends {WebInspector.ObjectPropertyTreeElement} + */ +WebInspector.ScopeVariableTreeElement = function(property) +{ + WebInspector.ObjectPropertyTreeElement.call(this, property); +} + +WebInspector.ScopeVariableTreeElement.prototype = { + onattach: function() + { + WebInspector.ObjectPropertyTreeElement.prototype.onattach.call(this); + if (this.hasChildren && this.propertyIdentifier in this.treeOutline.section.pane._expandedProperties) + this.expand(); + }, + + onexpand: function() + { + this.treeOutline.section.pane._expandedProperties[this.propertyIdentifier] = true; + }, + + oncollapse: function() + { + delete this.treeOutline.section.pane._expandedProperties[this.propertyIdentifier]; + }, + + get propertyIdentifier() + { + if ("_propertyIdentifier" in this) + return this._propertyIdentifier; + var section = this.treeOutline.section; + this._propertyIdentifier = section.title + ":" + (section.subtitle ? section.subtitle + ":" : "") + this.propertyPath; + return this._propertyIdentifier; + }, + + get propertyPath() + { + if ("_propertyPath" in this) + return this._propertyPath; + + var current = this; + var result; + + do { + if (result) + result = current.property.name + "." + result; + else + result = current.property.name; + current = current.parent; + } while (current && !current.root); + + this._propertyPath = result; + return result; + } +} + +WebInspector.ScopeVariableTreeElement.prototype.__proto__ = WebInspector.ObjectPropertyTreeElement.prototype; +/* WatchExpressionsSidebarPane.js */ + +/* + * Copyright (C) IBM Corp. 2009 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 IBM Corp. 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. + */ + +/** + * @constructor + * @extends {WebInspector.SidebarPane} + */ +WebInspector.WatchExpressionsSidebarPane = function() +{ + WebInspector.SidebarPane.call(this, WebInspector.UIString("Watch Expressions")); +} + +WebInspector.WatchExpressionsSidebarPane.prototype = { + show: function() + { + this._visible = true; + + // Expand and update watches first time they are shown. + if (this._wasShown) { + this._refreshExpressionsIfNeeded(); + return; + } + + this._wasShown = true; + + this.section = new WebInspector.WatchExpressionsSection(); + this.bodyElement.appendChild(this.section.element); + + var refreshButton = document.createElement("button"); + refreshButton.className = "pane-title-button refresh"; + refreshButton.addEventListener("click", this._refreshButtonClicked.bind(this), false); + this.titleElement.appendChild(refreshButton); + + var addButton = document.createElement("button"); + addButton.className = "pane-title-button add"; + addButton.addEventListener("click", this._addButtonClicked.bind(this), false); + this.titleElement.appendChild(addButton); + this._requiresUpdate = true; + + if (WebInspector.settings.watchExpressions.get().length > 0) + this.expanded = true; + }, + + hide: function() + { + this._visible = false; + }, + + reset: function() + { + this.refreshExpressions(); + }, + + refreshExpressions: function() + { + this._requiresUpdate = true; + this._refreshExpressionsIfNeeded(); + }, + + addExpression: function(expression) + { + this.section.addExpression(expression); + this.expanded = true; + }, + + _refreshExpressionsIfNeeded: function() + { + if (this._requiresUpdate && this._visible) { + this.section.update(); + delete this._requiresUpdate; + } else + this._requiresUpdate = true; + }, + + _addButtonClicked: function(event) + { + event.stopPropagation(); + this.expanded = true; + this.section.addNewExpressionAndEdit(); + }, + + _refreshButtonClicked: function(event) + { + event.stopPropagation(); + this.refreshExpressions(); + } +} + +WebInspector.WatchExpressionsSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype; + +/** + * @constructor + * @extends {WebInspector.ObjectPropertiesSection} + */ +WebInspector.WatchExpressionsSection = function() +{ + this._watchObjectGroupId = "watch-group"; + + WebInspector.ObjectPropertiesSection.call(this); + + this.emptyElement = document.createElement("div"); + this.emptyElement.className = "info"; + this.emptyElement.textContent = WebInspector.UIString("No Watch Expressions"); + + this.watchExpressions = WebInspector.settings.watchExpressions.get(); + + this.headerElement.className = "hidden"; + this.editable = true; + this.expanded = true; + this.propertiesElement.addStyleClass("watch-expressions"); + + this.element.addEventListener("mousemove", this._mouseMove.bind(this), true); + this.element.addEventListener("mouseout", this._mouseOut.bind(this), true); +} + +WebInspector.WatchExpressionsSection.NewWatchExpression = "\xA0"; + +WebInspector.WatchExpressionsSection.prototype = { + update: function(e) + { + if (e) + e.stopPropagation(); + + function appendResult(expression, watchIndex, result, wasThrown) + { + if (!result) + return; + + var property = new WebInspector.RemoteObjectProperty(expression, result); + property.watchIndex = watchIndex; + property.wasThrown = wasThrown; + + // To clarify what's going on here: + // In the outer function, we calculate the number of properties + // that we're going to be updating, and set that in the + // propertyCount variable. + // In this function, we test to see when we are processing the + // last property, and then call the superclass's updateProperties() + // method to get all the properties refreshed at once. + properties.push(property); + + if (properties.length == propertyCount) { + this.updateProperties(properties, WebInspector.WatchExpressionTreeElement, WebInspector.WatchExpressionsSection.CompareProperties); + + // check to see if we just added a new watch expression, + // which will always be the last property + if (this._newExpressionAdded) { + delete this._newExpressionAdded; + + var treeElement = this.findAddedTreeElement(); + if (treeElement) + treeElement.startEditing(); + } + + // Force displaying delete button for hovered element. + if (this._lastMouseMovePageY) + this._updateHoveredElement(this._lastMouseMovePageY); + } + } + + // TODO: pass exact injected script id. + RuntimeAgent.releaseObjectGroup(this._watchObjectGroupId) + var properties = []; + + // Count the properties, so we known when to call this.updateProperties() + // in appendResult() + var propertyCount = 0; + for (var i = 0; i < this.watchExpressions.length; ++i) { + if (!this.watchExpressions[i]) + continue; + ++propertyCount; + } + + // Now process all the expressions, since we have the actual count, + // which is checked in the appendResult inner function. + for (var i = 0; i < this.watchExpressions.length; ++i) { + var expression = this.watchExpressions[i]; + if (!expression) + continue; + + WebInspector.consoleView.evalInInspectedWindow(expression, this._watchObjectGroupId, false, true, false, appendResult.bind(this, expression, i)); + } + + if (!propertyCount) { + if (!this.emptyElement.parentNode) + this.element.appendChild(this.emptyElement); + } else { + if (this.emptyElement.parentNode) + this.element.removeChild(this.emptyElement); + } + + // note this is setting the expansion of the tree, not the section; + // with no expressions, and expanded tree, we get some extra vertical + // white space + this.expanded = (propertyCount != 0); + }, + + addExpression: function(expression) + { + this.watchExpressions.push(expression); + this.saveExpressions(); + this.update(); + }, + + addNewExpressionAndEdit: function() + { + this._newExpressionAdded = true; + this.watchExpressions.push(WebInspector.WatchExpressionsSection.NewWatchExpression); + this.update(); + }, + + updateExpression: function(element, value) + { + this.watchExpressions[element.property.watchIndex] = value; + this.saveExpressions(); + this.update(); + }, + + findAddedTreeElement: function() + { + var children = this.propertiesTreeOutline.children; + for (var i = 0; i < children.length; ++i) + if (children[i].property.name === WebInspector.WatchExpressionsSection.NewWatchExpression) + return children[i]; + }, + + saveExpressions: function() + { + var toSave = []; + for (var i = 0; i < this.watchExpressions.length; i++) + if (this.watchExpressions[i]) + toSave.push(this.watchExpressions[i]); + + WebInspector.settings.watchExpressions.set(toSave); + return toSave.length; + }, + + _mouseMove: function(e) + { + if (this.propertiesElement.firstChild) + this._updateHoveredElement(e.pageY); + }, + + _mouseOut: function() + { + if (this._hoveredElement) + this._hoveredElement.removeStyleClass("hovered"); + delete this._lastMouseMovePageY; + }, + + _updateHoveredElement: function(pageY) + { + if (this._hoveredElement) + this._hoveredElement.removeStyleClass("hovered"); + + this._hoveredElement = this.propertiesElement.firstChild; + while (true) { + var next = this._hoveredElement.nextSibling; + while(next && !next.clientHeight) + next = next.nextSibling; + if (!next || next.totalOffsetTop() > pageY) + break; + this._hoveredElement = next; + } + this._hoveredElement.addStyleClass("hovered"); + + this._lastMouseMovePageY = pageY; + } +} + +WebInspector.WatchExpressionsSection.prototype.__proto__ = WebInspector.ObjectPropertiesSection.prototype; + +WebInspector.WatchExpressionsSection.CompareProperties = function(propertyA, propertyB) +{ + if (propertyA.watchIndex == propertyB.watchIndex) + return 0; + else if (propertyA.watchIndex < propertyB.watchIndex) + return -1; + else + return 1; +} + +/** + * @constructor + * @extends {WebInspector.ObjectPropertyTreeElement} + */ +WebInspector.WatchExpressionTreeElement = function(property) +{ + WebInspector.ObjectPropertyTreeElement.call(this, property); +} + +WebInspector.WatchExpressionTreeElement.prototype = { + update: function() + { + WebInspector.ObjectPropertyTreeElement.prototype.update.call(this); + + if (this.property.wasThrown) + this.valueElement.addStyleClass("watch-expressions-error-level"); + + var deleteButton = document.createElement("input"); + deleteButton.type = "button"; + deleteButton.title = WebInspector.UIString("Delete watch expression."); + deleteButton.addStyleClass("enabled-button"); + deleteButton.addStyleClass("delete-button"); + deleteButton.addEventListener("click", this._deleteButtonClicked.bind(this), false); + this.listItemElement.insertBefore(deleteButton, this.listItemElement.firstChild); + }, + + _deleteButtonClicked: function() + { + this.treeOutline.section.updateExpression(this, null); + }, + + startEditing: function() + { + if (WebInspector.isBeingEdited(this.nameElement) || !this.treeOutline.section.editable) + return; + + this.nameElement.textContent = this.property.name.trim(); + + var context = { expanded: this.expanded }; + + // collapse temporarily, if required + this.hasChildren = false; + + this.listItemElement.addStyleClass("editing-sub-part"); + + WebInspector.startEditing(this.nameElement, new WebInspector.EditingConfig(this.editingCommitted.bind(this), this.editingCancelled.bind(this), context)); + }, + + editingCancelled: function(element, context) + { + if (!this.nameElement.textContent) + this.treeOutline.section.updateExpression(this, null); + + this.update(); + this.editingEnded(context); + }, + + applyExpression: function(expression, updateInterface) + { + expression = expression.trim(); + + if (!expression) + expression = null; + + this.property.name = expression; + this.treeOutline.section.updateExpression(this, expression); + } +} + +WebInspector.WatchExpressionTreeElement.prototype.__proto__ = WebInspector.ObjectPropertyTreeElement.prototype; +/* WorkersSidebarPane.js */ + +/* + * 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. + * * 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. + */ + +/** + * @constructor + * @extends {WebInspector.SidebarPane} + */ +WebInspector.WorkersSidebarPane = function() +{ + WebInspector.SidebarPane.call(this, WebInspector.UIString("Workers")); + + this._workers = {}; + + this._enableWorkersCheckbox = new WebInspector.Checkbox( + WebInspector.UIString("Debug"), + "sidebar-pane-subtitle", + WebInspector.UIString("Allow debugging workers. Enabling this option will replace native workers with the iframe-based JavaScript implementation")); + this.titleElement.insertBefore(this._enableWorkersCheckbox.element, this.titleElement.firstChild); + + this._enableWorkersCheckbox.addEventListener(this._onTriggerInstrument.bind(this)); + this._enableWorkersCheckbox.checked = false; + + this._listElement = document.createElement("ol"); + this._listElement.className = "workers-list"; + + this.bodyElement.appendChild(this._listElement); + this._treeOutline = new TreeOutline(this._listElement); +} + +WebInspector.WorkersSidebarPane.prototype = { + addWorker: function(id, url, isShared) + { + if (id in this._workers) + return; + var worker = new WebInspector.Worker(id, url, isShared); + this._workers[id] = worker; + + var title = WebInspector.linkifyURLAsNode(url, WebInspector.displayNameForURL(url), "worker-item", true, url); + this._treeOutline.appendChild(new TreeElement(title, worker, false)); + }, + + removeWorker: function(id) + { + if (id in this._workers) { + this._treeOutline.removeChild(this._treeOutline.getCachedTreeElement(this._workers[id])); + delete this._workers[id]; + } + }, + + _setInstrumentation: function(enabled) + { + if (!enabled === !this._fakeWorkersScriptIdentifier) + return; + + if (enabled) { + this._enableWorkersCheckbox.disabled = true; + function callback(error, identifier) + { + this._fakeWorkersScriptIdentifier = identifier; + this._enableWorkersCheckbox.disabled = false; + } + PageAgent.addScriptToEvaluateOnLoad("(" + InjectedFakeWorker + ")", callback.bind(this)); + } else { + PageAgent.removeScriptToEvaluateOnLoad(this._fakeWorkersScriptIdentifier); + this._fakeWorkersScriptIdentifier = null; + } + }, + + reset: function() + { + this._setInstrumentation(this._enableWorkersCheckbox.checked); + this._treeOutline.removeChildren(); + this._workers = {}; + }, + + _onTriggerInstrument: function(event) + { + this._setInstrumentation(this._enableWorkersCheckbox.checked); + } +}; + +WebInspector.WorkersSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype; + +/** + * @constructor + */ +WebInspector.Worker = function(id, url, shared) +{ + this.id = id; + this.url = url; + this.shared = shared; +} + +/** + * @constructor + * @extends {WebInspector.SidebarPane} + */ +WebInspector.WorkerListSidebarPane = function(workerManager) +{ + WebInspector.SidebarPane.call(this, WebInspector.UIString("Workers")); + + this._enableWorkersCheckbox = new WebInspector.Checkbox( + WebInspector.UIString("Pause on start"), + "sidebar-label", + WebInspector.UIString("Automatically attach to new workers and pause them. Enabling this option will force opening inspector for all new workers.")); + this._enableWorkersCheckbox.element.id = "pause-workers-checkbox"; + this.bodyElement.appendChild(this._enableWorkersCheckbox.element); + this._enableWorkersCheckbox.addEventListener(this._autoattachToWorkersClicked.bind(this)); + this._enableWorkersCheckbox.checked = false; + + if (Preferences.sharedWorkersDebugNote) { + var note = this.bodyElement.createChild("div"); + note.id = "shared-workers-list"; + note.addStyleClass("sidebar-label") + note.textContent = Preferences.sharedWorkersDebugNote; + } + + var separator = this.bodyElement.createChild("div", "sidebar-separator"); + separator.textContent = WebInspector.UIString("Dedicated worker inspectors"); + + this._workerListElement = document.createElement("ol"); + this._workerListElement.tabIndex = 0; + this._workerListElement.addStyleClass("properties-tree"); + this._workerListElement.addStyleClass("sidebar-label"); + this.bodyElement.appendChild(this._workerListElement); + + this._idToWorkerItem = {}; + this._workerManager = workerManager; + + workerManager.addEventListener(WebInspector.WorkerManager.Events.WorkerAdded, this._workerAdded, this); + workerManager.addEventListener(WebInspector.WorkerManager.Events.WorkerRemoved, this._workerRemoved, this); + workerManager.addEventListener(WebInspector.WorkerManager.Events.WorkersCleared, this._workersCleared, this); +} + +WebInspector.WorkerListSidebarPane.prototype = { + _workerAdded: function(event) + { + this._addWorker(event.data.workerId, event.data.url, event.data.inspectorConnected); + }, + + _workerRemoved: function(event) + { + var workerItem = this._idToWorkerItem[event.data]; + delete this._idToWorkerItem[event.data]; + workerItem.parentElement.removeChild(workerItem); + }, + + _workersCleared: function(event) + { + this._idToWorkerItem = {}; + this._workerListElement.removeChildren(); + }, + + _addWorker: function(workerId, url, inspectorConnected) + { + var item = this._workerListElement.createChild("div", "dedicated-worker-item"); + var link = item.createChild("a"); + link.textContent = url; + link.href = "#"; + link.target = "_blank"; + link.addEventListener("click", this._workerItemClicked.bind(this, workerId), true); + this._idToWorkerItem[workerId] = item; + }, + + _workerItemClicked: function(workerId, event) + { + event.preventDefault(); + this._workerManager.openWorkerInspector(workerId); + }, + + _autoattachToWorkersClicked: function(event) + { + WorkerAgent.setAutoconnectToWorkers(event.target.checked); + } +} + +WebInspector.WorkerListSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype; +/* MetricsSidebarPane.js */ + +/* + * 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. + * 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. + */ + +/** + * @constructor + * @extends {WebInspector.SidebarPane} + */ +WebInspector.MetricsSidebarPane = function() +{ + WebInspector.SidebarPane.call(this, WebInspector.UIString("Metrics")); + + WebInspector.cssModel.addEventListener(WebInspector.CSSStyleModel.Events.StyleSheetChanged, this._styleSheetOrMediaQueryResultChanged, this); + WebInspector.cssModel.addEventListener(WebInspector.CSSStyleModel.Events.MediaQueryResultChanged, this._styleSheetOrMediaQueryResultChanged, this); + WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.AttrModified, this._attributesUpdated, this); + WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.AttrRemoved, this._attributesUpdated, this); +} + +WebInspector.MetricsSidebarPane.prototype = { + /** + * @param {WebInspector.DOMNode=} node + */ + update: function(node) + { + if (node) + this.node = node; + this._innerUpdate(); + }, + + _innerUpdate: function() + { + // "style" attribute might have changed. Update metrics unless they are being edited + // (if a CSS property is added, a StyleSheetChanged event is dispatched). + if (this._isEditingMetrics) + return; + + // FIXME: avoid updates of a collapsed pane. + var node = this.node; + + if (!node || node.nodeType() !== Node.ELEMENT_NODE) { + this.bodyElement.removeChildren(); + return; + } + + function callback(style) + { + if (!style || this.node !== node) + return; + this._updateMetrics(style); + } + WebInspector.cssModel.getComputedStyleAsync(node.id, WebInspector.panels.elements.sidebarPanes.styles.forcedPseudoClasses, callback.bind(this)); + + function inlineStyleCallback(style) + { + if (!style || this.node !== node) + return; + this.inlineStyle = style; + } + WebInspector.cssModel.getInlineStylesAsync(node.id, inlineStyleCallback.bind(this)); + }, + + _styleSheetOrMediaQueryResultChanged: function() + { + this._innerUpdate(); + }, + + _attributesUpdated: function(event) + { + if (this.node !== event.data.node) + return; + + this._innerUpdate(); + }, + + _getPropertyValueAsPx: function(style, propertyName) + { + return Number(style.getPropertyValue(propertyName).replace(/px$/, "") || 0); + }, + + _getBox: function(computedStyle, componentName) + { + var suffix = componentName === "border" ? "-width" : ""; + var left = this._getPropertyValueAsPx(computedStyle, componentName + "-left" + suffix); + var top = this._getPropertyValueAsPx(computedStyle, componentName + "-top" + suffix); + var right = this._getPropertyValueAsPx(computedStyle, componentName + "-right" + suffix); + var bottom = this._getPropertyValueAsPx(computedStyle, componentName + "-bottom" + suffix); + return { left: left, top: top, right: right, bottom: bottom }; + }, + + _highlightDOMNode: function(showHighlight, mode, event) + { + event.stopPropagation(); + var nodeId = showHighlight && this.node ? this.node.id : 0; + if (nodeId) { + if (this._highlightMode === mode) + return; + this._highlightMode = mode; + WebInspector.domAgent.highlightDOMNode(nodeId, mode); + } else { + delete this._highlightMode; + WebInspector.domAgent.hideDOMNodeHighlight(); + } + + for (var i = 0; this._boxElements && i < this._boxElements.length; ++i) { + var element = this._boxElements[i]; + if (!nodeId || mode === "all" || element._name === mode) + element.style.backgroundColor = element._backgroundColor; + else + element.style.backgroundColor = ""; + } + }, + + _updateMetrics: function(style) + { + // Updating with computed style. + var metricsElement = document.createElement("div"); + metricsElement.className = "metrics"; + var self = this; + + function createBoxPartElement(style, name, side, suffix) + { + var propertyName = (name !== "position" ? name + "-" : "") + side + suffix; + var value = style.getPropertyValue(propertyName); + if (value === "" || (name !== "position" && value === "0px")) + value = "\u2012"; + else if (name === "position" && value === "auto") + value = "\u2012"; + value = value.replace(/px$/, ""); + + var element = document.createElement("div"); + element.className = side; + element.textContent = value; + element.addEventListener("dblclick", this.startEditing.bind(this, element, name, propertyName, style), false); + return element; + } + + function getContentAreaWidthPx(style) + { + var width = style.getPropertyValue("width").replace(/px$/, ""); + if (style.getPropertyValue("box-sizing") === "border-box") { + var borderBox = self._getBox(style, "border"); + var paddingBox = self._getBox(style, "padding"); + + width = width - borderBox.left - borderBox.right - paddingBox.left - paddingBox.right; + } + + return width; + } + + function getContentAreaHeightPx(style) + { + var height = style.getPropertyValue("height").replace(/px$/, ""); + if (style.getPropertyValue("box-sizing") === "border-box") { + var borderBox = self._getBox(style, "border"); + var paddingBox = self._getBox(style, "padding"); + + height = height - borderBox.top - borderBox.bottom - paddingBox.top - paddingBox.bottom; + } + + return height; + } + + // Display types for which margin is ignored. + var noMarginDisplayType = { + "table-cell": true, + "table-column": true, + "table-column-group": true, + "table-footer-group": true, + "table-header-group": true, + "table-row": true, + "table-row-group": true + }; + + // Display types for which padding is ignored. + var noPaddingDisplayType = { + "table-column": true, + "table-column-group": true, + "table-footer-group": true, + "table-header-group": true, + "table-row": true, + "table-row-group": true + }; + + // Position types for which top, left, bottom and right are ignored. + var noPositionType = { + "static": true + }; + + var boxes = ["content", "padding", "border", "margin", "position"]; + var boxColors = [ + WebInspector.Color.PageHighlight.Content, + WebInspector.Color.PageHighlight.Padding, + WebInspector.Color.PageHighlight.Border, + WebInspector.Color.PageHighlight.Margin, + WebInspector.Color.fromRGBA(0, 0, 0, 0) + ]; + var boxLabels = [WebInspector.UIString("content"), WebInspector.UIString("padding"), WebInspector.UIString("border"), WebInspector.UIString("margin"), WebInspector.UIString("position")]; + var previousBox = null; + this._boxElements = []; + for (var i = 0; i < boxes.length; ++i) { + var name = boxes[i]; + + if (name === "margin" && noMarginDisplayType[style.getPropertyValue("display")]) + continue; + if (name === "padding" && noPaddingDisplayType[style.getPropertyValue("display")]) + continue; + if (name === "position" && noPositionType[style.getPropertyValue("position")]) + continue; + + var boxElement = document.createElement("div"); + boxElement.className = name; + boxElement._backgroundColor = boxColors[i].toString("original"); + boxElement._name = name; + boxElement.style.backgroundColor = boxElement._backgroundColor; + boxElement.addEventListener("mouseover", this._highlightDOMNode.bind(this, true, name === "position" ? "all" : name), false); + this._boxElements.push(boxElement); + + if (name === "content") { + var widthElement = document.createElement("span"); + widthElement.textContent = getContentAreaWidthPx(style); + widthElement.addEventListener("dblclick", this.startEditing.bind(this, widthElement, "width", "width", style), false); + + var heightElement = document.createElement("span"); + heightElement.textContent = getContentAreaHeightPx(style); + heightElement.addEventListener("dblclick", this.startEditing.bind(this, heightElement, "height", "height", style), false); + + boxElement.appendChild(widthElement); + boxElement.appendChild(document.createTextNode(" \u00D7 ")); + boxElement.appendChild(heightElement); + } else { + var suffix = (name === "border" ? "-width" : ""); + + var labelElement = document.createElement("div"); + labelElement.className = "label"; + labelElement.textContent = boxLabels[i]; + boxElement.appendChild(labelElement); + + boxElement.appendChild(createBoxPartElement.call(this, style, name, "top", suffix)); + boxElement.appendChild(document.createElement("br")); + boxElement.appendChild(createBoxPartElement.call(this, style, name, "left", suffix)); + + if (previousBox) + boxElement.appendChild(previousBox); + + boxElement.appendChild(createBoxPartElement.call(this, style, name, "right", suffix)); + boxElement.appendChild(document.createElement("br")); + boxElement.appendChild(createBoxPartElement.call(this, style, name, "bottom", suffix)); + } + + previousBox = boxElement; + } + + metricsElement.appendChild(previousBox); + metricsElement.addEventListener("mouseover", this._highlightDOMNode.bind(this, false, ""), false); + this.bodyElement.removeChildren(); + this.bodyElement.appendChild(metricsElement); + }, + + startEditing: function(targetElement, box, styleProperty, computedStyle) + { + if (WebInspector.isBeingEdited(targetElement)) + return; + + var context = { box: box, styleProperty: styleProperty, computedStyle: computedStyle }; + var boundKeyDown = this._handleKeyDown.bind(this, context, styleProperty); + context.keyDownHandler = boundKeyDown; + targetElement.addEventListener("keydown", boundKeyDown, false); + + this._isEditingMetrics = true; + + var config = new WebInspector.EditingConfig(this.editingCommitted.bind(this), this.editingCancelled.bind(this), context); + WebInspector.startEditing(targetElement, config); + + window.getSelection().setBaseAndExtent(targetElement, 0, targetElement, 1); + }, + + _handleKeyDown: function(context, styleProperty, event) + { + if (!/^(?:Page)?(?:Up|Down)$/.test(event.keyIdentifier)) + return; + var element = event.currentTarget; + + var selection = window.getSelection(); + if (!selection.rangeCount) + return; + + var selectionRange = selection.getRangeAt(0); + if (!selectionRange.commonAncestorContainer.isSelfOrDescendant(element)) + return; + + var originalValue = element.textContent; + var wordRange = selectionRange.startContainer.rangeOfWord(selectionRange.startOffset, WebInspector.StylesSidebarPane.StyleValueDelimiters, element); + var wordString = wordRange.toString(); + + var matches = /(.*?)(-?(?:\d+(?:\.\d+)?|\.\d+))(.*)/.exec(wordString); + var replacementString; + if (matches && matches.length) { + var prefix = matches[1]; + var suffix = matches[3]; + var number = WebInspector.StylesSidebarPane.alteredFloatNumber(parseFloat(matches[2]), event); + if (number === null) { + // Need to check for null explicitly. + return; + } + + if (styleProperty !== "margin" && number < 0) + number = 0; + + replacementString = prefix + number + suffix; + } + if (!replacementString) + return; + + var replacementTextNode = document.createTextNode(replacementString); + + wordRange.deleteContents(); + wordRange.insertNode(replacementTextNode); + + var finalSelectionRange = document.createRange(); + finalSelectionRange.setStart(replacementTextNode, 0); + finalSelectionRange.setEnd(replacementTextNode, replacementString.length); + + selection.removeAllRanges(); + selection.addRange(finalSelectionRange); + + event.handled = true; + event.preventDefault(); + this._applyUserInput(element, replacementString, originalValue, context, false); + }, + + editingEnded: function(element, context) + { + delete this.originalPropertyData; + delete this.previousPropertyDataCandidate; + element.removeEventListener("keydown", context.keyDownHandler, false); + delete this._isEditingMetrics; + }, + + editingCancelled: function(element, context) + { + if ("originalPropertyData" in this && this.inlineStyle) { + if (!this.originalPropertyData) { + // An added property, remove the last property in the style. + var pastLastSourcePropertyIndex = this.inlineStyle.pastLastSourcePropertyIndex(); + if (pastLastSourcePropertyIndex) + this.inlineStyle.allProperties[pastLastSourcePropertyIndex - 1].setText("", false); + } else + this.inlineStyle.allProperties[this.originalPropertyData.index].setText(this.originalPropertyData.propertyText, false); + } + this.editingEnded(element, context); + this.update(); + }, + + _applyUserInput: function(element, userInput, previousContent, context, commitEditor) + { + if (!this.inlineStyle) { + // Element has no renderer. + return this.editingCancelled(element, context); // nothing changed, so cancel + } + + if (commitEditor && userInput === previousContent) + return this.editingCancelled(element, context); // nothing changed, so cancel + + if (context.box !== "position" && (!userInput || userInput === "\u2012")) + userInput = "0px"; + else if (context.box === "position" && (!userInput || userInput === "\u2012")) + userInput = "auto"; + + userInput = userInput.toLowerCase(); + // Append a "px" unit if the user input was just a number. + if (/^\d+$/.test(userInput)) + userInput += "px"; + + var styleProperty = context.styleProperty; + var computedStyle = context.computedStyle; + + if (computedStyle.getPropertyValue("box-sizing") === "border-box" && (styleProperty === "width" || styleProperty === "height")) { + if (!userInput.match(/px$/)) { + WebInspector.log("For elements with box-sizing: border-box, only absolute content area dimensions can be applied", WebInspector.ConsoleMessage.MessageLevel.Error, true); + return; + } + + var borderBox = this._getBox(computedStyle, "border"); + var paddingBox = this._getBox(computedStyle, "padding"); + var userValuePx = Number(userInput.replace(/px$/, "")); + if (isNaN(userValuePx)) + return; + if (styleProperty === "width") + userValuePx += borderBox.left + borderBox.right + paddingBox.left + paddingBox.right; + else + userValuePx += borderBox.top + borderBox.bottom + paddingBox.top + paddingBox.bottom; + + userInput = userValuePx + "px"; + } + + this.previousPropertyDataCandidate = null; + var self = this; + var callback = function(style) { + if (!style) + return; + self.inlineStyle = style; + if (!("originalPropertyData" in self)) + self.originalPropertyData = self.previousPropertyDataCandidate; + + if (typeof self._highlightMode !== "undefined") { + WebInspector.domAgent.highlightDOMNode(self.node.id, self._highlightMode); + } + + if (commitEditor) { + self.dispatchEventToListeners("metrics edited"); + self.update(); + } + }; + + var allProperties = this.inlineStyle.allProperties; + for (var i = 0; i < allProperties.length; ++i) { + var property = allProperties[i]; + if (property.name !== context.styleProperty || property.inactive) + continue; + + this.previousPropertyDataCandidate = property; + property.setValue(userInput, commitEditor, callback); + return; + } + + this.inlineStyle.appendProperty(context.styleProperty, userInput, callback); + }, + + editingCommitted: function(element, userInput, previousContent, context) + { + this.editingEnded(element, context); + this._applyUserInput(element, userInput, previousContent, context, true); + } +} + +WebInspector.MetricsSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype; +/* PropertiesSidebarPane.js */ + +/* + * 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. + * 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. + */ + +/** + * @constructor + * @extends {WebInspector.SidebarPane} + */ +WebInspector.PropertiesSidebarPane = function() +{ + WebInspector.SidebarPane.call(this, WebInspector.UIString("Properties")); +} + +WebInspector.PropertiesSidebarPane._objectGroupName = "properties-sidebar-pane"; + +WebInspector.PropertiesSidebarPane.prototype = { + update: function(node) + { + var body = this.bodyElement; + + if (!node) { + body.removeChildren(); + this.sections = []; + return; + } + + WebInspector.RemoteObject.resolveNode(node, WebInspector.PropertiesSidebarPane._objectGroupName, nodeResolved.bind(this)); + + function nodeResolved(object) + { + if (!object) + return; + function protoList() + { + var proto = this; + var result = {}; + var counter = 1; + while (proto) { + result[counter++] = proto; + proto = proto.__proto__; + } + return result; + } + object.callFunction(protoList, nodePrototypesReady.bind(this)); + object.release(); + } + + function nodePrototypesReady(object) + { + if (!object) + return; + object.getOwnProperties(fillSection.bind(this)); + } + + function fillSection(prototypes) + { + if (!prototypes) + return; + + var body = this.bodyElement; + body.removeChildren(); + this.sections = []; + + // Get array of prototype user-friendly names. + for (var i = 0; i < prototypes.length; ++i) { + if (!parseInt(prototypes[i].name, 10)) + continue; + + var prototype = prototypes[i].value; + var title = prototype.description; + if (title.match(/Prototype$/)) + title = title.replace(/Prototype$/, ""); + var section = new WebInspector.ObjectPropertiesSection(prototype, title); + this.sections.push(section); + body.appendChild(section.element); + } + } + } +} + +WebInspector.PropertiesSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype; +/* EventListenersSidebarPane.js */ + +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * Copyright (C) 2009 Joseph Pecoraro + * + * 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. + */ + +/** + * @constructor + * @extends {WebInspector.SidebarPane} + */ +WebInspector.EventListenersSidebarPane = function() +{ + WebInspector.SidebarPane.call(this, WebInspector.UIString("Event Listeners")); + this.bodyElement.addStyleClass("events-pane"); + + this.sections = []; + + this.settingsSelectElement = document.createElement("select"); + this.settingsSelectElement.className = "select-filter"; + + var option = document.createElement("option"); + option.value = "all"; + option.label = WebInspector.UIString("All Nodes"); + this.settingsSelectElement.appendChild(option); + + option = document.createElement("option"); + option.value = "selected"; + option.label = WebInspector.UIString("Selected Node Only"); + this.settingsSelectElement.appendChild(option); + + var filter = WebInspector.settings.eventListenersFilter.get(); + if (filter === "all") + this.settingsSelectElement[0].selected = true; + else if (filter === "selected") + this.settingsSelectElement[1].selected = true; + this.settingsSelectElement.addEventListener("click", function(event) { event.stopPropagation() }, false); + this.settingsSelectElement.addEventListener("change", this._changeSetting.bind(this), false); + + this.titleElement.appendChild(this.settingsSelectElement); + + this._linkifier = WebInspector.debuggerPresentationModel.createLinkifier(); +} + +WebInspector.EventListenersSidebarPane._objectGroupName = "event-listeners-sidebar-pane"; + +WebInspector.EventListenersSidebarPane.prototype = { + update: function(node) + { + RuntimeAgent.releaseObjectGroup(WebInspector.EventListenersSidebarPane._objectGroupName); + this._linkifier.reset(); + + var body = this.bodyElement; + body.removeChildren(); + this.sections = []; + + var self = this; + function callback(error, eventListeners) { + if (error) + return; + + var sectionNames = []; + var sectionMap = {}; + for (var i = 0; i < eventListeners.length; ++i) { + var eventListener = eventListeners[i]; + eventListener.node = WebInspector.domAgent.nodeForId(eventListener.nodeId); + delete eventListener.nodeId; // no longer needed + if (/^function _inspectorCommandLineAPI_logEvent\(/.test(eventListener.handlerBody.toString())) + continue; // ignore event listeners generated by monitorEvent + var type = eventListener.type; + var section = sectionMap[type]; + if (!section) { + section = new WebInspector.EventListenersSection(type, node.id, self._linkifier); + sectionMap[type] = section; + sectionNames.push(type); + self.sections.push(section); + } + section.addListener(eventListener); + } + + if (sectionNames.length === 0) { + var div = document.createElement("div"); + div.className = "info"; + div.textContent = WebInspector.UIString("No Event Listeners"); + body.appendChild(div); + return; + } + + sectionNames.sort(); + for (var i = 0; i < sectionNames.length; ++i) { + var section = sectionMap[sectionNames[i]]; + section.update(); + body.appendChild(section.element); + } + } + + if (node) + node.eventListeners(callback); + }, + + _changeSetting: function(event) + { + var selectedOption = this.settingsSelectElement[this.settingsSelectElement.selectedIndex]; + WebInspector.settings.eventListenersFilter.set(selectedOption.value); + + for (var i = 0; i < this.sections.length; ++i) + this.sections[i].update(); + } +} + +WebInspector.EventListenersSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype; + +/** + * @constructor + * @extends {WebInspector.PropertiesSection} + */ +WebInspector.EventListenersSection = function(title, nodeId, linkifier) +{ + this.eventListeners = []; + this._nodeId = nodeId; + this._linkifier = linkifier; + WebInspector.PropertiesSection.call(this, title); + + // Changed from a Properties List + this.propertiesElement.parentNode.removeChild(this.propertiesElement); + delete this.propertiesElement; + delete this.propertiesTreeOutline; + + this.eventBars = document.createElement("div"); + this.eventBars.className = "event-bars"; + this.element.appendChild(this.eventBars); +} + +WebInspector.EventListenersSection.prototype = { + update: function() + { + // A Filtered Array simplifies when to create connectors + var filteredEventListeners = this.eventListeners; + if (WebInspector.settings.eventListenersFilter.get() == "selected") { + filteredEventListeners = []; + for (var i = 0; i < this.eventListeners.length; ++i) { + var eventListener = this.eventListeners[i]; + if (eventListener.node.id === this._nodeId) + filteredEventListeners.push(eventListener); + } + } + + this.eventBars.removeChildren(); + var length = filteredEventListeners.length; + for (var i = 0; i < length; ++i) { + var eventListener = filteredEventListeners[i]; + var eventListenerBar = new WebInspector.EventListenerBar(eventListener, this._nodeId, this._linkifier); + this.eventBars.appendChild(eventListenerBar.element); + } + }, + + addListener: function(eventListener) + { + this.eventListeners.push(eventListener); + } +} + +WebInspector.EventListenersSection.prototype.__proto__ = WebInspector.PropertiesSection.prototype; + +/** + * @constructor + * @extends {WebInspector.ObjectPropertiesSection} + */ +WebInspector.EventListenerBar = function(eventListener, nodeId, linkifier) +{ + WebInspector.ObjectPropertiesSection.call(this); + + this.eventListener = eventListener; + this._nodeId = nodeId; + this._setNodeTitle(); + this._setFunctionSubtitle(linkifier); + this.editable = false; + this.element.className = "event-bar"; /* Changed from "section" */ + this.headerElement.addStyleClass("source-code"); + this.propertiesElement.className = "event-properties properties-tree source-code"; /* Changed from "properties" */ +} + +WebInspector.EventListenerBar.prototype = { + update: function() + { + function updateWithNodeObject(nodeObject) + { + var properties = []; + + if (this.eventListener.type) + properties.push(WebInspector.RemoteObjectProperty.fromPrimitiveValue("type", this.eventListener.type)); + if (typeof this.eventListener.useCapture !== "undefined") + properties.push(WebInspector.RemoteObjectProperty.fromPrimitiveValue("useCapture", this.eventListener.useCapture)); + if (typeof this.eventListener.isAttribute !== "undefined") + properties.push(WebInspector.RemoteObjectProperty.fromPrimitiveValue("isAttribute", this.eventListener.isAttribute)); + if (nodeObject) + properties.push(new WebInspector.RemoteObjectProperty("node", nodeObject)); + if (typeof this.eventListener.handlerBody !== "undefined") + properties.push(WebInspector.RemoteObjectProperty.fromPrimitiveValue("listenerBody", this.eventListener.handlerBody)); + if (this.eventListener.location) { + properties.push(WebInspector.RemoteObjectProperty.fromPrimitiveValue("sourceName", this.eventListener.location.scriptId)); + properties.push(WebInspector.RemoteObjectProperty.fromPrimitiveValue("lineNumber", this.eventListener.location.lineNumber)); + } + + this.updateProperties(properties); + } + WebInspector.RemoteObject.resolveNode(this.eventListener.node, WebInspector.EventListenersSidebarPane._objectGroupName, updateWithNodeObject.bind(this)); + }, + + _setNodeTitle: function() + { + var node = this.eventListener.node; + if (!node) + return; + + if (node.nodeType() === Node.DOCUMENT_NODE) { + this.titleElement.textContent = "document"; + return; + } + + if (node.id === this._nodeId) { + this.titleElement.textContent = node.appropriateSelectorFor(); + return; + } + + this.titleElement.removeChildren(); + this.titleElement.appendChild(WebInspector.DOMPresentationUtils.linkifyNodeReference(this.eventListener.node)); + }, + + _setFunctionSubtitle: function(linkifier) + { + // Requires that Function.toString() return at least the function's signature. + if (this.eventListener.location) { + this.subtitleElement.removeChildren(); + // FIXME(62725): eventListener.location should be a debugger Location. + var url = this.eventListener.location.scriptId; + var lineNumber = this.eventListener.location.lineNumber - 1; + var columnNumber = 0; + var urlElement = linkifier.linkifyLocation(url, lineNumber, columnNumber); + this.subtitleElement.appendChild(urlElement); + } else { + var match = this.eventListener.handlerBody.match(/function ([^\(]+?)\(/); + if (match) + this.subtitleElement.textContent = match[1]; + else + this.subtitleElement.textContent = WebInspector.UIString("(anonymous function)"); + } + } +} + +WebInspector.EventListenerBar.prototype.__proto__ = WebInspector.ObjectPropertiesSection.prototype; +/* Color.js */ + +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2009 Joseph Pecoraro + * + * 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. + */ + +/** + * @constructor + */ +WebInspector.Color = function(str) +{ + this.value = str; + this._parse(); +} + +/** + * @param {number=} a + */ +WebInspector.Color.fromRGBA = function(r, g, b, a) +{ + return new WebInspector.Color("rgba(" + r + "," + g + "," + b + "," + (typeof a === "undefined" ? 1 : a) + ")"); +} + +WebInspector.Color.prototype = { + /** + * @return {string} + */ + get shorthex() + { + if ("_short" in this) + return this._short; + + if (!this.simple) + return ""; + + var hex = this.hex; + if (hex.charAt(0) === hex.charAt(1) && hex.charAt(2) === hex.charAt(3) && hex.charAt(4) === hex.charAt(5)) + this._short = hex.charAt(0) + hex.charAt(2) + hex.charAt(4); + else + this._short = hex; + + return this._short; + }, + + /** + * @return {string} + */ + get hex() + { + if (!this.simple) + return ""; + + return this._hex; + }, + + set hex(x) + { + this._hex = x; + }, + + /** + * @return {Array.} + */ + get rgb() + { + if (this._rgb) + return this._rgb; + + if (this.simple) + this._rgb = this._hexToRGB(this.hex); + else { + var rgba = this.rgba; + this._rgb = [rgba[0], rgba[1], rgba[2]]; + } + + return this._rgb; + }, + + set rgb(x) + { + this._rgb = x; + }, + + /** + * @return {Array.} + */ + get hsl() + { + if (this._hsl) + return this._hsl; + + this._hsl = this._rgbToHSL(this.rgb); + return this._hsl; + }, + + set hsl(x) + { + this._hsl = x; + }, + + /** + * @return {string} + */ + get nickname() + { + if (typeof this._nickname !== "undefined") // would be set on parse if there was a nickname + return this._nickname; + else + return ""; + }, + + set nickname(x) + { + this._nickname = x; + }, + + /** + * @return {Array.} + */ + get rgba() + { + return this._rgba; + }, + + set rgba(x) + { + this._rgba = x; + }, + + /** + * @return {Array.} + */ + get hsla() + { + return this._hsla; + }, + + set hsla(x) + { + this._hsla = x; + }, + + /** + * @return {boolean} + */ + hasShortHex: function() + { + var shorthex = this.shorthex; + return (!!shorthex && shorthex.length === 3); + }, + + /** + * @return {string} + */ + toString: function(format) + { + if (!format) + format = this.format; + + switch (format) { + case "original": + return this.value; + case "rgb": + return "rgb(" + this.rgb.join(", ") + ")"; + case "rgba": + return "rgba(" + this.rgba.join(", ") + ")"; + case "hsl": + var hsl = this.hsl; + return "hsl(" + hsl[0] + ", " + hsl[1] + "%, " + hsl[2] + "%)"; + case "hsla": + var hsla = this.hsla; + return "hsla(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%, " + hsla[3] + ")"; + case "hex": + return "#" + this.hex; + case "shorthex": + return "#" + this.shorthex; + case "nickname": + return this.nickname; + } + + throw "invalid color format"; + }, + + /** + * @return {Object} + */ + toProtocolRGBA: function() + { + if (this._protocolRGBA) + return this._protocolRGBA; + + var components = this.rgba; + if (components) + this._protocolRGBA = { r: Number(components[0]), g: Number(components[1]), b: Number(components[2]), a: Number(components[3]) }; + else { + components = this.rgb; + this._protocolRGBA = { r: Number(components[0]), g: Number(components[1]), b: Number(components[2]) }; + } + return this._protocolRGBA; + }, + + /** + * @param {number} value + * @param {number} min + * @param {number} max + * @return {number} + */ + _clamp: function(value, min, max) + { + if (value < min) + return min; + if (value > max) + return max; + return value; + }, + + /** + * @param {number|string} rgbValue + * @return {number} + */ + _individualRGBValueToFloatValue: function(rgbValue) + { + if (typeof rgbValue === "number") + return this._clamp(rgbValue, 0, 255); + + if (rgbValue.indexOf("%") === -1) { + var intValue = parseInt(rgbValue, 10); + return this._clamp(intValue, 0, 255); + } + + var percentValue = parseFloat(rgbValue); + return this._clamp(percentValue, 0, 100) * 2.55; + }, + + /** + * @param {number|string} rgbValue + * @return {string} + */ + _individualRGBValueToHexValue: function(rgbValue) + { + var floatValue = this._individualRGBValueToFloatValue(rgbValue); + var hex = Math.round(floatValue).toString(16); + if (hex.length === 1) + hex = "0" + hex; + return hex; + }, + + /** + * @param {Array.} rgb + * @return {string} + */ + _rgbStringsToHex: function(rgb) + { + var r = this._individualRGBValueToHexValue(rgb[0]); + var g = this._individualRGBValueToHexValue(rgb[1]); + var b = this._individualRGBValueToHexValue(rgb[2]); + return (r + g + b).toUpperCase(); + }, + + /** + * @param {Array.} rgb + * @return {string} + */ + _rgbToHex: function(rgb) + { + var r = this._individualRGBValueToHexValue(rgb[0]); + var g = this._individualRGBValueToHexValue(rgb[1]); + var b = this._individualRGBValueToHexValue(rgb[2]); + return (r + g + b).toUpperCase(); + }, + + /** + * @param {string} hex + * @return {Array.} + */ + _hexToRGB: function(hex) + { + var r = parseInt(hex.substring(0,2), 16); + var g = parseInt(hex.substring(2,4), 16); + var b = parseInt(hex.substring(4,6), 16); + + return [r, g, b]; + }, + + /** + * @param {Array.} rgb + * @return {Array.} + */ + _rgbToHSL: function(rgb) + { + var r = this._individualRGBValueToFloatValue(rgb[0]) / 255; + var g = this._individualRGBValueToFloatValue(rgb[1]) / 255; + var b = this._individualRGBValueToFloatValue(rgb[2]) / 255; + var max = Math.max(r, g, b); + var min = Math.min(r, g, b); + var diff = max - min; + var add = max + min; + + if (min === max) + var h = 0; + else if (r === max) + var h = ((60 * (g - b) / diff) + 360) % 360; + else if (g === max) + var h = (60 * (b - r) / diff) + 120; + else + var h = (60 * (r - g) / diff) + 240; + + var l = 0.5 * add; + + if (l === 0) + var s = 0; + else if (l === 1) + var s = 1; + else if (l <= 0.5) + var s = diff / add; + else + var s = diff / (2 - add); + + h = Math.round(h); + s = Math.round(s*100); + l = Math.round(l*100); + + return [h, s, l]; + }, + + /** + * @param {Array.} hsl + * @return {Array.} + */ + _hslToRGB: function(hsl) + { + var h = parseFloat(hsl[0]) / 360; + var s = parseFloat(hsl[1]) / 100; + var l = parseFloat(hsl[2]) / 100; + + if (s < 0) + s = 0; + + if (l <= 0.5) + var q = l * (1 + s); + else + var q = l + s - (l * s); + + var p = 2 * l - q; + + var tr = h + (1 / 3); + var tg = h; + var tb = h - (1 / 3); + + var r = Math.round(hueToRGB(p, q, tr) * 255); + var g = Math.round(hueToRGB(p, q, tg) * 255); + var b = Math.round(hueToRGB(p, q, tb) * 255); + return [r, g, b]; + + function hueToRGB(p, q, h) { + if (h < 0) + h += 1; + else if (h > 1) + h -= 1; + + if ((h * 6) < 1) + return p + (q - p) * h * 6; + else if ((h * 2) < 1) + return q; + else if ((h * 3) < 2) + return p + (q - p) * ((2 / 3) - h) * 6; + else + return p; + } + }, + + /** + * @param {Array.} rgba + * @return {Array.} + */ + _rgbaToHSLA: function(rgba, alpha) + { + var hsl = this._rgbToHSL(rgba) + hsl.push(alpha); + return hsl; + }, + + /** + * @param {Array.} hsla + * @param {number} alpha + * @return {Array.} + */ + _hslaToRGBA: function(hsla, alpha) + { + var rgb = this._hslToRGB(hsla); + rgb.push(alpha); + return rgb; + }, + + _parse: function() + { + // Special Values - Advanced but Must Be Parsed First - transparent + var value = this.value.toLowerCase().replace(/%|\s+/g, ""); + if (value in WebInspector.Color.AdvancedNickNames) { + this.format = "nickname"; + var set = WebInspector.Color.AdvancedNickNames[value]; + this.simple = false; + this.rgba = set[0]; + this.hsla = set[1]; + this.nickname = set[2]; + this.alpha = set[0][3]; + return; + } + + // Simple - #hex, rgb(), nickname, hsl() + var simple = /^(?:#([0-9a-f]{3,6})|rgb\(([^)]+)\)|(\w+)|hsl\(([^)]+)\))$/i; + var match = this.value.match(simple); + if (match) { + this.simple = true; + + if (match[1]) { // hex + var hex = match[1].toUpperCase(); + if (hex.length === 3) { + this.format = "shorthex"; + this.hex = hex.charAt(0) + hex.charAt(0) + hex.charAt(1) + hex.charAt(1) + hex.charAt(2) + hex.charAt(2); + } else { + this.format = "hex"; + this.hex = hex; + } + } else if (match[2]) { // rgb + this.format = "rgb"; + var rgb = match[2].split(/\s*,\s*/); + this.rgb = rgb; + this.hex = this._rgbStringsToHex(rgb); + } else if (match[3]) { // nickname + var nickname = match[3].toLowerCase(); + if (nickname in WebInspector.Color.Nicknames) { + this.format = "nickname"; + this.hex = WebInspector.Color.Nicknames[nickname]; + } else // unknown name + throw "unknown color name"; + } else if (match[4]) { // hsl + this.format = "hsl"; + var hsl = match[4].replace(/%/g, "").split(/\s*,\s*/); + this.hsl = hsl; + this.rgb = this._hslToRGB(hsl); + this.hex = this._rgbToHex(this.rgb); + } + + // Fill in the values if this is a known hex color + var hex = this.hex; + if (hex && hex in WebInspector.Color.HexTable) { + var set = WebInspector.Color.HexTable[hex]; + this.rgb = set[0]; + this.hsl = set[1]; + this.nickname = set[2]; + } + + return; + } + + // Advanced - rgba(), hsla() + var advanced = /^(?:rgba\(([^)]+)\)|hsla\(([^)]+)\))$/; + match = this.value.match(advanced); + if (match) { + this.simple = false; + if (match[1]) { // rgba + this.format = "rgba"; + this.rgba = match[1].split(/\s*,\s*/); + this.rgba[3] = this.alpha = this._clamp(this.rgba[3], 0, 1); + this.hsla = this._rgbaToHSLA(this.rgba, this.alpha); + } else if (match[2]) { // hsla + this.format = "hsla"; + this.hsla = match[2].replace(/%/g, "").split(/\s*,\s*/); + this.hsla[3] = this.alpha = this._clamp(this.hsla[3], 0, 1); + this.rgba = this._hslaToRGBA(this.hsla, this.alpha); + } + + return; + } + + // Could not parse as a valid color + throw "could not parse color"; + } +} + +// Simple Values: [rgb, hsl, nickname] +WebInspector.Color.HexTable = { + "000000": [[0, 0, 0], [0, 0, 0], "black"], + "000080": [[0, 0, 128], [240, 100, 25], "navy"], + "00008B": [[0, 0, 139], [240, 100, 27], "darkBlue"], + "0000CD": [[0, 0, 205], [240, 100, 40], "mediumBlue"], + "0000FF": [[0, 0, 255], [240, 100, 50], "blue"], + "006400": [[0, 100, 0], [120, 100, 20], "darkGreen"], + "008000": [[0, 128, 0], [120, 100, 25], "green"], + "008080": [[0, 128, 128], [180, 100, 25], "teal"], + "008B8B": [[0, 139, 139], [180, 100, 27], "darkCyan"], + "00BFFF": [[0, 191, 255], [195, 100, 50], "deepSkyBlue"], + "00CED1": [[0, 206, 209], [181, 100, 41], "darkTurquoise"], + "00FA9A": [[0, 250, 154], [157, 100, 49], "mediumSpringGreen"], + "00FF00": [[0, 255, 0], [120, 100, 50], "lime"], + "00FF7F": [[0, 255, 127], [150, 100, 50], "springGreen"], + "00FFFF": [[0, 255, 255], [180, 100, 50], "cyan"], + "191970": [[25, 25, 112], [240, 64, 27], "midnightBlue"], + "1E90FF": [[30, 144, 255], [210, 100, 56], "dodgerBlue"], + "20B2AA": [[32, 178, 170], [177, 70, 41], "lightSeaGreen"], + "228B22": [[34, 139, 34], [120, 61, 34], "forestGreen"], + "2E8B57": [[46, 139, 87], [146, 50, 36], "seaGreen"], + "2F4F4F": [[47, 79, 79], [180, 25, 25], "darkSlateGray"], + "32CD32": [[50, 205, 50], [120, 61, 50], "limeGreen"], + "3CB371": [[60, 179, 113], [147, 50, 47], "mediumSeaGreen"], + "40E0D0": [[64, 224, 208], [174, 72, 56], "turquoise"], + "4169E1": [[65, 105, 225], [225, 73, 57], "royalBlue"], + "4682B4": [[70, 130, 180], [207, 44, 49], "steelBlue"], + "483D8B": [[72, 61, 139], [248, 39, 39], "darkSlateBlue"], + "48D1CC": [[72, 209, 204], [178, 60, 55], "mediumTurquoise"], + "4B0082": [[75, 0, 130], [275, 100, 25], "indigo"], + "556B2F": [[85, 107, 47], [82, 39, 30], "darkOliveGreen"], + "5F9EA0": [[95, 158, 160], [182, 25, 50], "cadetBlue"], + "6495ED": [[100, 149, 237], [219, 79, 66], "cornflowerBlue"], + "66CDAA": [[102, 205, 170], [160, 51, 60], "mediumAquaMarine"], + "696969": [[105, 105, 105], [0, 0, 41], "dimGray"], + "6A5ACD": [[106, 90, 205], [248, 53, 58], "slateBlue"], + "6B8E23": [[107, 142, 35], [80, 60, 35], "oliveDrab"], + "708090": [[112, 128, 144], [210, 13, 50], "slateGray"], + "778899": [[119, 136, 153], [210, 14, 53], "lightSlateGray"], + "7B68EE": [[123, 104, 238], [249, 80, 67], "mediumSlateBlue"], + "7CFC00": [[124, 252, 0], [90, 100, 49], "lawnGreen"], + "7FFF00": [[127, 255, 0], [90, 100, 50], "chartreuse"], + "7FFFD4": [[127, 255, 212], [160, 100, 75], "aquamarine"], + "800000": [[128, 0, 0], [0, 100, 25], "maroon"], + "800080": [[128, 0, 128], [300, 100, 25], "purple"], + "808000": [[128, 128, 0], [60, 100, 25], "olive"], + "808080": [[128, 128, 128], [0, 0, 50], "gray"], + "87CEEB": [[135, 206, 235], [197, 71, 73], "skyBlue"], + "87CEFA": [[135, 206, 250], [203, 92, 75], "lightSkyBlue"], + "8A2BE2": [[138, 43, 226], [271, 76, 53], "blueViolet"], + "8B0000": [[139, 0, 0], [0, 100, 27], "darkRed"], + "8B008B": [[139, 0, 139], [300, 100, 27], "darkMagenta"], + "8B4513": [[139, 69, 19], [25, 76, 31], "saddleBrown"], + "8FBC8F": [[143, 188, 143], [120, 25, 65], "darkSeaGreen"], + "90EE90": [[144, 238, 144], [120, 73, 75], "lightGreen"], + "9370D8": [[147, 112, 219], [260, 60, 65], "mediumPurple"], + "9400D3": [[148, 0, 211], [282, 100, 41], "darkViolet"], + "98FB98": [[152, 251, 152], [120, 93, 79], "paleGreen"], + "9932CC": [[153, 50, 204], [280, 61, 50], "darkOrchid"], + "9ACD32": [[154, 205, 50], [80, 61, 50], "yellowGreen"], + "A0522D": [[160, 82, 45], [19, 56, 40], "sienna"], + "A52A2A": [[165, 42, 42], [0, 59, 41], "brown"], + "A9A9A9": [[169, 169, 169], [0, 0, 66], "darkGray"], + "ADD8E6": [[173, 216, 230], [195, 53, 79], "lightBlue"], + "ADFF2F": [[173, 255, 47], [84, 100, 59], "greenYellow"], + "AFEEEE": [[175, 238, 238], [180, 65, 81], "paleTurquoise"], + "B0C4DE": [[176, 196, 222], [214, 41, 78], "lightSteelBlue"], + "B0E0E6": [[176, 224, 230], [187, 52, 80], "powderBlue"], + "B22222": [[178, 34, 34], [0, 68, 42], "fireBrick"], + "B8860B": [[184, 134, 11], [43, 89, 38], "darkGoldenrod"], + "BA55D3": [[186, 85, 211], [288, 59, 58], "mediumOrchid"], + "BC8F8F": [[188, 143, 143], [0, 25, 65], "rosyBrown"], + "BDB76B": [[189, 183, 107], [56, 38, 58], "darkKhaki"], + "C0C0C0": [[192, 192, 192], [0, 0, 75], "silver"], + "C71585": [[199, 21, 133], [322, 81, 43], "mediumVioletRed"], + "CD5C5C": [[205, 92, 92], [0, 53, 58], "indianRed"], + "CD853F": [[205, 133, 63], [30, 59, 53], "peru"], + "D2691E": [[210, 105, 30], [25, 75, 47], "chocolate"], + "D2B48C": [[210, 180, 140], [34, 44, 69], "tan"], + "D3D3D3": [[211, 211, 211], [0, 0, 83], "lightGrey"], + "D87093": [[219, 112, 147], [340, 60, 65], "paleVioletRed"], + "D8BFD8": [[216, 191, 216], [300, 24, 80], "thistle"], + "DA70D6": [[218, 112, 214], [302, 59, 65], "orchid"], + "DAA520": [[218, 165, 32], [43, 74, 49], "goldenrod"], + "DC143C": [[237, 164, 61], [35, 83, 58], "crimson"], + "DCDCDC": [[220, 220, 220], [0, 0, 86], "gainsboro"], + "DDA0DD": [[221, 160, 221], [300, 47, 75], "plum"], + "DEB887": [[222, 184, 135], [34, 57, 70], "burlyWood"], + "E0FFFF": [[224, 255, 255], [180, 100, 94], "lightCyan"], + "E6E6FA": [[230, 230, 250], [240, 67, 94], "lavender"], + "E9967A": [[233, 150, 122], [15, 72, 70], "darkSalmon"], + "EE82EE": [[238, 130, 238], [300, 76, 72], "violet"], + "EEE8AA": [[238, 232, 170], [55, 67, 80], "paleGoldenrod"], + "F08080": [[240, 128, 128], [0, 79, 72], "lightCoral"], + "F0E68C": [[240, 230, 140], [54, 77, 75], "khaki"], + "F0F8FF": [[240, 248, 255], [208, 100, 97], "aliceBlue"], + "F0FFF0": [[240, 255, 240], [120, 100, 97], "honeyDew"], + "F0FFFF": [[240, 255, 255], [180, 100, 97], "azure"], + "F4A460": [[244, 164, 96], [28, 87, 67], "sandyBrown"], + "F5DEB3": [[245, 222, 179], [39, 77, 83], "wheat"], + "F5F5DC": [[245, 245, 220], [60, 56, 91], "beige"], + "F5F5F5": [[245, 245, 245], [0, 0, 96], "whiteSmoke"], + "F5FFFA": [[245, 255, 250], [150, 100, 98], "mintCream"], + "F8F8FF": [[248, 248, 255], [240, 100, 99], "ghostWhite"], + "FA8072": [[250, 128, 114], [6, 93, 71], "salmon"], + "FAEBD7": [[250, 235, 215], [34, 78, 91], "antiqueWhite"], + "FAF0E6": [[250, 240, 230], [30, 67, 94], "linen"], + "FAFAD2": [[250, 250, 210], [60, 80, 90], "lightGoldenrodYellow"], + "FDF5E6": [[253, 245, 230], [39, 85, 95], "oldLace"], + "FF0000": [[255, 0, 0], [0, 100, 50], "red"], + "FF00FF": [[255, 0, 255], [300, 100, 50], "magenta"], + "FF1493": [[255, 20, 147], [328, 100, 54], "deepPink"], + "FF4500": [[255, 69, 0], [16, 100, 50], "orangeRed"], + "FF6347": [[255, 99, 71], [9, 100, 64], "tomato"], + "FF69B4": [[255, 105, 180], [330, 100, 71], "hotPink"], + "FF7F50": [[255, 127, 80], [16, 100, 66], "coral"], + "FF8C00": [[255, 140, 0], [33, 100, 50], "darkOrange"], + "FFA07A": [[255, 160, 122], [17, 100, 74], "lightSalmon"], + "FFA500": [[255, 165, 0], [39, 100, 50], "orange"], + "FFB6C1": [[255, 182, 193], [351, 100, 86], "lightPink"], + "FFC0CB": [[255, 192, 203], [350, 100, 88], "pink"], + "FFD700": [[255, 215, 0], [51, 100, 50], "gold"], + "FFDAB9": [[255, 218, 185], [28, 100, 86], "peachPuff"], + "FFDEAD": [[255, 222, 173], [36, 100, 84], "navajoWhite"], + "FFE4B5": [[255, 228, 181], [38, 100, 85], "moccasin"], + "FFE4C4": [[255, 228, 196], [33, 100, 88], "bisque"], + "FFE4E1": [[255, 228, 225], [6, 100, 94], "mistyRose"], + "FFEBCD": [[255, 235, 205], [36, 100, 90], "blanchedAlmond"], + "FFEFD5": [[255, 239, 213], [37, 100, 92], "papayaWhip"], + "FFF0F5": [[255, 240, 245], [340, 100, 97], "lavenderBlush"], + "FFF5EE": [[255, 245, 238], [25, 100, 97], "seaShell"], + "FFF8DC": [[255, 248, 220], [48, 100, 93], "cornsilk"], + "FFFACD": [[255, 250, 205], [54, 100, 90], "lemonChiffon"], + "FFFAF0": [[255, 250, 240], [40, 100, 97], "floralWhite"], + "FFFAFA": [[255, 250, 250], [0, 100, 99], "snow"], + "FFFF00": [[255, 255, 0], [60, 100, 50], "yellow"], + "FFFFE0": [[255, 255, 224], [60, 100, 94], "lightYellow"], + "FFFFF0": [[255, 255, 240], [60, 100, 97], "ivory"], + "FFFFFF": [[255, 255, 255], [0, 100, 100], "white"] +}; + +// Simple Values +WebInspector.Color.Nicknames = { + "aliceblue": "F0F8FF", + "antiquewhite": "FAEBD7", + "aqua": "00FFFF", + "aquamarine": "7FFFD4", + "azure": "F0FFFF", + "beige": "F5F5DC", + "bisque": "FFE4C4", + "black": "000000", + "blanchedalmond": "FFEBCD", + "blue": "0000FF", + "blueviolet": "8A2BE2", + "brown": "A52A2A", + "burlywood": "DEB887", + "cadetblue": "5F9EA0", + "chartreuse": "7FFF00", + "chocolate": "D2691E", + "coral": "FF7F50", + "cornflowerblue": "6495ED", + "cornsilk": "FFF8DC", + "crimson": "DC143C", + "cyan": "00FFFF", + "darkblue": "00008B", + "darkcyan": "008B8B", + "darkgoldenrod": "B8860B", + "darkgray": "A9A9A9", + "darkgreen": "006400", + "darkkhaki": "BDB76B", + "darkmagenta": "8B008B", + "darkolivegreen": "556B2F", + "darkorange": "FF8C00", + "darkorchid": "9932CC", + "darkred": "8B0000", + "darksalmon": "E9967A", + "darkseagreen": "8FBC8F", + "darkslateblue": "483D8B", + "darkslategray": "2F4F4F", + "darkturquoise": "00CED1", + "darkviolet": "9400D3", + "deeppink": "FF1493", + "deepskyblue": "00BFFF", + "dimgray": "696969", + "dodgerblue": "1E90FF", + "firebrick": "B22222", + "floralwhite": "FFFAF0", + "forestgreen": "228B22", + "fuchsia": "FF00FF", + "gainsboro": "DCDCDC", + "ghostwhite": "F8F8FF", + "gold": "FFD700", + "goldenrod": "DAA520", + "gray": "808080", + "green": "008000", + "greenyellow": "ADFF2F", + "honeydew": "F0FFF0", + "hotpink": "FF69B4", + "indianred": "CD5C5C", + "indigo": "4B0082", + "ivory": "FFFFF0", + "khaki": "F0E68C", + "lavender": "E6E6FA", + "lavenderblush": "FFF0F5", + "lawngreen": "7CFC00", + "lemonchiffon": "FFFACD", + "lightblue": "ADD8E6", + "lightcoral": "F08080", + "lightcyan": "E0FFFF", + "lightgoldenrodyellow": "FAFAD2", + "lightgreen": "90EE90", + "lightgrey": "D3D3D3", + "lightpink": "FFB6C1", + "lightsalmon": "FFA07A", + "lightseagreen": "20B2AA", + "lightskyblue": "87CEFA", + "lightslategray": "778899", + "lightsteelblue": "B0C4DE", + "lightyellow": "FFFFE0", + "lime": "00FF00", + "limegreen": "32CD32", + "linen": "FAF0E6", + "magenta": "FF00FF", + "maroon": "800000", + "mediumaquamarine": "66CDAA", + "mediumblue": "0000CD", + "mediumorchid": "BA55D3", + "mediumpurple": "9370DB", + "mediumseagreen": "3CB371", + "mediumslateblue": "7B68EE", + "mediumspringgreen": "00FA9A", + "mediumturquoise": "48D1CC", + "mediumvioletred": "C71585", + "midnightblue": "191970", + "mintcream": "F5FFFA", + "mistyrose": "FFE4E1", + "moccasin": "FFE4B5", + "navajowhite": "FFDEAD", + "navy": "000080", + "oldlace": "FDF5E6", + "olive": "808000", + "olivedrab": "6B8E23", + "orange": "FFA500", + "orangered": "FF4500", + "orchid": "DA70D6", + "palegoldenrod": "EEE8AA", + "palegreen": "98FB98", + "paleturquoise": "AFEEEE", + "palevioletred": "DB7093", + "papayawhip": "FFEFD5", + "peachpuff": "FFDAB9", + "peru": "CD853F", + "pink": "FFC0CB", + "plum": "DDA0DD", + "powderblue": "B0E0E6", + "purple": "800080", + "red": "FF0000", + "rosybrown": "BC8F8F", + "royalblue": "4169E1", + "saddlebrown": "8B4513", + "salmon": "FA8072", + "sandybrown": "F4A460", + "seagreen": "2E8B57", + "seashell": "FFF5EE", + "sienna": "A0522D", + "silver": "C0C0C0", + "skyblue": "87CEEB", + "slateblue": "6A5ACD", + "slategray": "708090", + "snow": "FFFAFA", + "springgreen": "00FF7F", + "steelblue": "4682B4", + "tan": "D2B48C", + "teal": "008080", + "thistle": "D8BFD8", + "tomato": "FF6347", + "turquoise": "40E0D0", + "violet": "EE82EE", + "wheat": "F5DEB3", + "white": "FFFFFF", + "whitesmoke": "F5F5F5", + "yellow": "FFFF00", + "yellowgreen": "9ACD32" +}; + +// Advanced Values [rgba, hsla, nickname] +WebInspector.Color.AdvancedNickNames = { + "transparent": [[0, 0, 0, 0], [0, 0, 0, 0], "transparent"], + "rgba(0,0,0,0)": [[0, 0, 0, 0], [0, 0, 0, 0], "transparent"], + "hsla(0,0,0,0)": [[0, 0, 0, 0], [0, 0, 0, 0], "transparent"], +}; + +WebInspector.Color.PageHighlight = { + Content: WebInspector.Color.fromRGBA(111, 168, 220, .66), + ContentLight: WebInspector.Color.fromRGBA(111, 168, 220, .5), + ContentOutline: WebInspector.Color.fromRGBA(9, 83, 148), + Padding: WebInspector.Color.fromRGBA(147, 196, 125, .55), + PaddingLight: WebInspector.Color.fromRGBA(147, 196, 125, .4), + Border: WebInspector.Color.fromRGBA(255, 229, 153, .66), + BorderLight: WebInspector.Color.fromRGBA(255, 229, 153, .5), + Margin: WebInspector.Color.fromRGBA(246, 178, 107, .66), + MarginLight: WebInspector.Color.fromRGBA(246, 178, 107, .5) +} +/* CSSCompletions.js */ + +/* + * Copyright (C) 2010 Nikita Vasilyev. All rights reserved. + * Copyright (C) 2010 Joseph Pecoraro. All rights reserved. + * 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. + * * 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. + */ + +/** + * @constructor + */ +WebInspector.CSSCompletions = function(values, acceptEmptyPrefix) +{ + this._values = values.slice(); + this._values.sort(); + this._acceptEmptyPrefix = acceptEmptyPrefix; +} + + +/** + * @type {WebInspector.CSSCompletions} + */ +WebInspector.CSSCompletions.cssNameCompletions = null; + +WebInspector.CSSCompletions.requestCSSNameCompletions = function() +{ + function propertyNamesCallback(error, names) + { + if (!error) + WebInspector.CSSCompletions.cssNameCompletions = new WebInspector.CSSCompletions(names, false); + } + CSSAgent.getSupportedCSSProperties(propertyNamesCallback); +} + +WebInspector.CSSCompletions.prototype = { + startsWith: function(prefix) + { + var firstIndex = this._firstIndexOfPrefix(prefix); + if (firstIndex === -1) + return []; + + var results = []; + while (firstIndex < this._values.length && this._values[firstIndex].indexOf(prefix) === 0) + results.push(this._values[firstIndex++]); + return results; + }, + + firstStartsWith: function(prefix) + { + var foundIndex = this._firstIndexOfPrefix(prefix); + return (foundIndex === -1 ? "" : this._values[foundIndex]); + }, + + _firstIndexOfPrefix: function(prefix) + { + if (!this._values.length) + return -1; + if (!prefix) + return this._acceptEmptyPrefix ? 0 : -1; + + var maxIndex = this._values.length - 1; + var minIndex = 0; + var foundIndex; + + do { + var middleIndex = (maxIndex + minIndex) >> 1; + if (this._values[middleIndex].indexOf(prefix) === 0) { + foundIndex = middleIndex; + break; + } + if (this._values[middleIndex] < prefix) + minIndex = middleIndex + 1; + else + maxIndex = middleIndex - 1; + } while (minIndex <= maxIndex); + + if (foundIndex === undefined) + return -1; + + while (foundIndex && this._values[foundIndex - 1].indexOf(prefix) === 0) + foundIndex--; + + return foundIndex; + }, + + keySet: function() + { + if (!this._keySet) + this._keySet = this._values.keySet(); + return this._keySet; + }, + + next: function(str, prefix) + { + return this._closest(str, prefix, 1); + }, + + previous: function(str, prefix) + { + return this._closest(str, prefix, -1); + }, + + _closest: function(str, prefix, shift) + { + if (!str) + return ""; + + var index = this._values.indexOf(str); + if (index === -1) + return ""; + + if (!prefix) { + index = (index + this._values.length + shift) % this._values.length; + return this._values[index]; + } + + var propertiesWithPrefix = this.startsWith(prefix); + var j = propertiesWithPrefix.indexOf(str); + j = (j + propertiesWithPrefix.length + shift) % propertiesWithPrefix.length; + return propertiesWithPrefix[j]; + } +} +/* CSSKeywordCompletions.js */ + +/* + * Copyright (C) 2011 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. + */ + +WebInspector.CSSKeywordCompletions = {} + +WebInspector.CSSKeywordCompletions.forProperty = function(propertyName) +{ + var acceptedKeywords = ["initial"]; + if (propertyName in WebInspector.CSSKeywordCompletions._propertyKeywordMap) + acceptedKeywords = acceptedKeywords.concat(WebInspector.CSSKeywordCompletions._propertyKeywordMap[propertyName]); + if (propertyName in WebInspector.CSSKeywordCompletions._colorAwareProperties) + acceptedKeywords = acceptedKeywords.concat(WebInspector.CSSKeywordCompletions._colors); + if (propertyName in WebInspector.CSSKeywordCompletions.InheritedProperties) + acceptedKeywords.push("inherit"); + return new WebInspector.CSSCompletions(acceptedKeywords, true); +} + +WebInspector.CSSKeywordCompletions.isColorAwareProperty = function(propertyName) +{ + return WebInspector.CSSKeywordCompletions._colorAwareProperties[propertyName] === true; +} + +WebInspector.CSSKeywordCompletions.colors = function() +{ + if (!WebInspector.CSSKeywordCompletions._colorsKeySet) + WebInspector.CSSKeywordCompletions._colorsKeySet = WebInspector.CSSKeywordCompletions._colors.keySet(); + return WebInspector.CSSKeywordCompletions._colorsKeySet; +} + +// Taken from http://www.w3.org/TR/CSS21/propidx.html. +WebInspector.CSSKeywordCompletions.InheritedProperties = [ + "azimuth", "border-collapse", "border-spacing", "caption-side", "color", "cursor", "direction", "elevation", + "empty-cells", "font-family", "font-size", "font-style", "font-variant", "font-weight", "font", "letter-spacing", + "line-height", "list-style-image", "list-style-position", "list-style-type", "list-style", "orphans", "pitch-range", + "pitch", "quotes", "richness", "speak-header", "speak-numeral", "speak-punctuation", "speak", "speech-rate", "stress", + "text-align", "text-indent", "text-transform", "text-shadow", "visibility", "voice-family", "volume", "white-space", "widows", "word-spacing" +].keySet(); + +WebInspector.CSSKeywordCompletions._colors = [ + "aqua", "black", "blue", "fuchsia", "gray", "green", "lime", "maroon", "navy", "olive", "orange", "purple", "red", + "silver", "teal", "white", "yellow", "transparent", "currentcolor", "grey", "aliceblue", "antiquewhite", + "aquamarine", "azure", "beige", "bisque", "blanchedalmond", "blueviolet", "brown", "burlywood", "cadetblue", + "chartreuse", "chocolate", "coral", "cornflowerblue", "cornsilk", "crimson", "cyan", "darkblue", "darkcyan", + "darkgoldenrod", "darkgray", "darkgreen", "darkgrey", "darkkhaki", "darkmagenta", "darkolivegreen", "darkorange", + "darkorchid", "darkred", "darksalmon", "darkseagreen", "darkslateblue", "darkslategray", "darkslategrey", + "darkturquoise", "darkviolet", "deeppink", "deepskyblue", "dimgray", "dimgrey", "dodgerblue", "firebrick", + "floralwhite", "forestgreen", "gainsboro", "ghostwhite", "gold", "goldenrod", "greenyellow", "honeydew", "hotpink", + "indianred", "indigo", "ivory", "khaki", "lavender", "lavenderblush", "lawngreen", "lemonchiffon", "lightblue", + "lightcoral", "lightcyan", "lightgoldenrodyellow", "lightgray", "lightgreen", "lightgrey", "lightpink", + "lightsalmon", "lightseagreen", "lightskyblue", "lightslategray", "lightslategrey", "lightsteelblue", "lightyellow", + "limegreen", "linen", "magenta", "mediumaquamarine", "mediumblue", "mediumorchid", "mediumpurple", "mediumseagreen", + "mediumslateblue", "mediumspringgreen", "mediumturquoise", "mediumvioletred", "midnightblue", "mintcream", + "mistyrose", "moccasin", "navajowhite", "oldlace", "olivedrab", "orangered", "orchid", "palegoldenrod", "palegreen", + "paleturquoise", "palevioletred", "papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue", "rosybrown", + "royalblue", "saddlebrown", "salmon", "sandybrown", "seagreen", "seashell", "sienna", "skyblue", "slateblue", + "slategray", "slategrey", "snow", "springgreen", "steelblue", "tan", "thistle", "tomato", "turquoise", "violet", + "wheat", "whitesmoke", "yellowgreen" +]; + +WebInspector.CSSKeywordCompletions._colorAwareProperties = [ + "background", "background-color", "background-image", "border", "border-color", "border-top", "border-right", "border-bottom", + "border-left", "border-top-color", "border-right-color", "border-bottom-color", "border-left-color", "color", + "outline", "outline-color", "text-line-through", "text-line-through-color", "text-overline", "text-overline-color", + "text-shadow", "text-underline", "text-underline-color", "-webkit-text-emphasis", "-webkit-text-emphasis-color" +].keySet(); + +WebInspector.CSSKeywordCompletions._propertyKeywordMap = { + "table-layout": [ + "auto", "fixed" + ], + "visibility": [ + "hidden", "visible", "collapse" + ], + "background-repeat": [ + "repeat", "repeat-x", "repeat-y", "no-repeat", "space", "round" + ], + "text-underline": [ + "none", "dotted", "dashed", "solid", "double", "dot-dash", "dot-dot-dash", "wave" + ], + "content": [ + "list-item", "close-quote", "no-close-quote", "no-open-quote", "open-quote" + ], + "list-style-image": [ + "none" + ], + "clear": [ + "none", "left", "right", "both" + ], + "text-underline-mode": [ + "continuous", "skip-white-space" + ], + "overflow-x": [ + "hidden", "auto", "visible", "overlay", "scroll" + ], + "stroke-linejoin": [ + "round", "miter", "bevel" + ], + "baseline-shift": [ + "baseline", "sub", "super" + ], + "border-bottom-width": [ + "medium", "thick", "thin" + ], + "marquee-speed": [ + "normal", "slow", "fast" + ], + "margin-top-collapse": [ + "collapse", "separate", "discard" + ], + "max-height": [ + "none" + ], + "box-orient": [ + "horizontal", "vertical", "inline-axis", "block-axis" + ], + "font-stretch": [ + "normal", "wider", "narrower", "ultra-condensed", "extra-condensed", "condensed", "semi-condensed", + "semi-expanded", "expanded", "extra-expanded", "ultra-expanded" + ], + "-webkit-color-correction": [ + "default", "srgb" + ], + "text-underline-style": [ + "none", "dotted", "dashed", "solid", "double", "dot-dash", "dot-dot-dash", "wave" + ], + "text-overline-mode": [ + "continuous", "skip-white-space" + ], + "-webkit-background-composite": [ + "highlight", "clear", "copy", "source-over", "source-in", "source-out", "source-atop", "destination-over", + "destination-in", "destination-out", "destination-atop", "xor", "plus-darker", "plus-lighter" + ], + "border-left-width": [ + "medium", "thick", "thin" + ], + "-webkit-writing-mode": [ + "lr", "rl", "tb", "lr-tb", "rl-tb", "tb-rl", "horizontal-tb", "vertical-rl", "vertical-lr", "horizontal-bt" + ], + "text-line-through-mode": [ + "continuous", "skip-white-space" + ], + "border-collapse": [ + "collapse", "separate" + ], + "page-break-inside": [ + "auto", "avoid" + ], + "border-top-width": [ + "medium", "thick", "thin" + ], + "outline-color": [ + "invert" + ], + "text-line-through-style": [ + "none", "dotted", "dashed", "solid", "double", "dot-dash", "dot-dot-dash", "wave" + ], + "outline-style": [ + "none", "hidden", "inset", "groove", "ridge", "outset", "dotted", "dashed", "solid", "double" + ], + "cursor": [ + "none", "copy", "auto", "crosshair", "default", "pointer", "move", "vertical-text", "cell", "context-menu", + "alias", "progress", "no-drop", "not-allowed", "-webkit-zoom-in", "-webkit-zoom-out", "e-resize", "ne-resize", + "nw-resize", "n-resize", "se-resize", "sw-resize", "s-resize", "w-resize", "ew-resize", "ns-resize", + "nesw-resize", "nwse-resize", "col-resize", "row-resize", "text", "wait", "help", "all-scroll", "-webkit-grab", + "-webkit-grabbing" + ], + "border-width": [ + "medium", "thick", "thin" + ], + "size": [ + "a3", "a4", "a5", "b4", "b5", "landscape", "ledger", "legal", "letter", "portrait" + ], + "background-size": [ + "contain", "cover" + ], + "direction": [ + "ltr", "rtl" + ], + "marquee-direction": [ + "left", "right", "auto", "reverse", "forwards", "backwards", "ahead", "up", "down" + ], + "enable-background": [ + "accumulate", "new" + ], + "float": [ + "none", "left", "right" + ], + "overflow-y": [ + "hidden", "auto", "visible", "overlay", "scroll" + ], + "margin-bottom-collapse": [ + "collapse", "separate", "discard" + ], + "box-reflect": [ + "left", "right", "above", "below" + ], + "overflow": [ + "hidden", "auto", "visible", "overlay", "scroll" + ], + "text-rendering": [ + "auto", "optimizespeed", "optimizelegibility", "geometricprecision" + ], + "text-align": [ + "-webkit-auto", "left", "right", "center", "justify", "-webkit-left", "-webkit-right", "-webkit-center" + ], + "list-style-position": [ + "outside", "inside" + ], + "margin-bottom": [ + "auto" + ], + "color-interpolation": [ + "linearrgb" + ], + "background-origin": [ + "border-box", "content-box", "padding-box" + ], + "word-wrap": [ + "normal", "break-word" + ], + "font-weight": [ + "normal", "bold", "bolder", "lighter", "100", "200", "300", "400", "500", "600", "700", "800", "900" + ], + "margin-before-collapse": [ + "collapse", "separate", "discard" + ], + "text-overline-width": [ + "normal", "medium", "auto", "thick", "thin" + ], + "text-transform": [ + "none", "capitalize", "uppercase", "lowercase" + ], + "border-right-style": [ + "none", "hidden", "inset", "groove", "ridge", "outset", "dotted", "dashed", "solid", "double" + ], + "border-left-style": [ + "none", "hidden", "inset", "groove", "ridge", "outset", "dotted", "dashed", "solid", "double" + ], + "-webkit-text-emphasis": [ + "circle", "filled", "open", "dot", "double-circle", "triangle", "sesame" + ], + "font-style": [ + "italic", "oblique", "normal" + ], + "speak": [ + "none", "normal", "spell-out", "digits", "literal-punctuation", "no-punctuation" + ], + "text-line-through": [ + "none", "dotted", "dashed", "solid", "double", "dot-dash", "dot-dot-dash", "wave", "continuous", + "skip-white-space" + ], + "color-rendering": [ + "auto", "optimizespeed", "optimizequality" + ], + "list-style-type": [ + "none", "disc", "circle", "square", "decimal", "decimal-leading-zero", "arabic-indic", "binary", "bengali", + "cambodian", "khmer", "devanagari", "gujarati", "gurmukhi", "kannada", "lower-hexadecimal", "lao", "malayalam", + "mongolian", "myanmar", "octal", "oriya", "persian", "urdu", "telugu", "tibetan", "thai", "upper-hexadecimal", + "lower-roman", "upper-roman", "lower-greek", "lower-alpha", "lower-latin", "upper-alpha", "upper-latin", "afar", + "ethiopic-halehame-aa-et", "ethiopic-halehame-aa-er", "amharic", "ethiopic-halehame-am-et", "amharic-abegede", + "ethiopic-abegede-am-et", "cjk-earthly-branch", "cjk-heavenly-stem", "ethiopic", "ethiopic-halehame-gez", + "ethiopic-abegede", "ethiopic-abegede-gez", "hangul-consonant", "hangul", "lower-norwegian", "oromo", + "ethiopic-halehame-om-et", "sidama", "ethiopic-halehame-sid-et", "somali", "ethiopic-halehame-so-et", "tigre", + "ethiopic-halehame-tig", "tigrinya-er", "ethiopic-halehame-ti-er", "tigrinya-er-abegede", + "ethiopic-abegede-ti-er", "tigrinya-et", "ethiopic-halehame-ti-et", "tigrinya-et-abegede", + "ethiopic-abegede-ti-et", "upper-greek", "upper-norwegian", "asterisks", "footnotes", "hebrew", "armenian", + "lower-armenian", "upper-armenian", "georgian", "cjk-ideographic", "hiragana", "katakana", "hiragana-iroha", + "katakana-iroha" + ], + "-webkit-text-combine": [ + "none", "horizontal" + ], + "outline": [ + "none", "hidden", "inset", "groove", "ridge", "outset", "dotted", "dashed", "solid", "double" + ], + "font": [ + "caption", "icon", "menu", "message-box", "small-caption", "-webkit-mini-control", "-webkit-small-control", + "-webkit-control", "status-bar", "italic", "oblique", "small-caps", "normal", "bold", "bolder", "lighter", + "100", "200", "300", "400", "500", "600", "700", "800", "900", "xx-small", "x-small", "small", "medium", + "large", "x-large", "xx-large", "-webkit-xxx-large", "smaller", "larger", "serif", "sans-serif", "cursive", + "fantasy", "monospace", "-webkit-body", "-webkit-pictograph" + ], + "dominant-baseline": [ + "middle", "auto", "central", "text-before-edge", "text-after-edge", "ideographic", "alphabetic", "hanging", + "mathematical", "use-script", "no-change", "reset-size" + ], + "display": [ + "none", "inline", "block", "list-item", "run-in", "compact", "inline-block", "table", "inline-table", + "table-row-group", "table-header-group", "table-footer-group", "table-row", "table-column-group", + "table-column", "table-cell", "table-caption", "-webkit-box", "-webkit-inline-box", "-wap-marquee" + ], + "-webkit-text-emphasis-position": [ + "over", "under" + ], + "image-rendering": [ + "auto", "optimizespeed", "optimizequality" + ], + "alignment-baseline": [ + "baseline", "middle", "auto", "before-edge", "after-edge", "central", "text-before-edge", "text-after-edge", + "ideographic", "alphabetic", "hanging", "mathematical" + ], + "outline-width": [ + "medium", "thick", "thin" + ], + "text-line-through-width": [ + "normal", "medium", "auto", "thick", "thin" + ], + "box-align": [ + "baseline", "center", "stretch", "start", "end" + ], + "border-right-width": [ + "medium", "thick", "thin" + ], + "border-top-style": [ + "none", "hidden", "inset", "groove", "ridge", "outset", "dotted", "dashed", "solid", "double" + ], + "line-height": [ + "normal" + ], + "text-overflow": [ + "clip", "ellipsis" + ], + "box-direction": [ + "normal", "reverse" + ], + "margin-after-collapse": [ + "collapse", "separate", "discard" + ], + "page-break-before": [ + "left", "right", "auto", "always", "avoid" + ], + "-webkit-hyphens": [ + "none", "auto", "manual" + ], + "border-image": [ + "repeat", "stretch" + ], + "text-decoration": [ + "blink", "line-through", "overline", "underline" + ], + "position": [ + "absolute", "fixed", "relative", "static" + ], + "font-family": [ + "serif", "sans-serif", "cursive", "fantasy", "monospace", "-webkit-body", "-webkit-pictograph" + ], + "text-overflow-mode": [ + "clip", "ellipsis" + ], + "border-bottom-style": [ + "none", "hidden", "inset", "groove", "ridge", "outset", "dotted", "dashed", "solid", "double" + ], + "unicode-bidi": [ + "normal", "bidi-override", "embed" + ], + "clip-rule": [ + "nonzero", "evenodd" + ], + "margin-left": [ + "auto" + ], + "margin-top": [ + "auto" + ], + "zoom": [ + "document", "reset" + ], + "text-overline-style": [ + "none", "dotted", "dashed", "solid", "double", "dot-dash", "dot-dot-dash", "wave" + ], + "max-width": [ + "none" + ], + "empty-cells": [ + "hide", "show" + ], + "pointer-events": [ + "none", "all", "auto", "visible", "visiblepainted", "visiblefill", "visiblestroke", "painted", "fill", "stroke" + ], + "letter-spacing": [ + "normal" + ], + "background-clip": [ + "border-box", "content-box", "padding-box" + ], + "-webkit-font-smoothing": [ + "none", "auto", "antialiased", "subpixel-antialiased" + ], + "border": [ + "none", "hidden", "inset", "groove", "ridge", "outset", "dotted", "dashed", "solid", "double" + ], + "font-size": [ + "xx-small", "x-small", "small", "medium", "large", "x-large", "xx-large", "-webkit-xxx-large", "smaller", + "larger" + ], + "font-variant": [ + "small-caps", "normal" + ], + "vertical-align": [ + "baseline", "middle", "sub", "super", "text-top", "text-bottom", "top", "bottom", "-webkit-baseline-middle" + ], + "marquee-style": [ + "none", "scroll", "slide", "alternate" + ], + "white-space": [ + "normal", "nowrap", "pre", "pre-line", "pre-wrap" + ], + "text-underline-width": [ + "normal", "medium", "auto", "thick", "thin" + ], + "box-lines": [ + "single", "multiple" + ], + "page-break-after": [ + "left", "right", "auto", "always", "avoid" + ], + "clip-path": [ + "none" + ], + "margin": [ + "auto" + ], + "marquee-repetition": [ + "infinite" + ], + "margin-right": [ + "auto" + ], + "-webkit-text-emphasis-style": [ + "circle", "filled", "open", "dot", "double-circle", "triangle", "sesame" + ], + "-webkit-transform": [ + "scale", "scaleX", "scaleY", "scale3d", "rotate", "rotateX", "rotateY", "rotateZ", "rotate3d", "skew", "skewX", "skewY", + "translate", "translateX", "translateY", "translateZ", "translate3d", "matrix", "matrix3d", "perspective" + ] +} +/* StylesSidebarPane.js */ + +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * Copyright (C) 2009 Joseph Pecoraro + * + * 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. + */ + +/** + * @constructor + * @extends {WebInspector.SidebarPane} + */ +WebInspector.StylesSidebarPane = function(computedStylePane) +{ + WebInspector.SidebarPane.call(this, WebInspector.UIString("Styles")); + + this.settingsSelectElement = document.createElement("select"); + this.settingsSelectElement.className = "select-settings"; + + var option = document.createElement("option"); + option.value = WebInspector.StylesSidebarPane.ColorFormat.Original; + option.label = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "As authored" : "As Authored"); + this.settingsSelectElement.appendChild(option); + + option = document.createElement("option"); + option.value = WebInspector.StylesSidebarPane.ColorFormat.HEX; + option.label = WebInspector.UIString("Hex Colors"); + this.settingsSelectElement.appendChild(option); + + option = document.createElement("option"); + option.value = WebInspector.StylesSidebarPane.ColorFormat.RGB; + option.label = WebInspector.UIString("RGB Colors"); + this.settingsSelectElement.appendChild(option); + + option = document.createElement("option"); + option.value = WebInspector.StylesSidebarPane.ColorFormat.HSL; + option.label = WebInspector.UIString("HSL Colors"); + this.settingsSelectElement.appendChild(option); + + // Prevent section from collapsing. + var muteEventListener = function(event) { event.stopPropagation(); event.preventDefault(); }; + + this.settingsSelectElement.addEventListener("click", muteEventListener, true); + this.settingsSelectElement.addEventListener("change", this._changeSetting.bind(this), false); + this._updateColorFormatFilter(); + + this.titleElement.appendChild(this.settingsSelectElement); + + this._elementStateButton = document.createElement("button"); + this._elementStateButton.className = "pane-title-button element-state"; + this._elementStateButton.title = WebInspector.UIString("Toggle Element State"); + this._elementStateButton.addEventListener("click", this._toggleElementStatePane.bind(this), false); + this.titleElement.appendChild(this._elementStateButton); + + var addButton = document.createElement("button"); + addButton.className = "pane-title-button add"; + addButton.id = "add-style-button-test-id"; + addButton.title = WebInspector.UIString("New Style Rule"); + addButton.addEventListener("click", this._createNewRule.bind(this), false); + this.titleElement.appendChild(addButton); + + this._computedStylePane = computedStylePane; + this.element.addEventListener("contextmenu", this._contextMenuEventFired.bind(this), true); + WebInspector.settings.colorFormat.addChangeListener(this._colorFormatSettingChanged.bind(this)); + + this._createElementStatePane(); + this.bodyElement.appendChild(this._elementStatePane); + this._sectionsContainer = document.createElement("div"); + this.bodyElement.appendChild(this._sectionsContainer); + + WebInspector.cssModel.addEventListener(WebInspector.CSSStyleModel.Events.StyleSheetChanged, this._styleSheetOrMediaQueryResultChanged, this); + WebInspector.cssModel.addEventListener(WebInspector.CSSStyleModel.Events.MediaQueryResultChanged, this._styleSheetOrMediaQueryResultChanged, this); + WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.AttrModified, this._attributesModified, this); + WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.AttrRemoved, this._attributesRemoved, this); + WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.StyleInvalidated, this._styleInvalidated, this); + WebInspector.settings.showUserAgentStyles.addChangeListener(this._showUserAgentStylesSettingChanged.bind(this)); +} + +WebInspector.StylesSidebarPane.ColorFormat = { + Original: "original", + Nickname: "nickname", + HEX: "hex", + ShortHEX: "shorthex", + RGB: "rgb", + RGBA: "rgba", + HSL: "hsl", + HSLA: "hsla" +} + +WebInspector.StylesSidebarPane.StyleValueDelimiters = " \xA0\t\n\"':;,/()"; + + +// Keep in sync with RenderStyleConstants.h PseudoId enum. Array below contains pseudo id names for corresponding enum indexes. +// First item is empty due to its artificial NOPSEUDO nature in the enum. +// FIXME: find a way of generating this mapping or getting it from combination of RenderStyleConstants and CSSSelector.cpp at +// runtime. +WebInspector.StylesSidebarPane.PseudoIdNames = [ + "", "first-line", "first-letter", "before", "after", "selection", "", "-webkit-scrollbar", "-webkit-file-upload-button", + "-webkit-input-placeholder", "-webkit-slider-thumb", "-webkit-search-cancel-button", "-webkit-search-decoration", + "-webkit-search-results-decoration", "-webkit-search-results-button", "-webkit-media-controls-panel", + "-webkit-media-controls-play-button", "-webkit-media-controls-mute-button", "-webkit-media-controls-timeline", + "-webkit-media-controls-timeline-container", "-webkit-media-controls-volume-slider", + "-webkit-media-controls-volume-slider-container", "-webkit-media-controls-current-time-display", + "-webkit-media-controls-time-remaining-display", "-webkit-media-controls-seek-back-button", "-webkit-media-controls-seek-forward-button", + "-webkit-media-controls-fullscreen-button", "-webkit-media-controls-rewind-button", "-webkit-media-controls-return-to-realtime-button", + "-webkit-media-controls-toggle-closed-captions-button", "-webkit-media-controls-status-display", "-webkit-scrollbar-thumb", + "-webkit-scrollbar-button", "-webkit-scrollbar-track", "-webkit-scrollbar-track-piece", "-webkit-scrollbar-corner", + "-webkit-resizer", "-webkit-input-list-button", "-webkit-inner-spin-button", "-webkit-outer-spin-button" +]; + +WebInspector.StylesSidebarPane.CSSNumberRegex = /^(-?(?:\d+(?:\.\d+)?|\.\d+))$/; + +WebInspector.StylesSidebarPane.alteredFloatNumber = function(number, event) +{ + var arrowKeyPressed = (event.keyIdentifier === "Up" || event.keyIdentifier === "Down"); + + // Jump by 10 when shift is down or jump by 0.1 when Alt/Option is down. + // Also jump by 10 for page up and down, or by 100 if shift is held with a page key. + var changeAmount = 1; + if (event.shiftKey && !arrowKeyPressed) + changeAmount = 100; + else if (event.shiftKey || !arrowKeyPressed) + changeAmount = 10; + else if (event.altKey) + changeAmount = 0.1; + + if (event.keyIdentifier === "Down" || event.keyIdentifier === "PageDown") + changeAmount *= -1; + + // Make the new number and constrain it to a precision of 6, this matches numbers the engine returns. + // Use the Number constructor to forget the fixed precision, so 1.100000 will print as 1.1. + var result = Number((number + changeAmount).toFixed(6)); + if (!String(result).match(WebInspector.StylesSidebarPane.CSSNumberRegex)) + return null; + + return result; +} + +WebInspector.StylesSidebarPane.alteredHexNumber = function(hexString, event) +{ + var number = parseInt(hexString, 16); + if (isNaN(number) || !isFinite(number)) + return hexString; + + var maxValue = Math.pow(16, hexString.length) - 1; + var arrowKeyPressed = (event.keyIdentifier === "Up" || event.keyIdentifier === "Down"); + + var delta; + if (arrowKeyPressed) + delta = (event.keyIdentifier === "Up") ? 1 : -1; + else + delta = (event.keyIdentifier === "PageUp") ? 16 : -16; + + if (event.shiftKey) + delta *= 16; + + var result = number + delta; + if (result < 0) + result = 0; // Color hex values are never negative, so clamp to 0. + else if (result > maxValue) + return hexString; + + // Ensure the result length is the same as the original hex value. + var resultString = result.toString(16).toUpperCase(); + for (var i = 0, lengthDelta = hexString.length - resultString.length; i < lengthDelta; ++i) + resultString = "0" + resultString; + return resultString; +}, + +WebInspector.StylesSidebarPane.prototype = { + _contextMenuEventFired: function(event) + { + var contextMenu = new WebInspector.ContextMenu(); + if (WebInspector.populateHrefContextMenu(contextMenu, this.node, event)) + contextMenu.show(event); + }, + + get forcedPseudoClasses() + { + return this._forcedPseudoClasses; + }, + + update: function(node, forceUpdate) + { + var refresh = false; + + if (forceUpdate) + delete this.node; + + if (!forceUpdate && (node === this.node)) + refresh = true; + + if (node && node.nodeType() === Node.TEXT_NODE && node.parentNode) + node = node.parentNode; + + if (node && node.nodeType() !== Node.ELEMENT_NODE) + node = null; + + if (node) + this.node = node; + else + node = this.node; + + this._innerUpdate(refresh); + }, + + _executeRebuildUpdate: function(node, callback) + { + var resultStyles = {}; + + function stylesCallback(matchedResult) + { + if (matchedResult) { + resultStyles.matchedCSSRules = matchedResult.matchedCSSRules; + resultStyles.pseudoElements = matchedResult.pseudoElements; + resultStyles.inherited = matchedResult.inherited; + this._rebuildUpdate(node, resultStyles); + } + if (callback) + callback(); + } + + function inlineCallback(inlineStyle, styleAttributes) + { + resultStyles.inlineStyle = inlineStyle; + resultStyles.styleAttributes = styleAttributes; + } + + function computedCallback(computedStyle) + { + resultStyles.computedStyle = computedStyle; + } + + WebInspector.cssModel.getComputedStyleAsync(node.id, this._forcedPseudoClasses, computedCallback.bind(this)); + WebInspector.cssModel.getInlineStylesAsync(node.id, inlineCallback.bind(this)); + WebInspector.cssModel.getMatchedStylesAsync(node.id, this._forcedPseudoClasses, true, true, stylesCallback.bind(this)); + }, + + /** + * @param {WebInspector.StylePropertiesSection=} editedSection + * @param {function()=} userCallback + */ + _innerUpdate: function(refresh, editedSection, userCallback) + { + var node = this.node; + if (!node) { + this._sectionsContainer.removeChildren(); + this._computedStylePane.bodyElement.removeChildren(); + this.sections = {}; + if (userCallback) + userCallback(); + return; + } + + function computedStyleCallback(computedStyle) + { + if (this.node === node && computedStyle) + this._refreshUpdate(node, computedStyle, editedSection); + if (userCallback) + userCallback(); + } + + if (refresh) + WebInspector.cssModel.getComputedStyleAsync(node.id, this._forcedPseudoClasses, computedStyleCallback.bind(this)); + else + this._executeRebuildUpdate(node, userCallback); + }, + + _styleSheetOrMediaQueryResultChanged: function() + { + if (this._userOperation || this._isEditingStyle) + return; + + this._innerUpdate(false); + }, + + _attributesModified: function(event) + { + if (this.node !== event.data.node) + return; + + // Changing style attribute will anyways generate _styleInvalidated message. + if (event.data.name === "style") + return; + + // "class" (or any other) attribute might have changed. Update styles unless they are being edited. + if (!this._isEditingStyle && !this._userOperation) + this._innerUpdate(false); + }, + + _attributesRemoved: function(event) + { + if (this.node !== event.data.node) + return; + + // "style" attribute might have been removed. + if (!this._isEditingStyle && !this._userOperation) + this._innerUpdate(false); + }, + + _styleInvalidated: function(event) + { + if (this.node !== event.data) + return; + + if (!this._isEditingStyle && !this._userOperation) + this._innerUpdate(false); + }, + + _refreshUpdate: function(node, computedStyle, editedSection) + { + for (var pseudoId in this.sections) { + var styleRules = this._refreshStyleRules(this.sections[pseudoId], computedStyle); + var usedProperties = {}; + var disabledComputedProperties = {}; + this._markUsedProperties(styleRules, usedProperties, disabledComputedProperties); + this._refreshSectionsForStyleRules(styleRules, usedProperties, disabledComputedProperties, editedSection); + } + // Trace the computed style. + this.sections[0][0].rebuildComputedTrace(this.sections[0]); + + this._nodeStylesUpdatedForTest(node, true); + }, + + _rebuildUpdate: function(node, styles) + { + this._sectionsContainer.removeChildren(); + this._computedStylePane.bodyElement.removeChildren(); + + var styleRules = this._rebuildStyleRules(node, styles); + var usedProperties = {}; + var disabledComputedProperties = {}; + this._markUsedProperties(styleRules, usedProperties, disabledComputedProperties); + this.sections[0] = this._rebuildSectionsForStyleRules(styleRules, usedProperties, disabledComputedProperties, 0, null); + var anchorElement = this.sections[0].inheritedPropertiesSeparatorElement; + // Trace the computed style. + this.sections[0][0].rebuildComputedTrace(this.sections[0]); + + for (var i = 0; i < styles.pseudoElements.length; ++i) { + var pseudoElementCSSRules = styles.pseudoElements[i]; + + styleRules = []; + var pseudoId = pseudoElementCSSRules.pseudoId; + + var entry = { isStyleSeparator: true, pseudoId: pseudoId }; + styleRules.push(entry); + + // Add rules in reverse order to match the cascade order. + for (var j = pseudoElementCSSRules.rules.length - 1; j >= 0; --j) { + var rule = pseudoElementCSSRules.rules[j]; + styleRules.push({ style: rule.style, selectorText: rule.selectorText, media: rule.media, sourceURL: rule.sourceURL, rule: rule, editable: !!(rule.style && rule.style.id) }); + } + usedProperties = {}; + disabledComputedProperties = {}; + this._markUsedProperties(styleRules, usedProperties, disabledComputedProperties); + this.sections[pseudoId] = this._rebuildSectionsForStyleRules(styleRules, usedProperties, disabledComputedProperties, pseudoId, anchorElement); + } + + this._nodeStylesUpdatedForTest(node, false); + }, + + _nodeStylesUpdatedForTest: function(node, refresh) + { + // Tests override this method. + }, + + _refreshStyleRules: function(sections, computedStyle) + { + var nodeComputedStyle = computedStyle; + var styleRules = []; + for (var i = 0; sections && i < sections.length; ++i) { + var section = sections[i]; + if (section.isBlank) + continue; + if (section.computedStyle) + section.styleRule.style = nodeComputedStyle; + var styleRule = { section: section, style: section.styleRule.style, computedStyle: section.computedStyle, rule: section.rule, editable: !!(section.styleRule.style && section.styleRule.style.id) }; + styleRules.push(styleRule); + } + return styleRules; + }, + + _rebuildStyleRules: function(node, styles) + { + var nodeComputedStyle = styles.computedStyle; + this.sections = {}; + + var styleRules = []; + + function addStyleAttributes() + { + for (var name in styles.styleAttributes) { + var attrStyle = { style: styles.styleAttributes[name], editable: false }; + attrStyle.selectorText = node.nodeNameInCorrectCase() + "[" + name; + if (node.getAttribute(name)) + attrStyle.selectorText += "=" + node.getAttribute(name); + attrStyle.selectorText += "]"; + styleRules.push(attrStyle); + } + } + + styleRules.push({ computedStyle: true, selectorText: "", style: nodeComputedStyle, editable: false }); + + // Inline style has the greatest specificity. + if (styles.inlineStyle && node.nodeType() === Node.ELEMENT_NODE) { + var inlineStyle = { selectorText: "element.style", style: styles.inlineStyle, isAttribute: true }; + styleRules.push(inlineStyle); + } + + // Add rules in reverse order to match the cascade order. + if (styles.matchedCSSRules.length) + styleRules.push({ isStyleSeparator: true, text: WebInspector.UIString("Matched CSS Rules") }); + var addedStyleAttributes; + for (var i = styles.matchedCSSRules.length - 1; i >= 0; --i) { + var rule = styles.matchedCSSRules[i]; + if (!WebInspector.settings.showUserAgentStyles.get() && (rule.isUser || rule.isUserAgent)) + continue; + if ((rule.isUser || rule.isUserAgent) && !addedStyleAttributes) { + // Show element's Style Attributes after all author rules. + addedStyleAttributes = true; + addStyleAttributes(); + } + styleRules.push({ style: rule.style, selectorText: rule.selectorText, media: rule.media, sourceURL: rule.sourceURL, rule: rule, editable: !!(rule.style && rule.style.id) }); + } + + if (!addedStyleAttributes) + addStyleAttributes(); + + // Walk the node structure and identify styles with inherited properties. + var parentNode = node.parentNode; + function insertInheritedNodeSeparator(node) + { + var entry = {}; + entry.isStyleSeparator = true; + entry.node = node; + styleRules.push(entry); + } + + for (var parentOrdinal = 0; parentOrdinal < styles.inherited.length; ++parentOrdinal) { + var parentStyles = styles.inherited[parentOrdinal]; + var separatorInserted = false; + if (parentStyles.inlineStyle) { + if (this._containsInherited(parentStyles.inlineStyle)) { + var inlineStyle = { selectorText: WebInspector.UIString("Style Attribute"), style: parentStyles.inlineStyle, isAttribute: true, isInherited: true }; + if (!separatorInserted) { + insertInheritedNodeSeparator(parentNode); + separatorInserted = true; + } + styleRules.push(inlineStyle); + } + } + + for (var i = parentStyles.matchedCSSRules.length - 1; i >= 0; --i) { + var rulePayload = parentStyles.matchedCSSRules[i]; + if (!this._containsInherited(rulePayload.style)) + continue; + var rule = rulePayload; + if (!WebInspector.settings.showUserAgentStyles.get() && (rule.isUser || rule.isUserAgent)) + continue; + + if (!separatorInserted) { + insertInheritedNodeSeparator(parentNode); + separatorInserted = true; + } + styleRules.push({ style: rule.style, selectorText: rule.selectorText, media: rule.media, sourceURL: rule.sourceURL, rule: rule, isInherited: true, editable: !!(rule.style && rule.style.id) }); + } + parentNode = parentNode.parentNode; + } + return styleRules; + }, + + _markUsedProperties: function(styleRules, usedProperties, disabledComputedProperties) + { + var priorityUsed = false; + + // Walk the style rules and make a list of all used and overloaded properties. + for (var i = 0; i < styleRules.length; ++i) { + var styleRule = styleRules[i]; + if (styleRule.computedStyle || styleRule.isStyleSeparator) + continue; + if (styleRule.section && styleRule.section.noAffect) + continue; + + styleRule.usedProperties = {}; + + var style = styleRule.style; + var allProperties = style.allProperties; + for (var j = 0; j < allProperties.length; ++j) { + var property = allProperties[j]; + if (!property.isLive || !property.parsedOk) + continue; + var name = property.name; + + if (!priorityUsed && property.priority.length) + priorityUsed = true; + + // If the property name is already used by another rule then this rule's + // property is overloaded, so don't add it to the rule's usedProperties. + if (!(name in usedProperties)) + styleRule.usedProperties[name] = true; + } + + // Add all the properties found in this style to the used properties list. + // Do this here so only future rules are affect by properties used in this rule. + for (var name in styleRules[i].usedProperties) + usedProperties[name] = true; + } + + if (priorityUsed) { + // Walk the properties again and account for !important. + var foundPriorityProperties = []; + + // Walk in direct order to detect the active/most specific rule providing a priority + // (in this case all subsequent !important values get canceled.) + for (var i = 0; i < styleRules.length; ++i) { + if (styleRules[i].computedStyle || styleRules[i].isStyleSeparator) + continue; + + var style = styleRules[i].style; + var allProperties = style.allProperties; + for (var j = 0; j < allProperties.length; ++j) { + var property = allProperties[j]; + if (!property.isLive) + continue; + var name = property.name; + if (property.priority.length) { + if (!(name in foundPriorityProperties)) + styleRules[i].usedProperties[name] = true; + else + delete styleRules[i].usedProperties[name]; + foundPriorityProperties[name] = true; + } else if (name in foundPriorityProperties) + delete styleRules[i].usedProperties[name]; + } + } + } + }, + + _refreshSectionsForStyleRules: function(styleRules, usedProperties, disabledComputedProperties, editedSection) + { + // Walk the style rules and update the sections with new overloaded and used properties. + for (var i = 0; i < styleRules.length; ++i) { + var styleRule = styleRules[i]; + var section = styleRule.section; + if (styleRule.computedStyle) { + section._disabledComputedProperties = disabledComputedProperties; + section._usedProperties = usedProperties; + section.update(); + } else { + section._usedProperties = styleRule.usedProperties; + section.update(section === editedSection); + } + } + }, + + _rebuildSectionsForStyleRules: function(styleRules, usedProperties, disabledComputedProperties, pseudoId, anchorElement) + { + // Make a property section for each style rule. + var sections = []; + var lastWasSeparator = true; + for (var i = 0; i < styleRules.length; ++i) { + var styleRule = styleRules[i]; + if (styleRule.isStyleSeparator) { + var separatorElement = document.createElement("div"); + separatorElement.className = "sidebar-separator"; + if (styleRule.node) { + var link = WebInspector.DOMPresentationUtils.linkifyNodeReference(styleRule.node); + separatorElement.appendChild(document.createTextNode(WebInspector.UIString("Inherited from") + " ")); + separatorElement.appendChild(link); + if (!sections.inheritedPropertiesSeparatorElement) + sections.inheritedPropertiesSeparatorElement = separatorElement; + } else if ("pseudoId" in styleRule) { + var pseudoName = WebInspector.StylesSidebarPane.PseudoIdNames[styleRule.pseudoId]; + if (pseudoName) + separatorElement.textContent = WebInspector.UIString("Pseudo ::%s element", pseudoName); + else + separatorElement.textContent = WebInspector.UIString("Pseudo element"); + } else + separatorElement.textContent = styleRule.text; + this._sectionsContainer.insertBefore(separatorElement, anchorElement); + lastWasSeparator = true; + continue; + } + var computedStyle = styleRule.computedStyle; + + // Default editable to true if it was omitted. + var editable = styleRule.editable; + if (typeof editable === "undefined") + editable = true; + + if (computedStyle) + var section = new WebInspector.ComputedStylePropertiesSection(styleRule, usedProperties, disabledComputedProperties); + else + var section = new WebInspector.StylePropertiesSection(this, styleRule, editable, styleRule.isInherited, lastWasSeparator); + section.pane = this; + section.expanded = true; + + if (computedStyle) { + this._computedStylePane.bodyElement.appendChild(section.element); + lastWasSeparator = true; + } else { + this._sectionsContainer.insertBefore(section.element, anchorElement); + lastWasSeparator = false; + } + sections.push(section); + } + return sections; + }, + + _containsInherited: function(style) + { + var properties = style.allProperties; + for (var i = 0; i < properties.length; ++i) { + var property = properties[i]; + // Does this style contain non-overridden inherited property? + if (property.isLive && property.name in WebInspector.CSSKeywordCompletions.InheritedProperties) + return true; + } + return false; + }, + + _colorFormatSettingChanged: function(event) + { + this._updateColorFormatFilter(); + for (var pseudoId in this.sections) { + var sections = this.sections[pseudoId]; + for (var i = 0; i < sections.length; ++i) + sections[i].update(true); + } + }, + + _updateColorFormatFilter: function() + { + // Select the correct color format setting again, since it needs to be selected. + var selectedIndex = 0; + var value = WebInspector.settings.colorFormat.get(); + var options = this.settingsSelectElement.options; + for (var i = 0; i < options.length; ++i) { + if (options[i].value === value) { + selectedIndex = i; + break; + } + } + this.settingsSelectElement.selectedIndex = selectedIndex; + }, + + _changeSetting: function(event) + { + var options = this.settingsSelectElement.options; + var selectedOption = options[this.settingsSelectElement.selectedIndex]; + WebInspector.settings.colorFormat.set(selectedOption.value); + }, + + _createNewRule: function(event) + { + event.stopPropagation(); + this.expanded = true; + this.addBlankSection().startEditingSelector(); + }, + + addBlankSection: function() + { + var blankSection = new WebInspector.BlankStylePropertiesSection(this, this.node ? this.node.appropriateSelectorFor(true) : ""); + blankSection.pane = this; + + var elementStyleSection = this.sections[0][1]; + this._sectionsContainer.insertBefore(blankSection.element, elementStyleSection.element.nextSibling); + + this.sections[0].splice(2, 0, blankSection); + + return blankSection; + }, + + removeSection: function(section) + { + for (var pseudoId in this.sections) { + var sections = this.sections[pseudoId]; + var index = sections.indexOf(section); + if (index === -1) + continue; + sections.splice(index, 1); + if (section.element.parentNode) + section.element.parentNode.removeChild(section.element); + } + }, + + registerShortcuts: function() + { + var section = WebInspector.shortcutsScreen.section(WebInspector.UIString("Styles Pane")); + var shortcut = WebInspector.KeyboardShortcut; + var keys = [ + shortcut.shortcutToString(shortcut.Keys.Tab), + shortcut.shortcutToString(shortcut.Keys.Tab, shortcut.Modifiers.Shift) + ]; + section.addRelatedKeys(keys, WebInspector.UIString("Next/previous property")); + keys = [ + shortcut.shortcutToString(shortcut.Keys.Up), + shortcut.shortcutToString(shortcut.Keys.Down) + ]; + section.addRelatedKeys(keys, WebInspector.UIString("Increment/decrement value")); + keys = [ + shortcut.shortcutToString(shortcut.Keys.Up, shortcut.Modifiers.Shift), + shortcut.shortcutToString(shortcut.Keys.Down, shortcut.Modifiers.Shift) + ]; + section.addRelatedKeys(keys, WebInspector.UIString("Increment/decrement by %f", 10)); + keys = [ + shortcut.shortcutToString(shortcut.Keys.PageUp), + shortcut.shortcutToString(shortcut.Keys.PageDown) + ]; + section.addRelatedKeys(keys, WebInspector.UIString("Increment/decrement by %f", 10)); + keys = [ + shortcut.shortcutToString(shortcut.Keys.PageUp, shortcut.Modifiers.Shift), + shortcut.shortcutToString(shortcut.Keys.PageDown, shortcut.Modifiers.Shift) + ]; + section.addRelatedKeys(keys, WebInspector.UIString("Increment/decrement by %f", 100)); + keys = [ + shortcut.shortcutToString(shortcut.Keys.PageUp, shortcut.Modifiers.Alt), + shortcut.shortcutToString(shortcut.Keys.PageDown, shortcut.Modifiers.Alt) + ]; + section.addRelatedKeys(keys, WebInspector.UIString("Increment/decrement by %f", 0.1)); + }, + + _toggleElementStatePane: function(event) + { + event.stopPropagation(); + if (!this._elementStateButton.hasStyleClass("toggled")) { + this.expand(); + this._elementStateButton.addStyleClass("toggled"); + this._elementStatePane.addStyleClass("expanded"); + } else { + this._elementStateButton.removeStyleClass("toggled"); + this._elementStatePane.removeStyleClass("expanded"); + // Clear flags on hide. + if (this._forcedPseudoClasses) { + for (var i = 0; i < this._elementStatePane.inputs.length; ++i) + this._elementStatePane.inputs[i].checked = false; + delete this._forcedPseudoClasses; + this._innerUpdate(false); + } + } + }, + + _createElementStatePane: function() + { + this._elementStatePane = document.createElement("div"); + this._elementStatePane.className = "styles-element-state-pane source-code"; + var table = document.createElement("table"); + + var inputs = []; + this._elementStatePane.inputs = inputs; + + function clickListener(event) + { + var pseudoClasses = []; + for (var i = 0; i < inputs.length; ++i) { + if (inputs[i].checked) + pseudoClasses.push(inputs[i].state); + } + this._forcedPseudoClasses = pseudoClasses.length ? pseudoClasses : undefined; + this._innerUpdate(false); + } + + function createCheckbox(state) + { + var td = document.createElement("td"); + var label = document.createElement("label"); + var input = document.createElement("input"); + input.type = "checkbox"; + input.state = state; + input.addEventListener("click", clickListener.bind(this), false); + inputs.push(input); + label.appendChild(input); + label.appendChild(document.createTextNode(":" + state)); + td.appendChild(label); + return td; + } + + var tr = document.createElement("tr"); + tr.appendChild(createCheckbox.call(this, "active")); + tr.appendChild(createCheckbox.call(this, "hover")); + table.appendChild(tr); + + tr = document.createElement("tr"); + tr.appendChild(createCheckbox.call(this, "focus")); + tr.appendChild(createCheckbox.call(this, "visited")); + table.appendChild(tr); + + this._elementStatePane.appendChild(table); + }, + + _showUserAgentStylesSettingChanged: function() + { + this._innerUpdate(false); + } +} + +WebInspector.StylesSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype; + +/** + * @constructor + * @extends {WebInspector.SidebarPane} + */ +WebInspector.ComputedStyleSidebarPane = function() +{ + WebInspector.SidebarPane.call(this, WebInspector.UIString("Computed Style")); + var showInheritedCheckbox = new WebInspector.Checkbox(WebInspector.UIString("Show inherited"), "sidebar-pane-subtitle"); + this.titleElement.appendChild(showInheritedCheckbox.element); + + if (WebInspector.settings.showInheritedComputedStyleProperties.get()) { + this.bodyElement.addStyleClass("show-inherited"); + showInheritedCheckbox.checked = true; + } + + function showInheritedToggleFunction(event) + { + WebInspector.settings.showInheritedComputedStyleProperties.set(showInheritedCheckbox.checked); + if (WebInspector.settings.showInheritedComputedStyleProperties.get()) + this.bodyElement.addStyleClass("show-inherited"); + else + this.bodyElement.removeStyleClass("show-inherited"); + } + + showInheritedCheckbox.addEventListener(showInheritedToggleFunction.bind(this)); +} + +WebInspector.ComputedStyleSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype; + +/** + * @constructor + * @extends {WebInspector.PropertiesSection} + */ +WebInspector.StylePropertiesSection = function(parentPane, styleRule, editable, isInherited, isFirstSection) +{ + WebInspector.PropertiesSection.call(this, ""); + this.element.className = "styles-section monospace" + (isFirstSection ? " first-styles-section" : ""); + + if (styleRule.media) { + for (var i = styleRule.media.length - 1; i >= 0; --i) { + var media = styleRule.media[i]; + var mediaDataElement = this.titleElement.createChild("div", "media"); + var mediaText; + switch (media.source) { + case WebInspector.CSSMedia.Source.LINKED_SHEET: + case WebInspector.CSSMedia.Source.INLINE_SHEET: + mediaText = "media=\"" + media.text + "\""; + break; + case WebInspector.CSSMedia.Source.MEDIA_RULE: + mediaText = "@media " + media.text; + break; + case WebInspector.CSSMedia.Source.IMPORT_RULE: + mediaText = "@import " + media.text; + break; + } + + if (media.sourceURL) { + var refElement = mediaDataElement.createChild("div", "subtitle"); + var anchor = WebInspector.linkifyResourceAsNode(media.sourceURL, media.sourceLine < 0 ? undefined : media.sourceLine, "subtitle"); + anchor.style.float = "right"; + refElement.appendChild(anchor); + } + + var mediaTextElement = mediaDataElement.createChild("span"); + mediaTextElement.textContent = mediaText; + mediaTextElement.title = media.text; + } + } + + var selectorContainer = document.createElement("div"); + this._selectorElement = document.createElement("span"); + this._selectorElement.textContent = styleRule.selectorText; + selectorContainer.appendChild(this._selectorElement); + + var openBrace = document.createElement("span"); + openBrace.textContent = " {"; + selectorContainer.appendChild(openBrace); + + var closeBrace = document.createElement("div"); + closeBrace.textContent = "}"; + this.element.appendChild(closeBrace); + + this._selectorElement.addEventListener("dblclick", this._handleSelectorDoubleClick.bind(this), false); + this.element.addEventListener("dblclick", this._handleEmptySpaceDoubleClick.bind(this), false); + + this._parentPane = parentPane; + this.styleRule = styleRule; + this.rule = this.styleRule.rule; + this.editable = editable; + this.isInherited = isInherited; + + if (this.rule) { + // Prevent editing the user agent and user rules. + if (this.rule.isUserAgent || this.rule.isUser) + this.editable = false; + this.titleElement.addStyleClass("styles-selector"); + } + + this._usedProperties = styleRule.usedProperties; + + this._selectorRefElement = document.createElement("div"); + this._selectorRefElement.className = "subtitle"; + this._selectorRefElement.appendChild(this._createRuleOriginNode()); + selectorContainer.insertBefore(this._selectorRefElement, selectorContainer.firstChild); + this.titleElement.appendChild(selectorContainer); + + if (isInherited) + this.element.addStyleClass("show-inherited"); // This one is related to inherited rules, not compted style. + + if (!this.editable) + this.element.addStyleClass("read-only"); +} + +WebInspector.StylePropertiesSection.prototype = { + collapse: function(dontRememberState) + { + // Overriding with empty body. + }, + + isPropertyInherited: function(propertyName) + { + if (this.isInherited) { + // While rendering inherited stylesheet, reverse meaning of this property. + // Render truly inherited properties with black, i.e. return them as non-inherited. + return !(propertyName in WebInspector.CSSKeywordCompletions.InheritedProperties); + } + return false; + }, + + isPropertyOverloaded: function(propertyName, shorthand) + { + if (!this._usedProperties || this.noAffect) + return false; + + if (this.isInherited && !(propertyName in WebInspector.CSSKeywordCompletions.InheritedProperties)) { + // In the inherited sections, only show overrides for the potentially inherited properties. + return false; + } + + var used = (propertyName in this._usedProperties); + if (used || !shorthand) + return !used; + + // Find out if any of the individual longhand properties of the shorthand + // are used, if none are then the shorthand is overloaded too. + var longhandProperties = this.styleRule.style.getLonghandProperties(propertyName); + for (var j = 0; j < longhandProperties.length; ++j) { + var individualProperty = longhandProperties[j]; + if (individualProperty.name in this._usedProperties) + return false; + } + + return true; + }, + + nextEditableSibling: function() + { + var curSection = this; + do { + curSection = curSection.nextSibling; + } while (curSection && !curSection.editable); + + if (!curSection) { + curSection = this.firstSibling; + while (curSection && !curSection.editable) + curSection = curSection.nextSibling; + } + + return (curSection && curSection.editable) ? curSection : null; + }, + + previousEditableSibling: function() + { + var curSection = this; + do { + curSection = curSection.previousSibling; + } while (curSection && !curSection.editable); + + if (!curSection) { + curSection = this.lastSibling; + while (curSection && !curSection.editable) + curSection = curSection.previousSibling; + } + + return (curSection && curSection.editable) ? curSection : null; + }, + + update: function(full) + { + if (full) { + this.propertiesTreeOutline.removeChildren(); + this.populated = false; + } else { + var child = this.propertiesTreeOutline.children[0]; + while (child) { + child.overloaded = this.isPropertyOverloaded(child.name, child.shorthand); + child = child.traverseNextTreeElement(false, null, true); + } + } + this.afterUpdate(); + }, + + afterUpdate: function() + { + if (this._afterUpdate) { + this._afterUpdate(this); + delete this._afterUpdate; + } + }, + + onpopulate: function() + { + var style = this.styleRule.style; + + var handledProperties = {}; + var shorthandNames = {}; + + this.uniqueProperties = []; + var allProperties = style.allProperties; + for (var i = 0; i < allProperties.length; ++i) + this.uniqueProperties.push(allProperties[i]); + + // Collect all shorthand names. + for (var i = 0; i < this.uniqueProperties.length; ++i) { + var property = this.uniqueProperties[i]; + if (property.disabled) + continue; + if (property.shorthand) + shorthandNames[property.shorthand] = true; + } + + // Create property tree elements. + for (var i = 0; i < this.uniqueProperties.length; ++i) { + var property = this.uniqueProperties[i]; + var disabled = property.disabled; + if (!disabled && this.disabledComputedProperties && !(property.name in this.usedProperties) && property.name in this.disabledComputedProperties) + disabled = true; + + var shorthand = !disabled ? property.shorthand : null; + + if (shorthand && shorthand in handledProperties) + continue; + + if (shorthand) { + property = style.getLiveProperty(shorthand); + if (!property) + property = new WebInspector.CSSProperty(style, style.allProperties.length, shorthand, style.getShorthandValue(shorthand), style.getShorthandPriority(shorthand), "style", true, true, "", undefined); + } + + // BUG71275: Never show purely style-based properties in editable rules. + if (!shorthand && this.editable && property.styleBased) + continue; + + var isShorthand = !!(property.isLive && (shorthand || shorthandNames[property.name])); + var inherited = this.isPropertyInherited(property.name); + var overloaded = this.isPropertyOverloaded(property.name, isShorthand); + + var item = new WebInspector.StylePropertyTreeElement(this._parentPane, this.styleRule, style, property, isShorthand, inherited, overloaded); + this.propertiesTreeOutline.appendChild(item); + handledProperties[property.name] = property; + } + }, + + findTreeElementWithName: function(name) + { + var treeElement = this.propertiesTreeOutline.children[0]; + while (treeElement) { + if (treeElement.name === name) + return treeElement; + treeElement = treeElement.traverseNextTreeElement(true, null, true); + } + return null; + }, + + /** + * @param {number=} optionalIndex + */ + addNewBlankProperty: function(optionalIndex) + { + var style = this.styleRule.style; + var property = style.newBlankProperty(); + var item = new WebInspector.StylePropertyTreeElement(this._parentPane, this.styleRule, style, property, false, false, false); + this.propertiesTreeOutline.appendChild(item); + item.listItemElement.textContent = ""; + item._newProperty = true; + item.updateTitle(); + return item; + }, + + _createRuleOriginNode: function() + { + function linkifyUncopyable(url, line) + { + var link = WebInspector.linkifyResourceAsNode(url, line); + link.classList.add("webkit-html-resource-link"); + link.setAttribute("data-uncopyable", link.textContent); + link.textContent = ""; + return link; + } + + if (this.styleRule.sourceURL) + return linkifyUncopyable(this.styleRule.sourceURL, this.rule.sourceLine); + if (!this.rule) + return document.createTextNode(""); + + var origin = ""; + if (this.rule.isUserAgent) + origin = WebInspector.UIString("user agent stylesheet"); + else if (this.rule.isUser) + origin = WebInspector.UIString("user stylesheet"); + else if (this.rule.isViaInspector) + origin = WebInspector.UIString("via inspector"); + return document.createTextNode(origin); + }, + + _handleEmptySpaceDoubleClick: function(event) + { + if (event.target.hasStyleClass("header") || this.element.hasStyleClass("read-only") || event.target.enclosingNodeOrSelfWithClass("media")) { + event.stopPropagation(); + return; + } + this.expand(); + this.addNewBlankProperty().startEditing(); + }, + + _handleSelectorClick: function(event) + { + event.stopPropagation(); + }, + + _handleSelectorDoubleClick: function(event) + { + this._startEditingOnMouseEvent(); + event.stopPropagation(); + }, + + _startEditingOnMouseEvent: function() + { + if (!this.editable) + return; + + if (!this.rule && this.propertiesTreeOutline.children.length === 0) { + this.expand(); + this.addNewBlankProperty().startEditing(); + return; + } + + if (!this.rule) + return; + + this.startEditingSelector(); + }, + + startEditingSelector: function() + { + var element = this._selectorElement; + if (WebInspector.isBeingEdited(element)) + return; + + this._selectorElement.scrollIntoViewIfNeeded(false); + + var config = new WebInspector.EditingConfig(this.editingSelectorCommitted.bind(this), this.editingSelectorCancelled.bind(this)); + WebInspector.startEditing(this._selectorElement, config); + + window.getSelection().setBaseAndExtent(element, 0, element, 1); + }, + + _moveEditorFromSelector: function(moveDirection) + { + if (!moveDirection) + return; + + if (moveDirection === "forward") { + this.expand(); + var firstChild = this.propertiesTreeOutline.children[0]; + if (!firstChild) + this.addNewBlankProperty().startEditing(); + else + firstChild.startEditing(firstChild.nameElement); + } else { + var previousSection = this.previousEditableSibling(); + if (!previousSection) + return; + + previousSection.expand(); + previousSection.addNewBlankProperty().startEditing(); + } + }, + + editingSelectorCommitted: function(element, newContent, oldContent, context, moveDirection) + { + if (newContent) + newContent = newContent.trim(); + if (newContent === oldContent) { + // Revert to a trimmed version of the selector if need be. + this._selectorElement.textContent = newContent; + return this._moveEditorFromSelector(moveDirection); + } + + function successCallback(newRule, doesAffectSelectedNode) + { + if (!doesAffectSelectedNode) { + this.noAffect = true; + this.element.addStyleClass("no-affect"); + } else { + delete this.noAffect; + this.element.removeStyleClass("no-affect"); + } + + this.rule = newRule; + this.styleRule = { section: this, style: newRule.style, selectorText: newRule.selectorText, media: newRule.media, sourceURL: newRule.sourceURL, rule: newRule }; + + this.pane.update(); + + this._moveEditorFromSelector(moveDirection); + } + + var selectedNode = WebInspector.panels.elements.selectedDOMNode(); + WebInspector.cssModel.setRuleSelector(this.rule.id, selectedNode ? selectedNode.id : 0, newContent, successCallback.bind(this), this._moveEditorFromSelector.bind(this, moveDirection)); + }, + + editingSelectorCancelled: function() + { + // Do nothing, this is overridden by BlankStylePropertiesSection. + } +} + +WebInspector.StylePropertiesSection.prototype.__proto__ = WebInspector.PropertiesSection.prototype; + +/** + * @constructor + * @extends {WebInspector.PropertiesSection} + */ +WebInspector.ComputedStylePropertiesSection = function(styleRule, usedProperties, disabledComputedProperties) +{ + WebInspector.PropertiesSection.call(this, ""); + this.headerElement.addStyleClass("hidden"); + this.element.className = "styles-section monospace first-styles-section read-only computed-style"; + this.styleRule = styleRule; + this._usedProperties = usedProperties; + this._disabledComputedProperties = disabledComputedProperties; + this._alwaysShowComputedProperties = { "display": true, "height": true, "width": true }; + this.computedStyle = true; + this._propertyTreeElements = {}; + this._expandedPropertyNames = {}; +} + +WebInspector.ComputedStylePropertiesSection.prototype = { + collapse: function(dontRememberState) + { + // Overriding with empty body. + }, + + _isPropertyInherited: function(propertyName) + { + return !(propertyName in this._usedProperties) && !(propertyName in this._alwaysShowComputedProperties) && !(propertyName in this._disabledComputedProperties); + }, + + update: function() + { + this._expandedPropertyNames = {}; + for (var name in this._propertyTreeElements) { + if (this._propertyTreeElements[name].expanded) + this._expandedPropertyNames[name] = true; + } + this._propertyTreeElements = {}; + this.propertiesTreeOutline.removeChildren(); + this.populated = false; + }, + + onpopulate: function() + { + function sorter(a, b) + { + return a.name.localeCompare(b.name); + } + + var style = this.styleRule.style; + var uniqueProperties = []; + var allProperties = style.allProperties; + for (var i = 0; i < allProperties.length; ++i) + uniqueProperties.push(allProperties[i]); + uniqueProperties.sort(sorter); + + this._propertyTreeElements = {}; + for (var i = 0; i < uniqueProperties.length; ++i) { + var property = uniqueProperties[i]; + var inherited = this._isPropertyInherited(property.name); + var item = new WebInspector.StylePropertyTreeElement(null, this.styleRule, style, property, false, inherited, false); + this.propertiesTreeOutline.appendChild(item); + this._propertyTreeElements[property.name] = item; + } + }, + + rebuildComputedTrace: function(sections) + { + for (var i = 0; i < sections.length; ++i) { + var section = sections[i]; + if (section.computedStyle || section.isBlank) + continue; + + for (var j = 0; j < section.uniqueProperties.length; ++j) { + var property = section.uniqueProperties[j]; + if (property.disabled) + continue; + if (section.isInherited && !(property.name in WebInspector.CSSKeywordCompletions.InheritedProperties)) + continue; + + var treeElement = this._propertyTreeElements[property.name]; + if (treeElement) { + var fragment = document.createDocumentFragment(); + var selector = fragment.createChild("span"); + selector.style.color = "gray"; + selector.textContent = section.styleRule.selectorText; + fragment.appendChild(document.createTextNode(" - " + property.value + " ")); + var subtitle = fragment.createChild("span"); + subtitle.style.float = "right"; + subtitle.appendChild(section._createRuleOriginNode()); + var childElement = new TreeElement(fragment, null, false); + treeElement.appendChild(childElement); + if (section.isPropertyOverloaded(property.name)) + childElement.listItemElement.addStyleClass("overloaded"); + if (!property.parsedOk) + childElement.listItemElement.addStyleClass("not-parsed-ok"); + } + } + } + + // Restore expanded state after update. + for (var name in this._expandedPropertyNames) { + if (name in this._propertyTreeElements) + this._propertyTreeElements[name].expand(); + } + } +} + +WebInspector.ComputedStylePropertiesSection.prototype.__proto__ = WebInspector.PropertiesSection.prototype; + +/** + * @constructor + * @extends {WebInspector.StylePropertiesSection} + */ +WebInspector.BlankStylePropertiesSection = function(parentPane, defaultSelectorText) +{ + WebInspector.StylePropertiesSection.call(this, parentPane, {selectorText: defaultSelectorText, rule: {isViaInspector: true}}, true, false, false); + this.element.addStyleClass("blank-section"); +} + +WebInspector.BlankStylePropertiesSection.prototype = { + get isBlank() + { + return !this._normal; + }, + + expand: function() + { + if (!this.isBlank) + WebInspector.StylePropertiesSection.prototype.expand.call(this); + }, + + editingSelectorCommitted: function(element, newContent, oldContent, context, moveDirection) + { + if (!this.isBlank) { + WebInspector.StylePropertiesSection.prototype.editingSelectorCommitted.call(this, element, newContent, oldContent, context, moveDirection); + return; + } + + function successCallback(newRule, doesSelectorAffectSelectedNode) + { + var styleRule = { section: this, style: newRule.style, selectorText: newRule.selectorText, sourceURL: newRule.sourceURL, rule: newRule }; + this.makeNormal(styleRule); + + if (!doesSelectorAffectSelectedNode) { + this.noAffect = true; + this.element.addStyleClass("no-affect"); + } + + this._selectorRefElement.textContent = WebInspector.UIString("via inspector"); + this.expand(); + if (this.element.parentElement) // Might have been detached already. + this._moveEditorFromSelector(moveDirection); + } + + WebInspector.cssModel.addRule(this.pane.node.id, newContent, successCallback.bind(this), this.editingSelectorCancelled.bind(this)); + }, + + editingSelectorCancelled: function() + { + if (!this.isBlank) { + WebInspector.StylePropertiesSection.prototype.editingSelectorCancelled.call(this); + return; + } + + this.pane.removeSection(this); + }, + + makeNormal: function(styleRule) + { + this.element.removeStyleClass("blank-section"); + this.styleRule = styleRule; + this.rule = styleRule.rule; + + // FIXME: replace this instance by a normal WebInspector.StylePropertiesSection. + this._normal = true; + } +} + +WebInspector.BlankStylePropertiesSection.prototype.__proto__ = WebInspector.StylePropertiesSection.prototype; + +/** + * @constructor + * @extends {TreeElement} + * @param {?WebInspector.StylesSidebarPane} parentPane + */ +WebInspector.StylePropertyTreeElement = function(parentPane, styleRule, style, property, shorthand, inherited, overloaded) +{ + this._parentPane = parentPane; + this._styleRule = styleRule; + this.style = style; + this.property = property; + this.shorthand = shorthand; + this._inherited = inherited; + this._overloaded = overloaded; + + // Pass an empty title, the title gets made later in onattach. + TreeElement.call(this, "", null, shorthand); +} + +WebInspector.StylePropertyTreeElement.prototype = { + get inherited() + { + return this._inherited; + }, + + set inherited(x) + { + if (x === this._inherited) + return; + this._inherited = x; + this.updateState(); + }, + + get overloaded() + { + return this._overloaded; + }, + + set overloaded(x) + { + if (x === this._overloaded) + return; + this._overloaded = x; + this.updateState(); + }, + + get disabled() + { + return this.property.disabled; + }, + + get name() + { + if (!this.disabled || !this.property.text) + return this.property.name; + + var text = this.property.text; + var index = text.indexOf(":"); + if (index < 1) + return this.property.name; + + return text.substring(0, index).trim(); + }, + + get priority() + { + if (this.disabled) + return ""; // rely upon raw text to render it in the value field + return this.property.priority; + }, + + get value() + { + if (!this.disabled || !this.property.text) + return this.property.value; + + var match = this.property.text.match(/(.*);\s*/); + if (!match || !match[1]) + return this.property.value; + + var text = match[1]; + var index = text.indexOf(":"); + if (index < 1) + return this.property.value; + + return text.substring(index + 1).trim(); + }, + + get parsedOk() + { + return this.property.parsedOk; + }, + + onattach: function() + { + this.updateTitle(); + }, + + updateTitle: function() + { + var value = this.value; + + this.updateState(); + + var enabledCheckboxElement; + if (this.parsedOk) { + enabledCheckboxElement = document.createElement("input"); + enabledCheckboxElement.className = "enabled-button"; + enabledCheckboxElement.type = "checkbox"; + enabledCheckboxElement.checked = !this.disabled; + enabledCheckboxElement.addEventListener("change", this.toggleEnabled.bind(this), false); + } + + var nameElement = document.createElement("span"); + nameElement.className = "webkit-css-property"; + nameElement.textContent = this.name; + this.nameElement = nameElement; + + var valueElement = document.createElement("span"); + valueElement.className = "value"; + this.valueElement = valueElement; + + var cf = WebInspector.StylesSidebarPane.ColorFormat; + + if (value) { + var self = this; + + function processValue(regex, processor, nextProcessor, valueText) + { + var container = document.createDocumentFragment(); + + var items = valueText.replace(regex, "\0$1\0").split("\0"); + for (var i = 0; i < items.length; ++i) { + if ((i % 2) === 0) { + if (nextProcessor) + container.appendChild(nextProcessor(items[i])); + else + container.appendChild(document.createTextNode(items[i])); + } else { + var processedNode = processor(items[i]); + if (processedNode) + container.appendChild(processedNode); + } + } + + return container; + } + + function linkifyURL(url) + { + var hrefUrl = url; + var match = hrefUrl.match(/['"]?([^'"]+)/); + if (match) + hrefUrl = match[1]; + var container = document.createDocumentFragment(); + container.appendChild(document.createTextNode("url(")); + if (self._styleRule.sourceURL) + hrefUrl = WebInspector.completeURL(self._styleRule.sourceURL, hrefUrl); + else if (WebInspector.panels.elements.selectedDOMNode()) + hrefUrl = WebInspector.resourceURLForRelatedNode(WebInspector.panels.elements.selectedDOMNode(), hrefUrl); + var hasResource = !!WebInspector.resourceForURL(hrefUrl); + // FIXME: WebInspector.linkifyURLAsNode() should really use baseURI. + container.appendChild(WebInspector.linkifyURLAsNode(hrefUrl, url, undefined, !hasResource)); + container.appendChild(document.createTextNode(")")); + return container; + } + + function processColor(text) + { + try { + var color = new WebInspector.Color(text); + } catch (e) { + return document.createTextNode(text); + } + + var swatchElement = document.createElement("span"); + swatchElement.title = WebInspector.UIString("Click to change color format"); + swatchElement.className = "swatch"; + swatchElement.style.setProperty("background-color", text); + + swatchElement.addEventListener("click", changeColorDisplay, false); + swatchElement.addEventListener("dblclick", function(event) { event.stopPropagation() }, false); + + var format; + var formatSetting = WebInspector.settings.colorFormat.get(); + if (formatSetting === cf.Original) + format = cf.Original; + else if (color.nickname) + format = cf.Nickname; + else if (formatSetting === cf.RGB) + format = (color.simple ? cf.RGB : cf.RGBA); + else if (formatSetting === cf.HSL) + format = (color.simple ? cf.HSL : cf.HSLA); + else if (color.simple) + format = (color.hasShortHex() ? cf.ShortHEX : cf.HEX); + else + format = cf.RGBA; + + var colorValueElement = document.createElement("span"); + colorValueElement.textContent = color.toString(format); + + function nextFormat(curFormat) + { + // The format loop is as follows: + // * original + // * rgb(a) + // * hsl(a) + // * nickname (if the color has a nickname) + // * if the color is simple: + // - shorthex (if has short hex) + // - hex + switch (curFormat) { + case cf.Original: + return color.simple ? cf.RGB : cf.RGBA; + + case cf.RGB: + case cf.RGBA: + return color.simple ? cf.HSL : cf.HSLA; + + case cf.HSL: + case cf.HSLA: + if (color.nickname) + return cf.Nickname; + if (color.simple) + return color.hasShortHex() ? cf.ShortHEX : cf.HEX; + else + return cf.Original; + + case cf.ShortHEX: + return cf.HEX; + + case cf.HEX: + return cf.Original; + + case cf.Nickname: + if (color.simple) + return color.hasShortHex() ? cf.ShortHEX : cf.HEX; + else + return cf.Original; + + default: + return null; + } + } + + function changeColorDisplay(event) + { + do { + format = nextFormat(format); + var currentValue = color.toString(format || ""); + } while (format && currentValue === color.value && format !== cf.Original); + + if (format) + colorValueElement.textContent = currentValue; + } + + var container = document.createDocumentFragment(); + container.appendChild(swatchElement); + container.appendChild(colorValueElement); + return container; + } + + var colorRegex = /((?:rgb|hsl)a?\([^)]+\)|#[0-9a-fA-F]{6}|#[0-9a-fA-F]{3}|\b\w+\b(?!-))/g; + var colorProcessor = processValue.bind(window, colorRegex, processColor, null); + + valueElement.appendChild(processValue(/url\(\s*([^)\s]+)\s*\)/g, linkifyURL, WebInspector.CSSKeywordCompletions.isColorAwareProperty(self.name) ? colorProcessor : null, value)); + } + + this.listItemElement.removeChildren(); + nameElement.normalize(); + valueElement.normalize(); + + if (!this.treeOutline) + return; + + // Append the checkbox for root elements of an editable section. + if (enabledCheckboxElement && this.treeOutline.section && this.treeOutline.section.editable && this.parent.root) + this.listItemElement.appendChild(enabledCheckboxElement); + this.listItemElement.appendChild(nameElement); + this.listItemElement.appendChild(document.createTextNode(": ")); + this.listItemElement.appendChild(valueElement); + this.listItemElement.appendChild(document.createTextNode(";")); + + if (!this.parsedOk) { + // Avoid having longhands under an invalid shorthand. + this.hasChildren = false; + this.listItemElement.addStyleClass("not-parsed-ok"); + + // Add a separate exclamation mark IMG element with a tooltip. + var exclamationElement = document.createElement("img"); + exclamationElement.className = "exclamation-mark"; + exclamationElement.title = WebInspector.CSSCompletions.cssNameCompletions.keySet()[this.property.name.toLowerCase()] ? WebInspector.UIString("Invalid property value.") : WebInspector.UIString("Unknown property name."); + this.listItemElement.insertBefore(exclamationElement, this.listItemElement.firstChild); + } + if (this.property.inactive) + this.listItemElement.addStyleClass("inactive"); + + this.tooltip = this.property.propertyText; + }, + + _updatePane: function(userCallback) + { + if (this.treeOutline && this.treeOutline.section && this.treeOutline.section.pane) + this.treeOutline.section.pane._innerUpdate(true, this.treeOutline.section, userCallback); + else { + if (userCallback) + userCallback(); + } + }, + + toggleEnabled: function(event) + { + var disabled = !event.target.checked; + + function callback(newStyle) + { + if (!newStyle) + return; + + this.style = newStyle; + this._styleRule.style = newStyle; + + if (this.treeOutline.section && this.treeOutline.section.pane) + this.treeOutline.section.pane.dispatchEventToListeners("style property toggled"); + + this._updatePane(); + + delete this._parentPane._userOperation; + } + + this._parentPane._userOperation = true; + this.property.setDisabled(disabled, callback.bind(this)); + }, + + updateState: function() + { + if (!this.listItemElement) + return; + + if (this.style.isPropertyImplicit(this.name) || this.value === "initial") + this.listItemElement.addStyleClass("implicit"); + else + this.listItemElement.removeStyleClass("implicit"); + + this.selectable = !this.inherited; + if (this.inherited) + this.listItemElement.addStyleClass("inherited"); + else + this.listItemElement.removeStyleClass("inherited"); + + if (this.overloaded) + this.listItemElement.addStyleClass("overloaded"); + else + this.listItemElement.removeStyleClass("overloaded"); + + if (this.disabled) + this.listItemElement.addStyleClass("disabled"); + else + this.listItemElement.removeStyleClass("disabled"); + }, + + onpopulate: function() + { + // Only populate once and if this property is a shorthand. + if (this.children.length || !this.shorthand) + return; + + var longhandProperties = this.style.getLonghandProperties(this.name); + for (var i = 0; i < longhandProperties.length; ++i) { + var name = longhandProperties[i].name; + + + if (this.treeOutline.section) { + var inherited = this.treeOutline.section.isPropertyInherited(name); + var overloaded = this.treeOutline.section.isPropertyOverloaded(name); + } + + var liveProperty = this.style.getLiveProperty(name); + var item = new WebInspector.StylePropertyTreeElement(this._parentPane, this._styleRule, this.style, liveProperty, false, inherited, overloaded); + this.appendChild(item); + } + }, + + ondblclick: function(event) + { + this.startEditing(event.target); + event.stopPropagation(); + }, + + restoreNameElement: function() + { + // Restore if it doesn't yet exist or was accidentally deleted. + if (this.nameElement === this.listItemElement.querySelector(".webkit-css-property")) + return; + + this.nameElement = document.createElement("span"); + this.nameElement.className = "webkit-css-property"; + this.nameElement.textContent = ""; + this.listItemElement.insertBefore(this.nameElement, this.listItemElement.firstChild); + }, + + startEditing: function(selectElement) + { + // FIXME: we don't allow editing of longhand properties under a shorthand right now. + if (this.parent.shorthand) + return; + + if (this.treeOutline.section && !this.treeOutline.section.editable) + return; + + if (!selectElement) + selectElement = this.nameElement; // No arguments passed in - edit the name element by default. + else + selectElement = selectElement.enclosingNodeOrSelfWithClass("webkit-css-property") || selectElement.enclosingNodeOrSelfWithClass("value"); + + var isEditingName = selectElement === this.nameElement; + if (!isEditingName && selectElement !== this.valueElement) { + // Double-click in the LI - start editing value. + isEditingName = false; + selectElement = this.valueElement; + } + + if (WebInspector.isBeingEdited(selectElement)) + return; + + var context = { + expanded: this.expanded, + hasChildren: this.hasChildren, + isEditingName: isEditingName, + previousContent: selectElement.textContent + }; + + // Lie about our children to prevent expanding on double click and to collapse shorthands. + this.hasChildren = false; + + if (selectElement.parentElement) + selectElement.parentElement.addStyleClass("child-editing"); + selectElement.textContent = selectElement.textContent; // remove color swatch and the like + + function pasteHandler(context, event) + { + var data = event.clipboardData.getData("Text"); + if (!data) + return; + var colonIdx = data.indexOf(":"); + if (colonIdx < 0) + return; + var name = data.substring(0, colonIdx).trim(); + var value = data.substring(colonIdx + 1).trim(); + + event.preventDefault(); + + if (!("originalName" in context)) { + context.originalName = this.nameElement.textContent; + context.originalValue = this.valueElement.textContent; + } + this.nameElement.textContent = name; + this.valueElement.textContent = value; + this.nameElement.normalize(); + this.valueElement.normalize(); + + this.editingCommitted(null, event.target.textContent, context.previousContent, context, "forward"); + } + + function blurListener(context, event) + { + this.editingCommitted(null, event.target.textContent, context.previousContent, context, ""); + } + + delete this.originalPropertyText; + + this._parentPane._isEditingStyle = true; + if (selectElement.parentElement) + selectElement.parentElement.scrollIntoViewIfNeeded(false); + + var applyItemCallback = !isEditingName ? this._applyFreeFlowStyleTextEdit.bind(this, true) : undefined; + this._prompt = new WebInspector.StylesSidebarPane.CSSPropertyPrompt(isEditingName ? WebInspector.CSSCompletions.cssNameCompletions : WebInspector.CSSKeywordCompletions.forProperty(this.nameElement.textContent), this, isEditingName); + if (applyItemCallback) { + this._prompt.addEventListener(WebInspector.TextPrompt.Events.ItemApplied, applyItemCallback, this); + this._prompt.addEventListener(WebInspector.TextPrompt.Events.ItemAccepted, applyItemCallback, this); + } + var proxyElement = this._prompt.attachAndStartEditing(selectElement, blurListener.bind(this, context)); + + proxyElement.addEventListener("keydown", this.editingNameValueKeyDown.bind(this, context), false); + if (isEditingName) + proxyElement.addEventListener("paste", pasteHandler.bind(this, context)); + + window.getSelection().setBaseAndExtent(selectElement, 0, selectElement, 1); + }, + + editingNameValueKeyDown: function(context, event) + { + if (event.handled) + return; + + var isEditingName = context.isEditingName; + var result; + + function shouldCommitValueSemicolon(text, cursorPosition) + { + // FIXME: should this account for semicolons inside comments? + var openQuote = ""; + for (var i = 0; i < cursorPosition; ++i) { + var ch = text[i]; + if (ch === "\\" && openQuote !== "") + ++i; // skip next character inside string + else if (!openQuote && (ch === "\"" || ch === "'")) + openQuote = ch; + else if (openQuote === ch) + openQuote = ""; + } + return !openQuote; + } + + // FIXME: the ":"/";" detection does not work for non-US layouts due to the event being keydown rather than keypress. + var isFieldInputTerminated = (event.keyCode === WebInspector.KeyboardShortcut.Keys.Semicolon.code) && + (isEditingName ? event.shiftKey : (!event.shiftKey && shouldCommitValueSemicolon(event.target.textContent, event.target.selectionLeftOffset()))); + if (isEnterKey(event) || isFieldInputTerminated) { + // Enter or colon (for name)/semicolon outside of string (for value). + event.preventDefault(); + result = "forward"; + } else if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Esc.code || event.keyIdentifier === "U+001B") + result = "cancel"; + else if (!isEditingName && this._newProperty && event.keyCode === WebInspector.KeyboardShortcut.Keys.Backspace.code) { + // For a new property, when Backspace is pressed at the beginning of new property value, move back to the property name. + var selection = window.getSelection(); + if (selection.isCollapsed && !selection.focusOffset) { + event.preventDefault(); + result = "backward"; + } + } else if (event.keyIdentifier === "U+0009") { // Tab key. + result = event.shiftKey ? "backward" : "forward"; + event.preventDefault(); + } + + if (result) { + switch (result) { + case "cancel": + this.editingCancelled(null, context); + break; + case "forward": + case "backward": + this.editingCommitted(null, event.target.textContent, context.previousContent, context, result); + break; + } + + event.stopPropagation(); + return; + } + + if (!isEditingName) + this._applyFreeFlowStyleTextEdit(false); + }, + + _applyFreeFlowStyleTextEdit: function(now) + { + if (this._applyFreeFlowStyleTextEditTimer) + clearTimeout(this._applyFreeFlowStyleTextEditTimer); + + function apply() + { + this.applyStyleText(this.nameElement.textContent + ": " + this.valueElement.textContent, false, false, false); + } + if (now) + apply.call(this); + else + this._applyFreeFlowStyleTextEditTimer = setTimeout(apply.bind(this), 100); + }, + + kickFreeFlowStyleEditForTest: function() + { + this._applyFreeFlowStyleTextEdit(true); + }, + + editingEnded: function(context) + { + if (this._applyFreeFlowStyleTextEditTimer) + clearTimeout(this._applyFreeFlowStyleTextEditTimer); + + this.hasChildren = context.hasChildren; + if (context.expanded) + this.expand(); + var editedElement = context.isEditingName ? this.nameElement : this.valueElement; + // The proxyElement has been deleted, no need to remove listener. + if (editedElement.parentElement) + editedElement.parentElement.removeStyleClass("child-editing"); + + delete this._parentPane._isEditingStyle; + }, + + editingCancelled: function(element, context) + { + this._removePrompt(); + this._revertStyleUponEditingCanceled(this.originalPropertyText); + // This should happen last, as it clears the info necessary to restore the property value after [Page]Up/Down changes. + this.editingEnded(context); + }, + + _revertStyleUponEditingCanceled: function(originalPropertyText) + { + if (typeof originalPropertyText === "string") { + delete this.originalPropertyText; + this.applyStyleText(originalPropertyText, true, false, true); + } else { + if (this._newProperty) + this.treeOutline.removeChild(this); + else + this.updateTitle(); + } + }, + + editingCommitted: function(element, userInput, previousContent, context, moveDirection) + { + this._removePrompt(); + this.editingEnded(context); + var isEditingName = context.isEditingName; + + // Determine where to move to before making changes + var createNewProperty, moveToPropertyName, moveToSelector; + var moveTo = this; + var moveToOther = (isEditingName ^ (moveDirection === "forward")); + var abandonNewProperty = this._newProperty && !userInput && (moveToOther || isEditingName); + if (moveDirection === "forward" && !isEditingName || moveDirection === "backward" && isEditingName) { + do { + moveTo = (moveDirection === "forward" ? moveTo.nextSibling : moveTo.previousSibling); + } while(moveTo && !moveTo.selectable); + + if (moveTo) + moveToPropertyName = moveTo.name; + else if (moveDirection === "forward" && (!this._newProperty || userInput)) + createNewProperty = true; + else if (moveDirection === "backward") + moveToSelector = true; + } + + // Make the Changes and trigger the moveToNextCallback after updating. + var blankInput = /^\s*$/.test(userInput); + var isDataPasted = "originalName" in context; + var isDirtyViaPaste = isDataPasted && (this.nameElement.textContent !== context.originalName || this.valueElement.textContent !== context.originalValue); + var shouldCommitNewProperty = this._newProperty && (moveToOther || (!moveDirection && !isEditingName) || (isEditingName && blankInput)); + if (((userInput !== previousContent || isDirtyViaPaste) && !this._newProperty) || shouldCommitNewProperty) { + this.treeOutline.section._afterUpdate = moveToNextCallback.bind(this, this._newProperty, !blankInput, this.treeOutline.section); + var propertyText; + if (blankInput || (this._newProperty && /^\s*$/.test(this.valueElement.textContent))) + propertyText = ""; + else { + if (isEditingName) + propertyText = userInput + ": " + this.valueElement.textContent; + else + propertyText = this.nameElement.textContent + ": " + userInput; + } + this.applyStyleText(propertyText, true, true, false); + } else { + if (!isDataPasted && !this._newProperty) + this.updateTitle(); + moveToNextCallback.call(this, this._newProperty, false, this.treeOutline.section); + } + + var moveToIndex = moveTo && this.treeOutline ? this.treeOutline.children.indexOf(moveTo) : -1; + + // The Callback to start editing the next/previous property/selector. + function moveToNextCallback(alreadyNew, valueChanged, section) + { + if (!moveDirection) + return; + + // User just tabbed through without changes. + if (moveTo && moveTo.parent) { + moveTo.startEditing(!isEditingName ? moveTo.nameElement : moveTo.valueElement); + return; + } + + // User has made a change then tabbed, wiping all the original treeElements. + // Recalculate the new treeElement for the same property we were going to edit next. + if (moveTo && !moveTo.parent) { + var propertyElements = section.propertiesTreeOutline.children; + if (moveDirection === "forward" && blankInput && !isEditingName) + --moveToIndex; + if (moveToIndex >= propertyElements.length && !this._newProperty) + createNewProperty = true; + else { + var treeElement = moveToIndex >= 0 ? propertyElements[moveToIndex] : null; + if (treeElement) { + treeElement.startEditing(!isEditingName ? treeElement.nameElement : treeElement.valueElement); + return; + } else if (!alreadyNew) + moveToSelector = true; + } + } + + // Create a new attribute in this section (or move to next editable selector if possible). + if (createNewProperty) { + if (alreadyNew && !valueChanged && (isEditingName ^ (moveDirection === "backward"))) + return; + + section.addNewBlankProperty().startEditing(); + return; + } + + if (abandonNewProperty) { + var sectionToEdit = moveDirection === "backward" ? section : section.nextEditableSibling(); + if (sectionToEdit) { + if (sectionToEdit.rule) + sectionToEdit.startEditingSelector(); + else + sectionToEdit._moveEditorFromSelector(moveDirection); + } + return; + } + + if (moveToSelector) { + if (section.rule) + section.startEditingSelector(); + else + section._moveEditorFromSelector(moveDirection); + } + } + }, + + _removePrompt: function() + { + // BUG 53242. This cannot go into editingEnded(), as it should always happen first for any editing outcome. + if (this._prompt) { + this._prompt.detach(); + delete this._prompt; + } + }, + + _hasBeenModifiedIncrementally: function() + { + // New properties applied via up/down or live editing have an originalPropertyText and will be deleted later + // on, if cancelled, when the empty string gets applied as their style text. + return typeof this.originalPropertyText === "string" || (!!this.property.propertyText && this._newProperty); + }, + + applyStyleText: function(styleText, updateInterface, majorChange, isRevert) + { + function userOperationFinishedCallback(parentPane, updateInterface) + { + if (updateInterface) + delete parentPane._userOperation; + } + + // Leave a way to cancel editing after incremental changes. + if (!isRevert && !updateInterface && !this._hasBeenModifiedIncrementally()) { + // Remember the rule's original CSS text on [Page](Up|Down), so it can be restored + // if the editing is canceled. + this.originalPropertyText = this.property.propertyText; + } + + if (!this.treeOutline) + return; + + var section = this.treeOutline.section; + var elementsPanel = WebInspector.panels.elements; + styleText = styleText.replace(/\s/g, " ").trim(); // Replace   with whitespace. + var styleTextLength = styleText.length; + if (!styleTextLength && updateInterface && !isRevert && this._newProperty && !this._hasBeenModifiedIncrementally()) { + // The user deleted everything and never applied a new property value via Up/Down scrolling/live editing, so remove the tree element and update. + this.parent.removeChild(this); + section.afterUpdate(); + return; + } + + var currentNode = this._parentPane.node; + if (updateInterface) + this._parentPane._userOperation = true; + + function callback(userCallback, originalPropertyText, newStyle) + { + if (!newStyle) { + if (updateInterface) { + // It did not apply, cancel editing. + this._revertStyleUponEditingCanceled(originalPropertyText); + } + userCallback(); + return; + } + + this.style = newStyle; + this.property = newStyle.propertyAt(this.property.index); + this._styleRule.style = this.style; + + if (section && section.pane) + section.pane.dispatchEventToListeners("style edited"); + + if (updateInterface && currentNode === section.pane.node) { + this._updatePane(userCallback); + return; + } + + userCallback(); + } + + // Append a ";" if the new text does not end in ";". + // FIXME: this does not handle trailing comments. + if (styleText.length && !/;\s*$/.test(styleText)) + styleText += ";"; + this.property.setText(styleText, majorChange, callback.bind(this, userOperationFinishedCallback.bind(null, this._parentPane, updateInterface), this.originalPropertyText)); + } +} + +WebInspector.StylePropertyTreeElement.prototype.__proto__ = TreeElement.prototype; + +/** + * @constructor + * @extends {WebInspector.TextPrompt} + * @param {function(*)=} acceptCallback + */ +WebInspector.StylesSidebarPane.CSSPropertyPrompt = function(cssCompletions, sidebarPane, isEditingName, acceptCallback) +{ + // Use the same callback both for applyItemCallback and acceptItemCallback. + WebInspector.TextPrompt.call(this, this._buildPropertyCompletions.bind(this), WebInspector.StylesSidebarPane.StyleValueDelimiters); + this.setSuggestBoxEnabled("generic-suggest"); + this._cssCompletions = cssCompletions; + this._sidebarPane = sidebarPane; + this._isEditingName = isEditingName; +} + +WebInspector.StylesSidebarPane.CSSPropertyPrompt.prototype = { + onKeyDown: function(event) + { + switch (event.keyIdentifier) { + case "Up": + case "Down": + case "PageUp": + case "PageDown": + if (this._handleNameOrValueUpDown(event)) { + event.preventDefault(); + return; + } + break; + } + + WebInspector.TextPrompt.prototype.onKeyDown.call(this, event); + }, + + tabKeyPressed: function() + { + this.acceptAutoComplete(); + + // Always tab to the next field. + return false; + }, + + _handleNameOrValueUpDown: function(event) + { + // Handle numeric value increment/decrement only at this point. + if (!this._isEditingName && this._handleUpOrDownValue(event)) + return true; + + return false; + }, + + _handleUpOrDownValue: function(event) + { + var arrowKeyPressed = (event.keyIdentifier === "Up" || event.keyIdentifier === "Down"); + var pageKeyPressed = (event.keyIdentifier === "PageUp" || event.keyIdentifier === "PageDown"); + if (!arrowKeyPressed && !pageKeyPressed) + return false; + + var selection = window.getSelection(); + if (!selection.rangeCount) + return false; + + var selectionRange = selection.getRangeAt(0); + if (!selectionRange.commonAncestorContainer.isSelfOrDescendant(this._sidebarPane.valueElement)) + return false; + + var wordRange = selectionRange.startContainer.rangeOfWord(selectionRange.startOffset, WebInspector.StylesSidebarPane.StyleValueDelimiters, this._sidebarPane.valueElement); + var wordString = wordRange.toString(); + var replacementString; + var prefix, suffix, number; + + var matches; + matches = /(.*#)([\da-fA-F]+)(.*)/.exec(wordString); + if (matches && matches.length) { + prefix = matches[1]; + suffix = matches[3]; + number = WebInspector.StylesSidebarPane.alteredHexNumber(matches[2], event); + + replacementString = prefix + number + suffix; + } else { + matches = /(.*?)(-?(?:\d+(?:\.\d+)?|\.\d+))(.*)/.exec(wordString); + if (matches && matches.length) { + prefix = matches[1]; + suffix = matches[3]; + number = WebInspector.StylesSidebarPane.alteredFloatNumber(parseFloat(matches[2]), event); + if (number === null) { + // Need to check for null explicitly. + return false; + } + + replacementString = prefix + number + suffix; + } + } + + if (replacementString) { + var replacementTextNode = document.createTextNode(replacementString); + + wordRange.deleteContents(); + wordRange.insertNode(replacementTextNode); + + var finalSelectionRange = document.createRange(); + finalSelectionRange.setStart(replacementTextNode, 0); + finalSelectionRange.setEnd(replacementTextNode, replacementString.length); + + selection.removeAllRanges(); + selection.addRange(finalSelectionRange); + + event.handled = true; + event.preventDefault(); + + // Synthesize property text disregarding any comments, custom whitespace etc. + this._sidebarPane.applyStyleText(this._sidebarPane.nameElement.textContent + ": " + this._sidebarPane.valueElement.textContent, false, false, false); + + return true; + } + return false; + }, + + _buildPropertyCompletions: function(wordRange, force, completionsReadyCallback) + { + var prefix = wordRange.toString().toLowerCase(); + if (!prefix && !force) + return; + + var results = this._cssCompletions.startsWith(prefix); + completionsReadyCallback(results); + } +} + +WebInspector.StylesSidebarPane.CSSPropertyPrompt.prototype.__proto__ = WebInspector.TextPrompt.prototype; +/* PanelEnablerView.js */ + +/* + * Copyright (C) 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 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 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. + */ + +/** + * @extends {WebInspector.View} + * @constructor + */ +WebInspector.PanelEnablerView = function(identifier, headingText, disclaimerText, buttonTitle) +{ + WebInspector.View.call(this); + this.registerRequiredCSS("panelEnablerView.css"); + + this.element.addStyleClass("panel-enabler-view"); + this.element.addStyleClass(identifier); + + this.contentElement = document.createElement("div"); + this.contentElement.className = "panel-enabler-view-content"; + this.element.appendChild(this.contentElement); + + this.imageElement = document.createElement("img"); + this.contentElement.appendChild(this.imageElement); + + this.choicesForm = document.createElement("form"); + this.contentElement.appendChild(this.choicesForm); + + this.headerElement = document.createElement("h1"); + this.headerElement.textContent = headingText; + this.choicesForm.appendChild(this.headerElement); + + var self = this; + function enableOption(text, checked) { + var label = document.createElement("label"); + var option = document.createElement("input"); + option.type = "radio"; + option.name = "enable-option"; + if (checked) + option.checked = true; + label.appendChild(option); + label.appendChild(document.createTextNode(text)); + self.choicesForm.appendChild(label); + return option; + }; + + this.enabledForSession = enableOption(WebInspector.UIString("Only enable for this session"), true); + this.enabledAlways = enableOption(WebInspector.UIString("Always enable"), false); + + this.disclaimerElement = document.createElement("div"); + this.disclaimerElement.className = "panel-enabler-disclaimer"; + this.disclaimerElement.textContent = disclaimerText; + this.choicesForm.appendChild(this.disclaimerElement); + + this.enableButton = document.createElement("button"); + this.enableButton.setAttribute("type", "button"); + this.enableButton.textContent = buttonTitle; + this.enableButton.addEventListener("click", this._enableButtonCicked.bind(this), false); + this.choicesForm.appendChild(this.enableButton); +} + +WebInspector.PanelEnablerView.prototype = { + _enableButtonCicked: function() + { + this.dispatchEventToListeners("enable clicked"); + }, + + onResize: function() + { + this.imageElement.removeStyleClass("hidden"); + + if (this.element.offsetWidth < (this.choicesForm.offsetWidth + this.imageElement.offsetWidth)) + this.imageElement.addStyleClass("hidden"); + }, + + get alwaysEnabled() { + return this.enabledAlways.checked; + } +} + +WebInspector.PanelEnablerView.prototype.__proto__ = WebInspector.View.prototype; +/* StatusBarButton.js */ + +/* + * 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. + */ + +/** + * @extends {WebInspector.Object} + * @constructor + * @param {number=} states + */ +WebInspector.StatusBarButton = function(title, className, states) +{ + this.element = document.createElement("button"); + this.element.className = className + " status-bar-item"; + this.element.addEventListener("click", this._clicked.bind(this), false); + + this.glyph = document.createElement("div"); + this.glyph.className = "glyph"; + this.element.appendChild(this.glyph); + + this.glyphShadow = document.createElement("div"); + this.glyphShadow.className = "glyph shadow"; + this.element.appendChild(this.glyphShadow); + + this.states = states; + if (!states) + this.states = 2; + + if (states == 2) + this._state = false; + else + this._state = 0; + + this.title = title; + this.disabled = false; + this._visible = true; +} + +WebInspector.StatusBarButton.prototype = { + _clicked: function() + { + this.dispatchEventToListeners("click"); + }, + + get disabled() + { + return this._disabled; + }, + + set disabled(x) + { + if (this._disabled === x) + return; + this._disabled = x; + this.element.disabled = x; + }, + + get title() + { + return this._title; + }, + + set title(x) + { + if (this._title === x) + return; + this._title = x; + this.element.title = x; + }, + + get state() + { + return this._state; + }, + + set state(x) + { + if (this._state === x) + return; + + if (this.states === 2) { + if (x) + this.element.addStyleClass("toggled-on"); + else + this.element.removeStyleClass("toggled-on"); + } else { + if (x !== 0) { + this.element.removeStyleClass("toggled-" + this._state); + this.element.addStyleClass("toggled-" + x); + } else + this.element.removeStyleClass("toggled-" + this._state); + } + this._state = x; + }, + + get toggled() + { + if (this.states !== 2) + throw("Only used toggled when there are 2 states, otherwise, use state"); + return this.state; + }, + + set toggled(x) + { + if (this.states !== 2) + throw("Only used toggled when there are 2 states, otherwise, use state"); + this.state = x; + }, + + get visible() + { + return this._visible; + }, + + set visible(x) + { + if (this._visible === x) + return; + + if (x) + this.element.removeStyleClass("hidden"); + else + this.element.addStyleClass("hidden"); + this._visible = x; + } +} + +WebInspector.StatusBarButton.prototype.__proto__ = WebInspector.Object.prototype; +/* ElementsPanel.js */ + +/* + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008 Matt Lilek + * Copyright (C) 2009 Joseph Pecoraro + * + * 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. + */ + +/** + * @constructor + * @extends {WebInspector.Panel} + */ +WebInspector.ElementsPanel = function() +{ + WebInspector.Panel.call(this, "elements"); + this.registerRequiredCSS("elementsPanel.css"); + this.registerRequiredCSS("textPrompt.css"); + this.setHideOnDetach(); + + const initialSidebarWidth = 325; + const minimalContentWidthPercent = 34; + this.createSplitView(this.element, WebInspector.SplitView.SidebarPosition.Right, initialSidebarWidth); + this.splitView.minimalSidebarWidth = Preferences.minElementsSidebarWidth; + this.splitView.minimalMainWidthPercent = minimalContentWidthPercent; + + this.contentElement = this.splitView.mainElement; + this.contentElement.id = "elements-content"; + this.contentElement.addStyleClass("outline-disclosure"); + this.contentElement.addStyleClass("source-code"); + if (!WebInspector.settings.domWordWrap.get()) + this.contentElement.classList.add("nowrap"); + WebInspector.settings.domWordWrap.addChangeListener(this._domWordWrapSettingChanged.bind(this)); + + this.contentElement.addEventListener("contextmenu", this._contextMenuEventFired.bind(this), true); + + this.treeOutline = new WebInspector.ElementsTreeOutline(true, true, false, this._populateContextMenu.bind(this)); + this.treeOutline.wireToDomAgent(); + + this.treeOutline.addEventListener(WebInspector.ElementsTreeOutline.Events.SelectedNodeChanged, this._selectedNodeChanged, this); + + this.crumbsElement = document.createElement("div"); + this.crumbsElement.className = "crumbs"; + this.crumbsElement.addEventListener("mousemove", this._mouseMovedInCrumbs.bind(this), false); + this.crumbsElement.addEventListener("mouseout", this._mouseMovedOutOfCrumbs.bind(this), false); + + this.sidebarPanes = {}; + this.sidebarPanes.computedStyle = new WebInspector.ComputedStyleSidebarPane(); + this.sidebarPanes.styles = new WebInspector.StylesSidebarPane(this.sidebarPanes.computedStyle); + this.sidebarPanes.metrics = new WebInspector.MetricsSidebarPane(); + this.sidebarPanes.properties = new WebInspector.PropertiesSidebarPane(); + if (Capabilities.nativeInstrumentationEnabled) + this.sidebarPanes.domBreakpoints = WebInspector.domBreakpointsSidebarPane; + this.sidebarPanes.eventListeners = new WebInspector.EventListenersSidebarPane(); + + this.sidebarPanes.styles.onexpand = this.updateStyles.bind(this); + this.sidebarPanes.metrics.onexpand = this.updateMetrics.bind(this); + this.sidebarPanes.properties.onexpand = this.updateProperties.bind(this); + this.sidebarPanes.eventListeners.onexpand = this.updateEventListeners.bind(this); + + this.sidebarPanes.styles.expanded = true; + + this.sidebarPanes.styles.addEventListener("style edited", this._stylesPaneEdited, this); + this.sidebarPanes.styles.addEventListener("style property toggled", this._stylesPaneEdited, this); + this.sidebarPanes.metrics.addEventListener("metrics edited", this._metricsPaneEdited, this); + + for (var pane in this.sidebarPanes) { + this.sidebarElement.appendChild(this.sidebarPanes[pane].element); + if (this.sidebarPanes[pane].onattach) + this.sidebarPanes[pane].onattach(); + } + + this.nodeSearchButton = new WebInspector.StatusBarButton(WebInspector.UIString("Select an element in the page to inspect it."), "node-search-status-bar-item"); + this.nodeSearchButton.addEventListener("click", this.toggleSearchingForNode, this); + + this._registerShortcuts(); + + WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.NodeRemoved, this._nodeRemoved, this); + WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.DocumentUpdated, this._documentUpdated, this); + WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.InspectElementRequested, this._inspectElementRequested, this); +} + +WebInspector.ElementsPanel.prototype = { + get toolbarItemLabel() + { + return WebInspector.UIString("Elements"); + }, + + get statusBarItems() + { + return [this.crumbsElement]; + }, + + get defaultFocusedElement() + { + return this.treeOutline.element; + }, + + statusBarResized: function() + { + this.updateBreadcrumbSizes(); + }, + + wasShown: function() + { + // Attach heavy component lazily + if (this.treeOutline.element.parentElement !== this.contentElement) + this.contentElement.appendChild(this.treeOutline.element); + + WebInspector.Panel.prototype.wasShown.call(this); + + this.updateBreadcrumb(); + this.treeOutline.updateSelection(); + this.treeOutline.setVisible(true); + + if (!this.treeOutline.rootDOMNode) + WebInspector.domAgent.requestDocument(); + + if (Capabilities.nativeInstrumentationEnabled) + this.sidebarElement.insertBefore(this.sidebarPanes.domBreakpoints.element, this.sidebarPanes.eventListeners.element); + }, + + willHide: function() + { + WebInspector.domAgent.hideDOMNodeHighlight(); + this.setSearchingForNode(false); + this.treeOutline.setVisible(false); + + // Detach heavy component on hide + this.contentElement.removeChild(this.treeOutline.element); + + WebInspector.Panel.prototype.willHide.call(this); + }, + + onResize: function() + { + this.treeOutline.updateSelection(); + this.updateBreadcrumbSizes(); + }, + + _selectedNodeChanged: function() + { + var selectedNode = this.selectedDOMNode(); + if (!selectedNode && this._lastValidSelectedNode) + this._selectedPathOnReset = this._lastValidSelectedNode.path(); + + this.updateBreadcrumb(false); + + for (var pane in this.sidebarPanes) + this.sidebarPanes[pane].needsUpdate = true; + + this.updateStyles(true); + this.updateMetrics(); + this.updateProperties(); + this.updateEventListeners(); + + if (selectedNode) { + ConsoleAgent.addInspectedNode(selectedNode.id); + this._lastValidSelectedNode = selectedNode; + } + }, + + _reset: function() + { + delete this.currentQuery; + }, + + _documentUpdated: function(event) + { + var inspectedRootDocument = event.data; + + this._reset(); + this.searchCanceled(); + + this.treeOutline.rootDOMNode = inspectedRootDocument; + + if (!inspectedRootDocument) { + if (this.isShowing()) + WebInspector.domAgent.requestDocument(); + return; + } + + if (Capabilities.nativeInstrumentationEnabled) + this.sidebarPanes.domBreakpoints.restoreBreakpoints(); + + /** + * @this {WebInspector.ElementsPanel} + * @param {WebInspector.DOMNode=} candidateFocusNode + */ + function selectNode(candidateFocusNode) + { + if (!candidateFocusNode) + candidateFocusNode = inspectedRootDocument.body || inspectedRootDocument.documentElement; + + if (!candidateFocusNode) + return; + + this.selectDOMNode(candidateFocusNode); + if (this.treeOutline.selectedTreeElement) + this.treeOutline.selectedTreeElement.expand(); + } + + function selectLastSelectedNode(nodeId) + { + if (this.selectedDOMNode()) { + // Focused node has been explicitly set while reaching out for the last selected node. + return; + } + var node = nodeId ? WebInspector.domAgent.nodeForId(nodeId) : null; + selectNode.call(this, node); + } + + if (this._selectedPathOnReset) + WebInspector.domAgent.pushNodeByPathToFrontend(this._selectedPathOnReset, selectLastSelectedNode.bind(this)); + else + selectNode.call(this); + delete this._selectedPathOnReset; + }, + + searchCanceled: function() + { + delete this._searchQuery; + this._hideSearchHighlights(); + + WebInspector.searchController.updateSearchMatchesCount(0, this); + + delete this._currentSearchResultIndex; + delete this._searchResults; + WebInspector.domAgent.cancelSearch(); + }, + + performSearch: function(query) + { + // Call searchCanceled since it will reset everything we need before doing a new search. + this.searchCanceled(); + + const whitespaceTrimmedQuery = query.trim(); + if (!whitespaceTrimmedQuery.length) + return; + + this._searchQuery = query; + + /** + * @param {number} resultCount + */ + function resultCountCallback(resultCount) + { + WebInspector.searchController.updateSearchMatchesCount(resultCount, this); + if (!resultCount) + return; + + this._searchResults = new Array(resultCount); + this._currentSearchResultIndex = -1; + this.jumpToNextSearchResult(); + } + WebInspector.domAgent.performSearch(whitespaceTrimmedQuery, resultCountCallback.bind(this)); + }, + + _contextMenuEventFired: function(event) + { + function toggleWordWrap() + { + WebInspector.settings.domWordWrap.set(!WebInspector.settings.domWordWrap.get()); + } + + var contextMenu = new WebInspector.ContextMenu(); + var populated = this.treeOutline.populateContextMenu(contextMenu, event); + if (populated) + contextMenu.appendSeparator(); + contextMenu.appendCheckboxItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Word wrap" : "Word Wrap"), toggleWordWrap.bind(this), WebInspector.settings.domWordWrap.get()); + + contextMenu.show(event); + }, + + _domWordWrapSettingChanged: function(event) + { + if (event.data) + this.contentElement.removeStyleClass("nowrap"); + else + this.contentElement.addStyleClass("nowrap"); + + var selectedNode = this.selectedDOMNode(); + if (!selectedNode) + return; + + var treeElement = this.treeOutline.findTreeElement(selectedNode); + if (treeElement) + treeElement.updateSelection(); // Recalculate selection highlight dimensions. + }, + + switchToAndFocus: function(node) + { + // Reset search restore. + WebInspector.searchController.cancelSearch(); + WebInspector.inspectorView.setCurrentPanel(this); + this.selectDOMNode(node, true); + }, + + _populateContextMenu: function(contextMenu, node) + { + if (Capabilities.nativeInstrumentationEnabled) { + // Add debbuging-related actions + contextMenu.appendSeparator(); + var pane = this.sidebarPanes.domBreakpoints; + pane.populateNodeContextMenu(node, contextMenu); + } + }, + + jumpToNextSearchResult: function() + { + if (!this._searchResults) + return; + + this._hideSearchHighlights(); + if (++this._currentSearchResultIndex >= this._searchResults.length) + this._currentSearchResultIndex = 0; + + this._highlightCurrentSearchResult(); + }, + + jumpToPreviousSearchResult: function() + { + if (!this._searchResults) + return; + + this._hideSearchHighlights(); + if (--this._currentSearchResultIndex < 0) + this._currentSearchResultIndex = (this._searchResults.length - 1); + + this._highlightCurrentSearchResult(); + }, + + _highlightCurrentSearchResult: function() + { + var index = this._currentSearchResultIndex; + var searchResults = this._searchResults; + var searchResult = searchResults[index]; + + if (searchResult === null) { + WebInspector.searchController.updateCurrentMatchIndex(index, this); + return; + } + + if (typeof searchResult === "undefined") { + // No data for slot, request it. + function callback(node) + { + searchResults[index] = node || null; + this._highlightCurrentSearchResult(); + } + WebInspector.domAgent.searchResult(index, callback.bind(this)); + return; + } + + WebInspector.searchController.updateCurrentMatchIndex(index, this); + + var treeElement = this.treeOutline.findTreeElement(searchResult); + if (treeElement) { + treeElement.highlightSearchResults(this._searchQuery); + treeElement.reveal(); + } + }, + + _hideSearchHighlights: function() + { + if (!this._searchResults) + return; + var searchResult = this._searchResults[this._currentSearchResultIndex]; + if (!searchResult) + return; + var treeElement = this.treeOutline.findTreeElement(searchResult); + if (treeElement) + treeElement.hideSearchHighlights(); + }, + + selectedDOMNode: function() + { + return this.treeOutline.selectedDOMNode(); + }, + + /** + * @param {boolean=} focus + */ + selectDOMNode: function(node, focus) + { + this.treeOutline.selectDOMNode(node, focus); + }, + + _nodeRemoved: function(event) + { + if (!this.isShowing()) + return; + + var crumbs = this.crumbsElement; + for (var crumb = crumbs.firstChild; crumb; crumb = crumb.nextSibling) { + if (crumb.representedObject === event.data.node) { + this.updateBreadcrumb(true); + return; + } + } + }, + + _stylesPaneEdited: function() + { + // Once styles are edited, the Metrics pane should be updated. + this.sidebarPanes.metrics.needsUpdate = true; + this.updateMetrics(); + }, + + _metricsPaneEdited: function() + { + // Once metrics are edited, the Styles pane should be updated. + this.sidebarPanes.styles.needsUpdate = true; + this.updateStyles(true); + }, + + _mouseMovedInCrumbs: function(event) + { + var nodeUnderMouse = document.elementFromPoint(event.pageX, event.pageY); + var crumbElement = nodeUnderMouse.enclosingNodeOrSelfWithClass("crumb"); + + WebInspector.domAgent.highlightDOMNode(crumbElement ? crumbElement.representedObject.id : 0); + + if ("_mouseOutOfCrumbsTimeout" in this) { + clearTimeout(this._mouseOutOfCrumbsTimeout); + delete this._mouseOutOfCrumbsTimeout; + } + }, + + _mouseMovedOutOfCrumbs: function(event) + { + var nodeUnderMouse = document.elementFromPoint(event.pageX, event.pageY); + if (nodeUnderMouse && nodeUnderMouse.isDescendant(this.crumbsElement)) + return; + + WebInspector.domAgent.hideDOMNodeHighlight(); + + this._mouseOutOfCrumbsTimeout = setTimeout(this.updateBreadcrumbSizes.bind(this), 1000); + }, + + /** + * @param {boolean=} forceUpdate + */ + updateBreadcrumb: function(forceUpdate) + { + if (!this.isShowing()) + return; + + var crumbs = this.crumbsElement; + + var handled = false; + var foundRoot = false; + var crumb = crumbs.firstChild; + while (crumb) { + if (crumb.representedObject === this.treeOutline.rootDOMNode) + foundRoot = true; + + if (foundRoot) + crumb.addStyleClass("dimmed"); + else + crumb.removeStyleClass("dimmed"); + + if (crumb.representedObject === this.selectedDOMNode()) { + crumb.addStyleClass("selected"); + handled = true; + } else { + crumb.removeStyleClass("selected"); + } + + crumb = crumb.nextSibling; + } + + if (handled && !forceUpdate) { + // We don't need to rebuild the crumbs, but we need to adjust sizes + // to reflect the new focused or root node. + this.updateBreadcrumbSizes(); + return; + } + + crumbs.removeChildren(); + + var panel = this; + + function selectCrumbFunction(event) + { + var crumb = event.currentTarget; + if (crumb.hasStyleClass("collapsed")) { + // Clicking a collapsed crumb will expose the hidden crumbs. + if (crumb === panel.crumbsElement.firstChild) { + // If the focused crumb is the first child, pick the farthest crumb + // that is still hidden. This allows the user to expose every crumb. + var currentCrumb = crumb; + while (currentCrumb) { + var hidden = currentCrumb.hasStyleClass("hidden"); + var collapsed = currentCrumb.hasStyleClass("collapsed"); + if (!hidden && !collapsed) + break; + crumb = currentCrumb; + currentCrumb = currentCrumb.nextSibling; + } + } + + panel.updateBreadcrumbSizes(crumb); + } else + panel.selectDOMNode(crumb.representedObject, true); + + event.preventDefault(); + } + + foundRoot = false; + for (var current = this.selectedDOMNode(); current; current = current.parentNode) { + if (current.nodeType() === Node.DOCUMENT_NODE) + continue; + + if (current === this.treeOutline.rootDOMNode) + foundRoot = true; + + crumb = document.createElement("span"); + crumb.className = "crumb"; + crumb.representedObject = current; + crumb.addEventListener("mousedown", selectCrumbFunction, false); + + var crumbTitle; + switch (current.nodeType()) { + case Node.ELEMENT_NODE: + WebInspector.DOMPresentationUtils.decorateNodeLabel(current, crumb); + break; + + case Node.TEXT_NODE: + crumbTitle = WebInspector.UIString("(text)"); + break + + case Node.COMMENT_NODE: + crumbTitle = ""; + break; + + case Node.DOCUMENT_TYPE_NODE: + crumbTitle = ""; + break; + + default: + crumbTitle = current.nodeNameInCorrectCase(); + } + + if (!crumb.childNodes.length) { + var nameElement = document.createElement("span"); + nameElement.textContent = crumbTitle; + crumb.appendChild(nameElement); + crumb.title = crumbTitle; + } + + if (foundRoot) + crumb.addStyleClass("dimmed"); + if (current === this.selectedDOMNode()) + crumb.addStyleClass("selected"); + if (!crumbs.childNodes.length) + crumb.addStyleClass("end"); + + crumbs.appendChild(crumb); + } + + if (crumbs.hasChildNodes()) + crumbs.lastChild.addStyleClass("start"); + + this.updateBreadcrumbSizes(); + }, + + /** + * @param {Element=} focusedCrumb + */ + updateBreadcrumbSizes: function(focusedCrumb) + { + if (!this.isShowing()) + return; + + if (document.body.offsetWidth <= 0) { + // The stylesheet hasn't loaded yet or the window is closed, + // so we can't calculate what is need. Return early. + return; + } + + var crumbs = this.crumbsElement; + if (!crumbs.childNodes.length || crumbs.offsetWidth <= 0) + return; // No crumbs, do nothing. + + // A Zero index is the right most child crumb in the breadcrumb. + var selectedIndex = 0; + var focusedIndex = 0; + var selectedCrumb; + + var i = 0; + var crumb = crumbs.firstChild; + while (crumb) { + // Find the selected crumb and index. + if (!selectedCrumb && crumb.hasStyleClass("selected")) { + selectedCrumb = crumb; + selectedIndex = i; + } + + // Find the focused crumb index. + if (crumb === focusedCrumb) + focusedIndex = i; + + // Remove any styles that affect size before + // deciding to shorten any crumbs. + if (crumb !== crumbs.lastChild) + crumb.removeStyleClass("start"); + if (crumb !== crumbs.firstChild) + crumb.removeStyleClass("end"); + + crumb.removeStyleClass("compact"); + crumb.removeStyleClass("collapsed"); + crumb.removeStyleClass("hidden"); + + crumb = crumb.nextSibling; + ++i; + } + + // Restore the start and end crumb classes in case they got removed in coalesceCollapsedCrumbs(). + // The order of the crumbs in the document is opposite of the visual order. + crumbs.firstChild.addStyleClass("end"); + crumbs.lastChild.addStyleClass("start"); + + function crumbsAreSmallerThanContainer() + { + var rightPadding = 20; + var errorWarningElement = document.getElementById("error-warning-count"); + if (!WebInspector.drawer.visible && errorWarningElement) + rightPadding += errorWarningElement.offsetWidth; + return ((crumbs.totalOffsetLeft() + crumbs.offsetWidth + rightPadding) < window.innerWidth); + } + + if (crumbsAreSmallerThanContainer()) + return; // No need to compact the crumbs, they all fit at full size. + + var BothSides = 0; + var AncestorSide = -1; + var ChildSide = 1; + + /** + * @param {boolean=} significantCrumb + */ + function makeCrumbsSmaller(shrinkingFunction, direction, significantCrumb) + { + if (!significantCrumb) + significantCrumb = (focusedCrumb || selectedCrumb); + + if (significantCrumb === selectedCrumb) + var significantIndex = selectedIndex; + else if (significantCrumb === focusedCrumb) + var significantIndex = focusedIndex; + else { + var significantIndex = 0; + for (var i = 0; i < crumbs.childNodes.length; ++i) { + if (crumbs.childNodes[i] === significantCrumb) { + significantIndex = i; + break; + } + } + } + + function shrinkCrumbAtIndex(index) + { + var shrinkCrumb = crumbs.childNodes[index]; + if (shrinkCrumb && shrinkCrumb !== significantCrumb) + shrinkingFunction(shrinkCrumb); + if (crumbsAreSmallerThanContainer()) + return true; // No need to compact the crumbs more. + return false; + } + + // Shrink crumbs one at a time by applying the shrinkingFunction until the crumbs + // fit in the container or we run out of crumbs to shrink. + if (direction) { + // Crumbs are shrunk on only one side (based on direction) of the signifcant crumb. + var index = (direction > 0 ? 0 : crumbs.childNodes.length - 1); + while (index !== significantIndex) { + if (shrinkCrumbAtIndex(index)) + return true; + index += (direction > 0 ? 1 : -1); + } + } else { + // Crumbs are shrunk in order of descending distance from the signifcant crumb, + // with a tie going to child crumbs. + var startIndex = 0; + var endIndex = crumbs.childNodes.length - 1; + while (startIndex != significantIndex || endIndex != significantIndex) { + var startDistance = significantIndex - startIndex; + var endDistance = endIndex - significantIndex; + if (startDistance >= endDistance) + var index = startIndex++; + else + var index = endIndex--; + if (shrinkCrumbAtIndex(index)) + return true; + } + } + + // We are not small enough yet, return false so the caller knows. + return false; + } + + function coalesceCollapsedCrumbs() + { + var crumb = crumbs.firstChild; + var collapsedRun = false; + var newStartNeeded = false; + var newEndNeeded = false; + while (crumb) { + var hidden = crumb.hasStyleClass("hidden"); + if (!hidden) { + var collapsed = crumb.hasStyleClass("collapsed"); + if (collapsedRun && collapsed) { + crumb.addStyleClass("hidden"); + crumb.removeStyleClass("compact"); + crumb.removeStyleClass("collapsed"); + + if (crumb.hasStyleClass("start")) { + crumb.removeStyleClass("start"); + newStartNeeded = true; + } + + if (crumb.hasStyleClass("end")) { + crumb.removeStyleClass("end"); + newEndNeeded = true; + } + + continue; + } + + collapsedRun = collapsed; + + if (newEndNeeded) { + newEndNeeded = false; + crumb.addStyleClass("end"); + } + } else + collapsedRun = true; + crumb = crumb.nextSibling; + } + + if (newStartNeeded) { + crumb = crumbs.lastChild; + while (crumb) { + if (!crumb.hasStyleClass("hidden")) { + crumb.addStyleClass("start"); + break; + } + crumb = crumb.previousSibling; + } + } + } + + function compact(crumb) + { + if (crumb.hasStyleClass("hidden")) + return; + crumb.addStyleClass("compact"); + } + + function collapse(crumb, dontCoalesce) + { + if (crumb.hasStyleClass("hidden")) + return; + crumb.addStyleClass("collapsed"); + crumb.removeStyleClass("compact"); + if (!dontCoalesce) + coalesceCollapsedCrumbs(); + } + + function compactDimmed(crumb) + { + if (crumb.hasStyleClass("dimmed")) + compact(crumb); + } + + function collapseDimmed(crumb) + { + if (crumb.hasStyleClass("dimmed")) + collapse(crumb, false); + } + + if (!focusedCrumb) { + // When not focused on a crumb we can be biased and collapse less important + // crumbs that the user might not care much about. + + // Compact child crumbs. + if (makeCrumbsSmaller(compact, ChildSide)) + return; + + // Collapse child crumbs. + if (makeCrumbsSmaller(collapse, ChildSide)) + return; + + // Compact dimmed ancestor crumbs. + if (makeCrumbsSmaller(compactDimmed, AncestorSide)) + return; + + // Collapse dimmed ancestor crumbs. + if (makeCrumbsSmaller(collapseDimmed, AncestorSide)) + return; + } + + // Compact ancestor crumbs, or from both sides if focused. + if (makeCrumbsSmaller(compact, (focusedCrumb ? BothSides : AncestorSide))) + return; + + // Collapse ancestor crumbs, or from both sides if focused. + if (makeCrumbsSmaller(collapse, (focusedCrumb ? BothSides : AncestorSide))) + return; + + if (!selectedCrumb) + return; + + // Compact the selected crumb. + compact(selectedCrumb); + if (crumbsAreSmallerThanContainer()) + return; + + // Collapse the selected crumb as a last resort. Pass true to prevent coalescing. + collapse(selectedCrumb, true); + }, + + updateStyles: function(forceUpdate) + { + var stylesSidebarPane = this.sidebarPanes.styles; + var computedStylePane = this.sidebarPanes.computedStyle; + if ((!stylesSidebarPane.expanded && !computedStylePane.expanded) || !stylesSidebarPane.needsUpdate) + return; + + stylesSidebarPane.update(this.selectedDOMNode(), forceUpdate); + stylesSidebarPane.needsUpdate = false; + }, + + updateMetrics: function() + { + var metricsSidebarPane = this.sidebarPanes.metrics; + if (!metricsSidebarPane.expanded || !metricsSidebarPane.needsUpdate) + return; + + metricsSidebarPane.update(this.selectedDOMNode()); + metricsSidebarPane.needsUpdate = false; + }, + + updateProperties: function() + { + var propertiesSidebarPane = this.sidebarPanes.properties; + if (!propertiesSidebarPane.expanded || !propertiesSidebarPane.needsUpdate) + return; + + propertiesSidebarPane.update(this.selectedDOMNode()); + propertiesSidebarPane.needsUpdate = false; + }, + + updateEventListeners: function() + { + var eventListenersSidebarPane = this.sidebarPanes.eventListeners; + if (!eventListenersSidebarPane.expanded || !eventListenersSidebarPane.needsUpdate) + return; + + eventListenersSidebarPane.update(this.selectedDOMNode()); + eventListenersSidebarPane.needsUpdate = false; + }, + + _registerShortcuts: function() + { + var shortcut = WebInspector.KeyboardShortcut; + var section = WebInspector.shortcutsScreen.section(WebInspector.UIString("Elements Panel")); + var keys = [ + shortcut.shortcutToString(shortcut.Keys.Up), + shortcut.shortcutToString(shortcut.Keys.Down) + ]; + section.addRelatedKeys(keys, WebInspector.UIString("Navigate elements")); + + keys = [ + shortcut.shortcutToString(shortcut.Keys.Right), + shortcut.shortcutToString(shortcut.Keys.Left) + ]; + section.addRelatedKeys(keys, WebInspector.UIString("Expand/collapse")); + section.addKey(shortcut.shortcutToString(shortcut.Keys.Enter), WebInspector.UIString("Edit attribute")); + + this.sidebarPanes.styles.registerShortcuts(); + }, + + handleShortcut: function(event) + { + // Cmd/Control + Shift + C should be a shortcut to clicking the Node Search Button. + // This shortcut matches Firebug. + if (event.keyIdentifier === "U+0043") { // C key + if (WebInspector.isMac()) + var isNodeSearchKey = event.metaKey && !event.ctrlKey && !event.altKey && event.shiftKey; + else + var isNodeSearchKey = event.ctrlKey && !event.metaKey && !event.altKey && event.shiftKey; + + if (isNodeSearchKey) { + this.toggleSearchingForNode(); + event.handled = true; + return; + } + } + }, + + handleCopyEvent: function(event) + { + // Don't prevent the normal copy if the user has a selection. + if (!window.getSelection().isCollapsed) + return; + event.clipboardData.clearData(); + event.preventDefault(); + this.selectedDOMNode().copyNode(); + }, + + sidebarResized: function(event) + { + this.treeOutline.updateSelection(); + }, + + _inspectElementRequested: function(event) + { + var node = event.data; + this.revealAndSelectNode(node.id); + }, + + revealAndSelectNode: function(nodeId) + { + WebInspector.inspectorView.setCurrentPanel(this); + + var node = WebInspector.domAgent.nodeForId(nodeId); + if (!node) + return; + + WebInspector.domAgent.highlightDOMNodeForTwoSeconds(nodeId); + this.selectDOMNode(node, true); + if (this.nodeSearchButton.toggled) { + InspectorFrontendHost.bringToFront(); + this.nodeSearchButton.toggled = false; + } + }, + + setSearchingForNode: function(enabled) + { + function callback(error) + { + if (!error) + this.nodeSearchButton.toggled = enabled; + } + WebInspector.domAgent.setInspectModeEnabled(enabled, callback.bind(this)); + }, + + toggleSearchingForNode: function() + { + this.setSearchingForNode(!this.nodeSearchButton.toggled); + } +} + +WebInspector.ElementsPanel.prototype.__proto__ = WebInspector.Panel.prototype; +/* NetworkPanel.js */ + +/* + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009 Anthony Ricaud + * Copyright (C) 2011 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: + * + * 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. + */ + +/** + * @constructor + * @extends {WebInspector.View} + */ +WebInspector.NetworkLogView = function() +{ + WebInspector.View.call(this); + this.registerRequiredCSS("networkLogView.css"); + + this._allowResourceSelection = false; + this._resources = []; + this._resourcesById = {}; + this._resourcesByURL = {}; + this._staleResources = {}; + this._resourceGridNodes = {}; + this._lastResourceGridNodeId = 0; + this._mainResourceLoadTime = -1; + this._mainResourceDOMContentTime = -1; + this._hiddenCategories = {}; + this._matchedResources = []; + this._matchedResourcesMap = {}; + this._currentMatchedResourceIndex = -1; + + this._categories = WebInspector.resourceCategories; + + this._createStatusbarButtons(); + this._createFilterStatusBarItems(); + this._linkifier = WebInspector.debuggerPresentationModel.createLinkifier(); + + WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceStarted, this._onResourceStarted, this); + WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceUpdated, this._onResourceUpdated, this); + WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceFinished, this._onResourceUpdated, this); + + WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, this._mainFrameNavigated, this); + WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.OnLoad, this._onLoadEventFired, this); + WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.DOMContentLoaded, this._domContentLoadedEventFired, this); + + this._initializeView(); + function onCanClearBrowserCache(error, result) + { + this._canClearBrowserCache = result; + } + NetworkAgent.canClearBrowserCache(onCanClearBrowserCache.bind(this)); + + function onCanClearBrowserCookies(error, result) + { + this._canClearBrowserCookies = result; + } + NetworkAgent.canClearBrowserCookies(onCanClearBrowserCookies.bind(this)); +} + +WebInspector.NetworkLogView.prototype = { + _initializeView: function() + { + this.element.id = "network-container"; + + this._createSortingFunctions(); + this._createTable(); + this._createTimelineGrid(); + this._createSummaryBar(); + + if (!this.useLargeRows) + this._setLargerResources(this.useLargeRows); + + this._allowPopover = true; + this._popoverHelper = new WebInspector.PopoverHelper(this.element, this._getPopoverAnchor.bind(this), this._showPopover.bind(this)); + // Enable faster hint. + this._popoverHelper.setTimeout(100); + + this.calculator = new WebInspector.NetworkTransferTimeCalculator(); + this._filter(this._filterAllElement, false); + + this.switchToDetailedView(); + }, + + get statusBarItems() + { + return [this._largerResourcesButton.element, this._preserveLogToggle.element, this._clearButton.element, this._filterBarElement]; + }, + + get useLargeRows() + { + return WebInspector.settings.resourcesLargeRows.get(); + }, + + set allowPopover(flag) + { + this._allowPopover = flag; + }, + + get allowResourceSelection() + { + return this._allowResourceSelection; + }, + + set allowResourceSelection(flag) + { + this._allowResourceSelection = !!flag; + }, + + elementsToRestoreScrollPositionsFor: function() + { + if (!this._dataGrid) // Not initialized yet. + return []; + return [this._dataGrid.scrollContainer]; + }, + + onResize: function() + { + this._updateOffscreenRows(); + }, + + _createTimelineGrid: function() + { + this._timelineGrid = new WebInspector.TimelineGrid(); + this._timelineGrid.element.addStyleClass("network-timeline-grid"); + this._dataGrid.element.appendChild(this._timelineGrid.element); + }, + + _createTable: function() + { + var columns; + if (Capabilities.nativeInstrumentationEnabled) + columns = {name: {}, method: {}, status: {}, type: {}, initiator: {}, size: {}, time: {}, timeline: {}}; + else + columns = {name: {}, method: {}, status: {}, type: {}, size: {}, time: {}, timeline: {}}; + columns.name.titleDOMFragment = this._makeHeaderFragment(WebInspector.UIString("Name"), WebInspector.UIString("Path")); + columns.name.sortable = true; + columns.name.width = "20%"; + columns.name.disclosure = true; + + columns.method.title = WebInspector.UIString("Method"); + columns.method.sortable = true; + columns.method.width = "6%"; + + columns.status.titleDOMFragment = this._makeHeaderFragment(WebInspector.UIString("Status"), WebInspector.UIString("Text")); + columns.status.sortable = true; + columns.status.width = "6%"; + + columns.type.title = WebInspector.UIString("Type"); + columns.type.sortable = true; + columns.type.width = "6%"; + + if (Capabilities.nativeInstrumentationEnabled) { + columns.initiator.title = WebInspector.UIString("Initiator"); + columns.initiator.sortable = true; + columns.initiator.width = "10%"; + } + + columns.size.titleDOMFragment = this._makeHeaderFragment(WebInspector.UIString("Size"), WebInspector.UIString("Content")); + columns.size.sortable = true; + columns.size.width = "6%"; + columns.size.aligned = "right"; + + columns.time.titleDOMFragment = this._makeHeaderFragment(WebInspector.UIString("Time"), WebInspector.UIString("Latency")); + columns.time.sortable = true; + columns.time.width = "6%"; + columns.time.aligned = "right"; + + columns.timeline.title = ""; + columns.timeline.sortable = false; + if (Capabilities.nativeInstrumentationEnabled) + columns.timeline.width = "40%"; + else + columns.timeline.width = "50%"; + columns.timeline.sort = "ascending"; + + this._dataGrid = new WebInspector.DataGrid(columns); + this._dataGrid.resizeMethod = WebInspector.DataGrid.ResizeMethod.Last; + this._dataGrid.element.addStyleClass("network-log-grid"); + this._dataGrid.element.addEventListener("contextmenu", this._contextMenu.bind(this), true); + this._dataGrid.show(this.element); + + // Event listeners need to be added _after_ we attach to the document, so that owner document is properly update. + this._dataGrid.addEventListener("sorting changed", this._sortItems, this); + this._dataGrid.addEventListener("width changed", this._updateDividersIfNeeded, this); + this._dataGrid.scrollContainer.addEventListener("scroll", this._updateOffscreenRows.bind(this)); + + this._patchTimelineHeader(); + }, + + _makeHeaderFragment: function(title, subtitle) + { + var fragment = document.createDocumentFragment(); + fragment.appendChild(document.createTextNode(title)); + var subtitleDiv = document.createElement("div"); + subtitleDiv.className = "network-header-subtitle"; + subtitleDiv.textContent = subtitle; + fragment.appendChild(subtitleDiv); + return fragment; + }, + + _patchTimelineHeader: function() + { + var timelineSorting = document.createElement("select"); + + var option = document.createElement("option"); + option.value = "startTime"; + option.label = WebInspector.UIString("Timeline"); + timelineSorting.appendChild(option); + + option = document.createElement("option"); + option.value = "startTime"; + option.label = WebInspector.UIString("Start Time"); + timelineSorting.appendChild(option); + + option = document.createElement("option"); + option.value = "responseTime"; + option.label = WebInspector.UIString("Response Time"); + timelineSorting.appendChild(option); + + option = document.createElement("option"); + option.value = "endTime"; + option.label = WebInspector.UIString("End Time"); + timelineSorting.appendChild(option); + + option = document.createElement("option"); + option.value = "duration"; + option.label = WebInspector.UIString("Duration"); + timelineSorting.appendChild(option); + + option = document.createElement("option"); + option.value = "latency"; + option.label = WebInspector.UIString("Latency"); + timelineSorting.appendChild(option); + + var header = this._dataGrid.headerTableHeader("timeline"); + header.replaceChild(timelineSorting, header.firstChild); + + timelineSorting.addEventListener("click", function(event) { event.stopPropagation() }, false); + timelineSorting.addEventListener("change", this._sortByTimeline.bind(this), false); + this._timelineSortSelector = timelineSorting; + }, + + _createSortingFunctions: function() + { + this._sortingFunctions = {}; + this._sortingFunctions.name = WebInspector.NetworkDataGridNode.NameComparator; + this._sortingFunctions.method = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "method", false); + this._sortingFunctions.status = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "statusCode", false); + this._sortingFunctions.type = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "mimeType", false); + this._sortingFunctions.initiator = WebInspector.NetworkDataGridNode.InitiatorComparator; + this._sortingFunctions.size = WebInspector.NetworkDataGridNode.SizeComparator; + this._sortingFunctions.time = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "duration", false); + this._sortingFunctions.timeline = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "startTime", false); + this._sortingFunctions.startTime = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "startTime", false); + this._sortingFunctions.endTime = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "endTime", false); + this._sortingFunctions.responseTime = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "responseReceivedTime", false); + this._sortingFunctions.duration = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "duration", true); + this._sortingFunctions.latency = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "latency", true); + + var timeCalculator = new WebInspector.NetworkTransferTimeCalculator(); + var durationCalculator = new WebInspector.NetworkTransferDurationCalculator(); + + this._calculators = {}; + this._calculators.timeline = timeCalculator; + this._calculators.startTime = timeCalculator; + this._calculators.endTime = timeCalculator; + this._calculators.responseTime = timeCalculator; + this._calculators.duration = durationCalculator; + this._calculators.latency = durationCalculator; + }, + + _sortItems: function() + { + this._removeAllNodeHighlights(); + var columnIdentifier = this._dataGrid.sortColumnIdentifier; + if (columnIdentifier === "timeline") { + this._sortByTimeline(); + return; + } + var sortingFunction = this._sortingFunctions[columnIdentifier]; + if (!sortingFunction) + return; + + this._dataGrid.sortNodes(sortingFunction, this._dataGrid.sortOrder === "descending"); + this._timelineSortSelector.selectedIndex = 0; + this._updateOffscreenRows(); + + this.performSearch(null, true); + }, + + _sortByTimeline: function() + { + this._removeAllNodeHighlights(); + var selectedIndex = this._timelineSortSelector.selectedIndex; + if (!selectedIndex) + selectedIndex = 1; // Sort by start time by default. + var selectedOption = this._timelineSortSelector[selectedIndex]; + var value = selectedOption.value; + + var sortingFunction = this._sortingFunctions[value]; + this._dataGrid.sortNodes(sortingFunction); + this.calculator = this._calculators[value]; + if (this.calculator.startAtZero) + this._timelineGrid.hideEventDividers(); + else + this._timelineGrid.showEventDividers(); + this._dataGrid.markColumnAsSortedBy("timeline", "ascending"); + this._updateOffscreenRows(); + }, + + _createFilterStatusBarItems: function() + { + var filterBarElement = document.createElement("div"); + filterBarElement.className = "scope-bar status-bar-item"; + filterBarElement.id = "network-filter"; + + function createFilterElement(category, label) + { + var categoryElement = document.createElement("li"); + categoryElement.category = category; + categoryElement.className = category; + categoryElement.appendChild(document.createTextNode(label)); + categoryElement.addEventListener("click", this._updateFilter.bind(this), false); + filterBarElement.appendChild(categoryElement); + + return categoryElement; + } + + this._filterAllElement = createFilterElement.call(this, "all", WebInspector.UIString("All")); + + // Add a divider + var dividerElement = document.createElement("div"); + dividerElement.addStyleClass("scope-bar-divider"); + filterBarElement.appendChild(dividerElement); + + for (var category in this._categories) + createFilterElement.call(this, category, this._categories[category].title); + this._filterBarElement = filterBarElement; + }, + + _createSummaryBar: function() + { + var tbody = this._dataGrid.dataTableBody; + var tfoot = document.createElement("tfoot"); + var tr = tfoot.createChild("tr", "revealed network-summary-bar"); + var td = tr.createChild("td"); + td.setAttribute("colspan", 7); + tbody.parentNode.insertBefore(tfoot, tbody); + this._summaryBarElement = td; + }, + + _updateSummaryBar: function() + { + var requestsNumber = this._resources.length; + + if (!requestsNumber) { + if (this._summaryBarElement._isDisplayingWarning) + return; + this._summaryBarElement._isDisplayingWarning = true; + + var img = document.createElement("img"); + img.src = "Images/warningIcon.png"; + this._summaryBarElement.removeChildren(); + this._summaryBarElement.appendChild(img); + this._summaryBarElement.appendChild(document.createTextNode( + WebInspector.UIString("No requests captured. Reload the page to see detailed information on the network activity."))); + return; + } + delete this._summaryBarElement._isDisplayingWarning; + + var transferSize = 0; + var selectedRequestsNumber = 0; + var selectedTransferSize = 0; + var baseTime = -1; + var maxTime = -1; + for (var i = 0; i < this._resources.length; ++i) { + var resource = this._resources[i]; + var resourceTransferSize = (resource.cached || !resource.transferSize) ? 0 : resource.transferSize; + transferSize += resourceTransferSize; + if (!this._hiddenCategories.all || !this._hiddenCategories[resource.category.name]) { + selectedRequestsNumber++; + selectedTransferSize += resourceTransferSize; + } + if (resource.url === WebInspector.inspectedPageURL) + baseTime = resource.startTime; + if (resource.endTime > maxTime) + maxTime = resource.endTime; + } + var text = ""; + if (this._hiddenCategories.all) { + text += String.sprintf(WebInspector.UIString("%d / %d requests"), selectedRequestsNumber, requestsNumber); + text += " \u2758 " + String.sprintf(WebInspector.UIString("%s / %s transferred"), Number.bytesToString(selectedTransferSize), Number.bytesToString(transferSize)); + } else { + text += String.sprintf(WebInspector.UIString("%d requests"), requestsNumber); + text += " \u2758 " + String.sprintf(WebInspector.UIString("%s transferred"), Number.bytesToString(transferSize)); + } + if (baseTime !== -1 && this._mainResourceLoadTime !== -1 && this._mainResourceDOMContentTime !== -1 && this._mainResourceDOMContentTime > baseTime) { + text += " \u2758 " + String.sprintf(WebInspector.UIString("%s (onload: %s, DOMContentLoaded: %s)"), + Number.secondsToString(maxTime - baseTime), + Number.secondsToString(this._mainResourceLoadTime - baseTime), + Number.secondsToString(this._mainResourceDOMContentTime - baseTime)); + } + this._summaryBarElement.textContent = text; + }, + + _showCategory: function(category) + { + this._dataGrid.element.addStyleClass("filter-" + category); + delete this._hiddenCategories[category]; + }, + + _hideCategory: function(category) + { + this._dataGrid.element.removeStyleClass("filter-" + category); + this._hiddenCategories[category] = true; + }, + + _updateFilter: function(e) + { + this._removeAllNodeHighlights(); + var isMac = WebInspector.isMac(); + var selectMultiple = false; + if (isMac && e.metaKey && !e.ctrlKey && !e.altKey && !e.shiftKey) + selectMultiple = true; + if (!isMac && e.ctrlKey && !e.metaKey && !e.altKey && !e.shiftKey) + selectMultiple = true; + + this._filter(e.target, selectMultiple); + this.performSearch(null, true); + this._updateSummaryBar(); + }, + + _filter: function(target, selectMultiple) + { + function unselectAll() + { + for (var i = 0; i < this._filterBarElement.childNodes.length; ++i) { + var child = this._filterBarElement.childNodes[i]; + if (!child.category) + continue; + + child.removeStyleClass("selected"); + this._hideCategory(child.category); + } + } + + if (target.category === this._filterAllElement) { + if (target.hasStyleClass("selected")) { + // We can't unselect All, so we break early here + return; + } + + // If All wasn't selected, and now is, unselect everything else. + unselectAll.call(this); + } else { + // Something other than All is being selected, so we want to unselect All. + if (this._filterAllElement.hasStyleClass("selected")) { + this._filterAllElement.removeStyleClass("selected"); + this._hideCategory("all"); + } + } + + if (!selectMultiple) { + // If multiple selection is off, we want to unselect everything else + // and just select ourselves. + unselectAll.call(this); + + target.addStyleClass("selected"); + this._showCategory(target.category); + this._updateOffscreenRows(); + return; + } + + if (target.hasStyleClass("selected")) { + // If selectMultiple is turned on, and we were selected, we just + // want to unselect ourselves. + target.removeStyleClass("selected"); + this._hideCategory(target.category); + } else { + // If selectMultiple is turned on, and we weren't selected, we just + // want to select ourselves. + target.addStyleClass("selected"); + this._showCategory(target.category); + } + this._updateOffscreenRows(); + }, + + _defaultRefreshDelay: 500, + + _scheduleRefresh: function() + { + if (this._needsRefresh) + return; + + this._needsRefresh = true; + + if (this.isShowing() && !this._refreshTimeout) + this._refreshTimeout = setTimeout(this.refresh.bind(this), this._defaultRefreshDelay); + }, + + _updateDividersIfNeeded: function(force) + { + if (!this._dataGrid) + return; + var timelineColumn = this._dataGrid.columns.timeline; + for (var i = 0; i < this._dataGrid.resizers.length; ++i) { + if (timelineColumn.ordinal === this._dataGrid.resizers[i].rightNeighboringColumnID) { + // Position timline grid location. + this._timelineGrid.element.style.left = this._dataGrid.resizers[i].style.left; + this._timelineGrid.element.style.right = "18px"; + } + } + + var proceed = true; + if (!this.isShowing()) { + this._scheduleRefresh(); + proceed = false; + } else + proceed = this._timelineGrid.updateDividers(force, this.calculator); + + if (!proceed) + return; + + if (this.calculator.startAtZero || !this.calculator.computePercentageFromEventTime) { + // If our current sorting method starts at zero, that means it shows all + // resources starting at the same point, and so onLoad event and DOMContent + // event lines really wouldn't make much sense here, so don't render them. + // Additionally, if the calculator doesn't have the computePercentageFromEventTime + // function defined, we are probably sorting by size, and event times aren't relevant + // in this case. + return; + } + + this._timelineGrid.removeEventDividers(); + if (this._mainResourceLoadTime !== -1) { + var percent = this.calculator.computePercentageFromEventTime(this._mainResourceLoadTime); + + var loadDivider = document.createElement("div"); + loadDivider.className = "network-event-divider network-red-divider"; + + var loadDividerPadding = document.createElement("div"); + loadDividerPadding.className = "network-event-divider-padding"; + loadDividerPadding.title = WebInspector.UIString("Load event fired"); + loadDividerPadding.appendChild(loadDivider); + loadDividerPadding.style.left = percent + "%"; + this._timelineGrid.addEventDivider(loadDividerPadding); + } + + if (this._mainResourceDOMContentTime !== -1) { + var percent = this.calculator.computePercentageFromEventTime(this._mainResourceDOMContentTime); + + var domContentDivider = document.createElement("div"); + domContentDivider.className = "network-event-divider network-blue-divider"; + + var domContentDividerPadding = document.createElement("div"); + domContentDividerPadding.className = "network-event-divider-padding"; + domContentDividerPadding.title = WebInspector.UIString("DOMContent event fired"); + domContentDividerPadding.appendChild(domContentDivider); + domContentDividerPadding.style.left = percent + "%"; + this._timelineGrid.addEventDivider(domContentDividerPadding); + } + }, + + _refreshIfNeeded: function() + { + if (this._needsRefresh) + this.refresh(); + }, + + _invalidateAllItems: function() + { + for (var i = 0; i < this._resources.length; ++i) { + var resource = this._resources[i]; + this._staleResources[resource.requestId] = resource; + } + }, + + get calculator() + { + return this._calculator; + }, + + set calculator(x) + { + if (!x || this._calculator === x) + return; + + this._calculator = x; + this._calculator.reset(); + + this._invalidateAllItems(); + this.refresh(); + }, + + _resourceGridNode: function(resource) + { + return this._resourceGridNodes[resource.__gridNodeId]; + }, + + _createResourceGridNode: function(resource) + { + var node = new WebInspector.NetworkDataGridNode(this, resource); + resource.__gridNodeId = this._lastResourceGridNodeId++; + this._resourceGridNodes[resource.__gridNodeId] = node; + return node; + }, + + _createStatusbarButtons: function() + { + this._preserveLogToggle = new WebInspector.StatusBarButton(WebInspector.UIString("Preserve Log upon Navigation"), "record-profile-status-bar-item"); + this._preserveLogToggle.addEventListener("click", this._onPreserveLogClicked, this); + + this._clearButton = new WebInspector.StatusBarButton(WebInspector.UIString("Clear"), "clear-status-bar-item"); + this._clearButton.addEventListener("click", this._reset, this); + + this._largerResourcesButton = new WebInspector.StatusBarButton(WebInspector.UIString("Use small resource rows."), "network-larger-resources-status-bar-item"); + this._largerResourcesButton.toggled = WebInspector.settings.resourcesLargeRows.get(); + this._largerResourcesButton.addEventListener("click", this._toggleLargerResources, this); + }, + + _onLoadEventFired: function(event) + { + this._mainResourceLoadTime = event.data || -1; + // Schedule refresh to update boundaries and draw the new line. + this._scheduleRefresh(); + }, + + _domContentLoadedEventFired: function(event) + { + this._mainResourceDOMContentTime = event.data || -1; + // Schedule refresh to update boundaries and draw the new line. + this._scheduleRefresh(); + }, + + wasShown: function() + { + this._refreshIfNeeded(); + }, + + willHide: function() + { + this._popoverHelper.hidePopover(); + }, + + refresh: function() + { + this._needsRefresh = false; + if (this._refreshTimeout) { + clearTimeout(this._refreshTimeout); + delete this._refreshTimeout; + } + + this._removeAllNodeHighlights(); + var wasScrolledToLastRow = this._dataGrid.isScrolledToLastRow(); + var boundariesChanged = false; + if (this.calculator.updateBoundariesForEventTime) { + boundariesChanged = this.calculator.updateBoundariesForEventTime(this._mainResourceLoadTime) || boundariesChanged; + boundariesChanged = this.calculator.updateBoundariesForEventTime(this._mainResourceDOMContentTime) || boundariesChanged; + } + + for (var resourceId in this._staleResources) { + var resource = this._staleResources[resourceId]; + var node = this._resourceGridNode(resource); + if (!node) { + // Create the timeline tree element and graph. + node = this._createResourceGridNode(resource); + this._dataGrid.appendChild(node); + } + node.refreshResource(); + + if (this.calculator.updateBoundaries(resource)) + boundariesChanged = true; + + if (!node.isFilteredOut()) + this._updateHighlightIfMatched(resource); + } + + if (boundariesChanged) { + // The boundaries changed, so all item graphs are stale. + this._invalidateAllItems(); + } + + for (var resourceId in this._staleResources) + this._resourceGridNode(this._staleResources[resourceId]).refreshGraph(this.calculator); + + this._staleResources = {}; + this._sortItems(); + this._updateSummaryBar(); + this._dataGrid.updateWidths(); + // FIXME: evaluate performance impact of moving this before a call to sortItems() + if (wasScrolledToLastRow) + this._dataGrid.scrollToLastRow(); + }, + + _onPreserveLogClicked: function(e) + { + this._preserveLogToggle.toggled = !this._preserveLogToggle.toggled; + }, + + _reset: function() + { + this.dispatchEventToListeners(WebInspector.NetworkLogView.EventTypes.ViewCleared); + + this._clearSearchMatchedList(); + if (this._popoverHelper) + this._popoverHelper.hidePopover(); + + if (this._calculator) + this._calculator.reset(); + + this._resources = []; + this._resourcesById = {}; + this._resourcesByURL = {}; + this._staleResources = {}; + this._resourceGridNodes = {}; + + if (this._dataGrid) { + this._dataGrid.removeChildren(); + this._updateDividersIfNeeded(true); + this._updateSummaryBar(); + } + + this._mainResourceLoadTime = -1; + this._mainResourceDOMContentTime = -1; + this._linkifier.reset(); + }, + + get resources() + { + return this._resources; + }, + + resourceById: function(id) + { + return this._resourcesById[id]; + }, + + _onResourceStarted: function(event) + { + this._appendResource(event.data); + }, + + _appendResource: function(resource) + { + this._resources.push(resource); + + // In case of redirect request id is reassigned to a redirected + // resource and we need to update _resourcesById ans search results. + if (this._resourcesById[resource.requestId]) { + var oldResource = resource.redirects[resource.redirects.length - 1]; + this._resourcesById[oldResource.requestId] = oldResource; + + this._updateSearchMatchedListAfterRequestIdChanged(resource.requestId, oldResource.requestId); + } + this._resourcesById[resource.requestId] = resource; + + this._resourcesByURL[resource.url] = resource; + + // Pull all the redirects of the main resource upon commit load. + if (resource.redirects) { + for (var i = 0; i < resource.redirects.length; ++i) + this._refreshResource(resource.redirects[i]); + } + + this._refreshResource(resource); + }, + + _onResourceUpdated: function(event) + { + this._refreshResource(event.data); + }, + + _refreshResource: function(resource) + { + this._staleResources[resource.requestId] = resource; + this._scheduleRefresh(); + }, + + clear: function() + { + if (this._preserveLogToggle.toggled) + return; + this._reset(); + }, + + _mainFrameNavigated: function(event) + { + if (this._preserveLogToggle.toggled) + return; + + var frame = /** @type {WebInspector.ResourceTreeFrame} */ event.data; + var loaderId = frame.loaderId; + + // Preserve provisional load resources. + var resourcesToPreserve = []; + for (var i = 0; i < this._resources.length; ++i) { + var resource = this._resources[i]; + if (resource.loaderId === loaderId) + resourcesToPreserve.push(resource); + } + + this._reset(); + + // Restore preserved items. + for (var i = 0; i < resourcesToPreserve.length; ++i) + this._appendResource(resourcesToPreserve[i]); + }, + + switchToDetailedView: function() + { + if (!this._dataGrid) + return; + if (this._dataGrid.selectedNode) + this._dataGrid.selectedNode.selected = false; + + this.element.removeStyleClass("brief-mode"); + + this._dataGrid.showColumn("method"); + this._dataGrid.showColumn("status"); + this._dataGrid.showColumn("type"); + if (Capabilities.nativeInstrumentationEnabled) + this._dataGrid.showColumn("initiator"); + this._dataGrid.showColumn("size"); + this._dataGrid.showColumn("time"); + this._dataGrid.showColumn("timeline"); + + var widths = {}; + widths.name = 20; + widths.method = 6; + widths.status = 6; + widths.type = 6; + if (Capabilities.nativeInstrumentationEnabled) + widths.initiator = 10; + widths.size = 6; + widths.time = 6; + if (Capabilities.nativeInstrumentationEnabled) + widths.timeline = 40; + else + widths.timeline = 50; + + this._dataGrid.applyColumnWidthsMap(widths); + }, + + switchToBriefView: function() + { + this.element.addStyleClass("brief-mode"); + this._removeAllNodeHighlights(); + + this._dataGrid.hideColumn("method"); + this._dataGrid.hideColumn("status"); + this._dataGrid.hideColumn("type"); + if (Capabilities.nativeInstrumentationEnabled) + this._dataGrid.hideColumn("initiator"); + this._dataGrid.hideColumn("size"); + this._dataGrid.hideColumn("time"); + this._dataGrid.hideColumn("timeline"); + + var widths = {}; + widths.name = 100; + this._dataGrid.applyColumnWidthsMap(widths); + + this._popoverHelper.hidePopover(); + }, + + _toggleLargerResources: function() + { + WebInspector.settings.resourcesLargeRows.set(!WebInspector.settings.resourcesLargeRows.get()); + this._setLargerResources(WebInspector.settings.resourcesLargeRows.get()); + }, + + _setLargerResources: function(enabled) + { + this._largerResourcesButton.toggled = enabled; + if (!enabled) { + this._largerResourcesButton.title = WebInspector.UIString("Use large resource rows."); + this._dataGrid.element.addStyleClass("small"); + this._timelineGrid.element.addStyleClass("small"); + } else { + this._largerResourcesButton.title = WebInspector.UIString("Use small resource rows."); + this._dataGrid.element.removeStyleClass("small"); + this._timelineGrid.element.removeStyleClass("small"); + } + this.dispatchEventToListeners(WebInspector.NetworkLogView.EventTypes.RowSizeChanged, { largeRows: enabled }); + this._updateOffscreenRows(); + }, + + _getPopoverAnchor: function(element) + { + if (!this._allowPopover) + return; + var anchor = element.enclosingNodeOrSelfWithClass("network-graph-bar") || element.enclosingNodeOrSelfWithClass("network-graph-label"); + if (!anchor) + return null; + var resource = anchor.parentElement.resource; + return resource && resource.timing ? anchor : null; + }, + + _showPopover: function(anchor, popover) + { + var resource = anchor.parentElement.resource; + var tableElement = WebInspector.ResourceTimingView.createTimingTable(resource); + popover.show(tableElement, anchor); + }, + + _contextMenu: function(event) + { + var contextMenu = new WebInspector.ContextMenu(); + var gridNode = this._dataGrid.dataGridNodeFromNode(event.target); + var resource = gridNode && gridNode._resource; + + if (resource) { + contextMenu.appendItem(WebInspector.openLinkExternallyLabel(), WebInspector.openResource.bind(WebInspector, resource.url, false)); + contextMenu.appendSeparator(); + contextMenu.appendItem(WebInspector.copyLinkAddressLabel(), this._copyLocation.bind(this, resource)); + if (resource.requestHeadersText) + contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Copy request headers" : "Copy Request Headers"), this._copyRequestHeaders.bind(this, resource)); + if (resource.responseHeadersText) + contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Copy response headers" : "Copy Response Headers"), this._copyResponseHeaders.bind(this, resource)); + contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Copy entry as HAR" : "Copy Entry as HAR"), this._copyResource.bind(this, resource)); + } + contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Copy all as HAR" : "Copy All as HAR"), this._copyAll.bind(this)); + + if (InspectorFrontendHost.canSaveAs()) { + contextMenu.appendSeparator(); + if (resource) + contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Save entry as HAR" : "Save Entry as HAR"), this._exportResource.bind(this, resource)); + contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Save all as HAR" : "Save All as HAR"), this._exportAll.bind(this)); + } + + if (this._canClearBrowserCache || this._canClearBrowserCookies) + contextMenu.appendSeparator(); + if (this._canClearBrowserCache) + contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Clear browser cache" : "Clear Browser Cache"), this._clearBrowserCache.bind(this)); + if (this._canClearBrowserCookies) + contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Clear browser cookies" : "Clear Browser Cookies"), this._clearBrowserCookies.bind(this)); + + contextMenu.show(event); + }, + + _copyAll: function() + { + var harArchive = { + log: (new WebInspector.HARLog(this._resources)).build() + }; + InspectorFrontendHost.copyText(JSON.stringify(harArchive, null, 2)); + }, + + _copyResource: function(resource) + { + var har = (new WebInspector.HAREntry(resource)).build(); + InspectorFrontendHost.copyText(JSON.stringify(har, null, 2)); + }, + + _copyLocation: function(resource) + { + InspectorFrontendHost.copyText(resource.url); + }, + + _copyRequestHeaders: function(resource) + { + InspectorFrontendHost.copyText(resource.requestHeadersText); + }, + + _copyResponseHeaders: function(resource) + { + InspectorFrontendHost.copyText(resource.responseHeadersText); + }, + + _exportAll: function() + { + var harArchive = { + log: (new WebInspector.HARLog(this._resources)).build() + }; + + InspectorFrontendHost.saveAs(WebInspector.inspectedPageDomain + ".har", JSON.stringify(harArchive, null, 2)); + }, + + _exportResource: function(resource) + { + var har = (new WebInspector.HAREntry(resource)).build(); + InspectorFrontendHost.saveAs(resource.displayName + ".har", JSON.stringify(har, null, 2)); + }, + + _clearBrowserCache: function(event) + { + if (confirm(WebInspector.UIString("Are you sure you want to clear browser cache?"))) + NetworkAgent.clearBrowserCache(); + }, + + _clearBrowserCookies: function(event) + { + if (confirm(WebInspector.UIString("Are you sure you want to clear browser cookies?"))) + NetworkAgent.clearBrowserCookies(); + }, + + _updateOffscreenRows: function() + { + var dataTableBody = this._dataGrid.dataTableBody; + var rows = dataTableBody.children; + var recordsCount = rows.length; + if (recordsCount < 2) + return; // Filler row only. + + var visibleTop = this._dataGrid.scrollContainer.scrollTop; + var visibleBottom = visibleTop + this._dataGrid.scrollContainer.offsetHeight; + + var rowHeight = 0; + + // Filler is at recordsCount - 1. + var unfilteredRowIndex = 0; + for (var i = 0; i < recordsCount - 1; ++i) { + var row = rows[i]; + + var dataGridNode = this._dataGrid.dataGridNodeFromNode(row); + if (dataGridNode.isFilteredOut()) { + row.removeStyleClass("offscreen"); + continue; + } + + if (!rowHeight) + rowHeight = row.offsetHeight; + + var rowIsVisible = unfilteredRowIndex * rowHeight < visibleBottom && (unfilteredRowIndex + 1) * rowHeight > visibleTop; + if (rowIsVisible !== row.rowIsVisible) { + if (rowIsVisible) + row.removeStyleClass("offscreen"); + else + row.addStyleClass("offscreen"); + row.rowIsVisible = rowIsVisible; + } + unfilteredRowIndex++; + } + }, + + _matchResource: function(resource) + { + if (!this._searchRegExp) + return -1; + + if ((!resource.displayName || !resource.displayName.match(this._searchRegExp)) && !resource.folder.match(this._searchRegExp)) + return -1; + + if (resource.requestId in this._matchedResourcesMap) + return this._matchedResourcesMap[resource.requestId]; + + var matchedResourceIndex = this._matchedResources.length; + this._matchedResourcesMap[resource.requestId] = matchedResourceIndex; + this._matchedResources.push(resource.requestId); + + return matchedResourceIndex; + }, + + _clearSearchMatchedList: function() + { + this._matchedResources = []; + this._matchedResourcesMap = {}; + this._highlightNthMatchedResource(-1, false); + }, + + _updateSearchMatchedListAfterRequestIdChanged: function(oldRequestId, newRequestId) + { + var resourceIndex = this._matchedResourcesMap[oldRequestId]; + if (resourceIndex) { + delete this._matchedResourcesMap[oldRequestId]; + this._matchedResourcesMap[newRequestId] = resourceIndex; + this._matchedResources[resourceIndex] = newRequestId; + } + }, + + _updateHighlightIfMatched: function(resource) + { + var matchedResourceIndex = this._matchResource(resource); + if (matchedResourceIndex === -1) + return; + + this.dispatchEventToListeners(WebInspector.NetworkLogView.EventTypes.SearchCountUpdated, this._matchedResources.length); + + if (this._currentMatchedResourceIndex !== -1 && this._currentMatchedResourceIndex !== matchedResourceIndex) + return; + + this._highlightNthMatchedResource(matchedResourceIndex, false); + }, + + _highlightNthMatchedResource: function(matchedResourceIndex, reveal) + { + if (this._highlightedSubstringChanges) { + revertDomChanges(this._highlightedSubstringChanges); + this._highlightedSubstringChanges = null; + } + + if (matchedResourceIndex === -1) { + this._currentMatchedResourceIndex = matchedResourceIndex; + return; + } + + var resource = this._resourcesById[this._matchedResources[matchedResourceIndex]]; + if (!resource) + return; + + var nameMatched = resource.displayName && resource.displayName.match(this._searchRegExp); + var pathMatched = resource.path && resource.folder.match(this._searchRegExp); + if (!nameMatched && pathMatched && !this._largerResourcesButton.toggled) + this._toggleLargerResources(); + + var node = this._resourceGridNode(resource); + if (node) { + this._highlightedSubstringChanges = node._highlightMatchedSubstring(this._searchRegExp); + if (reveal) + node.reveal(); + this._currentMatchedResourceIndex = matchedResourceIndex; + } + this.dispatchEventToListeners(WebInspector.NetworkLogView.EventTypes.SearchIndexUpdated, this._currentMatchedResourceIndex); + }, + + performSearch: function(searchQuery, sortOrFilterApplied) + { + var newMatchedResourceIndex = 0; + var currentMatchedRequestId; + if (this._currentMatchedResourceIndex !== -1) + currentMatchedRequestId = this._matchedResources[this._currentMatchedResourceIndex]; + + if (!sortOrFilterApplied) + this._searchRegExp = createPlainTextSearchRegex(searchQuery, "i"); + + this._clearSearchMatchedList(); + + var childNodes = this._dataGrid.dataTableBody.childNodes; + var resourceNodes = Array.prototype.slice.call(childNodes, 0, childNodes.length - 1); // drop the filler row. + + for (var i = 0; i < resourceNodes.length; ++i) { + var dataGridNode = this._dataGrid.dataGridNodeFromNode(resourceNodes[i]); + if (dataGridNode.isFilteredOut()) + continue; + + if (this._matchResource(dataGridNode._resource) !== -1 && dataGridNode._resource.requestId === currentMatchedRequestId) + newMatchedResourceIndex = this._matchedResources.length - 1; + } + + this.dispatchEventToListeners(WebInspector.NetworkLogView.EventTypes.SearchCountUpdated, this._matchedResources.length); + this._highlightNthMatchedResource(newMatchedResourceIndex, !sortOrFilterApplied); + }, + + jumpToPreviousSearchResult: function() + { + if (!this._matchedResources.length) + return; + this._highlightNthMatchedResource((this._currentMatchedResourceIndex + this._matchedResources.length - 1) % this._matchedResources.length, true); + }, + + jumpToNextSearchResult: function() + { + if (!this._matchedResources.length) + return; + this._highlightNthMatchedResource((this._currentMatchedResourceIndex + 1) % this._matchedResources.length, true); + }, + + searchCanceled: function() + { + this._clearSearchMatchedList(); + this.dispatchEventToListeners(WebInspector.NetworkLogView.EventTypes.SearchCountUpdated, 0); + }, + + revealAndHighlightResource: function(resource) + { + this._removeAllNodeHighlights(); + + var node = this._resourceGridNode(resource); + if (node) { + this._dataGrid.element.focus(); + node.reveal(); + this._highlightNode(node); + } + }, + + _removeAllNodeHighlights: function() + { + if (this._highlightedNode) { + this._highlightedNode.element.removeStyleClass("highlighted-row"); + delete this._highlightedNode; + } + }, + + _highlightNode: function(node) + { + node.element.addStyleClass("highlighted-row"); + this._highlightedNode = node; + } +}; + +WebInspector.NetworkLogView.prototype.__proto__ = WebInspector.View.prototype; + +WebInspector.NetworkLogView.EventTypes = { + ViewCleared: "ViewCleared", + RowSizeChanged: "RowSizeChanged", + ResourceSelected: "ResourceSelected", + SearchCountUpdated: "SearchCountUpdated", + SearchIndexUpdated: "SearchIndexUpdated" +}; + +/** + * @constructor + * @extends {WebInspector.Panel} + */ +WebInspector.NetworkPanel = function() +{ + WebInspector.Panel.call(this, "network"); + this.registerRequiredCSS("networkPanel.css"); + + this.createSplitView(); + this.splitView.hideMainElement(); + + this._networkLogView = new WebInspector.NetworkLogView(); + this._networkLogView.show(this.sidebarElement); + + this._viewsContainerElement = this.splitView.mainElement; + this._viewsContainerElement.id = "network-views"; + this._viewsContainerElement.addStyleClass("hidden"); + if (!this._networkLogView.useLargeRows) + this._viewsContainerElement.addStyleClass("small"); + + this._networkLogView.addEventListener(WebInspector.NetworkLogView.EventTypes.ViewCleared, this._onViewCleared, this); + this._networkLogView.addEventListener(WebInspector.NetworkLogView.EventTypes.RowSizeChanged, this._onRowSizeChanged, this); + this._networkLogView.addEventListener(WebInspector.NetworkLogView.EventTypes.ResourceSelected, this._onResourceSelected, this); + this._networkLogView.addEventListener(WebInspector.NetworkLogView.EventTypes.SearchCountUpdated, this._onSearchCountUpdated, this); + this._networkLogView.addEventListener(WebInspector.NetworkLogView.EventTypes.SearchIndexUpdated, this._onSearchIndexUpdated, this); + + this._closeButtonElement = document.createElement("button"); + this._closeButtonElement.id = "network-close-button"; + this._closeButtonElement.addEventListener("click", this._toggleGridMode.bind(this), false); + this._viewsContainerElement.appendChild(this._closeButtonElement); + + function viewGetter() + { + return this.visibleView; + } + WebInspector.GoToLineDialog.install(this, viewGetter.bind(this)); +} + +WebInspector.NetworkPanel.prototype = { + get toolbarItemLabel() + { + return WebInspector.UIString("Network"); + }, + + get statusBarItems() + { + return this._networkLogView.statusBarItems; + }, + + elementsToRestoreScrollPositionsFor: function() + { + return this._networkLogView.elementsToRestoreScrollPositionsFor(); + }, + + // FIXME: only used by the layout tests, should not be exposed. + _reset: function() + { + this._networkLogView._reset(); + }, + + handleShortcut: function(event) + { + if (this._viewingResourceMode && event.keyCode === WebInspector.KeyboardShortcut.Keys.Esc.code) { + this._toggleGridMode(); + event.handled = true; + return; + } + + WebInspector.Panel.prototype.handleShortcut.call(this, event); + }, + + wasShown: function() + { + WebInspector.Panel.prototype.wasShown.call(this); + }, + + get resources() + { + return this._networkLogView.resources; + }, + + resourceById: function(id) + { + return this._networkLogView.resourceById(id); + }, + + _resourceByAnchor: function(anchor) + { + return anchor.requestId ? this.resourceById(anchor.requestId) : this._networkLogView._resourcesByURL[anchor.href]; + }, + + canShowAnchorLocation: function(anchor) + { + return !!this._resourceByAnchor(anchor); + }, + + showAnchorLocation: function(anchor) + { + var resource = this._resourceByAnchor(anchor); + this.revealAndHighlightResource(resource) + }, + + revealAndHighlightResource: function(resource) + { + this._toggleGridMode(); + if (resource) + this._networkLogView.revealAndHighlightResource(resource); + }, + + _onViewCleared: function(event) + { + this._closeVisibleResource(); + this._toggleGridMode(); + this._viewsContainerElement.removeChildren(); + this._viewsContainerElement.appendChild(this._closeButtonElement); + }, + + _onRowSizeChanged: function(event) + { + if (event.data.largeRows) + this._viewsContainerElement.removeStyleClass("small"); + else + this._viewsContainerElement.addStyleClass("small"); + }, + + _onSearchCountUpdated: function(event) + { + WebInspector.searchController.updateSearchMatchesCount(event.data, this); + }, + + _onSearchIndexUpdated: function(event) + { + WebInspector.searchController.updateCurrentMatchIndex(event.data, this); + }, + + _onResourceSelected: function(event) + { + this._showResource(event.data); + }, + + _showResource: function(resource) + { + if (!resource) + return; + + this._toggleViewingResourceMode(); + + if (this.visibleView) { + this.visibleView.detach(); + delete this.visibleView; + } + + var view = new WebInspector.NetworkItemView(resource); + view.show(this._viewsContainerElement); + this.visibleView = view; + }, + + _closeVisibleResource: function() + { + this.element.removeStyleClass("viewing-resource"); + + if (this.visibleView) { + this.visibleView.detach(); + delete this.visibleView; + } + }, + + _toggleGridMode: function() + { + if (this._viewingResourceMode) { + this._viewingResourceMode = false; + this.element.removeStyleClass("viewing-resource"); + this.splitView.hideMainElement(); + } + + this._networkLogView.switchToDetailedView(); + this._networkLogView.allowPopover = true; + this._networkLogView.allowResourceSelection = false; + }, + + _toggleViewingResourceMode: function() + { + if (this._viewingResourceMode) + return; + this._viewingResourceMode = true; + + this.element.addStyleClass("viewing-resource"); + this.splitView.showMainElement(); + this._networkLogView.allowPopover = false; + this._networkLogView.allowResourceSelection = true; + this._networkLogView.switchToBriefView(); + }, + + performSearch: function(searchQuery, sortOrFilterApplied) + { + this._networkLogView.performSearch(searchQuery, sortOrFilterApplied); + }, + + jumpToPreviousSearchResult: function() + { + this._networkLogView.jumpToPreviousSearchResult(); + }, + + jumpToNextSearchResult: function() + { + this._networkLogView.jumpToNextSearchResult(); + }, + + searchCanceled: function() + { + this._networkLogView.searchCanceled(); + } +} + +WebInspector.NetworkPanel.prototype.__proto__ = WebInspector.Panel.prototype; + +/** + * @constructor + */ +WebInspector.NetworkBaseCalculator = function() +{ +} + +WebInspector.NetworkBaseCalculator.prototype = { + computeBarGraphPercentages: function(item) + { + return {start: 0, middle: 0, end: (this._value(item) / this.boundarySpan) * 100}; + }, + + computeBarGraphLabels: function(item) + { + const label = this.formatValue(this._value(item)); + return {left: label, right: label, tooltip: label}; + }, + + get boundarySpan() + { + return this.maximumBoundary - this.minimumBoundary; + }, + + updateBoundaries: function(item) + { + this.minimumBoundary = 0; + + var value = this._value(item); + if (typeof this.maximumBoundary === "undefined" || value > this.maximumBoundary) { + this.maximumBoundary = value; + return true; + } + return false; + }, + + reset: function() + { + delete this.minimumBoundary; + delete this.maximumBoundary; + }, + + _value: function(item) + { + return 0; + }, + + formatValue: function(value) + { + return value.toString(); + } +} + +/** + * @constructor + * @extends {WebInspector.NetworkBaseCalculator} + */ +WebInspector.NetworkTimeCalculator = function(startAtZero) +{ + WebInspector.NetworkBaseCalculator.call(this); + this.startAtZero = startAtZero; +} + +WebInspector.NetworkTimeCalculator.prototype = { + computeBarGraphPercentages: function(resource) + { + if (resource.startTime !== -1) + var start = ((resource.startTime - this.minimumBoundary) / this.boundarySpan) * 100; + else + var start = 0; + + if (resource.responseReceivedTime !== -1) + var middle = ((resource.responseReceivedTime - this.minimumBoundary) / this.boundarySpan) * 100; + else + var middle = (this.startAtZero ? start : 100); + + if (resource.endTime !== -1) + var end = ((resource.endTime - this.minimumBoundary) / this.boundarySpan) * 100; + else + var end = (this.startAtZero ? middle : 100); + + if (this.startAtZero) { + end -= start; + middle -= start; + start = 0; + } + + return {start: start, middle: middle, end: end}; + }, + + computePercentageFromEventTime: function(eventTime) + { + // This function computes a percentage in terms of the total loading time + // of a specific event. If startAtZero is set, then this is useless, and we + // want to return 0. + if (eventTime !== -1 && !this.startAtZero) + return ((eventTime - this.minimumBoundary) / this.boundarySpan) * 100; + + return 0; + }, + + updateBoundariesForEventTime: function(eventTime) + { + if (eventTime === -1 || this.startAtZero) + return false; + + if (typeof this.maximumBoundary === "undefined" || eventTime > this.maximumBoundary) { + this.maximumBoundary = eventTime; + return true; + } + return false; + }, + + computeBarGraphLabels: function(resource) + { + var rightLabel = ""; + if (resource.responseReceivedTime !== -1 && resource.endTime !== -1) + rightLabel = this.formatValue(resource.endTime - resource.responseReceivedTime); + + var hasLatency = resource.latency > 0; + if (hasLatency) + var leftLabel = this.formatValue(resource.latency); + else + var leftLabel = rightLabel; + + if (resource.timing) + return {left: leftLabel, right: rightLabel}; + + if (hasLatency && rightLabel) { + var total = this.formatValue(resource.duration); + var tooltip = WebInspector.UIString("%s latency, %s download (%s total)", leftLabel, rightLabel, total); + } else if (hasLatency) + var tooltip = WebInspector.UIString("%s latency", leftLabel); + else if (rightLabel) + var tooltip = WebInspector.UIString("%s download", rightLabel); + + if (resource.cached) + tooltip = WebInspector.UIString("%s (from cache)", tooltip); + return {left: leftLabel, right: rightLabel, tooltip: tooltip}; + }, + + updateBoundaries: function(resource) + { + var didChange = false; + + var lowerBound; + if (this.startAtZero) + lowerBound = 0; + else + lowerBound = this._lowerBound(resource); + + if (lowerBound !== -1 && (typeof this.minimumBoundary === "undefined" || lowerBound < this.minimumBoundary)) { + this.minimumBoundary = lowerBound; + didChange = true; + } + + var upperBound = this._upperBound(resource); + if (upperBound !== -1 && (typeof this.maximumBoundary === "undefined" || upperBound > this.maximumBoundary)) { + this.maximumBoundary = upperBound; + didChange = true; + } + + return didChange; + }, + + formatValue: function(value) + { + return Number.secondsToString(value); + }, + + _lowerBound: function(resource) + { + return 0; + }, + + _upperBound: function(resource) + { + return 0; + } +} + +WebInspector.NetworkTimeCalculator.prototype.__proto__ = WebInspector.NetworkBaseCalculator.prototype; + +/** + * @constructor + * @extends {WebInspector.NetworkTimeCalculator} + */ +WebInspector.NetworkTransferTimeCalculator = function() +{ + WebInspector.NetworkTimeCalculator.call(this, false); +} + +WebInspector.NetworkTransferTimeCalculator.prototype = { + formatValue: function(value) + { + return Number.secondsToString(value); + }, + + _lowerBound: function(resource) + { + return resource.startTime; + }, + + _upperBound: function(resource) + { + return resource.endTime; + } +} + +WebInspector.NetworkTransferTimeCalculator.prototype.__proto__ = WebInspector.NetworkTimeCalculator.prototype; + +/** + * @constructor + * @extends {WebInspector.NetworkTimeCalculator} + */ +WebInspector.NetworkTransferDurationCalculator = function() +{ + WebInspector.NetworkTimeCalculator.call(this, true); +} + +WebInspector.NetworkTransferDurationCalculator.prototype = { + formatValue: function(value) + { + return Number.secondsToString(value); + }, + + _upperBound: function(resource) + { + return resource.duration; + } +} + +WebInspector.NetworkTransferDurationCalculator.prototype.__proto__ = WebInspector.NetworkTimeCalculator.prototype; + +/** + * @constructor + * @extends {WebInspector.DataGridNode} + */ +WebInspector.NetworkDataGridNode = function(parentView, resource) +{ + WebInspector.DataGridNode.call(this, {}); + this._parentView = parentView; + this._resource = resource; +} + +WebInspector.NetworkDataGridNode.prototype = { + createCells: function() + { + // Out of sight, out of mind: create nodes offscreen to save on render tree update times when running updateOffscreenRows() + this._element.addStyleClass("offscreen"); + this._nameCell = this._createDivInTD("name"); + this._methodCell = this._createDivInTD("method"); + this._statusCell = this._createDivInTD("status"); + this._typeCell = this._createDivInTD("type"); + if (Capabilities.nativeInstrumentationEnabled) + this._initiatorCell = this._createDivInTD("initiator"); + this._sizeCell = this._createDivInTD("size"); + this._timeCell = this._createDivInTD("time"); + this._createTimelineCell(); + this._nameCell.addEventListener("click", this.select.bind(this), false); + this._nameCell.addEventListener("dblclick", this._openInNewTab.bind(this), false); + }, + + isFilteredOut: function() + { + if (!this._parentView._hiddenCategories.all) + return false; + return this._resource.category.name in this._parentView._hiddenCategories; + }, + + select: function() + { + this._parentView.dispatchEventToListeners(WebInspector.NetworkLogView.EventTypes.ResourceSelected, this._resource); + WebInspector.DataGridNode.prototype.select.apply(this, arguments); + }, + + _highlightMatchedSubstring: function(regexp) + { + var domChanges = []; + var matchInfo = this._nameCell.textContent.match(regexp); + highlightSearchResult(this._nameCell, matchInfo.index, matchInfo[0].length, domChanges); + return domChanges; + }, + + _openInNewTab: function() + { + InspectorFrontendHost.openInNewTab(this._resource.url); + }, + + get selectable() + { + return this._parentView.allowResourceSelection && !this.isFilteredOut(); + }, + + _createDivInTD: function(columnIdentifier) + { + var td = document.createElement("td"); + td.className = columnIdentifier + "-column"; + var div = document.createElement("div"); + td.appendChild(div); + this._element.appendChild(td); + return div; + }, + + _createTimelineCell: function() + { + this._graphElement = document.createElement("div"); + this._graphElement.className = "network-graph-side"; + + this._barAreaElement = document.createElement("div"); + // this._barAreaElement.className = "network-graph-bar-area hidden"; + this._barAreaElement.className = "network-graph-bar-area"; + this._barAreaElement.resource = this._resource; + this._graphElement.appendChild(this._barAreaElement); + + this._barLeftElement = document.createElement("div"); + this._barLeftElement.className = "network-graph-bar waiting"; + this._barAreaElement.appendChild(this._barLeftElement); + + this._barRightElement = document.createElement("div"); + this._barRightElement.className = "network-graph-bar"; + this._barAreaElement.appendChild(this._barRightElement); + + + this._labelLeftElement = document.createElement("div"); + this._labelLeftElement.className = "network-graph-label waiting"; + this._barAreaElement.appendChild(this._labelLeftElement); + + this._labelRightElement = document.createElement("div"); + this._labelRightElement.className = "network-graph-label"; + this._barAreaElement.appendChild(this._labelRightElement); + + this._graphElement.addEventListener("mouseover", this._refreshLabelPositions.bind(this), false); + + this._timelineCell = document.createElement("td"); + this._timelineCell.className = "timeline-column"; + this._element.appendChild(this._timelineCell); + this._timelineCell.appendChild(this._graphElement); + }, + + refreshResource: function() + { + this._refreshNameCell(); + + this._methodCell.setTextAndTitle(this._resource.requestMethod); + + this._refreshStatusCell(); + this._refreshTypeCell(); + if (Capabilities.nativeInstrumentationEnabled) + this._refreshInitiatorCell(); + this._refreshSizeCell(); + this._refreshTimeCell(); + + if (this._resource.cached) + this._graphElement.addStyleClass("resource-cached"); + + this._element.addStyleClass("network-item"); + if (!this._element.hasStyleClass("network-category-" + this._resource.category.name)) { + this._element.removeMatchingStyleClasses("network-category-\\w+"); + this._element.addStyleClass("network-category-" + this._resource.category.name); + } + }, + + _refreshNameCell: function() + { + this._nameCell.removeChildren(); + + if (this._resource.category === WebInspector.resourceCategories.images) { + var previewImage = document.createElement("img"); + previewImage.className = "image-network-icon-preview"; + this._resource.populateImageSource(previewImage); + + var iconElement = document.createElement("div"); + iconElement.className = "icon"; + iconElement.appendChild(previewImage); + } else { + var iconElement = document.createElement("img"); + iconElement.className = "icon"; + } + this._nameCell.appendChild(iconElement); + this._nameCell.appendChild(document.createTextNode(this._fileName())); + + + var subtitle = this._resource.displayDomain; + + if (this._resource.path) + subtitle += this._resource.folder; + + this._appendSubtitle(this._nameCell, subtitle); + this._nameCell.title = this._resource.url; + }, + + _fileName: function() + { + var fileName = this._resource.displayName; + if (this._resource.queryString) + fileName += "?" + this._resource.queryString; + return fileName; + }, + + _refreshStatusCell: function() + { + this._statusCell.removeChildren(); + + if (this._resource.failed) { + if (this._resource.canceled) + this._statusCell.setTextAndTitle(WebInspector.UIString("(canceled)")); + else + this._statusCell.setTextAndTitle(WebInspector.UIString("(failed)")); + this._statusCell.addStyleClass("network-dim-cell"); + this.element.addStyleClass("network-error-row"); + return; + } + + this._statusCell.removeStyleClass("network-dim-cell"); + this.element.removeStyleClass("network-error-row"); + + if (this._resource.statusCode) { + this._statusCell.appendChild(document.createTextNode(this._resource.statusCode)); + this._appendSubtitle(this._statusCell, this._resource.statusText); + this._statusCell.title = this._resource.statusCode + " " + this._resource.statusText; + if (this._resource.statusCode >= 400) + this.element.addStyleClass("network-error-row"); + if (this._resource.cached) + this._statusCell.addStyleClass("network-dim-cell"); + } else { + if (!this._resource.isHttpFamily() && this._resource.finished) + this._statusCell.setTextAndTitle(WebInspector.UIString("Success")); + else if (this._resource.isPingRequest()) + this._statusCell.setTextAndTitle(WebInspector.UIString("(ping)")); + else + this._statusCell.setTextAndTitle(WebInspector.UIString("(pending)")); + this._statusCell.addStyleClass("network-dim-cell"); + } + }, + + _refreshTypeCell: function() + { + if (this._resource.mimeType) { + this._typeCell.removeStyleClass("network-dim-cell"); + this._typeCell.setTextAndTitle(this._resource.mimeType); + } else if (this._resource.isPingRequest) { + this._typeCell.removeStyleClass("network-dim-cell"); + this._typeCell.setTextAndTitle(this._resource.requestContentType()); + } else { + this._typeCell.addStyleClass("network-dim-cell"); + this._typeCell.setTextAndTitle(WebInspector.UIString("Pending")); + } + }, + + _refreshInitiatorCell: function() + { + var initiator = this._resource.initiator; + if ((initiator && initiator.type !== "other") || this._resource.redirectSource) { + this._initiatorCell.removeStyleClass("network-dim-cell"); + this._initiatorCell.removeChildren(); + if (this._resource.redirectSource) { + var redirectSource = this._resource.redirectSource; + this._initiatorCell.title = redirectSource.url; + this._initiatorCell.appendChild(WebInspector.linkifyRequestAsNode(redirectSource)); + this._appendSubtitle(this._initiatorCell, WebInspector.UIString("Redirect")); + } else if (initiator.type === "script") { + var topFrame = initiator.stackTrace[0]; + // This could happen when resource loading was triggered by console. + if (!topFrame.url) { + this._initiatorCell.addStyleClass("network-dim-cell"); + this._initiatorCell.setTextAndTitle(WebInspector.UIString("Other")); + return; + } + this._initiatorCell.title = topFrame.url + ":" + topFrame.lineNumber; + var urlElement = this._parentView._linkifier.linkifyLocation(topFrame.url, topFrame.lineNumber - 1, 0); + this._initiatorCell.appendChild(urlElement); + this._appendSubtitle(this._initiatorCell, WebInspector.UIString("Script")); + } else { // initiator.type === "parser" + this._initiatorCell.title = initiator.url + ":" + initiator.lineNumber; + this._initiatorCell.appendChild(WebInspector.linkifyResourceAsNode(initiator.url, initiator.lineNumber - 1)); + this._appendSubtitle(this._initiatorCell, WebInspector.UIString("Parser")); + } + } else { + this._initiatorCell.addStyleClass("network-dim-cell"); + this._initiatorCell.setTextAndTitle(WebInspector.UIString("Other")); + } + }, + + _refreshSizeCell: function() + { + if (this._resource.cached) { + this._sizeCell.setTextAndTitle(WebInspector.UIString("(from cache)")); + this._sizeCell.addStyleClass("network-dim-cell"); + } else { + var resourceSize = typeof this._resource.resourceSize === "number" ? Number.bytesToString(this._resource.resourceSize) : "?"; + var transferSize = typeof this._resource.transferSize === "number" ? Number.bytesToString(this._resource.transferSize) : "?"; + this._sizeCell.setTextAndTitle(transferSize); + this._sizeCell.removeStyleClass("network-dim-cell"); + this._appendSubtitle(this._sizeCell, resourceSize); + } + }, + + _refreshTimeCell: function() + { + if (this._resource.duration > 0) { + this._timeCell.removeStyleClass("network-dim-cell"); + this._timeCell.setTextAndTitle(Number.secondsToString(this._resource.duration)); + this._appendSubtitle(this._timeCell, Number.secondsToString(this._resource.latency)); + } else { + this._timeCell.addStyleClass("network-dim-cell"); + this._timeCell.setTextAndTitle(WebInspector.UIString("Pending")); + } + }, + + _appendSubtitle: function(cellElement, subtitleText) + { + var subtitleElement = document.createElement("div"); + subtitleElement.className = "network-cell-subtitle"; + subtitleElement.textContent = subtitleText; + cellElement.appendChild(subtitleElement); + }, + + refreshGraph: function(calculator) + { + var percentages = calculator.computeBarGraphPercentages(this._resource); + this._percentages = percentages; + + this._barAreaElement.removeStyleClass("hidden"); + + if (!this._graphElement.hasStyleClass("network-category-" + this._resource.category.name)) { + this._graphElement.removeMatchingStyleClasses("network-category-\\w+"); + this._graphElement.addStyleClass("network-category-" + this._resource.category.name); + } + + this._barLeftElement.style.setProperty("left", percentages.start + "%"); + this._barRightElement.style.setProperty("right", (100 - percentages.end) + "%"); + + this._barLeftElement.style.setProperty("right", (100 - percentages.end) + "%"); + this._barRightElement.style.setProperty("left", percentages.middle + "%"); + + var labels = calculator.computeBarGraphLabels(this._resource); + this._labelLeftElement.textContent = labels.left; + this._labelRightElement.textContent = labels.right; + + var tooltip = (labels.tooltip || ""); + this._barLeftElement.title = tooltip; + this._labelLeftElement.title = tooltip; + this._labelRightElement.title = tooltip; + this._barRightElement.title = tooltip; + }, + + _refreshLabelPositions: function() + { + if (!this._percentages) + return; + this._labelLeftElement.style.removeProperty("left"); + this._labelLeftElement.style.removeProperty("right"); + this._labelLeftElement.removeStyleClass("before"); + this._labelLeftElement.removeStyleClass("hidden"); + + this._labelRightElement.style.removeProperty("left"); + this._labelRightElement.style.removeProperty("right"); + this._labelRightElement.removeStyleClass("after"); + this._labelRightElement.removeStyleClass("hidden"); + + const labelPadding = 10; + const barRightElementOffsetWidth = this._barRightElement.offsetWidth; + const barLeftElementOffsetWidth = this._barLeftElement.offsetWidth; + + if (this._barLeftElement) { + var leftBarWidth = barLeftElementOffsetWidth - labelPadding; + var rightBarWidth = (barRightElementOffsetWidth - barLeftElementOffsetWidth) - labelPadding; + } else { + var leftBarWidth = (barLeftElementOffsetWidth - barRightElementOffsetWidth) - labelPadding; + var rightBarWidth = barRightElementOffsetWidth - labelPadding; + } + + const labelLeftElementOffsetWidth = this._labelLeftElement.offsetWidth; + const labelRightElementOffsetWidth = this._labelRightElement.offsetWidth; + + const labelBefore = (labelLeftElementOffsetWidth > leftBarWidth); + const labelAfter = (labelRightElementOffsetWidth > rightBarWidth); + const graphElementOffsetWidth = this._graphElement.offsetWidth; + + if (labelBefore && (graphElementOffsetWidth * (this._percentages.start / 100)) < (labelLeftElementOffsetWidth + 10)) + var leftHidden = true; + + if (labelAfter && (graphElementOffsetWidth * ((100 - this._percentages.end) / 100)) < (labelRightElementOffsetWidth + 10)) + var rightHidden = true; + + if (barLeftElementOffsetWidth == barRightElementOffsetWidth) { + // The left/right label data are the same, so a before/after label can be replaced by an on-bar label. + if (labelBefore && !labelAfter) + leftHidden = true; + else if (labelAfter && !labelBefore) + rightHidden = true; + } + + if (labelBefore) { + if (leftHidden) + this._labelLeftElement.addStyleClass("hidden"); + this._labelLeftElement.style.setProperty("right", (100 - this._percentages.start) + "%"); + this._labelLeftElement.addStyleClass("before"); + } else { + this._labelLeftElement.style.setProperty("left", this._percentages.start + "%"); + this._labelLeftElement.style.setProperty("right", (100 - this._percentages.middle) + "%"); + } + + if (labelAfter) { + if (rightHidden) + this._labelRightElement.addStyleClass("hidden"); + this._labelRightElement.style.setProperty("left", this._percentages.end + "%"); + this._labelRightElement.addStyleClass("after"); + } else { + this._labelRightElement.style.setProperty("left", this._percentages.middle + "%"); + this._labelRightElement.style.setProperty("right", (100 - this._percentages.end) + "%"); + } + } +} + +WebInspector.NetworkDataGridNode.NameComparator = function(a, b) +{ + var aFileName = a._resource.displayName + (a._resource.queryString ? a._resource.queryString : ""); + var bFileName = b._resource.displayName + (b._resource.queryString ? b._resource.queryString : ""); + if (aFileName > bFileName) + return 1; + if (bFileName > aFileName) + return -1; + return 0; +} + +WebInspector.NetworkDataGridNode.SizeComparator = function(a, b) +{ + if (b._resource.cached && !a._resource.cached) + return 1; + if (a._resource.cached && !b._resource.cached) + return -1; + + if (a._resource.resourceSize === b._resource.resourceSize) + return 0; + + return a._resource.resourceSize - b._resource.resourceSize; +} + +WebInspector.NetworkDataGridNode.InitiatorComparator = function(a, b) +{ + if (!a._resource.initiator || a._resource.initiator.type === "Other") + return -1; + if (!b._resource.initiator || b._resource.initiator.type === "Other") + return 1; + + if (a._resource.initiator.url < b._resource.initiator.url) + return -1; + if (a._resource.initiator.url > b._resource.initiator.url) + return 1; + + return a._resource.initiator.lineNumber - b._resource.initiator.lineNumber; +} + +WebInspector.NetworkDataGridNode.ResourcePropertyComparator = function(propertyName, revert, a, b) +{ + var aValue = a._resource[propertyName]; + var bValue = b._resource[propertyName]; + if (aValue > bValue) + return revert ? -1 : 1; + if (bValue > aValue) + return revert ? 1 : -1; + return 0; +} + +WebInspector.NetworkDataGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype; +/* InjectedFakeWorker.js */ + +/* + * 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. + * * 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. + */ + +var InjectedFakeWorker = function(InjectedScriptHost, inspectedWindow, injectedScriptId) +{ + +Worker = function(url) +{ + var impl = new FakeWorker(this, url); + if (impl === null) + return null; + + this.isFake = true; + this.postMessage = bind(impl.postMessage, impl); + this.terminate = bind(impl.terminate, impl); + + function onmessageGetter() + { + return impl.channel.port1.onmessage; + } + function onmessageSetter(callback) + { + impl.channel.port1.onmessage = callback; + } + this.__defineGetter__("onmessage", onmessageGetter); + this.__defineSetter__("onmessage", onmessageSetter); + this.addEventListener = bind(impl.channel.port1.addEventListener, impl.channel.port1); + this.removeEventListener = bind(impl.channel.port1.removeEventListener, impl.channel.port1); + this.dispatchEvent = bind(impl.channel.port1.dispatchEvent, impl.channel.port1); +} + +function FakeWorker(worker, url) +{ + var scriptURL = this._expandURLAndCheckOrigin(document.baseURI, location.href, url); + + this._worker = worker; + this._id = InjectedScriptHost.nextWorkerId(); + this.channel = new MessageChannel(); + this._listeners = []; + this._buildWorker(scriptURL); + + InjectedScriptHost.didCreateWorker(this._id, scriptURL.url, false); +} + +FakeWorker.prototype = { + postMessage: function(msg, opt_ports) + { + if (this._frame != null) + this.channel.port1.postMessage.apply(this.channel.port1, arguments); + else if (this._pendingMessages) + this._pendingMessages.push(arguments) + else + this._pendingMessages = [ arguments ]; + }, + + terminate: function() + { + InjectedScriptHost.didDestroyWorker(this._id); + + this.channel.port1.close(); + this.channel.port2.close(); + if (this._frame != null) + this._frame.frameElement.parentNode.removeChild(this._frame.frameElement); + this._frame = null; + this._worker = null; // Break reference loop. + }, + + _buildWorker: function(url) + { + var code = this._loadScript(url.url); + var iframeElement = document.createElement("iframe"); + iframeElement.style.display = "none"; + + this._document = document; + iframeElement.onload = bind(this._onWorkerFrameLoaded, this, iframeElement, url, code); + + if (document.body) + this._attachWorkerFrameToDocument(iframeElement, url, code); + else + window.addEventListener("load", bind(this._attachWorkerFrameToDocument, this, iframeElement), false); + }, + + _attachWorkerFrameToDocument: function(iframeElement) + { + document.body.appendChild(iframeElement); + }, + + _onWorkerFrameLoaded: function(iframeElement, url, code) + { + var frame = iframeElement.contentWindow; + this._frame = frame; + this._setupWorkerContext(frame, url); + + var frameContents = '(function() { var location = __devtools.location; var window; ' + code + '})();\n' + '//@ sourceURL=' + url.url; + + frame.eval(frameContents); + if (this._pendingMessages) { + for (var msg = 0; msg < this._pendingMessages.length; ++msg) + this.postMessage.apply(this, this._pendingMessages[msg]); + delete this._pendingMessages; + } + }, + + _setupWorkerContext: function(workerFrame, url) + { + workerFrame.__devtools = { + handleException: bind(this._handleException, this), + location: url.mockLocation() + }; + + var self = this; + + function onmessageGetter() + { + return self.channel.port2.onmessage ? self.channel.port2.onmessage.originalCallback : null; + } + + function onmessageSetter(callback) + { + var wrappedCallback = bind(self._callbackWrapper, self, callback); + wrappedCallback.originalCallback = callback; + self.channel.port2.onmessage = wrappedCallback; + } + + workerFrame.__defineGetter__("onmessage", onmessageGetter); + workerFrame.__defineSetter__("onmessage", onmessageSetter); + workerFrame.addEventListener = bind(this._addEventListener, this); + workerFrame.removeEventListener = bind(this._removeEventListener, this); + workerFrame.dispatchEvent = bind(this.channel.port2.dispatchEvent, this.channel.port2); + workerFrame.postMessage = bind(this.channel.port2.postMessage, this.channel.port2); + workerFrame.importScripts = bind(this._importScripts, this, workerFrame); + workerFrame.close = bind(this.terminate, this); + }, + + _addEventListener: function(type, callback, useCapture) + { + var wrappedCallback = bind(this._callbackWrapper, this, callback); + wrappedCallback.originalCallback = callback; + wrappedCallback.type = type; + wrappedCallback.useCapture = Boolean(useCapture); + + this.channel.port2.addEventListener(type, wrappedCallback, useCapture); + this._listeners.push(wrappedCallback); + }, + + _removeEventListener: function(type, callback, useCapture) + { + var listeners = this._listeners; + for (var i = 0; i < listeners.length; ++i) { + if (listeners[i].originalCallback === callback && + listeners[i].type === type && + listeners[i].useCapture === Boolean(useCapture)) { + this.channel.port2.removeEventListener(type, listeners[i], useCapture); + listeners[i] = listeners[listeners.length - 1]; + listeners.pop(); + break; + } + } + }, + + _callbackWrapper: function(callback, msg) + { + // Shortcut -- if no exception handlers installed, avoid try/catch so as not to obscure line number. + if (!this._frame.onerror && !this._worker.onerror) { + callback(msg); + return; + } + + try { + callback(msg); + } catch (e) { + this._handleException(e, this._frame.onerror, this._worker.onerror); + } + }, + + _handleException: function(e) + { + // NB: it should be an ErrorEvent, but creating it from script is not + // currently supported, so emulate it on top of plain vanilla Event. + var errorEvent = this._document.createEvent("Event"); + errorEvent.initEvent("Event", false, false); + errorEvent.message = "Uncaught exception"; + + for (var i = 1; i < arguments.length; ++i) { + if (arguments[i] && arguments[i](errorEvent)) + return; + } + + throw e; + }, + + _importScripts: function(targetFrame) + { + for (var i = 1; i < arguments.length; ++i) { + var workerOrigin = targetFrame.__devtools.location.href; + var url = this._expandURLAndCheckOrigin(workerOrigin, workerOrigin, arguments[i]); + targetFrame.eval(this._loadScript(url.url) + "\n//@ sourceURL= " + url.url); + } + }, + + _loadScript: function(url) + { + var xhr = new XMLHttpRequest(); + xhr.open("GET", url, false); + xhr.send(null); + + var text = xhr.responseText; + if (xhr.status != 0 && xhr.status/100 !== 2) { // We're getting status === 0 when using file://. + console.error("Failed to load worker: " + url + "[" + xhr.status + "]"); + text = ""; // We've got error message, not worker code. + } + return text; + }, + + _expandURLAndCheckOrigin: function(baseURL, origin, url) + { + var scriptURL = new URL(baseURL).completeWith(url); + + if (!scriptURL.sameOrigin(origin)) + throw new DOMCoreException("SECURITY_ERR",18); + return scriptURL; + } +}; + +function URL(url) +{ + this.url = url; + this.split(); +} + +URL.prototype = { + urlRegEx: (/^(http[s]?|file):\/\/([^\/:]*)(:[\d]+)?(?:(\/[^#?]*)(\?[^#]*)?(?:#(.*))?)?$/i), + + split: function() + { + function emptyIfNull(str) + { + return str == null ? "" : str; + } + var parts = this.urlRegEx.exec(this.url); + + this.schema = parts[1]; + this.host = parts[2]; + this.port = emptyIfNull(parts[3]); + this.path = emptyIfNull(parts[4]); + this.query = emptyIfNull(parts[5]); + this.fragment = emptyIfNull(parts[6]); + }, + + mockLocation: function() + { + var host = this.host.replace(/^[^@]*@/, ""); + + return { + href: this.url, + protocol: this.schema + ":", + host: host, + hostname: host, + port: this.port, + pathname: this.path, + search: this.query, + hash: this.fragment + }; + }, + + completeWith: function(url) + { + if (url === "" || /^[^/]*:/.exec(url)) // If given absolute url, return as is now. + return new URL(url); + + var relParts = /^([^#?]*)(.*)$/.exec(url); // => [ url, path, query-andor-fragment ] + + var path = (relParts[1].slice(0, 1) === "/" ? "" : this.path.replace(/[^/]*$/, "")) + relParts[1]; + path = path.replace(/(\/\.)+(\/|$)/g, "/").replace(/[^/]*\/\.\.(\/|$)/g, ""); + + return new URL(this.schema + "://" + this.host + this.port + path + relParts[2]); + }, + + sameOrigin: function(url) + { + function normalizePort(schema, port) + { + var portNo = port.slice(1); + return (schema === "https" && portNo == 443 || schema === "http" && portNo == 80) ? "" : port; + } + + var other = new URL(url); + + return this.schema === other.schema && + this.host === other.host && + normalizePort(this.schema, this.port) === normalizePort(other.schema, other.port); + } +}; + +function DOMCoreException(name, code) +{ + function formatError() + { + return "Error: " + this.message; + } + + this.name = name; + this.message = name + ": DOM Exception " + code; + this.code = code; + this.toString = bind(formatError, this); +} + +function bind(func, thisObject) +{ + var args = Array.prototype.slice.call(arguments, 2); + return function() { return func.apply(thisObject, args.concat(Array.prototype.slice.call(arguments, 0))); }; +} + +function noop() +{ +} + +} +/* TextViewer.js */ + +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * Copyright (C) 2010 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: + * + * * 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. + */ + +/** + * @extends {WebInspector.View} + * @constructor + */ +WebInspector.TextViewer = function(textModel, platform, url, delegate) +{ + WebInspector.View.call(this); + this.registerRequiredCSS("textViewer.css"); + + this._textModel = textModel; + this._textModel.changeListener = this._textChanged.bind(this); + this._textModel.resetUndoStack(); + this._delegate = delegate; + + this.element.className = "text-editor monospace"; + + var enterTextChangeMode = this._enterInternalTextChangeMode.bind(this); + var exitTextChangeMode = this._exitInternalTextChangeMode.bind(this); + var syncScrollListener = this._syncScroll.bind(this); + var syncDecorationsForLineListener = this._syncDecorationsForLine.bind(this); + var syncLineHeightListener = this._syncLineHeight.bind(this); + this._mainPanel = new WebInspector.TextEditorMainPanel(this._textModel, url, syncScrollListener, syncDecorationsForLineListener, enterTextChangeMode, exitTextChangeMode); + this._gutterPanel = new WebInspector.TextEditorGutterPanel(this._textModel, syncDecorationsForLineListener, syncLineHeightListener); + this.element.appendChild(this._mainPanel.element); + this.element.appendChild(this._gutterPanel.element); + + // Forward mouse wheel events from the unscrollable gutter to the main panel. + function forwardWheelEvent(event) + { + var clone = document.createEvent("WheelEvent"); + clone.initWebKitWheelEvent(event.wheelDeltaX, event.wheelDeltaY, + event.view, + event.screenX, event.screenY, + event.clientX, event.clientY, + event.ctrlKey, event.altKey, event.shiftKey, event.metaKey); + this._mainPanel.element.dispatchEvent(clone); + } + this._gutterPanel.element.addEventListener("mousewheel", forwardWheelEvent.bind(this), false); + + this.element.addEventListener("dblclick", this._doubleClick.bind(this), true); + this.element.addEventListener("keydown", this._handleKeyDown.bind(this), false); + this.element.addEventListener("contextmenu", this._contextMenu.bind(this), true); + + this._registerShortcuts(); +} + +WebInspector.TextViewer.prototype = { + set mimeType(mimeType) + { + this._mainPanel.mimeType = mimeType; + }, + + set readOnly(readOnly) + { + if (this._mainPanel.readOnly === readOnly) + return; + this._mainPanel.readOnly = readOnly; + WebInspector.markBeingEdited(this.element, !readOnly); + }, + + get readOnly() + { + return this._mainPanel.readOnly; + }, + + get textModel() + { + return this._textModel; + }, + + focus: function() + { + this._mainPanel.element.focus(); + }, + + revealLine: function(lineNumber) + { + this._mainPanel.revealLine(lineNumber); + }, + + addDecoration: function(lineNumber, decoration) + { + this._mainPanel.addDecoration(lineNumber, decoration); + this._gutterPanel.addDecoration(lineNumber, decoration); + }, + + removeDecoration: function(lineNumber, decoration) + { + this._mainPanel.removeDecoration(lineNumber, decoration); + this._gutterPanel.removeDecoration(lineNumber, decoration); + }, + + markAndRevealRange: function(range) + { + this._mainPanel.markAndRevealRange(range); + }, + + highlightLine: function(lineNumber) + { + if (typeof lineNumber !== "number" || lineNumber < 0) + return; + + lineNumber = Math.min(lineNumber, this._textModel.linesCount - 1); + this._mainPanel.highlightLine(lineNumber); + }, + + clearLineHighlight: function() + { + this._mainPanel.clearLineHighlight(); + }, + + freeCachedElements: function() + { + this._mainPanel.freeCachedElements(); + this._gutterPanel.freeCachedElements(); + }, + + elementsToRestoreScrollPositionsFor: function() + { + return [this._mainPanel.element]; + }, + + inheritScrollPositions: function(textViewer) + { + this._mainPanel.element._scrollTop = textViewer._mainPanel.element.scrollTop; + this._mainPanel.element._scrollLeft = textViewer._mainPanel.element.scrollLeft; + }, + + beginUpdates: function() + { + this._mainPanel.beginUpdates(); + this._gutterPanel.beginUpdates(); + }, + + endUpdates: function() + { + this._mainPanel.endUpdates(); + this._gutterPanel.endUpdates(); + this._updatePanelOffsets(); + }, + + onResize: function() + { + this._mainPanel.resize(); + this._gutterPanel.resize(); + this._updatePanelOffsets(); + }, + + // WebInspector.TextModel listener + _textChanged: function(oldRange, newRange, oldText, newText) + { + if (!this._internalTextChangeMode) + this._textModel.resetUndoStack(); + this._mainPanel.textChanged(oldRange, newRange); + this._gutterPanel.textChanged(oldRange, newRange); + this._updatePanelOffsets(); + }, + + _enterInternalTextChangeMode: function() + { + this._internalTextChangeMode = true; + this._delegate.beforeTextChanged(); + }, + + _exitInternalTextChangeMode: function(oldRange, newRange) + { + this._internalTextChangeMode = false; + this._delegate.afterTextChanged(oldRange, newRange); + }, + + _updatePanelOffsets: function() + { + var lineNumbersWidth = this._gutterPanel.element.offsetWidth; + if (lineNumbersWidth) + this._mainPanel.element.style.setProperty("left", lineNumbersWidth + "px"); + else + this._mainPanel.element.style.removeProperty("left"); // Use default value set in CSS. + }, + + _syncScroll: function() + { + var mainElement = this._mainPanel.element; + var gutterElement = this._gutterPanel.element; + // Handle horizontal scroll bar at the bottom of the main panel. + this._gutterPanel.syncClientHeight(mainElement.clientHeight); + gutterElement.scrollTop = mainElement.scrollTop; + }, + + _syncDecorationsForLine: function(lineNumber) + { + if (lineNumber >= this._textModel.linesCount) + return; + + var mainChunk = this._mainPanel.chunkForLine(lineNumber); + if (mainChunk.linesCount === 1 && mainChunk.decorated) { + var gutterChunk = this._gutterPanel.makeLineAChunk(lineNumber); + var height = mainChunk.height; + if (height) + gutterChunk.element.style.setProperty("height", height + "px"); + else + gutterChunk.element.style.removeProperty("height"); + } else { + var gutterChunk = this._gutterPanel.chunkForLine(lineNumber); + if (gutterChunk.linesCount === 1) + gutterChunk.element.style.removeProperty("height"); + } + }, + + _syncLineHeight: function(gutterRow) { + if (this._lineHeightSynced) + return; + if (gutterRow && gutterRow.offsetHeight) { + // Force equal line heights for the child panels. + this.element.style.setProperty("line-height", gutterRow.offsetHeight + "px"); + this._lineHeightSynced = true; + } + }, + + _doubleClick: function(event) + { + if (!this.readOnly) + return; + + var lineRow = event.target.enclosingNodeOrSelfWithClass("webkit-line-content"); + if (!lineRow) + return; // Do not trigger editing from line numbers. + + this._delegate.doubleClick(lineRow.lineNumber); + window.getSelection().collapseToStart(); + }, + + _registerShortcuts: function() + { + var keys = WebInspector.KeyboardShortcut.Keys; + var modifiers = WebInspector.KeyboardShortcut.Modifiers; + + this._shortcuts = {}; + var commitEditing = this._commitEditing.bind(this); + var cancelEditing = this._cancelEditing.bind(this); + this._shortcuts[WebInspector.KeyboardShortcut.makeKey("s", modifiers.CtrlOrMeta)] = commitEditing; + this._shortcuts[WebInspector.KeyboardShortcut.makeKey(keys.Enter.code, modifiers.CtrlOrMeta)] = commitEditing; + this._shortcuts[WebInspector.KeyboardShortcut.makeKey(keys.Esc.code)] = cancelEditing; + + var handleEnterKey = this._mainPanel.handleEnterKey.bind(this._mainPanel); + this._shortcuts[WebInspector.KeyboardShortcut.makeKey(keys.Enter.code, WebInspector.KeyboardShortcut.Modifiers.None)] = handleEnterKey; + + var handleUndo = this._mainPanel.handleUndoRedo.bind(this._mainPanel, false); + var handleRedo = this._mainPanel.handleUndoRedo.bind(this._mainPanel, true); + this._shortcuts[WebInspector.KeyboardShortcut.makeKey("z", modifiers.CtrlOrMeta)] = handleUndo; + this._shortcuts[WebInspector.KeyboardShortcut.makeKey("z", modifiers.Shift | modifiers.CtrlOrMeta)] = handleRedo; + + var handleTabKey = this._mainPanel.handleTabKeyPress.bind(this._mainPanel, false); + var handleShiftTabKey = this._mainPanel.handleTabKeyPress.bind(this._mainPanel, true); + this._shortcuts[WebInspector.KeyboardShortcut.makeKey(keys.Tab.code)] = handleTabKey; + this._shortcuts[WebInspector.KeyboardShortcut.makeKey(keys.Tab.code, modifiers.Shift)] = handleShiftTabKey; + }, + + _handleKeyDown: function(e) + { + if (this.readOnly) + return; + + var shortcutKey = WebInspector.KeyboardShortcut.makeKeyFromEvent(e); + var handler = this._shortcuts[shortcutKey]; + if (handler && handler()) { + e.preventDefault(); + e.stopPropagation(); + } + }, + + _contextMenu: function(event) + { + var contextMenu = new WebInspector.ContextMenu(); + var target = event.target.enclosingNodeOrSelfWithClass("webkit-line-number"); + if (target) + this._delegate.populateLineGutterContextMenu(contextMenu, target.lineNumber); + else { + target = this._mainPanel._enclosingLineRowOrSelf(event.target); + this._delegate.populateTextAreaContextMenu(contextMenu, target && target.lineNumber); + } + var fileName = this._delegate.suggestedFileName(); + if (fileName) + contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Save as..." : "Save As..."), InspectorFrontendHost.saveAs.bind(InspectorFrontendHost, fileName, this._textModel.text)); + + contextMenu.show(event); + }, + + _commitEditing: function() + { + if (this.readOnly) + return false; + + this._delegate.commitEditing(); + return true; + }, + + _cancelEditing: function() + { + if (this.readOnly) + return false; + + return this._delegate.cancelEditing(); + }, + + wasShown: function() + { + if (!this.readOnly) + WebInspector.markBeingEdited(this.element, true); + }, + + willHide: function() + { + if (!this.readOnly) + WebInspector.markBeingEdited(this.element, false); + } +} + +WebInspector.TextViewer.prototype.__proto__ = WebInspector.View.prototype; + +/** + * @interface + */ +WebInspector.TextViewerDelegate = function() +{ +} + +WebInspector.TextViewerDelegate.prototype = { + doubleClick: function(lineNumber) { }, + + beforeTextChanged: function() { }, + + afterTextChanged: function(oldRange, newRange) { }, + + commitEditing: function() { }, + + cancelEditing: function() { }, + + populateLineGutterContextMenu: function(contextMenu, lineNumber) { }, + + populateTextAreaContextMenu: function(contextMenu, lineNumber) { }, + + suggestedFileName: function() { } +} + +/** + * @constructor + */ +WebInspector.TextEditorChunkedPanel = function(textModel) +{ + this._textModel = textModel; + + this._defaultChunkSize = 50; + this._paintCoalescingLevel = 0; + this._domUpdateCoalescingLevel = 0; +} + +WebInspector.TextEditorChunkedPanel.prototype = { + get textModel() + { + return this._textModel; + }, + + revealLine: function(lineNumber) + { + if (lineNumber >= this._textModel.linesCount) + return; + + var chunk = this.makeLineAChunk(lineNumber); + chunk.element.scrollIntoViewIfNeeded(); + }, + + addDecoration: function(lineNumber, decoration) + { + if (lineNumber >= this._textModel.linesCount) + return; + + var chunk = this.makeLineAChunk(lineNumber); + chunk.addDecoration(decoration); + }, + + removeDecoration: function(lineNumber, decoration) + { + if (lineNumber >= this._textModel.linesCount) + return; + + var chunk = this.chunkForLine(lineNumber); + chunk.removeDecoration(decoration); + }, + + _buildChunks: function() + { + this.beginDomUpdates(); + + this._container.removeChildren(); + + this._textChunks = []; + for (var i = 0; i < this._textModel.linesCount; i += this._defaultChunkSize) { + var chunk = this._createNewChunk(i, i + this._defaultChunkSize); + this._textChunks.push(chunk); + this._container.appendChild(chunk.element); + } + + this._repaintAll(); + + this.endDomUpdates(); + }, + + makeLineAChunk: function(lineNumber) + { + var chunkNumber = this._chunkNumberForLine(lineNumber); + var oldChunk = this._textChunks[chunkNumber]; + + if (!oldChunk) { + console.error("No chunk for line number: " + lineNumber); + return; + } + + if (oldChunk.linesCount === 1) + return oldChunk; + + return this._splitChunkOnALine(lineNumber, chunkNumber, true); + }, + + _splitChunkOnALine: function(lineNumber, chunkNumber, createSuffixChunk) + { + this.beginDomUpdates(); + + var oldChunk = this._textChunks[chunkNumber]; + var wasExpanded = oldChunk.expanded; + oldChunk.expanded = false; + + var insertIndex = chunkNumber + 1; + + // Prefix chunk. + if (lineNumber > oldChunk.startLine) { + var prefixChunk = this._createNewChunk(oldChunk.startLine, lineNumber); + prefixChunk.readOnly = oldChunk.readOnly; + this._textChunks.splice(insertIndex++, 0, prefixChunk); + this._container.insertBefore(prefixChunk.element, oldChunk.element); + } + + // Line chunk. + var endLine = createSuffixChunk ? lineNumber + 1 : oldChunk.startLine + oldChunk.linesCount; + var lineChunk = this._createNewChunk(lineNumber, endLine); + lineChunk.readOnly = oldChunk.readOnly; + this._textChunks.splice(insertIndex++, 0, lineChunk); + this._container.insertBefore(lineChunk.element, oldChunk.element); + + // Suffix chunk. + if (oldChunk.startLine + oldChunk.linesCount > endLine) { + var suffixChunk = this._createNewChunk(endLine, oldChunk.startLine + oldChunk.linesCount); + suffixChunk.readOnly = oldChunk.readOnly; + this._textChunks.splice(insertIndex, 0, suffixChunk); + this._container.insertBefore(suffixChunk.element, oldChunk.element); + } + + // Remove enclosing chunk. + this._textChunks.splice(chunkNumber, 1); + this._container.removeChild(oldChunk.element); + + if (wasExpanded) { + if (prefixChunk) + prefixChunk.expanded = true; + lineChunk.expanded = true; + if (suffixChunk) + suffixChunk.expanded = true; + } + + this.endDomUpdates(); + + return lineChunk; + }, + + _scroll: function() + { + // FIXME: Replace the "2" with the padding-left value from CSS. + if (this.element.scrollLeft <= 2) + this.element.scrollLeft = 0; + + this._scheduleRepaintAll(); + if (this._syncScrollListener) + this._syncScrollListener(); + }, + + _scheduleRepaintAll: function() + { + if (this._repaintAllTimer) + clearTimeout(this._repaintAllTimer); + this._repaintAllTimer = setTimeout(this._repaintAll.bind(this), 50); + }, + + beginUpdates: function() + { + this._paintCoalescingLevel++; + }, + + endUpdates: function() + { + this._paintCoalescingLevel--; + if (!this._paintCoalescingLevel) + this._repaintAll(); + }, + + beginDomUpdates: function() + { + this._domUpdateCoalescingLevel++; + }, + + endDomUpdates: function() + { + this._domUpdateCoalescingLevel--; + }, + + _chunkNumberForLine: function(lineNumber) + { + function compareLineNumbers(value, chunk) + { + return value < chunk.startLine ? -1 : 1; + } + var insertBefore = insertionIndexForObjectInListSortedByFunction(lineNumber, this._textChunks, compareLineNumbers); + return insertBefore - 1; + }, + + chunkForLine: function(lineNumber) + { + return this._textChunks[this._chunkNumberForLine(lineNumber)]; + }, + + _findFirstVisibleChunkNumber: function(visibleFrom) + { + function compareOffsetTops(value, chunk) + { + return value < chunk.offsetTop ? -1 : 1; + } + var insertBefore = insertionIndexForObjectInListSortedByFunction(visibleFrom, this._textChunks, compareOffsetTops); + return insertBefore - 1; + }, + + _findVisibleChunks: function(visibleFrom, visibleTo) + { + var from = this._findFirstVisibleChunkNumber(visibleFrom); + for (var to = from + 1; to < this._textChunks.length; ++to) { + if (this._textChunks[to].offsetTop >= visibleTo) + break; + } + return { start: from, end: to }; + }, + + _findFirstVisibleLineNumber: function(visibleFrom) + { + var chunk = this._textChunks[this._findFirstVisibleChunkNumber(visibleFrom)]; + if (!chunk.expanded) + return chunk.startLine; + + var lineNumbers = []; + for (var i = 0; i < chunk.linesCount; ++i) { + lineNumbers.push(chunk.startLine + i); + } + + function compareLineRowOffsetTops(value, lineNumber) + { + var lineRow = chunk.getExpandedLineRow(lineNumber); + return value < lineRow.offsetTop ? -1 : 1; + } + var insertBefore = insertionIndexForObjectInListSortedByFunction(visibleFrom, lineNumbers, compareLineRowOffsetTops); + return lineNumbers[insertBefore - 1]; + }, + + _repaintAll: function() + { + delete this._repaintAllTimer; + + if (this._paintCoalescingLevel || this._dirtyLines) + return; + + var visibleFrom = this.element.scrollTop; + var visibleTo = this.element.scrollTop + this.element.clientHeight; + + if (visibleTo) { + var result = this._findVisibleChunks(visibleFrom, visibleTo); + this._expandChunks(result.start, result.end); + } + }, + + _expandChunks: function(fromIndex, toIndex) + { + // First collapse chunks to collect the DOM elements into a cache to reuse them later. + for (var i = 0; i < fromIndex; ++i) + this._textChunks[i].expanded = false; + for (var i = toIndex; i < this._textChunks.length; ++i) + this._textChunks[i].expanded = false; + for (var i = fromIndex; i < toIndex; ++i) + this._textChunks[i].expanded = true; + }, + + _totalHeight: function(firstElement, lastElement) + { + lastElement = (lastElement || firstElement).nextElementSibling; + if (lastElement) + return lastElement.offsetTop - firstElement.offsetTop; + + var offsetParent = firstElement.offsetParent; + if (offsetParent && offsetParent.scrollHeight > offsetParent.clientHeight) + return offsetParent.scrollHeight - firstElement.offsetTop; + + var total = 0; + while (firstElement && firstElement !== lastElement) { + total += firstElement.offsetHeight; + firstElement = firstElement.nextElementSibling; + } + return total; + }, + + resize: function() + { + this._repaintAll(); + } +} + +/** + * @constructor + * @extends {WebInspector.TextEditorChunkedPanel} + */ +WebInspector.TextEditorGutterPanel = function(textModel, syncDecorationsForLineListener, syncLineHeightListener) +{ + WebInspector.TextEditorChunkedPanel.call(this, textModel); + + this._syncDecorationsForLineListener = syncDecorationsForLineListener; + this._syncLineHeightListener = syncLineHeightListener; + + this.element = document.createElement("div"); + this.element.className = "text-editor-lines"; + + this._container = document.createElement("div"); + this._container.className = "inner-container"; + this.element.appendChild(this._container); + + this.element.addEventListener("scroll", this._scroll.bind(this), false); + + this.freeCachedElements(); + this._buildChunks(); +} + +WebInspector.TextEditorGutterPanel.prototype = { + freeCachedElements: function() + { + this._cachedRows = []; + }, + + _createNewChunk: function(startLine, endLine) + { + return new WebInspector.TextEditorGutterChunk(this, startLine, endLine); + }, + + textChanged: function(oldRange, newRange) + { + this.beginDomUpdates(); + + var linesDiff = newRange.linesCount - oldRange.linesCount; + if (linesDiff) { + // Remove old chunks (if needed). + for (var chunkNumber = this._textChunks.length - 1; chunkNumber >= 0 ; --chunkNumber) { + var chunk = this._textChunks[chunkNumber]; + if (chunk.startLine + chunk.linesCount <= this._textModel.linesCount) + break; + chunk.expanded = false; + this._container.removeChild(chunk.element); + } + this._textChunks.length = chunkNumber + 1; + + // Add new chunks (if needed). + var totalLines = 0; + if (this._textChunks.length) { + var lastChunk = this._textChunks[this._textChunks.length - 1]; + totalLines = lastChunk.startLine + lastChunk.linesCount; + } + for (var i = totalLines; i < this._textModel.linesCount; i += this._defaultChunkSize) { + var chunk = this._createNewChunk(i, i + this._defaultChunkSize); + this._textChunks.push(chunk); + this._container.appendChild(chunk.element); + } + this._repaintAll(); + } else { + // Decorations may have been removed, so we may have to sync those lines. + var chunkNumber = this._chunkNumberForLine(newRange.startLine); + var chunk = this._textChunks[chunkNumber]; + while (chunk && chunk.startLine <= newRange.endLine) { + if (chunk.linesCount === 1) + this._syncDecorationsForLineListener(chunk.startLine); + chunk = this._textChunks[++chunkNumber]; + } + } + + this.endDomUpdates(); + }, + + syncClientHeight: function(clientHeight) + { + if (this.element.offsetHeight > clientHeight) + this._container.style.setProperty("padding-bottom", (this.element.offsetHeight - clientHeight) + "px"); + else + this._container.style.removeProperty("padding-bottom"); + } +} + +WebInspector.TextEditorGutterPanel.prototype.__proto__ = WebInspector.TextEditorChunkedPanel.prototype; + +/** + * @constructor + */ +WebInspector.TextEditorGutterChunk = function(textViewer, startLine, endLine) +{ + this._textViewer = textViewer; + this._textModel = textViewer._textModel; + + this.startLine = startLine; + endLine = Math.min(this._textModel.linesCount, endLine); + this.linesCount = endLine - startLine; + + this._expanded = false; + + this.element = document.createElement("div"); + this.element.lineNumber = startLine; + this.element.className = "webkit-line-number"; + + if (this.linesCount === 1) { + // Single line chunks are typically created for decorations. Host line number in + // the sub-element in order to allow flexible border / margin management. + var innerSpan = document.createElement("span"); + innerSpan.className = "webkit-line-number-inner"; + innerSpan.textContent = startLine + 1; + var outerSpan = document.createElement("div"); + outerSpan.className = "webkit-line-number-outer"; + outerSpan.appendChild(innerSpan); + this.element.appendChild(outerSpan); + } else { + var lineNumbers = []; + for (var i = startLine; i < endLine; ++i) + lineNumbers.push(i + 1); + this.element.textContent = lineNumbers.join("\n"); + } +} + +WebInspector.TextEditorGutterChunk.prototype = { + addDecoration: function(decoration) + { + this._textViewer.beginDomUpdates(); + if (typeof decoration === "string") + this.element.addStyleClass(decoration); + this._textViewer.endDomUpdates(); + }, + + removeDecoration: function(decoration) + { + this._textViewer.beginDomUpdates(); + if (typeof decoration === "string") + this.element.removeStyleClass(decoration); + this._textViewer.endDomUpdates(); + }, + + get expanded() + { + return this._expanded; + }, + + set expanded(expanded) + { + if (this.linesCount === 1) + this._textViewer._syncDecorationsForLineListener(this.startLine); + + if (this._expanded === expanded) + return; + + this._expanded = expanded; + + if (this.linesCount === 1) + return; + + this._textViewer.beginDomUpdates(); + + if (expanded) { + this._expandedLineRows = []; + var parentElement = this.element.parentElement; + for (var i = this.startLine; i < this.startLine + this.linesCount; ++i) { + var lineRow = this._createRow(i); + parentElement.insertBefore(lineRow, this.element); + this._expandedLineRows.push(lineRow); + } + parentElement.removeChild(this.element); + this._textViewer._syncLineHeightListener(this._expandedLineRows[0]); + } else { + var elementInserted = false; + for (var i = 0; i < this._expandedLineRows.length; ++i) { + var lineRow = this._expandedLineRows[i]; + var parentElement = lineRow.parentElement; + if (parentElement) { + if (!elementInserted) { + elementInserted = true; + parentElement.insertBefore(this.element, lineRow); + } + parentElement.removeChild(lineRow); + } + this._textViewer._cachedRows.push(lineRow); + } + delete this._expandedLineRows; + } + + this._textViewer.endDomUpdates(); + }, + + get height() + { + if (!this._expandedLineRows) + return this._textViewer._totalHeight(this.element); + return this._textViewer._totalHeight(this._expandedLineRows[0], this._expandedLineRows[this._expandedLineRows.length - 1]); + }, + + get offsetTop() + { + return (this._expandedLineRows && this._expandedLineRows.length) ? this._expandedLineRows[0].offsetTop : this.element.offsetTop; + }, + + _createRow: function(lineNumber) + { + var lineRow = this._textViewer._cachedRows.pop() || document.createElement("div"); + lineRow.lineNumber = lineNumber; + lineRow.className = "webkit-line-number"; + lineRow.textContent = lineNumber + 1; + return lineRow; + } +} + +/** + * @constructor + * @extends {WebInspector.TextEditorChunkedPanel} + */ +WebInspector.TextEditorMainPanel = function(textModel, url, syncScrollListener, syncDecorationsForLineListener, enterTextChangeMode, exitTextChangeMode) +{ + WebInspector.TextEditorChunkedPanel.call(this, textModel); + + this._syncScrollListener = syncScrollListener; + this._syncDecorationsForLineListener = syncDecorationsForLineListener; + this._enterTextChangeMode = enterTextChangeMode; + this._exitTextChangeMode = exitTextChangeMode; + + this._url = url; + this._highlighter = new WebInspector.TextEditorHighlighter(textModel, this._highlightDataReady.bind(this)); + this._readOnly = true; + + this.element = document.createElement("div"); + this.element.className = "text-editor-contents"; + this.element.tabIndex = 0; + + this._container = document.createElement("div"); + this._container.className = "inner-container"; + this._container.tabIndex = 0; + this.element.appendChild(this._container); + + this.element.addEventListener("scroll", this._scroll.bind(this), false); + + // In WebKit the DOMNodeRemoved event is fired AFTER the node is removed, thus it should be + // attached to all DOM nodes that we want to track. Instead, we attach the DOMNodeRemoved + // listeners only on the line rows, and use DOMSubtreeModified to track node removals inside + // the line rows. For more info see: https://bugs.webkit.org/show_bug.cgi?id=55666 + // + // OPTIMIZATION. It is very expensive to listen to the DOM mutation events, thus we remove the + // listeners whenever we do any internal DOM manipulations (such as expand/collapse line rows) + // and set the listeners back when we are finished. + this._handleDOMUpdatesCallback = this._handleDOMUpdates.bind(this); + this._container.addEventListener("DOMCharacterDataModified", this._handleDOMUpdatesCallback, false); + this._container.addEventListener("DOMNodeInserted", this._handleDOMUpdatesCallback, false); + this._container.addEventListener("DOMSubtreeModified", this._handleDOMUpdatesCallback, false); + + this.freeCachedElements(); + this._buildChunks(); +} + +WebInspector.TextEditorMainPanel.prototype = { + set mimeType(mimeType) + { + this._highlighter.mimeType = mimeType; + }, + + set readOnly(readOnly) + { + if (this._readOnly === readOnly) + return; + + this.beginDomUpdates(); + this._readOnly = readOnly; + if (this._readOnly) + this._container.removeStyleClass("text-editor-editable"); + else { + this._container.addStyleClass("text-editor-editable"); + this._updateSelectionOnStartEditing(); + } + this.endDomUpdates(); + }, + + get readOnly() + { + return this._readOnly; + }, + + _updateSelectionOnStartEditing: function() + { + // focus() needs to go first for the case when the last selection was inside the editor and + // the "Edit" button was clicked. In this case we bail at the check below, but the + // editor does not receive the focus, thus "Esc" does not cancel editing until at least + // one change has been made to the editor contents. + this._container.focus(); + var selection = window.getSelection(); + if (selection.rangeCount) { + var commonAncestorContainer = selection.getRangeAt(0).commonAncestorContainer; + if (this._container.isSelfOrAncestor(commonAncestorContainer)) + return; + } + + selection.removeAllRanges(); + var range = document.createRange(); + range.setStart(this._container, 0); + range.setEnd(this._container, 0); + selection.addRange(range); + }, + + setEditableRange: function(startLine, endLine) + { + this.beginDomUpdates(); + + var firstChunkNumber = this._chunkNumberForLine(startLine); + var firstChunk = this._textChunks[firstChunkNumber]; + if (firstChunk.startLine !== startLine) { + this._splitChunkOnALine(startLine, firstChunkNumber); + firstChunkNumber += 1; + } + + var lastChunkNumber = this._textChunks.length; + if (endLine !== this._textModel.linesCount) { + lastChunkNumber = this._chunkNumberForLine(endLine); + var lastChunk = this._textChunks[lastChunkNumber]; + if (lastChunk && lastChunk.startLine !== endLine) { + this._splitChunkOnALine(endLine, lastChunkNumber); + lastChunkNumber += 1; + } + } + + for (var chunkNumber = 0; chunkNumber < firstChunkNumber; ++chunkNumber) + this._textChunks[chunkNumber].readOnly = true; + for (var chunkNumber = firstChunkNumber; chunkNumber < lastChunkNumber; ++chunkNumber) + this._textChunks[chunkNumber].readOnly = false; + for (var chunkNumber = lastChunkNumber; chunkNumber < this._textChunks.length; ++chunkNumber) + this._textChunks[chunkNumber].readOnly = true; + + this.endDomUpdates(); + }, + + clearEditableRange: function() + { + for (var chunkNumber = 0; chunkNumber < this._textChunks.length; ++chunkNumber) + this._textChunks[chunkNumber].readOnly = false; + }, + + markAndRevealRange: function(range) + { + if (this._rangeToMark) { + var markedLine = this._rangeToMark.startLine; + delete this._rangeToMark; + // Remove the marked region immediately. + if (!this._dirtyLines) { + this.beginDomUpdates(); + var chunk = this.chunkForLine(markedLine); + var wasExpanded = chunk.expanded; + chunk.expanded = false; + chunk.updateCollapsedLineRow(); + chunk.expanded = wasExpanded; + this.endDomUpdates(); + } else + this._paintLines(markedLine, markedLine + 1); + } + + if (range) { + this._rangeToMark = range; + this.revealLine(range.startLine); + var chunk = this.makeLineAChunk(range.startLine); + this._paintLine(chunk.element); + if (this._markedRangeElement) + this._markedRangeElement.scrollIntoViewIfNeeded(); + } + delete this._markedRangeElement; + }, + + highlightLine: function(lineNumber) + { + this.clearLineHighlight(); + this._highlightedLine = lineNumber; + this.revealLine(lineNumber); + this.addDecoration(lineNumber, "webkit-highlighted-line"); + }, + + clearLineHighlight: function() + { + if (typeof this._highlightedLine === "number") { + this.removeDecoration(this._highlightedLine, "webkit-highlighted-line"); + delete this._highlightedLine; + } + }, + + freeCachedElements: function() + { + this._cachedSpans = []; + this._cachedTextNodes = []; + this._cachedRows = []; + }, + + handleUndoRedo: function(redo) + { + if (this._dirtyLines) + return false; + + this.beginUpdates(); + this._enterTextChangeMode(); + + var callback = function(oldRange, newRange) { + this._exitTextChangeMode(oldRange, newRange); + this._enterTextChangeMode(); + }.bind(this); + + var range = redo ? this._textModel.redo(callback) : this._textModel.undo(callback); + if (range) + this._setCaretLocation(range.endLine, range.endColumn, true); + + this._exitTextChangeMode(null, null); + this.endUpdates(); + + return true; + }, + + handleTabKeyPress: function(shiftKey) + { + if (this._dirtyLines) + return false; + + var selection = this._getSelection(); + if (!selection) + return false; + + var range = selection.normalize(); + + this.beginUpdates(); + this._enterTextChangeMode(); + + var newRange; + if (shiftKey) + newRange = this._unindentLines(range); + else { + if (range.isEmpty()) { + newRange = this._setText(range, WebInspector.settings.textEditorIndent.get()); + newRange.startColumn = newRange.endColumn; + } else + newRange = this._indentLines(range); + + } + + this._exitTextChangeMode(range, newRange); + this.endUpdates(); + this._restoreSelection(newRange, true); + return true; + }, + + _indentLines: function(range) + { + var indent = WebInspector.settings.textEditorIndent.get(); + + if (this._lastEditedRange) + this._textModel.markUndoableState(); + + for (var lineNumber = range.startLine; lineNumber <= range.endLine; lineNumber++) + this._textModel.setText(new WebInspector.TextRange(lineNumber, 0, lineNumber, 0), indent); + + var newRange = range.clone(); + newRange.startColumn += indent.length; + newRange.endColumn += indent.length; + this._lastEditedRange = newRange; + + return newRange; + }, + + _unindentLines: function(range) + { + if (this._lastEditedRange) + this._textModel.markUndoableState(); + + var indent = WebInspector.settings.textEditorIndent.get(); + var indentLength = indent === WebInspector.TextEditorModel.Indent.TabCharacter ? 4 : indent.length; + var lineIndentRegex = new RegExp("^ {1," + indentLength + "}"); + var newRange = range.clone(); + + for (var lineNumber = range.startLine; lineNumber <= range.endLine; lineNumber++) { + var line = this._textModel.line(lineNumber); + var firstCharacter = line.charAt(0); + var lineIndentLength; + + if (firstCharacter === " ") + lineIndentLength = line.match(lineIndentRegex)[0].length; + else if (firstCharacter === "\t") + lineIndentLength = 1; + else + continue; + + this._textModel.setText(new WebInspector.TextRange(lineNumber, 0, lineNumber, lineIndentLength), ""); + + if (lineNumber === range.startLine) + newRange.startColumn = Math.max(0, newRange.startColumn - lineIndentLength); + } + + if (lineIndentLength) + newRange.endColumn = Math.max(0, newRange.endColumn - lineIndentLength); + + this._lastEditedRange = newRange; + + return newRange; + }, + + handleEnterKey: function() + { + if (this._dirtyLines) + return false; + + var range = this._getSelection(); + if (!range) + return false; + + range.normalize(); + + if (range.endColumn === 0) + return false; + + var line = this._textModel.line(range.startLine); + var linePrefix = line.substring(0, range.startColumn); + var indentMatch = linePrefix.match(/^\s+/); + var currentIndent = indentMatch ? indentMatch[0] : ""; + + var textEditorIndent = WebInspector.settings.textEditorIndent.get(); + var indent = WebInspector.TextEditorModel.endsWithBracketRegex.test(linePrefix) ? currentIndent + textEditorIndent : currentIndent; + + if (!indent) + return false; + + this.beginUpdates(); + this._enterTextChangeMode(); + + var lineBreak = this._textModel.lineBreak; + var newRange; + if (range.isEmpty() && line.substr(range.endColumn - 1, 2) === '{}') { + // {|} + // becomes + // { + // | + // } + newRange = this._setText(range, lineBreak + indent + lineBreak + currentIndent); + newRange.endLine--; + newRange.endColumn += textEditorIndent.length; + } else + newRange = this._setText(range, lineBreak + indent); + + newRange = newRange.collapseToEnd(); + + this._exitTextChangeMode(range, newRange); + this.endUpdates(); + this._restoreSelection(newRange, true); + + return true; + }, + + _splitChunkOnALine: function(lineNumber, chunkNumber, createSuffixChunk) + { + var selection = this._getSelection(); + var chunk = WebInspector.TextEditorChunkedPanel.prototype._splitChunkOnALine.call(this, lineNumber, chunkNumber, createSuffixChunk); + this._restoreSelection(selection); + return chunk; + }, + + beginDomUpdates: function() + { + WebInspector.TextEditorChunkedPanel.prototype.beginDomUpdates.call(this); + if (this._domUpdateCoalescingLevel === 1) { + this._container.removeEventListener("DOMCharacterDataModified", this._handleDOMUpdatesCallback, false); + this._container.removeEventListener("DOMNodeInserted", this._handleDOMUpdatesCallback, false); + this._container.removeEventListener("DOMSubtreeModified", this._handleDOMUpdatesCallback, false); + } + }, + + endDomUpdates: function() + { + WebInspector.TextEditorChunkedPanel.prototype.endDomUpdates.call(this); + if (this._domUpdateCoalescingLevel === 0) { + this._container.addEventListener("DOMCharacterDataModified", this._handleDOMUpdatesCallback, false); + this._container.addEventListener("DOMNodeInserted", this._handleDOMUpdatesCallback, false); + this._container.addEventListener("DOMSubtreeModified", this._handleDOMUpdatesCallback, false); + } + }, + + _enableDOMNodeRemovedListener: function(lineRow, enable) + { + if (enable) + lineRow.addEventListener("DOMNodeRemoved", this._handleDOMUpdatesCallback, false); + else + lineRow.removeEventListener("DOMNodeRemoved", this._handleDOMUpdatesCallback, false); + }, + + _buildChunks: function() + { + for (var i = 0; i < this._textModel.linesCount; ++i) + this._textModel.removeAttribute(i, "highlight"); + + WebInspector.TextEditorChunkedPanel.prototype._buildChunks.call(this); + }, + + _createNewChunk: function(startLine, endLine) + { + return new WebInspector.TextEditorMainChunk(this, startLine, endLine); + }, + + _expandChunks: function(fromIndex, toIndex) + { + var lastChunk = this._textChunks[toIndex - 1]; + var lastVisibleLine = lastChunk.startLine + lastChunk.linesCount; + + var selection = this._getSelection(); + + this._muteHighlightListener = true; + this._highlighter.highlight(lastVisibleLine); + delete this._muteHighlightListener; + + this._restorePaintLinesOperationsCredit(); + WebInspector.TextEditorChunkedPanel.prototype._expandChunks.call(this, fromIndex, toIndex); + this._adjustPaintLinesOperationsRefreshValue(); + + this._restoreSelection(selection); + }, + + _highlightDataReady: function(fromLine, toLine) + { + if (this._muteHighlightListener) + return; + this._restorePaintLinesOperationsCredit(); + this._paintLines(fromLine, toLine, true /*restoreSelection*/); + }, + + _schedulePaintLines: function(startLine, endLine) + { + if (startLine >= endLine) + return; + + if (!this._scheduledPaintLines) { + this._scheduledPaintLines = [ { startLine: startLine, endLine: endLine } ]; + this._paintScheduledLinesTimer = setTimeout(this._paintScheduledLines.bind(this), 0); + } else { + for (var i = 0; i < this._scheduledPaintLines.length; ++i) { + var chunk = this._scheduledPaintLines[i]; + if (chunk.startLine <= endLine && chunk.endLine >= startLine) { + chunk.startLine = Math.min(chunk.startLine, startLine); + chunk.endLine = Math.max(chunk.endLine, endLine); + return; + } + if (chunk.startLine > endLine) { + this._scheduledPaintLines.splice(i, 0, { startLine: startLine, endLine: endLine }); + return; + } + } + this._scheduledPaintLines.push({ startLine: startLine, endLine: endLine }); + } + }, + + _paintScheduledLines: function(skipRestoreSelection) + { + if (this._paintScheduledLinesTimer) + clearTimeout(this._paintScheduledLinesTimer); + delete this._paintScheduledLinesTimer; + + if (!this._scheduledPaintLines) + return; + + // Reschedule the timer if we can not paint the lines yet, or the user is scrolling. + if (this._dirtyLines || this._repaintAllTimer) { + this._paintScheduledLinesTimer = setTimeout(this._paintScheduledLines.bind(this), 50); + return; + } + + var scheduledPaintLines = this._scheduledPaintLines; + delete this._scheduledPaintLines; + + this._restorePaintLinesOperationsCredit(); + this._paintLineChunks(scheduledPaintLines, !skipRestoreSelection); + this._adjustPaintLinesOperationsRefreshValue(); + }, + + _restorePaintLinesOperationsCredit: function() + { + if (!this._paintLinesOperationsRefreshValue) + this._paintLinesOperationsRefreshValue = 250; + this._paintLinesOperationsCredit = this._paintLinesOperationsRefreshValue; + this._paintLinesOperationsLastRefresh = Date.now(); + }, + + _adjustPaintLinesOperationsRefreshValue: function() + { + var operationsDone = this._paintLinesOperationsRefreshValue - this._paintLinesOperationsCredit; + if (operationsDone <= 0) + return; + var timePast = Date.now() - this._paintLinesOperationsLastRefresh; + if (timePast <= 0) + return; + // Make the synchronous CPU chunk for painting the lines 50 msec. + var value = Math.floor(operationsDone / timePast * 50); + this._paintLinesOperationsRefreshValue = Number.constrain(value, 150, 1500); + }, + + /** + * @param {boolean=} restoreSelection + */ + _paintLines: function(fromLine, toLine, restoreSelection) + { + this._paintLineChunks([ { startLine: fromLine, endLine: toLine } ], restoreSelection); + }, + + _paintLineChunks: function(lineChunks, restoreSelection) + { + // First, paint visible lines, so that in case of long lines we should start highlighting + // the visible area immediately, instead of waiting for the lines above the visible area. + var visibleFrom = this.element.scrollTop; + var firstVisibleLineNumber = this._findFirstVisibleLineNumber(visibleFrom); + + var chunk; + var selection; + var invisibleLineRows = []; + for (var i = 0; i < lineChunks.length; ++i) { + var lineChunk = lineChunks[i]; + if (this._dirtyLines || this._scheduledPaintLines) { + this._schedulePaintLines(lineChunk.startLine, lineChunk.endLine); + continue; + } + for (var lineNumber = lineChunk.startLine; lineNumber < lineChunk.endLine; ++lineNumber) { + if (!chunk || lineNumber < chunk.startLine || lineNumber >= chunk.startLine + chunk.linesCount) + chunk = this.chunkForLine(lineNumber); + var lineRow = chunk.getExpandedLineRow(lineNumber); + if (!lineRow) + continue; + if (lineNumber < firstVisibleLineNumber) { + invisibleLineRows.push(lineRow); + continue; + } + if (restoreSelection && !selection) + selection = this._getSelection(); + this._paintLine(lineRow); + if (this._paintLinesOperationsCredit < 0) { + this._schedulePaintLines(lineNumber + 1, lineChunk.endLine); + break; + } + } + } + + for (var i = 0; i < invisibleLineRows.length; ++i) { + if (restoreSelection && !selection) + selection = this._getSelection(); + this._paintLine(invisibleLineRows[i]); + } + + if (restoreSelection) + this._restoreSelection(selection); + }, + + _paintLine: function(lineRow) + { + var lineNumber = lineRow.lineNumber; + if (this._dirtyLines) { + this._schedulePaintLines(lineNumber, lineNumber + 1); + return; + } + + this.beginDomUpdates(); + try { + if (this._scheduledPaintLines || this._paintLinesOperationsCredit < 0) { + this._schedulePaintLines(lineNumber, lineNumber + 1); + return; + } + + var highlight = this._textModel.getAttribute(lineNumber, "highlight"); + if (!highlight) + return; + + lineRow.removeChildren(); + var line = this._textModel.line(lineNumber); + if (!line) + lineRow.appendChild(document.createElement("br")); + + var plainTextStart = -1; + for (var j = 0; j < line.length;) { + if (j > 1000) { + // This line is too long - do not waste cycles on minified js highlighting. + if (plainTextStart === -1) + plainTextStart = j; + break; + } + var attribute = highlight[j]; + if (!attribute || !attribute.tokenType) { + if (plainTextStart === -1) + plainTextStart = j; + j++; + } else { + if (plainTextStart !== -1) { + this._appendTextNode(lineRow, line.substring(plainTextStart, j)); + plainTextStart = -1; + --this._paintLinesOperationsCredit; + } + this._appendSpan(lineRow, line.substring(j, j + attribute.length), attribute.tokenType); + j += attribute.length; + --this._paintLinesOperationsCredit; + } + } + if (plainTextStart !== -1) { + this._appendTextNode(lineRow, line.substring(plainTextStart, line.length)); + --this._paintLinesOperationsCredit; + } + if (lineRow.decorationsElement) + lineRow.appendChild(lineRow.decorationsElement); + } finally { + if (this._rangeToMark && this._rangeToMark.startLine === lineNumber) + this._markedRangeElement = highlightSearchResult(lineRow, this._rangeToMark.startColumn, this._rangeToMark.endColumn - this._rangeToMark.startColumn); + this.endDomUpdates(); + } + }, + + _releaseLinesHighlight: function(lineRow) + { + if (!lineRow) + return; + if ("spans" in lineRow) { + var spans = lineRow.spans; + for (var j = 0; j < spans.length; ++j) + this._cachedSpans.push(spans[j]); + delete lineRow.spans; + } + if ("textNodes" in lineRow) { + var textNodes = lineRow.textNodes; + for (var j = 0; j < textNodes.length; ++j) + this._cachedTextNodes.push(textNodes[j]); + delete lineRow.textNodes; + } + this._cachedRows.push(lineRow); + }, + + _getSelection: function() + { + var selection = window.getSelection(); + if (!selection.rangeCount) + return null; + // Selection may be outside of the viewer. + if (!this._container.isAncestor(selection.anchorNode) || !this._container.isAncestor(selection.focusNode)) + return null; + var start = this._selectionToPosition(selection.anchorNode, selection.anchorOffset); + var end = selection.isCollapsed ? start : this._selectionToPosition(selection.focusNode, selection.focusOffset); + return new WebInspector.TextRange(start.line, start.column, end.line, end.column); + }, + + /** + * @param {boolean=} scrollIntoView + */ + _restoreSelection: function(range, scrollIntoView) + { + if (!range) + return; + var start = this._positionToSelection(range.startLine, range.startColumn); + var end = range.isEmpty() ? start : this._positionToSelection(range.endLine, range.endColumn); + window.getSelection().setBaseAndExtent(start.container, start.offset, end.container, end.offset); + + if (scrollIntoView) { + for (var node = end.container; node; node = node.parentElement) { + if (node.scrollIntoViewIfNeeded) { + node.scrollIntoViewIfNeeded(); + break; + } + } + } + }, + + _setCaretLocation: function(line, column, scrollIntoView) + { + var range = new WebInspector.TextRange(line, column, line, column); + this._restoreSelection(range, scrollIntoView); + }, + + _selectionToPosition: function(container, offset) + { + if (container === this._container && offset === 0) + return { line: 0, column: 0 }; + if (container === this._container && offset === 1) + return { line: this._textModel.linesCount - 1, column: this._textModel.lineLength(this._textModel.linesCount - 1) }; + + var lineRow = this._enclosingLineRowOrSelf(container); + var lineNumber = lineRow.lineNumber; + if (container === lineRow && offset === 0) + return { line: lineNumber, column: 0 }; + + // This may be chunk and chunks may contain \n. + var column = 0; + var node = lineRow.nodeType === Node.TEXT_NODE ? lineRow : lineRow.traverseNextTextNode(lineRow); + while (node && node !== container) { + var text = node.textContent; + for (var i = 0; i < text.length; ++i) { + if (text.charAt(i) === "\n") { + lineNumber++; + column = 0; + } else + column++; + } + node = node.traverseNextTextNode(lineRow); + } + + if (node === container && offset) { + var text = node.textContent; + for (var i = 0; i < offset; ++i) { + if (text.charAt(i) === "\n") { + lineNumber++; + column = 0; + } else + column++; + } + } + return { line: lineNumber, column: column }; + }, + + _positionToSelection: function(line, column) + { + var chunk = this.chunkForLine(line); + // One-lined collapsed chunks may still stay highlighted. + var lineRow = chunk.linesCount === 1 ? chunk.element : chunk.getExpandedLineRow(line); + if (lineRow) + var rangeBoundary = lineRow.rangeBoundaryForOffset(column); + else { + var offset = column; + for (var i = chunk.startLine; i < line; ++i) + offset += this._textModel.lineLength(i) + 1; // \n + lineRow = chunk.element; + if (lineRow.firstChild) + var rangeBoundary = { container: lineRow.firstChild, offset: offset }; + else + var rangeBoundary = { container: lineRow, offset: 0 }; + } + return rangeBoundary; + }, + + _enclosingLineRowOrSelf: function(element) + { + var lineRow = element.enclosingNodeOrSelfWithClass("webkit-line-content"); + if (lineRow) + return lineRow; + + for (lineRow = element; lineRow; lineRow = lineRow.parentElement) { + if (lineRow.parentElement === this._container) + return lineRow; + } + return null; + }, + + _appendSpan: function(element, content, className) + { + if (className === "html-resource-link" || className === "html-external-link") { + element.appendChild(this._createLink(content, className === "html-external-link")); + return; + } + + var span = this._cachedSpans.pop() || document.createElement("span"); + span.className = "webkit-" + className; + span.textContent = content; + element.appendChild(span); + if (!("spans" in element)) + element.spans = []; + element.spans.push(span); + }, + + _appendTextNode: function(element, text) + { + var textNode = this._cachedTextNodes.pop(); + if (textNode) + textNode.nodeValue = text; + else + textNode = document.createTextNode(text); + element.appendChild(textNode); + if (!("textNodes" in element)) + element.textNodes = []; + element.textNodes.push(textNode); + }, + + _createLink: function(content, isExternal) + { + var quote = content.charAt(0); + if (content.length > 1 && (quote === "\"" || quote === "'")) + content = content.substring(1, content.length - 1); + else + quote = null; + + var a = WebInspector.linkifyURLAsNode(this._rewriteHref(content), content, undefined, isExternal); + var span = document.createElement("span"); + span.className = "webkit-html-attribute-value"; + if (quote) + span.appendChild(document.createTextNode(quote)); + span.appendChild(a); + if (quote) + span.appendChild(document.createTextNode(quote)); + return span; + }, + + /** + * @param {boolean=} isExternal + */ + _rewriteHref: function(hrefValue, isExternal) + { + if (!this._url || !hrefValue || hrefValue.indexOf("://") > 0) + return hrefValue; + return WebInspector.completeURL(this._url, hrefValue); + }, + + _handleDOMUpdates: function(e) + { + if (this._domUpdateCoalescingLevel) + return; + + var target = e.target; + if (target === this._container) + return; + + var lineRow = this._enclosingLineRowOrSelf(target); + if (!lineRow) + return; + + if (lineRow.decorationsElement && lineRow.decorationsElement.isSelfOrAncestor(target)) { + if (this._syncDecorationsForLineListener) + this._syncDecorationsForLineListener(lineRow.lineNumber); + return; + } + + if (this._readOnly) + return; + + if (target === lineRow && e.type === "DOMNodeInserted") { + // Ensure that the newly inserted line row has no lineNumber. + delete lineRow.lineNumber; + } + + var startLine = 0; + for (var row = lineRow; row; row = row.previousSibling) { + if (typeof row.lineNumber === "number") { + startLine = row.lineNumber; + break; + } + } + + var endLine = startLine + 1; + for (var row = lineRow.nextSibling; row; row = row.nextSibling) { + if (typeof row.lineNumber === "number" && row.lineNumber > startLine) { + endLine = row.lineNumber; + break; + } + } + + if (target === lineRow && e.type === "DOMNodeRemoved") { + // Now this will no longer be valid. + delete lineRow.lineNumber; + } + + if (this._dirtyLines) { + this._dirtyLines.start = Math.min(this._dirtyLines.start, startLine); + this._dirtyLines.end = Math.max(this._dirtyLines.end, endLine); + } else { + this._dirtyLines = { start: startLine, end: endLine }; + setTimeout(this._applyDomUpdates.bind(this), 0); + // Remove marked ranges, if any. + this.markAndRevealRange(null); + } + }, + + _applyDomUpdates: function() + { + if (!this._dirtyLines) + return; + + // Check if the editor had been set readOnly by the moment when this async callback got executed. + if (this._readOnly) { + delete this._dirtyLines; + return; + } + + // This is a "foreign" call outside of this class. Should be before we delete the dirty lines flag. + this._enterTextChangeMode(); + + var dirtyLines = this._dirtyLines; + delete this._dirtyLines; + + var firstChunkNumber = this._chunkNumberForLine(dirtyLines.start); + var startLine = this._textChunks[firstChunkNumber].startLine; + var endLine = this._textModel.linesCount; + + // Collect lines. + var firstLineRow; + if (firstChunkNumber) { + var chunk = this._textChunks[firstChunkNumber - 1]; + firstLineRow = chunk.expanded ? chunk.getExpandedLineRow(chunk.startLine + chunk.linesCount - 1) : chunk.element; + firstLineRow = firstLineRow.nextSibling; + } else + firstLineRow = this._container.firstChild; + + var lines = []; + for (var lineRow = firstLineRow; lineRow; lineRow = lineRow.nextSibling) { + if (typeof lineRow.lineNumber === "number" && lineRow.lineNumber >= dirtyLines.end) { + endLine = lineRow.lineNumber; + break; + } + // Update with the newest lineNumber, so that the call to the _getSelection method below should work. + lineRow.lineNumber = startLine + lines.length; + this._collectLinesFromDiv(lines, lineRow); + } + + // Try to decrease the range being replaced, if possible. + var startOffset = 0; + while (startLine < dirtyLines.start && startOffset < lines.length) { + if (this._textModel.line(startLine) !== lines[startOffset]) + break; + ++startOffset; + ++startLine; + } + + var endOffset = lines.length; + while (endLine > dirtyLines.end && endOffset > startOffset) { + if (this._textModel.line(endLine - 1) !== lines[endOffset - 1]) + break; + --endOffset; + --endLine; + } + + lines = lines.slice(startOffset, endOffset); + + // Try to decrease the range being replaced by column offsets, if possible. + var startColumn = 0; + var endColumn = this._textModel.lineLength(endLine - 1); + if (lines.length > 0) { + var line1 = this._textModel.line(startLine); + var line2 = lines[0]; + while (line1[startColumn] && line1[startColumn] === line2[startColumn]) + ++startColumn; + lines[0] = line2.substring(startColumn); + + line1 = this._textModel.line(endLine - 1); + line2 = lines[lines.length - 1]; + for (var i = 0; i < endColumn && i < line2.length; ++i) { + if (startLine === endLine - 1 && endColumn - i <= startColumn) + break; + if (line1[endColumn - i - 1] !== line2[line2.length - i - 1]) + break; + } + if (i) { + endColumn -= i; + lines[lines.length - 1] = line2.substring(0, line2.length - i); + } + } + + var selection = this._getSelection(); + + if (lines.length === 0 && endLine < this._textModel.linesCount) + var oldRange = new WebInspector.TextRange(startLine, 0, endLine, 0); + else if (lines.length === 0 && startLine > 0) + var oldRange = new WebInspector.TextRange(startLine - 1, this._textModel.lineLength(startLine - 1), endLine - 1, this._textModel.lineLength(endLine - 1)); + else + var oldRange = new WebInspector.TextRange(startLine, startColumn, endLine - 1, endColumn); + + var newRange = this._setText(oldRange, lines.join("\n")); + + this._paintScheduledLines(true); + this._restoreSelection(selection); + + this._exitTextChangeMode(oldRange, newRange); + }, + + textChanged: function(oldRange, newRange) + { + this.beginDomUpdates(); + this._removeDecorationsInRange(oldRange); + this._updateChunksForRanges(oldRange, newRange); + this._updateHighlightsForRange(newRange); + this.endDomUpdates(); + }, + + _setText: function(range, text) + { + if (this._lastEditedRange && (!text || text.indexOf("\n") !== -1 || this._lastEditedRange.endLine !== range.startLine || this._lastEditedRange.endColumn !== range.startColumn)) + this._textModel.markUndoableState(); + + var newRange = this._textModel.setText(range, text); + this._lastEditedRange = newRange; + + return newRange; + }, + + _removeDecorationsInRange: function(range) + { + for (var i = this._chunkNumberForLine(range.startLine); i < this._textChunks.length; ++i) { + var chunk = this._textChunks[i]; + if (chunk.startLine > range.endLine) + break; + chunk.removeAllDecorations(); + } + }, + + _updateChunksForRanges: function(oldRange, newRange) + { + // Update the chunks in range: firstChunkNumber <= index <= lastChunkNumber + var firstChunkNumber = this._chunkNumberForLine(oldRange.startLine); + var lastChunkNumber = firstChunkNumber; + while (lastChunkNumber + 1 < this._textChunks.length) { + if (this._textChunks[lastChunkNumber + 1].startLine > oldRange.endLine) + break; + ++lastChunkNumber; + } + + var startLine = this._textChunks[firstChunkNumber].startLine; + var linesCount = this._textChunks[lastChunkNumber].startLine + this._textChunks[lastChunkNumber].linesCount - startLine; + var linesDiff = newRange.linesCount - oldRange.linesCount; + linesCount += linesDiff; + + if (linesDiff) { + // Lines shifted, update the line numbers of the chunks below. + for (var chunkNumber = lastChunkNumber + 1; chunkNumber < this._textChunks.length; ++chunkNumber) + this._textChunks[chunkNumber].startLine += linesDiff; + } + + var firstLineRow; + if (firstChunkNumber) { + var chunk = this._textChunks[firstChunkNumber - 1]; + firstLineRow = chunk.expanded ? chunk.getExpandedLineRow(chunk.startLine + chunk.linesCount - 1) : chunk.element; + firstLineRow = firstLineRow.nextSibling; + } else + firstLineRow = this._container.firstChild; + + // Most frequent case: a chunk remained the same. + for (var chunkNumber = firstChunkNumber; chunkNumber <= lastChunkNumber; ++chunkNumber) { + var chunk = this._textChunks[chunkNumber]; + if (chunk.startLine + chunk.linesCount > this._textModel.linesCount) + break; + var lineNumber = chunk.startLine; + for (var lineRow = firstLineRow; lineRow && lineNumber < chunk.startLine + chunk.linesCount; lineRow = lineRow.nextSibling) { + if (lineRow.lineNumber !== lineNumber || lineRow !== chunk.getExpandedLineRow(lineNumber) || lineRow.textContent !== this._textModel.line(lineNumber) || !lineRow.firstChild) + break; + ++lineNumber; + } + if (lineNumber < chunk.startLine + chunk.linesCount) + break; + chunk.updateCollapsedLineRow(); + ++firstChunkNumber; + firstLineRow = lineRow; + startLine += chunk.linesCount; + linesCount -= chunk.linesCount; + } + + if (firstChunkNumber > lastChunkNumber && linesCount === 0) + return; + + // Maybe merge with the next chunk, so that we should not create 1-sized chunks when appending new lines one by one. + var chunk = this._textChunks[lastChunkNumber + 1]; + var linesInLastChunk = linesCount % this._defaultChunkSize; + if (chunk && !chunk.decorated && linesInLastChunk > 0 && linesInLastChunk + chunk.linesCount <= this._defaultChunkSize) { + ++lastChunkNumber; + linesCount += chunk.linesCount; + } + + var scrollTop = this.element.scrollTop; + var scrollLeft = this.element.scrollLeft; + + // Delete all DOM elements that were either controlled by the old chunks, or have just been inserted. + var firstUnmodifiedLineRow = null; + chunk = this._textChunks[lastChunkNumber + 1]; + if (chunk) + firstUnmodifiedLineRow = chunk.expanded ? chunk.getExpandedLineRow(chunk.startLine) : chunk.element; + + while (firstLineRow && firstLineRow !== firstUnmodifiedLineRow) { + var lineRow = firstLineRow; + firstLineRow = firstLineRow.nextSibling; + this._container.removeChild(lineRow); + } + + // Replace old chunks with the new ones. + for (var chunkNumber = firstChunkNumber; linesCount > 0; ++chunkNumber) { + var chunkLinesCount = Math.min(this._defaultChunkSize, linesCount); + var newChunk = this._createNewChunk(startLine, startLine + chunkLinesCount); + this._container.insertBefore(newChunk.element, firstUnmodifiedLineRow); + + if (chunkNumber <= lastChunkNumber) + this._textChunks[chunkNumber] = newChunk; + else + this._textChunks.splice(chunkNumber, 0, newChunk); + startLine += chunkLinesCount; + linesCount -= chunkLinesCount; + } + if (chunkNumber <= lastChunkNumber) + this._textChunks.splice(chunkNumber, lastChunkNumber - chunkNumber + 1); + + this.element.scrollTop = scrollTop; + this.element.scrollLeft = scrollLeft; + }, + + _updateHighlightsForRange: function(range) + { + var visibleFrom = this.element.scrollTop; + var visibleTo = this.element.scrollTop + this.element.clientHeight; + + var result = this._findVisibleChunks(visibleFrom, visibleTo); + var chunk = this._textChunks[result.end - 1]; + var lastVisibleLine = chunk.startLine + chunk.linesCount; + + lastVisibleLine = Math.max(lastVisibleLine, range.endLine + 1); + lastVisibleLine = Math.min(lastVisibleLine, this._textModel.linesCount); + + var updated = this._highlighter.updateHighlight(range.startLine, lastVisibleLine); + if (!updated) { + // Highlights for the chunks below are invalid, so just collapse them. + for (var i = this._chunkNumberForLine(range.startLine); i < this._textChunks.length; ++i) + this._textChunks[i].expanded = false; + } + + this._repaintAll(); + }, + + _collectLinesFromDiv: function(lines, element) + { + var textContents = []; + var node = element.nodeType === Node.TEXT_NODE ? element : element.traverseNextNode(element); + while (node) { + if (element.decorationsElement === node) { + node = node.nextSibling; + continue; + } + if (node.nodeName.toLowerCase() === "br") + textContents.push("\n"); + else if (node.nodeType === Node.TEXT_NODE) + textContents.push(node.textContent); + node = node.traverseNextNode(element); + } + + var textContent = textContents.join(""); + // The last \n (if any) does not "count" in a DIV. + textContent = textContent.replace(/\n$/, ""); + + textContents = textContent.split("\n"); + for (var i = 0; i < textContents.length; ++i) + lines.push(textContents[i]); + } +} + +WebInspector.TextEditorMainPanel.prototype.__proto__ = WebInspector.TextEditorChunkedPanel.prototype; + +/** + * @constructor + */ +WebInspector.TextEditorMainChunk = function(textViewer, startLine, endLine) +{ + this._textViewer = textViewer; + this._textModel = textViewer._textModel; + + this.element = document.createElement("div"); + this.element.lineNumber = startLine; + this.element.className = "webkit-line-content"; + this._textViewer._enableDOMNodeRemovedListener(this.element, true); + + this._startLine = startLine; + endLine = Math.min(this._textModel.linesCount, endLine); + this.linesCount = endLine - startLine; + + this._expanded = false; + this._readOnly = false; + + this.updateCollapsedLineRow(); +} + +WebInspector.TextEditorMainChunk.prototype = { + addDecoration: function(decoration) + { + this._textViewer.beginDomUpdates(); + if (typeof decoration === "string") + this.element.addStyleClass(decoration); + else { + if (!this.element.decorationsElement) { + this.element.decorationsElement = document.createElement("div"); + this.element.decorationsElement.className = "webkit-line-decorations"; + this.element.appendChild(this.element.decorationsElement); + } + this.element.decorationsElement.appendChild(decoration); + } + this._textViewer.endDomUpdates(); + }, + + removeDecoration: function(decoration) + { + this._textViewer.beginDomUpdates(); + if (typeof decoration === "string") + this.element.removeStyleClass(decoration); + else if (this.element.decorationsElement) + this.element.decorationsElement.removeChild(decoration); + this._textViewer.endDomUpdates(); + }, + + removeAllDecorations: function() + { + this._textViewer.beginDomUpdates(); + this.element.className = "webkit-line-content"; + if (this.element.decorationsElement) { + this.element.removeChild(this.element.decorationsElement); + delete this.element.decorationsElement; + } + this._textViewer.endDomUpdates(); + }, + + get decorated() + { + return this.element.className !== "webkit-line-content" || !!(this.element.decorationsElement && this.element.decorationsElement.firstChild); + }, + + get startLine() + { + return this._startLine; + }, + + set startLine(startLine) + { + this._startLine = startLine; + this.element.lineNumber = startLine; + if (this._expandedLineRows) { + for (var i = 0; i < this._expandedLineRows.length; ++i) + this._expandedLineRows[i].lineNumber = startLine + i; + } + }, + + get expanded() + { + return this._expanded; + }, + + set expanded(expanded) + { + if (this._expanded === expanded) + return; + + this._expanded = expanded; + + if (this.linesCount === 1) { + if (expanded) + this._textViewer._paintLine(this.element); + return; + } + + this._textViewer.beginDomUpdates(); + + if (expanded) { + this._expandedLineRows = []; + var parentElement = this.element.parentElement; + for (var i = this.startLine; i < this.startLine + this.linesCount; ++i) { + var lineRow = this._createRow(i); + this._textViewer._enableDOMNodeRemovedListener(lineRow, true); + this._updateElementReadOnlyState(lineRow); + parentElement.insertBefore(lineRow, this.element); + this._expandedLineRows.push(lineRow); + } + this._textViewer._enableDOMNodeRemovedListener(this.element, false); + parentElement.removeChild(this.element); + this._textViewer._paintLines(this.startLine, this.startLine + this.linesCount); + } else { + var elementInserted = false; + for (var i = 0; i < this._expandedLineRows.length; ++i) { + var lineRow = this._expandedLineRows[i]; + this._textViewer._enableDOMNodeRemovedListener(lineRow, false); + var parentElement = lineRow.parentElement; + if (parentElement) { + if (!elementInserted) { + elementInserted = true; + this._textViewer._enableDOMNodeRemovedListener(this.element, true); + parentElement.insertBefore(this.element, lineRow); + } + parentElement.removeChild(lineRow); + } + this._textViewer._releaseLinesHighlight(lineRow); + } + delete this._expandedLineRows; + } + + this._textViewer.endDomUpdates(); + }, + + set readOnly(readOnly) + { + if (this._readOnly === readOnly) + return; + + this._readOnly = readOnly; + this._updateElementReadOnlyState(this.element); + if (this._expandedLineRows) { + for (var i = 0; i < this._expandedLineRows.length; ++i) + this._updateElementReadOnlyState(this._expandedLineRows[i]); + } + }, + + get readOnly() + { + return this._readOnly; + }, + + _updateElementReadOnlyState: function(element) + { + if (this._readOnly) + element.addStyleClass("text-editor-read-only"); + else + element.removeStyleClass("text-editor-read-only"); + }, + + get height() + { + if (!this._expandedLineRows) + return this._textViewer._totalHeight(this.element); + return this._textViewer._totalHeight(this._expandedLineRows[0], this._expandedLineRows[this._expandedLineRows.length - 1]); + }, + + get offsetTop() + { + return (this._expandedLineRows && this._expandedLineRows.length) ? this._expandedLineRows[0].offsetTop : this.element.offsetTop; + }, + + _createRow: function(lineNumber) + { + var lineRow = this._textViewer._cachedRows.pop() || document.createElement("div"); + lineRow.lineNumber = lineNumber; + lineRow.className = "webkit-line-content"; + lineRow.textContent = this._textModel.line(lineNumber); + if (!lineRow.textContent) + lineRow.appendChild(document.createElement("br")); + return lineRow; + }, + + getExpandedLineRow: function(lineNumber) + { + if (!this._expanded || lineNumber < this.startLine || lineNumber >= this.startLine + this.linesCount) + return null; + if (!this._expandedLineRows) + return this.element; + return this._expandedLineRows[lineNumber - this.startLine]; + }, + + updateCollapsedLineRow: function() + { + if (this.linesCount === 1 && this._expanded) + return; + + var lines = []; + for (var i = this.startLine; i < this.startLine + this.linesCount; ++i) + lines.push(this._textModel.line(i)); + + this.element.removeChildren(); + this.element.textContent = lines.join("\n"); + + // The last empty line will get swallowed otherwise. + if (!lines[lines.length - 1]) + this.element.appendChild(document.createElement("br")); + } +} +/* SourceFrame.js */ + +/* + * Copyright (C) 2011 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. + */ + +/** + * @extends {WebInspector.View} + * @constructor + */ +WebInspector.SourceFrame = function(url) +{ + WebInspector.View.call(this); + this.element.addStyleClass("script-view"); + + this._url = url; + + this._textModel = new WebInspector.TextEditorModel(); + + var textViewerDelegate = new WebInspector.TextViewerDelegateForSourceFrame(this); + this._textViewer = new WebInspector.TextViewer(this._textModel, WebInspector.platform(), this._url, textViewerDelegate); + + this._editButton = new WebInspector.StatusBarButton(WebInspector.UIString("Edit"), "edit-source-status-bar-item"); + this._editButton.addEventListener("click", this._editButtonClicked.bind(this), this); + + this._currentSearchResultIndex = -1; + this._searchResults = []; + + this._messages = []; + this._rowMessages = {}; + this._messageBubbles = {}; + + if (WebInspector.experimentsSettings.sourceFrameAlwaysEditable.isEnabled()) + this.startEditing(); +} + +WebInspector.SourceFrame.Events = { + Loaded: "loaded" +} + +WebInspector.SourceFrame.createSearchRegex = function(query) +{ + var regex; + + // First try creating regex if user knows the / / hint. + try { + if (/^\/.*\/$/.test(query)) + regex = new RegExp(query.substring(1, query.length - 1)); + } catch (e) { + // Silent catch. + } + + // Otherwise just do case-insensitive search. + if (!regex) + regex = createPlainTextSearchRegex(query, "i"); + + return regex; +} + +WebInspector.SourceFrame.prototype = { + wasShown: function() + { + this._ensureContentLoaded(); + this._textViewer.show(this.element); + if (this._wasHiddenWhileEditing) + this.setReadOnly(false); + }, + + willHide: function() + { + WebInspector.View.prototype.willHide.call(this); + if (this.loaded) + this._textViewer.freeCachedElements(); + + this._clearLineHighlight(); + if (!this._textViewer.readOnly) + this._wasHiddenWhileEditing = true; + this.setReadOnly(true); + }, + + focus: function() + { + this._textViewer.focus(); + }, + + get statusBarItems() + { + return WebInspector.experimentsSettings.sourceFrameAlwaysEditable.isEnabled() ? [] : [this._editButton.element]; + }, + + get loaded() + { + return this._loaded; + }, + + hasContent: function() + { + return true; + }, + + get textViewer() + { + return this._textViewer; + }, + + _ensureContentLoaded: function() + { + if (!this._contentRequested) { + this._contentRequested = true; + this.requestContent(this.setContent.bind(this)); + } + }, + + requestContent: function(callback) + { + }, + + /** + * @param {TextDiff} diffData + */ + markDiff: function(diffData) + { + if (this._diffLines && this.loaded) + this._removeDiffDecorations(); + + this._diffLines = diffData; + if (this.loaded) + this._updateDiffDecorations(); + }, + + addMessage: function(msg) + { + this._messages.push(msg); + if (this.loaded) + this.addMessageToSource(msg.line - 1, msg); + }, + + clearMessages: function() + { + for (var line in this._messageBubbles) { + var bubble = this._messageBubbles[line]; + bubble.parentNode.removeChild(bubble); + } + + this._messages = []; + this._rowMessages = {}; + this._messageBubbles = {}; + + this._textViewer.doResize(); + }, + + get textModel() + { + return this._textModel; + }, + + canHighlightLine: function(line) + { + return true; + }, + + highlightLine: function(line) + { + if (this.loaded) + this._textViewer.highlightLine(line); + else + this._lineToHighlight = line; + }, + + _clearLineHighlight: function() + { + if (this.loaded) + this._textViewer.clearLineHighlight(); + else + delete this._lineToHighlight; + }, + + _saveViewerState: function() + { + this._viewerState = { + textModelContent: this._textModel.text, + messages: this._messages, + diffLines: this._diffLines, + }; + }, + + _restoreViewerState: function() + { + if (!this._viewerState) + return; + this._textModel.setText(null, this._viewerState.textModelContent); + + this._messages = this._viewerState.messages; + this._diffLines = this._viewerState.diffLines; + this._setTextViewerDecorations(); + + delete this._viewerState; + }, + + beforeTextChanged: function() + { + if (!this._viewerState) + this._saveViewerState(); + + WebInspector.searchController.cancelSearch(); + this.clearMessages(); + }, + + afterTextChanged: function(oldRange, newRange) + { + }, + + setContent: function(mimeType, content) + { + this._textViewer.mimeType = mimeType; + + this._loaded = true; + this._textModel.setText(null, content); + + this._textViewer.beginUpdates(); + + this._setTextViewerDecorations(); + + if (typeof this._lineToHighlight === "number") { + this.highlightLine(this._lineToHighlight); + delete this._lineToHighlight; + } + + if (this._delayedFindSearchMatches) { + this._delayedFindSearchMatches(); + delete this._delayedFindSearchMatches; + } + + this.dispatchEventToListeners(WebInspector.SourceFrame.Events.Loaded); + + this._textViewer.endUpdates(); + + if (!this.canEditSource()) + this._editButton.disabled = true; + }, + + _setTextViewerDecorations: function() + { + this._rowMessages = {}; + this._messageBubbles = {}; + + this._textViewer.beginUpdates(); + + this._addExistingMessagesToSource(); + this._updateDiffDecorations(); + + this._textViewer.doResize(); + + this._textViewer.endUpdates(); + }, + + performSearch: function(query, callback) + { + // Call searchCanceled since it will reset everything we need before doing a new search. + this.searchCanceled(); + + function doFindSearchMatches(query) + { + this._currentSearchResultIndex = -1; + this._searchResults = []; + + var regex = WebInspector.SourceFrame.createSearchRegex(query); + this._searchResults = this._collectRegexMatches(regex); + + callback(this, this._searchResults.length); + } + + if (this.loaded) + doFindSearchMatches.call(this, query); + else + this._delayedFindSearchMatches = doFindSearchMatches.bind(this, query); + + this._ensureContentLoaded(); + }, + + searchCanceled: function() + { + delete this._delayedFindSearchMatches; + if (!this.loaded) + return; + + this._currentSearchResultIndex = -1; + this._searchResults = []; + this._textViewer.markAndRevealRange(null); + }, + + hasSearchResults: function() + { + return this._searchResults.length > 0; + }, + + jumpToFirstSearchResult: function() + { + this.jumpToSearchResult(0); + }, + + jumpToLastSearchResult: function() + { + this.jumpToSearchResult(this._searchResults.length - 1); + }, + + jumpToNextSearchResult: function() + { + this.jumpToSearchResult(this._currentSearchResultIndex + 1); + }, + + jumpToPreviousSearchResult: function() + { + this.jumpToSearchResult(this._currentSearchResultIndex - 1); + }, + + showingFirstSearchResult: function() + { + return this._searchResults.length && this._currentSearchResultIndex === 0; + }, + + showingLastSearchResult: function() + { + return this._searchResults.length && this._currentSearchResultIndex === (this._searchResults.length - 1); + }, + + get currentSearchResultIndex() + { + return this._currentSearchResultIndex; + }, + + jumpToSearchResult: function(index) + { + if (!this.loaded || !this._searchResults.length) + return; + this._currentSearchResultIndex = (index + this._searchResults.length) % this._searchResults.length; + this._textViewer.markAndRevealRange(this._searchResults[this._currentSearchResultIndex]); + }, + + _collectRegexMatches: function(regexObject) + { + var ranges = []; + for (var i = 0; i < this._textModel.linesCount; ++i) { + var line = this._textModel.line(i); + var offset = 0; + do { + var match = regexObject.exec(line); + if (match) { + if (match[0].length) + ranges.push(new WebInspector.TextRange(i, offset + match.index, i, offset + match.index + match[0].length)); + offset += match.index + 1; + line = line.substring(match.index + 1); + } + } while (match && line); + } + return ranges; + }, + + _updateDiffDecorations: function() + { + if (!this._diffLines) + return; + + function addDecorations(textViewer, lines, className) + { + for (var i = 0; i < lines.length; ++i) + textViewer.addDecoration(lines[i], className); + } + addDecorations(this._textViewer, this._diffLines.added, "webkit-added-line"); + addDecorations(this._textViewer, this._diffLines.removed, "webkit-removed-line"); + addDecorations(this._textViewer, this._diffLines.changed, "webkit-changed-line"); + }, + + _removeDiffDecorations: function() + { + function removeDecorations(textViewer, lines, className) + { + for (var i = 0; i < lines.length; ++i) + textViewer.removeDecoration(lines[i], className); + } + removeDecorations(this._textViewer, this._diffLines.added, "webkit-added-line"); + removeDecorations(this._textViewer, this._diffLines.removed, "webkit-removed-line"); + removeDecorations(this._textViewer, this._diffLines.changed, "webkit-changed-line"); + }, + + _addExistingMessagesToSource: function() + { + var length = this._messages.length; + for (var i = 0; i < length; ++i) + this.addMessageToSource(this._messages[i].line - 1, this._messages[i]); + }, + + addMessageToSource: function(lineNumber, msg) + { + if (lineNumber >= this._textModel.linesCount) + lineNumber = this._textModel.linesCount - 1; + if (lineNumber < 0) + lineNumber = 0; + + var messageBubbleElement = this._messageBubbles[lineNumber]; + if (!messageBubbleElement || messageBubbleElement.nodeType !== Node.ELEMENT_NODE || !messageBubbleElement.hasStyleClass("webkit-html-message-bubble")) { + messageBubbleElement = document.createElement("div"); + messageBubbleElement.className = "webkit-html-message-bubble"; + this._messageBubbles[lineNumber] = messageBubbleElement; + this._textViewer.addDecoration(lineNumber, messageBubbleElement); + } + + var rowMessages = this._rowMessages[lineNumber]; + if (!rowMessages) { + rowMessages = []; + this._rowMessages[lineNumber] = rowMessages; + } + + for (var i = 0; i < rowMessages.length; ++i) { + if (rowMessages[i].consoleMessage.isEqual(msg)) { + rowMessages[i].repeatCount = msg.totalRepeatCount; + this._updateMessageRepeatCount(rowMessages[i]); + return; + } + } + + var rowMessage = { consoleMessage: msg }; + rowMessages.push(rowMessage); + + var imageURL; + switch (msg.level) { + case WebInspector.ConsoleMessage.MessageLevel.Error: + messageBubbleElement.addStyleClass("webkit-html-error-message"); + imageURL = "Images/errorIcon.png"; + break; + case WebInspector.ConsoleMessage.MessageLevel.Warning: + messageBubbleElement.addStyleClass("webkit-html-warning-message"); + imageURL = "Images/warningIcon.png"; + break; + } + + var messageLineElement = document.createElement("div"); + messageLineElement.className = "webkit-html-message-line"; + messageBubbleElement.appendChild(messageLineElement); + + // Create the image element in the Inspector's document so we can use relative image URLs. + var image = document.createElement("img"); + image.src = imageURL; + image.className = "webkit-html-message-icon"; + messageLineElement.appendChild(image); + messageLineElement.appendChild(document.createTextNode(msg.message)); + + rowMessage.element = messageLineElement; + rowMessage.repeatCount = msg.totalRepeatCount; + this._updateMessageRepeatCount(rowMessage); + }, + + _updateMessageRepeatCount: function(rowMessage) + { + if (rowMessage.repeatCount < 2) + return; + + if (!rowMessage.repeatCountElement) { + var repeatCountElement = document.createElement("span"); + rowMessage.element.appendChild(repeatCountElement); + rowMessage.repeatCountElement = repeatCountElement; + } + + rowMessage.repeatCountElement.textContent = WebInspector.UIString(" (repeated %d times)", rowMessage.repeatCount); + }, + + populateLineGutterContextMenu: function(contextMenu, lineNumber) + { + }, + + populateTextAreaContextMenu: function(contextMenu, lineNumber) + { + if (!window.getSelection().isCollapsed) + return; + WebInspector.populateResourceContextMenu(contextMenu, this._url, lineNumber); + }, + + suggestedFileName: function() + { + }, + + inheritScrollPositions: function(sourceFrame) + { + this._textViewer.inheritScrollPositions(sourceFrame._textViewer); + }, + + _editButtonClicked: function() + { + if (!this.canEditSource()) + return; + + const shouldStartEditing = !this._editButton.toggled; + if (shouldStartEditing) + this.startEditing(); + else + this.commitEditing(); + }, + + canEditSource: function() + { + return false; + }, + + startEditing: function() + { + if (!this.canEditSource()) + return false; + + if (this._commitEditingInProgress) + return false; + + this.setReadOnly(false); + return true; + }, + + commitEditing: function() + { + if (!this._viewerState) { + // No editing was actually done. + this.setReadOnly(true); + return; + } + + this._commitEditingInProgress = true; + this._textViewer.readOnly = true; + this._editButton.toggled = false; + this.editContent(this._textModel.text, this.didEditContent.bind(this)); + }, + + didEditContent: function(error) + { + this._commitEditingInProgress = false; + this._textViewer.readOnly = false; + + if (error) { + if (error.message) + WebInspector.log(error.message, WebInspector.ConsoleMessage.MessageLevel.Error, true); + return; + } + + delete this._viewerState; + }, + + editContent: function(newContent, callback) + { + }, + + cancelEditing: function() + { + if (WebInspector.experimentsSettings.sourceFrameAlwaysEditable.isEnabled()) + return false; + + this._restoreViewerState(); + this.setReadOnly(true); + return true; + }, + + get readOnly() + { + return this._textViewer.readOnly; + }, + + setReadOnly: function(readOnly) + { + if (readOnly && WebInspector.experimentsSettings.sourceFrameAlwaysEditable.isEnabled()) + return; + this._textViewer.readOnly = readOnly; + this._editButton.toggled = !readOnly; + } +} + +WebInspector.SourceFrame.prototype.__proto__ = WebInspector.View.prototype; + + +/** + * @implements {WebInspector.TextViewerDelegate} + * @constructor + */ +WebInspector.TextViewerDelegateForSourceFrame = function(sourceFrame) +{ + this._sourceFrame = sourceFrame; +} + +WebInspector.TextViewerDelegateForSourceFrame.prototype = { + doubleClick: function(lineNumber) + { + this._sourceFrame.startEditing(lineNumber); + }, + + beforeTextChanged: function() + { + this._sourceFrame.beforeTextChanged(); + }, + + afterTextChanged: function(oldRange, newRange) + { + this._sourceFrame.afterTextChanged(oldRange, newRange); + }, + + commitEditing: function() + { + this._sourceFrame.commitEditing(); + }, + + cancelEditing: function() + { + return this._sourceFrame.cancelEditing(); + }, + + populateLineGutterContextMenu: function(contextMenu, lineNumber) + { + this._sourceFrame.populateLineGutterContextMenu(contextMenu, lineNumber); + }, + + populateTextAreaContextMenu: function(contextMenu, lineNumber) + { + this._sourceFrame.populateTextAreaContextMenu(contextMenu, lineNumber); + }, + + suggestedFileName: function() + { + return this._sourceFrame.suggestedFileName(); + } +} + +WebInspector.TextViewerDelegateForSourceFrame.prototype.__proto__ = WebInspector.TextViewerDelegate.prototype; +/* ResourceView.js */ + +/* + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) IBM Corp. 2009 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. + */ + +/** + * @extends {WebInspector.View} + * @constructor + */ +WebInspector.ResourceView = function(resource) +{ + WebInspector.View.call(this); + this.registerRequiredCSS("resourceView.css"); + + this.element.addStyleClass("resource-view"); + this.resource = resource; +} + +WebInspector.ResourceView.prototype = { + hasContent: function() + { + return false; + } +} + +WebInspector.ResourceView.prototype.__proto__ = WebInspector.View.prototype; + +WebInspector.ResourceView.hasTextContent = function(resource) +{ + switch (resource.category) { + case WebInspector.resourceCategories.documents: + case WebInspector.resourceCategories.scripts: + case WebInspector.resourceCategories.xhr: + case WebInspector.resourceCategories.stylesheets: + return true; + case WebInspector.resourceCategories.other: + return resource.content && !resource.contentEncoded; + default: + return false; + } +} + +WebInspector.ResourceView.nonSourceViewForResource = function(resource) +{ + switch (resource.category) { + case WebInspector.resourceCategories.images: + return new WebInspector.ImageView(resource); + case WebInspector.resourceCategories.fonts: + return new WebInspector.FontView(resource); + default: + return new WebInspector.ResourceView(resource); + } +} + +/** + * @extends {WebInspector.SourceFrame} + * @constructor + */ +WebInspector.ResourceSourceFrame = function(resource) +{ + this._resource = resource; + WebInspector.SourceFrame.call(this, resource.url); +} + +//This is a map from resource.type to mime types +//found in WebInspector.SourceTokenizer.Registry. +WebInspector.ResourceSourceFrame.DefaultMIMETypeForResourceType = { + 0: "text/html", + 1: "text/css", + 4: "text/javascript" +} + +WebInspector.ResourceSourceFrame.mimeTypeForResource = function(resource) { + return WebInspector.ResourceSourceFrame.DefaultMIMETypeForResourceType[resource.type] || resource.mimeType; +} + +WebInspector.ResourceSourceFrame.prototype = { + get resource() + { + return this._resource; + }, + + requestContent: function(callback) + { + function contentLoaded(text) + { + var mimeType = WebInspector.ResourceSourceFrame.mimeTypeForResource(this.resource); + callback(mimeType, text); + } + + this.resource.requestContent(contentLoaded.bind(this)); + }, + + suggestedFileName: function() + { + return this.resource.displayName; + } +} + +WebInspector.ResourceSourceFrame.prototype.__proto__ = WebInspector.SourceFrame.prototype; + +/** + * @constructor + * @extends {WebInspector.ResourceSourceFrame} + */ +WebInspector.EditableResourceSourceFrame = function(resource) +{ + WebInspector.ResourceSourceFrame.call(this, resource); +} + +WebInspector.EditableResourceSourceFrame.prototype = { + canEditSource: function() + { + return this.resource.isEditable() && !this._commitEditingInProgress; + }, + + editContent: function(newText, callback) + { + this._clearIncrementalUpdateTimer(); + var majorChange = true; + this.resource.setContent(newText, majorChange, callback); + }, + + cancelEditing: function() + { + if (WebInspector.experimentsSettings.sourceFrameAlwaysEditable.isEnabled()) + return false; + + this._clearIncrementalUpdateTimer(); + const majorChange = false; + if (this._viewerState) + this.resource.setContent(this._viewerState.textModelContent, majorChange); + WebInspector.SourceFrame.prototype.cancelEditing.call(this); + return true; + }, + + afterTextChanged: function(oldRange, newRange) + { + function commitIncrementalEdit() + { + var majorChange = false; + this.resource.setContent(this._textModel.text, majorChange, function() {}); + } + const updateTimeout = 200; + this._incrementalUpdateTimer = setTimeout(commitIncrementalEdit.bind(this), updateTimeout); + }, + + _clearIncrementalUpdateTimer: function() + { + if (this._incrementalUpdateTimer) + clearTimeout(this._incrementalUpdateTimer); + delete this._incrementalUpdateTimer; + }, +} + +WebInspector.EditableResourceSourceFrame.prototype.__proto__ = WebInspector.ResourceSourceFrame.prototype; + +/** + * @extends {WebInspector.ResourceSourceFrame} + * @constructor + */ +WebInspector.ResourceRevisionSourceFrame = function(revision) +{ + WebInspector.ResourceSourceFrame.call(this, revision.resource); + this._revision = revision; +} + +WebInspector.ResourceRevisionSourceFrame.prototype = { + get resource() + { + return this._revision.resource; + }, + + requestContent: function(callback) + { + function contentLoaded(text) + { + var mimeType = WebInspector.ResourceSourceFrame.mimeTypeForResource(this.resource); + callback(mimeType, text); + } + + this._revision.requestContent(contentLoaded.bind(this)); + }, +} + +WebInspector.ResourceRevisionSourceFrame.prototype.__proto__ = WebInspector.ResourceSourceFrame.prototype; +/* JavaScriptSourceFrame.js */ + +/* + * Copyright (C) 2011 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. + */ + +/** + * @constructor + * @extends {WebInspector.SourceFrame} + * @param {WebInspector.ScriptsPanel} scriptsPanel + * @param {WebInspector.DebuggerPresentationModel} model + * @param {WebInspector.UISourceCode} uiSourceCode + */ +WebInspector.JavaScriptSourceFrame = function(scriptsPanel, model, uiSourceCode) +{ + this._scriptsPanel = scriptsPanel; + this._model = model; + this._uiSourceCode = uiSourceCode; + this._popoverObjectGroup = "popover"; + this._breakpoints = {}; + + WebInspector.SourceFrame.call(this, uiSourceCode.url); + + this._popoverHelper = new WebInspector.ObjectPopoverHelper(this.textViewer.element, + this._getPopoverAnchor.bind(this), this._onShowPopover.bind(this), this._onHidePopover.bind(this), true); + + this.textViewer.element.addEventListener("mousedown", this._onMouseDown.bind(this), true); + this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.ContentChanged, this._onContentChanged, this); + this.addEventListener(WebInspector.SourceFrame.Events.Loaded, this._onTextViewerContentLoaded, this); +} + +WebInspector.JavaScriptSourceFrame.prototype = { + get uiSourceCode() + { + return this._uiSourceCode; + }, + + // View events + willHide: function() + { + WebInspector.SourceFrame.prototype.willHide.call(this); + this._popoverHelper.hidePopover(); + }, + + // SourceFrame overrides + requestContent: function(callback) + { + this._uiSourceCode.requestContent(callback); + }, + + canEditSource: function() + { + return this._model.canEditScriptSource(this._uiSourceCode); + }, + + suggestedFileName: function() + { + return this._uiSourceCode.fileName || "untitled.js"; + }, + + editContent: function(newContent, callback) + { + this._model.setScriptSource(this._uiSourceCode, newContent, callback); + }, + + _onContentChanged: function() + { + if (!this.textViewer.readOnly) + return; + this.requestContent(this.setContent.bind(this)); + }, + + setReadOnly: function(readOnly) + { + if (this._popoverHelper && !readOnly) + this._popoverHelper.hidePopover(); + WebInspector.SourceFrame.prototype.setReadOnly.call(this, readOnly); + if (readOnly) + this._scriptsPanel.setScriptSourceIsBeingEdited(this._uiSourceCode, false); + }, + + populateLineGutterContextMenu: function(contextMenu, lineNumber) + { + contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Continue to here" : "Continue to Here"), this._model.continueToLine.bind(this._model, this._uiSourceCode, lineNumber)); + + var breakpoint = this._model.findBreakpoint(this._uiSourceCode, lineNumber); + if (!breakpoint) { + // This row doesn't have a breakpoint: We want to show Add Breakpoint and Add and Edit Breakpoint. + contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Add breakpoint" : "Add Breakpoint"), this._setBreakpoint.bind(this, lineNumber, "", true)); + + function addConditionalBreakpoint() + { + this.addBreakpoint(lineNumber, true, true, true); + function didEditBreakpointCondition(committed, condition) + { + this.removeBreakpoint(lineNumber); + if (committed) + this._setBreakpoint(lineNumber, condition, true); + } + this._editBreakpointCondition(lineNumber, "", didEditBreakpointCondition.bind(this)); + } + contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Add conditional breakpoint…" : "Add Conditional Breakpoint…"), addConditionalBreakpoint.bind(this)); + } else { + // This row has a breakpoint, we want to show edit and remove breakpoint, and either disable or enable. + contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Remove breakpoint" : "Remove Breakpoint"), this._model.removeBreakpoint.bind(this._model, this._uiSourceCode, lineNumber)); + + function editBreakpointCondition() + { + function didEditBreakpointCondition(committed, condition) + { + if (committed) + this._model.updateBreakpoint(this._uiSourceCode, lineNumber, condition, breakpoint.enabled); + } + this._editBreakpointCondition(lineNumber, breakpoint.condition, didEditBreakpointCondition.bind(this)); + } + contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Edit breakpoint…" : "Edit Breakpoint…"), editBreakpointCondition.bind(this)); + function setBreakpointEnabled(enabled) + { + this._model.updateBreakpoint(this._uiSourceCode, lineNumber, breakpoint.condition, enabled); + } + if (breakpoint.enabled) + contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Disable breakpoint" : "Disable Breakpoint"), setBreakpointEnabled.bind(this, false)); + else + contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Enable breakpoint" : "Enable Breakpoint"), setBreakpointEnabled.bind(this, true)); + } + }, + + populateTextAreaContextMenu: function(contextMenu, lineNumber) + { + WebInspector.SourceFrame.prototype.populateTextAreaContextMenu.call(this, contextMenu, lineNumber); + var selection = window.getSelection(); + if (selection.type === "Range" && !selection.isCollapsed) { + var addToWatchLabel = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Add to watch" : "Add to Watch"); + contextMenu.appendItem(addToWatchLabel, this._scriptsPanel.addToWatch.bind(this._scriptsPanel, selection.toString())); + var evaluateLabel = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Evaluate in console" : "Evaluate in Console"); + contextMenu.appendItem(evaluateLabel, WebInspector.evaluateInConsole.bind(WebInspector, selection.toString())); + } + }, + + afterTextChanged: function(oldRange, newRange) + { + if (!oldRange || !newRange) + return; + + // Adjust execution line number. + if (typeof this._executionLineNumber === "number") { + var newExecutionLineNumber = this._lineNumberAfterEditing(this._executionLineNumber, oldRange, newRange); + this.clearExecutionLine(); + this.setExecutionLine(newExecutionLineNumber, true); + } + + // Adjust breakpoints. + var oldBreakpoints = this._breakpoints; + this._breakpoints = {}; + for (var lineNumber in oldBreakpoints) { + lineNumber = Number(lineNumber); + var breakpoint = oldBreakpoints[lineNumber]; + var newLineNumber = this._lineNumberAfterEditing(lineNumber, oldRange, newRange); + if (lineNumber === newLineNumber) + this._breakpoints[lineNumber] = breakpoint; + else { + this.removeBreakpoint(lineNumber); + this.addBreakpoint(newLineNumber, breakpoint.resolved, breakpoint.conditional, breakpoint.enabled); + } + } + }, + + beforeTextChanged: function() + { + if (!this._javaScriptSourceFrameState) { + this._javaScriptSourceFrameState = { + executionLineNumber: this._executionLineNumber, + breakpoints: this._breakpoints + } + this._scriptsPanel.setScriptSourceIsBeingEdited(this._uiSourceCode, true); + } + WebInspector.SourceFrame.prototype.beforeTextChanged.call(this); + }, + + cancelEditing: function() + { + if (WebInspector.experimentsSettings.sourceFrameAlwaysEditable.isEnabled()) + return false; + + WebInspector.SourceFrame.prototype.cancelEditing.call(this); + + if (!this._javaScriptSourceFrameState) + return true; + + if (typeof this._javaScriptSourceFrameState.executionLineNumber === "number") { + this.clearExecutionLine(); + this.setExecutionLine(this._javaScriptSourceFrameState.executionLineNumber); + } + + var oldBreakpoints = this._breakpoints; + this._breakpoints = {}; + for (var lineNumber in oldBreakpoints) + this.removeBreakpoint(Number(lineNumber)); + + var newBreakpoints = this._javaScriptSourceFrameState.breakpoints; + for (var lineNumber in newBreakpoints) { + lineNumber = Number(lineNumber); + var breakpoint = newBreakpoints[lineNumber]; + this.addBreakpoint(lineNumber, breakpoint.resolved, breakpoint.conditional, breakpoint.enabled); + } + + delete this._javaScriptSourceFrameState; + return true; + }, + + didEditContent: function(error) + { + WebInspector.SourceFrame.prototype.didEditContent.call(this, error); + if (error) + return; + + var newBreakpoints = {}; + for (var lineNumber in this._breakpoints) { + newBreakpoints[lineNumber] = this._breakpoints[lineNumber]; + this.removeBreakpoint(Number(lineNumber)); + } + + for (var lineNumber in this._javaScriptSourceFrameState.breakpoints) + this._model.removeBreakpoint(this._uiSourceCode, Number(lineNumber)); + + for (var lineNumber in newBreakpoints) { + var breakpoint = newBreakpoints[lineNumber]; + this._setBreakpoint(Number(lineNumber), breakpoint.condition, breakpoint.enabled); + } + this._scriptsPanel.setScriptSourceIsBeingEdited(this._uiSourceCode, false); + delete this._javaScriptSourceFrameState; + }, + + // Popover callbacks + _shouldShowPopover: function(element) + { + if (!this._model.paused) + return false; + if (!element.enclosingNodeOrSelfWithClass("webkit-line-content")) + return false; + if (window.getSelection().type === "Range") + return false; + + // We are interested in identifiers and "this" keyword. + if (element.hasStyleClass("webkit-javascript-keyword")) + return element.textContent === "this"; + + return element.hasStyleClass("webkit-javascript-ident"); + }, + + _getPopoverAnchor: function(element) + { + if (!this._shouldShowPopover(element)) + return; + return element; + }, + + _onShowPopover: function(element, showCallback) + { + if (!this.readOnly) { + this._popoverHelper.hidePopover(); + return; + } + this._highlightElement = this._highlightExpression(element); + + function showObjectPopover(result, wasThrown) + { + if (!this._model.paused) { + this._popoverHelper.hidePopover(); + return; + } + showCallback(WebInspector.RemoteObject.fromPayload(result), wasThrown); + // Popover may have been removed by showCallback(). + if (this._highlightElement) + this._highlightElement.addStyleClass("source-frame-eval-expression"); + } + + var selectedCallFrame = this._model.selectedCallFrame; + selectedCallFrame.evaluate(this._highlightElement.textContent, this._popoverObjectGroup, false, false, showObjectPopover.bind(this)); + }, + + _onHidePopover: function() + { + // Replace higlight element with its contents inplace. + var highlightElement = this._highlightElement; + if (!highlightElement) + return; + // FIXME: the text editor should maintain highlight on its own. The check below is a workaround for + // the case when highlight element is detached from DOM by the TextViewer when re-building the DOM. + var parentElement = highlightElement.parentElement; + if (parentElement) { + var child = highlightElement.firstChild; + while (child) { + var nextSibling = child.nextSibling; + parentElement.insertBefore(child, highlightElement); + child = nextSibling; + } + parentElement.removeChild(highlightElement); + } + delete this._highlightElement; + RuntimeAgent.releaseObjectGroup(this._popoverObjectGroup); + }, + + _highlightExpression: function(element) + { + // Collect tokens belonging to evaluated expression. + var tokens = [ element ]; + var token = element.previousSibling; + while (token && (token.className === "webkit-javascript-ident" || token.className === "webkit-javascript-keyword" || token.textContent.trim() === ".")) { + tokens.push(token); + token = token.previousSibling; + } + tokens.reverse(); + + // Wrap them with highlight element. + var parentElement = element.parentElement; + var nextElement = element.nextSibling; + var container = document.createElement("span"); + for (var i = 0; i < tokens.length; ++i) + container.appendChild(tokens[i]); + parentElement.insertBefore(container, nextElement); + return container; + }, + + addBreakpoint: function(lineNumber, resolved, conditional, enabled) + { + this._breakpoints[lineNumber] = { + resolved: resolved, + conditional: conditional, + enabled: enabled + }; + this.textViewer.beginUpdates(); + this.textViewer.addDecoration(lineNumber, "webkit-breakpoint"); + if (!enabled) + this.textViewer.addDecoration(lineNumber, "webkit-breakpoint-disabled"); + if (conditional) + this.textViewer.addDecoration(lineNumber, "webkit-breakpoint-conditional"); + this.textViewer.endUpdates(); + }, + + removeBreakpoint: function(lineNumber) + { + delete this._breakpoints[lineNumber]; + this.textViewer.beginUpdates(); + this.textViewer.removeDecoration(lineNumber, "webkit-breakpoint"); + this.textViewer.removeDecoration(lineNumber, "webkit-breakpoint-disabled"); + this.textViewer.removeDecoration(lineNumber, "webkit-breakpoint-conditional"); + this.textViewer.endUpdates(); + }, + + _setBreakpoint: function(lineNumber, condition, enabled) + { + this._model.setBreakpoint(this._uiSourceCode, lineNumber, condition, enabled); + this._scriptsPanel.activateBreakpoints(); + }, + + _onMouseDown: function(event) + { + if (event.button != 0 || event.altKey || event.ctrlKey || event.metaKey) + return; + var target = event.target.enclosingNodeOrSelfWithClass("webkit-line-number"); + if (!target) + return; + var lineNumber = target.lineNumber; + + var breakpoint = this._model.findBreakpoint(this._uiSourceCode, lineNumber); + if (breakpoint) { + if (event.shiftKey) + this._model.updateBreakpoint(this._uiSourceCode, lineNumber, breakpoint.condition, !breakpoint.enabled); + else + this._model.removeBreakpoint(this._uiSourceCode, lineNumber); + } else + this._setBreakpoint(lineNumber, "", true); + event.preventDefault(); + }, + + _editBreakpointCondition: function(lineNumber, condition, callback) + { + this._conditionElement = this._createConditionElement(lineNumber); + this.textViewer.addDecoration(lineNumber, this._conditionElement); + + function finishEditing(committed, element, newText) + { + this.textViewer.removeDecoration(lineNumber, this._conditionElement); + delete this._conditionEditorElement; + delete this._conditionElement; + callback(committed, newText); + } + + var config = new WebInspector.EditingConfig(finishEditing.bind(this, true), finishEditing.bind(this, false)); + WebInspector.startEditing(this._conditionEditorElement, config); + this._conditionEditorElement.value = condition; + this._conditionEditorElement.select(); + }, + + _createConditionElement: function(lineNumber) + { + var conditionElement = document.createElement("div"); + conditionElement.className = "source-frame-breakpoint-condition"; + + var labelElement = document.createElement("label"); + labelElement.className = "source-frame-breakpoint-message"; + labelElement.htmlFor = "source-frame-breakpoint-condition"; + labelElement.appendChild(document.createTextNode(WebInspector.UIString("The breakpoint on line %d will stop only if this expression is true:", lineNumber))); + conditionElement.appendChild(labelElement); + + var editorElement = document.createElement("input"); + editorElement.id = "source-frame-breakpoint-condition"; + editorElement.className = "monospace"; + editorElement.type = "text"; + conditionElement.appendChild(editorElement); + this._conditionEditorElement = editorElement; + + return conditionElement; + }, + + /** + * @param {boolean=} skipRevealLine + */ + setExecutionLine: function(lineNumber, skipRevealLine) + { + this._executionLineNumber = lineNumber; + if (this.loaded) { + this.textViewer.addDecoration(lineNumber, "webkit-execution-line"); + if (!skipRevealLine) + this.textViewer.revealLine(lineNumber); + } + }, + + clearExecutionLine: function() + { + if (this.loaded) + this.textViewer.removeDecoration(this._executionLineNumber, "webkit-execution-line"); + delete this._executionLineNumber; + }, + + _lineNumberAfterEditing: function(lineNumber, oldRange, newRange) + { + var shiftOffset = lineNumber <= oldRange.startLine ? 0 : newRange.linesCount - oldRange.linesCount; + + // Special case of editing the line itself. We should decide whether the line number should move below or not. + if (lineNumber === oldRange.startLine) { + var whiteSpacesRegex = /^[\s\xA0]*$/; + for (var i = 0; lineNumber + i <= newRange.endLine; ++i) { + if (!whiteSpacesRegex.test(this._textModel.line(lineNumber + i))) { + shiftOffset = i; + break; + } + } + } + + var newLineNumber = Math.max(0, lineNumber + shiftOffset); + if (oldRange.startLine < lineNumber && lineNumber < oldRange.endLine) + newLineNumber = oldRange.startLine; + return newLineNumber; + }, + + _onTextViewerContentLoaded: function() + { + if (typeof this._executionLineNumber === "number") + this.setExecutionLine(this._executionLineNumber); + } +} + +WebInspector.JavaScriptSourceFrame.prototype.__proto__ = WebInspector.SourceFrame.prototype; +/* SplitView.js */ + +/* + * Copyright (C) 2011 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: + * + * 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 GOOGLE INC. 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 GOOGLE INC. + * 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. + */ + +/** + * @constructor + * @extends {WebInspector.View} + * @param {string=} sidebarPosition + * @param {string=} sidebarWidthSettingName + * @param {number=} defaultSidebarWidth + */ +WebInspector.SplitView = function(sidebarPosition, sidebarWidthSettingName, defaultSidebarWidth) +{ + WebInspector.View.call(this); + this.registerRequiredCSS("splitView.css"); + + this.element.className = "split-view"; + + this._leftElement = document.createElement("div"); + this._leftElement.className = "split-view-contents"; + this.element.appendChild(this._leftElement); + + this._rightElement = document.createElement("div"); + this._rightElement.className = "split-view-contents"; + this.element.appendChild(this._rightElement); + + this.sidebarResizerElement = document.createElement("div"); + this.sidebarResizerElement.className = "split-view-resizer"; + this.installResizer(this.sidebarResizerElement); + this._resizable = true; + this.element.appendChild(this.sidebarResizerElement); + + defaultSidebarWidth = defaultSidebarWidth || 200; + this._savedSidebarWidth = defaultSidebarWidth; + + this._sidebarWidthSettingName = sidebarWidthSettingName; + if (this._sidebarWidthSettingName) + WebInspector.settings[this._sidebarWidthSettingName] = WebInspector.settings.createSetting(this._sidebarWidthSettingName, undefined); + + this._minimalSidebarWidth = Preferences.minSidebarWidth; + this._minimalMainWidth = 0; + this._minimalSidebarWidthPercent = 0; + this._minimalMainWidthPercent = 50; + + this._mainElementHidden = false; + this._sidebarElementHidden = false; + + this._innerSetSidebarPosition(sidebarPosition || WebInspector.SplitView.SidebarPosition.Left); +} + +WebInspector.SplitView.EventTypes = { + Resized: "Resized", +} + +/** + * @enum {string} + */ +WebInspector.SplitView.SidebarPosition = { + Left: "Left", + Right: "Right" +} + +WebInspector.SplitView.prototype = { + /** + * @type {boolean} + */ + get hasLeftSidebar() + { + return this._sidebarPosition === WebInspector.SplitView.SidebarPosition.Left; + }, + + /** + * @type {Element} + */ + get mainElement() + { + return this.hasLeftSidebar ? this._rightElement : this._leftElement; + }, + + /** + * @type {Element} + */ + get sidebarElement() + { + return this.hasLeftSidebar ? this._leftElement : this._rightElement; + }, + + /** + * @type {boolean} + */ + get resizable() + { + return this._resizable && !this._mainElementHidden && !this._sidebarElementHidden + }, + + /** + * @type {boolean} + */ + set resizable(resizable) + { + if (this._resizable === resizable) + return; + this._resizable = resizable; + this._updateResizer(resizable); + }, + + _updateResizer: function() + { + if (this.resizable) + this.sidebarResizerElement.removeStyleClass("hidden"); + else + this.sidebarResizerElement.addStyleClass("hidden"); + }, + + /** + * @type {string} + */ + set sidebarPosition(sidebarPosition) + { + if (this._sidebarPosition === sidebarPosition) + return; + this._innerSetSidebarPosition(sidebarPosition); + this._restoreSidebarWidth(); + }, + + /** + * @param {string} sidebarPosition + */ + _innerSetSidebarPosition: function(sidebarPosition) + { + this._sidebarPosition = sidebarPosition; + + this._leftElement.style.left = 0; + this._rightElement.style.right = 0; + if (this.hasLeftSidebar) { + this._leftElement.addStyleClass("split-view-sidebar-left"); + this._rightElement.removeStyleClass("split-view-sidebar-right"); + this._leftElement.style.removeProperty("right"); + this._rightElement.style.removeProperty("width"); + this.sidebarResizerElement.style.removeProperty("right"); + } else { + this._rightElement.addStyleClass("split-view-sidebar-right"); + this._leftElement.removeStyleClass("split-view-sidebar-left"); + this._leftElement.style.removeProperty("width"); + this._rightElement.style.removeProperty("left"); + this.sidebarResizerElement.style.removeProperty("left"); + } + }, + + /** + * @param {number} width + */ + set minimalSidebarWidth(width) + { + this._minimalSidebarWidth = width; + }, + + /** + * @param {number} width + */ + set minimalMainWidth(width) + { + this._minimalMainWidth = width; + }, + + /** + * @param {number} widthPercent + */ + set minimalSidebarWidthPercent(widthPercent) + { + this._minimalSidebarWidthPercent = widthPercent; + }, + + /** + * @param {number} widthPercent + */ + set minimalMainWidthPercent(widthPercent) + { + this._minimalMainWidthPercent = widthPercent; + }, + + /** + * @param {number} width + */ + setMainWidth: function(width) + { + this.setSidebarWidth(this._totalWidth - width); + }, + + /** + * @param {number} width + */ + setSidebarWidth: function(width) + { + if (this._sidebarWidth === width) + return; + + this._innerSetSidebarWidth(width); + this.saveSidebarWidth(); + }, + + /** + * @param {number} width + */ + _innerSetSidebarWidth: function(width) + { + if (this.hasLeftSidebar) + this._innerSetLeftSidebarWidth(width); + else + this._innerSetRightSidebarWidth(width); + this._sidebarWidth = width; + this.doResize(); + this.dispatchEventToListeners(WebInspector.SplitView.EventTypes.Resized, this._sidebarWidth); + }, + + /** + * @param {number} width + */ + _innerSetLeftSidebarWidth: function(width) + { + this._leftElement.style.width = width + "px"; + this._rightElement.style.left = width + "px"; + this.sidebarResizerElement.style.left = (width - 3) + "px"; + }, + + /** + * @param {number} width + */ + _innerSetRightSidebarWidth: function(width) + { + this._rightElement.style.width = width + "px"; + this._leftElement.style.right = width + "px"; + this.sidebarResizerElement.style.right = (width - 3) + "px"; + }, + + /** + * @param {number} width + */ + _setSidebarWidthEnsuringConstraints: function(width) + { + var minWidth = Math.max(this._minimalSidebarWidth, this._totalWidth * this._minimalSidebarWidthPercent); + var maxWidth = Math.min(this._totalWidth - this._minimalMainWidth, this._totalWidth * (100 - this._minimalMainWidthPercent) / 100 ); + width = Number.constrain(width, minWidth, maxWidth); + + this.setSidebarWidth(width); + }, + + hideMainElement: function() + { + if (this._mainElementHidden) + return; + + if (this._sidebarElementHidden) + this.showSidebarElement(); + + this.mainElement.addStyleClass("hidden"); + this.sidebarElement.addStyleClass("maximized"); + + if (this.hasLeftSidebar) + this.sidebarElement.style.right = "0px"; + else + this.sidebarElement.style.left = "0px"; + + this._mainElementHidden = true; + this._updateResizer(); + this._restoreSidebarWidth(); + }, + + showMainElement: function() + { + if (!this._mainElementHidden) + return; + + this.mainElement.removeStyleClass("hidden"); + this.sidebarElement.removeStyleClass("maximized"); + + if (this.hasLeftSidebar) + this.sidebarElement.style.right = ""; + else + this.sidebarElement.style.left = ""; + + this._mainElementHidden = false; + this._updateResizer(); + this._restoreSidebarWidth(); + }, + + hideSidebarElement: function() + { + if (this._sidebarElementHidden) + return; + + if (this._mainElementHidden) + this.showMainElement(); + + this.sidebarElement.addStyleClass("hidden"); + this._sidebarElementHidden = true; + this._updateResizer(); + this._restoreSidebarWidth(); + }, + + showSidebarElement: function() + { + if (!this._sidebarElementHidden) + return; + + this.sidebarElement.removeStyleClass("hidden"); + this._sidebarElementHidden = false; + this._updateResizer(); + this._restoreSidebarWidth(); + }, + + wasShown: function() + { + this._totalWidth = this.element.offsetWidth; + this._restoreSidebarWidth(); + }, + + onResize: function() + { + this._totalWidth = this.element.offsetWidth; + + if (this._mainElementHidden) + this._sidebarWidth = this._totalWidth; + }, + + /** + * @param {Event} event + */ + _startResizerDragging: function(event) + { + if (!this._resizable) + return; + + var leftWidth = this.hasLeftSidebar ? this._sidebarWidth : this._totalWidth - this._sidebarWidth; + this._dragOffset = leftWidth - event.pageX; + + WebInspector.elementDragStart(this.sidebarResizerElement, this._resizerDragging.bind(this), this._endResizerDragging.bind(this), event, "ew-resize"); + }, + + /** + * @param {Event} event + */ + _resizerDragging: function(event) + { + var leftWidth = event.pageX + this._dragOffset + var rightWidth = this._totalWidth - leftWidth; + var sidebarWidth = this.hasLeftSidebar ? leftWidth : rightWidth; + + this._setSidebarWidthEnsuringConstraints(sidebarWidth); + event.preventDefault(); + }, + + /** + * @param {Event} event + */ + _endResizerDragging: function(event) + { + delete this._dragOffset; + WebInspector.elementDragEnd(event); + }, + + /** + * @param {Element} resizerElement + */ + installResizer: function(resizerElement) + { + resizerElement.addEventListener("mousedown", this._startResizerDragging.bind(this), false); + }, + + /** + * @return {number} + */ + preferredSidebarWidth: function() + { + if (!this._sidebarWidthSettingName) + return this._savedSidebarWidth; + + return WebInspector.settings[this._sidebarWidthSettingName].get() || this._savedSidebarWidth; + }, + + _restoreSidebarWidth: function() + { + if (this._mainElementHidden) { + this.sidebarElement.style.width = ""; + this._sidebarWidth = this._totalWidth; + return; + } + + if (this._sidebarElementHidden) { + this._innerSetSidebarWidth(0); + return; + } + + // Ensure restore satisfies constraints. + this._setSidebarWidthEnsuringConstraints(this.preferredSidebarWidth()); + }, + + saveSidebarWidth: function() + { + this._savedSidebarWidth = this._sidebarWidth; + if (!this._sidebarWidthSettingName) + return; + + WebInspector.settings[this._sidebarWidthSettingName].set(this._sidebarWidth); + }, + + /** + * @return {Array.} + */ + elementsToRestoreScrollPositionsFor: function() + { + return [ this.mainElement, this.sidebarElement ]; + } +} + +WebInspector.SplitView.prototype.__proto__ = WebInspector.View.prototype; +/* TabbedEditorContainer.js */ + +/* + * Copyright (C) 2011 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: + * + * 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 GOOGLE INC. 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 GOOGLE INC. + * 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. + */ + +/** + * @implements {WebInspector.ScriptsPanel.EditorContainer} + * @extends {WebInspector.Object} + * @constructor + */ +WebInspector.TabbedEditorContainer = function() +{ + this._tabbedPane = new WebInspector.TabbedPane(); + this._tabbedPane.closeableTabs = true; + this._tabbedPane.element.id = "scripts-editor-container-tabbed-pane"; + + this._tabbedPane.addEventListener(WebInspector.TabbedPane.EventTypes.TabClosed, this._tabClosed, this); + this._tabbedPane.addEventListener(WebInspector.TabbedPane.EventTypes.TabSelected, this._tabSelected, this); + + this._titles = new Map(); + this._tooltips = new Map(); + this._tabIds = new Map(); +} + +WebInspector.TabbedEditorContainer._tabId = 0; + +WebInspector.TabbedEditorContainer.prototype = { + /** + * @type {WebInspector.SourceFrame} + */ + get currentSourceFrame() + { + return this._tabbedPane.visibleView; + }, + + /** + * @param {Element} parentElement + */ + show: function(parentElement) + { + this._tabbedPane.show(parentElement); + }, + + /** + * @param {string} title + * @param {WebInspector.SourceFrame} sourceFrame + * @param {string} tooltip + */ + showSourceFrame: function(title, sourceFrame, tooltip) + { + var tabId = this._tabIds.get(sourceFrame) || this._appendSourceFrameTab(title, sourceFrame, tooltip); + this._tabbedPane.selectTab(tabId); + }, + + /** + * @param {string} title + * @param {WebInspector.SourceFrame} sourceFrame + * @param {string} tooltip + */ + _appendSourceFrameTab: function(title, sourceFrame, tooltip) + { + var tabId = this._generateTabId(); + this._tabIds.put(sourceFrame, tabId) + this._titles.put(sourceFrame, title) + this._tooltips.put(sourceFrame, tooltip) + + this._tabbedPane.appendTab(tabId, title, sourceFrame, tooltip); + return tabId; + }, + + /** + * @param {WebInspector.SourceFrame} sourceFrame + */ + _removeSourceFrameTab: function(sourceFrame) + { + var tabId = this._tabIds.get(sourceFrame); + + if (tabId) + this._tabbedPane.closeTab(tabId); + }, + + /** + * @param {WebInspector.Event} event + */ + _tabClosed: function(event) + { + var sourceFrame = /** @type {WebInspector.UISourceCode} */ event.data.view; + this._tabIds.remove(sourceFrame); + this._titles.remove(sourceFrame); + this._tooltips.remove(sourceFrame); + }, + + /** + * @param {WebInspector.Event} event + */ + _tabSelected: function(event) + { + var sourceFrame = /** @type {WebInspector.UISourceCode} */ event.data.view; + this.dispatchEventToListeners(WebInspector.ScriptsPanel.EditorContainer.Events.EditorSelected, sourceFrame); + }, + + /** + * @param {WebInspector.SourceFrame} oldSourceFrame + * @param {string} title + * @param {WebInspector.SourceFrame} sourceFrame + * @param {string} tooltip + */ + _replaceSourceFrameTab: function(oldSourceFrame, title, sourceFrame, tooltip) + { + var tabId = this._tabIds.get(oldSourceFrame); + + if (tabId) { + this._tabIds.remove(oldSourceFrame); + this._titles.remove(oldSourceFrame); + this._tooltips.remove(oldSourceFrame); + + this._tabIds.put(sourceFrame, tabId); + this._titles.put(sourceFrame, title); + this._tooltips.put(sourceFrame, tooltip); + + this._tabbedPane.changeTabTitle(tabId, title); + this._tabbedPane.changeTabView(tabId, sourceFrame); + this._tabbedPane.changeTabTooltip(tabId, tooltip); + } + }, + + /** + * @param {WebInspector.SourceFrame} sourceFrame + * @return {boolean} + */ + isSourceFrameOpen: function(sourceFrame) + { + return !!this._tabIds.get(sourceFrame); + }, + + /** + * @param {Array.} oldSourceFrames + * @param {string} title + * @param {WebInspector.SourceFrame} sourceFrame + * @param {string} tooltip + */ + replaceSourceFrames: function(oldSourceFrames, title, sourceFrame, tooltip) + { + var mainSourceFrame; + for (var i = 0; i < oldSourceFrames.length; ++i) { + var tabId = this._tabIds.get(oldSourceFrames[i]); + if (tabId && (!mainSourceFrame || this._tabbedPane.selectedTabId === tabId)) { + mainSourceFrame = oldSourceFrames[i]; + break; + } + } + + if (mainSourceFrame) + this._replaceSourceFrameTab(mainSourceFrame, title, sourceFrame, tooltip); + + for (var i = 0; i < oldSourceFrames.length; ++i) + this._removeSourceFrameTab(oldSourceFrames[i]); + }, + + /** + * @param {WebInspector.SourceFrame} sourceFrame + * @param {boolean} isDirty + */ + setSourceFrameIsDirty: function(sourceFrame, isDirty) + { + var tabId = this._tabIds.get(sourceFrame); + if (tabId) { + var title = this._titles.get(sourceFrame); + if (isDirty) + title += "*"; + this._tabbedPane.changeTabTitle(tabId, title); + } + }, + + reset: function() + { + this._tabbedPane.closeAllTabs(); + this._titles = new Map(); + this._tooltips = new Map(); + this._tabIds = new Map(); + }, + + /** + * @return {string} + */ + _generateTabId: function() + { + return "tab_" + (WebInspector.TabbedEditorContainer._tabId++); + } +} + +WebInspector.TabbedEditorContainer.prototype.__proto__ = WebInspector.Object.prototype;/* ScriptsPanel.js */ + +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2011 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: + * 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 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 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. + */ + +/** + * @constructor + * @extends {WebInspector.Panel} + */ +WebInspector.ScriptsPanel = function(presentationModel) +{ + WebInspector.Panel.call(this, "scripts"); + this.registerRequiredCSS("scriptsPanel.css"); + + WebInspector.settings.pauseOnExceptionStateString = WebInspector.settings.createSetting("pauseOnExceptionStateString", WebInspector.ScriptsPanel.PauseOnExceptionsState.DontPauseOnExceptions); + + this._presentationModel = presentationModel; + + function viewGetter() + { + return this.visibleView; + } + WebInspector.GoToLineDialog.install(this, viewGetter.bind(this)); + WebInspector.JavaScriptOutlineDialog.install(this, viewGetter.bind(this)); + + this.debugToolbar = this._createDebugToolbar(); + + const initialDebugSidebarWidth = 225; + const maximalDebugSidebarWidthPercent = 50; + this.createSplitView(this.element, WebInspector.SplitView.SidebarPosition.Right, initialDebugSidebarWidth); + this.splitView.element.id = "scripts-split-view"; + this.splitView.minimalSidebarWidth = Preferences.minScriptsSidebarWidth; + this.splitView.minimalMainWidthPercent = 100 - maximalDebugSidebarWidthPercent; + + this.sidebarElement.appendChild(this.debugToolbar); + + this.debugSidebarResizeWidgetElement = document.createElement("div"); + this.debugSidebarResizeWidgetElement.id = "scripts-debug-sidebar-resizer-widget"; + this.splitView.installResizer(this.debugSidebarResizeWidgetElement); + + if (WebInspector.experimentsSettings.useScriptsNavigator.isEnabled()) { + const initialNavigatorWidth = 225; + const minimalViewsContainerWidthPercent = 50; + this.editorView = new WebInspector.SplitView(WebInspector.SplitView.SidebarPosition.Left, "scriptsPanelNavigatorSidebarWidth", initialNavigatorWidth); + + this.editorView.minimalSidebarWidth = Preferences.minScriptsSidebarWidth; + this.editorView.minimalMainWidthPercent = minimalViewsContainerWidthPercent; + this.editorView.show(this.splitView.mainElement); + + this._fileSelector = new WebInspector.ScriptsNavigator(this._presentationModel); + + this._fileSelector.show(this.editorView.sidebarElement); + + this._navigatorResizeWidgetElement = document.createElement("div"); + this._navigatorResizeWidgetElement.id = "scripts-navigator-resizer-widget"; + this.editorView.installResizer(this._navigatorResizeWidgetElement); + this.editorView.sidebarElement.appendChild(this._navigatorResizeWidgetElement); + + this._editorContainer = new WebInspector.TabbedEditorContainer(); + this._editorContainer.show(this.editorView.mainElement); + WebInspector.OpenResourceDialog.install(this, this._presentationModel, this.editorView.mainElement); + } else { + this._fileSelector = new WebInspector.ScriptsPanel.ComboBoxFileSelector(this._presentationModel); + this._fileSelector.show(this.splitView.mainElement); + + this._editorContainer = new WebInspector.ScriptsPanel.SingleFileEditorContainer(); + this._editorContainer.show(this.splitView.mainElement); + WebInspector.OpenResourceDialog.install(this, this._presentationModel, this.splitView.mainElement); + } + this._fileSelector.addEventListener(WebInspector.ScriptsPanel.FileSelector.Events.FileSelected, this._fileSelected, this); + this._fileSelector.addEventListener(WebInspector.ScriptsPanel.FileSelector.Events.ReleasedFocusAfterSelection, this._fileSelectorReleasedFocus, this); + this._editorContainer.addEventListener(WebInspector.ScriptsPanel.EditorContainer.Events.EditorSelected, this._editorSelected, this); + + this.splitView.mainElement.appendChild(this.debugSidebarResizeWidgetElement); + + this.sidebarPanes = {}; + this.sidebarPanes.watchExpressions = new WebInspector.WatchExpressionsSidebarPane(); + this.sidebarPanes.callstack = new WebInspector.CallStackSidebarPane(this._presentationModel); + this.sidebarPanes.scopechain = new WebInspector.ScopeChainSidebarPane(); + this.sidebarPanes.jsBreakpoints = new WebInspector.JavaScriptBreakpointsSidebarPane(this._presentationModel, this._showSourceLine.bind(this)); + if (Capabilities.nativeInstrumentationEnabled) { + this.sidebarPanes.domBreakpoints = WebInspector.domBreakpointsSidebarPane; + this.sidebarPanes.xhrBreakpoints = new WebInspector.XHRBreakpointsSidebarPane(); + this.sidebarPanes.eventListenerBreakpoints = new WebInspector.EventListenerBreakpointsSidebarPane(); + } + + if (Preferences.exposeWorkersInspection && !WebInspector.WorkerManager.isWorkerFrontend()) { + WorkerAgent.setWorkerInspectionEnabled(true); + this.sidebarPanes.workerList = new WebInspector.WorkerListSidebarPane(WebInspector.workerManager); + } else + this.sidebarPanes.workers = new WebInspector.WorkersSidebarPane(); + + this._debugSidebarContentsElement = document.createElement("div"); + this._debugSidebarContentsElement.id = "scripts-debug-sidebar-contents"; + this.sidebarElement.appendChild(this._debugSidebarContentsElement); + + for (var pane in this.sidebarPanes) + this._debugSidebarContentsElement.appendChild(this.sidebarPanes[pane].element); + + this.sidebarPanes.callstack.expanded = true; + + this.sidebarPanes.scopechain.expanded = true; + this.sidebarPanes.jsBreakpoints.expanded = true; + + var helpSection = WebInspector.shortcutsScreen.section(WebInspector.UIString("Scripts Panel")); + this.sidebarPanes.callstack.registerShortcuts(helpSection, this.registerShortcut.bind(this)); + var evaluateInConsoleShortcut = WebInspector.KeyboardShortcut.makeDescriptor("e", WebInspector.KeyboardShortcut.Modifiers.Shift | WebInspector.KeyboardShortcut.Modifiers.Ctrl); + helpSection.addKey(evaluateInConsoleShortcut.name, WebInspector.UIString("Evaluate selection in console")); + this.registerShortcut(evaluateInConsoleShortcut.key, this._evaluateSelectionInConsole.bind(this)); + + var scriptOutlineShortcut = WebInspector.JavaScriptOutlineDialog.createShortcut(); + helpSection.addKey(scriptOutlineShortcut.name, WebInspector.UIString("Go to Function")); + + var openResourceShortcut = WebInspector.OpenResourceDialog.createShortcut(); + helpSection.addKey(openResourceShortcut.name, WebInspector.UIString("Open Script")); + + var panelEnablerHeading = WebInspector.UIString("You need to enable debugging before you can use the Scripts panel."); + var panelEnablerDisclaimer = WebInspector.UIString("Enabling debugging will make scripts run slower."); + var panelEnablerButton = WebInspector.UIString("Enable Debugging"); + + this.panelEnablerView = new WebInspector.PanelEnablerView("scripts", panelEnablerHeading, panelEnablerDisclaimer, panelEnablerButton); + this.panelEnablerView.addEventListener("enable clicked", this.enableDebugging, this); + + this.enableToggleButton = new WebInspector.StatusBarButton("", "enable-toggle-status-bar-item"); + this.enableToggleButton.addEventListener("click", this.toggleDebugging, this); + if (!Capabilities.debuggerCausesRecompilation) + this.enableToggleButton.element.addStyleClass("hidden"); + + this._pauseOnExceptionButton = new WebInspector.StatusBarButton("", "scripts-pause-on-exceptions-status-bar-item", 3); + this._pauseOnExceptionButton.addEventListener("click", this._togglePauseOnExceptions, this); + + this._toggleFormatSourceButton = new WebInspector.StatusBarButton(WebInspector.UIString("Pretty print"), "scripts-toggle-pretty-print-status-bar-item"); + this._toggleFormatSourceButton.toggled = false; + this._toggleFormatSourceButton.addEventListener("click", this._toggleFormatSource, this); + + this._scriptViewStatusBarItemsContainer = document.createElement("div"); + this._scriptViewStatusBarItemsContainer.style.display = "inline-block"; + + this._debuggerEnabled = !Capabilities.debuggerCausesRecompilation; + + this._reset(false); + + WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerWasEnabled, this._debuggerWasEnabled, this); + WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerWasDisabled, this._debuggerWasDisabled, this); + + this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.UISourceCodeAdded, this._uiSourceCodeAdded, this) + this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.UISourceCodeReplaced, this._uiSourceCodeReplaced, this); + this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.UISourceCodeRemoved, this._uiSourceCodeRemoved, this); + this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.ConsoleMessageAdded, this._consoleMessageAdded, this); + this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.ConsoleMessagesCleared, this._consoleMessagesCleared, this); + this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.BreakpointAdded, this._breakpointAdded, this); + this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.BreakpointRemoved, this._breakpointRemoved, this); + this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.DebuggerPaused, this._debuggerPaused, this); + this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.DebuggerResumed, this._debuggerResumed, this); + this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.CallFrameSelected, this._callFrameSelected, this); + this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.ConsoleCommandEvaluatedInSelectedCallFrame, this._consoleCommandEvaluatedInSelectedCallFrame, this); + this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.ExecutionLineChanged, this._executionLineChanged, this); + this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.DebuggerReset, this._reset.bind(this, false)); + + var enableDebugger = !Capabilities.debuggerCausesRecompilation || WebInspector.settings.debuggerEnabled.get(); + if (enableDebugger) + WebInspector.debuggerModel.enableDebugger(); + + WebInspector.advancedSearchController.registerSearchScope(new WebInspector.ScriptsSearchScope()); + + this._sourceFramesByUISourceCode = new Map(); +} + +// Keep these in sync with WebCore::ScriptDebugServer +WebInspector.ScriptsPanel.PauseOnExceptionsState = { + DontPauseOnExceptions : "none", + PauseOnAllExceptions : "all", + PauseOnUncaughtExceptions: "uncaught" +}; + +WebInspector.ScriptsPanel.prototype = { + get toolbarItemLabel() + { + return WebInspector.UIString("Scripts"); + }, + + get statusBarItems() + { + return [this.enableToggleButton.element, this._pauseOnExceptionButton.element, this._toggleFormatSourceButton.element, this._scriptViewStatusBarItemsContainer]; + }, + + get defaultFocusedElement() + { + return this._fileSelector.defaultFocusedElement; + }, + + get paused() + { + return this._paused; + }, + + wasShown: function() + { + WebInspector.Panel.prototype.wasShown.call(this); + if (Capabilities.nativeInstrumentationEnabled) + this._debugSidebarContentsElement.insertBefore(this.sidebarPanes.domBreakpoints.element, this.sidebarPanes.xhrBreakpoints.element); + this.sidebarPanes.watchExpressions.show(); + }, + + breakpointsActivated: function() + { + return this.toggleBreakpointsButton.toggled; + }, + + activateBreakpoints: function() + { + if (!this.breakpointsActivated) + this._toggleBreakpointsClicked(); + }, + + _didBuildOutlineChunk: function(event) + { + WebInspector.JavaScriptOutlineDialog.didAddChunk(event.data); + if (event.data.total === event.data.index) { + if (this._outlineWorker) { + this._outlineWorker.terminate(); + delete this._outlineWorker; + } + } + }, + + _uiSourceCodeAdded: function(event) + { + var uiSourceCode = /** @type {WebInspector.UISourceCode} */ event.data; + + if (!uiSourceCode.url) { + // Anonymous sources are shown only when stepping. + return; + } + + this._fileSelector.addUISourceCode(uiSourceCode); + + var lastViewedURL = WebInspector.settings.lastViewedScriptFile.get(); + if (!this._initialViewSelectionProcessed) { + this._initialViewSelectionProcessed = true; + // Option we just added is the only option in files select. + // We have to show corresponding source frame immediately. + this._showAndRevealInFileSelector(uiSourceCode); + // Restore original value of lastViewedScriptFile because + // source frame was shown as a result of initial load. + WebInspector.settings.lastViewedScriptFile.set(lastViewedURL); + } else if (uiSourceCode.url === lastViewedURL) + this._showAndRevealInFileSelector(uiSourceCode); + }, + + _uiSourceCodeRemoved: function(event) + { + var uiSourceCode = /** @type {WebInspector.UISourceCode} */ event.data; + this._removeSourceFrame(uiSourceCode); + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + * @param {boolean} inEditMode + */ + setScriptSourceIsBeingEdited: function(uiSourceCode, inEditMode) + { + this._fileSelector.setScriptSourceIsDirty(uiSourceCode, inEditMode); + var sourceFrame = this._sourceFramesByUISourceCode.get(uiSourceCode) + if (sourceFrame) + this._editorContainer.setSourceFrameIsDirty(sourceFrame, inEditMode); + }, + + _consoleMessagesCleared: function() + { + var uiSourceCodes = this._sourceFramesByUISourceCode; + for (var i = 0; i < uiSourceCodes.length; ++i) { + var sourceFrame = this._sourceFramesByUISourceCode.get(uiSourceCodes[i]) + sourceFrame.clearMessages(); + } + }, + + _consoleMessageAdded: function(event) + { + var message = event.data; + + var sourceFrame = this._sourceFramesByUISourceCode.get(message.uiSourceCode) + if (sourceFrame && sourceFrame.loaded) + sourceFrame.addMessageToSource(message.lineNumber, message.originalMessage); + }, + + _breakpointAdded: function(event) + { + var breakpoint = event.data; + + var sourceFrame = this._sourceFramesByUISourceCode.get(breakpoint.uiSourceCode) + if (sourceFrame && sourceFrame.loaded) + sourceFrame.addBreakpoint(breakpoint.lineNumber, breakpoint.resolved, breakpoint.condition, breakpoint.enabled); + + this.sidebarPanes.jsBreakpoints.addBreakpoint(breakpoint); + }, + + _breakpointRemoved: function(event) + { + var breakpoint = event.data; + + var sourceFrame = this._sourceFramesByUISourceCode.get(breakpoint.uiSourceCode) + if (sourceFrame && sourceFrame.loaded) + sourceFrame.removeBreakpoint(breakpoint.lineNumber); + + this.sidebarPanes.jsBreakpoints.removeBreakpoint(breakpoint.uiSourceCode, breakpoint.lineNumber); + }, + + _consoleCommandEvaluatedInSelectedCallFrame: function(event) + { + this.sidebarPanes.scopechain.update(this._presentationModel.selectedCallFrame); + }, + + _debuggerPaused: function(event) + { + var callFrames = event.data.callFrames; + var details = event.data.details; + + this._paused = true; + this._waitingToPause = false; + this._stepping = false; + + this._updateDebuggerButtons(); + + WebInspector.inspectorView.setCurrentPanel(this); + + this.sidebarPanes.callstack.update(callFrames); + this._updateCallFrame(this._presentationModel.selectedCallFrame); + + if (details.reason === WebInspector.DebuggerModel.BreakReason.DOM) { + this.sidebarPanes.domBreakpoints.highlightBreakpoint(details.auxData); + function didCreateBreakpointHitStatusMessage(element) + { + this.sidebarPanes.callstack.setStatus(element); + } + this.sidebarPanes.domBreakpoints.createBreakpointHitStatusMessage(details.auxData, didCreateBreakpointHitStatusMessage.bind(this)); + } else if (details.reason === WebInspector.DebuggerModel.BreakReason.EventListener) { + var eventName = details.auxData.eventName; + this.sidebarPanes.eventListenerBreakpoints.highlightBreakpoint(details.auxData.eventName); + var eventNameForUI = WebInspector.EventListenerBreakpointsSidebarPane.eventNameForUI(eventName); + this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a \"%s\" Event Listener.", eventNameForUI)); + } else if (details.reason === WebInspector.DebuggerModel.BreakReason.XHR) { + this.sidebarPanes.xhrBreakpoints.highlightBreakpoint(details.auxData["breakpointURL"]); + this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a XMLHttpRequest.")); + } else if (details.reason === WebInspector.DebuggerModel.BreakReason.Exception) { + this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on exception: '%s'.", details.auxData.description)); + } else { + function didGetUILocation(uiLocation) + { + if (!this._presentationModel.findBreakpoint(uiLocation.uiSourceCode, uiLocation.lineNumber)) + return; + this.sidebarPanes.jsBreakpoints.highlightBreakpoint(uiLocation.uiSourceCode, uiLocation.lineNumber); + this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a JavaScript breakpoint.")); + } + callFrames[0].uiLocation(didGetUILocation.bind(this)); + } + + window.focus(); + InspectorFrontendHost.bringToFront(); + }, + + _debuggerResumed: function() + { + this._paused = false; + this._waitingToPause = false; + this._stepping = false; + + this._clearInterface(); + }, + + _debuggerWasEnabled: function() + { + this._setPauseOnExceptions(WebInspector.settings.pauseOnExceptionStateString.get()); + + if (this._debuggerEnabled) + return; + + this._debuggerEnabled = true; + this._reset(true); + }, + + _debuggerWasDisabled: function() + { + if (!this._debuggerEnabled) + return; + + this._debuggerEnabled = false; + this._reset(true); + }, + + _reset: function(preserveItems) + { + delete this.currentQuery; + this.searchCanceled(); + + this._debuggerResumed(); + + delete this._initialViewSelectionProcessed; + + this._editorContainer.reset(); + this._updateScriptViewStatusBarItems(); + + this.sidebarPanes.jsBreakpoints.reset(); + this.sidebarPanes.watchExpressions.reset(); + if (!preserveItems && this.sidebarPanes.workers) + this.sidebarPanes.workers.reset(); + }, + + get visibleView() + { + return this._editorContainer.currentSourceFrame; + }, + + _updateScriptViewStatusBarItems: function() + { + this._scriptViewStatusBarItemsContainer.removeChildren(); + + var sourceFrame = this.visibleView; + if (sourceFrame) { + var statusBarItems = sourceFrame.statusBarItems || []; + for (var i = 0; i < statusBarItems.length; ++i) + this._scriptViewStatusBarItemsContainer.appendChild(statusBarItems[i]); + } + }, + + canShowAnchorLocation: function(anchor) + { + return this._debuggerEnabled && anchor.uiSourceCode; + }, + + showAnchorLocation: function(anchor) + { + this._showSourceLine(anchor.uiSourceCode, anchor.lineNumber); + }, + + showFunctionDefinition: function(functionLocation) + { + WebInspector.showPanelForAnchorNavigation(this); + var uiLocation = this._presentationModel.rawLocationToUILocation(functionLocation); + this._showSourceLine(uiLocation.uiSourceCode, uiLocation.lineNumber); + }, + + showUISourceCode: function(uiSourceCode) + { + this._showSourceLine(uiSourceCode); + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + * @param {number=} lineNumber + */ + _showSourceLine: function(uiSourceCode, lineNumber) + { + var sourceFrame = this._showAndRevealInFileSelector(uiSourceCode); + if (typeof lineNumber === "number") + sourceFrame.highlightLine(lineNumber); + sourceFrame.focus(); + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + * @return {WebInspector.SourceFrame} + */ + _showFile: function(uiSourceCode) + { + var sourceFrame = this._sourceFramesByUISourceCode.get(uiSourceCode) || this._createSourceFrame(uiSourceCode); + + this._editorContainer.showSourceFrame(uiSourceCode.displayName, sourceFrame, uiSourceCode.url); + this._updateScriptViewStatusBarItems(); + + if (uiSourceCode.url) + WebInspector.settings.lastViewedScriptFile.set(uiSourceCode.url); + + return sourceFrame; + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + * @return {WebInspector.SourceFrame} + */ + _showAndRevealInFileSelector: function(uiSourceCode) + { + if (!this._fileSelector.isScriptSourceAdded(uiSourceCode)) + return null; + + this._fileSelector.revealUISourceCode(uiSourceCode); + return this._showFile(uiSourceCode); + }, + + requestVisibleScriptOutline: function() + { + function contentCallback(mimeType, content) + { + if (this._outlineWorker) + this._outlineWorker.terminate(); + this._outlineWorker = new Worker("ScriptFormatterWorker.js"); + this._outlineWorker.onmessage = this._didBuildOutlineChunk.bind(this); + const method = "outline"; + this._outlineWorker.postMessage({ method: method, params: { content: content, id: this.visibleView.uiSourceCode.id } }); + } + + if (this.visibleView.uiSourceCode) + this.visibleView.uiSourceCode.requestContent(contentCallback.bind(this)); + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + */ + _createSourceFrame: function(uiSourceCode) + { + var sourceFrame = new WebInspector.JavaScriptSourceFrame(this, this._presentationModel, uiSourceCode); + + sourceFrame._uiSourceCode = uiSourceCode; + sourceFrame.addEventListener(WebInspector.SourceFrame.Events.Loaded, this._sourceFrameLoaded, this); + this._sourceFramesByUISourceCode.put(uiSourceCode, sourceFrame); + return sourceFrame; + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + */ + _removeSourceFrame: function(uiSourceCode) + { + var sourceFrame = this._sourceFramesByUISourceCode.get(uiSourceCode); + if (!sourceFrame) + return; + this._sourceFramesByUISourceCode.remove(uiSourceCode); + sourceFrame.detach(); + sourceFrame.removeEventListener(WebInspector.SourceFrame.Events.Loaded, this._sourceFrameLoaded, this); + }, + + /** + * @param {Event} event + */ + _uiSourceCodeReplaced: function(event) + { + var oldUISourceCodeList = /** @type {Array.} */ event.data.oldUISourceCodeList; + var uiSourceCodeList = /** @type {Array.} */ event.data.uiSourceCodeList; + + var addedToFileSelector = false; + var sourceFrames = []; + for (var i = 0; i < oldUISourceCodeList.length; ++i) { + var uiSourceCode = oldUISourceCodeList[i]; + var oldSourceFrame = this._sourceFramesByUISourceCode.get(uiSourceCode); + + if (this._fileSelector.isScriptSourceAdded(uiSourceCode)) { + addedToFileSelector = true; + + if (oldSourceFrame) + sourceFrames.push(oldSourceFrame); + this._removeSourceFrame(uiSourceCode); + } + } + + if (addedToFileSelector) { + this._fileSelector.replaceUISourceCodes(oldUISourceCodeList, uiSourceCodeList); + + var shouldReplace = false; + for (var i = 0; i < sourceFrames.length; ++i) { + if (this._editorContainer.isSourceFrameOpen(sourceFrames[i])) { + shouldReplace = true; + break; + } + } + + if (shouldReplace) { + var newUISourceCode = uiSourceCodeList[0]; + var sourceFrame = this._sourceFramesByUISourceCode.get(newUISourceCode) || this._createSourceFrame(newUISourceCode); + this._editorContainer.replaceSourceFrames(sourceFrames, newUISourceCode.displayName, sourceFrame, newUISourceCode.url); + } + } + }, + + _sourceFrameLoaded: function(event) + { + var sourceFrame = /** @type {WebInspector.JavaScriptSourceFrame} */ event.target; + var uiSourceCode = sourceFrame._uiSourceCode; + + var messages = this._presentationModel.messagesForUISourceCode(uiSourceCode); + for (var i = 0; i < messages.length; ++i) { + var message = messages[i]; + sourceFrame.addMessageToSource(message.lineNumber, message.originalMessage); + } + + var breakpoints = this._presentationModel.breakpointsForUISourceCode(uiSourceCode); + for (var i = 0; i < breakpoints.length; ++i) { + var breakpoint = breakpoints[i]; + sourceFrame.addBreakpoint(breakpoint.lineNumber, breakpoint.resolved, breakpoint.condition, breakpoint.enabled); + } + }, + + _clearCurrentExecutionLine: function() + { + if (this._executionSourceFrame) + this._executionSourceFrame.clearExecutionLine(); + delete this._executionSourceFrame; + }, + + _executionLineChanged: function(event) + { + var uiLocation = event.data; + + this._updateExecutionLine(uiLocation); + }, + + _updateExecutionLine: function(uiLocation) + { + this._clearCurrentExecutionLine(); + if (!uiLocation) + return; + + // Anonymous scripts are not added to files select by default. + this._fileSelector.addUISourceCode(uiLocation.uiSourceCode); + + var sourceFrame = this._showAndRevealInFileSelector(uiLocation.uiSourceCode); + sourceFrame.setExecutionLine(uiLocation.lineNumber); + this._executionSourceFrame = sourceFrame; + }, + + _callFrameSelected: function(event) + { + var callFrame = event.data; + + if (!callFrame) + return; + + this._updateCallFrame(callFrame); + }, + + _updateCallFrame: function(callFrame) + { + this.sidebarPanes.scopechain.update(callFrame); + this.sidebarPanes.watchExpressions.refreshExpressions(); + this.sidebarPanes.callstack.selectedCallFrame = callFrame; + this._updateExecutionLine(this._presentationModel.executionLineLocation); + }, + + _editorSelected: function(event) + { + var sourceFrame = /** @type {WebInspector.SourceFrame} */ event.data; + this._fileSelector.revealUISourceCode(sourceFrame._uiSourceCode); + }, + + _fileSelected: function(event) + { + var uiSourceCode = /** @type {WebInspector.UISourceCode} */ event.data; + this._showFile(uiSourceCode); + }, + + _fileSelectorReleasedFocus: function(event) + { + var uiSourceCode = /** @type {WebInspector.UISourceCode} */ event.data; + var sourceFrame = this._sourceFramesByUISourceCode.get(uiSourceCode); + if (sourceFrame) + sourceFrame.focus(); + }, + + _setPauseOnExceptions: function(pauseOnExceptionsState) + { + pauseOnExceptionsState = pauseOnExceptionsState || WebInspector.ScriptsPanel.PauseOnExceptionsState.DontPauseOnExceptions; + function callback(error) + { + if (error) + return; + if (pauseOnExceptionsState == WebInspector.ScriptsPanel.PauseOnExceptionsState.DontPauseOnExceptions) + this._pauseOnExceptionButton.title = WebInspector.UIString("Don't pause on exceptions.\nClick to Pause on all exceptions."); + else if (pauseOnExceptionsState == WebInspector.ScriptsPanel.PauseOnExceptionsState.PauseOnAllExceptions) + this._pauseOnExceptionButton.title = WebInspector.UIString("Pause on all exceptions.\nClick to Pause on uncaught exceptions."); + else if (pauseOnExceptionsState == WebInspector.ScriptsPanel.PauseOnExceptionsState.PauseOnUncaughtExceptions) + this._pauseOnExceptionButton.title = WebInspector.UIString("Pause on uncaught exceptions.\nClick to Not pause on exceptions."); + + this._pauseOnExceptionButton.state = pauseOnExceptionsState; + WebInspector.settings.pauseOnExceptionStateString.set(pauseOnExceptionsState); + } + DebuggerAgent.setPauseOnExceptions(pauseOnExceptionsState, callback.bind(this)); + }, + + _updateDebuggerButtons: function() + { + if (this._debuggerEnabled) { + this.enableToggleButton.title = WebInspector.UIString("Debugging enabled. Click to disable."); + this.enableToggleButton.toggled = true; + this._pauseOnExceptionButton.visible = true; + this.panelEnablerView.detach(); + } else { + this.enableToggleButton.title = WebInspector.UIString("Debugging disabled. Click to enable."); + this.enableToggleButton.toggled = false; + this._pauseOnExceptionButton.visible = false; + this.panelEnablerView.show(this.element); + } + + if (this._paused) { + this.pauseButton.addStyleClass("paused"); + + this.pauseButton.disabled = false; + this.stepOverButton.disabled = false; + this.stepIntoButton.disabled = false; + this.stepOutButton.disabled = false; + + this.debuggerStatusElement.textContent = WebInspector.UIString("Paused"); + } else { + this.pauseButton.removeStyleClass("paused"); + + this.pauseButton.disabled = this._waitingToPause; + this.stepOverButton.disabled = true; + this.stepIntoButton.disabled = true; + this.stepOutButton.disabled = true; + + if (this._waitingToPause) + this.debuggerStatusElement.textContent = WebInspector.UIString("Pausing"); + else if (this._stepping) + this.debuggerStatusElement.textContent = WebInspector.UIString("Stepping"); + else + this.debuggerStatusElement.textContent = ""; + } + }, + + _clearInterface: function() + { + this.sidebarPanes.callstack.update(null); + this.sidebarPanes.scopechain.update(null); + this.sidebarPanes.jsBreakpoints.clearBreakpointHighlight(); + if (Capabilities.nativeInstrumentationEnabled) { + this.sidebarPanes.domBreakpoints.clearBreakpointHighlight(); + this.sidebarPanes.eventListenerBreakpoints.clearBreakpointHighlight(); + this.sidebarPanes.xhrBreakpoints.clearBreakpointHighlight(); + } + + this._clearCurrentExecutionLine(); + this._updateDebuggerButtons(); + }, + + get debuggingEnabled() + { + return this._debuggerEnabled; + }, + + enableDebugging: function() + { + if (this._debuggerEnabled) + return; + this.toggleDebugging(this.panelEnablerView.alwaysEnabled); + }, + + disableDebugging: function() + { + if (!this._debuggerEnabled) + return; + this.toggleDebugging(this.panelEnablerView.alwaysEnabled); + }, + + toggleDebugging: function(optionalAlways) + { + this._paused = false; + this._waitingToPause = false; + this._stepping = false; + + if (this._debuggerEnabled) { + WebInspector.settings.debuggerEnabled.set(false); + WebInspector.debuggerModel.disableDebugger(); + } else { + WebInspector.settings.debuggerEnabled.set(!!optionalAlways); + WebInspector.debuggerModel.enableDebugger(); + } + }, + + _togglePauseOnExceptions: function() + { + var nextStateMap = {}; + var stateEnum = WebInspector.ScriptsPanel.PauseOnExceptionsState; + nextStateMap[stateEnum.DontPauseOnExceptions] = stateEnum.PauseOnAllExceptions; + nextStateMap[stateEnum.PauseOnAllExceptions] = stateEnum.PauseOnUncaughtExceptions; + nextStateMap[stateEnum.PauseOnUncaughtExceptions] = stateEnum.DontPauseOnExceptions; + this._setPauseOnExceptions(nextStateMap[this._pauseOnExceptionButton.state]); + }, + + _togglePause: function() + { + if (this._paused) { + this._paused = false; + this._waitingToPause = false; + DebuggerAgent.resume(); + } else { + this._stepping = false; + this._waitingToPause = true; + DebuggerAgent.pause(); + } + + this._clearInterface(); + }, + + _stepOverClicked: function() + { + if (!this._paused) + return; + + this._paused = false; + this._stepping = true; + + this._clearInterface(); + + DebuggerAgent.stepOver(); + }, + + _stepIntoClicked: function() + { + if (!this._paused) + return; + + this._paused = false; + this._stepping = true; + + this._clearInterface(); + + DebuggerAgent.stepInto(); + }, + + _stepOutClicked: function() + { + if (!this._paused) + return; + + this._paused = false; + this._stepping = true; + + this._clearInterface(); + + DebuggerAgent.stepOut(); + }, + + _toggleBreakpointsClicked: function() + { + this.toggleBreakpointsButton.toggled = !this.toggleBreakpointsButton.toggled; + if (this.toggleBreakpointsButton.toggled) { + DebuggerAgent.setBreakpointsActive(true); + this.toggleBreakpointsButton.title = WebInspector.UIString("Deactivate all breakpoints."); + WebInspector.inspectorView.element.removeStyleClass("breakpoints-deactivated"); + } else { + DebuggerAgent.setBreakpointsActive(false); + this.toggleBreakpointsButton.title = WebInspector.UIString("Activate all breakpoints."); + WebInspector.inspectorView.element.addStyleClass("breakpoints-deactivated"); + } + }, + + _evaluateSelectionInConsole: function() + { + var selection = window.getSelection(); + if (selection.type === "Range" && !selection.isCollapsed) + WebInspector.evaluateInConsole(selection.toString()); + }, + + _createDebugToolbar: function() + { + var debugToolbar = document.createElement("div"); + debugToolbar.className = "status-bar"; + debugToolbar.id = "scripts-debug-toolbar"; + + var title, handler, shortcuts; + var platformSpecificModifier = WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta; + + // Continue. + title = WebInspector.UIString("Pause script execution (%s)."); + handler = this._togglePause.bind(this); + shortcuts = []; + shortcuts.push(WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.F8)); + shortcuts.push(WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.Slash, platformSpecificModifier)); + this.pauseButton = this._createButtonAndRegisterShortcuts("scripts-pause", title, handler, shortcuts, WebInspector.UIString("Pause/Continue")); + debugToolbar.appendChild(this.pauseButton); + + // Step over. + title = WebInspector.UIString("Step over next function call (%s)."); + handler = this._stepOverClicked.bind(this); + shortcuts = []; + shortcuts.push(WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.F10)); + shortcuts.push(WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.SingleQuote, platformSpecificModifier)); + this.stepOverButton = this._createButtonAndRegisterShortcuts("scripts-step-over", title, handler, shortcuts, WebInspector.UIString("Step over")); + debugToolbar.appendChild(this.stepOverButton); + + // Step into. + title = WebInspector.UIString("Step into next function call (%s)."); + handler = this._stepIntoClicked.bind(this); + shortcuts = []; + shortcuts.push(WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.F11)); + shortcuts.push(WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.Semicolon, platformSpecificModifier)); + this.stepIntoButton = this._createButtonAndRegisterShortcuts("scripts-step-into", title, handler, shortcuts, WebInspector.UIString("Step into")); + debugToolbar.appendChild(this.stepIntoButton); + + // Step out. + title = WebInspector.UIString("Step out of current function (%s)."); + handler = this._stepOutClicked.bind(this); + shortcuts = []; + shortcuts.push(WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.F11, WebInspector.KeyboardShortcut.Modifiers.Shift)); + shortcuts.push(WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.Semicolon, WebInspector.KeyboardShortcut.Modifiers.Shift | platformSpecificModifier)); + this.stepOutButton = this._createButtonAndRegisterShortcuts("scripts-step-out", title, handler, shortcuts, WebInspector.UIString("Step out")); + debugToolbar.appendChild(this.stepOutButton); + + this.toggleBreakpointsButton = new WebInspector.StatusBarButton(WebInspector.UIString("Deactivate all breakpoints."), "toggle-breakpoints"); + this.toggleBreakpointsButton.toggled = true; + this.toggleBreakpointsButton.addEventListener("click", this._toggleBreakpointsClicked, this); + debugToolbar.appendChild(this.toggleBreakpointsButton.element); + + this.debuggerStatusElement = document.createElement("div"); + this.debuggerStatusElement.id = "scripts-debugger-status"; + debugToolbar.appendChild(this.debuggerStatusElement); + + return debugToolbar; + }, + + _createButtonAndRegisterShortcuts: function(buttonId, buttonTitle, handler, shortcuts, shortcutDescription) + { + var button = document.createElement("button"); + button.className = "status-bar-item"; + button.id = buttonId; + button.title = String.vsprintf(buttonTitle, [shortcuts[0].name]); + button.disabled = true; + button.appendChild(document.createElement("img")); + button.addEventListener("click", handler, false); + + var shortcutNames = []; + for (var i = 0; i < shortcuts.length; ++i) { + this.registerShortcut(shortcuts[i].key, handler); + shortcutNames.push(shortcuts[i].name); + } + var section = WebInspector.shortcutsScreen.section(WebInspector.UIString("Scripts Panel")); + section.addAlternateKeys(shortcutNames, shortcutDescription); + + return button; + }, + + searchCanceled: function() + { + if (this._searchView) + this._searchView.searchCanceled(); + + delete this._searchView; + delete this._searchQuery; + }, + + performSearch: function(query) + { + WebInspector.searchController.updateSearchMatchesCount(0, this); + + if (!this.visibleView) + return; + + // Call searchCanceled since it will reset everything we need before doing a new search. + this.searchCanceled(); + + this._searchView = this.visibleView; + this._searchQuery = query; + + function finishedCallback(view, searchMatches) + { + if (!searchMatches) + return; + + WebInspector.searchController.updateSearchMatchesCount(searchMatches, this); + view.jumpToFirstSearchResult(); + WebInspector.searchController.updateCurrentMatchIndex(view.currentSearchResultIndex, this); + } + + this._searchView.performSearch(query, finishedCallback.bind(this)); + }, + + jumpToNextSearchResult: function() + { + if (!this._searchView) + return; + + if (this._searchView !== this.visibleView) { + this.performSearch(this._searchQuery); + return; + } + + if (this._searchView.showingLastSearchResult()) + this._searchView.jumpToFirstSearchResult(); + else + this._searchView.jumpToNextSearchResult(); + WebInspector.searchController.updateCurrentMatchIndex(this._searchView.currentSearchResultIndex, this); + }, + + jumpToPreviousSearchResult: function() + { + if (!this._searchView) + return; + + if (this._searchView !== this.visibleView) { + this.performSearch(this._searchQuery); + if (this._searchView) + this._searchView.jumpToLastSearchResult(); + return; + } + + if (this._searchView.showingFirstSearchResult()) + this._searchView.jumpToLastSearchResult(); + else + this._searchView.jumpToPreviousSearchResult(); + WebInspector.searchController.updateCurrentMatchIndex(this._searchView.currentSearchResultIndex, this); + }, + + _toggleFormatSource: function() + { + this._toggleFormatSourceButton.toggled = !this._toggleFormatSourceButton.toggled; + this._presentationModel.setFormatSource(this._toggleFormatSourceButton.toggled); + }, + + addToWatch: function(expression) + { + this.sidebarPanes.watchExpressions.addExpression(expression); + } +} + +WebInspector.ScriptsPanel.prototype.__proto__ = WebInspector.Panel.prototype; + +/** + * @interface + */ +WebInspector.ScriptsPanel.FileSelector = function() { } + +WebInspector.ScriptsPanel.FileSelector.Events = { + FileSelected: "FileSelected", + ReleasedFocusAfterSelection: "ReleasedFocusAfterSelection" +} + +WebInspector.ScriptsPanel.FileSelector.prototype = { + /** + * @type {Element} + */ + get defaultFocusedElement() { }, + + /** + * @param {Element} element + */ + show: function(element) { }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + */ + addUISourceCode: function(uiSourceCode) { }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + * @return {boolean} + */ + isScriptSourceAdded: function(uiSourceCode) { }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + */ + revealUISourceCode: function(uiSourceCode) { return false; }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + * @param {boolean} isDirty + */ + setScriptSourceIsDirty: function(uiSourceCode, isDirty) { }, + + /** + * @param {Array.} oldUISourceCodeList + * @param {Array.} uiSourceCodeList + */ + replaceUISourceCodes: function(oldUISourceCodeList, uiSourceCodeList) { } +} + +/** + * @interface + */ +WebInspector.ScriptsPanel.EditorContainer = function() { } + +WebInspector.ScriptsPanel.EditorContainer.Events = { + EditorSelected: "EditorSelected" +} + +WebInspector.ScriptsPanel.EditorContainer.prototype = { + /** + * @type {WebInspector.SourceFrame} + */ + get currentSourceFrame() { }, + + /** + * @param {Element} element + */ + show: function(element) { }, + + /** + * @param {string} title + * @param {WebInspector.SourceFrame} sourceFrame + * @param {string} tooltip + */ + showSourceFrame: function(title, sourceFrame, tooltip) { }, + + /** + * @param {WebInspector.SourceFrame} sourceFrame + * @return {boolean} + */ + isSourceFrameOpen: function(sourceFrame) { return false; }, + + /** + * @param {Array.} oldSourceFrames + * @param {string} title + * @param {WebInspector.SourceFrame} sourceFrame + * @param {string} tooltip + */ + replaceSourceFrames: function(oldSourceFrames, title, sourceFrame, tooltip) { }, + + /** + * @param {WebInspector.SourceFrame} sourceFrame + * @param {boolean} isDirty + */ + setSourceFrameIsDirty: function(sourceFrame, isDirty) { }, + + reset: function() { } +} + +/** + * @implements {WebInspector.ScriptsPanel.FileSelector} + * @extends {WebInspector.Object} + * @constructor + */ +WebInspector.ScriptsPanel.ComboBoxFileSelector = function(presentationModel) +{ + WebInspector.Object.call(this); + this.editorToolbar = this._createEditorToolbar(); + + this._presentationModel = presentationModel; + WebInspector.settings.showScriptFolders.addChangeListener(this._showScriptFoldersSettingChanged.bind(this)); + WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerWasDisabled, this._reset, this); + this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.DebuggerReset, this._reset, this); + + this._backForwardList = []; +} + +WebInspector.ScriptsPanel.ComboBoxFileSelector.prototype = { + get defaultFocusedElement() + { + return this._filesSelectElement; + }, + + /** + * @param {Element} element + */ + show: function(element) + { + element.appendChild(this.editorToolbar); + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + */ + addUISourceCode: function(uiSourceCode) + { + if (uiSourceCode._option) + return; + + this._addOptionToFilesSelect(uiSourceCode); + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + * @return {boolean} + */ + isScriptSourceAdded: function(uiSourceCode) + { + return !!uiSourceCode._option; + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + */ + revealUISourceCode: function(uiSourceCode) + { + this._innerRevealUISourceCode(uiSourceCode, true); + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + * @param {boolean} addToHistory + */ + _innerRevealUISourceCode: function(uiSourceCode, addToHistory) + { + if (!uiSourceCode._option) + return; + + if (addToHistory) + this._addToHistory(uiSourceCode); + + this._updateBackAndForwardButtons(); + this._filesSelectElement.selectedIndex = uiSourceCode._option.index; + + return; + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + */ + _addToHistory: function(uiSourceCode) + { + var oldIndex = this._currentBackForwardIndex; + if (oldIndex >= 0) + this._backForwardList.splice(oldIndex + 1, this._backForwardList.length - oldIndex); + + // Check for a previous entry of the same object in _backForwardList. If one is found, remove it. + var previousEntryIndex = this._backForwardList.indexOf(uiSourceCode); + if (previousEntryIndex !== -1) + this._backForwardList.splice(previousEntryIndex, 1); + + this._backForwardList.push(uiSourceCode); + this._currentBackForwardIndex = this._backForwardList.length - 1; + }, + + /** + * @param {Array.} oldUISourceCodeList + * @param {Array.} uiSourceCodeList + */ + replaceUISourceCodes: function(oldUISourceCodeList, uiSourceCodeList) + { + var visible = false; + var selectedOption = this._filesSelectElement[this._filesSelectElement.selectedIndex]; + var selectedUISourceCode = selectedOption ? selectedOption._uiSourceCode : null; + for (var i = 0; i < oldUISourceCodeList.length; ++i) { + var uiSourceCode = oldUISourceCodeList[i]; + if (selectedUISourceCode === oldUISourceCodeList[i]) + visible = true; + var option = uiSourceCode._option; + // FIXME: find out why we are getting here with option detached. + if (option && this._filesSelectElement === option.parentElement) + this._filesSelectElement.removeChild(option); + } + + for (var i = 0; i < uiSourceCodeList.length; ++i) + this._addOptionToFilesSelect(uiSourceCodeList[i]); + + if (visible) + this._filesSelectElement.selectedIndex = uiSourceCodeList[0]._option.index; + }, + + _showScriptFoldersSettingChanged: function() + { + var selectedOption = this._filesSelectElement[this._filesSelectElement.selectedIndex]; + var uiSourceCode = selectedOption ? selectedOption._uiSourceCode : null; + + var options = Array.prototype.slice.call(this._filesSelectElement); + this._resetFilesSelect(); + for (var i = 0; i < options.length; ++i) { + if (options[i]._uiSourceCode) + this._addOptionToFilesSelect(options[i]._uiSourceCode); + } + + if (uiSourceCode) { + var index = uiSourceCode._option.index; + if (typeof index === "number") + this._filesSelectElement.selectedIndex = index; + } + }, + + _reset: function() + { + this._backForwardList = []; + this._currentBackForwardIndex = -1; + this._updateBackAndForwardButtons(); + this._resetFilesSelect(); + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + * @param {boolean} isDirty + */ + setScriptSourceIsDirty: function(uiSourceCode, isDirty) + { + var option = uiSourceCode._option; + if (!option) + return; + if (isDirty) + option.text = option.text.replace(/[^*]$/, "$&*"); + else + option.text = option.text.replace(/[*]$/, ""); + }, + + /** + * @return {Element} + */ + _createEditorToolbar: function() + { + var editorToolbar = document.createElement("div"); + editorToolbar.className = "status-bar"; + editorToolbar.id = "scripts-editor-toolbar"; + + this.backButton = document.createElement("button"); + this.backButton.className = "status-bar-item"; + this.backButton.id = "scripts-back"; + this.backButton.title = WebInspector.UIString("Show the previous script resource."); + this.backButton.disabled = true; + this.backButton.appendChild(document.createElement("img")); + this.backButton.addEventListener("click", this._goBack.bind(this), false); + editorToolbar.appendChild(this.backButton); + + this.forwardButton = document.createElement("button"); + this.forwardButton.className = "status-bar-item"; + this.forwardButton.id = "scripts-forward"; + this.forwardButton.title = WebInspector.UIString("Show the next script resource."); + this.forwardButton.disabled = true; + this.forwardButton.appendChild(document.createElement("img")); + this.forwardButton.addEventListener("click", this._goForward.bind(this), false); + editorToolbar.appendChild(this.forwardButton); + + this._filesSelectElement = document.createElement("select"); + this._filesSelectElement.className = "status-bar-item"; + this._filesSelectElement.id = "scripts-files"; + this._filesSelectElement.addEventListener("change", this._filesSelectChanged.bind(this, true), false); + this._filesSelectElement.addEventListener("keyup", this._filesSelectChanged.bind(this, false), false); + editorToolbar.appendChild(this._filesSelectElement); + + return editorToolbar; + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + */ + _addOptionToFilesSelect: function(uiSourceCode) + { + var showScriptFolders = WebInspector.settings.showScriptFolders.get(); + + var select = this._filesSelectElement; + if (!select.domainOptions) + select.domainOptions = {}; + if (!select.folderOptions) + select.folderOptions = {}; + + var option = document.createElement("option"); + option._uiSourceCode = uiSourceCode; + var parsedURL = uiSourceCode.url.asParsedURL(); + + const indent = WebInspector.isMac() ? "" : "\u00a0\u00a0\u00a0\u00a0"; + + option.displayName = uiSourceCode.displayName; + + var contentScriptPrefix = uiSourceCode.isContentScript ? "2:" : "0:"; + var folderName = uiSourceCode.folderName; + var domain = uiSourceCode.domain; + + if (uiSourceCode.isContentScript && domain) { + // Render extension domain as a path in structured view + folderName = domain + (folderName ? folderName : ""); + domain = ""; + } + + var folderNameForSorting = contentScriptPrefix + (domain ? domain + "\t\t" : "") + folderName; + + if (showScriptFolders) { + option.text = indent + uiSourceCode.displayName; + option.nameForSorting = folderNameForSorting + "\t/\t" + uiSourceCode.fileName; // Use '\t' to make files stick to their folder. + } else { + option.text = uiSourceCode.displayName; + // Content script should contain its domain name as a prefix + if (uiSourceCode.isContentScript && folderName) + option.text = folderName + "/" + option.text; + option.nameForSorting = contentScriptPrefix + option.text; + } + option.title = uiSourceCode.url; + + if (uiSourceCode.isContentScript) + option.addStyleClass("extension-script"); + + function insertOrdered(option) + { + function optionCompare(a, b) + { + return a.nameForSorting.localeCompare(b.nameForSorting); + } + var insertionIndex = insertionIndexForObjectInListSortedByFunction(option, select.childNodes, optionCompare); + select.insertBefore(option, insertionIndex < 0 ? null : select.childNodes.item(insertionIndex)); + } + + insertOrdered(option); + + if (uiSourceCode.isContentScript && !select.contentScriptSection) { + var contentScriptSection = document.createElement("option"); + contentScriptSection.text = "\u2014 " + WebInspector.UIString("Content scripts") + " \u2014"; + contentScriptSection.disabled = true; + contentScriptSection.nameForSorting = "1/ContentScriptSeparator"; + select.contentScriptSection = contentScriptSection; + insertOrdered(contentScriptSection); + } + + if (showScriptFolders && !uiSourceCode.isContentScript && domain && !select.domainOptions[domain]) { + var domainOption = document.createElement("option"); + domainOption.text = "\u2014 " + domain + " \u2014"; + domainOption.nameForSorting = "0:" + domain; + domainOption.disabled = true; + select.domainOptions[domain] = domainOption; + insertOrdered(domainOption); + } + + if (showScriptFolders && folderName && !select.folderOptions[folderNameForSorting]) { + var folderOption = document.createElement("option"); + folderOption.text = folderName; + folderOption.nameForSorting = folderNameForSorting; + folderOption.disabled = true; + select.folderOptions[folderNameForSorting] = folderOption; + insertOrdered(folderOption); + } + + option._uiSourceCode = uiSourceCode; + uiSourceCode._option = option; + }, + + _resetFilesSelect: function() + { + this._filesSelectElement.removeChildren(); + this._filesSelectElement.domainOptions = {}; + this._filesSelectElement.folderOptions = {}; + delete this._filesSelectElement.contentScriptSection; + }, + + _updateBackAndForwardButtons: function() + { + this.backButton.disabled = this._currentBackForwardIndex <= 0; + this.forwardButton.disabled = this._currentBackForwardIndex >= (this._backForwardList.length - 1); + }, + + _goBack: function() + { + if (this._currentBackForwardIndex <= 0) { + console.error("Can't go back from index " + this._currentBackForwardIndex); + return; + } + + var uiSourceCode = this._backForwardList[--this._currentBackForwardIndex]; + this._innerRevealUISourceCode(uiSourceCode, false); + this.dispatchEventToListeners(WebInspector.ScriptsPanel.FileSelector.Events.FileSelected, uiSourceCode); + }, + + _goForward: function() + { + if (this._currentBackForwardIndex >= this._backForwardList.length - 1) { + console.error("Can't go forward from index " + this._currentBackForwardIndex); + return; + } + + var uiSourceCode = this._backForwardList[++this._currentBackForwardIndex]; + this._innerRevealUISourceCode(uiSourceCode, false); + this.dispatchEventToListeners(WebInspector.ScriptsPanel.FileSelector.Events.FileSelected, uiSourceCode); + }, + + /** + * @param {boolean} focusSource + */ + _filesSelectChanged: function(focusSource) + { + if (this._filesSelectElement.selectedIndex === -1) + return; + + var uiSourceCode = this._filesSelectElement[this._filesSelectElement.selectedIndex]._uiSourceCode; + this._innerRevealUISourceCode(uiSourceCode, true); + this.dispatchEventToListeners(WebInspector.ScriptsPanel.FileSelector.Events.FileSelected, uiSourceCode); + if (focusSource) + this.dispatchEventToListeners(WebInspector.ScriptsPanel.FileSelector.Events.ReleasedFocusAfterSelection, uiSourceCode); + } +} + +WebInspector.ScriptsPanel.ComboBoxFileSelector.prototype.__proto__ = WebInspector.Object.prototype; + +/** + * @implements {WebInspector.ScriptsPanel.EditorContainer} + * @extends {WebInspector.Object} + * @constructor + */ +WebInspector.ScriptsPanel.SingleFileEditorContainer = function() +{ + this.element = document.createElement("div"); + this.element.className = "scripts-views-container"; +} + +WebInspector.ScriptsPanel.SingleFileEditorContainer.prototype = { + /** + * @type {WebInspector.SourceFrame} + */ + get currentSourceFrame() + { + return this._currentSourceFrame; + }, + + /** + * @param {Element} element + */ + show: function(element) + { + element.appendChild(this.element); + }, + + /** + * @param {string} title + * @param {WebInspector.SourceFrame} sourceFrame + * @param {string} tooltip + */ + showSourceFrame: function(title, sourceFrame, tooltip) + { + if (this._currentSourceFrame === sourceFrame) + return; + + if (this._currentSourceFrame) + this._currentSourceFrame.detach(); + + this._currentSourceFrame = sourceFrame; + + if (sourceFrame) + sourceFrame.show(this.element); + }, + + /** + * @param {WebInspector.SourceFrame} sourceFrame + * @return {boolean} + */ + isSourceFrameOpen: function(sourceFrame) + { + return this._currentSourceFrame && this._currentSourceFrame === sourceFrame; + }, + + /** + * @param {Array.} oldSourceFrames + * @param {string} title + * @param {WebInspector.SourceFrame} sourceFrame + * @param {string} tooltip + */ + replaceSourceFrames: function(oldSourceFrames, title, sourceFrame, tooltip) + { + this._currentSourceFrame.detach(); + this._currentSourceFrame = null; + this.showSourceFrame(title, sourceFrame, tooltip); + }, + + /** + * @param {WebInspector.SourceFrame} sourceFrame + * @param {boolean} isDirty + */ + setSourceFrameIsDirty: function(sourceFrame, isDirty) + { + // Do nothing. + }, + + reset: function() + { + if (this._currentSourceFrame) { + this._currentSourceFrame.detach(); + this._currentSourceFrame = null; + } + } +} + +WebInspector.ScriptsPanel.SingleFileEditorContainer.prototype.__proto__ = WebInspector.Object.prototype; +/* ScriptsNavigator.js */ + +/* + * Copyright (C) 2011 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: + * + * 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 GOOGLE INC. 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 GOOGLE INC. + * 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. + */ + +/** + * @implements {WebInspector.ScriptsPanel.FileSelector} + * @extends {WebInspector.Object} + * @constructor + */ +WebInspector.ScriptsNavigator = function(presentationModel) +{ + WebInspector.Object.call(this); + + this._tabbedPane = new WebInspector.TabbedPane(); + this._tabbedPane.shrinkableTabs = true; + + this._presentationModel = presentationModel; + + this._tabbedPane.element.id = "scripts-navigator-tabbed-pane"; + + this._treeSearchBox = document.createElement("div"); + this._treeSearchBox.id = "scripts-navigator-tree-search-box"; + + this._navigatorScriptsTreeElement = document.createElement("ol"); + var scriptsView = new WebInspector.View(); + scriptsView.element.addStyleClass("outline-disclosure"); + scriptsView.element.addStyleClass("navigator"); + scriptsView.element.appendChild(this._navigatorScriptsTreeElement); + this._navigatorScriptsTree = new WebInspector.NavigatorTreeOutline(this, this._navigatorScriptsTreeElement); + this._tabbedPane.appendTab(WebInspector.ScriptsNavigator.ScriptsTab, WebInspector.UIString("Scripts"), scriptsView); + this._tabbedPane.selectTab(WebInspector.ScriptsNavigator.ScriptsTab); + + this._navigatorContentScriptsTreeElement = document.createElement("ol"); + var contentScriptsView = new WebInspector.View(); + contentScriptsView.element.addStyleClass("outline-disclosure"); + contentScriptsView.element.addStyleClass("navigator"); + contentScriptsView.element.appendChild(this._navigatorContentScriptsTreeElement); + this._navigatorContentScriptsTree = new WebInspector.NavigatorTreeOutline(this, this._navigatorContentScriptsTreeElement); + this._tabbedPane.appendTab(WebInspector.ScriptsNavigator.ContentScriptsTab, WebInspector.UIString("Content scripts"), contentScriptsView); + + this._folderTreeElements = {}; + + this._scriptTreeElementsByUISourceCode = new Map(); + + WebInspector.settings.showScriptFolders.addChangeListener(this._showScriptFoldersSettingChanged.bind(this)); + + WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerWasDisabled, this._reset, this); + this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.DebuggerReset, this._reset, this); +} + +WebInspector.ScriptsNavigator.ScriptsTab = "scripts"; +WebInspector.ScriptsNavigator.ContentScriptsTab = "contentScripts"; + +WebInspector.ScriptsNavigator.prototype = { + /** + * @type {Element} + */ + get defaultFocusedElement() + { + return this._navigatorScriptsTreeElement; + }, + + /** + * @param {Element} element + */ + show: function(element) + { + this._tabbedPane.show(element); + element.appendChild(this._treeSearchBox); + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + */ + addUISourceCode: function(uiSourceCode) + { + if (this._scriptTreeElementsByUISourceCode.get(uiSourceCode)) + return; + + var scriptTitle = uiSourceCode.fileName || WebInspector.UIString("(program)"); + var scriptTreeElement = new WebInspector.NavigatorScriptTreeElement(this, uiSourceCode, scriptTitle); + this._scriptTreeElementsByUISourceCode.put(uiSourceCode, scriptTreeElement); + + var folderTreeElement = this._getOrCreateFolderTreeElement(uiSourceCode.isContentScript, uiSourceCode.domain, uiSourceCode.folderName); + folderTreeElement.appendChild(scriptTreeElement); + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + * @return {boolean} + */ + isScriptSourceAdded: function(uiSourceCode) + { + var scriptTreeElement = this._scriptTreeElementsByUISourceCode.get(uiSourceCode); + return !!scriptTreeElement; + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + */ + revealUISourceCode: function(uiSourceCode) + { + this._lastSelectedUISourceCode = uiSourceCode; + this._tabbedPane.selectTab(uiSourceCode.isContentScript ? WebInspector.ScriptsNavigator.ContentScriptsTab : WebInspector.ScriptsNavigator.ScriptsTab); + + var scriptTreeElement = this._scriptTreeElementsByUISourceCode.get(uiSourceCode); + scriptTreeElement.revealAndSelect(true); + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + * @param {boolean} isDirty + */ + setScriptSourceIsDirty: function(uiSourceCode, isDirty) + { + // Do nothing. + }, + + /** + * @param {Array.} oldUISourceCodeList + * @param {Array.} uiSourceCodeList + */ + replaceUISourceCodes: function(oldUISourceCodeList, uiSourceCodeList) + { + var selected = false; + for (var i = 0; i < oldUISourceCodeList.length; ++i) { + var uiSourceCode = oldUISourceCodeList[i]; + var treeElement = this._scriptTreeElementsByUISourceCode.get(uiSourceCode); + if (treeElement) { + if (this._lastSelectedUISourceCode && this._lastSelectedUISourceCode === uiSourceCode) + selected = true; + this.removeUISourceCode(uiSourceCode); + } + } + + for (var i = 0; i < uiSourceCodeList.length; ++i) + this.addUISourceCode(uiSourceCodeList[i]); + + if (selected) + this.revealUISourceCode(uiSourceCodeList[0]); + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + */ + scriptSelected: function(uiSourceCode) + { + this._lastSelectedUISourceCode = uiSourceCode; + this.dispatchEventToListeners(WebInspector.ScriptsPanel.FileSelector.Events.FileSelected, uiSourceCode); + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + */ + removeUISourceCode: function(uiSourceCode) + { + var treeElement = this._scriptTreeElementsByUISourceCode.get(uiSourceCode); + while (treeElement) { + var parent = treeElement.parent; + if (parent) { + if (treeElement instanceof WebInspector.NavigatorFolderTreeElement) + delete this._folderTreeElements[treeElement.folderIdentifier]; + parent.removeChild(treeElement); + if (parent.children.length) + break; + } + treeElement = parent; + } + }, + + _showScriptFoldersSettingChanged: function() + { + var uiSourceCodes = this._navigatorScriptsTree.scriptTreeElements(); + uiSourceCodes = uiSourceCodes.concat(this._navigatorContentScriptsTree.scriptTreeElements()); + this._reset(); + for (var i = 0; i < uiSourceCodes.length; ++i) + this.addUISourceCode(uiSourceCodes[i]); + + this.revealUISourceCode(this._lastSelectedUISourceCode); + }, + + _reset: function() + { + this._navigatorScriptsTree.stopSearch(); + this._navigatorScriptsTree.removeChildren(); + this._navigatorContentScriptsTree.stopSearch(); + this._navigatorContentScriptsTree.removeChildren(); + this._folderTreeElements = {}; + }, + + /** + * @param {boolean} isContentScript + * @param {string} domain + * @param {string} folderName + */ + _folderIdentifier: function(isContentScript, domain, folderName) + { + var contentScriptPrefix = isContentScript ? "0" : "1"; + return contentScriptPrefix + ":" + domain + folderName; + }, + + /** + * @param {boolean} isContentScript + * @param {string} domain + * @param {string} folderName + */ + _getOrCreateFolderTreeElement: function(isContentScript, domain, folderName) + { + var folderIdentifier = this._folderIdentifier(isContentScript, domain, folderName); + + if (this._folderTreeElements[folderIdentifier]) + return this._folderTreeElements[folderIdentifier]; + + var showScriptFolders = WebInspector.settings.showScriptFolders.get(); + + if ((domain === "" && folderName === "") || !showScriptFolders) + return isContentScript ? this._navigatorContentScriptsTree : this._navigatorScriptsTree; + + var folderTreeElement = new WebInspector.NavigatorFolderTreeElement(folderIdentifier, domain, folderName); + + var parentFolderElement; + if (folderName === "") + parentFolderElement = isContentScript ? this._navigatorContentScriptsTree : this._navigatorScriptsTree; + else + parentFolderElement = this._getOrCreateFolderTreeElement(isContentScript, domain, ""); + + parentFolderElement.appendChild(folderTreeElement); + + this._folderTreeElements[folderIdentifier] = folderTreeElement; + return folderTreeElement; + } +} + +WebInspector.ScriptsNavigator.prototype.__proto__ = WebInspector.Object.prototype; + +/** + * @constructor + * @extends {TreeOutline} + * @param {Element} element + */ +WebInspector.NavigatorTreeOutline = function(navigator, element) +{ + TreeOutline.call(this, element); + + this._navigator = navigator; + + this.comparator = WebInspector.NavigatorTreeOutline._treeElementsCompare; + + this.searchable = true; + this.searchInputElement = document.createElement("input"); +} + +WebInspector.NavigatorTreeOutline._treeElementsCompare = function compare(treeElement1, treeElement2) +{ + // Insert in the alphabetical order, first domains, then folders, then scripts. + function typeWeight(treeElement) + { + if (treeElement instanceof WebInspector.NavigatorFolderTreeElement) { + if (treeElement.isDomain) + return 1; + return 2; + } + return 3; + } + + var typeWeight1 = typeWeight(treeElement1); + var typeWeight2 = typeWeight(treeElement2); + + var result; + if (typeWeight1 > typeWeight2) + result = 1; + else if (typeWeight1 < typeWeight2) + result = -1; + else { + var title1 = treeElement1.titleText; + var title2 = treeElement2.titleText; + result = title1.localeCompare(title2); + } + return result; +} + +WebInspector.NavigatorTreeOutline.prototype = { + /** + * @return {Array.} + */ + scriptTreeElements: function() + { + var result = []; + if (this.children.length) { + for (var treeElement = this.children[0]; treeElement; treeElement = treeElement.traverseNextTreeElement(false, this, true)) { + if (treeElement instanceof WebInspector.NavigatorScriptTreeElement) + result.push(treeElement.uiSourceCode); + } + } + return result; + }, + + searchStarted: function() + { + this._navigator._treeSearchBox.appendChild(this.searchInputElement); + this._navigator._treeSearchBox.addStyleClass("visible"); + }, + + searchFinished: function() + { + this._navigator._treeSearchBox.removeChild(this.searchInputElement); + this._navigator._treeSearchBox.removeStyleClass("visible"); + }, +} + +WebInspector.NavigatorTreeOutline.prototype.__proto__ = TreeOutline.prototype; + +/** + * @constructor + * @extends {TreeElement} + * @param {string} title + * @param {Array.} iconClasses + * @param {boolean} hasChildren + * @param {boolean=} noIcon + */ +WebInspector.BaseNavigatorTreeElement = function(title, iconClasses, hasChildren, noIcon) +{ + TreeElement.call(this, "", null, hasChildren); + this._titleText = title; + this._iconClasses = iconClasses; + this._noIcon = noIcon; +} + +WebInspector.BaseNavigatorTreeElement.prototype = { + onattach: function() + { + this.listItemElement.removeChildren(); + if (this._iconClasses) { + for (var i = 0; i < this._iconClasses.length; ++i) + this.listItemElement.addStyleClass(this._iconClasses[i]); + } + + var selectionElement = document.createElement("div"); + selectionElement.className = "selection"; + this.listItemElement.appendChild(selectionElement); + + if (!this._noIcon) { + this.imageElement = document.createElement("img"); + this.imageElement.className = "icon"; + this.listItemElement.appendChild(this.imageElement); + } + + this.titleElement = document.createElement("div"); + this.titleElement.className = "base-navigator-tree-element-title"; + this._titleTextNode = document.createTextNode(""); + this._titleTextNode.textContent = this._titleText; + this.titleElement.appendChild(this._titleTextNode); + this.listItemElement.appendChild(this.titleElement); + + this.expand(); + }, + + onreveal: function() + { + if (this.listItemElement) + this.listItemElement.scrollIntoViewIfNeeded(true); + }, + + /** + * @type {string} + */ + get titleText() + { + return this._titleText; + }, + + set titleText(titleText) + { + this._titleText = titleText || ""; + this._titleTextNode.textContent = this._titleText; + }, + + /** + * @param {string} searchText + */ + matchesSearchText: function(searchText) + { + return this.titleText.match(new RegExp("^" + searchText.escapeForRegExp(), "i")); + } +} + +WebInspector.BaseNavigatorTreeElement.prototype.__proto__ = TreeElement.prototype; + +/** + * @constructor + * @extends {WebInspector.BaseNavigatorTreeElement} + * @param {string} folderIdentifier + * @param {string} domain + * @param {string} folderName + */ +WebInspector.NavigatorFolderTreeElement = function(folderIdentifier, domain, folderName) +{ + this._folderIdentifier = folderIdentifier; + this._folderName = folderName; + + var iconClass = this.isDomain ? "scripts-navigator-domain-tree-item" : "scripts-navigator-folder-tree-item"; + var title = this.isDomain ? domain : folderName.substring(1); + WebInspector.BaseNavigatorTreeElement.call(this, title, [iconClass], true); +} + +WebInspector.NavigatorFolderTreeElement.prototype = { + /** + * @type {string} + */ + get folderIdentifier() + { + return this._folderIdentifier; + }, + + /** + * @type {boolean} + */ + get isDomain() + { + return this._folderName === ""; + }, + + onattach: function() + { + WebInspector.BaseNavigatorTreeElement.prototype.onattach.call(this); + if (this._isDomain) + this.collapse(); + else + this.expand(); + } +} + +WebInspector.NavigatorFolderTreeElement.prototype.__proto__ = WebInspector.BaseNavigatorTreeElement.prototype; + +/** + * @constructor + * @extends {WebInspector.BaseNavigatorTreeElement} + * @param {WebInspector.ScriptsNavigator} navigator + * @param {WebInspector.UISourceCode} uiSourceCode + * @param {string} title + */ +WebInspector.NavigatorScriptTreeElement = function(navigator, uiSourceCode, title) +{ + WebInspector.BaseNavigatorTreeElement.call(this, title, ["scripts-navigator-script-tree-item"], false); + this._navigator = navigator; + this._uiSourceCode = uiSourceCode; + this.tooltip = uiSourceCode.url; +} + +WebInspector.NavigatorScriptTreeElement.prototype = { + /** + * @type {WebInspector.UISourceCode} + */ + get uiSourceCode() + { + return this._uiSourceCode; + }, + + /** + * @param {Event} event + */ + ondblclick: function(event) + { + this._navigator.scriptSelected(this.uiSourceCode); + }, + + onenter: function() + { + this._navigator.scriptSelected(this.uiSourceCode); + } +} + +WebInspector.NavigatorScriptTreeElement.prototype.__proto__ = WebInspector.BaseNavigatorTreeElement.prototype; +/* ResourcesPanel.js */ + +/* + * Copyright (C) 2007, 2008, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2009 Joseph Pecoraro + * + * 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. + */ + +/** + * @constructor + * @extends {WebInspector.Panel} + */ +WebInspector.ResourcesPanel = function(database) +{ + WebInspector.Panel.call(this, "resources"); + this.registerRequiredCSS("resourcesPanel.css"); + + WebInspector.settings.resourcesLastSelectedItem = WebInspector.settings.createSetting("resourcesLastSelectedItem", {}); + + this.createSplitViewWithSidebarTree(); + this.sidebarElement.addStyleClass("outline-disclosure"); + this.sidebarElement.addStyleClass("filter-all"); + this.sidebarElement.addStyleClass("children"); + this.sidebarElement.addStyleClass("small"); + + this.sidebarTreeElement.removeStyleClass("sidebar-tree"); + + this.resourcesListTreeElement = new WebInspector.StorageCategoryTreeElement(this, WebInspector.UIString("Frames"), "Frames", ["frame-storage-tree-item"]); + this.sidebarTree.appendChild(this.resourcesListTreeElement); + + this.databasesListTreeElement = new WebInspector.StorageCategoryTreeElement(this, WebInspector.UIString("Databases"), "Databases", ["database-storage-tree-item"]); + this.sidebarTree.appendChild(this.databasesListTreeElement); + + this.localStorageListTreeElement = new WebInspector.StorageCategoryTreeElement(this, WebInspector.UIString("Local Storage"), "LocalStorage", ["domstorage-storage-tree-item", "local-storage"]); + this.sidebarTree.appendChild(this.localStorageListTreeElement); + + this.sessionStorageListTreeElement = new WebInspector.StorageCategoryTreeElement(this, WebInspector.UIString("Session Storage"), "SessionStorage", ["domstorage-storage-tree-item", "session-storage"]); + this.sidebarTree.appendChild(this.sessionStorageListTreeElement); + + this.cookieListTreeElement = new WebInspector.StorageCategoryTreeElement(this, WebInspector.UIString("Cookies"), "Cookies", ["cookie-storage-tree-item"]); + this.sidebarTree.appendChild(this.cookieListTreeElement); + + this.applicationCacheListTreeElement = new WebInspector.StorageCategoryTreeElement(this, WebInspector.UIString("Application Cache"), "ApplicationCache", ["application-cache-storage-tree-item"]); + this.sidebarTree.appendChild(this.applicationCacheListTreeElement); + + this.storageViews = this.splitView.mainElement; + this.storageViews.addStyleClass("diff-container"); + + this.storageViewStatusBarItemsContainer = document.createElement("div"); + this.storageViewStatusBarItemsContainer.className = "status-bar-items"; + + this._databases = []; + this._domStorage = []; + this._cookieViews = {}; + this._origins = {}; + this._domains = {}; + + this.sidebarElement.addEventListener("mousemove", this._onmousemove.bind(this), false); + this.sidebarElement.addEventListener("mouseout", this._onmouseout.bind(this), false); + + function viewGetter() + { + return this.visibleView; + } + WebInspector.GoToLineDialog.install(this, viewGetter.bind(this)); + + WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.OnLoad, this._onLoadEventFired, this); + WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.CachedResourcesLoaded, this._cachedResourcesLoaded, this); + WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.WillLoadCachedResources, this._resetWithFrames, this); +} + +WebInspector.ResourcesPanel.prototype = { + get toolbarItemLabel() + { + return WebInspector.UIString("Resources"); + }, + + get statusBarItems() + { + return [this.storageViewStatusBarItemsContainer]; + }, + + wasShown: function() + { + WebInspector.Panel.prototype.wasShown.call(this); + this._initialize(); + }, + + _initialize: function() + { + if (!this._initialized && this.isShowing() && this._cachedResourcesWereLoaded) { + this._populateResourceTree(); + this._populateApplicationCacheTree(); + this._initDefaultSelection(); + this._initialized = true; + } + }, + + _onLoadEventFired: function() + { + this._initDefaultSelection(); + }, + + _initDefaultSelection: function() + { + if (!this._initialized) + return; + + var itemURL = WebInspector.settings.resourcesLastSelectedItem.get(); + if (itemURL) { + for (var treeElement = this.sidebarTree.children[0]; treeElement; treeElement = treeElement.traverseNextTreeElement(false, this.sidebarTree, true)) { + if (treeElement.itemURL === itemURL) { + treeElement.revealAndSelect(true); + return; + } + } + } + + var mainResource = WebInspector.inspectedPageURL && this.resourcesListTreeElement && this.resourcesListTreeElement.expanded && WebInspector.resourceTreeModel.resourceForURL(WebInspector.inspectedPageURL); + if (mainResource) + this.showResource(mainResource); + }, + + _resetWithFrames: function() + { + this.resourcesListTreeElement.removeChildren(); + this._treeElementForFrameId = {}; + this._reset(); + }, + + _reset: function() + { + this._origins = {}; + this._domains = {}; + for (var i = 0; i < this._databases.length; ++i) { + var database = this._databases[i]; + delete database._tableViews; + if (database._queryView) + database._queryView.removeEventListener(WebInspector.DatabaseQueryView.Events.SchemaUpdated, this._updateDatabaseTables, this); + delete database._queryView; + } + this._databases = []; + + var domStorageLength = this._domStorage.length; + for (var i = 0; i < this._domStorage.length; ++i) { + var domStorage = this._domStorage[i]; + delete domStorage._domStorageView; + } + this._domStorage = []; + + this._cookieViews = {}; + + this.databasesListTreeElement.removeChildren(); + this.localStorageListTreeElement.removeChildren(); + this.sessionStorageListTreeElement.removeChildren(); + this.cookieListTreeElement.removeChildren(); + + if (this.visibleView) + this.visibleView.detach(); + + this.storageViewStatusBarItemsContainer.removeChildren(); + + if (this.sidebarTree.selectedTreeElement) + this.sidebarTree.selectedTreeElement.deselect(); + }, + + _populateResourceTree: function() + { + this._treeElementForFrameId = {}; + WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameAdded, this._frameAdded, this); + WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameNavigated, this._frameNavigated, this); + WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameDetached, this._frameDetached, this); + WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.ResourceAdded, this._resourceAdded, this); + + function populateFrame(frame) + { + this._frameAdded({data:frame}); + for (var i = 0; i < frame.childFrames.length; ++i) + populateFrame.call(this, frame.childFrames[i]); + + var resources = frame.resources(); + for (var i = 0; i < resources.length; ++i) + this._resourceAdded({data:resources[i]}); + } + populateFrame.call(this, WebInspector.resourceTreeModel.mainFrame); + }, + + _frameAdded: function(event) + { + var frame = event.data; + var parentFrame = frame.parentFrame; + + var parentTreeElement = parentFrame ? this._treeElementForFrameId[parentFrame.id] : this.resourcesListTreeElement; + if (!parentTreeElement) { + console.warn("No frame to route " + frame.url + " to.") + return; + } + + var frameTreeElement = new WebInspector.FrameTreeElement(this, frame); + this._treeElementForFrameId[frame.id] = frameTreeElement; + parentTreeElement.appendChild(frameTreeElement); + }, + + _frameDetached: function(event) + { + var frame = event.data; + var frameTreeElement = this._treeElementForFrameId[frame.id]; + if (!frameTreeElement) + return; + + delete this._treeElementForFrameId[frame.id]; + if (frameTreeElement.parent) + frameTreeElement.parent.removeChild(frameTreeElement); + }, + + _resourceAdded: function(event) + { + var resource = event.data; + var frameId = resource.frameId; + + if (resource.statusCode >= 301 && resource.statusCode <= 303) + return; + + var frameTreeElement = this._treeElementForFrameId[frameId]; + if (!frameTreeElement) { + // This is a frame's main resource, it will be retained + // and re-added by the resource manager; + return; + } + + frameTreeElement.appendResource(resource); + }, + + _frameNavigated: function(event) + { + var frame = event.data; + + if (!frame.parentFrame) + this._reset(); + + var frameId = frame.id; + var frameTreeElement = this._treeElementForFrameId[frameId]; + if (frameTreeElement) + frameTreeElement.frameNavigated(frame); + + var applicationCacheFrameTreeElement = this._applicationCacheFrameElements[frameId]; + if (applicationCacheFrameTreeElement) + applicationCacheFrameTreeElement.frameNavigated(frame); + }, + + _cachedResourcesLoaded: function() + { + this._cachedResourcesWereLoaded = true; + this._initialize(); + }, + + addDatabase: function(database) + { + this._databases.push(database); + + var databaseTreeElement = new WebInspector.DatabaseTreeElement(this, database); + database._databasesTreeElement = databaseTreeElement; + this.databasesListTreeElement.appendChild(databaseTreeElement); + }, + + addDocumentURL: function(url) + { + var parsedURL = url.asParsedURL(); + if (!parsedURL) + return; + + var domain = parsedURL.host; + if (!this._domains[domain]) { + this._domains[domain] = true; + + var cookieDomainTreeElement = new WebInspector.CookieTreeElement(this, domain); + this.cookieListTreeElement.appendChild(cookieDomainTreeElement); + } + }, + + addDOMStorage: function(domStorage) + { + this._domStorage.push(domStorage); + var domStorageTreeElement = new WebInspector.DOMStorageTreeElement(this, domStorage, (domStorage.isLocalStorage ? "local-storage" : "session-storage")); + domStorage._domStorageTreeElement = domStorageTreeElement; + if (domStorage.isLocalStorage) + this.localStorageListTreeElement.appendChild(domStorageTreeElement); + else + this.sessionStorageListTreeElement.appendChild(domStorageTreeElement); + }, + + selectDatabase: function(databaseId) + { + var database; + for (var i = 0, len = this._databases.length; i < len; ++i) { + database = this._databases[i]; + if (database.id === databaseId) { + this.showDatabase(database); + database._databasesTreeElement.select(); + return; + } + } + }, + + selectDOMStorage: function(storageId) + { + var domStorage = this._domStorageForId(storageId); + if (domStorage) { + this.showDOMStorage(domStorage); + domStorage._domStorageTreeElement.select(); + } + }, + + canShowAnchorLocation: function(anchor) + { + return !!WebInspector.resourceForURL(anchor.href); + }, + + showAnchorLocation: function(anchor) + { + var resource = WebInspector.resourceForURL(anchor.href); + this.showResource(resource, anchor.lineNumber); + }, + + /** + * @param {number=} line + */ + showResource: function(resource, line) + { + var resourceTreeElement = this._findTreeElementForResource(resource); + if (resourceTreeElement) + resourceTreeElement.revealAndSelect(); + + if (typeof line === "number") { + var view = this._resourceViewForResource(resource); + if (view.canHighlightLine()) + view.highlightLine(line); + } + return true; + }, + + _showResourceView: function(resource) + { + var view = this._resourceViewForResource(resource); + if (!view) { + this.visibleView.detach(); + return; + } + if (view.searchCanceled) + view.searchCanceled(); + this._fetchAndApplyDiffMarkup(view, resource); + this._innerShowView(view); + }, + + _resourceViewForResource: function(resource) + { + if (WebInspector.ResourceView.hasTextContent(resource)) { + var treeElement = this._findTreeElementForResource(resource); + if (!treeElement) + return null; + return treeElement.sourceView(); + } + return WebInspector.ResourceView.nonSourceViewForResource(resource); + }, + + _showRevisionView: function(revision) + { + var view = this._sourceViewForRevision(revision); + this._fetchAndApplyDiffMarkup(view, revision.resource, revision); + this._innerShowView(view); + }, + + _sourceViewForRevision: function(revision) + { + var treeElement = this._findTreeElementForRevision(revision); + return treeElement.sourceView(); + }, + + /** + * @param {WebInspector.ResourceRevision=} revision + */ + _fetchAndApplyDiffMarkup: function(view, resource, revision) + { + var baseRevision = resource.history[0]; + if (!baseRevision) + return; + if (!(view instanceof WebInspector.SourceFrame)) + return; + + baseRevision.requestContent(step1.bind(this)); + + function step1(baseContent) + { + (revision ? revision : resource).requestContent(step2.bind(this, baseContent)); + } + + function step2(baseContent, revisionContent) + { + this._applyDiffMarkup(view, baseContent, revisionContent); + } + }, + + _applyDiffMarkup: function(view, baseContent, newContent) + { + var diffData = TextDiff.compute(baseContent, newContent); + view.markDiff(diffData); + }, + + /** + * @param {string=} tableName + */ + showDatabase: function(database, tableName) + { + if (!database) + return; + + var view; + if (tableName) { + if (!("_tableViews" in database)) + database._tableViews = {}; + view = database._tableViews[tableName]; + if (!view) { + view = new WebInspector.DatabaseTableView(database, tableName); + database._tableViews[tableName] = view; + } + } else { + view = database._queryView; + if (!view) { + view = new WebInspector.DatabaseQueryView(database); + database._queryView = view; + view.addEventListener(WebInspector.DatabaseQueryView.Events.SchemaUpdated, this._updateDatabaseTables, this); + } + } + + this._innerShowView(view); + }, + + showDOMStorage: function(domStorage) + { + if (!domStorage) + return; + + var view; + view = domStorage._domStorageView; + if (!view) { + view = new WebInspector.DOMStorageItemsView(domStorage); + domStorage._domStorageView = view; + } + + this._innerShowView(view); + }, + + showCookies: function(treeElement, cookieDomain) + { + var view = this._cookieViews[cookieDomain]; + if (!view) { + view = new WebInspector.CookieItemsView(treeElement, cookieDomain); + this._cookieViews[cookieDomain] = view; + } + + this._innerShowView(view); + }, + + showApplicationCache: function(frameId) + { + if (!this._applicationCacheViews[frameId]) + this._applicationCacheViews[frameId] = new WebInspector.ApplicationCacheItemsView(this._applicationCacheModel, frameId); + + this._innerShowView(this._applicationCacheViews[frameId]); + }, + + showCategoryView: function(categoryName) + { + if (!this._categoryView) + this._categoryView = new WebInspector.StorageCategoryView(); + this._categoryView.setText(categoryName); + this._innerShowView(this._categoryView); + }, + + _innerShowView: function(view) + { + if (this.visibleView) + this.visibleView.detach(); + + view.show(this.storageViews); + this.visibleView = view; + + this.storageViewStatusBarItemsContainer.removeChildren(); + var statusBarItems = view.statusBarItems || []; + for (var i = 0; i < statusBarItems.length; ++i) + this.storageViewStatusBarItemsContainer.appendChild(statusBarItems[i]); + }, + + closeVisibleView: function() + { + if (!this.visibleView) + return; + this.visibleView.detach(); + delete this.visibleView; + }, + + _updateDatabaseTables: function(event) + { + var database = event.data; + + if (!database || !database._databasesTreeElement) + return; + + database._databasesTreeElement.shouldRefreshChildren = true; + + if (!("_tableViews" in database)) + return; + + var tableNamesHash = {}; + var self = this; + function tableNamesCallback(tableNames) + { + var tableNamesLength = tableNames.length; + for (var i = 0; i < tableNamesLength; ++i) + tableNamesHash[tableNames[i]] = true; + + for (var tableName in database._tableViews) { + if (!(tableName in tableNamesHash)) { + if (self.visibleView === database._tableViews[tableName]) + self.closeVisibleView(); + delete database._tableViews[tableName]; + } + } + } + database.getTableNames(tableNamesCallback); + }, + + updateDOMStorage: function(storageId) + { + var domStorage = this._domStorageForId(storageId); + if (!domStorage) + return; + + var view = domStorage._domStorageView; + if (this.visibleView && view === this.visibleView) + domStorage._domStorageView.update(); + }, + + _populateApplicationCacheTree: function() + { + this._applicationCacheModel = new WebInspector.ApplicationCacheModel(); + + this._applicationCacheViews = {}; + this._applicationCacheFrameElements = {}; + this._applicationCacheManifestElements = {}; + + this._applicationCacheModel.addEventListener(WebInspector.ApplicationCacheModel.EventTypes.FrameManifestAdded, this._applicationCacheFrameManifestAdded, this); + this._applicationCacheModel.addEventListener(WebInspector.ApplicationCacheModel.EventTypes.FrameManifestRemoved, this._applicationCacheFrameManifestRemoved, this); + + this._applicationCacheModel.addEventListener(WebInspector.ApplicationCacheModel.EventTypes.FrameManifestStatusUpdated, this._applicationCacheFrameManifestStatusChanged, this); + this._applicationCacheModel.addEventListener(WebInspector.ApplicationCacheModel.EventTypes.NetworkStateChanged, this._applicationCacheNetworkStateChanged, this); + }, + + _applicationCacheFrameManifestAdded: function(event) + { + var frameId = event.data; + var manifestURL = this._applicationCacheModel.frameManifestURL(frameId); + var status = this._applicationCacheModel.frameManifestStatus(frameId) + + var manifestTreeElement = this._applicationCacheManifestElements[manifestURL] + if (!manifestTreeElement) { + manifestTreeElement = new WebInspector.ApplicationCacheManifestTreeElement(this, manifestURL); + this.applicationCacheListTreeElement.appendChild(manifestTreeElement); + this._applicationCacheManifestElements[manifestURL] = manifestTreeElement; + } + + var frameTreeElement = new WebInspector.ApplicationCacheFrameTreeElement(this, frameId, manifestURL); + manifestTreeElement.appendChild(frameTreeElement); + manifestTreeElement.expand(); + this._applicationCacheFrameElements[frameId] = frameTreeElement; + }, + + _applicationCacheFrameManifestRemoved: function(event) + { + var frameId = event.data; + var frameTreeElement = this._applicationCacheFrameElements[frameId]; + if (!frameTreeElement) + return; + + var manifestURL = frameTreeElement.manifestURL; + delete this._applicationCacheFrameElements[frameId]; + delete this._applicationCacheViews[frameId]; + frameTreeElement.parent.removeChild(frameTreeElement); + + var manifestTreeElement = this._applicationCacheManifestElements[manifestURL]; + if (manifestTreeElement.children.length !== 0) + return; + + delete this._applicationCacheManifestElements[manifestURL]; + manifestTreeElement.parent.removeChild(manifestTreeElement); + }, + + _applicationCacheFrameManifestStatusChanged: function(event) + { + var frameId = event.data; + var status = this._applicationCacheModel.frameManifestStatus(frameId) + + if (this._applicationCacheViews[frameId]) + this._applicationCacheViews[frameId].updateStatus(status); + }, + + _applicationCacheNetworkStateChanged: function(event) + { + var isNowOnline = event.data; + + for (var manifestURL in this._applicationCacheViews) + this._applicationCacheViews[manifestURL].updateNetworkState(isNowOnline); + }, + + _domStorageForId: function(storageId) + { + if (!this._domStorage) + return null; + var domStorageLength = this._domStorage.length; + for (var i = 0; i < domStorageLength; ++i) { + var domStorage = this._domStorage[i]; + if (domStorage.id == storageId) + return domStorage; + } + return null; + }, + + sidebarResized: function(event) + { + var width = event.data; + this.storageViewStatusBarItemsContainer.style.left = width + "px"; + }, + + performSearch: function(query) + { + this._resetSearchResults(); + var regex = WebInspector.SourceFrame.createSearchRegex(query); + var totalMatchesCount = 0; + + function searchInEditedResource(treeElement) + { + var resource = treeElement.representedObject; + if (resource.history.length == 0) + return; + var matchesCount = countRegexMatches(regex, resource.content) + treeElement.searchMatchesFound(matchesCount); + totalMatchesCount += matchesCount; + } + + function callback(error, result) + { + if (!error) { + for (var i = 0; i < result.length; i++) { + var searchResult = result[i]; + var frameTreeElement = this._treeElementForFrameId[searchResult.frameId]; + if (!frameTreeElement) + continue; + var resource = frameTreeElement.resourceByURL(searchResult.url); + + // FIXME: When the same script is used in several frames and this script contains at least + // one search result then some search results can not be matched with a resource on panel. + // https://bugs.webkit.org/show_bug.cgi?id=66005 + if (!resource) + continue; + + if (resource.history.length > 0) + continue; // Skip edited resources. + this._findTreeElementForResource(resource).searchMatchesFound(searchResult.matchesCount); + totalMatchesCount += searchResult.matchesCount; + } + } + + WebInspector.searchController.updateSearchMatchesCount(totalMatchesCount, this); + this._searchController = new WebInspector.ResourcesSearchController(this.resourcesListTreeElement, totalMatchesCount); + + if (this.sidebarTree.selectedTreeElement && this.sidebarTree.selectedTreeElement.searchMatchesCount) + this.jumpToNextSearchResult(); + } + + this._forAllResourceTreeElements(searchInEditedResource.bind(this)); + PageAgent.searchInResources(regex.source, !regex.ignoreCase, true, callback.bind(this)); + }, + + _ensureViewSearchPerformed: function(callback) + { + function viewSearchPerformedCallback(searchId) + { + if (searchId !== this._lastViewSearchId) + return; // Search is obsolete. + this._viewSearchInProgress = false; + callback(); + } + + if (!this._viewSearchInProgress) { + if (!this.visibleView.hasSearchResults()) { + // We give id to each search, so that we can skip callbacks for obsolete searches. + this._lastViewSearchId = this._lastViewSearchId ? this._lastViewSearchId + 1 : 0; + this._viewSearchInProgress = true; + this.visibleView.performSearch(this.currentQuery, viewSearchPerformedCallback.bind(this, this._lastViewSearchId)); + } else + callback(); + } + }, + + _showSearchResult: function(searchResult) + { + this._lastSearchResultIndex = searchResult.index; + this._lastSearchResultTreeElement = searchResult.treeElement; + + // At first show view for treeElement. + if (searchResult.treeElement !== this.sidebarTree.selectedTreeElement) { + this.showResource(searchResult.treeElement.representedObject); + WebInspector.searchController.focusSearchField(); + } + + function callback(searchId) + { + if (this.sidebarTree.selectedTreeElement !== this._lastSearchResultTreeElement) + return; // User has selected another view while we were searching. + if (this._lastSearchResultIndex != -1) + this.visibleView.jumpToSearchResult(this._lastSearchResultIndex); + WebInspector.searchController.updateCurrentMatchIndex(searchResult.currentMatchIndex - 1, this); + } + + // Then run SourceFrame search if needed and jump to search result index when done. + this._ensureViewSearchPerformed(callback.bind(this)); + }, + + _resetSearchResults: function() + { + function callback(resourceTreeElement) + { + resourceTreeElement._resetSearchResults(); + } + + this._forAllResourceTreeElements(callback); + if (this.visibleView && this.visibleView.searchCanceled) + this.visibleView.searchCanceled(); + + this._lastSearchResultTreeElement = null; + this._lastSearchResultIndex = -1; + this._viewSearchInProgress = false; + }, + + searchCanceled: function() + { + function callback(resourceTreeElement) + { + resourceTreeElement._updateErrorsAndWarningsBubbles(); + } + + WebInspector.searchController.updateSearchMatchesCount(0, this); + this._resetSearchResults(); + this._forAllResourceTreeElements(callback); + }, + + jumpToNextSearchResult: function() + { + if (!this.currentSearchMatches) + return; + var currentTreeElement = this.sidebarTree.selectedTreeElement; + var nextSearchResult = this._searchController.nextSearchResult(currentTreeElement); + this._showSearchResult(nextSearchResult); + }, + + jumpToPreviousSearchResult: function() + { + if (!this.currentSearchMatches) + return; + var currentTreeElement = this.sidebarTree.selectedTreeElement; + var previousSearchResult = this._searchController.previousSearchResult(currentTreeElement); + this._showSearchResult(previousSearchResult); + }, + + _forAllResourceTreeElements: function(callback) + { + var stop = false; + for (var treeElement = this.resourcesListTreeElement; !stop && treeElement; treeElement = treeElement.traverseNextTreeElement(false, this.resourcesListTreeElement, true)) { + if (treeElement instanceof WebInspector.FrameResourceTreeElement) + stop = callback(treeElement); + } + }, + + _findTreeElementForResource: function(resource) + { + function isAncestor(ancestor, object) + { + // Redirects, XHRs do not belong to the tree, it is fine to silently return false here. + return false; + } + + function getParent(object) + { + // Redirects, XHRs do not belong to the tree, it is fine to silently return false here. + return null; + } + + return this.sidebarTree.findTreeElement(resource, isAncestor, getParent); + }, + + _findTreeElementForRevision: function(revision) + { + function isAncestor(ancestor, object) + { + return false; + } + + function getParent(object) + { + return null; + } + + return this.sidebarTree.findTreeElement(revision, isAncestor, getParent); + }, + + showView: function(view) + { + if (view) + this.showResource(view.resource); + }, + + _onmousemove: function(event) + { + var nodeUnderMouse = document.elementFromPoint(event.pageX, event.pageY); + if (!nodeUnderMouse) + return; + + var listNode = nodeUnderMouse.enclosingNodeOrSelfWithNodeName("li"); + if (!listNode) + return; + + var element = listNode.treeElement; + if (this._previousHoveredElement === element) + return; + + if (this._previousHoveredElement) { + this._previousHoveredElement.hovered = false; + delete this._previousHoveredElement; + } + + if (element instanceof WebInspector.FrameTreeElement) { + this._previousHoveredElement = element; + element.hovered = true; + } + }, + + _onmouseout: function(event) + { + if (this._previousHoveredElement) { + this._previousHoveredElement.hovered = false; + delete this._previousHoveredElement; + } + } +} + +WebInspector.ResourcesPanel.prototype.__proto__ = WebInspector.Panel.prototype; + +/** + * @constructor + * @extends {TreeElement} + * @param {boolean=} hasChildren + * @param {boolean=} noIcon + */ +WebInspector.BaseStorageTreeElement = function(storagePanel, representedObject, title, iconClasses, hasChildren, noIcon) +{ + TreeElement.call(this, "", representedObject, hasChildren); + this._storagePanel = storagePanel; + this._titleText = title; + this._iconClasses = iconClasses; + this._noIcon = noIcon; +} + +WebInspector.BaseStorageTreeElement.prototype = { + onattach: function() + { + this.listItemElement.removeChildren(); + if (this._iconClasses) { + for (var i = 0; i < this._iconClasses.length; ++i) + this.listItemElement.addStyleClass(this._iconClasses[i]); + } + + var selectionElement = document.createElement("div"); + selectionElement.className = "selection"; + this.listItemElement.appendChild(selectionElement); + + if (!this._noIcon) { + this.imageElement = document.createElement("img"); + this.imageElement.className = "icon"; + this.listItemElement.appendChild(this.imageElement); + } + + this.titleElement = document.createElement("div"); + this.titleElement.className = "base-storage-tree-element-title"; + this._titleTextNode = document.createTextNode(""); + this.titleElement.appendChild(this._titleTextNode); + this._updateTitle(); + this._updateSubtitle(); + this.listItemElement.appendChild(this.titleElement); + }, + + get displayName() + { + return this._displayName; + }, + + _updateDisplayName: function() + { + this._displayName = this._titleText || ""; + if (this._subtitleText) + this._displayName += " (" + this._subtitleText + ")"; + }, + + _updateTitle: function() + { + this._updateDisplayName(); + + if (!this.titleElement) + return; + + this._titleTextNode.textContent = this._titleText || ""; + }, + + _updateSubtitle: function() + { + this._updateDisplayName(); + + if (!this.titleElement) + return; + + if (this._subtitleText) { + if (!this._subtitleElement) { + this._subtitleElement = document.createElement("span"); + this._subtitleElement.className = "base-storage-tree-element-subtitle"; + this.titleElement.appendChild(this._subtitleElement); + } + this._subtitleElement.textContent = "(" + this._subtitleText + ")"; + } else if (this._subtitleElement) { + this.titleElement.removeChild(this._subtitleElement); + delete this._subtitleElement; + } + }, + + onselect: function() + { + var itemURL = this.itemURL; + if (itemURL) + WebInspector.settings.resourcesLastSelectedItem.set(itemURL); + }, + + onreveal: function() + { + if (this.listItemElement) + this.listItemElement.scrollIntoViewIfNeeded(false); + }, + + get titleText() + { + return this._titleText; + }, + + set titleText(titleText) + { + this._titleText = titleText; + this._updateTitle(); + }, + + get subtitleText() + { + return this._subtitleText; + }, + + set subtitleText(subtitleText) + { + this._subtitleText = subtitleText; + this._updateSubtitle(); + }, + + get searchMatchesCount() + { + return 0; + } +} + +WebInspector.BaseStorageTreeElement.prototype.__proto__ = TreeElement.prototype; + +/** + * @constructor + * @extends {WebInspector.BaseStorageTreeElement} + * @param {boolean=} noIcon + */ +WebInspector.StorageCategoryTreeElement = function(storagePanel, categoryName, settingsKey, iconClasses, noIcon) +{ + WebInspector.BaseStorageTreeElement.call(this, storagePanel, null, categoryName, iconClasses, true, noIcon); + this._expandedSettingKey = "resources" + settingsKey + "Expanded"; + WebInspector.settings[this._expandedSettingKey] = WebInspector.settings.createSetting(this._expandedSettingKey, settingsKey === "Frames"); + this._categoryName = categoryName; +} + +WebInspector.StorageCategoryTreeElement.prototype = { + get itemURL() + { + return "category://" + this._categoryName; + }, + + onselect: function() + { + WebInspector.BaseStorageTreeElement.prototype.onselect.call(this); + this._storagePanel.showCategoryView(this._categoryName); + }, + + onattach: function() + { + WebInspector.BaseStorageTreeElement.prototype.onattach.call(this); + if (WebInspector.settings[this._expandedSettingKey].get()) + this.expand(); + }, + + onexpand: function() + { + WebInspector.settings[this._expandedSettingKey].set(true); + }, + + oncollapse: function() + { + WebInspector.settings[this._expandedSettingKey].set(false); + } +} + +WebInspector.StorageCategoryTreeElement.prototype.__proto__ = WebInspector.BaseStorageTreeElement.prototype; + +/** + * @constructor + * @extends {WebInspector.BaseStorageTreeElement} + */ +WebInspector.FrameTreeElement = function(storagePanel, frame) +{ + WebInspector.BaseStorageTreeElement.call(this, storagePanel, null, "", ["frame-storage-tree-item"]); + this._frame = frame; + this.frameNavigated(frame); +} + +WebInspector.FrameTreeElement.prototype = { + frameNavigated: function(frame) + { + this.removeChildren(); + this._frameId = frame.id; + + this.titleText = frame.name; + this.subtitleText = WebInspector.Resource.displayName(frame.url); + + this._categoryElements = {}; + this._treeElementForResource = {}; + + this._storagePanel.addDocumentURL(frame.url); + }, + + get itemURL() + { + return "frame://" + encodeURI(this.displayName); + }, + + onselect: function() + { + WebInspector.BaseStorageTreeElement.prototype.onselect.call(this); + this._storagePanel.showCategoryView(this.displayName); + + this.listItemElement.removeStyleClass("hovered"); + DOMAgent.hideHighlight(); + }, + + set hovered(hovered) + { + if (hovered) { + this.listItemElement.addStyleClass("hovered"); + DOMAgent.highlightFrame(this._frameId, WebInspector.Color.PageHighlight.Content.toProtocolRGBA(), WebInspector.Color.PageHighlight.ContentOutline.toProtocolRGBA()); + } else { + this.listItemElement.removeStyleClass("hovered"); + DOMAgent.hideHighlight(); + } + }, + + appendResource: function(resource) + { + var categoryName = resource.category.name; + var categoryElement = resource.category === WebInspector.resourceCategories.documents ? this : this._categoryElements[categoryName]; + if (!categoryElement) { + categoryElement = new WebInspector.StorageCategoryTreeElement(this._storagePanel, resource.category.title, categoryName, null, true); + this._categoryElements[resource.category.name] = categoryElement; + this._insertInPresentationOrder(this, categoryElement); + } + var resourceTreeElement = new WebInspector.FrameResourceTreeElement(this._storagePanel, resource); + this._insertInPresentationOrder(categoryElement, resourceTreeElement); + resourceTreeElement._populateRevisions(); + + this._treeElementForResource[resource.url] = resourceTreeElement; + }, + + resourceByURL: function(url) + { + var treeElement = this._treeElementForResource[url]; + return treeElement ? treeElement.representedObject : null; + }, + + appendChild: function(treeElement) + { + this._insertInPresentationOrder(this, treeElement); + }, + + _insertInPresentationOrder: function(parentTreeElement, childTreeElement) + { + // Insert in the alphabetical order, first frames, then resources. Document resource goes last. + function typeWeight(treeElement) + { + if (treeElement instanceof WebInspector.StorageCategoryTreeElement) + return 2; + if (treeElement instanceof WebInspector.FrameTreeElement) + return 1; + return 3; + } + + function compare(treeElement1, treeElement2) + { + var typeWeight1 = typeWeight(treeElement1); + var typeWeight2 = typeWeight(treeElement2); + + var result; + if (typeWeight1 > typeWeight2) + result = 1; + else if (typeWeight1 < typeWeight2) + result = -1; + else { + var title1 = treeElement1.displayName || treeElement1.titleText; + var title2 = treeElement2.displayName || treeElement2.titleText; + result = title1.localeCompare(title2); + } + return result; + } + + var children = parentTreeElement.children; + var i; + for (i = 0; i < children.length; ++i) { + if (compare(childTreeElement, children[i]) < 0) + break; + } + parentTreeElement.insertChild(childTreeElement, i); + } +} + +WebInspector.FrameTreeElement.prototype.__proto__ = WebInspector.BaseStorageTreeElement.prototype; + +/** + * @constructor + * @extends {WebInspector.BaseStorageTreeElement} + */ +WebInspector.FrameResourceTreeElement = function(storagePanel, resource) +{ + WebInspector.BaseStorageTreeElement.call(this, storagePanel, resource, resource.displayName, ["resource-sidebar-tree-item", "resources-category-" + resource.category.name]); + this._resource = resource; + this._resource.addEventListener(WebInspector.Resource.Events.MessageAdded, this._consoleMessageAdded, this); + this._resource.addEventListener(WebInspector.Resource.Events.MessagesCleared, this._consoleMessagesCleared, this); + this._resource.addEventListener(WebInspector.Resource.Events.RevisionAdded, this._revisionAdded, this); + this.tooltip = resource.url; +} + +WebInspector.FrameResourceTreeElement.prototype = { + get itemURL() + { + return this._resource.url; + }, + + onselect: function() + { + WebInspector.BaseStorageTreeElement.prototype.onselect.call(this); + this._storagePanel._showResourceView(this._resource); + }, + + ondblclick: function(event) + { + InspectorFrontendHost.openInNewTab(this._resource.url); + }, + + onattach: function() + { + WebInspector.BaseStorageTreeElement.prototype.onattach.call(this); + + if (this._resource.category === WebInspector.resourceCategories.images) { + var previewImage = document.createElement("img"); + previewImage.className = "image-resource-icon-preview"; + this._resource.populateImageSource(previewImage); + + var iconElement = document.createElement("div"); + iconElement.className = "icon"; + iconElement.appendChild(previewImage); + this.listItemElement.replaceChild(iconElement, this.imageElement); + } + + this._statusElement = document.createElement("div"); + this._statusElement.className = "status"; + this.listItemElement.insertBefore(this._statusElement, this.titleElement); + + this.listItemElement.draggable = true; + this.listItemElement.addEventListener("dragstart", this._ondragstart.bind(this), false); + this.listItemElement.addEventListener("contextmenu", this._handleContextMenuEvent.bind(this), true); + + this._updateErrorsAndWarningsBubbles(); + }, + + _ondragstart: function(event) + { + event.dataTransfer.setData("text/plain", this._resource.content); + event.dataTransfer.effectAllowed = "copy"; + return true; + }, + + _handleContextMenuEvent: function(event) + { + var contextMenu = new WebInspector.ContextMenu(); + contextMenu.appendItem(WebInspector.openLinkExternallyLabel(), WebInspector.openResource.bind(WebInspector, this._resource.url, false)); + this._appendOpenInNetworkPanelAction(contextMenu, event); + WebInspector.populateResourceContextMenu(contextMenu, this._resource.url, null); + this._appendSaveAsAction(contextMenu, event); + contextMenu.show(event); + }, + + _appendOpenInNetworkPanelAction: function(contextMenu, event) + { + if (!this._resource.requestId) + return; + + contextMenu.appendItem(WebInspector.openInNetworkPanelLabel(), WebInspector.openRequestInNetworkPanel.bind(WebInspector, this._resource)); + }, + + _appendSaveAsAction: function(contextMenu, event) + { + if (!InspectorFrontendHost.canSaveAs()) + return; + + if (this._resource.type !== WebInspector.Resource.Type.Document && + this._resource.type !== WebInspector.Resource.Type.Stylesheet && + this._resource.type !== WebInspector.Resource.Type.Script) + return; + + function save() + { + var fileName = this._resource.displayName; + this._resource.requestContent(InspectorFrontendHost.saveAs.bind(InspectorFrontendHost, fileName)); + } + + contextMenu.appendSeparator(); + contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Save as..." : "Save As..."), save.bind(this)); + }, + + _setBubbleText: function(x) + { + if (!this._bubbleElement) { + this._bubbleElement = document.createElement("div"); + this._bubbleElement.className = "bubble"; + this._statusElement.appendChild(this._bubbleElement); + } + + this._bubbleElement.textContent = x; + }, + + _resetBubble: function() + { + if (this._bubbleElement) { + this._bubbleElement.textContent = ""; + this._bubbleElement.removeStyleClass("search-matches"); + this._bubbleElement.removeStyleClass("warning"); + this._bubbleElement.removeStyleClass("error"); + } + }, + + _resetSearchResults: function() + { + this._resetBubble(); + this._searchMatchesCount = 0; + }, + + get searchMatchesCount() + { + return this._searchMatchesCount; + }, + + searchMatchesFound: function(matchesCount) + { + this._resetSearchResults(); + + this._searchMatchesCount = matchesCount; + this._setBubbleText(matchesCount); + this._bubbleElement.addStyleClass("search-matches"); + + // Expand, do not scroll into view. + var currentAncestor = this.parent; + while (currentAncestor && !currentAncestor.root) { + if (!currentAncestor.expanded) + currentAncestor.expand(); + currentAncestor = currentAncestor.parent; + } + }, + + _updateErrorsAndWarningsBubbles: function() + { + if (this._storagePanel.currentQuery) + return; + + this._resetBubble(); + + if (this._resource.warnings || this._resource.errors) + this._setBubbleText(this._resource.warnings + this._resource.errors); + + if (this._resource.warnings) + this._bubbleElement.addStyleClass("warning"); + + if (this._resource.errors) + this._bubbleElement.addStyleClass("error"); + }, + + _consoleMessagesCleared: function() + { + // FIXME: move to the SourceFrame. + if (this._sourceView) + this._sourceView.clearMessages(); + + this._updateErrorsAndWarningsBubbles(); + }, + + _consoleMessageAdded: function(event) + { + var msg = event.data; + if (this._sourceView) + this._sourceView.addMessage(msg); + this._updateErrorsAndWarningsBubbles(); + }, + + _populateRevisions: function() + { + for (var i = 0; i < this._resource.history.length; ++i) + this._appendRevision(this._resource.history[i]); + }, + + _revisionAdded: function(event) + { + this._appendRevision(event.data); + }, + + _appendRevision: function(revision) + { + this.insertChild(new WebInspector.ResourceRevisionTreeElement(this._storagePanel, revision), 0); + var oldView = this._sourceView; + if (oldView) { + // This is needed when resource content was changed from scripts panel. + var newView = this._recreateSourceView(); + if (oldView === this._storagePanel.visibleView) + this._storagePanel._showResourceView(this._resource); + } + }, + + sourceView: function() + { + if (!this._sourceView) { + this._sourceView = this._createSourceView(); + if (this._resource.messages) { + for (var i = 0; i < this._resource.messages.length; i++) + this._sourceView.addMessage(this._resource.messages[i]); + } + } + return this._sourceView; + }, + + _createSourceView: function() + { + return new WebInspector.EditableResourceSourceFrame(this._resource); + }, + + _recreateSourceView: function() + { + var oldView = this._sourceView; + var newView = this._createSourceView(); + + var oldViewParentNode = oldView.isShowing() ? oldView.element.parentNode : null; + newView.inheritScrollPositions(oldView); + + this._sourceView.detach(); + this._sourceView = newView; + + if (oldViewParentNode) + newView.show(oldViewParentNode); + + return newView; + } +} + +WebInspector.FrameResourceTreeElement.prototype.__proto__ = WebInspector.BaseStorageTreeElement.prototype; + +/** + * @constructor + * @extends {WebInspector.BaseStorageTreeElement} + */ +WebInspector.DatabaseTreeElement = function(storagePanel, database) +{ + WebInspector.BaseStorageTreeElement.call(this, storagePanel, null, database.name, ["database-storage-tree-item"], true); + this._database = database; +} + +WebInspector.DatabaseTreeElement.prototype = { + get itemURL() + { + return "database://" + encodeURI(this._database.name); + }, + + onselect: function() + { + WebInspector.BaseStorageTreeElement.prototype.onselect.call(this); + this._storagePanel.showDatabase(this._database); + }, + + onexpand: function() + { + this._updateChildren(); + }, + + _updateChildren: function() + { + this.removeChildren(); + + function tableNamesCallback(tableNames) + { + var tableNamesLength = tableNames.length; + for (var i = 0; i < tableNamesLength; ++i) + this.appendChild(new WebInspector.DatabaseTableTreeElement(this._storagePanel, this._database, tableNames[i])); + } + this._database.getTableNames(tableNamesCallback.bind(this)); + } +} + +WebInspector.DatabaseTreeElement.prototype.__proto__ = WebInspector.BaseStorageTreeElement.prototype; + +/** + * @constructor + * @extends {WebInspector.BaseStorageTreeElement} + */ +WebInspector.DatabaseTableTreeElement = function(storagePanel, database, tableName) +{ + WebInspector.BaseStorageTreeElement.call(this, storagePanel, null, tableName, ["database-storage-tree-item"]); + this._database = database; + this._tableName = tableName; +} + +WebInspector.DatabaseTableTreeElement.prototype = { + get itemURL() + { + return "database://" + encodeURI(this._database.name) + "/" + encodeURI(this._tableName); + }, + + onselect: function() + { + WebInspector.BaseStorageTreeElement.prototype.onselect.call(this); + this._storagePanel.showDatabase(this._database, this._tableName); + } +} +WebInspector.DatabaseTableTreeElement.prototype.__proto__ = WebInspector.BaseStorageTreeElement.prototype; + +/** + * @constructor + * @extends {WebInspector.BaseStorageTreeElement} + */ +WebInspector.DOMStorageTreeElement = function(storagePanel, domStorage, className) +{ + WebInspector.BaseStorageTreeElement.call(this, storagePanel, null, domStorage.domain ? domStorage.domain : WebInspector.UIString("Local Files"), ["domstorage-storage-tree-item", className]); + this._domStorage = domStorage; +} + +WebInspector.DOMStorageTreeElement.prototype = { + get itemURL() + { + return "storage://" + this._domStorage.domain + "/" + (this._domStorage.isLocalStorage ? "local" : "session"); + }, + + onselect: function() + { + WebInspector.BaseStorageTreeElement.prototype.onselect.call(this); + this._storagePanel.showDOMStorage(this._domStorage); + } +} +WebInspector.DOMStorageTreeElement.prototype.__proto__ = WebInspector.BaseStorageTreeElement.prototype; + +/** + * @constructor + * @extends {WebInspector.BaseStorageTreeElement} + */ +WebInspector.CookieTreeElement = function(storagePanel, cookieDomain) +{ + WebInspector.BaseStorageTreeElement.call(this, storagePanel, null, cookieDomain ? cookieDomain : WebInspector.UIString("Local Files"), ["cookie-storage-tree-item"]); + this._cookieDomain = cookieDomain; +} + +WebInspector.CookieTreeElement.prototype = { + get itemURL() + { + return "cookies://" + this._cookieDomain; + }, + + onselect: function() + { + WebInspector.BaseStorageTreeElement.prototype.onselect.call(this); + this._storagePanel.showCookies(this, this._cookieDomain); + } +} +WebInspector.CookieTreeElement.prototype.__proto__ = WebInspector.BaseStorageTreeElement.prototype; + +/** + * @constructor + * @extends {WebInspector.BaseStorageTreeElement} + */ +WebInspector.ApplicationCacheManifestTreeElement = function(storagePanel, manifestURL) +{ + var title = WebInspector.Resource.displayName(manifestURL); + WebInspector.BaseStorageTreeElement.call(this, storagePanel, null, title, ["application-cache-storage-tree-item"]); + this.tooltip = manifestURL; + this._manifestURL = manifestURL; +} + +WebInspector.ApplicationCacheManifestTreeElement.prototype = { + get itemURL() + { + return "appcache://" + this._manifestURL; + }, + + get manifestURL() + { + return this._manifestURL; + }, + + onselect: function() + { + WebInspector.BaseStorageTreeElement.prototype.onselect.call(this); + this._storagePanel.showCategoryView(this._manifestURL); + } +} +WebInspector.ApplicationCacheManifestTreeElement.prototype.__proto__ = WebInspector.BaseStorageTreeElement.prototype; + +/** + * @constructor + * @extends {WebInspector.BaseStorageTreeElement} + */ +WebInspector.ApplicationCacheFrameTreeElement = function(storagePanel, frameId, manifestURL) +{ + WebInspector.BaseStorageTreeElement.call(this, storagePanel, null, "", ["frame-storage-tree-item"]); + this._frameId = frameId; + this._manifestURL = manifestURL; + this._refreshTitles(); +} + +WebInspector.ApplicationCacheFrameTreeElement.prototype = { + get itemURL() + { + return "appcache://" + this._manifestURL + "/" + encodeURI(this.displayName); + }, + + get frameId() + { + return this._frameId; + }, + + get manifestURL() + { + return this._manifestURL; + }, + + _refreshTitles: function() + { + var frame = WebInspector.resourceTreeModel.frameForId(this._frameId); + if (!frame) { + this.subtitleText = WebInspector.UIString("new frame"); + return; + } + this.titleText = frame.name; + this.subtitleText = WebInspector.Resource.displayName(frame.url); + }, + + frameNavigated: function() + { + this._refreshTitles(); + }, + + onselect: function() + { + WebInspector.BaseStorageTreeElement.prototype.onselect.call(this); + this._storagePanel.showApplicationCache(this._frameId); + } +} +WebInspector.ApplicationCacheFrameTreeElement.prototype.__proto__ = WebInspector.BaseStorageTreeElement.prototype; + +/** + * @constructor + * @extends {WebInspector.BaseStorageTreeElement} + */ +WebInspector.ResourceRevisionTreeElement = function(storagePanel, revision) +{ + var title = revision.timestamp ? revision.timestamp.toLocaleTimeString() : WebInspector.UIString("(original)"); + WebInspector.BaseStorageTreeElement.call(this, storagePanel, revision, title, ["resource-sidebar-tree-item", "resources-category-" + revision.resource.category.name]); + if (revision.timestamp) + this.tooltip = revision.timestamp.toLocaleString(); + this._revision = revision; +} + +WebInspector.ResourceRevisionTreeElement.prototype = { + get itemURL() + { + return this._revision.resource.url; + }, + + onattach: function() + { + WebInspector.BaseStorageTreeElement.prototype.onattach.call(this); + this.listItemElement.draggable = true; + this.listItemElement.addEventListener("dragstart", this._ondragstart.bind(this), false); + this.listItemElement.addEventListener("contextmenu", this._handleContextMenuEvent.bind(this), true); + }, + + onselect: function() + { + WebInspector.BaseStorageTreeElement.prototype.onselect.call(this); + this._storagePanel._showRevisionView(this._revision); + }, + + _ondragstart: function(event) + { + if (this._revision.content) { + event.dataTransfer.setData("text/plain", this._revision.content); + event.dataTransfer.effectAllowed = "copy"; + return true; + } + }, + + _handleContextMenuEvent: function(event) + { + var contextMenu = new WebInspector.ContextMenu(); + contextMenu.appendItem(WebInspector.UIString("Revert to this revision"), this._revision.revertToThis.bind(this._revision)); + + if (InspectorFrontendHost.canSaveAs()) { + function save() + { + var fileName = this._revision.resource.displayName; + this._revision.requestContent(InspectorFrontendHost.saveAs.bind(InspectorFrontendHost, fileName)); + } + contextMenu.appendSeparator(); + contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Save as..." : "Save As..."), save.bind(this)); + } + + contextMenu.show(event); + }, + + sourceView: function() + { + if (!this._sourceView) + this._sourceView = new WebInspector.ResourceRevisionSourceFrame(this._revision); + return this._sourceView; + } +} + +WebInspector.ResourceRevisionTreeElement.prototype.__proto__ = WebInspector.BaseStorageTreeElement.prototype; + +/** + * @constructor + * @extends {WebInspector.View} + */ +WebInspector.StorageCategoryView = function() +{ + WebInspector.View.call(this); + + this.element.addStyleClass("storage-view"); + this._emptyView = new WebInspector.EmptyView(""); + this._emptyView.show(this.element); +} + +WebInspector.StorageCategoryView.prototype = { + setText: function(text) + { + this._emptyView.text = text; + } +} + +WebInspector.StorageCategoryView.prototype.__proto__ = WebInspector.View.prototype; + +/** + * @constructor + * @param {WebInspector.BaseStorageTreeElement} rootElement + * @param {number} matchesCount + */ +WebInspector.ResourcesSearchController = function(rootElement, matchesCount) +{ + this._root = rootElement; + this._matchesCount = matchesCount; + this._traverser = new WebInspector.SearchResultsTreeElementsTraverser(rootElement); + this._lastTreeElement = null; + this._lastIndex = -1; +} + +WebInspector.ResourcesSearchController.prototype = { + /** + * @param {WebInspector.BaseStorageTreeElement} currentTreeElement + */ + nextSearchResult: function(currentTreeElement) + { + if (!currentTreeElement) + return this._searchResult(this._traverser.first(), 0, 1); + + if (!currentTreeElement.searchMatchesCount) + return this._searchResult(this._traverser.next(currentTreeElement), 0); + + if (this._lastTreeElement !== currentTreeElement || this._lastIndex === -1) + return this._searchResult(currentTreeElement, 0); + + if (this._lastIndex == currentTreeElement.searchMatchesCount - 1) + return this._searchResult(this._traverser.next(currentTreeElement), 0, this._currentMatchIndex % this._matchesCount + 1); + + return this._searchResult(currentTreeElement, this._lastIndex + 1, this._currentMatchIndex + 1); + }, + + /** + * @param {WebInspector.BaseStorageTreeElement} currentTreeElement + */ + previousSearchResult: function(currentTreeElement) + { + if (!currentTreeElement) { + var treeElement = this._traverser.last(); + return this._searchResult(treeElement, treeElement.searchMatchesCount - 1, this._matchesCount); + } + + if (currentTreeElement.searchMatchesCount && this._lastTreeElement === currentTreeElement) { + if (this._lastIndex > 0) + return this._searchResult(currentTreeElement, this._lastIndex - 1, this._currentMatchIndex - 1); + else { + var treeElement = this._traverser.previous(currentTreeElement); + var currentMatchIndex = this._currentMatchIndex - 1 ? this._currentMatchIndex - 1 : this._matchesCount; + return this._searchResult(treeElement, treeElement.searchMatchesCount - 1, currentMatchIndex); + } + } + + var treeElement = this._traverser.previous(currentTreeElement) + return this._searchResult(treeElement, treeElement.searchMatchesCount - 1); + }, + + /** + * @param {WebInspector.BaseStorageTreeElement} treeElement + * @param {number} index + * @param {number=} currentMatchIndex + * @return {Object} + */ + _searchResult: function(treeElement, index, currentMatchIndex) + { + this._lastTreeElement = treeElement; + this._lastIndex = index; + if (!currentMatchIndex) + currentMatchIndex = this._traverser.matchIndex(treeElement, index); + this._currentMatchIndex = currentMatchIndex; + return {treeElement: treeElement, index: index, currentMatchIndex: currentMatchIndex}; + } +} + +/** + * @constructor + * @param {WebInspector.BaseStorageTreeElement} rootElement + */ +WebInspector.SearchResultsTreeElementsTraverser = function(rootElement) +{ + this._root = rootElement; +} + +WebInspector.SearchResultsTreeElementsTraverser.prototype = { + /** + * @return {WebInspector.BaseStorageTreeElement} + */ + first: function() + { + return this.next(this._root); + }, + + /** + * @return {WebInspector.BaseStorageTreeElement} + */ + last: function() + { + return this.previous(this._root); + }, + + /** + * @param {WebInspector.BaseStorageTreeElement} startTreeElement + * @return {WebInspector.BaseStorageTreeElement} + */ + next: function(startTreeElement) + { + var treeElement = startTreeElement; + do { + treeElement = this._traverseNext(treeElement) || this._root; + } while (treeElement != startTreeElement && !this._elementSearchMatchesCount(treeElement)); + return treeElement; + }, + + /** + * @param {WebInspector.BaseStorageTreeElement} startTreeElement + * @return {WebInspector.BaseStorageTreeElement} + */ + previous: function(startTreeElement) + { + var treeElement = startTreeElement; + do { + treeElement = this._traversePrevious(treeElement) || this._lastTreeElement(); + } while (treeElement != startTreeElement && !this._elementSearchMatchesCount(treeElement)); + return treeElement; + }, + + /** + * @param {WebInspector.BaseStorageTreeElement} startTreeElement + * @param {number} index + * @return {number} + */ + matchIndex: function(startTreeElement, index) + { + var matchIndex = 1; + var treeElement = this._root; + while (treeElement != startTreeElement) { + matchIndex += this._elementSearchMatchesCount(treeElement); + treeElement = this._traverseNext(treeElement) || this._root; + if (treeElement === this._root) + return 0; + } + return matchIndex + index; + }, + + /** + * @param {WebInspector.BaseStorageTreeElement} treeElement + * @return {number} + */ + _elementSearchMatchesCount: function(treeElement) + { + return treeElement.searchMatchesCount; + }, + + /** + * @param {WebInspector.BaseStorageTreeElement} treeElement + * @return {WebInspector.BaseStorageTreeElement} + */ + _traverseNext: function(treeElement) + { + return /** @type {WebInspector.BaseStorageTreeElement} */ treeElement.traverseNextTreeElement(false, this._root, true); + }, + + /** + * @param {WebInspector.BaseStorageTreeElement} treeElement + * @return {WebInspector.BaseStorageTreeElement} + */ + _traversePrevious: function(treeElement) + { + return /** @type {WebInspector.BaseStorageTreeElement} */ treeElement.traversePreviousTreeElement(false, true); + }, + + /** + * @return {WebInspector.BaseStorageTreeElement} + */ + _lastTreeElement: function() + { + var treeElement = this._root; + var nextTreeElement; + while (nextTreeElement = this._traverseNext(treeElement)) + treeElement = nextTreeElement; + return treeElement; + } +} +/* ProfilesPanel.js */ + +/* + * Copyright (C) 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 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 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. + */ + +const UserInitiatedProfileName = "org.webkit.profiles.user-initiated"; + +WebInspector.ProfileType = function(id, name) +{ + this._id = id; + this._name = name; +} + +WebInspector.ProfileType.URLRegExp = /webkit-profile:\/\/(.+)\/(.+)#([0-9]+)/; + +WebInspector.ProfileType.prototype = { + get buttonTooltip() + { + return ""; + }, + + get id() + { + return this._id; + }, + + get treeItemTitle() + { + return this._name; + }, + + get name() + { + return this._name; + }, + + buttonClicked: function() + { + }, + + viewForProfile: function(profile) + { + if (!profile._profileView) + profile._profileView = this.createView(profile); + return profile._profileView; + }, + + reset: function() + { + }, + + get description() + { + return ""; + }, + + // Must be implemented by subclasses. + createView: function(profile) + { + throw new Error("Needs implemented."); + }, + + // Must be implemented by subclasses. + createSidebarTreeElementForProfile: function(profile) + { + throw new Error("Needs implemented."); + } +} + +WebInspector.registerLinkifierPlugin(function(title) +{ + var profileStringMatches = WebInspector.ProfileType.URLRegExp.exec(title); + if (profileStringMatches) + title = WebInspector.panels.profiles.displayTitleForProfileLink(profileStringMatches[2], profileStringMatches[1]); + return title; +}); + +WebInspector.ProfilesPanel = function() +{ + WebInspector.Panel.call(this, "profiles"); + this.registerRequiredCSS("panelEnablerView.css"); + this.registerRequiredCSS("heapProfiler.css"); + this.registerRequiredCSS("profilesPanel.css"); + + this.createSplitViewWithSidebarTree(); + + this.profilesItemTreeElement = new WebInspector.ProfilesSidebarTreeElement(this); + this.sidebarTree.appendChild(this.profilesItemTreeElement); + + this._profileTypesByIdMap = {}; + + var panelEnablerHeading = WebInspector.UIString("You need to enable profiling before you can use the Profiles panel."); + var panelEnablerDisclaimer = WebInspector.UIString("Enabling profiling will make scripts run slower."); + var panelEnablerButton = WebInspector.UIString("Enable Profiling"); + this.panelEnablerView = new WebInspector.PanelEnablerView("profiles", panelEnablerHeading, panelEnablerDisclaimer, panelEnablerButton); + this.panelEnablerView.addEventListener("enable clicked", this.enableProfiler, this); + + this.profileViews = document.createElement("div"); + this.profileViews.id = "profile-views"; + this.splitView.mainElement.appendChild(this.profileViews); + + this.enableToggleButton = new WebInspector.StatusBarButton("", "enable-toggle-status-bar-item"); + this.enableToggleButton.addEventListener("click", this._toggleProfiling.bind(this), false); + if (!Capabilities.profilerCausesRecompilation) + this.enableToggleButton.element.addStyleClass("hidden"); + + this.recordButton = new WebInspector.StatusBarButton("", "record-profile-status-bar-item"); + this.recordButton.addEventListener("click", this.toggleRecordButton, this); + + this.clearResultsButton = new WebInspector.StatusBarButton(WebInspector.UIString("Clear all profiles."), "clear-status-bar-item"); + this.clearResultsButton.addEventListener("click", this._clearProfiles.bind(this), false); + + this.profileViewStatusBarItemsContainer = document.createElement("div"); + this.profileViewStatusBarItemsContainer.className = "status-bar-items"; + + this._profiles = []; + this._profilerEnabled = !Capabilities.profilerCausesRecompilation; + + this._launcherView = new WebInspector.ProfileLauncherView(this); + this._launcherView.addEventListener(WebInspector.ProfileLauncherView.EventTypes.ProfileTypeSelected, this._onProfileTypeSelected, this); + this._reset(); + this._launcherView.setUpEventListeners(); + + this._registerProfileType(new WebInspector.CPUProfileType()); + this._registerProfileType(new WebInspector.CSSSelectorProfileType()); + if (Capabilities.heapProfilerPresent) + this._registerProfileType(new WebInspector.DetailedHeapshotProfileType()); + + InspectorBackend.registerProfilerDispatcher(new WebInspector.ProfilerDispatcher(this)); + + if (!Capabilities.profilerCausesRecompilation || WebInspector.settings.profilerEnabled.get()) + ProfilerAgent.enable(this._profilerWasEnabled.bind(this)); +} + +WebInspector.ProfilesPanel.EventTypes = { + ProfileStarted: "profile-started", + ProfileFinished: "profile-finished" +} + +WebInspector.ProfilesPanel.prototype = { + get toolbarItemLabel() + { + return WebInspector.UIString("Profiles"); + }, + + get statusBarItems() + { + return [this.enableToggleButton.element, this.recordButton.element, this.clearResultsButton.element, this.profileViewStatusBarItemsContainer]; + }, + + toggleRecordButton: function() + { + this._selectedProfileType.buttonClicked(); + }, + + wasShown: function() + { + WebInspector.Panel.prototype.wasShown.call(this); + this._populateProfiles(); + }, + + _profilerWasEnabled: function() + { + if (this._profilerEnabled) + return; + + this._profilerEnabled = true; + + this._reset(); + if (this.isShowing()) + this._populateProfiles(); + }, + + _profilerWasDisabled: function() + { + if (!this._profilerEnabled) + return; + + this._profilerEnabled = false; + this._reset(); + }, + + _onProfileTypeSelected: function(event) + { + this._selectedProfileType = event.data; + this.recordButton.title = this._selectedProfileType.buttonTooltip; + }, + + _reset: function() + { + WebInspector.Panel.prototype.reset.call(this); + + for (var i = 0; i < this._profiles.length; ++i) { + var view = this._profiles[i]._profileView; + if (view) { + view.detach(); + if ("dispose" in view) + view.dispose(); + } + + delete this._profiles[i]._profileView; + } + delete this.visibleView; + + delete this.currentQuery; + this.searchCanceled(); + + for (var id in this._profileTypesByIdMap) { + var profileType = this._profileTypesByIdMap[id]; + var treeElement = profileType.treeElement; + treeElement.removeChildren(); + treeElement.hidden = true; + profileType.reset(); + } + + this._profiles = []; + this._profilesIdMap = {}; + this._profileGroups = {}; + this._profileGroupsForLinks = {}; + this._profilesWereRequested = false; + + this.sidebarTreeElement.removeStyleClass("some-expandable"); + + this.profileViews.removeChildren(); + this.profileViewStatusBarItemsContainer.removeChildren(); + + this.removeAllListeners(); + this._launcherView.setUpEventListeners(); + + this._updateInterface(); + this.profilesItemTreeElement.select(); + this._showLauncherView(); + }, + + _showLauncherView: function() + { + this.closeVisibleView(); + this.profileViewStatusBarItemsContainer.removeChildren(); + this._launcherView.show(this.splitView.mainElement); + this.visibleView = this._launcherView; + }, + + _clearProfiles: function() + { + ProfilerAgent.clearProfiles(); + this._reset(); + }, + + _registerProfileType: function(profileType) + { + this._profileTypesByIdMap[profileType.id] = profileType; + this._launcherView.addProfileType(profileType); + profileType.treeElement = new WebInspector.SidebarSectionTreeElement(profileType.treeItemTitle, null, true); + profileType.treeElement.hidden = true; + this.sidebarTree.appendChild(profileType.treeElement); + }, + + _makeKey: function(text, profileTypeId) + { + return escape(text) + '/' + escape(profileTypeId); + }, + + addProfileHeader: function(profile) + { + if (this.hasTemporaryProfile(profile.typeId)) + this._removeTemporaryProfile(); + + var typeId = profile.typeId; + var profileType = this.getProfileType(typeId); + var sidebarParent = profileType.treeElement; + sidebarParent.hidden = false; + var small = false; + var alternateTitle; + + profile.__profilesPanelProfileType = profileType; + this._profiles.push(profile); + this._profilesIdMap[this._makeKey(profile.uid, typeId)] = profile; + + if (profile.title.indexOf(UserInitiatedProfileName) !== 0) { + var profileTitleKey = this._makeKey(profile.title, typeId); + if (!(profileTitleKey in this._profileGroups)) + this._profileGroups[profileTitleKey] = []; + + var group = this._profileGroups[profileTitleKey]; + group.push(profile); + + if (group.length === 2) { + // Make a group TreeElement now that there are 2 profiles. + group._profilesTreeElement = new WebInspector.ProfileGroupSidebarTreeElement(profile.title); + + // Insert at the same index for the first profile of the group. + var index = sidebarParent.children.indexOf(group[0]._profilesTreeElement); + sidebarParent.insertChild(group._profilesTreeElement, index); + + // Move the first profile to the group. + var selected = group[0]._profilesTreeElement.selected; + sidebarParent.removeChild(group[0]._profilesTreeElement); + group._profilesTreeElement.appendChild(group[0]._profilesTreeElement); + if (selected) + group[0]._profilesTreeElement.revealAndSelect(); + + group[0]._profilesTreeElement.small = true; + group[0]._profilesTreeElement.mainTitle = WebInspector.UIString("Run %d", 1); + + this.sidebarTreeElement.addStyleClass("some-expandable"); + } + + if (group.length >= 2) { + sidebarParent = group._profilesTreeElement; + alternateTitle = WebInspector.UIString("Run %d", group.length); + small = true; + } + } + + var profileTreeElement = profileType.createSidebarTreeElementForProfile(profile); + profile.sidebarElement = profileTreeElement; + profileTreeElement.small = small; + if (alternateTitle) + profileTreeElement.mainTitle = alternateTitle; + profile._profilesTreeElement = profileTreeElement; + + sidebarParent.appendChild(profileTreeElement); + if (!profile.isTemporary) { + if (!this.visibleView) + this.showProfile(profile); + this.dispatchEventToListeners("profile added"); + delete this._temporaryRecordingProfile; + this.dispatchEventToListeners(WebInspector.ProfilesPanel.EventTypes.ProfileFinished); + this.recordButton.toggled = false; + } else { + this.dispatchEventToListeners(WebInspector.ProfilesPanel.EventTypes.ProfileStarted); + this.recordButton.toggled = true; + } + + this.recordButton.title = this._selectedProfileType.buttonTooltip; + }, + + _removeTemporaryProfile: function() + { + this._removeProfileHeader(this._temporaryRecordingProfile); + delete this._temporaryRecordingProfile; + }, + + _removeProfileHeader: function(profile) + { + var typeId = profile.typeId; + var profileType = this.getProfileType(typeId); + var sidebarParent = profileType.treeElement; + + for (var i = 0; i < this._profiles.length; ++i) { + if (this._profiles[i].uid === profile.uid) { + profile = this._profiles[i]; + this._profiles.splice(i, 1); + break; + } + } + delete this._profilesIdMap[this._makeKey(profile.uid, typeId)]; + + var profileTitleKey = this._makeKey(profile.title, typeId); + delete this._profileGroups[profileTitleKey]; + + sidebarParent.removeChild(profile._profilesTreeElement); + + if (!profile.isTemporary) + ProfilerAgent.removeProfile(profile.typeId, profile.uid); + + // No other item will be selected if there aren't any other profiles, so + // make sure that view gets cleared when the last profile is removed. + if (!this._profiles.length) + this.closeVisibleView(); + }, + + showProfile: function(profile) + { + if (!profile || profile.isTemporary) + return; + + this.closeVisibleView(); + + var view = profile.__profilesPanelProfileType.viewForProfile(profile); + + view.show(this.profileViews); + + profile._profilesTreeElement._suppressOnSelect = true; + profile._profilesTreeElement.revealAndSelect(); + delete profile._profilesTreeElement._suppressOnSelect; + + this.visibleView = view; + + this.profileViewStatusBarItemsContainer.removeChildren(); + + var statusBarItems = view.statusBarItems; + if (statusBarItems) + for (var i = 0; i < statusBarItems.length; ++i) + this.profileViewStatusBarItemsContainer.appendChild(statusBarItems[i]); + }, + + getProfiles: function(typeId) + { + var result = []; + var profilesCount = this._profiles.length; + for (var i = 0; i < profilesCount; ++i) { + var profile = this._profiles[i]; + if (!profile.isTemporary && profile.typeId === typeId) + result.push(profile); + } + return result; + }, + + hasTemporaryProfile: function(typeId) + { + var profilesCount = this._profiles.length; + for (var i = 0; i < profilesCount; ++i) + if (this._profiles[i].typeId === typeId && this._profiles[i].isTemporary) + return true; + return false; + }, + + hasProfile: function(profile) + { + return !!this._profilesIdMap[this._makeKey(profile.uid, profile.typeId)]; + }, + + getProfile: function(typeId, uid) + { + return this._profilesIdMap[this._makeKey(uid, typeId)]; + }, + + loadHeapSnapshot: function(uid, callback) + { + var profile = this._profilesIdMap[this._makeKey(uid, WebInspector.DetailedHeapshotProfileType.TypeId)]; + if (!profile) + return; + + if (!profile.proxy) { + function setProfileWait(event) { + profile.sidebarElement.wait = event.data; + } + var worker = new WebInspector.HeapSnapshotWorker(); + worker.addEventListener("wait", setProfileWait, this); + profile.proxy = worker.createObject("WebInspector.HeapSnapshotLoader"); + } + var proxy = profile.proxy; + if (proxy.startLoading(callback)) { + profile.sidebarElement.subtitle = WebInspector.UIString("Loading\u2026"); + profile.sidebarElement.wait = true; + ProfilerAgent.getProfile(profile.typeId, profile.uid); + } + }, + + _addHeapSnapshotChunk: function(uid, chunk) + { + var profile = this._profilesIdMap[this._makeKey(uid, WebInspector.DetailedHeapshotProfileType.TypeId)]; + if (!profile || !profile.proxy) + return; + profile.proxy.pushJSONChunk(chunk); + }, + + _finishHeapSnapshot: function(uid) + { + var profile = this._profilesIdMap[this._makeKey(uid, WebInspector.DetailedHeapshotProfileType.TypeId)]; + if (!profile || !profile.proxy) + return; + var proxy = profile.proxy; + function parsed(snapshotProxy) + { + profile.proxy = snapshotProxy; + profile.sidebarElement.subtitle = Number.bytesToString(snapshotProxy.totalSize); + profile.sidebarElement.wait = false; + snapshotProxy.worker.startCheckingForLongRunningCalls(); + } + if (proxy.finishLoading(parsed)) + profile.sidebarElement.subtitle = WebInspector.UIString("Parsing\u2026"); + }, + + showView: function(view) + { + this.showProfile(view.profile); + }, + + getProfileType: function(typeId) + { + return this._profileTypesByIdMap[typeId]; + }, + + showProfileForURL: function(url) + { + var match = url.match(WebInspector.ProfileType.URLRegExp); + if (!match) + return; + this.showProfile(this._profilesIdMap[this._makeKey(match[3], match[1])]); + }, + + closeVisibleView: function() + { + if (this.visibleView) + this.visibleView.detach(); + delete this.visibleView; + }, + + displayTitleForProfileLink: function(title, typeId) + { + title = unescape(title); + if (title.indexOf(UserInitiatedProfileName) === 0) { + title = WebInspector.UIString("Profile %d", title.substring(UserInitiatedProfileName.length + 1)); + } else { + var titleKey = this._makeKey(title, typeId); + if (!(titleKey in this._profileGroupsForLinks)) + this._profileGroupsForLinks[titleKey] = 0; + + var groupNumber = ++this._profileGroupsForLinks[titleKey]; + + if (groupNumber > 2) + // The title is used in the console message announcing that a profile has started so it gets + // incremented twice as often as it's displayed + title += " " + WebInspector.UIString("Run %d", (groupNumber + 1) / 2); + } + + return title; + }, + + performSearch: function(query) + { + this.searchCanceled(); + + var searchableViews = this._searchableViews(); + if (!searchableViews || !searchableViews.length) + return; + + var parentElement = this.viewsContainerElement; + var visibleView = this.visibleView; + var sortFuction = this.searchResultsSortFunction; + + var matchesCountUpdateTimeout = null; + + function updateMatchesCount() + { + WebInspector.searchController.updateSearchMatchesCount(this._totalSearchMatches, this); + matchesCountUpdateTimeout = null; + } + + function updateMatchesCountSoon() + { + if (matchesCountUpdateTimeout) + return; + // Update the matches count every half-second so it doesn't feel twitchy. + matchesCountUpdateTimeout = setTimeout(updateMatchesCount.bind(this), 500); + } + + function finishedCallback(view, searchMatches) + { + if (!searchMatches) + return; + + this._totalSearchMatches += searchMatches; + this._searchResults.push(view); + + if (sortFuction) + this._searchResults.sort(sortFuction); + + if (this.searchMatchFound) + this.searchMatchFound(view, searchMatches); + + updateMatchesCountSoon.call(this); + + if (view === visibleView) + view.jumpToFirstSearchResult(); + } + + var i = 0; + var panel = this; + var boundFinishedCallback = finishedCallback.bind(this); + var chunkIntervalIdentifier = null; + + // Split up the work into chunks so we don't block the + // UI thread while processing. + + function processChunk() + { + var view = searchableViews[i]; + + if (++i >= searchableViews.length) { + if (panel._currentSearchChunkIntervalIdentifier === chunkIntervalIdentifier) + delete panel._currentSearchChunkIntervalIdentifier; + clearInterval(chunkIntervalIdentifier); + } + + if (!view) + return; + + view.currentQuery = query; + view.performSearch(query, boundFinishedCallback); + } + + processChunk(); + + chunkIntervalIdentifier = setInterval(processChunk, 25); + this._currentSearchChunkIntervalIdentifier = chunkIntervalIdentifier; + }, + + jumpToNextSearchResult: function() + { + if (!this.showView || !this._searchResults || !this._searchResults.length) + return; + + var showFirstResult = false; + + this._currentSearchResultIndex = this._searchResults.indexOf(this.visibleView); + if (this._currentSearchResultIndex === -1) { + this._currentSearchResultIndex = 0; + showFirstResult = true; + } + + var currentView = this._searchResults[this._currentSearchResultIndex]; + + if (currentView.showingLastSearchResult()) { + if (++this._currentSearchResultIndex >= this._searchResults.length) + this._currentSearchResultIndex = 0; + currentView = this._searchResults[this._currentSearchResultIndex]; + showFirstResult = true; + } + + if (currentView !== this.visibleView) { + this.showView(currentView); + WebInspector.searchController.focusSearchField(); + } + + if (showFirstResult) + currentView.jumpToFirstSearchResult(); + else + currentView.jumpToNextSearchResult(); + }, + + jumpToPreviousSearchResult: function() + { + if (!this.showView || !this._searchResults || !this._searchResults.length) + return; + + var showLastResult = false; + + this._currentSearchResultIndex = this._searchResults.indexOf(this.visibleView); + if (this._currentSearchResultIndex === -1) { + this._currentSearchResultIndex = 0; + showLastResult = true; + } + + var currentView = this._searchResults[this._currentSearchResultIndex]; + + if (currentView.showingFirstSearchResult()) { + if (--this._currentSearchResultIndex < 0) + this._currentSearchResultIndex = (this._searchResults.length - 1); + currentView = this._searchResults[this._currentSearchResultIndex]; + showLastResult = true; + } + + if (currentView !== this.visibleView) { + this.showView(currentView); + WebInspector.searchController.focusSearchField(); + } + + if (showLastResult) + currentView.jumpToLastSearchResult(); + else + currentView.jumpToPreviousSearchResult(); + }, + + _searchableViews: function() + { + var views = []; + + const visibleView = this.visibleView; + if (visibleView && visibleView.performSearch) + views.push(visibleView); + + var profilesLength = this._profiles.length; + for (var i = 0; i < profilesLength; ++i) { + var profile = this._profiles[i]; + var view = profile.__profilesPanelProfileType.viewForProfile(profile); + if (!view.performSearch || view === visibleView) + continue; + views.push(view); + } + + return views; + }, + + searchMatchFound: function(view, matches) + { + view.profile._profilesTreeElement.searchMatches = matches; + }, + + searchCanceled: function() + { + if (this._searchResults) { + for (var i = 0; i < this._searchResults.length; ++i) { + var view = this._searchResults[i]; + if (view.searchCanceled) + view.searchCanceled(); + delete view.currentQuery; + } + } + + WebInspector.Panel.prototype.searchCanceled.call(this); + + if (this._currentSearchChunkIntervalIdentifier) { + clearInterval(this._currentSearchChunkIntervalIdentifier); + delete this._currentSearchChunkIntervalIdentifier; + } + + this._totalSearchMatches = 0; + this._currentSearchResultIndex = 0; + this._searchResults = []; + + if (!this._profiles) + return; + + for (var i = 0; i < this._profiles.length; ++i) { + var profile = this._profiles[i]; + profile._profilesTreeElement.searchMatches = 0; + } + }, + + _updateInterface: function() + { + // FIXME: Replace ProfileType-specific button visibility changes by a single ProfileType-agnostic "combo-button" visibility change. + if (this._profilerEnabled) { + this.enableToggleButton.title = WebInspector.UIString("Profiling enabled. Click to disable."); + this.enableToggleButton.toggled = true; + this.recordButton.visible = true; + this.profileViewStatusBarItemsContainer.removeStyleClass("hidden"); + this.clearResultsButton.element.removeStyleClass("hidden"); + this.panelEnablerView.detach(); + } else { + this.enableToggleButton.title = WebInspector.UIString("Profiling disabled. Click to enable."); + this.enableToggleButton.toggled = false; + this.recordButton.visible = false; + this.profileViewStatusBarItemsContainer.addStyleClass("hidden"); + this.clearResultsButton.element.addStyleClass("hidden"); + this.panelEnablerView.show(this.element); + } + }, + + get profilerEnabled() + { + return this._profilerEnabled; + }, + + enableProfiler: function() + { + if (this._profilerEnabled) + return; + this._toggleProfiling(this.panelEnablerView.alwaysEnabled); + }, + + disableProfiler: function() + { + if (!this._profilerEnabled) + return; + this._toggleProfiling(this.panelEnablerView.alwaysEnabled); + }, + + _toggleProfiling: function(optionalAlways) + { + if (this._profilerEnabled) { + WebInspector.settings.profilerEnabled.set(false); + ProfilerAgent.disable(this._profilerWasDisabled.bind(this)); + } else { + WebInspector.settings.profilerEnabled.set(!!optionalAlways); + ProfilerAgent.enable(this._profilerWasEnabled.bind(this)); + } + }, + + _populateProfiles: function() + { + if (!this._profilerEnabled || this._profilesWereRequested) + return; + + function populateCallback(error, profileHeaders) { + if (error) + return; + profileHeaders.sort(function(a, b) { return a.uid - b.uid; }); + var profileHeadersLength = profileHeaders.length; + for (var i = 0; i < profileHeadersLength; ++i) + if (!this.hasProfile(profileHeaders[i])) + this.addProfileHeader(profileHeaders[i]); + } + + ProfilerAgent.getProfileHeaders(populateCallback.bind(this)); + + this._profilesWereRequested = true; + }, + + sidebarResized: function(event) + { + var width = event.data; + // Min width = * 31 + this.profileViewStatusBarItemsContainer.style.left = Math.max(5 * 31, width) + "px"; + }, + + setRecordingProfile: function(profileType, isProfiling) + { + this.getProfileType(profileType).setRecordingProfile(isProfiling); + if (this.hasTemporaryProfile(profileType) !== isProfiling) { + if (!this._temporaryRecordingProfile) { + this._temporaryRecordingProfile = { + typeId: profileType, + title: WebInspector.UIString("Recording\u2026"), + uid: -1, + isTemporary: true + }; + } + if (isProfiling) { + this.addProfileHeader(this._temporaryRecordingProfile); + if (profileType === WebInspector.CPUProfileType.TypeId) + WebInspector.userMetrics.ProfilesCPUProfileTaken.record(); + } else + this._removeTemporaryProfile() + } + }, + + takeHeapSnapshot: function() + { + if (!this.hasTemporaryProfile(WebInspector.DetailedHeapshotProfileType.TypeId)) { + if (!this._temporaryRecordingProfile) { + this._temporaryRecordingProfile = { + typeId: WebInspector.DetailedHeapshotProfileType.TypeId, + title: WebInspector.UIString("Snapshotting\u2026"), + uid: -1, + isTemporary: true + }; + } + this.addProfileHeader(this._temporaryRecordingProfile); + } + ProfilerAgent.takeHeapSnapshot(); + WebInspector.userMetrics.ProfilesHeapProfileTaken.record(); + }, + + _reportHeapSnapshotProgress: function(done, total) + { + if (this.hasTemporaryProfile(WebInspector.DetailedHeapshotProfileType.TypeId)) { + this._temporaryRecordingProfile.sidebarElement.subtitle = WebInspector.UIString("%.2f%%", (done / total) * 100); + this._temporaryRecordingProfile.sidebarElement.wait = true; + if (done >= total) + this._removeTemporaryProfile(); + } + } +} + +WebInspector.ProfilesPanel.prototype.__proto__ = WebInspector.Panel.prototype; + + +WebInspector.ProfilerDispatcher = function(profiler) +{ + this._profiler = profiler; +} + +WebInspector.ProfilerDispatcher.prototype = { + resetProfiles: function() + { + this._profiler._reset(); + }, + + addProfileHeader: function(profile) + { + this._profiler.addProfileHeader(profile); + }, + + addHeapSnapshotChunk: function(uid, chunk) + { + this._profiler._addHeapSnapshotChunk(uid, chunk); + }, + + finishHeapSnapshot: function(uid) + { + this._profiler._finishHeapSnapshot(uid); + }, + + setRecordingProfile: function(isProfiling) + { + this._profiler.setRecordingProfile(WebInspector.CPUProfileType.TypeId, isProfiling); + }, + + reportHeapSnapshotProgress: function(done, total) + { + this._profiler._reportHeapSnapshotProgress(done, total); + } +} + +WebInspector.ProfileSidebarTreeElement = function(profile, titleFormat, className) +{ + this.profile = profile; + this._titleFormat = titleFormat; + + if (this.profile.title.indexOf(UserInitiatedProfileName) === 0) + this._profileNumber = this.profile.title.substring(UserInitiatedProfileName.length + 1); + + WebInspector.SidebarTreeElement.call(this, className, "", "", profile, false); + + this.refreshTitles(); +} + +WebInspector.ProfileSidebarTreeElement.prototype = { + onselect: function() + { + if (!this._suppressOnSelect) + this.treeOutline.panel.showProfile(this.profile); + }, + + ondelete: function() + { + this.treeOutline.panel._removeProfileHeader(this.profile); + return true; + }, + + get mainTitle() + { + if (this._mainTitle) + return this._mainTitle; + if (this.profile.title.indexOf(UserInitiatedProfileName) === 0) + return WebInspector.UIString(this._titleFormat, this._profileNumber); + return this.profile.title; + }, + + set mainTitle(x) + { + this._mainTitle = x; + this.refreshTitles(); + }, + + set searchMatches(matches) + { + if (!matches) { + if (!this.bubbleElement) + return; + this.bubbleElement.removeStyleClass("search-matches"); + this.bubbleText = ""; + return; + } + + this.bubbleText = matches; + this.bubbleElement.addStyleClass("search-matches"); + } +} + +WebInspector.ProfileSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype; + +WebInspector.ProfileGroupSidebarTreeElement = function(title, subtitle) +{ + WebInspector.SidebarTreeElement.call(this, "profile-group-sidebar-tree-item", title, subtitle, null, true); +} + +WebInspector.ProfileGroupSidebarTreeElement.prototype = { + onselect: function() + { + if (this.children.length > 0) + WebInspector.panels.profiles.showProfile(this.children[this.children.length - 1].profile); + } +} + +WebInspector.ProfileGroupSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype; + +/** + * @constructor + * @extends {WebInspector.SidebarTreeElement} + */ +WebInspector.ProfilesSidebarTreeElement = function(panel) +{ + this._panel = panel; + this.small = false; + + WebInspector.SidebarTreeElement.call(this, "profile-launcher-view-tree-item", WebInspector.UIString("Profiles"), "", null, false); +} + +WebInspector.ProfilesSidebarTreeElement.prototype = { + onselect: function() + { + this._panel._showLauncherView(); + }, + + get selectable() + { + return true; + } +} + +WebInspector.ProfilesSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype; +/* ConsolePanel.js */ + +/* + * Copyright (C) 2009 Joseph Pecoraro + * + * 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. + */ + +/** + * @constructor + * @extends {WebInspector.Panel} + */ +WebInspector.ConsolePanel = function() +{ + WebInspector.Panel.call(this, "console"); + + WebInspector.consoleView.addEventListener(WebInspector.ConsoleView.Events.EntryAdded, this._consoleMessageAdded, this); + WebInspector.consoleView.addEventListener(WebInspector.ConsoleView.Events.ConsoleCleared, this._consoleCleared, this); + this._view = WebInspector.consoleView; +} + +WebInspector.ConsolePanel.prototype = { + get toolbarItemLabel() + { + return WebInspector.UIString("Console"); + }, + + get statusBarItems() + { + return this._view.statusBarItems; + }, + + wasShown: function() + { + WebInspector.Panel.prototype.wasShown.call(this); + if (WebInspector.drawer.visible) { + WebInspector.drawer.hide(WebInspector.Drawer.AnimationType.Immediately); + this._drawerWasVisible = true; + } + this._view.show(this.element); + }, + + willHide: function() + { + if (this._drawerWasVisible) { + WebInspector.drawer.show(this._view, WebInspector.Drawer.AnimationType.Immediately); + delete this._drawerWasVisible; + } + WebInspector.Panel.prototype.willHide.call(this); + }, + + searchCanceled: function() + { + this._clearCurrentSearchResultHighlight(); + delete this._searchResults; + delete this._searchRegex; + }, + + performSearch: function(query) + { + WebInspector.searchController.updateSearchMatchesCount(0, this); + this.searchCanceled(); + this._searchRegex = createPlainTextSearchRegex(query, "gi"); + + this._searchResults = []; + var messages = WebInspector.consoleView.messages; + for (var i = 0; i < messages.length; i++) { + if (messages[i].matchesRegex(this._searchRegex)) { + this._searchResults.push(messages[i]); + this._searchRegex.lastIndex = 0; + } + } + WebInspector.searchController.updateSearchMatchesCount(this._searchResults.length, this); + this._currentSearchResultIndex = -1; + if (this._searchResults.length) + this._jumpToSearchResult(0); + }, + + jumpToNextSearchResult: function() + { + if (!this._searchResults || !this._searchResults.length) + return; + this._jumpToSearchResult((this._currentSearchResultIndex + 1) % this._searchResults.length); + }, + + jumpToPreviousSearchResult: function() + { + if (!this._searchResults || !this._searchResults.length) + return; + var index = this._currentSearchResultIndex - 1; + if (index === -1) + index = this._searchResults.length - 1; + this._jumpToSearchResult(index); + }, + + _clearCurrentSearchResultHighlight: function() + { + if (!this._searchResults) + return; + var highlightedMessage = this._searchResults[this._currentSearchResultIndex]; + if (highlightedMessage) + highlightedMessage.clearHighlight(); + this._currentSearchResultIndex = -1; + }, + + _jumpToSearchResult: function(index) + { + this._clearCurrentSearchResultHighlight(); + this._currentSearchResultIndex = index; + this._searchResults[index].highlightSearchResults(this._searchRegex); + }, + + _consoleMessageAdded: function(event) + { + if (!this._searchRegex || !this.isShowing()) + return; + var message = event.data; + this._searchRegex.lastIndex = 0; + if (message.matchesRegex(this._searchRegex)) { + this._searchResults.push(message); + WebInspector.searchController.updateSearchMatchesCount(this._searchResults.length, this); + } + }, + + _consoleCleared: function() + { + if (!this._searchResults) + return; + this._clearCurrentSearchResultHighlight(); + this._searchResults.length = 0; + if (this.isShowing()) + WebInspector.searchController.updateSearchMatchesCount(0, this); + } +} + +WebInspector.ConsolePanel.prototype.__proto__ = WebInspector.Panel.prototype; +/* ExtensionAPI.js */ + +/* + * Copyright (C) 2011 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. + */ + +function defineCommonExtensionSymbols(apiPrivate) +{ + if (!apiPrivate.audits) + apiPrivate.audits = {}; + + apiPrivate.audits.Severity = { + Info: "info", + Warning: "warning", + Severe: "severe" + }; + + if (!apiPrivate.console) + apiPrivate.console = {}; + apiPrivate.console.Severity = { + Tip: "tip", + Debug: "debug", + Log: "log", + Warning: "warning", + Error: "error" + }; + apiPrivate.Events = { + AuditStarted: "audit-started-", + ButtonClicked: "button-clicked-", + ConsoleMessageAdded: "console-message-added", + ElementsPanelObjectSelected: "panel-objectSelected-elements", + NetworkRequestFinished: "network-request-finished", + Reset: "reset", + OpenResource: "open-resource", + PanelSearch: "panel-search-", + Reload: "Reload", + ResourceAdded: "resource-added", + ResourceContentCommitted: "resource-content-committed", + TimelineEventRecorded: "timeline-event-recorded", + ViewShown: "view-shown-", + ViewHidden: "view-hidden-" + }; + apiPrivate.Commands = { + AddAuditCategory: "addAuditCategory", + AddAuditResult: "addAuditResult", + AddConsoleMessage: "addConsoleMessage", + AddRequestHeaders: "addRequestHeaders", + CreatePanel: "createPanel", + CreateSidebarPane: "createSidebarPane", + CreateStatusBarButton: "createStatusBarButton", + EvaluateOnInspectedPage: "evaluateOnInspectedPage", + GetConsoleMessages: "getConsoleMessages", + GetHAR: "getHAR", + GetPageResources: "getPageResources", + GetRequestContent: "getRequestContent", + GetResourceContent: "getResourceContent", + Subscribe: "subscribe", + SetOpenResourceHandler: "setOpenResourceHandler", + SetResourceContent: "setResourceContent", + SetSidebarContent: "setSidebarContent", + SetSidebarHeight: "setSidebarHeight", + SetSidebarPage: "setSidebarPage", + StopAuditCategoryRun: "stopAuditCategoryRun", + Unsubscribe: "unsubscribe", + UpdateButton: "updateButton", + InspectedURLChanged: "inspectedURLChanged" + }; +} + +function injectedExtensionAPI(injectedScriptId) +{ + +var apiPrivate = {}; + +defineCommonExtensionSymbols(apiPrivate); + +var commands = apiPrivate.Commands; +var events = apiPrivate.Events; + +// Here and below, all constructors are private to API implementation. +// For a public type Foo, if internal fields are present, these are on +// a private FooImpl type, an instance of FooImpl is used in a closure +// by Foo consutrctor to re-bind publicly exported members to an instance +// of Foo. + +/** + * @constructor + */ +function EventSinkImpl(type, customDispatch) +{ + this._type = type; + this._listeners = []; + this._customDispatch = customDispatch; +} + +EventSinkImpl.prototype = { + addListener: function(callback) + { + if (typeof callback !== "function") + throw "addListener: callback is not a function"; + if (this._listeners.length === 0) + extensionServer.sendRequest({ command: commands.Subscribe, type: this._type }); + this._listeners.push(callback); + extensionServer.registerHandler("notify-" + this._type, bind(this._dispatch, this)); + }, + + removeListener: function(callback) + { + var listeners = this._listeners; + + for (var i = 0; i < listeners.length; ++i) { + if (listeners[i] === callback) { + listeners.splice(i, 1); + break; + } + } + if (this._listeners.length === 0) + extensionServer.sendRequest({ command: commands.Unsubscribe, type: this._type }); + }, + + _fire: function() + { + var listeners = this._listeners.slice(); + for (var i = 0; i < listeners.length; ++i) + listeners[i].apply(null, arguments); + }, + + _dispatch: function(request) + { + if (this._customDispatch) + this._customDispatch.call(this, request); + else + this._fire.apply(this, request.arguments); + } +} + +/** + * @constructor + */ +function InspectorExtensionAPI() +{ + this.audits = new Audits(); + this.inspectedWindow = new InspectedWindow(); + this.panels = new Panels(); + this.network = new Network(); + defineDeprecatedProperty(this, "webInspector", "resources", "network"); + this.timeline = new Timeline(); + this.console = new ConsoleAPI(); + + this.onReset = new EventSink(events.Reset); +} + +/** + * @constructor + */ +InspectorExtensionAPI.prototype = { + log: function(message) + { + extensionServer.sendRequest({ command: commands.Log, message: message }); + } +} + +/** + * @constructor + */ +function ConsoleAPI() +{ + this.onMessageAdded = new EventSink(events.ConsoleMessageAdded); +} + +ConsoleAPI.prototype = { + getMessages: function(callback) + { + extensionServer.sendRequest({ command: commands.GetConsoleMessages }, callback); + }, + + addMessage: function(severity, text, url, line) + { + extensionServer.sendRequest({ command: commands.AddConsoleMessage, severity: severity, text: text, url: url, line: line }); + }, + + get Severity() + { + return apiPrivate.console.Severity; + } +} + +/** + * @constructor + */ +function Network() +{ + function dispatchRequestEvent(message) + { + var request = message.arguments[1]; + request.__proto__ = new Request(message.arguments[0]); + this._fire(request); + } + this.onRequestFinished = new EventSink(events.NetworkRequestFinished, dispatchRequestEvent); + defineDeprecatedProperty(this, "network", "onFinished", "onRequestFinished"); + this.onNavigated = new EventSink(events.InspectedURLChanged); +} + +Network.prototype = { + getHAR: function(callback) + { + function callbackWrapper(result) + { + var entries = (result && result.entries) || []; + for (var i = 0; i < entries.length; ++i) { + entries[i].__proto__ = new Request(entries[i]._requestId); + delete entries[i]._requestId; + } + callback(result); + } + return extensionServer.sendRequest({ command: commands.GetHAR }, callback && callbackWrapper); + }, + + addRequestHeaders: function(headers) + { + return extensionServer.sendRequest({ command: commands.AddRequestHeaders, headers: headers, extensionId: window.location.hostname }); + } +} + +/** + * @constructor + */ +function RequestImpl(id) +{ + this._id = id; +} + +RequestImpl.prototype = { + getContent: function(callback) + { + function callbackWrapper(response) + { + callback(response.content, response.encoding); + } + extensionServer.sendRequest({ command: commands.GetRequestContent, id: this._id }, callback && callbackWrapper); + } +} + +/** + * @constructor + */ +function Panels() +{ + var panels = { + elements: new ElementsPanel() + }; + + function panelGetter(name) + { + return panels[name]; + } + for (var panel in panels) + this.__defineGetter__(panel, bind(panelGetter, null, panel)); +} + +Panels.prototype = { + create: function(title, icon, page, callback) + { + var id = "extension-panel-" + extensionServer.nextObjectId(); + var request = { + command: commands.CreatePanel, + id: id, + title: title, + icon: icon, + page: page + }; + extensionServer.sendRequest(request, callback && bind(callback, this, new ExtensionPanel(id))); + }, + + setOpenResourceHandler: function(callback) + { + var hadHandler = extensionServer.hasHandler(events.OpenResource); + + if (!callback) + extensionServer.unregisterHandler(events.OpenResource); + else { + function callbackWrapper(message) + { + callback.call(null, message.resource, message.lineNumber); + } + extensionServer.registerHandler(events.OpenResource, callbackWrapper); + } + // Only send command if we either removed an existing handler or added handler and had none before. + if (hadHandler === !callback) + extensionServer.sendRequest({ command: commands.SetOpenResourceHandler, "handlerPresent": !!callback }); + } +} + +/** + * @constructor + */ +function ExtensionViewImpl(id) +{ + this._id = id; + + function dispatchShowEvent(message) + { + var frameIndex = message.arguments[0]; + this._fire(window.top.frames[frameIndex]); + } + this.onShown = new EventSink(events.ViewShown + id, dispatchShowEvent); + this.onHidden = new EventSink(events.ViewHidden + id); +} + +/** + * @constructor + */ +function PanelWithSidebarImpl(id) +{ + this._id = id; +} + +PanelWithSidebarImpl.prototype = { + createSidebarPane: function(title, callback) + { + var id = "extension-sidebar-" + extensionServer.nextObjectId(); + var request = { + command: commands.CreateSidebarPane, + panel: this._id, + id: id, + title: title + }; + function callbackWrapper() + { + callback(new ExtensionSidebarPane(id)); + } + extensionServer.sendRequest(request, callback && callbackWrapper); + } +} + +PanelWithSidebarImpl.prototype.__proto__ = ExtensionViewImpl.prototype; + +/** + * @constructor + * @extends {PanelWithSidebar} + */ +function ElementsPanel() +{ + var id = "elements"; + PanelWithSidebar.call(this, id); + this.onSelectionChanged = new EventSink(events.ElementsPanelObjectSelected); +} + +/** + * @constructor + * @extends {ExtensionViewImpl} + */ +function ExtensionPanelImpl(id) +{ + ExtensionViewImpl.call(this, id); + this.onSearch = new EventSink(events.PanelSearch + id); +} + +ExtensionPanelImpl.prototype = { + createStatusBarButton: function(iconPath, tooltipText, disabled) + { + var id = "button-" + extensionServer.nextObjectId(); + var request = { + command: commands.CreateStatusBarButton, + panel: this._id, + id: id, + icon: iconPath, + tooltip: tooltipText, + disabled: !!disabled + }; + extensionServer.sendRequest(request); + return new Button(id); + } +}; + +ExtensionPanelImpl.prototype.__proto__ = ExtensionViewImpl.prototype; + +/** + * @constructor + * @extends {ExtensionViewImpl} + */ +function ExtensionSidebarPaneImpl(id) +{ + ExtensionViewImpl.call(this, id); +} + +ExtensionSidebarPaneImpl.prototype = { + setHeight: function(height) + { + extensionServer.sendRequest({ command: commands.SetSidebarHeight, id: this._id, height: height }); + }, + + setExpression: function(expression, rootTitle, callback) + { + extensionServer.sendRequest({ command: commands.SetSidebarContent, id: this._id, expression: expression, rootTitle: rootTitle, evaluateOnPage: true }, callback); + }, + + setObject: function(jsonObject, rootTitle, callback) + { + extensionServer.sendRequest({ command: commands.SetSidebarContent, id: this._id, expression: jsonObject, rootTitle: rootTitle }, callback); + }, + + setPage: function(page) + { + extensionServer.sendRequest({ command: commands.SetSidebarPage, id: this._id, page: page }); + } +} + +/** + * @constructor + */ +function ButtonImpl(id) +{ + this._id = id; + this.onClicked = new EventSink(events.ButtonClicked + id); +} + +ButtonImpl.prototype = { + update: function(iconPath, tooltipText, disabled) + { + var request = { + command: commands.UpdateButton, + id: this._id, + icon: iconPath, + tooltip: tooltipText, + disabled: !!disabled + }; + extensionServer.sendRequest(request); + } +}; + +/** + * @constructor + */ +function Audits() +{ +} + +Audits.prototype = { + addCategory: function(displayName, resultCount) + { + var id = "extension-audit-category-" + extensionServer.nextObjectId(); + extensionServer.sendRequest({ command: commands.AddAuditCategory, id: id, displayName: displayName, resultCount: resultCount }); + return new AuditCategory(id); + } +} + +/** + * @constructor + */ +function AuditCategoryImpl(id) +{ + function dispatchAuditEvent(request) + { + var auditResult = new AuditResult(request.arguments[0]); + try { + this._fire(auditResult); + } catch (e) { + console.error("Uncaught exception in extension audit event handler: " + e); + auditResult.done(); + } + } + this._id = id; + this.onAuditStarted = new EventSink(events.AuditStarted + id, dispatchAuditEvent); +} + +/** + * @constructor + */ +function AuditResultImpl(id) +{ + this._id = id; + + this.createURL = bind(this._nodeFactory, null, "url"); + this.createSnippet = bind(this._nodeFactory, null, "snippet"); + this.createText = bind(this._nodeFactory, null, "text"); +} + +AuditResultImpl.prototype = { + addResult: function(displayName, description, severity, details) + { + // shorthand for specifying details directly in addResult(). + if (details && !(details instanceof AuditResultNode)) + details = new AuditResultNode(details instanceof Array ? details : [details]); + + var request = { + command: commands.AddAuditResult, + resultId: this._id, + displayName: displayName, + description: description, + severity: severity, + details: details + }; + extensionServer.sendRequest(request); + }, + + createResult: function() + { + return new AuditResultNode(Array.prototype.slice.call(arguments)); + }, + + done: function() + { + extensionServer.sendRequest({ command: commands.StopAuditCategoryRun, resultId: this._id }); + }, + + get Severity() + { + return apiPrivate.audits.Severity; + }, + + createResourceLink: function(url, lineNumber) + { + return { + type: "resourceLink", + arguments: [url, lineNumber && lineNumber - 1] + }; + }, + + _nodeFactory: function(type) + { + return { + type: type, + arguments: Array.prototype.slice.call(arguments, 1) + }; + } +} + +/** + * @constructor + */ +function AuditResultNode(contents) +{ + this.contents = contents; + this.children = []; + this.expanded = false; +} + +AuditResultNode.prototype = { + addChild: function() + { + var node = new AuditResultNode(Array.prototype.slice.call(arguments)); + this.children.push(node); + return node; + } +}; + +/** + * @constructor + */ +function InspectedWindow() +{ + function dispatchResourceEvent(message) + { + this._fire(new Resource(message.arguments[0])); + } + function dispatchResourceContentEvent(message) + { + this._fire(new Resource(message.arguments[0]), message.arguments[1]); + } + this.onResourceAdded = new EventSink(events.ResourceAdded, dispatchResourceEvent); + this.onResourceContentCommitted = new EventSink(events.ResourceContentCommitted, dispatchResourceContentEvent); +} + +InspectedWindow.prototype = { + reload: function(optionsOrUserAgent) + { + var options = null; + if (typeof optionsOrUserAgent === "object") + options = optionsOrUserAgent; + else if (typeof optionsOrUserAgent === "string") { + options = { userAgent: optionsOrUserAgent }; + console.warn("Passing userAgent as string parameter to inspectedWindow.reload() is deprecated. " + + "Use inspectedWindow.reload({ userAgent: value}) instead."); + } + return extensionServer.sendRequest({ command: commands.Reload, options: options }); + }, + + eval: function(expression, callback) + { + function callbackWrapper(result) + { + callback(result.value, result.isException); + } + return extensionServer.sendRequest({ command: commands.EvaluateOnInspectedPage, expression: expression }, callback && callbackWrapper); + }, + + getResources: function(callback) + { + function wrapResource(resourceData) + { + return new Resource(resourceData); + } + function callbackWrapper(resources) + { + callback(resources.map(wrapResource)); + } + return extensionServer.sendRequest({ command: commands.GetPageResources }, callback && callbackWrapper); + } +} + +/** + * @constructor + */ +function ResourceImpl(resourceData) +{ + this._url = resourceData.url + this._type = resourceData.type; +} + +ResourceImpl.prototype = { + get url() + { + return this._url; + }, + + get type() + { + return this._type; + }, + + getContent: function(callback) + { + function callbackWrapper(response) + { + callback(response.content, response.encoding); + } + + return extensionServer.sendRequest({ command: commands.GetResourceContent, url: this._url }, callback && callbackWrapper); + }, + + setContent: function(content, commit, callback) + { + return extensionServer.sendRequest({ command: commands.SetResourceContent, url: this._url, content: content, commit: commit }, callback); + } +} + +/** + * @constructor + */ +function TimelineImpl() +{ + this.onEventRecorded = new EventSink(events.TimelineEventRecorded); +} + +/** + * @constructor + */ +function ExtensionServerClient() +{ + this._callbacks = {}; + this._handlers = {}; + this._lastRequestId = 0; + this._lastObjectId = 0; + + this.registerHandler("callback", bind(this._onCallback, this)); + + var channel = new MessageChannel(); + this._port = channel.port1; + this._port.addEventListener("message", bind(this._onMessage, this), false); + this._port.start(); + + top.postMessage("registerExtension", [ channel.port2 ], "*"); +} + +ExtensionServerClient.prototype = { + sendRequest: function(message, callback) + { + if (typeof callback === "function") + message.requestId = this._registerCallback(callback); + return this._port.postMessage(message); + }, + + hasHandler: function(command) + { + return !!this._handlers[command]; + }, + + registerHandler: function(command, handler) + { + this._handlers[command] = handler; + }, + + unregisterHandler: function(command) + { + delete this._handlers[command]; + }, + + nextObjectId: function() + { + return injectedScriptId + "_" + ++this._lastObjectId; + }, + + _registerCallback: function(callback) + { + var id = ++this._lastRequestId; + this._callbacks[id] = callback; + return id; + }, + + _onCallback: function(request) + { + if (request.requestId in this._callbacks) { + var callback = this._callbacks[request.requestId]; + delete this._callbacks[request.requestId]; + callback(request.result); + } + }, + + _onMessage: function(event) + { + var request = event.data; + var handler = this._handlers[request.command]; + if (handler) + handler.call(this, request); + } +} + +/** + * @param {...*} vararg + */ +function bind(func, thisObject, vararg) +{ + var args = Array.prototype.slice.call(arguments, 2); + return function() { return func.apply(thisObject, args.concat(Array.prototype.slice.call(arguments, 0))); }; +} + +function populateInterfaceClass(interface, implementation) +{ + for (var member in implementation) { + if (member.charAt(0) === "_") + continue; + var descriptor = null; + // Traverse prototype chain until we find the owner. + for (var owner = implementation; owner && !descriptor; owner = owner.__proto__) + descriptor = Object.getOwnPropertyDescriptor(owner, member); + if (!descriptor) + continue; + if (typeof descriptor.value === "function") + interface[member] = bind(descriptor.value, implementation); + else if (typeof descriptor.get === "function") + interface.__defineGetter__(member, bind(descriptor.get, implementation)); + else + Object.defineProperty(interface, member, descriptor); + } +} + +function declareInterfaceClass(implConstructor) +{ + return function() + { + var impl = { __proto__: implConstructor.prototype }; + implConstructor.apply(impl, arguments); + populateInterfaceClass(this, impl); + } +} + +function defineDeprecatedProperty(object, className, oldName, newName) +{ + var warningGiven = false; + function getter() + { + if (!warningGiven) { + console.warn(className + "." + oldName + " is deprecated. Use " + className + "." + newName + " instead"); + warningGiven = true; + } + return object[newName]; + } + object.__defineGetter__(oldName, getter); +} + +var AuditCategory = declareInterfaceClass(AuditCategoryImpl); +var AuditResult = declareInterfaceClass(AuditResultImpl); +var Button = declareInterfaceClass(ButtonImpl); +var EventSink = declareInterfaceClass(EventSinkImpl); +var ExtensionPanel = declareInterfaceClass(ExtensionPanelImpl); +var ExtensionSidebarPane = declareInterfaceClass(ExtensionSidebarPaneImpl); +var PanelWithSidebar = declareInterfaceClass(PanelWithSidebarImpl); +var Request = declareInterfaceClass(RequestImpl); +var Resource = declareInterfaceClass(ResourceImpl); +var Timeline = declareInterfaceClass(TimelineImpl); + +var extensionServer = new ExtensionServerClient(); + +return new InspectorExtensionAPI(); +} + +// Default implementation; platforms will override. +function buildPlatformExtensionAPI(extensionInfo) +{ + function platformExtensionAPI(coreAPI) + { + window.webInspector = coreAPI; + } + return platformExtensionAPI.toString(); +} + + +function buildExtensionAPIInjectedScript(extensionInfo) +{ + return "(function(injectedScriptHost, inspectedWindow, injectedScriptId){ " + + defineCommonExtensionSymbols.toString() + ";" + + injectedExtensionAPI.toString() + ";" + + buildPlatformExtensionAPI(extensionInfo) + ";" + + "platformExtensionAPI(injectedExtensionAPI(injectedScriptId));" + + "return {};" + + "})"; +} +/* ExtensionAuditCategory.js */ + +/* + * 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. + * * 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. + */ + +/** + * @constructor + */ +WebInspector.ExtensionAuditCategory = function(id, displayName, ruleCount) +{ + this._id = id; + this._displayName = displayName; + this._ruleCount = ruleCount; +} + +WebInspector.ExtensionAuditCategory.prototype = { + // AuditCategory interface + get id() + { + return this._id; + }, + + get displayName() + { + return this._displayName; + }, + + get ruleCount() + { + return this._ruleCount; + }, + + run: function(resources, callback) + { + new WebInspector.ExtensionAuditCategoryResults(this, callback); + } +} + +/** + * @constructor + */ +WebInspector.ExtensionAuditCategoryResults = function(category, callback) +{ + this._category = category; + this._pendingRules = category.ruleCount; + this._ruleCompletionCallback = callback; + + this.id = category.id + "-" + ++WebInspector.ExtensionAuditCategoryResults._lastId; + WebInspector.extensionServer.startAuditRun(category, this); +} + +WebInspector.ExtensionAuditCategoryResults.prototype = { + get complete() + { + return !this._pendingRules; + }, + + cancel: function() + { + while (!this.complete) + this._addResult(null); + }, + + addResult: function(displayName, description, severity, details) + { + var result = new WebInspector.AuditRuleResult(displayName); + result.addChild(description); + result.severity = severity; + if (details) + this._addNode(result, details); + this._addResult(result); + }, + + _addNode: function(parent, node) + { + var addedNode = parent.addChild(node.contents, node.expanded); + if (node.children) { + for (var i = 0; i < node.children.length; ++i) + this._addNode(addedNode, node.children[i]); + } + }, + + _addResult: function(result) + { + this._ruleCompletionCallback(result); + this._pendingRules--; + if (!this._pendingRules) + WebInspector.extensionServer.stopAuditRun(this); + } +} + +WebInspector.ExtensionAuditCategoryResults._lastId = 0; +/* ExtensionServer.js */ + +/* + * Copyright (C) 2011 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. + */ + +/** + * @constructor + */ +WebInspector.ExtensionServer = function() +{ + this._clientObjects = {}; + this._handlers = {}; + this._subscribers = {}; + this._subscriptionStartHandlers = {}; + this._subscriptionStopHandlers = {}; + this._extraHeaders = {}; + this._requests = {}; + this._lastRequestId = 0; + this._registeredExtensions = {}; + this._status = new WebInspector.ExtensionStatus(); + + var commands = WebInspector.extensionAPI.Commands; + + this._registerHandler(commands.AddAuditCategory, this._onAddAuditCategory.bind(this)); + this._registerHandler(commands.AddAuditResult, this._onAddAuditResult.bind(this)); + this._registerHandler(commands.AddConsoleMessage, this._onAddConsoleMessage.bind(this)); + this._registerHandler(commands.AddRequestHeaders, this._onAddRequestHeaders.bind(this)); + this._registerHandler(commands.CreatePanel, this._onCreatePanel.bind(this)); + this._registerHandler(commands.CreateSidebarPane, this._onCreateSidebarPane.bind(this)); + this._registerHandler(commands.CreateStatusBarButton, this._onCreateStatusBarButton.bind(this)); + this._registerHandler(commands.EvaluateOnInspectedPage, this._onEvaluateOnInspectedPage.bind(this)); + this._registerHandler(commands.GetHAR, this._onGetHAR.bind(this)); + this._registerHandler(commands.GetConsoleMessages, this._onGetConsoleMessages.bind(this)); + this._registerHandler(commands.GetPageResources, this._onGetPageResources.bind(this)); + this._registerHandler(commands.GetRequestContent, this._onGetRequestContent.bind(this)); + this._registerHandler(commands.GetResourceContent, this._onGetResourceContent.bind(this)); + this._registerHandler(commands.Log, this._onLog.bind(this)); + this._registerHandler(commands.Reload, this._onReload.bind(this)); + this._registerHandler(commands.SetOpenResourceHandler, this._onSetOpenResourceHandler.bind(this)); + this._registerHandler(commands.SetResourceContent, this._onSetResourceContent.bind(this)); + this._registerHandler(commands.SetSidebarHeight, this._onSetSidebarHeight.bind(this)); + this._registerHandler(commands.SetSidebarContent, this._onSetSidebarContent.bind(this)); + this._registerHandler(commands.SetSidebarPage, this._onSetSidebarPage.bind(this)); + this._registerHandler(commands.StopAuditCategoryRun, this._onStopAuditCategoryRun.bind(this)); + this._registerHandler(commands.Subscribe, this._onSubscribe.bind(this)); + this._registerHandler(commands.Unsubscribe, this._onUnsubscribe.bind(this)); + this._registerHandler(commands.UpdateButton, this._onUpdateButton.bind(this)); + + window.addEventListener("message", this._onWindowMessage.bind(this), false); +} + +WebInspector.ExtensionServer.prototype = { + hasExtensions: function() + { + return !!Object.keys(this._registeredExtensions).length; + }, + + notifySearchAction: function(panelId, action, searchString) + { + this._postNotification(WebInspector.extensionAPI.Events.PanelSearch + panelId, action, searchString); + }, + + notifyViewShown: function(identifier, frameIndex) + { + this._postNotification(WebInspector.extensionAPI.Events.ViewShown + identifier, frameIndex); + }, + + notifyViewHidden: function(identifier) + { + this._postNotification(WebInspector.extensionAPI.Events.ViewHidden + identifier); + }, + + notifyButtonClicked: function(identifier) + { + this._postNotification(WebInspector.extensionAPI.Events.ButtonClicked + identifier); + }, + + _inspectedURLChanged: function(event) + { + this._requests = {}; + var url = event.data; + this._postNotification(WebInspector.extensionAPI.Events.InspectedURLChanged, url); + }, + + _mainFrameNavigated: function(event) + { + this._postNotification(WebInspector.extensionAPI.Events.Reset); + }, + + startAuditRun: function(category, auditRun) + { + this._clientObjects[auditRun.id] = auditRun; + this._postNotification("audit-started-" + category.id, auditRun.id); + }, + + stopAuditRun: function(auditRun) + { + delete this._clientObjects[auditRun.id]; + }, + + /** + * @param {...*} vararg + */ + _postNotification: function(type, vararg) + { + var subscribers = this._subscribers[type]; + if (!subscribers) + return; + var message = { + command: "notify-" + type, + arguments: Array.prototype.slice.call(arguments, 1) + }; + for (var i = 0; i < subscribers.length; ++i) + subscribers[i].postMessage(message); + }, + + _onSubscribe: function(message, port) + { + var subscribers = this._subscribers[message.type]; + if (subscribers) + subscribers.push(port); + else { + this._subscribers[message.type] = [ port ]; + if (this._subscriptionStartHandlers[message.type]) + this._subscriptionStartHandlers[message.type](); + } + }, + + _onUnsubscribe: function(message, port) + { + var subscribers = this._subscribers[message.type]; + if (!subscribers) + return; + subscribers.remove(port); + if (!subscribers.length) { + delete this._subscribers[message.type]; + if (this._subscriptionStopHandlers[message.type]) + this._subscriptionStopHandlers[message.type](); + } + }, + + _onAddRequestHeaders: function(message) + { + var id = message.extensionId; + if (typeof id !== "string") + return this._status.E_BADARGTYPE("extensionId", typeof id, "string"); + var extensionHeaders = this._extraHeaders[id]; + if (!extensionHeaders) { + extensionHeaders = {}; + this._extraHeaders[id] = extensionHeaders; + } + for (var name in message.headers) + extensionHeaders[name] = message.headers[name]; + var allHeaders = /** @type NetworkAgent.Headers */ {}; + for (var extension in this._extraHeaders) { + var headers = this._extraHeaders[extension]; + for (name in headers) { + if (typeof headers[name] === "string") + allHeaders[name] = headers[name]; + } + } + NetworkAgent.setExtraHTTPHeaders(allHeaders); + }, + + _onCreatePanel: function(message, port) + { + var id = message.id; + // The ids are generated on the client API side and must be unique, so the check below + // shouldn't be hit unless someone is bypassing the API. + if (id in this._clientObjects || id in WebInspector.panels) + return this._status.E_EXISTS(id); + + var page = this._expandResourcePath(port._extensionOrigin, message.page); + var icon = this._expandResourcePath(port._extensionOrigin, message.icon) + var panel = new WebInspector.ExtensionPanel(id, message.title, page, icon); + this._clientObjects[id] = panel; + WebInspector.panels[id] = panel; + WebInspector.addPanel(panel); + return this._status.OK(); + }, + + _onCreateStatusBarButton: function(message, port) + { + var panel = this._clientObjects[message.panel]; + if (!panel || !(panel instanceof WebInspector.ExtensionPanel)) + return this._status.E_NOTFOUND(message.panel); + var button = new WebInspector.ExtensionButton(message.id, this._expandResourcePath(port._extensionOrigin, message.icon), message.tooltip, message.disabled); + this._clientObjects[message.id] = button; + panel.addStatusBarItem(button.element); + return this._status.OK(); + }, + + _onUpdateButton: function(message, port) + { + var button = this._clientObjects[message.id]; + if (!button || !(button instanceof WebInspector.ExtensionButton)) + return this._status.E_NOTFOUND(message.id); + button.update(this._expandResourcePath(port._extensionOrigin, message.icon), message.tooltip, message.disabled); + return this._status.OK(); + }, + + _onCreateSidebarPane: function(message) + { + var panel = WebInspector.panels[message.panel]; + if (!panel) + return this._status.E_NOTFOUND(message.panel); + if (!panel.sidebarElement || !panel.sidebarPanes) + return this._status.E_NOTSUPPORTED(); + var id = message.id; + var sidebar = new WebInspector.ExtensionSidebarPane(message.title, message.id); + this._clientObjects[id] = sidebar; + panel.sidebarPanes[id] = sidebar; + panel.sidebarElement.appendChild(sidebar.element); + + return this._status.OK(); + }, + + _onSetSidebarHeight: function(message) + { + var sidebar = this._clientObjects[message.id]; + if (!sidebar) + return this._status.E_NOTFOUND(message.id); + sidebar.setHeight(message.height); + return this._status.OK(); + }, + + _onSetSidebarContent: function(message, port) + { + var sidebar = this._clientObjects[message.id]; + if (!sidebar) + return this._status.E_NOTFOUND(message.id); + function callback(error) + { + var result = error ? this._status.E_FAILED(error) : this._status.OK(); + this._dispatchCallback(message.requestId, port, result); + } + if (message.evaluateOnPage) + sidebar.setExpression(message.expression, message.rootTitle, callback.bind(this)); + else + sidebar.setObject(message.expression, message.rootTitle, callback.bind(this)); + }, + + _onSetSidebarPage: function(message, port) + { + var sidebar = this._clientObjects[message.id]; + if (!sidebar) + return this._status.E_NOTFOUND(message.id); + sidebar.setPage(this._expandResourcePath(port._extensionOrigin, message.page)); + }, + + _onSetOpenResourceHandler: function(message, port) + { + var name = this._registeredExtensions[port._extensionOrigin].name || ("Extension " + port._extensionOrigin); + if (message.handlerPresent) + WebInspector.openAnchorLocationRegistry.registerHandler(name, this._handleOpenURL.bind(this, port)); + else + WebInspector.openAnchorLocationRegistry.unregisterHandler(name); + }, + + _handleOpenURL: function(port, details) + { + var resource = WebInspector.resourceForURL(details.url); + if (!resource) + return false; + var lineNumber = details.lineNumber; + if (typeof lineNumber === "number") + lineNumber += 1; + port.postMessage({ + command: "open-resource", + resource: this._makeResource(resource), + lineNumber: lineNumber + }); + return true; + }, + + _onLog: function(message) + { + WebInspector.log(message.message); + }, + + _onReload: function(message) + { + var options = /** @type ExtensionReloadOptions */ (message.options || {}); + NetworkAgent.setUserAgentOverride(typeof options.userAgent === "string" ? options.userAgent : ""); + var injectedScript; + if (options.injectedScript) { + // Wrap client script into anonymous function, return another anonymous function that + // returns empty object for compatibility with InjectedScriptManager on the backend. + injectedScript = "((function(){" + options.injectedScript + "})(),function(){return {}})"; + } + PageAgent.reload(!!options.ignoreCache, injectedScript); + return this._status.OK(); + }, + + _onEvaluateOnInspectedPage: function(message, port) + { + function callback(error, resultPayload, wasThrown) + { + var result = {}; + if (error) { + result.isException = true; + result.value = error.message; + } else + result.value = resultPayload.value; + + if (wasThrown) + result.isException = true; + + this._dispatchCallback(message.requestId, port, result); + } + RuntimeAgent.evaluate(message.expression, "", true, undefined, undefined, true, callback.bind(this)); + }, + + _onGetConsoleMessages: function() + { + return WebInspector.console.messages.map(this._makeConsoleMessage); + }, + + _onAddConsoleMessage: function(message) + { + function convertSeverity(level) + { + switch (level) { + case WebInspector.extensionAPI.console.Severity.Tip: + return WebInspector.ConsoleMessage.MessageLevel.Tip; + case WebInspector.extensionAPI.console.Severity.Log: + return WebInspector.ConsoleMessage.MessageLevel.Log; + case WebInspector.extensionAPI.console.Severity.Warning: + return WebInspector.ConsoleMessage.MessageLevel.Warning; + case WebInspector.extensionAPI.console.Severity.Error: + return WebInspector.ConsoleMessage.MessageLevel.Error; + case WebInspector.extensionAPI.console.Severity.Debug: + return WebInspector.ConsoleMessage.MessageLevel.Debug; + } + } + var level = convertSeverity(message.severity); + if (!level) + return this._status.E_BADARG("message.severity", message.severity); + + var consoleMessage = WebInspector.ConsoleMessage.create( + WebInspector.ConsoleMessage.MessageSource.JS, + level, + message.text, + WebInspector.ConsoleMessage.MessageType.Log, + message.url, + message.line); + WebInspector.console.addMessage(consoleMessage); + }, + + _makeConsoleMessage: function(message) + { + function convertLevel(level) + { + if (!level) + return; + switch (level) { + case WebInspector.ConsoleMessage.MessageLevel.Tip: + return WebInspector.extensionAPI.console.Severity.Tip; + case WebInspector.ConsoleMessage.MessageLevel.Log: + return WebInspector.extensionAPI.console.Severity.Log; + case WebInspector.ConsoleMessage.MessageLevel.Warning: + return WebInspector.extensionAPI.console.Severity.Warning; + case WebInspector.ConsoleMessage.MessageLevel.Error: + return WebInspector.extensionAPI.console.Severity.Error; + case WebInspector.ConsoleMessage.MessageLevel.Debug: + return WebInspector.extensionAPI.console.Severity.Debug; + default: + return WebInspector.extensionAPI.console.Severity.Log; + } + } + var result = { + severity: convertLevel(message.level), + text: message.text, + }; + if (message.url) + result.url = message.url; + if (message.line) + result.line = message.line; + return result; + }, + + _onGetHAR: function() + { + var requests = WebInspector.networkLog.resources; + var harLog = (new WebInspector.HARLog(requests)).build(); + for (var i = 0; i < harLog.entries.length; ++i) + harLog.entries[i]._requestId = this._requestId(requests[i]); + return harLog; + }, + + _makeResource: function(resource) + { + return { + url: resource.url, + type: WebInspector.Resource.Type.toString(resource.type) + }; + }, + + _onGetPageResources: function() + { + var resources = []; + function pushResourceData(resource) + { + resources.push(this._makeResource(resource)); + } + WebInspector.resourceTreeModel.forAllResources(pushResourceData.bind(this)); + return resources; + }, + + _getResourceContent: function(resource, message, port) + { + function onContentAvailable(content, encoded) + { + var response = { + encoding: encoded ? "base64" : "", + content: content + }; + this._dispatchCallback(message.requestId, port, response); + } + resource.requestContent(onContentAvailable.bind(this)); + }, + + _onGetRequestContent: function(message, port) + { + var request = this._requestById(message.id); + if (!request) + return this._status.E_NOTFOUND(message.id); + this._getResourceContent(request, message, port); + }, + + _onGetResourceContent: function(message, port) + { + var resource = WebInspector.resourceTreeModel.resourceForURL(message.url); + if (!resource) + return this._status.E_NOTFOUND(message.url); + this._getResourceContent(resource, message, port); + }, + + _onSetResourceContent: function(message, port) + { + function callbackWrapper(error) + { + var response = error ? this._status.E_FAILED(error) : this._status.OK(); + this._dispatchCallback(message.requestId, port, response); + } + var resource = WebInspector.resourceTreeModel.resourceForURL(message.url); + if (!resource) + return this._status.E_NOTFOUND(message.url); + resource.setContent(message.content, message.commit, callbackWrapper.bind(this)); + }, + + _requestId: function(request) + { + if (!request._extensionRequestId) { + request._extensionRequestId = ++this._lastRequestId; + this._requests[request._extensionRequestId] = request; + } + return request._extensionRequestId; + }, + + _requestById: function(id) + { + return this._requests[id]; + }, + + _onAddAuditCategory: function(message) + { + var category = new WebInspector.ExtensionAuditCategory(message.id, message.displayName, message.resultCount); + if (WebInspector.panels.audits.getCategory(category.id)) + return this._status.E_EXISTS(category.id); + this._clientObjects[message.id] = category; + WebInspector.panels.audits.addCategory(category); + }, + + _onAddAuditResult: function(message) + { + var auditResult = this._clientObjects[message.resultId]; + if (!auditResult) + return this._status.E_NOTFOUND(message.resultId); + try { + auditResult.addResult(message.displayName, message.description, message.severity, message.details); + } catch (e) { + return e; + } + return this._status.OK(); + }, + + _onStopAuditCategoryRun: function(message) + { + var auditRun = this._clientObjects[message.resultId]; + if (!auditRun) + return this._status.E_NOTFOUND(message.resultId); + auditRun.cancel(); + }, + + _dispatchCallback: function(requestId, port, result) + { + if (requestId) + port.postMessage({ command: "callback", requestId: requestId, result: result }); + }, + + initExtensions: function() + { + this._registerAutosubscriptionHandler(WebInspector.extensionAPI.Events.ConsoleMessageAdded, + WebInspector.console, WebInspector.ConsoleModel.Events.MessageAdded, this._notifyConsoleMessageAdded); + this._registerAutosubscriptionHandler(WebInspector.extensionAPI.Events.NetworkRequestFinished, + WebInspector.networkManager, WebInspector.NetworkManager.EventTypes.ResourceFinished, this._notifyRequestFinished); + this._registerAutosubscriptionHandler(WebInspector.extensionAPI.Events.ResourceAdded, + WebInspector.resourceTreeModel, + WebInspector.ResourceTreeModel.EventTypes.ResourceAdded, + this._notifyResourceAdded); + if (WebInspector.panels.elements) { + this._registerAutosubscriptionHandler(WebInspector.extensionAPI.Events.ElementsPanelObjectSelected, + WebInspector.panels.elements.treeOutline, + WebInspector.ElementsTreeOutline.Events.SelectedNodeChanged, + this._notifyElementsSelectionChanged); + } + this._registerAutosubscriptionHandler(WebInspector.extensionAPI.Events.ResourceContentCommitted, + WebInspector.resourceTreeModel, + WebInspector.ResourceTreeModel.EventTypes.ResourceContentCommitted, + this._notifyResourceContentCommitted); + + function onTimelineSubscriptionStarted() + { + WebInspector.timelineManager.addEventListener(WebInspector.TimelineManager.EventTypes.TimelineEventRecorded, + this._notifyTimelineEventRecorded, this); + WebInspector.timelineManager.start(); + } + function onTimelineSubscriptionStopped() + { + WebInspector.timelineManager.stop(); + WebInspector.timelineManager.removeEventListener(WebInspector.TimelineManager.EventTypes.TimelineEventRecorded, + this._notifyTimelineEventRecorded, this); + } + this._registerSubscriptionHandler(WebInspector.extensionAPI.Events.TimelineEventRecorded, + onTimelineSubscriptionStarted.bind(this), onTimelineSubscriptionStopped.bind(this)); + + WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.InspectedURLChanged, + this._inspectedURLChanged, this); + WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, this._mainFrameNavigated, this); + InspectorExtensionRegistry.getExtensionsAsync(); + }, + + _notifyConsoleMessageAdded: function(event) + { + this._postNotification(WebInspector.extensionAPI.Events.ConsoleMessageAdded, this._makeConsoleMessage(event.data)); + }, + + _notifyResourceAdded: function(event) + { + var resource = event.data; + this._postNotification(WebInspector.extensionAPI.Events.ResourceAdded, this._makeResource(resource)); + }, + + _notifyResourceContentCommitted: function(event) + { + this._postNotification(WebInspector.extensionAPI.Events.ResourceContentCommitted, this._makeResource(event.data.resource), event.data.content); + }, + + _notifyRequestFinished: function(event) + { + var request = event.data; + this._postNotification(WebInspector.extensionAPI.Events.NetworkRequestFinished, this._requestId(request), (new WebInspector.HAREntry(request)).build()); + }, + + _notifyElementsSelectionChanged: function() + { + this._postNotification(WebInspector.extensionAPI.Events.ElementsPanelObjectSelected); + }, + + _notifyTimelineEventRecorded: function(event) + { + this._postNotification(WebInspector.extensionAPI.Events.TimelineEventRecorded, event.data); + }, + + /** + * @param {Array.} extensions + */ + _addExtensions: function(extensions) + { + for (var i = 0; i < extensions.length; ++i) + this._addExtension(extensions[i]); + }, + + _addExtension: function(extensionInfo) + { + const urlOriginRegExp = new RegExp("([^:]+:\/\/[^/]*)\/"); // Can't use regexp literal here, MinJS chokes on it. + var startPage = extensionInfo.startPage; + var name = extensionInfo.name; + + try { + var originMatch = urlOriginRegExp.exec(startPage); + if (!originMatch) { + console.error("Skipping extension with invalid URL: " + startPage); + return false; + } + var extensionOrigin = originMatch[1]; + if (!this._registeredExtensions[extensionOrigin]) { + // See ExtensionAPI.js and ExtensionCommon.js for details. + InspectorFrontendHost.setInjectedScriptForOrigin(extensionOrigin, buildExtensionAPIInjectedScript(extensionInfo)); + this._registeredExtensions[extensionOrigin] = { name: name }; + } + var iframe = document.createElement("iframe"); + iframe.src = startPage; + iframe.style.display = "none"; + document.body.appendChild(iframe); + } catch (e) { + console.error("Failed to initialize extension " + startPage + ":" + e); + return false; + } + return true; + }, + + _onWindowMessage: function(event) + { + if (event.data === "registerExtension") + this._registerExtension(event.origin, event.ports[0]); + }, + + _registerExtension: function(origin, port) + { + if (!this._registeredExtensions.hasOwnProperty(origin)) { + if (origin !== window.location.origin) // Just ignore inspector frames. + console.error("Ignoring unauthorized client request from " + origin); + return; + } + port._extensionOrigin = origin; + port.addEventListener("message", this._onmessage.bind(this), false); + port.start(); + }, + + _onmessage: function(event) + { + var message = event.data; + var result; + + if (message.command in this._handlers) + result = this._handlers[message.command](message, event.target); + else + result = this._status.E_NOTSUPPORTED(message.command); + + if (result && message.requestId) + this._dispatchCallback(message.requestId, event.target, result); + }, + + _registerHandler: function(command, callback) + { + this._handlers[command] = callback; + }, + + _registerSubscriptionHandler: function(eventTopic, onSubscribeFirst, onUnsubscribeLast) + { + this._subscriptionStartHandlers[eventTopic] = onSubscribeFirst; + this._subscriptionStopHandlers[eventTopic] = onUnsubscribeLast; + }, + + _registerAutosubscriptionHandler: function(eventTopic, eventTarget, frontendEventType, handler) + { + this._registerSubscriptionHandler(eventTopic, + eventTarget.addEventListener.bind(eventTarget, frontendEventType, handler, this), + eventTarget.removeEventListener.bind(eventTarget, frontendEventType, handler, this)); + }, + + _expandResourcePath: function(extensionPath, resourcePath) + { + if (!resourcePath) + return; + return extensionPath + this._normalizePath(resourcePath); + }, + + _normalizePath: function(path) + { + var source = path.split("/"); + var result = []; + + for (var i = 0; i < source.length; ++i) { + if (source[i] === ".") + continue; + // Ignore empty path components resulting from //, as well as a leading and traling slashes. + if (source[i] === "") + continue; + if (source[i] === "..") + result.pop(); + else + result.push(source[i]); + } + return "/" + result.join("/"); + } +} + +/** + * @constructor + */ +WebInspector.ExtensionStatus = function() +{ + function makeStatus(code, description) + { + var details = Array.prototype.slice.call(arguments, 2); + var status = { code: code, description: description, details: details }; + if (code !== "OK") { + status.isError = true; + console.log("Extension server error: " + String.vsprintf(description, details)); + } + return status; + } + + this.OK = makeStatus.bind(null, "OK", "OK"); + this.E_EXISTS = makeStatus.bind(null, "E_EXISTS", "Object already exists: %s"); + this.E_BADARG = makeStatus.bind(null, "E_BADARG", "Invalid argument %s: %s"); + this.E_BADARGTYPE = makeStatus.bind(null, "E_BADARGTYPE", "Invalid type for argument %s: got %s, expected %s"); + this.E_NOTFOUND = makeStatus.bind(null, "E_NOTFOUND", "Object not found: %s"); + this.E_NOTSUPPORTED = makeStatus.bind(null, "E_NOTSUPPORTED", "Object does not support requested operation: %s"); + this.E_FAILED = makeStatus.bind(null, "E_FAILED", "Operation failed: %s"); +} + +WebInspector.addExtensions = function(extensions) +{ + WebInspector.extensionServer._addExtensions(extensions); +} + +WebInspector.extensionAPI = {}; +defineCommonExtensionSymbols(WebInspector.extensionAPI); + +WebInspector.extensionServer = new WebInspector.ExtensionServer(); + +window.addExtension = function(page, name) +{ + WebInspector.extensionServer._addExtension({ + startPage: page, + name: name, + }); +} +/* ExtensionPanel.js */ + +/* + * Copyright (C) 2011 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. + */ + +/** + * @constructor + * @extends {WebInspector.View} + * @param {string} id + * @param {Element} parent + * @param {string} src + * @param {string} className + */ +WebInspector.ExtensionView = function(id, parent, src, className) +{ + WebInspector.View.call(this); + + this._id = id; + this._iframe = document.createElement("iframe"); + this._iframe.addEventListener("load", this._onLoad.bind(this), false); + this._iframe.src = src; + this._iframe.className = className; + + this.element.appendChild(this._iframe); + this.show(parent); +} + +WebInspector.ExtensionView.prototype = { + wasShown: function() + { + if (typeof this._frameIndex === "number") + WebInspector.extensionServer.notifyViewShown(this._id, this._frameIndex); + }, + + willHide: function() + { + if (typeof this._frameIndex === "number") + WebInspector.extensionServer.notifyViewHidden(this._id); + }, + + _onLoad: function() + { + this._frameIndex = Array.prototype.indexOf.call(window.frames, this._iframe.contentWindow); + if (this.isShowing()) + WebInspector.extensionServer.notifyViewShown(this._id, this._frameIndex); + } +} + +WebInspector.ExtensionView.prototype.__proto__ = WebInspector.View.prototype; + +/** + * @constructor + * @extends {WebInspector.View} + * @param {string} id + */ +WebInspector.ExtensionNotifierView = function(id) +{ + WebInspector.View.call(this); + + this._id = id; +} + +WebInspector.ExtensionNotifierView.prototype = { + wasShown: function() + { + WebInspector.extensionServer.notifyViewShown(this._id); + }, + + willHide: function() + { + WebInspector.extensionServer.notifyViewHidden(this._id); + } +} + +WebInspector.ExtensionNotifierView.prototype.__proto__ = WebInspector.View.prototype; + +/** + * @constructor + * @extends {WebInspector.Panel} + * @param {string} id + * @param {string} label + * @param {string} iconURL + */ +WebInspector.ExtensionPanel = function(id, label, pageURL, iconURL) +{ + WebInspector.Panel.call(this, id); + this.setHideOnDetach(); + this._toolbarItemLabel = label; + this._statusBarItems = []; + + if (iconURL) { + this._addStyleRule(".toolbar-item." + id + " .toolbar-icon", "background-image: url(" + iconURL + ");"); + this._addStyleRule(".toolbar-small .toolbar-item." + id + " .toolbar-icon", "background-position-x: -32px;"); + } + new WebInspector.ExtensionView(id, this.element, pageURL, "extension panel"); +} + +WebInspector.ExtensionPanel.prototype = { + get toolbarItemLabel() + { + return this._toolbarItemLabel; + }, + + get defaultFocusedElement() + { + return this.sidebarTreeElement || this.element; + }, + + get statusBarItems() + { + return this._statusBarItems; + }, + + /** + * @param {Element} element + */ + addStatusBarItem: function(element) + { + this._statusBarItems.push(element); + }, + + searchCanceled: function(startingNewSearch) + { + WebInspector.extensionServer.notifySearchAction(this._id, "cancelSearch"); + WebInspector.Panel.prototype.searchCanceled.apply(this, arguments); + }, + + performSearch: function(query) + { + WebInspector.extensionServer.notifySearchAction(this._id, "performSearch", query); + WebInspector.Panel.prototype.performSearch.apply(this, arguments); + }, + + jumpToNextSearchResult: function() + { + WebInspector.extensionServer.notifySearchAction(this._id, "nextSearchResult"); + WebInspector.Panel.prototype.jumpToNextSearchResult.call(this); + }, + + jumpToPreviousSearchResult: function() + { + WebInspector.extensionServer.notifySearchAction(this._id, "previousSearchResult"); + WebInspector.Panel.prototype.jumpToPreviousSearchResult.call(this); + }, + + _addStyleRule: function(selector, body) + { + var style = document.createElement("style"); + style.textContent = selector + " { " + body + " }"; + document.head.appendChild(style); + } +} + +WebInspector.ExtensionPanel.prototype.__proto__ = WebInspector.Panel.prototype; + +/** + * @constructor + * @param {string} id + * @param {string} iconURL + * @param {string=} tooltip + * @param {boolean=} disabled + */ +WebInspector.ExtensionButton = function(id, iconURL, tooltip, disabled) +{ + this._id = id; + this.element = document.createElement("button"); + this.element.className = "status-bar-item extension"; + this.element.addEventListener("click", this._onClicked.bind(this), false); + this.update(iconURL, tooltip, disabled); +} + +WebInspector.ExtensionButton.prototype = { + /** + * @param {string} iconURL + * @param {string=} tooltip + * @param {boolean=} disabled + */ + update: function(iconURL, tooltip, disabled) + { + if (typeof iconURL === "string") + this.element.style.backgroundImage = "url(" + iconURL + ")"; + if (typeof tooltip === "string") + this.element.title = tooltip; + if (typeof disabled === "boolean") + this.element.disabled = disabled; + }, + + _onClicked: function() + { + WebInspector.extensionServer.notifyButtonClicked(this._id); + } +} + +/** + * @constructor + * @extends {WebInspector.SidebarPane} + * @param {string} title + * @param {string} id + */ +WebInspector.ExtensionSidebarPane = function(title, id) +{ + WebInspector.SidebarPane.call(this, title); + this._id = id; +} + +WebInspector.ExtensionSidebarPane.prototype = { + /** + * @param {Object} object + * @param {string} title + * @param {function(?string=)} callback + */ + setObject: function(object, title, callback) + { + this._createObjectPropertiesView(); + this._setObject(WebInspector.RemoteObject.fromLocalObject(object), title, callback); + }, + + /** + * @param {string} expression + * @param {string} title + * @param {function(?string=)} callback + */ + setExpression: function(expression, title, callback) + { + this._createObjectPropertiesView(); + RuntimeAgent.evaluate(expression, "extension-watch", true, undefined, undefined, undefined, this._onEvaluate.bind(this, title, callback)); + }, + + /** + * @param {string} url + */ + setPage: function(url) + { + if (this._objectPropertiesView) { + this._objectPropertiesView.detach(); + delete this._objectPropertiesView; + } + if (this._extensionView) + this._extensionView.detach(true); + + this._extensionView = new WebInspector.ExtensionView(this._id, this.bodyElement, url, "extension"); + }, + + /** + * @param {string} height + */ + setHeight: function(height) + { + this.bodyElement.style.height = height; + }, + + /** + * @param {string} title + * @param {function(?string=)} callback + * @param {?Protocol.Error} error + * @param {RuntimeAgent.RemoteObject} result + * @param {boolean=} wasThrown + */ + _onEvaluate: function(title, callback, error, result, wasThrown) + { + if (error) + callback(error.toString()); + else + this._setObject(WebInspector.RemoteObject.fromPayload(result), title, callback); + }, + + _createObjectPropertiesView: function() + { + if (this._objectPropertiesView) + return; + if (this._extensionView) { + this._extensionView.detach(true); + delete this._extensionView; + } + this._objectPropertiesView = new WebInspector.ExtensionNotifierView(this._id); + this._objectPropertiesView.show(this.bodyElement); + }, + + /** + * @param {Object} object + * @param {string} title + * @param {function(?string=)} callback + */ + _setObject: function(object, title, callback) + { + // This may only happen if setPage() was called while we were evaluating the expression. + if (!this._objectPropertiesView) { + callback("operation cancelled"); + return; + } + this._objectPropertiesView.element.removeChildren(); + var section = new WebInspector.ObjectPropertiesSection(object, title); + if (!title) + section.headerElement.addStyleClass("hidden"); + section.expanded = true; + section.editable = false; + this._objectPropertiesView.element.appendChild(section.element); + callback(); + } +} + +WebInspector.ExtensionSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype; +/* AuditsPanel.js */ + +/* + * Copyright (C) 2012 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. + */ + +/** + * @constructor + * @extends {WebInspector.Panel} + */ +WebInspector.AuditsPanel = function() +{ + WebInspector.Panel.call(this, "audits"); + this.registerRequiredCSS("panelEnablerView.css"); + this.registerRequiredCSS("auditsPanel.css"); + + this.createSplitViewWithSidebarTree(); + this.auditsTreeElement = new WebInspector.SidebarSectionTreeElement("", {}, true); + this.sidebarTree.appendChild(this.auditsTreeElement); + this.auditsTreeElement.listItemElement.addStyleClass("hidden"); + + this.auditsItemTreeElement = new WebInspector.AuditsSidebarTreeElement(); + this.auditsTreeElement.appendChild(this.auditsItemTreeElement); + + this.auditResultsTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("RESULTS"), {}, true); + this.sidebarTree.appendChild(this.auditResultsTreeElement); + this.auditResultsTreeElement.expand(); + + this.clearResultsButton = new WebInspector.StatusBarButton(WebInspector.UIString("Clear audit results."), "clear-status-bar-item"); + this.clearResultsButton.addEventListener("click", this._clearButtonClicked, this); + + this.viewsContainerElement = this.splitView.mainElement; + + this._constructCategories(); + + this._launcherView = new WebInspector.AuditLauncherView(this.initiateAudit.bind(this), this.terminateAudit.bind(this)); + for (var id in this.categoriesById) + this._launcherView.addCategory(this.categoriesById[id]); + + WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.OnLoad, this._didMainResourceLoad, this); +} + +WebInspector.AuditsPanel.prototype = { + get toolbarItemLabel() + { + return WebInspector.UIString("Audits"); + }, + + get statusBarItems() + { + return [this.clearResultsButton.element]; + }, + + get categoriesById() + { + return this._auditCategoriesById; + }, + + addCategory: function(category) + { + this.categoriesById[category.id] = category; + this._launcherView.addCategory(category); + }, + + getCategory: function(id) + { + return this.categoriesById[id]; + }, + + _constructCategories: function() + { + this._auditCategoriesById = {}; + for (var categoryCtorID in WebInspector.AuditCategories) { + var auditCategory = new WebInspector.AuditCategories[categoryCtorID](); + auditCategory._id = categoryCtorID; + this.categoriesById[categoryCtorID] = auditCategory; + } + }, + + _executeAudit: function(categories, resultCallback) + { + var resources = WebInspector.networkLog.resources; + + var rulesRemaining = 0; + for (var i = 0; i < categories.length; ++i) + rulesRemaining += categories[i].ruleCount; + + this._progressMonitor.setTotalWork(rulesRemaining); + + var results = []; + var mainResourceURL = WebInspector.inspectedPageURL; + + function ruleResultReadyCallback(categoryResult, ruleResult) + { + if (this._progressMonitor.canceled) + return; + + if (ruleResult && ruleResult.children) + categoryResult.addRuleResult(ruleResult); + + --rulesRemaining; + this._progressMonitor.worked(1); + + if (this._progressMonitor.done() && resultCallback) + resultCallback(mainResourceURL, results); + } + + if (this._progressMonitor.done()) { + resultCallback(mainResourceURL, results); + return; + } + + for (var i = 0; i < categories.length; ++i) { + var category = categories[i]; + var result = new WebInspector.AuditCategoryResult(category); + results.push(result); + category.run(resources, ruleResultReadyCallback.bind(this, result), this._progressMonitor); + } + }, + + _auditFinishedCallback: function(launcherCallback, mainResourceURL, results) + { + var children = this.auditResultsTreeElement.children; + var ordinal = 1; + for (var i = 0; i < children.length; ++i) { + if (children[i].mainResourceURL === mainResourceURL) + ordinal++; + } + + var resultTreeElement = new WebInspector.AuditResultSidebarTreeElement(results, mainResourceURL, ordinal); + this.auditResultsTreeElement.appendChild(resultTreeElement); + resultTreeElement.revealAndSelect(); + if (!this._progressMonitor.canceled && launcherCallback) + launcherCallback(); + }, + + initiateAudit: function(categoryIds, progressElement, runImmediately, launcherCallback) + { + if (!categoryIds || !categoryIds.length) + return; + + this._progressMonitor = new WebInspector.AuditProgressMonitor(progressElement); + + var categories = []; + for (var i = 0; i < categoryIds.length; ++i) + categories.push(this.categoriesById[categoryIds[i]]); + + function initiateAuditCallback(categories, launcherCallback) + { + this._executeAudit(categories, this._auditFinishedCallback.bind(this, launcherCallback)); + } + + if (runImmediately) + initiateAuditCallback.call(this, categories, launcherCallback); + else + this._reloadResources(initiateAuditCallback.bind(this, categories, launcherCallback)); + + WebInspector.userMetrics.AuditsStarted.record(); + }, + + terminateAudit: function(launcherCallback) + { + this._progressMonitor.canceled = true; + launcherCallback(); + }, + + _reloadResources: function(callback) + { + this._pageReloadCallback = callback; + PageAgent.reload(false); + }, + + _didMainResourceLoad: function() + { + if (this._pageReloadCallback) { + var callback = this._pageReloadCallback; + delete this._pageReloadCallback; + callback(); + } + }, + + showResults: function(categoryResults) + { + if (!categoryResults._resultView) + categoryResults._resultView = new WebInspector.AuditResultView(categoryResults); + + this.visibleView = categoryResults._resultView; + }, + + showLauncherView: function() + { + this.visibleView = this._launcherView; + }, + + get visibleView() + { + return this._visibleView; + }, + + set visibleView(x) + { + if (this._visibleView === x) + return; + + if (this._visibleView) + this._visibleView.detach(); + + this._visibleView = x; + + if (x) + x.show(this.viewsContainerElement); + }, + + wasShown: function() + { + WebInspector.Panel.prototype.wasShown.call(this); + if (!this._visibleView) + this.auditsItemTreeElement.select(); + }, + + _clearButtonClicked: function() + { + this.auditsItemTreeElement.revealAndSelect(); + this.auditResultsTreeElement.removeChildren(); + } +} + +WebInspector.AuditsPanel.prototype.__proto__ = WebInspector.Panel.prototype; + +/** + * @constructor + */ +WebInspector.AuditCategory = function(displayName) +{ + this._displayName = displayName; + this._rules = []; +} + +WebInspector.AuditCategory.prototype = { + get id() + { + // this._id value is injected at construction time. + return this._id; + }, + + get displayName() + { + return this._displayName; + }, + + get ruleCount() + { + this._ensureInitialized(); + return this._rules.length; + }, + + addRule: function(rule, severity) + { + rule.severity = severity; + this._rules.push(rule); + }, + + run: function(resources, callback, progressMonitor) + { + this._ensureInitialized(); + for (var i = 0; i < this._rules.length; ++i) + this._rules[i].run(resources, callback, progressMonitor); + }, + + _ensureInitialized: function() + { + if (!this._initialized) { + if ("initialize" in this) + this.initialize(); + this._initialized = true; + } + } +} + +/** + * @constructor + */ +WebInspector.AuditRule = function(id, displayName) +{ + this._id = id; + this._displayName = displayName; +} + +WebInspector.AuditRule.Severity = { + Info: "info", + Warning: "warning", + Severe: "severe" +} + +WebInspector.AuditRule.SeverityOrder = { + "info": 3, + "warning": 2, + "severe": 1 +} + +WebInspector.AuditRule.prototype = { + get id() + { + return this._id; + }, + + get displayName() + { + return this._displayName; + }, + + set severity(severity) + { + this._severity = severity; + }, + + run: function(resources, callback, progressMonitor) + { + if (progressMonitor.canceled) + return; + + var result = new WebInspector.AuditRuleResult(this.displayName); + result.severity = this._severity; + this.doRun(resources, result, callback, progressMonitor); + }, + + doRun: function(resources, result, callback, progressMonitor) + { + throw new Error("doRun() not implemented"); + } +} + +/** + * @constructor + */ +WebInspector.AuditCategoryResult = function(category) +{ + this.title = category.displayName; + this.ruleResults = []; +} + +WebInspector.AuditCategoryResult.prototype = { + addRuleResult: function(ruleResult) + { + this.ruleResults.push(ruleResult); + } +} + +/** + * @constructor + * @param {boolean=} expanded + * @param {string=} className + */ +WebInspector.AuditRuleResult = function(value, expanded, className) +{ + this.value = value; + this.className = className; + this.expanded = expanded; + this.violationCount = 0; + this._formatters = { + r: WebInspector.AuditRuleResult.linkifyDisplayName + }; + var standardFormatters = Object.keys(String.standardFormatters); + for (var i = 0; i < standardFormatters.length; ++i) + this._formatters[standardFormatters[i]] = String.standardFormatters[standardFormatters[i]]; +} + +WebInspector.AuditRuleResult.linkifyDisplayName = function(url) +{ + return WebInspector.linkifyURLAsNode(url, WebInspector.displayNameForURL(url)); +} + +WebInspector.AuditRuleResult.resourceDomain = function(domain) +{ + return domain || WebInspector.UIString("[empty domain]"); +} + +WebInspector.AuditRuleResult.prototype = { + /** + * @param {boolean=} expanded + * @param {string=} className + */ + addChild: function(value, expanded, className) + { + if (!this.children) + this.children = []; + var entry = new WebInspector.AuditRuleResult(value, expanded, className); + this.children.push(entry); + return entry; + }, + + addURL: function(url) + { + return this.addChild(WebInspector.AuditRuleResult.linkifyDisplayName(url)); + }, + + addURLs: function(urls) + { + for (var i = 0; i < urls.length; ++i) + this.addURL(urls[i]); + }, + + addSnippet: function(snippet) + { + return this.addChild(snippet, false, "source-code"); + }, + + /** + * @param {string} format + * @param {...*} vararg + */ + addFormatted: function(format, vararg) + { + var substitutions = Array.prototype.slice.call(arguments, 1); + var fragment = document.createDocumentFragment(); + + var formattedResult = String.format(format, substitutions, this._formatters, fragment, this._append).formattedResult; + if (formattedResult instanceof Node) + formattedResult.normalize(); + return this.addChild(formattedResult); + }, + + _append: function(a, b) + { + if (!(b instanceof Node)) + b = document.createTextNode(b); + a.appendChild(b); + return a; + } +} + +/** + * @constructor + * @param {Element} progressElement + */ +WebInspector.AuditProgressMonitor = function(progressElement) +{ + this._element = progressElement; + this.setTotalWork(WebInspector.AuditProgressMonitor.INDETERMINATE); +} + +WebInspector.AuditProgressMonitor.INDETERMINATE = -1; + +WebInspector.AuditProgressMonitor.prototype = { + setTotalWork: function(total) + { + if (this.canceled || this._total === total) + return; + this._total = total; + this._value = 0; + this._element.max = total; + if (total === WebInspector.AuditProgressMonitor.INDETERMINATE) + this._element.removeAttribute("value"); + else + this._element.value = 0; + }, + + worked: function(items) + { + if (this.canceled || this.indeterminate || this.done()) + return; + this._value += items; + if (this._value > this._total) + this._value = this._total; + this._element.value = this._value; + }, + + get indeterminate() + { + return this._total === WebInspector.AuditProgressMonitor.INDETERMINATE; + }, + + done: function() + { + return !this.indeterminate && (this.canceled || this._value === this._total); + }, + + get canceled() + { + return !!this._canceled; + }, + + set canceled(x) + { + if (this._canceled === x) + return; + if (x) + this.setTotalWork(WebInspector.AuditProgressMonitor.INDETERMINATE); + this._canceled = x; + } +} + +/** + * @constructor + * @extends {WebInspector.SidebarTreeElement} + */ +WebInspector.AuditsSidebarTreeElement = function() +{ + this.small = false; + + WebInspector.SidebarTreeElement.call(this, "audits-sidebar-tree-item", WebInspector.UIString("Audits"), "", null, false); +} + +WebInspector.AuditsSidebarTreeElement.prototype = { + onattach: function() + { + WebInspector.SidebarTreeElement.prototype.onattach.call(this); + }, + + onselect: function() + { + WebInspector.panels.audits.showLauncherView(); + }, + + get selectable() + { + return true; + }, + + refresh: function() + { + this.refreshTitles(); + } +} + +WebInspector.AuditsSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype; + +/** + * @constructor + * @extends {WebInspector.SidebarTreeElement} + */ +WebInspector.AuditResultSidebarTreeElement = function(results, mainResourceURL, ordinal) +{ + this.results = results; + this.mainResourceURL = mainResourceURL; + + WebInspector.SidebarTreeElement.call(this, "audit-result-sidebar-tree-item", String.sprintf("%s (%d)", mainResourceURL, ordinal), "", {}, false); +} + +WebInspector.AuditResultSidebarTreeElement.prototype = { + onselect: function() + { + WebInspector.panels.audits.showResults(this.results); + }, + + get selectable() + { + return true; + } +} + +WebInspector.AuditResultSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype; + +// Contributed audit rules should go into this namespace. +WebInspector.AuditRules = {}; + +// Contributed audit categories should go into this namespace. +WebInspector.AuditCategories = {}; +/* AuditResultView.js */ + +/* + * 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. + */ + +/** + * @constructor + * @extends {WebInspector.View} + */ +WebInspector.AuditResultView = function(categoryResults) +{ + WebInspector.View.call(this); + this.element.className = "audit-result-view"; + + function categorySorter(a, b) { + return (a.title || "").localeCompare(b.title || ""); + } + categoryResults.sort(categorySorter); + for (var i = 0; i < categoryResults.length; ++i) + this.element.appendChild(new WebInspector.AuditCategoryResultPane(categoryResults[i]).element); + + this.element.addEventListener("contextmenu", this._contextMenuEventFired.bind(this), true); +} + +WebInspector.AuditResultView.prototype = { + _contextMenuEventFired: function(event) + { + var contextMenu = new WebInspector.ContextMenu(); + if (WebInspector.populateHrefContextMenu(contextMenu, null, event)) + contextMenu.show(event); + } +} + +WebInspector.AuditResultView.prototype.__proto__ = WebInspector.View.prototype; + +/** + * @constructor + * @extends {WebInspector.SidebarPane} + */ +WebInspector.AuditCategoryResultPane = function(categoryResult) +{ + WebInspector.SidebarPane.call(this, categoryResult.title); + var treeOutlineElement = document.createElement("ol"); + this.bodyElement.addStyleClass("audit-result-tree"); + this.bodyElement.appendChild(treeOutlineElement); + + this._treeOutline = new TreeOutline(treeOutlineElement); + this._treeOutline.expandTreeElementsWhenArrowing = true; + + function ruleSorter(a, b) + { + var result = WebInspector.AuditRule.SeverityOrder[a.severity || 0] - WebInspector.AuditRule.SeverityOrder[b.severity || 0]; + if (!result) + result = (a.value || "").localeCompare(b.value || ""); + return result; + } + + categoryResult.ruleResults.sort(ruleSorter); + + for (var i = 0; i < categoryResult.ruleResults.length; ++i) { + var ruleResult = categoryResult.ruleResults[i]; + var treeElement = this._appendResult(this._treeOutline, ruleResult); + treeElement.listItemElement.addStyleClass("audit-result"); + + if (ruleResult.severity) { + var severityElement = document.createElement("img"); + severityElement.className = "severity-" + ruleResult.severity; + treeElement.listItemElement.appendChild(severityElement); + } + } + this.expand(); +} + +WebInspector.AuditCategoryResultPane.prototype = { + _appendResult: function(parentTreeElement, result) + { + var title = ""; + + if (typeof result.value === "string") { + title = result.value; + if (result.violationCount) + title = String.sprintf("%s (%d)", title, result.violationCount); + } + + var treeElement = new TreeElement(null, null, !!result.children); + treeElement.title = title; + parentTreeElement.appendChild(treeElement); + + if (result.className) + treeElement.listItemElement.addStyleClass(result.className); + if (typeof result.value !== "string") + treeElement.listItemElement.appendChild(WebInspector.applyFormatters(result.value)); + + if (result.children) { + for (var i = 0; i < result.children.length; ++i) + this._appendResult(treeElement, result.children[i]); + } + if (result.expanded) { + treeElement.listItemElement.removeStyleClass("parent"); + treeElement.listItemElement.addStyleClass("parent-expanded"); + treeElement.expand(); + } + return treeElement; + } +} + +WebInspector.AuditCategoryResultPane.prototype.__proto__ = WebInspector.SidebarPane.prototype; +/* AuditLauncherView.js */ + +/* + * Copyright (C) 2011 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. + */ + +/** + * @constructor + * @extends {WebInspector.View} + */ +WebInspector.AuditLauncherView = function(runnerCallback, stopCallback) +{ + WebInspector.View.call(this); + + this._runnerCallback = runnerCallback; + this._stopCallback = stopCallback; + this._categoryIdPrefix = "audit-category-item-"; + this._auditRunning = false; + + this.element.addStyleClass("audit-launcher-view"); + this.element.addStyleClass("panel-enabler-view"); + + this._contentElement = document.createElement("div"); + this._contentElement.className = "audit-launcher-view-content"; + this.element.appendChild(this._contentElement); + this._boundCategoryClickListener = this._categoryClicked.bind(this); + + this._resetResourceCount(); + + this._sortedCategories = []; + + this._headerElement = document.createElement("h1"); + this._headerElement.className = "no-audits"; + this._headerElement.textContent = WebInspector.UIString("No audits to run"); + this._contentElement.appendChild(this._headerElement); + + WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceStarted, this._onResourceStarted, this); + WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceFinished, this._onResourceFinished, this); +} + +WebInspector.AuditLauncherView.prototype = { + _resetResourceCount: function() + { + this._loadedResources = 0; + this._totalResources = 0; + }, + + _onResourceStarted: function(event) + { + var resource = event.data; + // Ignore long-living WebSockets for the sake of progress indicator, as we won't be waiting them anyway. + if (resource.type === WebInspector.Resource.Type.WebSocket) + return; + ++this._totalResources; + this._updateResourceProgress(); + }, + + _onResourceFinished: function(event) + { + var resource = event.data; + // See resorceStarted for details. + if (resource.type === WebInspector.Resource.Type.WebSocket) + return; + ++this._loadedResources; + this._updateResourceProgress(); + }, + + addCategory: function(category) + { + if (!this._sortedCategories.length) + this._createLauncherUI(); + + var categoryElement = this._createCategoryElement(category.displayName, category.id); + category._checkboxElement = categoryElement.firstChild; + if (this._selectAllCheckboxElement.checked) { + category._checkboxElement.checked = true; + ++this._currentCategoriesCount; + } + + function compareCategories(a, b) + { + var aTitle = a.displayName || ""; + var bTitle = b.displayName || ""; + return aTitle.localeCompare(bTitle); + } + var insertBefore = insertionIndexForObjectInListSortedByFunction(category, this._sortedCategories, compareCategories); + this._categoriesElement.insertBefore(categoryElement, this._categoriesElement.children[insertBefore]); + this._sortedCategories.splice(insertBefore, 0, category); + this._updateButton(); + }, + + _setAuditRunning: function(auditRunning) + { + if (this._auditRunning === auditRunning) + return; + this._auditRunning = auditRunning; + delete this._stopRequested; + this._updateButton(); + this._updateResourceProgress(); + }, + + _launchButtonClicked: function(event) + { + if (!this._auditRunning) { + var catIds = []; + for (var category = 0; category < this._sortedCategories.length; ++category) { + if (this._sortedCategories[category]._checkboxElement.checked) + catIds.push(this._sortedCategories[category].id); + } + + this._setAuditRunning(true); + this._runnerCallback(catIds, this._resourceProgressElement, this._auditPresentStateElement.checked, this._setAuditRunning.bind(this, false)); + } else { + this._stopRequested = true; + this._stopCallback(this._setAuditRunning.bind(this, false)); + this._updateButton(); + } + }, + + _selectAllClicked: function(checkCategories) + { + var childNodes = this._categoriesElement.childNodes; + for (var i = 0, length = childNodes.length; i < length; ++i) + childNodes[i].firstChild.checked = checkCategories; + this._currentCategoriesCount = checkCategories ? this._sortedCategories.length : 0; + this._updateButton(); + }, + + _categoryClicked: function(event) + { + this._currentCategoriesCount += event.target.checked ? 1 : -1; + this._selectAllCheckboxElement.checked = this._currentCategoriesCount === this._sortedCategories.length; + this._updateButton(); + }, + + _createCategoryElement: function(title, id) + { + var labelElement = document.createElement("label"); + labelElement.id = this._categoryIdPrefix + id; + + var element = document.createElement("input"); + element.type = "checkbox"; + if (id !== "") + element.addEventListener("click", this._boundCategoryClickListener, false); + labelElement.appendChild(element); + labelElement.appendChild(document.createTextNode(title)); + + return labelElement; + }, + + _createLauncherUI: function() + { + this._headerElement = document.createElement("h1"); + this._headerElement.textContent = WebInspector.UIString("Select audits to run"); + + for (var child = 0; child < this._contentElement.children.length; ++child) + this._contentElement.removeChild(this._contentElement.children[child]); + + this._contentElement.appendChild(this._headerElement); + + function handleSelectAllClick(event) + { + this._selectAllClicked(event.target.checked); + } + var categoryElement = this._createCategoryElement(WebInspector.UIString("Select All"), ""); + categoryElement.id = "audit-launcher-selectall"; + this._selectAllCheckboxElement = categoryElement.firstChild; + this._selectAllCheckboxElement.checked = true; + this._selectAllCheckboxElement.addEventListener("click", handleSelectAllClick.bind(this), false); + this._contentElement.appendChild(categoryElement); + + this._categoriesElement = this._contentElement.createChild("div", "audit-categories-container"); + this._currentCategoriesCount = 0; + + this._contentElement.createChild("div", "flexible-space"); + + this._buttonContainerElement = this._contentElement.createChild("div", "button-container"); + + var labelElement = this._buttonContainerElement.createChild("label"); + this._auditPresentStateElement = labelElement.createChild("input"); + this._auditPresentStateElement.name = "audit-mode"; + this._auditPresentStateElement.type = "radio"; + this._auditPresentStateElement.checked = true; + this._auditPresentStateLabelElement = document.createTextNode(WebInspector.UIString("Audit Present State")); + labelElement.appendChild(this._auditPresentStateLabelElement); + + labelElement = this._buttonContainerElement.createChild("label"); + this.auditReloadedStateElement = labelElement.createChild("input"); + this.auditReloadedStateElement.name = "audit-mode"; + this.auditReloadedStateElement.type = "radio"; + labelElement.appendChild(document.createTextNode("Reload Page and Audit on Load")); + + this._launchButton = this._buttonContainerElement.createChild("button"); + this._launchButton.textContent = WebInspector.UIString("Run"); + this._launchButton.addEventListener("click", this._launchButtonClicked.bind(this), false); + + this._resourceProgressContainer = this._buttonContainerElement.createChild("span", "resource-progress"); + this._resourceProgressElement = this._resourceProgressContainer.createChild("progress"); + this._resourceProgressContainer.appendChild(document.createTextNode(" ")); + this._resourceProgressTextElement = this._resourceProgressContainer.createChild("span"); + + + this._selectAllClicked(this._selectAllCheckboxElement.checked); + this._updateButton(); + this._updateResourceProgress(); + }, + + _updateResourceProgress: function() + { + if (!this._resourceProgressContainer) + return; + + if (!this._auditRunning || this._stopRequested) { + this._resetResourceCount(); + this._resourceProgressContainer.addStyleClass("hidden"); + } else + this._resourceProgressContainer.removeStyleClass("hidden"); + if (this._loadedResources) + this._resourceProgressTextElement.textContent = WebInspector.UIString("Loading (%d of %d)", this._loadedResources, this._totalResources); + else + this._resourceProgressTextElement.textContent = ""; + }, + + _updateButton: function() + { + this._launchButton.textContent = this._auditRunning ? WebInspector.UIString("Stop") : WebInspector.UIString("Run"); + this._launchButton.disabled = !this._currentCategoriesCount || (this._auditRunning && this._stopRequested); + } +} + +WebInspector.AuditLauncherView.prototype.__proto__ = WebInspector.View.prototype; +/* AuditRules.js */ + +/* + * 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. + * * 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. + */ + +WebInspector.AuditRules.IPAddressRegexp = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/; + +WebInspector.AuditRules.CacheableResponseCodes = +{ + 200: true, + 203: true, + 206: true, + 300: true, + 301: true, + 410: true, + + 304: true // Underlying resource is cacheable +} + +WebInspector.AuditRules.getDomainToResourcesMap = function(resources, types, needFullResources) +{ + var domainToResourcesMap = {}; + for (var i = 0, size = resources.length; i < size; ++i) { + var resource = resources[i]; + if (types && types.indexOf(resource.type) === -1) + continue; + var parsedURL = resource.url.asParsedURL(); + if (!parsedURL) + continue; + var domain = parsedURL.host; + var domainResources = domainToResourcesMap[domain]; + if (domainResources === undefined) { + domainResources = []; + domainToResourcesMap[domain] = domainResources; + } + domainResources.push(needFullResources ? resource : resource.url); + } + return domainToResourcesMap; +} + +/** + * @constructor + * @extends {WebInspector.AuditRule} + */ +WebInspector.AuditRules.GzipRule = function() +{ + WebInspector.AuditRule.call(this, "network-gzip", "Enable gzip compression"); +} + +WebInspector.AuditRules.GzipRule.prototype = { + doRun: function(resources, result, callback, progressMonitor) + { + var totalSavings = 0; + var compressedSize = 0; + var candidateSize = 0; + var summary = result.addChild("", true); + for (var i = 0, length = resources.length; i < length; ++i) { + var resource = resources[i]; + if (resource.statusCode === 304) + continue; // Do not test 304 Not Modified resources as their contents are always empty. + if (this._shouldCompress(resource)) { + var size = resource.resourceSize; + candidateSize += size; + if (this._isCompressed(resource)) { + compressedSize += size; + continue; + } + var savings = 2 * size / 3; + totalSavings += savings; + summary.addFormatted("%r could save ~%s", resource.url, Number.bytesToString(savings)); + result.violationCount++; + } + } + if (!totalSavings) + return callback(null); + summary.value = String.sprintf("Compressing the following resources with gzip could reduce their transfer size by about two thirds (~%s):", Number.bytesToString(totalSavings)); + callback(result); + }, + + _isCompressed: function(resource) + { + var encodingHeader = resource.responseHeaders["Content-Encoding"]; + if (!encodingHeader) + return false; + + return /\b(?:gzip|deflate)\b/.test(encodingHeader); + }, + + _shouldCompress: function(resource) + { + return WebInspector.Resource.Type.isTextType(resource.type) && resource.domain && resource.resourceSize !== undefined && resource.resourceSize > 150; + } +} + +WebInspector.AuditRules.GzipRule.prototype.__proto__ = WebInspector.AuditRule.prototype; + +/** + * @constructor + * @extends {WebInspector.AuditRule} + */ +WebInspector.AuditRules.CombineExternalResourcesRule = function(id, name, type, resourceTypeName, allowedPerDomain) +{ + WebInspector.AuditRule.call(this, id, name); + this._type = type; + this._resourceTypeName = resourceTypeName; + this._allowedPerDomain = allowedPerDomain; +} + +WebInspector.AuditRules.CombineExternalResourcesRule.prototype = { + doRun: function(resources, result, callback, progressMonitor) + { + var domainToResourcesMap = WebInspector.AuditRules.getDomainToResourcesMap(resources, [this._type], false); + var penalizedResourceCount = 0; + // TODO: refactor according to the chosen i18n approach + var summary = result.addChild("", true); + for (var domain in domainToResourcesMap) { + var domainResources = domainToResourcesMap[domain]; + var extraResourceCount = domainResources.length - this._allowedPerDomain; + if (extraResourceCount <= 0) + continue; + penalizedResourceCount += extraResourceCount - 1; + summary.addChild(String.sprintf("%d %s resources served from %s.", domainResources.length, this._resourceTypeName, WebInspector.AuditRuleResult.resourceDomain(domain))); + result.violationCount += domainResources.length; + } + if (!penalizedResourceCount) + return callback(null); + + summary.value = "There are multiple resources served from same domain. Consider combining them into as few files as possible."; + callback(result); + } +} + +WebInspector.AuditRules.CombineExternalResourcesRule.prototype.__proto__ = WebInspector.AuditRule.prototype; + +/** + * @constructor + * @extends {WebInspector.AuditRules.CombineExternalResourcesRule} + */ +WebInspector.AuditRules.CombineJsResourcesRule = function(allowedPerDomain) { + WebInspector.AuditRules.CombineExternalResourcesRule.call(this, "page-externaljs", "Combine external JavaScript", WebInspector.Resource.Type.Script, "JavaScript", allowedPerDomain); +} + +WebInspector.AuditRules.CombineJsResourcesRule.prototype.__proto__ = WebInspector.AuditRules.CombineExternalResourcesRule.prototype; + +/** + * @constructor + * @extends {WebInspector.AuditRules.CombineExternalResourcesRule} + */ +WebInspector.AuditRules.CombineCssResourcesRule = function(allowedPerDomain) { + WebInspector.AuditRules.CombineExternalResourcesRule.call(this, "page-externalcss", "Combine external CSS", WebInspector.Resource.Type.Stylesheet, "CSS", allowedPerDomain); +} + +WebInspector.AuditRules.CombineCssResourcesRule.prototype.__proto__ = WebInspector.AuditRules.CombineExternalResourcesRule.prototype; + +/** + * @constructor + * @extends {WebInspector.AuditRule} + */ +WebInspector.AuditRules.MinimizeDnsLookupsRule = function(hostCountThreshold) { + WebInspector.AuditRule.call(this, "network-minimizelookups", "Minimize DNS lookups"); + this._hostCountThreshold = hostCountThreshold; +} + +WebInspector.AuditRules.MinimizeDnsLookupsRule.prototype = { + doRun: function(resources, result, callback, progressMonitor) + { + var summary = result.addChild(""); + var domainToResourcesMap = WebInspector.AuditRules.getDomainToResourcesMap(resources, undefined, false); + for (var domain in domainToResourcesMap) { + if (domainToResourcesMap[domain].length > 1) + continue; + var parsedURL = domain.asParsedURL(); + if (!parsedURL) + continue; + if (!parsedURL.host.search(WebInspector.AuditRules.IPAddressRegexp)) + continue; // an IP address + summary.addSnippet(domain); + result.violationCount++; + } + if (!summary.children || summary.children.length <= this._hostCountThreshold) + return callback(null); + + summary.value = "The following domains only serve one resource each. If possible, avoid the extra DNS lookups by serving these resources from existing domains."; + callback(result); + } +} + +WebInspector.AuditRules.MinimizeDnsLookupsRule.prototype.__proto__ = WebInspector.AuditRule.prototype; + +/** + * @constructor + * @extends {WebInspector.AuditRule} + */ +WebInspector.AuditRules.ParallelizeDownloadRule = function(optimalHostnameCount, minRequestThreshold, minBalanceThreshold) +{ + WebInspector.AuditRule.call(this, "network-parallelizehosts", "Parallelize downloads across hostnames"); + this._optimalHostnameCount = optimalHostnameCount; + this._minRequestThreshold = minRequestThreshold; + this._minBalanceThreshold = minBalanceThreshold; +} + +WebInspector.AuditRules.ParallelizeDownloadRule.prototype = { + doRun: function(resources, result, callback, progressMonitor) + { + function hostSorter(a, b) + { + var aCount = domainToResourcesMap[a].length; + var bCount = domainToResourcesMap[b].length; + return (aCount < bCount) ? 1 : (aCount == bCount) ? 0 : -1; + } + + var domainToResourcesMap = WebInspector.AuditRules.getDomainToResourcesMap( + resources, + [WebInspector.Resource.Type.Stylesheet, WebInspector.Resource.Type.Image], + true); + + var hosts = []; + for (var url in domainToResourcesMap) + hosts.push(url); + + if (!hosts.length) + return callback(null); // no hosts (local file or something) + + hosts.sort(hostSorter); + + var optimalHostnameCount = this._optimalHostnameCount; + if (hosts.length > optimalHostnameCount) + hosts.splice(optimalHostnameCount); + + var busiestHostResourceCount = domainToResourcesMap[hosts[0]].length; + var resourceCountAboveThreshold = busiestHostResourceCount - this._minRequestThreshold; + if (resourceCountAboveThreshold <= 0) + return callback(null); + + var avgResourcesPerHost = 0; + for (var i = 0, size = hosts.length; i < size; ++i) + avgResourcesPerHost += domainToResourcesMap[hosts[i]].length; + + // Assume optimal parallelization. + avgResourcesPerHost /= optimalHostnameCount; + avgResourcesPerHost = Math.max(avgResourcesPerHost, 1); + + var pctAboveAvg = (resourceCountAboveThreshold / avgResourcesPerHost) - 1.0; + var minBalanceThreshold = this._minBalanceThreshold; + if (pctAboveAvg < minBalanceThreshold) + return callback(null); + + var resourcesOnBusiestHost = domainToResourcesMap[hosts[0]]; + var entry = result.addChild(String.sprintf("This page makes %d parallelizable requests to %s. Increase download parallelization by distributing the following requests across multiple hostnames.", busiestHostResourceCount, hosts[0]), true); + for (var i = 0; i < resourcesOnBusiestHost.length; ++i) + entry.addURL(resourcesOnBusiestHost[i].url); + + result.violationCount = resourcesOnBusiestHost.length; + callback(result); + } +} + +WebInspector.AuditRules.ParallelizeDownloadRule.prototype.__proto__ = WebInspector.AuditRule.prototype; + +/** + * The reported CSS rule size is incorrect (parsed != original in WebKit), + * so use percentages instead, which gives a better approximation. + * @constructor + * @extends {WebInspector.AuditRule} + */ +WebInspector.AuditRules.UnusedCssRule = function() +{ + WebInspector.AuditRule.call(this, "page-unusedcss", "Remove unused CSS rules"); +} + +WebInspector.AuditRules.UnusedCssRule.prototype = { + doRun: function(resources, result, callback, progressMonitor) + { + var self = this; + + function evalCallback(styleSheets) { + if (progressMonitor.canceled) + return; + + if (!styleSheets.length) + return callback(null); + + var pseudoSelectorRegexp = /:hover|:link|:active|:visited|:focus|:before|:after/; + var selectors = []; + var testedSelectors = {}; + for (var i = 0; i < styleSheets.length; ++i) { + var styleSheet = styleSheets[i]; + for (var curRule = 0; curRule < styleSheet.rules.length; ++curRule) { + var selectorText = styleSheet.rules[curRule].selectorText; + if (selectorText.match(pseudoSelectorRegexp) || testedSelectors[selectorText]) + continue; + selectors.push(selectorText); + testedSelectors[selectorText] = 1; + } + } + + function selectorsCallback(callback, styleSheets, testedSelectors, foundSelectors) + { + if (progressMonitor.canceled) + return; + + var inlineBlockOrdinal = 0; + var totalStylesheetSize = 0; + var totalUnusedStylesheetSize = 0; + var summary; + + for (var i = 0; i < styleSheets.length; ++i) { + var styleSheet = styleSheets[i]; + var stylesheetSize = 0; + var unusedStylesheetSize = 0; + var unusedRules = []; + for (var curRule = 0; curRule < styleSheet.rules.length; ++curRule) { + var rule = styleSheet.rules[curRule]; + // Exact computation whenever source ranges are available. + var textLength = (rule.selectorRange && rule.style.range && rule.style.range.end) ? rule.style.range.end - rule.selectorRange.start + 1 : 0; + if (!textLength && rule.style.cssText) + textLength = rule.style.cssText.length + rule.selectorText.length; + stylesheetSize += textLength; + if (!testedSelectors[rule.selectorText] || foundSelectors[rule.selectorText]) + continue; + unusedStylesheetSize += textLength; + unusedRules.push(rule.selectorText); + } + totalStylesheetSize += stylesheetSize; + totalUnusedStylesheetSize += unusedStylesheetSize; + + if (!unusedRules.length) + continue; + + var resource = WebInspector.resourceForURL(styleSheet.sourceURL); + var isInlineBlock = resource && resource.type == WebInspector.Resource.Type.Document; + var url = !isInlineBlock ? WebInspector.AuditRuleResult.linkifyDisplayName(styleSheet.sourceURL) : String.sprintf("Inline block #%d", ++inlineBlockOrdinal); + var pctUnused = Math.round(100 * unusedStylesheetSize / stylesheetSize); + if (!summary) + summary = result.addChild("", true); + var entry = summary.addFormatted("%s: %s (%d%%) is not used by the current page.", url, Number.bytesToString(unusedStylesheetSize), pctUnused); + + for (var j = 0; j < unusedRules.length; ++j) + entry.addSnippet(unusedRules[j]); + + result.violationCount += unusedRules.length; + } + + if (!totalUnusedStylesheetSize) + return callback(null); + + var totalUnusedPercent = Math.round(100 * totalUnusedStylesheetSize / totalStylesheetSize); + summary.value = String.sprintf("%s (%d%%) of CSS is not used by the current page.", Number.bytesToString(totalUnusedStylesheetSize), totalUnusedPercent); + + callback(result); + } + + var foundSelectors = {}; + function queryCallback(boundSelectorsCallback, selector, styleSheets, testedSelectors, nodeId) + { + if (nodeId) + foundSelectors[selector] = true; + if (boundSelectorsCallback) + boundSelectorsCallback(foundSelectors); + } + + function documentLoaded(selectors, document) { + for (var i = 0; i < selectors.length; ++i) { + if (progressMonitor.canceled) + return; + WebInspector.domAgent.querySelector(document.id, selectors[i], queryCallback.bind(null, i === selectors.length - 1 ? selectorsCallback.bind(null, callback, styleSheets, testedSelectors) : null, selectors[i], styleSheets, testedSelectors)); + } + } + + WebInspector.domAgent.requestDocument(documentLoaded.bind(null, selectors)); + } + + function styleSheetCallback(styleSheets, sourceURL, continuation, styleSheet) + { + if (progressMonitor.canceled) + return; + + if (styleSheet) { + styleSheet.sourceURL = sourceURL; + styleSheets.push(styleSheet); + } + if (continuation) + continuation(styleSheets); + } + + function allStylesCallback(error, styleSheetInfos) + { + if (progressMonitor.canceled) + return; + + if (error || !styleSheetInfos || !styleSheetInfos.length) + return evalCallback([]); + var styleSheets = []; + for (var i = 0; i < styleSheetInfos.length; ++i) { + var info = styleSheetInfos[i]; + WebInspector.CSSStyleSheet.createForId(info.styleSheetId, styleSheetCallback.bind(null, styleSheets, info.sourceURL, i == styleSheetInfos.length - 1 ? evalCallback : null)); + } + } + + CSSAgent.getAllStyleSheets(allStylesCallback); + } +} + +WebInspector.AuditRules.UnusedCssRule.prototype.__proto__ = WebInspector.AuditRule.prototype; + +/** + * @constructor + * @extends {WebInspector.AuditRule} + */ +WebInspector.AuditRules.CacheControlRule = function(id, name) +{ + WebInspector.AuditRule.call(this, id, name); +} + +WebInspector.AuditRules.CacheControlRule.MillisPerMonth = 1000 * 60 * 60 * 24 * 30; + +WebInspector.AuditRules.CacheControlRule.prototype = { + + doRun: function(resources, result, callback, progressMonitor) + { + var cacheableAndNonCacheableResources = this._cacheableAndNonCacheableResources(resources); + if (cacheableAndNonCacheableResources[0].length) + this.runChecks(cacheableAndNonCacheableResources[0], result); + this.handleNonCacheableResources(cacheableAndNonCacheableResources[1], result); + + callback(result); + }, + + handleNonCacheableResources: function(resources, result) + { + }, + + _cacheableAndNonCacheableResources: function(resources) + { + var processedResources = [[], []]; + for (var i = 0; i < resources.length; ++i) { + var resource = resources[i]; + if (!this.isCacheableResource(resource)) + continue; + if (this._isExplicitlyNonCacheable(resource)) + processedResources[1].push(resource); + else + processedResources[0].push(resource); + } + return processedResources; + }, + + execCheck: function(messageText, resourceCheckFunction, resources, result) + { + var resourceCount = resources.length; + var urls = []; + for (var i = 0; i < resourceCount; ++i) { + if (resourceCheckFunction.call(this, resources[i])) + urls.push(resources[i].url); + } + if (urls.length) { + var entry = result.addChild(messageText, true); + entry.addURLs(urls); + result.violationCount += urls.length; + } + }, + + freshnessLifetimeGreaterThan: function(resource, timeMs) + { + var dateHeader = this.responseHeader(resource, "Date"); + if (!dateHeader) + return false; + + var dateHeaderMs = Date.parse(dateHeader); + if (isNaN(dateHeaderMs)) + return false; + + var freshnessLifetimeMs; + var maxAgeMatch = this.responseHeaderMatch(resource, "Cache-Control", "max-age=(\\d+)"); + + if (maxAgeMatch) + freshnessLifetimeMs = (maxAgeMatch[1]) ? 1000 * maxAgeMatch[1] : 0; + else { + var expiresHeader = this.responseHeader(resource, "Expires"); + if (expiresHeader) { + var expDate = Date.parse(expiresHeader); + if (!isNaN(expDate)) + freshnessLifetimeMs = expDate - dateHeaderMs; + } + } + + return (isNaN(freshnessLifetimeMs)) ? false : freshnessLifetimeMs > timeMs; + }, + + responseHeader: function(resource, header) + { + return resource.responseHeaders[header]; + }, + + hasResponseHeader: function(resource, header) + { + return resource.responseHeaders[header] !== undefined; + }, + + isCompressible: function(resource) + { + return WebInspector.Resource.Type.isTextType(resource.type); + }, + + isPubliclyCacheable: function(resource) + { + if (this._isExplicitlyNonCacheable(resource)) + return false; + + if (this.responseHeaderMatch(resource, "Cache-Control", "public")) + return true; + + return resource.url.indexOf("?") == -1 && !this.responseHeaderMatch(resource, "Cache-Control", "private"); + }, + + responseHeaderMatch: function(resource, header, regexp) + { + return resource.responseHeaders[header] + ? resource.responseHeaders[header].match(new RegExp(regexp, "im")) + : undefined; + }, + + hasExplicitExpiration: function(resource) + { + return this.hasResponseHeader(resource, "Date") && + (this.hasResponseHeader(resource, "Expires") || this.responseHeaderMatch(resource, "Cache-Control", "max-age")); + }, + + _isExplicitlyNonCacheable: function(resource) + { + var hasExplicitExp = this.hasExplicitExpiration(resource); + return this.responseHeaderMatch(resource, "Cache-Control", "(no-cache|no-store|must-revalidate)") || + this.responseHeaderMatch(resource, "Pragma", "no-cache") || + (hasExplicitExp && !this.freshnessLifetimeGreaterThan(resource, 0)) || + (!hasExplicitExp && resource.url && resource.url.indexOf("?") >= 0) || + (!hasExplicitExp && !this.isCacheableResource(resource)); + }, + + isCacheableResource: function(resource) + { + return resource.statusCode !== undefined && WebInspector.AuditRules.CacheableResponseCodes[resource.statusCode]; + } +} + +WebInspector.AuditRules.CacheControlRule.prototype.__proto__ = WebInspector.AuditRule.prototype; + +/** + * @constructor + * @extends {WebInspector.AuditRules.CacheControlRule} + */ +WebInspector.AuditRules.BrowserCacheControlRule = function() +{ + WebInspector.AuditRules.CacheControlRule.call(this, "http-browsercache", "Leverage browser caching"); +} + +WebInspector.AuditRules.BrowserCacheControlRule.prototype = { + handleNonCacheableResources: function(resources, result) + { + if (resources.length) { + var entry = result.addChild("The following resources are explicitly non-cacheable. Consider making them cacheable if possible:", true); + result.violationCount += resources.length; + for (var i = 0; i < resources.length; ++i) + entry.addURL(resources[i].url); + } + }, + + runChecks: function(resources, result, callback) + { + this.execCheck("The following resources are missing a cache expiration. Resources that do not specify an expiration may not be cached by browsers:", + this._missingExpirationCheck, resources, result); + this.execCheck("The following resources specify a \"Vary\" header that disables caching in most versions of Internet Explorer:", + this._varyCheck, resources, result); + this.execCheck("The following cacheable resources have a short freshness lifetime:", + this._oneMonthExpirationCheck, resources, result); + + // Unable to implement the favicon check due to the WebKit limitations. + this.execCheck("To further improve cache hit rate, specify an expiration one year in the future for the following cacheable resources:", + this._oneYearExpirationCheck, resources, result); + }, + + _missingExpirationCheck: function(resource) + { + return this.isCacheableResource(resource) && !this.hasResponseHeader(resource, "Set-Cookie") && !this.hasExplicitExpiration(resource); + }, + + _varyCheck: function(resource) + { + var varyHeader = this.responseHeader(resource, "Vary"); + if (varyHeader) { + varyHeader = varyHeader.replace(/User-Agent/gi, ""); + varyHeader = varyHeader.replace(/Accept-Encoding/gi, ""); + varyHeader = varyHeader.replace(/[, ]*/g, ""); + } + return varyHeader && varyHeader.length && this.isCacheableResource(resource) && this.freshnessLifetimeGreaterThan(resource, 0); + }, + + _oneMonthExpirationCheck: function(resource) + { + return this.isCacheableResource(resource) && + !this.hasResponseHeader(resource, "Set-Cookie") && + !this.freshnessLifetimeGreaterThan(resource, WebInspector.AuditRules.CacheControlRule.MillisPerMonth) && + this.freshnessLifetimeGreaterThan(resource, 0); + }, + + _oneYearExpirationCheck: function(resource) + { + return this.isCacheableResource(resource) && + !this.hasResponseHeader(resource, "Set-Cookie") && + !this.freshnessLifetimeGreaterThan(resource, 11 * WebInspector.AuditRules.CacheControlRule.MillisPerMonth) && + this.freshnessLifetimeGreaterThan(resource, WebInspector.AuditRules.CacheControlRule.MillisPerMonth); + } +} + +WebInspector.AuditRules.BrowserCacheControlRule.prototype.__proto__ = WebInspector.AuditRules.CacheControlRule.prototype; + +/** + * @constructor + * @extends {WebInspector.AuditRules.CacheControlRule} + */ +WebInspector.AuditRules.ProxyCacheControlRule = function() { + WebInspector.AuditRules.CacheControlRule.call(this, "http-proxycache", "Leverage proxy caching"); +} + +WebInspector.AuditRules.ProxyCacheControlRule.prototype = { + runChecks: function(resources, result, callback) + { + this.execCheck("Resources with a \"?\" in the URL are not cached by most proxy caching servers:", + this._questionMarkCheck, resources, result); + this.execCheck("Consider adding a \"Cache-Control: public\" header to the following resources:", + this._publicCachingCheck, resources, result); + this.execCheck("The following publicly cacheable resources contain a Set-Cookie header. This security vulnerability can cause cookies to be shared by multiple users.", + this._setCookieCacheableCheck, resources, result); + }, + + _questionMarkCheck: function(resource) + { + return resource.url.indexOf("?") >= 0 && !this.hasResponseHeader(resource, "Set-Cookie") && this.isPubliclyCacheable(resource); + }, + + _publicCachingCheck: function(resource) + { + return this.isCacheableResource(resource) && + !this.isCompressible(resource) && + !this.responseHeaderMatch(resource, "Cache-Control", "public") && + !this.hasResponseHeader(resource, "Set-Cookie"); + }, + + _setCookieCacheableCheck: function(resource) + { + return this.hasResponseHeader(resource, "Set-Cookie") && this.isPubliclyCacheable(resource); + } +} + +WebInspector.AuditRules.ProxyCacheControlRule.prototype.__proto__ = WebInspector.AuditRules.CacheControlRule.prototype; + +/** + * @constructor + * @extends {WebInspector.AuditRule} + */ +WebInspector.AuditRules.ImageDimensionsRule = function() +{ + WebInspector.AuditRule.call(this, "page-imagedims", "Specify image dimensions"); +} + +WebInspector.AuditRules.ImageDimensionsRule.prototype = { + doRun: function(resources, result, callback, progressMonitor) + { + var urlToNoDimensionCount = {}; + + function doneCallback() + { + for (var url in urlToNoDimensionCount) { + var entry = entry || result.addChild("A width and height should be specified for all images in order to speed up page display. The following image(s) are missing a width and/or height:", true); + var format = "%r"; + if (urlToNoDimensionCount[url] > 1) + format += " (%d uses)"; + entry.addFormatted(format, url, urlToNoDimensionCount[url]); + result.violationCount++; + } + callback(entry ? result : null); + } + + function imageStylesReady(imageId, styles, isLastStyle, computedStyle) + { + if (progressMonitor.canceled) + return; + + const node = WebInspector.domAgent.nodeForId(imageId); + var src = node.getAttribute("src"); + if (!src.asParsedURL()) { + for (var frameOwnerCandidate = node; frameOwnerCandidate; frameOwnerCandidate = frameOwnerCandidate.parentNode) { + if (frameOwnerCandidate.documentURL) { + var completeSrc = WebInspector.completeURL(frameOwnerCandidate.documentURL, src); + break; + } + } + } + if (completeSrc) + src = completeSrc; + + if (computedStyle.getPropertyValue("position") === "absolute") { + if (isLastStyle) + doneCallback(); + return; + } + + var widthFound = "width" in styles.styleAttributes; + var heightFound = "height" in styles.styleAttributes; + + var inlineStyle = styles.inlineStyle; + if (inlineStyle) { + if (inlineStyle.getPropertyValue("width") !== "") + widthFound = true; + if (inlineStyle.getPropertyValue("height") !== "") + heightFound = true; + } + + for (var i = styles.matchedCSSRules.length - 1; i >= 0 && !(widthFound && heightFound); --i) { + var style = styles.matchedCSSRules[i].style; + if (style.getPropertyValue("width") !== "") + widthFound = true; + if (style.getPropertyValue("height") !== "") + heightFound = true; + } + + if (!widthFound || !heightFound) { + if (src in urlToNoDimensionCount) + ++urlToNoDimensionCount[src]; + else + urlToNoDimensionCount[src] = 1; + } + + if (isLastStyle) + doneCallback(); + } + + function getStyles(nodeIds) + { + if (progressMonitor.canceled) + return; + var targetResult = {}; + + function inlineCallback(inlineStyle, styleAttributes) + { + targetResult.inlineStyle = inlineStyle; + targetResult.styleAttributes = styleAttributes; + } + + function matchedCallback(result) + { + if (result) + targetResult.matchedCSSRules = result.matchedCSSRules; + } + + if (!nodeIds || !nodeIds.length) + doneCallback(); + + for (var i = 0; nodeIds && i < nodeIds.length; ++i) { + WebInspector.cssModel.getMatchedStylesAsync(nodeIds[i], undefined, false, false, matchedCallback); + WebInspector.cssModel.getInlineStylesAsync(nodeIds[i], inlineCallback); + WebInspector.cssModel.getComputedStyleAsync(nodeIds[i], undefined, imageStylesReady.bind(null, nodeIds[i], targetResult, i === nodeIds.length - 1)); + } + } + + function onDocumentAvailable(root) + { + if (progressMonitor.canceled) + return; + WebInspector.domAgent.querySelectorAll(root.id, "img[src]", getStyles); + } + + if (progressMonitor.canceled) + return; + WebInspector.domAgent.requestDocument(onDocumentAvailable); + } +} + +WebInspector.AuditRules.ImageDimensionsRule.prototype.__proto__ = WebInspector.AuditRule.prototype; + +/** + * @constructor + * @extends {WebInspector.AuditRule} + */ +WebInspector.AuditRules.CssInHeadRule = function() +{ + WebInspector.AuditRule.call(this, "page-cssinhead", "Put CSS in the document head"); +} + +WebInspector.AuditRules.CssInHeadRule.prototype = { + doRun: function(resources, result, callback, progressMonitor) + { + function evalCallback(evalResult) + { + if (progressMonitor.canceled) + return; + + if (!evalResult) + return callback(null); + + var summary = result.addChild(""); + + var outputMessages = []; + for (var url in evalResult) { + var urlViolations = evalResult[url]; + if (urlViolations[0]) { + result.addFormatted("%s style block(s) in the %r body should be moved to the document head.", urlViolations[0], url); + result.violationCount += urlViolations[0]; + } + for (var i = 0; i < urlViolations[1].length; ++i) + result.addFormatted("Link node %r should be moved to the document head in %r", urlViolations[1][i], url); + result.violationCount += urlViolations[1].length; + } + summary.value = String.sprintf("CSS in the document body adversely impacts rendering performance."); + callback(result); + } + + function externalStylesheetsReceived(root, inlineStyleNodeIds, nodeIds) + { + if (progressMonitor.canceled) + return; + + if (!nodeIds) + return; + var externalStylesheetNodeIds = nodeIds; + var result = null; + if (inlineStyleNodeIds.length || externalStylesheetNodeIds.length) { + var urlToViolationsArray = {}; + var externalStylesheetHrefs = []; + for (var j = 0; j < externalStylesheetNodeIds.length; ++j) { + var linkNode = WebInspector.domAgent.nodeForId(externalStylesheetNodeIds[j]); + var completeHref = WebInspector.completeURL(linkNode.ownerDocument.documentURL, linkNode.getAttribute("href")); + externalStylesheetHrefs.push(completeHref || ""); + } + urlToViolationsArray[root.documentURL] = [inlineStyleNodeIds.length, externalStylesheetHrefs]; + result = urlToViolationsArray; + } + evalCallback(result); + } + + function inlineStylesReceived(root, nodeIds) + { + if (progressMonitor.canceled) + return; + + if (!nodeIds) + return; + WebInspector.domAgent.querySelectorAll(root.id, "body link[rel~='stylesheet'][href]", externalStylesheetsReceived.bind(null, root, nodeIds)); + } + + function onDocumentAvailable(root) + { + if (progressMonitor.canceled) + return; + + WebInspector.domAgent.querySelectorAll(root.id, "body style", inlineStylesReceived.bind(null, root)); + } + + WebInspector.domAgent.requestDocument(onDocumentAvailable); + } +} + +WebInspector.AuditRules.CssInHeadRule.prototype.__proto__ = WebInspector.AuditRule.prototype; + +/** + * @constructor + * @extends {WebInspector.AuditRule} + */ +WebInspector.AuditRules.StylesScriptsOrderRule = function() +{ + WebInspector.AuditRule.call(this, "page-stylescriptorder", "Optimize the order of styles and scripts"); +} + +WebInspector.AuditRules.StylesScriptsOrderRule.prototype = { + doRun: function(resources, result, callback, progressMonitor) + { + function evalCallback(resultValue) + { + if (progressMonitor.canceled) + return; + + if (!resultValue) + return callback(null); + + var lateCssUrls = resultValue[0]; + var cssBeforeInlineCount = resultValue[1]; + + var entry = result.addChild("The following external CSS files were included after an external JavaScript file in the document head. To ensure CSS files are downloaded in parallel, always include external CSS before external JavaScript.", true); + entry.addURLs(lateCssUrls); + result.violationCount += lateCssUrls.length; + + if (cssBeforeInlineCount) { + result.addChild(String.sprintf(" %d inline script block%s found in the head between an external CSS file and another resource. To allow parallel downloading, move the inline script before the external CSS file, or after the next resource.", cssBeforeInlineCount, cssBeforeInlineCount > 1 ? "s were" : " was")); + result.violationCount += cssBeforeInlineCount; + } + callback(result); + } + + function cssBeforeInlineReceived(lateStyleIds, nodeIds) + { + if (progressMonitor.canceled) + return; + + if (!nodeIds) + return; + + var cssBeforeInlineCount = nodeIds.length; + var result = null; + if (lateStyleIds.length || cssBeforeInlineCount) { + var lateStyleUrls = []; + for (var i = 0; i < lateStyleIds.length; ++i) { + var lateStyleNode = WebInspector.domAgent.nodeForId(lateStyleIds[i]); + var completeHref = WebInspector.completeURL(lateStyleNode.ownerDocument.documentURL, lateStyleNode.getAttribute("href")); + lateStyleUrls.push(completeHref || ""); + } + result = [ lateStyleUrls, cssBeforeInlineCount ]; + } + + evalCallback(result); + } + + function lateStylesReceived(root, nodeIds) + { + if (progressMonitor.canceled) + return; + + if (!nodeIds) + return; + + WebInspector.domAgent.querySelectorAll(root.id, "head link[rel~='stylesheet'][href] ~ script:not([src])", cssBeforeInlineReceived.bind(null, nodeIds)); + } + + function onDocumentAvailable(root) + { + if (progressMonitor.canceled) + return; + + WebInspector.domAgent.querySelectorAll(root.id, "head script[src] ~ link[rel~='stylesheet'][href]", lateStylesReceived.bind(null, root)); + } + + WebInspector.domAgent.requestDocument(onDocumentAvailable); + } +} + +WebInspector.AuditRules.StylesScriptsOrderRule.prototype.__proto__ = WebInspector.AuditRule.prototype; + +/** + * @constructor + * @extends {WebInspector.AuditRule} + */ +WebInspector.AuditRules.CookieRuleBase = function(id, name) +{ + WebInspector.AuditRule.call(this, id, name); +} + +WebInspector.AuditRules.CookieRuleBase.prototype = { + doRun: function(resources, result, callback, progressMonitor) + { + var self = this; + function resultCallback(receivedCookies, isAdvanced) { + if (progressMonitor.canceled) + return; + + self.processCookies(isAdvanced ? receivedCookies : [], resources, result); + callback(result); + } + + WebInspector.Cookies.getCookiesAsync(resultCallback); + }, + + mapResourceCookies: function(resourcesByDomain, allCookies, callback) + { + for (var i = 0; i < allCookies.length; ++i) { + for (var resourceDomain in resourcesByDomain) { + if (WebInspector.Cookies.cookieDomainMatchesResourceDomain(allCookies[i].domain, resourceDomain)) + this._callbackForResourceCookiePairs(resourcesByDomain[resourceDomain], allCookies[i], callback); + } + } + }, + + _callbackForResourceCookiePairs: function(resources, cookie, callback) + { + if (!resources) + return; + for (var i = 0; i < resources.length; ++i) { + if (WebInspector.Cookies.cookieMatchesResourceURL(cookie, resources[i].url)) + callback(resources[i], cookie); + } + } +} + +WebInspector.AuditRules.CookieRuleBase.prototype.__proto__ = WebInspector.AuditRule.prototype; + +/** + * @constructor + * @extends {WebInspector.AuditRules.CookieRuleBase} + */ +WebInspector.AuditRules.CookieSizeRule = function(avgBytesThreshold) +{ + WebInspector.AuditRules.CookieRuleBase.call(this, "http-cookiesize", "Minimize cookie size"); + this._avgBytesThreshold = avgBytesThreshold; + this._maxBytesThreshold = 1000; +} + +WebInspector.AuditRules.CookieSizeRule.prototype = { + _average: function(cookieArray) + { + var total = 0; + for (var i = 0; i < cookieArray.length; ++i) + total += cookieArray[i].size; + return cookieArray.length ? Math.round(total / cookieArray.length) : 0; + }, + + _max: function(cookieArray) + { + var result = 0; + for (var i = 0; i < cookieArray.length; ++i) + result = Math.max(cookieArray[i].size, result); + return result; + }, + + processCookies: function(allCookies, resources, result) + { + function maxSizeSorter(a, b) + { + return b.maxCookieSize - a.maxCookieSize; + } + + function avgSizeSorter(a, b) + { + return b.avgCookieSize - a.avgCookieSize; + } + + var cookiesPerResourceDomain = {}; + + function collectorCallback(resource, cookie) + { + var cookies = cookiesPerResourceDomain[resource.domain]; + if (!cookies) { + cookies = []; + cookiesPerResourceDomain[resource.domain] = cookies; + } + cookies.push(cookie); + } + + if (!allCookies.length) + return; + + var sortedCookieSizes = []; + + var domainToResourcesMap = WebInspector.AuditRules.getDomainToResourcesMap(resources, + null, + true); + var matchingResourceData = {}; + this.mapResourceCookies(domainToResourcesMap, allCookies, collectorCallback.bind(this)); + + for (var resourceDomain in cookiesPerResourceDomain) { + var cookies = cookiesPerResourceDomain[resourceDomain]; + sortedCookieSizes.push({ + domain: resourceDomain, + avgCookieSize: this._average(cookies), + maxCookieSize: this._max(cookies) + }); + } + var avgAllCookiesSize = this._average(allCookies); + + var hugeCookieDomains = []; + sortedCookieSizes.sort(maxSizeSorter); + + for (var i = 0, len = sortedCookieSizes.length; i < len; ++i) { + var maxCookieSize = sortedCookieSizes[i].maxCookieSize; + if (maxCookieSize > this._maxBytesThreshold) + hugeCookieDomains.push(WebInspector.AuditRuleResult.resourceDomain(sortedCookieSizes[i].domain) + ": " + Number.bytesToString(maxCookieSize)); + } + + var bigAvgCookieDomains = []; + sortedCookieSizes.sort(avgSizeSorter); + for (var i = 0, len = sortedCookieSizes.length; i < len; ++i) { + var domain = sortedCookieSizes[i].domain; + var avgCookieSize = sortedCookieSizes[i].avgCookieSize; + if (avgCookieSize > this._avgBytesThreshold && avgCookieSize < this._maxBytesThreshold) + bigAvgCookieDomains.push(WebInspector.AuditRuleResult.resourceDomain(domain) + ": " + Number.bytesToString(avgCookieSize)); + } + result.addChild(String.sprintf("The average cookie size for all requests on this page is %s", Number.bytesToString(avgAllCookiesSize))); + + var message; + if (hugeCookieDomains.length) { + var entry = result.addChild("The following domains have a cookie size in excess of 1KB. This is harmful because requests with cookies larger than 1KB typically cannot fit into a single network packet.", true); + entry.addURLs(hugeCookieDomains); + result.violationCount += hugeCookieDomains.length; + } + + if (bigAvgCookieDomains.length) { + var entry = result.addChild(String.sprintf("The following domains have an average cookie size in excess of %d bytes. Reducing the size of cookies for these domains can reduce the time it takes to send requests.", this._avgBytesThreshold), true); + entry.addURLs(bigAvgCookieDomains); + result.violationCount += bigAvgCookieDomains.length; + } + } +} + +WebInspector.AuditRules.CookieSizeRule.prototype.__proto__ = WebInspector.AuditRules.CookieRuleBase.prototype; + +/** + * @constructor + * @extends {WebInspector.AuditRules.CookieRuleBase} + */ +WebInspector.AuditRules.StaticCookielessRule = function(minResources) +{ + WebInspector.AuditRules.CookieRuleBase.call(this, "http-staticcookieless", "Serve static content from a cookieless domain"); + this._minResources = minResources; +} + +WebInspector.AuditRules.StaticCookielessRule.prototype = { + processCookies: function(allCookies, resources, result) + { + var domainToResourcesMap = WebInspector.AuditRules.getDomainToResourcesMap(resources, + [WebInspector.Resource.Type.Stylesheet, + WebInspector.Resource.Type.Image], + true); + var totalStaticResources = 0; + for (var domain in domainToResourcesMap) + totalStaticResources += domainToResourcesMap[domain].length; + if (totalStaticResources < this._minResources) + return; + var matchingResourceData = {}; + this.mapResourceCookies(domainToResourcesMap, allCookies, this._collectorCallback.bind(this, matchingResourceData)); + + var badUrls = []; + var cookieBytes = 0; + for (var url in matchingResourceData) { + badUrls.push(url); + cookieBytes += matchingResourceData[url] + } + if (badUrls.length < this._minResources) + return; + + var entry = result.addChild(String.sprintf("%s of cookies were sent with the following static resources. Serve these static resources from a domain that does not set cookies:", Number.bytesToString(cookieBytes)), true); + entry.addURLs(badUrls); + result.violationCount = badUrls.length; + }, + + _collectorCallback: function(matchingResourceData, resource, cookie) + { + matchingResourceData[resource.url] = (matchingResourceData[resource.url] || 0) + cookie.size; + } +} + +WebInspector.AuditRules.StaticCookielessRule.prototype.__proto__ = WebInspector.AuditRules.CookieRuleBase.prototype; +/* AuditCategories.js */ + +/* + * 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. + * * 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. + */ + +/** + * @constructor + * @extends {WebInspector.AuditCategory} + */ +WebInspector.AuditCategories.PagePerformance = function() { + WebInspector.AuditCategory.call(this, WebInspector.AuditCategories.PagePerformance.AuditCategoryName); +} + +WebInspector.AuditCategories.PagePerformance.AuditCategoryName = "Web Page Performance"; + +WebInspector.AuditCategories.PagePerformance.prototype = { + initialize: function() + { + this.addRule(new WebInspector.AuditRules.UnusedCssRule(), WebInspector.AuditRule.Severity.Warning); + this.addRule(new WebInspector.AuditRules.CssInHeadRule(), WebInspector.AuditRule.Severity.Severe); + this.addRule(new WebInspector.AuditRules.StylesScriptsOrderRule(), WebInspector.AuditRule.Severity.Severe); + } +} + +WebInspector.AuditCategories.PagePerformance.prototype.__proto__ = WebInspector.AuditCategory.prototype; + +/** + * @constructor + * @extends {WebInspector.AuditCategory} + */ +WebInspector.AuditCategories.NetworkUtilization = function() { + WebInspector.AuditCategory.call(this, WebInspector.AuditCategories.NetworkUtilization.AuditCategoryName); +} + +WebInspector.AuditCategories.NetworkUtilization.AuditCategoryName = "Network Utilization"; + +WebInspector.AuditCategories.NetworkUtilization.prototype = { + initialize: function() + { + this.addRule(new WebInspector.AuditRules.GzipRule(), WebInspector.AuditRule.Severity.Severe); + this.addRule(new WebInspector.AuditRules.ImageDimensionsRule(), WebInspector.AuditRule.Severity.Warning); + this.addRule(new WebInspector.AuditRules.CookieSizeRule(400), WebInspector.AuditRule.Severity.Warning); + this.addRule(new WebInspector.AuditRules.StaticCookielessRule(5), WebInspector.AuditRule.Severity.Warning); + this.addRule(new WebInspector.AuditRules.CombineJsResourcesRule(2), WebInspector.AuditRule.Severity.Severe); + this.addRule(new WebInspector.AuditRules.CombineCssResourcesRule(2), WebInspector.AuditRule.Severity.Severe); + this.addRule(new WebInspector.AuditRules.MinimizeDnsLookupsRule(4), WebInspector.AuditRule.Severity.Warning); + this.addRule(new WebInspector.AuditRules.ParallelizeDownloadRule(4, 10, 0.5), WebInspector.AuditRule.Severity.Warning); + this.addRule(new WebInspector.AuditRules.BrowserCacheControlRule(), WebInspector.AuditRule.Severity.Severe); + this.addRule(new WebInspector.AuditRules.ProxyCacheControlRule(), WebInspector.AuditRule.Severity.Warning); + } +} + +WebInspector.AuditCategories.NetworkUtilization.prototype.__proto__ = WebInspector.AuditCategory.prototype; +/* AuditFormatters.js */ + +/* + * 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. + * * 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. + */ + +WebInspector.applyFormatters = function(value) +{ + var formatter; + var type = typeof value; + var args; + + switch (type) { + case "string": + case "boolean": + case "number": + formatter = WebInspector.AuditFormatters.text; + args = [ value.toString() ]; + break; + + case "object": + if (value instanceof Node) + return value; + if (value instanceof Array) { + formatter = WebInspector.AuditFormatters.concat; + args = value; + } else if (value.type && value.arguments) { + formatter = WebInspector.AuditFormatters[value.type]; + args = value.arguments; + } + } + if (!formatter) + throw "Invalid value or formatter: " + type + JSON.stringify(value); + + return formatter.apply(null, args); +} + +WebInspector.AuditFormatters = { + text: function(text) + { + return document.createTextNode(text); + }, + + snippet: function(snippetText) + { + var div = document.createElement("div"); + div.textContent = snippetText; + div.className = "source-code"; + return div; + }, + + concat: function() + { + var parent = document.createElement("span"); + for (var arg = 0; arg < arguments.length; ++arg) + parent.appendChild(WebInspector.applyFormatters(arguments[arg])); + return parent; + }, + + url: function(url, displayText, allowExternalNavigation) + { + var a = document.createElement("a"); + a.href = url; + a.title = url; + a.textContent = displayText || url; + if (allowExternalNavigation) + a.target = "_blank"; + return a; + }, + + resourceLink: function(url, line) + { + // FIXME: use WebInspector.DebuggerPresentationModel.Linkifier + return WebInspector.linkifyResourceAsNode(url, line, "console-message-url webkit-html-resource-link"); + } +}; +/* NetworkItemView.js */ + +/* + * 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. + * * 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. + */ + +/** + * @extends {WebInspector.TabbedPane} + * @constructor + */ +WebInspector.NetworkItemView = function(resource) +{ + WebInspector.TabbedPane.call(this); + + this.element.addStyleClass("network-item-view"); + + var headersView = new WebInspector.ResourceHeadersView(resource); + this.appendTab("headers", WebInspector.UIString("Headers"), headersView); + + var responseView = new WebInspector.ResourceResponseView(resource); + var previewView = new WebInspector.ResourcePreviewView(resource, responseView); + + this.appendTab("preview", WebInspector.UIString("Preview"), previewView); + this.appendTab("response", WebInspector.UIString("Response"), responseView); + + if (resource.requestCookies || resource.responseCookies) { + this._cookiesView = new WebInspector.ResourceCookiesView(resource); + this.appendTab("cookies", WebInspector.UIString("Cookies"), this._cookiesView); + } + + if (resource.timing) { + var timingView = new WebInspector.ResourceTimingView(resource); + this.appendTab("timing", WebInspector.UIString("Timing"), timingView); + } + + this.addEventListener(WebInspector.TabbedPane.EventTypes.TabSelected, this._tabSelected, this); +} + +WebInspector.NetworkItemView.prototype = { + wasShown: function() + { + WebInspector.TabbedPane.prototype.wasShown.call(this); + this._selectTab(); + }, + + /** + * @param {string=} tabId + */ + _selectTab: function(tabId) + { + if (!tabId) + tabId = WebInspector.settings.resourceViewTab.get(); + + if (!this.selectTab(tabId)) { + this._isInFallbackSelection = true; + this.selectTab("headers"); + delete this._isInFallbackSelection; + } + }, + + _tabSelected: function(event) + { + if (event.data.isUserGesture) + WebInspector.settings.resourceViewTab.set(event.data.tabId); + } +} + +WebInspector.NetworkItemView.prototype.__proto__ = WebInspector.TabbedPane.prototype; + +/** + * @extends {WebInspector.ResourceView} + * @constructor + */ +WebInspector.ResourceContentView = function(resource) +{ + WebInspector.ResourceView.call(this, resource); +} + +WebInspector.ResourceContentView.prototype = { + hasContent: function() + { + return true; + }, + + get innerView() + { + return this._innerView; + }, + + set innerView(innerView) + { + this._innerView = innerView; + }, + + wasShown: function() + { + this._ensureInnerViewShown(); + }, + + _ensureInnerViewShown: function() + { + if (this._innerViewShowRequested) + return; + this._innerViewShowRequested = true; + + function callback() + { + this._innerViewShowRequested = false; + this.contentLoaded(); + } + + this.resource.requestContent(callback.bind(this)); + }, + + contentLoaded: function() + { + // Should be implemented by subclasses. + }, + + canHighlightLine: function() + { + return this._innerView && this._innerView.canHighlightLine(); + }, + + highlightLine: function(line) + { + if (this.canHighlightLine()) + this._innerView.highlightLine(line); + } +} + +WebInspector.ResourceContentView.prototype.__proto__ = WebInspector.ResourceView.prototype; +/* EmptyView.js */ + +/* + * Copyright (C) 2011 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. + */ + +/** + * @constructor + * @extends {WebInspector.View} + */ +WebInspector.EmptyView = function(text) +{ + WebInspector.View.call(this); + this._text = text; +} + +WebInspector.EmptyView.prototype = { + wasShown: function() + { + this.element.className = "storage-empty-view"; + this.element.textContent = this._text; + }, + + set text(text) + { + this._text = text; + if (this.visible) + this.element.textContent = this._text; + }, +} + +WebInspector.EmptyView.prototype.__proto__ = WebInspector.View.prototype; +/* ResourceHeadersView.js */ + +/* + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) IBM Corp. 2009 All rights reserved. + * 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: + * + * 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. + */ + +/** + * @extends {WebInspector.View} + * @constructor + */ +WebInspector.ResourceHeadersView = function(resource) +{ + WebInspector.View.call(this); + this.registerRequiredCSS("resourceView.css"); + this.element.addStyleClass("resource-headers-view"); + + this._resource = resource; + + this._headersListElement = document.createElement("ol"); + this._headersListElement.className = "outline-disclosure"; + this.element.appendChild(this._headersListElement); + + this._headersTreeOutline = new TreeOutline(this._headersListElement); + this._headersTreeOutline.expandTreeElementsWhenArrowing = true; + + this._urlTreeElement = new TreeElement("", null, false); + this._urlTreeElement.selectable = false; + this._headersTreeOutline.appendChild(this._urlTreeElement); + + this._requestMethodTreeElement = new TreeElement("", null, false); + this._requestMethodTreeElement.selectable = false; + this._headersTreeOutline.appendChild(this._requestMethodTreeElement); + + this._statusCodeTreeElement = new TreeElement("", null, false); + this._statusCodeTreeElement.selectable = false; + this._headersTreeOutline.appendChild(this._statusCodeTreeElement); + + this._requestHeadersTreeElement = new TreeElement("", null, true); + this._requestHeadersTreeElement.expanded = true; + this._requestHeadersTreeElement.selectable = false; + this._headersTreeOutline.appendChild(this._requestHeadersTreeElement); + + this._decodeRequestParameters = true; + + this._showRequestHeadersText = false; + this._showResponseHeadersText = false; + + this._queryStringTreeElement = new TreeElement("", null, true); + this._queryStringTreeElement.expanded = true; + this._queryStringTreeElement.selectable = false; + this._queryStringTreeElement.hidden = true; + this._headersTreeOutline.appendChild(this._queryStringTreeElement); + + this._urlFragmentTreeElement = new TreeElement("", null, true); + this._urlFragmentTreeElement.expanded = true; + this._urlFragmentTreeElement.selectable = false; + this._urlFragmentTreeElement.hidden = true; + this._headersTreeOutline.appendChild(this._urlFragmentTreeElement); + + this._formDataTreeElement = new TreeElement("", null, true); + this._formDataTreeElement.expanded = true; + this._formDataTreeElement.selectable = false; + this._formDataTreeElement.hidden = true; + this._headersTreeOutline.appendChild(this._formDataTreeElement); + + this._requestPayloadTreeElement = new TreeElement(WebInspector.UIString("Request Payload"), null, true); + this._requestPayloadTreeElement.expanded = true; + this._requestPayloadTreeElement.selectable = false; + this._requestPayloadTreeElement.hidden = true; + this._headersTreeOutline.appendChild(this._requestPayloadTreeElement); + + this._responseHeadersTreeElement = new TreeElement("", null, true); + this._responseHeadersTreeElement.expanded = true; + this._responseHeadersTreeElement.selectable = false; + this._headersTreeOutline.appendChild(this._responseHeadersTreeElement); + + resource.addEventListener("requestHeaders changed", this._refreshRequestHeaders, this); + resource.addEventListener("responseHeaders changed", this._refreshResponseHeaders, this); + resource.addEventListener("finished", this._refreshHTTPInformation, this); + + this._refreshURL(); + this._refreshQueryString(); + this._refreshUrlFragment(); + this._refreshRequestHeaders(); + this._refreshResponseHeaders(); + this._refreshHTTPInformation(); +} + +WebInspector.ResourceHeadersView.prototype = { + /** + * @param {string} name + * @param {string} value + */ + _formatHeader: function(name, value) + { + var fragment = document.createDocumentFragment(); + fragment.createChild("div", "header-name").textContent = name + ":"; + fragment.createChild("div", "header-value source-code").textContent = value; + + return fragment; + }, + + /** + * @param {string} value + * @param {string} className + * @param {boolean} decodeParameters + */ + _formatParameter: function(value, className, decodeParameters) + { + var errorDecoding = false; + + if (decodeParameters) { + value = value.replace(/\+/g, " "); + if (value.indexOf("%") >= 0) { + try { + value = decodeURIComponent(value); + } catch(e) { + errorDecoding = true; + } + } + } + var div = document.createElement("div"); + div.className = className; + if (errorDecoding) + div.createChild("span", "error-message").textContent = WebInspector.UIString("(unable to decode value)"); + else + div.textContent = value; + return div; + }, + + _refreshURL: function() + { + this._urlTreeElement.title = this._formatHeader(WebInspector.UIString("Request URL"), this._resource.url); + }, + + _refreshQueryString: function() + { + var queryParameters = this._resource.queryParameters; + this._queryStringTreeElement.hidden = !queryParameters; + if (queryParameters) + this._refreshParms(WebInspector.UIString("Query String Parameters"), queryParameters, this._queryStringTreeElement); + }, + + _refreshUrlFragment: function() + { + var urlFragment = this._resource.urlFragment; + this._urlFragmentTreeElement.hidden = !urlFragment; + + if (!urlFragment) + return; + + var sectionTitle = WebInspector.UIString("URL fragment"); + + this._urlFragmentTreeElement.removeChildren(); + this._urlFragmentTreeElement.listItemElement.removeChildren(); + this._urlFragmentTreeElement.listItemElement.appendChild(document.createTextNode(sectionTitle)); + + var fragmentTreeElement = new TreeElement(null, null, false); + fragmentTreeElement.title = this._formatHeader("#", urlFragment); + fragmentTreeElement.selectable = false; + this._urlFragmentTreeElement.appendChild(fragmentTreeElement); + }, + + _refreshFormData: function() + { + this._formDataTreeElement.hidden = true; + this._requestPayloadTreeElement.hidden = true; + + var formData = this._resource.requestFormData; + if (!formData) + return; + + var formParameters = this._resource.formParameters; + if (formParameters) { + this._formDataTreeElement.hidden = false; + this._refreshParms(WebInspector.UIString("Form Data"), formParameters, this._formDataTreeElement); + } else { + this._requestPayloadTreeElement.hidden = false; + this._refreshRequestPayload(formData); + } + }, + + _refreshRequestPayload: function(formData) + { + this._requestPayloadTreeElement.removeChildren(); + + var title = document.createElement("div"); + title.className = "raw-form-data header-value source-code"; + title.textContent = formData; + + var parmTreeElement = new TreeElement(title, null, false); + parmTreeElement.selectable = false; + this._requestPayloadTreeElement.appendChild(parmTreeElement); + }, + + _refreshParms: function(title, parms, parmsTreeElement) + { + parmsTreeElement.removeChildren(); + + parmsTreeElement.listItemElement.removeChildren(); + parmsTreeElement.listItemElement.appendChild(document.createTextNode(title)); + + var headerCount = document.createElement("span"); + headerCount.addStyleClass("header-count"); + headerCount.textContent = WebInspector.UIString(" (%d)", parms.length); + parmsTreeElement.listItemElement.appendChild(headerCount); + + var toggleTitle = this._decodeRequestParameters ? WebInspector.UIString("view URL encoded") : WebInspector.UIString("view decoded"); + var toggleButton = this._createToggleButton(toggleTitle); + toggleButton.addEventListener("click", this._toggleURLdecoding.bind(this)); + parmsTreeElement.listItemElement.appendChild(toggleButton); + + + for (var i = 0; i < parms.length; ++i) { + var paramNameValue = document.createDocumentFragment(); + var name = this._formatParameter(parms[i].name + ":", "header-name", this._decodeRequestParameters); + var value = this._formatParameter(parms[i].value, "header-value source-code", this._decodeRequestParameters); + paramNameValue.appendChild(name); + paramNameValue.appendChild(value); + + var parmTreeElement = new TreeElement(paramNameValue, null, false); + parmTreeElement.selectable = false; + parmsTreeElement.appendChild(parmTreeElement); + } + }, + + _toggleURLdecoding: function(event) + { + this._decodeRequestParameters = !this._decodeRequestParameters; + this._refreshQueryString(); + this._refreshFormData(); + }, + + _getHeaderValue: function(headers, key) + { + var lowerKey = key.toLowerCase(); + for (var testKey in headers) { + if (testKey.toLowerCase() === lowerKey) + return headers[testKey]; + } + }, + + _refreshRequestHeaders: function() + { + var additionalRow = null; + if (typeof this._resource.webSocketRequestKey3 !== "undefined") + additionalRow = {header: "(Key3)", value: this._resource.webSocketRequestKey3}; + if (this._showRequestHeadersText) + this._refreshHeadersText(WebInspector.UIString("Request Headers"), this._resource.sortedRequestHeaders, this._resource.requestHeadersText, this._requestHeadersTreeElement); + else + this._refreshHeaders(WebInspector.UIString("Request Headers"), this._resource.sortedRequestHeaders, additionalRow, this._requestHeadersTreeElement); + + if (this._resource.requestHeadersText) { + var toggleButton = this._createHeadersToggleButton(this._showRequestHeadersText); + toggleButton.addEventListener("click", this._toggleRequestHeadersText.bind(this)); + this._requestHeadersTreeElement.listItemElement.appendChild(toggleButton); + } + + this._refreshFormData(); + }, + + _refreshResponseHeaders: function() + { + var additionalRow = null; + if (typeof this._resource.webSocketChallengeResponse !== "undefined") + additionalRow = {header: "(Challenge Response)", value: this._resource.webSocketChallengeResponse}; + if (this._showResponseHeadersText) + this._refreshHeadersText(WebInspector.UIString("Response Headers"), this._resource.sortedResponseHeaders, this._resource.responseHeadersText, this._responseHeadersTreeElement); + else + this._refreshHeaders(WebInspector.UIString("Response Headers"), this._resource.sortedResponseHeaders, additionalRow, this._responseHeadersTreeElement); + + if (this._resource.responseHeadersText) { + var toggleButton = this._createHeadersToggleButton(this._showResponseHeadersText); + toggleButton.addEventListener("click", this._toggleResponseHeadersText.bind(this)); + this._responseHeadersTreeElement.listItemElement.appendChild(toggleButton); + } + }, + + _refreshHTTPInformation: function() + { + var requestMethodElement = this._requestMethodTreeElement; + requestMethodElement.hidden = !this._resource.statusCode; + var statusCodeElement = this._statusCodeTreeElement; + statusCodeElement.hidden = !this._resource.statusCode; + + if (this._resource.statusCode) { + var statusImageSource = ""; + if (this._resource.statusCode < 300 || this._resource.statusCode === 304) + statusImageSource = "Images/successGreenDot.png"; + else if (this._resource.statusCode < 400) + statusImageSource = "Images/warningOrangeDot.png"; + else + statusImageSource = "Images/errorRedDot.png"; + + requestMethodElement.title = this._formatHeader(WebInspector.UIString("Request Method"), this._resource.requestMethod); + + var statusCodeFragment = document.createDocumentFragment(); + statusCodeFragment.createChild("div", "header-name").textContent = WebInspector.UIString("Status Code") + ":"; + + var statusCodeImage = statusCodeFragment.createChild("img", "resource-status-image"); + statusCodeImage.src = statusImageSource; + statusCodeImage.title = this._resource.statusCode + " " + this._resource.statusText; + var value = statusCodeFragment.createChild("div", "header-value source-code"); + value.textContent = this._resource.statusCode + " " + this._resource.statusText; + if (this._resource.cached) + value.createChild("span", "status-from-cache").textContent = " " + WebInspector.UIString("(from cache)"); + + statusCodeElement.title = statusCodeFragment; + } + }, + + _refreshHeadersTitle: function(title, headersTreeElement, headersLength) + { + headersTreeElement.listItemElement.removeChildren(); + headersTreeElement.listItemElement.appendChild(document.createTextNode(title)); + + var headerCount = document.createElement("span"); + headerCount.addStyleClass("header-count"); + headerCount.textContent = WebInspector.UIString(" (%d)", headersLength); + headersTreeElement.listItemElement.appendChild(headerCount); + }, + + _refreshHeaders: function(title, headers, additionalRow, headersTreeElement) + { + headersTreeElement.removeChildren(); + + var length = headers.length; + this._refreshHeadersTitle(title, headersTreeElement, length); + headersTreeElement.hidden = !length; + for (var i = 0; i < length; ++i) { + var headerTreeElement = new TreeElement(null, null, false); + headerTreeElement.title = this._formatHeader(headers[i].header, headers[i].value); + headerTreeElement.selectable = false; + headersTreeElement.appendChild(headerTreeElement); + } + + if (additionalRow) { + var headerTreeElement = new TreeElement(null, null, false); + headerTreeElement.title = this._formatHeader(additionalRow.header, additionalRow.value); + headerTreeElement.selectable = false; + headersTreeElement.appendChild(headerTreeElement); + } + }, + + _refreshHeadersText: function(title, headers, headersText, headersTreeElement) + { + headersTreeElement.removeChildren(); + + this._refreshHeadersTitle(title, headersTreeElement, headers.length); + var headerTreeElement = new TreeElement(null, null, false); + headerTreeElement.selectable = false; + headersTreeElement.appendChild(headerTreeElement); + + var headersTextElement = document.createElement("span"); + headersTextElement.addStyleClass("header-value"); + headersTextElement.addStyleClass("source-code"); + headersTextElement.textContent = String(headersText).trim(); + headerTreeElement.listItemElement.appendChild(headersTextElement); + }, + + _toggleRequestHeadersText: function(event) + { + this._showRequestHeadersText = !this._showRequestHeadersText; + this._refreshRequestHeaders(); + }, + + _toggleResponseHeadersText: function(event) + { + this._showResponseHeadersText = !this._showResponseHeadersText; + this._refreshResponseHeaders(); + }, + + _createToggleButton: function(title) + { + var button = document.createElement("span"); + button.addStyleClass("header-toggle"); + button.textContent = title; + return button; + }, + + _createHeadersToggleButton: function(isHeadersTextShown) + { + var toggleTitle = isHeadersTextShown ? WebInspector.UIString("view parsed") : WebInspector.UIString("view source"); + return this._createToggleButton(toggleTitle); + } +} + +WebInspector.ResourceHeadersView.prototype.__proto__ = WebInspector.View.prototype; +/* ResourceCookiesView.js */ + +/* + * Copyright (C) 2011 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. + */ + +/** + * @extends {WebInspector.View} + * @constructor + */ +WebInspector.ResourceCookiesView = function(resource) +{ + WebInspector.View.call(this); + this.element.addStyleClass("resource-cookies-view"); + + this._resource = resource; + + resource.addEventListener("requestHeaders changed", this._refreshCookies, this); + resource.addEventListener("responseHeaders changed", this._refreshCookies, this); +} + +WebInspector.ResourceCookiesView.prototype = { + wasShown: function() + { + if (!this._gotCookies) { + if (!this._emptyView) { + this._emptyView = new WebInspector.EmptyView(WebInspector.UIString("This request has no cookies.")); + this._emptyView.show(this.element); + } + return; + } + + if (!this._cookiesTable) + this._buildCookiesTable(); + }, + + get _gotCookies() + { + return !!(this._resource.requestCookies || this._resource.responseCookies); + }, + + _buildCookiesTable: function() + { + this.detachChildViews(); + + this._cookiesTable = new WebInspector.CookiesTable(null, true); + this._cookiesTable.addCookiesFolder(WebInspector.UIString("Request Cookies"), this._resource.requestCookies); + this._cookiesTable.addCookiesFolder(WebInspector.UIString("Response Cookies"), this._resource.responseCookies); + this._cookiesTable.show(this.element); + }, + + _refreshCookies: function() + { + delete this._cookiesTable; + if (!this._gotCookies || !this.isShowing()) + return; + this._buildCookiesTable(); + this._cookiesTable.updateWidths(); + } +} + +WebInspector.ResourceCookiesView.prototype.__proto__ = WebInspector.View.prototype; +/* ResourceTimingView.js */ + +/* + * 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. + * * 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. + */ + +/** + * @extends {WebInspector.View} + * @constructor + */ +WebInspector.ResourceTimingView = function(resource) +{ + WebInspector.View.call(this); + this.element.addStyleClass("resource-timing-view"); + + this._resource = resource; + + resource.addEventListener("timing changed", this._refresh, this); +} + +WebInspector.ResourceTimingView.prototype = { + wasShown: function() + { + if (!this._resource.timing) { + if (!this._emptyView) { + this._emptyView = new WebInspector.EmptyView(WebInspector.UIString("This request has no detailed timing info.")); + this._emptyView.show(this.element); + this.innerView = this._emptyView; + } + return; + } + + if (this._emptyView) { + this._emptyView.detach(); + delete this._emptyView; + } + + this._refresh(); + }, + + _refresh: function() + { + if (this._tableElement) + this._tableElement.parentElement.removeChild(this._tableElement); + + this._tableElement = WebInspector.ResourceTimingView.createTimingTable(this._resource); + this.element.appendChild(this._tableElement); + } +} + +WebInspector.ResourceTimingView.createTimingTable = function(resource) +{ + var tableElement = document.createElement("table"); + var rows = []; + + function addRow(title, className, start, end) + { + var row = {}; + row.title = title; + row.className = className; + row.start = start; + row.end = end; + rows.push(row); + } + + if (resource.timing.proxyStart !== -1) + addRow(WebInspector.UIString("Proxy"), "proxy", resource.timing.proxyStart, resource.timing.proxyEnd); + + if (resource.timing.dnsStart !== -1) + addRow(WebInspector.UIString("DNS Lookup"), "dns", resource.timing.dnsStart, resource.timing.dnsEnd); + + if (resource.timing.connectStart !== -1) { + if (resource.connectionReused) + addRow(WebInspector.UIString("Blocking"), "connecting", resource.timing.connectStart, resource.timing.connectEnd); + else { + var connectStart = resource.timing.connectStart; + // Connection includes DNS, subtract it here. + if (resource.timing.dnsStart !== -1) + connectStart += resource.timing.dnsEnd - resource.timing.dnsStart; + addRow(WebInspector.UIString("Connecting"), "connecting", connectStart, resource.timing.connectEnd); + } + } + + if (resource.timing.sslStart !== -1) + addRow(WebInspector.UIString("SSL"), "ssl", resource.timing.sslStart, resource.timing.sslEnd); + + var sendStart = resource.timing.sendStart; + if (resource.timing.sslStart !== -1) + sendStart += resource.timing.sslEnd - resource.timing.sslStart; + + addRow(WebInspector.UIString("Sending"), "sending", resource.timing.sendStart, resource.timing.sendEnd); + addRow(WebInspector.UIString("Waiting"), "waiting", resource.timing.sendEnd, resource.timing.receiveHeadersEnd); + addRow(WebInspector.UIString("Receiving"), "receiving", (resource.responseReceivedTime - resource.timing.requestTime) * 1000, (resource.endTime - resource.timing.requestTime) * 1000); + + const chartWidth = 200; + var total = (resource.endTime - resource.timing.requestTime) * 1000; + var scale = chartWidth / total; + + for (var i = 0; i < rows.length; ++i) { + var tr = document.createElement("tr"); + tableElement.appendChild(tr); + + var td = document.createElement("td"); + td.textContent = rows[i].title; + tr.appendChild(td); + + td = document.createElement("td"); + td.width = chartWidth + "px"; + + var row = document.createElement("div"); + row.className = "network-timing-row"; + td.appendChild(row); + + var bar = document.createElement("span"); + bar.className = "network-timing-bar " + rows[i].className; + bar.style.left = scale * rows[i].start + "px"; + bar.style.right = scale * (total - rows[i].end) + "px"; + bar.style.backgroundColor = rows[i].color; + bar.textContent = "\u200B"; // Important for 0-time items to have 0 width. + row.appendChild(bar); + + var title = document.createElement("span"); + title.className = "network-timing-bar-title"; + if (total - rows[i].end < rows[i].start) + title.style.right = (scale * (total - rows[i].end) + 3) + "px"; + else + title.style.left = (scale * rows[i].start + 3) + "px"; + title.textContent = Number.secondsToString((rows[i].end - rows[i].start) / 1000); + row.appendChild(title); + + tr.appendChild(td); + } + return tableElement; +} + +WebInspector.ResourceTimingView.prototype.__proto__ = WebInspector.View.prototype; +/* ResourceJSONView.js */ + +/* + * Copyright (C) 2011 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. + */ + +/** + * @extends {WebInspector.ResourceView} + * @constructor + */ +WebInspector.ResourceJSONView = function(resource, parsedJSON) +{ + WebInspector.ResourceView.call(this, resource); + this._parsedJSON = parsedJSON; + this.element.addStyleClass("json"); +} + +WebInspector.ResourceJSONView.parseJSON = function(text) +{ + var prefix = ""; + + // Trim while(1), for(;;), weird numbers, etc. We need JSON start. + var start = /[{[]/.exec(text); + if (start && start.index) { + prefix = text.substring(0, start.index); + text = text.substring(start.index); + } + + try { + return new WebInspector.ParsedJSON(JSON.parse(text), prefix, ""); + } catch (e) { + return; + } +} + +WebInspector.ResourceJSONView.parseJSONP = function(text) +{ + // Taking everything between first and last parentheses + var start = text.indexOf("("); + var end = text.lastIndexOf(")"); + if (start == -1 || end == -1 || end < start) + return; + + var prefix = text.substring(0, start + 1); + var suffix = text.substring(end); + text = text.substring(start + 1, end); + + try { + return new WebInspector.ParsedJSON(JSON.parse(text), prefix, suffix); + } catch (e) { + return; + } +} + +WebInspector.ResourceJSONView.prototype = { + hasContent: function() + { + return true; + }, + + wasShown: function() + { + this._initialize(); + }, + + _initialize: function() + { + if (this._initialized) + return; + this._initialized = true; + + var obj = WebInspector.RemoteObject.fromLocalObject(this._parsedJSON.data); + var title = this._parsedJSON.prefix + obj.description + this._parsedJSON.suffix; + var section = new WebInspector.ObjectPropertiesSection(obj, title); + section.expand(); + section.editable = false; + this.element.appendChild(section.element); + } +} + +WebInspector.ResourceJSONView.prototype.__proto__ = WebInspector.ResourceView.prototype; + +/** + * @constructor + */ +WebInspector.ParsedJSON = function(data, prefix, suffix) +{ + this.data = data; + this.prefix = prefix; + this.suffix = suffix; +} +/* ResourceHTMLView.js */ + +/* + * Copyright (C) 2011 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. + */ + +/** + * @constructor + * @extends {WebInspector.ResourceView} + */ +WebInspector.ResourceHTMLView = function(resource) +{ + WebInspector.ResourceView.call(this, resource); + this.element.addStyleClass("html"); +} + +WebInspector.ResourceHTMLView.prototype = { + hasContent: function() + { + return true; + }, + + wasShown: function() + { + this._createIFrame(); + }, + + willHide: function(parentElement) + { + this.element.removeChildren(); + }, + + _createIFrame: function() + { + // We need to create iframe again each time because contentDocument + // is deleted when iframe is removed from its parent. + this.element.removeChildren(); + var iframe = document.createElement("iframe"); + this.element.appendChild(iframe); + iframe.setAttribute("sandbox", ""); // Forbid to run JavaScript and set unique origin. + + iframe.contentDocument.body.innerHTML = this.resource.content; + } +} + +WebInspector.ResourceHTMLView.prototype.__proto__ = WebInspector.ResourceView.prototype; +/* ResourceResponseView.js */ + +/* + * Copyright (C) 2011 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. + */ + +/** + * @extends {WebInspector.ResourceContentView} + * @constructor + */ +WebInspector.ResourceResponseView = function(resource) +{ + WebInspector.ResourceContentView.call(this, resource); +} + +WebInspector.ResourceResponseView.prototype = { + get sourceView() + { + if (!this._sourceView && WebInspector.ResourceView.hasTextContent(this.resource)) + this._sourceView = new WebInspector.ResourceSourceFrame(this.resource); + return this._sourceView; + }, + + contentLoaded: function() + { + if (!this.resource.content || !this.sourceView) { + if (!this._emptyView) { + this._emptyView = new WebInspector.EmptyView(WebInspector.UIString("This request has no response data available.")); + this._emptyView.show(this.element); + this.innerView = this._emptyView; + } + } else { + if (this._emptyView) { + this._emptyView.detach(); + delete this._emptyView; + } + + this.sourceView.show(this.element); + this.innerView = this.sourceView; + } + } +} + +WebInspector.ResourceResponseView.prototype.__proto__ = WebInspector.ResourceContentView.prototype; +/* ResourcePreviewView.js */ + +/* + * Copyright (C) 2011 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. + */ + +/** + * @extends {WebInspector.ResourceContentView} + * @constructor + */ +WebInspector.ResourcePreviewView = function(resource, responseView) +{ + WebInspector.ResourceContentView.call(this, resource); + this._responseView = responseView; +} + +WebInspector.ResourcePreviewView.prototype = { + contentLoaded: function() + { + if (!this.resource.content) { + if (!this._emptyView) { + this._emptyView = this._createEmptyView(); + this._emptyView.show(this.element); + this.innerView = this._emptyView; + } + } else { + if (this._emptyView) { + this._emptyView.detach(); + delete this._emptyView; + } + + if (!this._previewView) + this._previewView = this._createPreviewView(); + this._previewView.show(this.element); + this.innerView = this._previewView; + } + }, + + _createEmptyView: function() + { + return new WebInspector.EmptyView(WebInspector.UIString("This request has no preview available.")); + }, + + _createPreviewView: function() + { + if (this.resource.hasErrorStatusCode() && this.resource.content) + return new WebInspector.ResourceHTMLView(this.resource); + + if (this.resource.category === WebInspector.resourceCategories.xhr && this.resource.content) { + var parsedJSON = WebInspector.ResourceJSONView.parseJSON(this.resource.content); + if (parsedJSON) + return new WebInspector.ResourceJSONView(this.resource, parsedJSON); + } + + if (this.resource.content && this.resource.category === WebInspector.resourceCategories.scripts && this.resource.mimeType === "application/json") { + var parsedJSONP = WebInspector.ResourceJSONView.parseJSONP(this.resource.content); + if (parsedJSONP) + return new WebInspector.ResourceJSONView(this.resource, parsedJSONP); + } + + if (this._responseView.sourceView) + return this._responseView.sourceView; + + if (this.resource.category === WebInspector.resourceCategories.other) + return this._createEmptyView(); + + return WebInspector.ResourceView.nonSourceViewForResource(this.resource); + } +} + +WebInspector.ResourcePreviewView.prototype.__proto__ = WebInspector.ResourceContentView.prototype; +/* ScriptFormatter.js */ + +/* + * Copyright (C) 2011 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. + */ + +/** + * @constructor + */ +WebInspector.ScriptFormatter = function() +{ + this._tasks = []; +} + +/** + * @param {Array.} lineEndings + * @param {DebuggerAgent.Location} location + * @return {number} + */ +WebInspector.ScriptFormatter.locationToPosition = function(lineEndings, location) +{ + var position = location.lineNumber ? lineEndings[location.lineNumber - 1] + 1 : 0; + return position + location.columnNumber; +} + +/** + * @param {Array.} lineEndings + * @param {number} position + * @return {DebuggerAgent.Location} + */ +WebInspector.ScriptFormatter.positionToLocation = function(lineEndings, position) +{ + var lineNumber = lineEndings.upperBound(position - 1); + if (!lineNumber) + var columnNumber = position; + else + var columnNumber = position - lineEndings[lineNumber - 1] - 1; + return new WebInspector.DebuggerModel.Location(lineNumber, columnNumber); +} + +WebInspector.ScriptFormatter.prototype = { + /** + * @param {string} mimeType + * @param {string} content + * @param {function(string, WebInspector.FormattedSourceMapping)} callback + */ + formatContent: function(mimeType, content, callback) + { + content = content.replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/^\uFEFF/, ''); + const method = "format"; + var parameters = { mimeType: mimeType, content: content, indentString: " " }; + this._tasks.push({ data: parameters, callback: callback }); + this._worker.postMessage({ method: method, params: parameters }); + }, + + /** + * @param {WebInspector.Event} event + */ + _didFormatContent: function(event) + { + var task = this._tasks.shift(); + var originalContent = task.data.content; + var formattedContent = event.data.content; + var mapping = event.data["mapping"]; + var sourceMapping = new WebInspector.FormattedSourceMapping(originalContent.lineEndings(), formattedContent.lineEndings(), mapping); + task.callback(formattedContent, sourceMapping); + }, + + /** + * @return {Worker} + */ + get _worker() + { + if (!this._cachedWorker) { + this._cachedWorker = new Worker("ScriptFormatterWorker.js"); + this._cachedWorker.onmessage = this._didFormatContent.bind(this); + } + return this._cachedWorker; + } +} + +/** + * @constructor + */ +WebInspector.FormatterMappingPayload = function() +{ + this.original = []; + this.formatted = []; +} + +/** + * @constructor + * @param {Array.} originalLineEndings + * @param {Array.} formattedLineEndings + * @param {WebInspector.FormatterMappingPayload} mapping + */ +WebInspector.FormattedSourceMapping = function(originalLineEndings, formattedLineEndings, mapping) +{ + this._originalLineEndings = originalLineEndings; + this._formattedLineEndings = formattedLineEndings; + this._mapping = mapping; +} + +WebInspector.FormattedSourceMapping.prototype = { + /** + * @param {DebuggerAgent.Location} location + * @return {DebuggerAgent.Location} + */ + originalToFormatted: function(location) + { + var originalPosition = WebInspector.ScriptFormatter.locationToPosition(this._originalLineEndings, location); + var formattedPosition = this._convertPosition(this._mapping.original, this._mapping.formatted, originalPosition); + return WebInspector.ScriptFormatter.positionToLocation(this._formattedLineEndings, formattedPosition); + }, + + /** + * @param {DebuggerAgent.Location} location + * @return {DebuggerAgent.Location} + */ + formattedToOriginal: function(location) + { + var formattedPosition = WebInspector.ScriptFormatter.locationToPosition(this._formattedLineEndings, location); + var originalPosition = this._convertPosition(this._mapping.formatted, this._mapping.original, formattedPosition); + return WebInspector.ScriptFormatter.positionToLocation(this._originalLineEndings, originalPosition); + }, + + /** + * @param {Array.} positions1 + * @param {Array.} positions2 + * @param {number} position + * @return {number} + */ + _convertPosition: function(positions1, positions2, position) + { + var index = positions1.upperBound(position) - 1; + var convertedPosition = positions2[index] + position - positions1[index]; + if (index < positions2.length - 1 && convertedPosition > positions2[index + 1]) + convertedPosition = positions2[index + 1]; + return convertedPosition; + } +} +/* DOMSyntaxHighlighter.js */ + +/* + * 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. + * * 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. + */ + +/** + * @constructor + */ +WebInspector.DOMSyntaxHighlighter = function(mimeType, stripExtraWhitespace) +{ + this._tokenizer = WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer(mimeType); + this._stripExtraWhitespace = stripExtraWhitespace; +} + +WebInspector.DOMSyntaxHighlighter.prototype = { + createSpan: function(content, className) + { + var span = document.createElement("span"); + span.className = "webkit-" + className; + if (this._stripExtraWhitespace) + content = content.replace(/^[\n\r]*/, "").replace(/\s*$/, ""); + span.appendChild(document.createTextNode(content)); + return span; + }, + + syntaxHighlightNode: function(node) + { + this._tokenizer.condition = this._tokenizer.createInitialCondition(); + var lines = node.textContent.split("\n"); + node.removeChildren(); + + for (var i = lines[0].length ? 0 : 1; i < lines.length; ++i) { + var line = lines[i]; + var plainTextStart = 0; + this._tokenizer.line = line; + var column = 0; + do { + var newColumn = this._tokenizer.nextToken(column); + var tokenType = this._tokenizer.tokenType; + if (tokenType) { + if (column > plainTextStart) { + var plainText = line.substring(plainTextStart, column); + node.appendChild(document.createTextNode(plainText)); + } + var token = line.substring(column, newColumn); + node.appendChild(this.createSpan(token, tokenType)); + plainTextStart = newColumn; + } + column = newColumn; + } while (column < line.length) + + if (plainTextStart < line.length) { + var plainText = line.substring(plainTextStart, line.length); + node.appendChild(document.createTextNode(plainText)); + } + if (i < lines.length - 1) + node.appendChild(document.createElement("br")); + } + } +} +/* TextEditorModel.js */ + +/* + * 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. + */ + +/** + * @constructor + */ +WebInspector.TextRange = function(startLine, startColumn, endLine, endColumn) +{ + this.startLine = startLine; + this.startColumn = startColumn; + this.endLine = endLine; + this.endColumn = endColumn; +} + +WebInspector.TextRange.prototype = { + isEmpty: function() + { + return this.startLine === this.endLine && this.startColumn === this.endColumn; + }, + + get linesCount() + { + return this.endLine - this.startLine; + }, + + collapseToEnd: function() + { + return new WebInspector.TextRange(this.endLine, this.endColumn, this.endLine, this.endColumn); + }, + + normalize: function() + { + if (this.startLine > this.endLine || (this.startLine === this.endLine && this.startColumn > this.endColumn)) + return new WebInspector.TextRange(this.endLine, this.endColumn, this.startLine, this.startColumn); + else + return this; + }, + + clone: function() + { + return new WebInspector.TextRange(this.startLine, this.startColumn, this.endLine, this.endColumn); + } +} + +/** + * @constructor + */ +WebInspector.TextEditorModel = function() +{ + this._lines = [""]; + this._attributes = []; + this._undoStack = []; + this._noPunctuationRegex = /[^ !%&()*+,-.:;<=>?\[\]\^{|}~]+/; + this._lineBreak = "\n"; +} + +WebInspector.TextEditorModel.Indent = { + TwoSpaces: " ", + FourSpaces: " ", + EightSpaces: " ", + TabCharacter: "\t" +} + +WebInspector.TextEditorModel.endsWithBracketRegex = /[{(\[]\s*$/; + +WebInspector.TextEditorModel.prototype = { + set changeListener(changeListener) + { + this._changeListener = changeListener; + }, + + get linesCount() + { + return this._lines.length; + }, + + get text() + { + return this._lines.join(this._lineBreak); + }, + + get lineBreak() + { + return this._lineBreak; + }, + + line: function(lineNumber) + { + if (lineNumber >= this._lines.length) + throw "Out of bounds:" + lineNumber; + return this._lines[lineNumber]; + }, + + lineLength: function(lineNumber) + { + return this._lines[lineNumber].length; + }, + + setText: function(range, text) + { + text = text || ""; + if (!range) { + range = new WebInspector.TextRange(0, 0, this._lines.length - 1, this._lines[this._lines.length - 1].length); + this._lineBreak = /\r\n/.test(text) ? "\r\n" : "\n"; + } + var command = this._pushUndoableCommand(range); + var newRange = this._innerSetText(range, text); + command.range = newRange.clone(); + + if (this._changeListener) + this._changeListener(range, newRange, command.text, text); + return newRange; + }, + + _innerSetText: function(range, text) + { + this._eraseRange(range); + if (text === "") + return new WebInspector.TextRange(range.startLine, range.startColumn, range.startLine, range.startColumn); + + var newLines = text.split(/\r?\n/); + + var prefix = this._lines[range.startLine].substring(0, range.startColumn); + var suffix = this._lines[range.startLine].substring(range.startColumn); + + var postCaret = prefix.length; + // Insert text. + if (newLines.length === 1) { + this._setLine(range.startLine, prefix + newLines[0] + suffix); + postCaret += newLines[0].length; + } else { + this._setLine(range.startLine, prefix + newLines[0]); + for (var i = 1; i < newLines.length; ++i) + this._insertLine(range.startLine + i, newLines[i]); + this._setLine(range.startLine + newLines.length - 1, newLines[newLines.length - 1] + suffix); + postCaret = newLines[newLines.length - 1].length; + } + return new WebInspector.TextRange(range.startLine, range.startColumn, + range.startLine + newLines.length - 1, postCaret); + }, + + _eraseRange: function(range) + { + if (range.isEmpty()) + return; + + var prefix = this._lines[range.startLine].substring(0, range.startColumn); + var suffix = this._lines[range.endLine].substring(range.endColumn); + + if (range.endLine > range.startLine) + this._removeLines(range.startLine + 1, range.endLine - range.startLine); + this._setLine(range.startLine, prefix + suffix); + }, + + _setLine: function(lineNumber, text) + { + this._lines[lineNumber] = text; + }, + + _removeLines: function(fromLine, count) + { + this._lines.splice(fromLine, count); + this._attributes.splice(fromLine, count); + }, + + _insertLine: function(lineNumber, text) + { + this._lines.splice(lineNumber, 0, text); + this._attributes.splice(lineNumber, 0, {}); + }, + + wordRange: function(lineNumber, column) + { + return new WebInspector.TextRange(lineNumber, this.wordStart(lineNumber, column, true), lineNumber, this.wordEnd(lineNumber, column, true)); + }, + + wordStart: function(lineNumber, column, gapless) + { + var line = this._lines[lineNumber]; + var prefix = line.substring(0, column).split("").reverse().join(""); + var prefixMatch = this._noPunctuationRegex.exec(prefix); + return prefixMatch && (!gapless || prefixMatch.index === 0) ? column - prefixMatch.index - prefixMatch[0].length : column; + }, + + wordEnd: function(lineNumber, column, gapless) + { + var line = this._lines[lineNumber]; + var suffix = line.substring(column); + var suffixMatch = this._noPunctuationRegex.exec(suffix); + return suffixMatch && (!gapless || suffixMatch.index === 0) ? column + suffixMatch.index + suffixMatch[0].length : column; + }, + + copyRange: function(range) + { + if (!range) + range = new WebInspector.TextRange(0, 0, this._lines.length - 1, this._lines[this._lines.length - 1].length); + + var clip = []; + if (range.startLine === range.endLine) { + clip.push(this._lines[range.startLine].substring(range.startColumn, range.endColumn)); + return clip.join(this._lineBreak); + } + clip.push(this._lines[range.startLine].substring(range.startColumn)); + for (var i = range.startLine + 1; i < range.endLine; ++i) + clip.push(this._lines[i]); + clip.push(this._lines[range.endLine].substring(0, range.endColumn)); + return clip.join(this._lineBreak); + }, + + setAttribute: function(line, name, value) + { + var attrs = this._attributes[line]; + if (!attrs) { + attrs = {}; + this._attributes[line] = attrs; + } + attrs[name] = value; + }, + + getAttribute: function(line, name) + { + var attrs = this._attributes[line]; + return attrs ? attrs[name] : null; + }, + + removeAttribute: function(line, name) + { + var attrs = this._attributes[line]; + if (attrs) + delete attrs[name]; + }, + + _pushUndoableCommand: function(range) + { + var command = { + text: this.copyRange(range), + startLine: range.startLine, + startColumn: range.startColumn, + endLine: range.startLine, + endColumn: range.startColumn + }; + if (this._inUndo) + this._redoStack.push(command); + else { + if (!this._inRedo) + this._redoStack = []; + this._undoStack.push(command); + } + return command; + }, + + undo: function(callback) + { + this._markRedoableState(); + + this._inUndo = true; + var range = this._doUndo(this._undoStack, callback); + delete this._inUndo; + + return range; + }, + + redo: function(callback) + { + this.markUndoableState(); + + this._inRedo = true; + var range = this._doUndo(this._redoStack, callback); + delete this._inRedo; + + return range; + }, + + _doUndo: function(stack, callback) + { + var range = null; + for (var i = stack.length - 1; i >= 0; --i) { + var command = stack[i]; + stack.length = i; + + range = this.setText(command.range, command.text); + if (callback) + callback(command.range, range); + if (i > 0 && stack[i - 1].explicit) + return range; + } + return range; + }, + + markUndoableState: function() + { + if (this._undoStack.length) + this._undoStack[this._undoStack.length - 1].explicit = true; + }, + + _markRedoableState: function() + { + if (this._redoStack.length) + this._redoStack[this._redoStack.length - 1].explicit = true; + }, + + resetUndoStack: function() + { + this._undoStack = []; + } +} + +WebInspector.settings.textEditorIndent = WebInspector.settings.createSetting("textEditorIndent", WebInspector.TextEditorModel.Indent.FourSpaces); +/* TextEditorHighlighter.js */ + +/* + * Copyright (C) 2009 Google 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 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. + */ + +/** + * @constructor + */ +WebInspector.TextEditorHighlighter = function(textModel, damageCallback) +{ + this._textModel = textModel; + this._tokenizer = WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer("text/html"); + this._damageCallback = damageCallback; + this._highlightChunkLimit = 1000; +} + +WebInspector.TextEditorHighlighter._MaxLineCount = 10000; + +WebInspector.TextEditorHighlighter.prototype = { + set mimeType(mimeType) + { + var tokenizer = WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer(mimeType); + if (tokenizer) + this._tokenizer = tokenizer; + }, + + set highlightChunkLimit(highlightChunkLimit) + { + this._highlightChunkLimit = highlightChunkLimit; + }, + + /** + * @param {boolean=} forceRun + */ + highlight: function(endLine, forceRun) + { + if (this._textModel.linesCount > WebInspector.TextEditorHighlighter._MaxLineCount) + return; + + // First check if we have work to do. + var state = this._textModel.getAttribute(endLine - 1, "highlight"); + if (state && state.postConditionStringified) { + // Last line is highlighted, just exit. + return; + } + + this._requestedEndLine = endLine; + + if (this._highlightTimer && !forceRun) { + // There is a timer scheduled, it will catch the new job based on the new endLine set. + return; + } + + // We will be highlighting. First rewind to the last highlighted line to gain proper highlighter context. + var startLine = endLine; + while (startLine > 0) { + state = this._textModel.getAttribute(startLine - 1, "highlight"); + if (state && state.postConditionStringified) + break; + startLine--; + } + + // Do small highlight synchronously. This will provide instant highlight on PageUp / PageDown, gentle scrolling. + this._highlightInChunks(startLine, endLine); + }, + + updateHighlight: function(startLine, endLine) + { + if (this._textModel.linesCount > WebInspector.TextEditorHighlighter._MaxLineCount) + return; + + // Start line was edited, we should highlight everything until endLine. + this._clearHighlightState(startLine); + + if (startLine) { + var state = this._textModel.getAttribute(startLine - 1, "highlight"); + if (!state || !state.postConditionStringified) { + // Highlighter did not reach this point yet, nothing to update. It will reach it on subsequent timer tick and do the job. + return false; + } + } + + var restored = this._highlightLines(startLine, endLine); + if (!restored) { + for (var i = this._lastHighlightedLine; i < this._textModel.linesCount; ++i) { + var state = this._textModel.getAttribute(i, "highlight"); + if (!state && i > endLine) + break; + this._textModel.setAttribute(i, "highlight-outdated", state); + this._textModel.removeAttribute(i, "highlight"); + } + + if (this._highlightTimer) { + clearTimeout(this._highlightTimer); + this._requestedEndLine = endLine; + this._highlightTimer = setTimeout(this._highlightInChunks.bind(this, this._lastHighlightedLine, this._requestedEndLine), 10); + } + } + return restored; + }, + + _highlightInChunks: function(startLine, endLine) + { + delete this._highlightTimer; + + // First we always check if we have work to do. Could be that user scrolled back and we can quit. + var state = this._textModel.getAttribute(this._requestedEndLine - 1, "highlight"); + if (state && state.postConditionStringified) + return; + + if (this._requestedEndLine !== endLine) { + // User keeps updating the job in between of our timer ticks. Just reschedule self, don't eat CPU (they must be scrolling). + this._highlightTimer = setTimeout(this._highlightInChunks.bind(this, startLine, this._requestedEndLine), 100); + return; + } + + // The textModel may have been already updated. + if (this._requestedEndLine > this._textModel.linesCount) + this._requestedEndLine = this._textModel.linesCount; + + this._highlightLines(startLine, this._requestedEndLine); + + // Schedule tail highlight if necessary. + if (this._lastHighlightedLine < this._requestedEndLine) + this._highlightTimer = setTimeout(this._highlightInChunks.bind(this, this._lastHighlightedLine, this._requestedEndLine), 10); + }, + + _highlightLines: function(startLine, endLine) + { + // Restore highlighter context taken from previous line. + var state = this._textModel.getAttribute(startLine - 1, "highlight"); + var postConditionStringified = state ? state.postConditionStringified : JSON.stringify(this._tokenizer.createInitialCondition()); + + var tokensCount = 0; + for (var lineNumber = startLine; lineNumber < endLine; ++lineNumber) { + state = this._selectHighlightState(lineNumber, postConditionStringified); + if (state.postConditionStringified) { + // This line is already highlighted. + postConditionStringified = state.postConditionStringified; + } else { + var lastHighlightedColumn = 0; + if (state.midConditionStringified) { + lastHighlightedColumn = state.lastHighlightedColumn; + postConditionStringified = state.midConditionStringified; + } + + var line = this._textModel.line(lineNumber); + this._tokenizer.line = line; + this._tokenizer.condition = JSON.parse(postConditionStringified); + + // Highlight line. + do { + var newColumn = this._tokenizer.nextToken(lastHighlightedColumn); + var tokenType = this._tokenizer.tokenType; + if (tokenType) + state[lastHighlightedColumn] = { length: newColumn - lastHighlightedColumn, tokenType: tokenType }; + lastHighlightedColumn = newColumn; + if (++tokensCount > this._highlightChunkLimit) + break; + } while (lastHighlightedColumn < line.length); + + postConditionStringified = JSON.stringify(this._tokenizer.condition); + + if (lastHighlightedColumn < line.length) { + // Too much work for single chunk - exit. + state.lastHighlightedColumn = lastHighlightedColumn; + state.midConditionStringified = postConditionStringified; + break; + } else { + delete state.lastHighlightedColumn; + delete state.midConditionStringified; + state.postConditionStringified = postConditionStringified; + } + } + + var nextLineState = this._textModel.getAttribute(lineNumber + 1, "highlight"); + if (nextLineState && nextLineState.preConditionStringified === state.postConditionStringified) { + // Following lines are up to date, no need re-highlight. + ++lineNumber; + this._damageCallback(startLine, lineNumber); + + // Advance the "pointer" to the last highlighted line within the given chunk. + for (; lineNumber < endLine; ++lineNumber) { + state = this._textModel.getAttribute(lineNumber, "highlight"); + if (!state || !state.postConditionStringified) + break; + } + this._lastHighlightedLine = lineNumber; + return true; + } + } + + this._damageCallback(startLine, lineNumber); + this._lastHighlightedLine = lineNumber; + return false; + }, + + _selectHighlightState: function(lineNumber, preConditionStringified) + { + var state = this._textModel.getAttribute(lineNumber, "highlight"); + if (state && state.preConditionStringified === preConditionStringified) + return state; + + var outdatedState = this._textModel.getAttribute(lineNumber, "highlight-outdated"); + if (outdatedState && outdatedState.preConditionStringified === preConditionStringified) { + // Swap states. + this._textModel.setAttribute(lineNumber, "highlight", outdatedState); + this._textModel.setAttribute(lineNumber, "highlight-outdated", state); + return outdatedState; + } + + if (state) + this._textModel.setAttribute(lineNumber, "highlight-outdated", state); + + state = {}; + state.preConditionStringified = preConditionStringified; + this._textModel.setAttribute(lineNumber, "highlight", state); + return state; + }, + + _clearHighlightState: function(lineNumber) + { + this._textModel.removeAttribute(lineNumber, "highlight"); + this._textModel.removeAttribute(lineNumber, "highlight-outdated"); + } +} +/* SourceTokenizer.js */ + +/* Generated by re2c 0.13.5 on Tue Jan 26 01:16:33 2010 */ +/* + * 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. + */ + +/** + * @constructor + */ +WebInspector.SourceTokenizer = function() +{ +} + +WebInspector.SourceTokenizer.prototype = { + set line(line) { + this._line = line; + }, + + set condition(condition) + { + this._condition = condition; + }, + + get condition() + { + return this._condition; + }, + + getLexCondition: function() + { + return this.condition.lexCondition; + }, + + setLexCondition: function(lexCondition) + { + this.condition.lexCondition = lexCondition; + }, + + _charAt: function(cursor) + { + return cursor < this._line.length ? this._line.charAt(cursor) : "\n"; + }, + + createInitialCondition: function() + { + }, + + nextToken: function(cursor) + { + } +} + +/** + * @constructor + */ +WebInspector.SourceTokenizer.Registry = function() { + this._tokenizers = {}; + this._tokenizerConstructors = { + "text/css": "SourceCSSTokenizer", + "text/html": "SourceHTMLTokenizer", + "text/javascript": "SourceJavaScriptTokenizer" + }; +} + +WebInspector.SourceTokenizer.Registry.getInstance = function() +{ + if (!WebInspector.SourceTokenizer.Registry._instance) + WebInspector.SourceTokenizer.Registry._instance = new WebInspector.SourceTokenizer.Registry(); + return WebInspector.SourceTokenizer.Registry._instance; +} + +WebInspector.SourceTokenizer.Registry.prototype = { + getTokenizer: function(mimeType) + { + if (!this._tokenizerConstructors[mimeType]) + return null; + var tokenizerClass = this._tokenizerConstructors[mimeType]; + var tokenizer = this._tokenizers[tokenizerClass]; + if (!tokenizer) { + tokenizer = new WebInspector[tokenizerClass](); + this._tokenizers[tokenizerClass] = tokenizer; + } + return tokenizer; + } +} +/* SourceCSSTokenizer.js */ + +/* Generated by re2c 0.13.5 on Mon Dec 19 17:28:29 2011 */ +/* + * 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. + */ + +// Generate js file as follows: + +/* +re2c -isc Source/WebCore/inspector/front-end/SourceCSSTokenizer.re2js \ + | sed 's|^yy\([^:]*\)*\:|case \1:|' \ + | sed 's|[*]cursor[+][+]|this._charAt(cursor++)|' \ + | sed 's|[[*][+][+]cursor|this._charAt(++cursor)|' \ + | sed 's|[*]cursor|this._charAt(cursor)|' \ + | sed 's|yych = \*\([^;]*\)|yych = this._charAt\1|' \ + | sed 's|{ gotoCase = \([^; continue; };]*\)|{ gotoCase = \1; continue; }|' \ + | sed 's|unsigned\ int|var|' \ + | sed 's|var\ yych|case 1: case 1: var yych|' > Source/WebCore/inspector/front-end/SourceCSSTokenizer.js +*/ + +/** + * @constructor + * @extends {WebInspector.SourceTokenizer} + */ +WebInspector.SourceCSSTokenizer = function() +{ + WebInspector.SourceTokenizer.call(this); + + this._propertyKeywords = WebInspector.CSSCompletions.cssNameCompletions.keySet(); + this._colorKeywords = WebInspector.CSSKeywordCompletions.colors(); + + this._valueKeywords = [ + "above", "absolute", "activeborder", "activecaption", "afar", "after-white-space", "ahead", "alias", "all", "all-scroll", + "alternate", "always", "amharic", "amharic-abegede", "antialiased", "appworkspace", "arabic-indic", "armenian", "asterisks", + "auto", "avoid", "background", "backwards", "baseline", "below", "bidi-override", "binary", "bengali", "blink", + "block", "block-axis", "bold", "bolder", "border", "border-box", "both", "bottom", "break-all", "break-word", "button", + "button-bevel", "buttonface", "buttonhighlight", "buttonshadow", "buttontext", "cambodian", "capitalize", "caps-lock-indicator", + "caption", "captiontext", "caret", "cell", "center", "checkbox", "circle", "cjk-earthly-branch", "cjk-heavenly-stem", "cjk-ideographic", + "clear", "clip", "close-quote", "col-resize", "collapse", "compact", "condensed", "contain", "content", "content-box", "context-menu", + "continuous", "copy", "cover", "crop", "cross", "crosshair", "currentcolor", "cursive", "dashed", "decimal", "decimal-leading-zero", "default", + "default-button", "destination-atop", "destination-in", "destination-out", "destination-over", "devanagari", "disc", "discard", "document", + "dot-dash", "dot-dot-dash", "dotted", "double", "down", "e-resize", "ease", "ease-in", "ease-in-out", "ease-out", "element", + "ellipsis", "embed", "end", "ethiopic", "ethiopic-abegede", "ethiopic-abegede-am-et", "ethiopic-abegede-gez", + "ethiopic-abegede-ti-er", "ethiopic-abegede-ti-et", "ethiopic-halehame-aa-er", "ethiopic-halehame-aa-et", + "ethiopic-halehame-am-et", "ethiopic-halehame-gez", "ethiopic-halehame-om-et", "ethiopic-halehame-sid-et", + "ethiopic-halehame-so-et", "ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et", "ethiopic-halehame-tig", "ew-resize", "expanded", + "extra-condensed", "extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "footnotes", "forwards", "from", "geometricPrecision", + "georgian", "graytext", "groove", "gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hebrew", "help", + "hidden", "hide", "higher", "highlight", "highlighttext", "hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "icon", "ignore", + "inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite", "infobackground", "infotext", "inherit", "initial", "inline", + "inline-axis", "inline-block", "inline-table", "inset", "inside", "intrinsic", "invert", "italic", "justify", "kannada", "katakana", + "katakana-iroha", "khmer", "landscape", "lao", "large", "larger", "left", "level", "lighter", "line-through", "linear", "lines", + "list-button", "list-item", "listbox", "listitem", "local", "logical", "loud", "lower", "lower-alpha", "lower-armenian", "lower-greek", + "lower-hexadecimal", "lower-latin", "lower-norwegian", "lower-roman", "lowercase", "ltr", "malayalam", "match", "media-controls-background", + "media-current-time-display", "media-fullscreen-button", "media-mute-button", "media-play-button", "media-return-to-realtime-button", + "media-rewind-button", "media-seek-back-button", "media-seek-forward-button", "media-slider", "media-sliderthumb", "media-time-remaining-display", + "media-volume-slider", "media-volume-slider-container", "media-volume-sliderthumb", "medium", "menu", "menulist", "menulist-button", + "menulist-text", "menulist-textfield", "menutext", "message-box", "middle", "min-intrinsic", "mix", "mongolian", "monospace", "move", "multiple", + "myanmar", "n-resize", "narrower", "navy", "ne-resize", "nesw-resize", "no-close-quote", "no-drop", "no-open-quote", "no-repeat", "none", + "normal", "not-allowed", "nowrap", "ns-resize", "nw-resize", "nwse-resize", "oblique", "octal", "open-quote", "optimizeLegibility", + "optimizeSpeed", "oriya", "oromo", "outset", "outside", "overlay", "overline", "padding", "padding-box", "painted", "paused", + "persian", "plus-darker", "plus-lighter", "pointer", "portrait", "pre", "pre-line", "pre-wrap", "preserve-3d", "progress", + "push-button", "radio", "read-only", "read-write", "read-write-plaintext-only", "relative", "repeat", "repeat-x", + "repeat-y", "reset", "reverse", "rgb", "rgba", "ridge", "right", "round", "row-resize", "rtl", "run-in", "running", "s-resize", "sans-serif", + "scroll", "scrollbar", "se-resize", "searchfield", "searchfield-cancel-button", "searchfield-decoration", "searchfield-results-button", + "searchfield-results-decoration", "semi-condensed", "semi-expanded", "separate", "serif", "show", "sidama", "single", + "skip-white-space", "slide", "slider-horizontal", "slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow", + "small", "small-caps", "small-caption", "smaller", "solid", "somali", "source-atop", "source-in", "source-out", "source-over", + "space", "square", "square-button", "start", "static", "status-bar", "stretch", "stroke", "sub", "subpixel-antialiased", "super", + "sw-resize", "table", "table-caption", "table-cell", "table-column", "table-column-group", "table-footer-group", "table-header-group", + "table-row", "table-row-group", "telugu", "text", "text-bottom", "text-top", "textarea", "textfield", "thai", "thick", "thin", + "threeddarkshadow", "threedface", "threedhighlight", "threedlightshadow", "threedshadow", "tibetan", "tigre", "tigrinya-er", "tigrinya-er-abegede", + "tigrinya-et", "tigrinya-et-abegede", "to", "top", "transparent", "ultra-condensed", "ultra-expanded", "underline", "up", "upper-alpha", "upper-armenian", + "upper-greek", "upper-hexadecimal", "upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url", "vertical", "vertical-text", "visible", + "visibleFill", "visiblePainted", "visibleStroke", "visual", "w-resize", "wait", "wave", "white", "wider", "window", "windowframe", "windowtext", + "x-large", "x-small", "xor", "xx-large", "xx-small", "yellow", "-wap-marquee", "-webkit-activelink", "-webkit-auto", "-webkit-baseline-middle", + "-webkit-body", "-webkit-box", "-webkit-center", "-webkit-control", "-webkit-focus-ring-color", "-webkit-grab", "-webkit-grabbing", + "-webkit-gradient", "-webkit-inline-box", "-webkit-left", "-webkit-link", "-webkit-marquee", "-webkit-mini-control", "-webkit-nowrap", "-webkit-pictograph", + "-webkit-right", "-webkit-small-control", "-webkit-text", "-webkit-xxx-large", "-webkit-zoom-in", "-webkit-zoom-out", + ].keySet(); + + this._mediaTypes = ["all", "aural", "braille", "embossed", "handheld", "import", "print", "projection", "screen", "tty", "tv"].keySet(); + + this._lexConditions = { + INITIAL: 0, + COMMENT: 1, + DSTRING: 2, + SSTRING: 3 + }; + + this._parseConditions = { + INITIAL: 0, + PROPERTY: 1, + PROPERTY_VALUE: 2, + AT_RULE: 3, + AT_MEDIA_RULE: 4 + }; + + this.case_INITIAL = 1000; + this.case_COMMENT = 1002; + this.case_DSTRING = 1003; + this.case_SSTRING = 1004; + + this.condition = this.createInitialCondition(); +} + +WebInspector.SourceCSSTokenizer.prototype = { + createInitialCondition: function() + { + return { lexCondition: this._lexConditions.INITIAL, parseCondition: this._parseConditions.INITIAL }; + }, + + /** + * @param {boolean=} stringEnds + */ + _stringToken: function(cursor, stringEnds) + { + if (this._isPropertyValue()) + this.tokenType = "css-string"; + else + this.tokenType = null; + return cursor; + }, + + _isPropertyValue: function() + { + return this._condition.parseCondition === this._parseConditions.PROPERTY_VALUE || this._condition.parseCondition === this._parseConditions.AT_RULE; + }, + + nextToken: function(cursor) + { + var cursorOnEnter = cursor; + var gotoCase = 1; + var YYMARKER; + while (1) { + switch (gotoCase) + // Following comment is replaced with generated state machine. + + { + case 1: var yych; + var yyaccept = 0; + if (this.getLexCondition() < 2) { + if (this.getLexCondition() < 1) { + { gotoCase = this.case_INITIAL; continue; }; + } else { + { gotoCase = this.case_COMMENT; continue; }; + } + } else { + if (this.getLexCondition() < 3) { + { gotoCase = this.case_DSTRING; continue; }; + } else { + { gotoCase = this.case_SSTRING; continue; }; + } + } +/* *********************************** */ +case this.case_COMMENT: + + yych = this._charAt(cursor); + if (yych <= '\f') { + if (yych == '\n') { gotoCase = 4; continue; }; + { gotoCase = 3; continue; }; + } else { + if (yych <= '\r') { gotoCase = 4; continue; }; + if (yych == '*') { gotoCase = 6; continue; }; + { gotoCase = 3; continue; }; + } +case 2: + { this.tokenType = "css-comment"; return cursor; } +case 3: + yyaccept = 0; + yych = this._charAt(YYMARKER = ++cursor); + { gotoCase = 12; continue; }; +case 4: + ++cursor; + { this.tokenType = null; return cursor; } +case 6: + yyaccept = 1; + yych = this._charAt(YYMARKER = ++cursor); + if (yych == '*') { gotoCase = 9; continue; }; + if (yych != '/') { gotoCase = 11; continue; }; +case 7: + ++cursor; + this.setLexCondition(this._lexConditions.INITIAL); + { this.tokenType = "css-comment"; return cursor; } +case 9: + ++cursor; + yych = this._charAt(cursor); + if (yych == '*') { gotoCase = 9; continue; }; + if (yych == '/') { gotoCase = 7; continue; }; +case 11: + yyaccept = 0; + YYMARKER = ++cursor; + yych = this._charAt(cursor); +case 12: + if (yych <= '\f') { + if (yych == '\n') { gotoCase = 2; continue; }; + { gotoCase = 11; continue; }; + } else { + if (yych <= '\r') { gotoCase = 2; continue; }; + if (yych == '*') { gotoCase = 9; continue; }; + { gotoCase = 11; continue; }; + } +/* *********************************** */ +case this.case_DSTRING: + yych = this._charAt(cursor); + if (yych <= '\r') { + if (yych == '\n') { gotoCase = 17; continue; }; + if (yych <= '\f') { gotoCase = 16; continue; }; + { gotoCase = 17; continue; }; + } else { + if (yych <= '"') { + if (yych <= '!') { gotoCase = 16; continue; }; + { gotoCase = 19; continue; }; + } else { + if (yych == '\\') { gotoCase = 21; continue; }; + { gotoCase = 16; continue; }; + } + } +case 15: + { return this._stringToken(cursor); } +case 16: + yyaccept = 0; + yych = this._charAt(YYMARKER = ++cursor); + { gotoCase = 23; continue; }; +case 17: + ++cursor; +case 18: + { this.tokenType = null; return cursor; } +case 19: + ++cursor; +case 20: + this.setLexCondition(this._lexConditions.INITIAL); + { return this._stringToken(cursor, true); } +case 21: + yych = this._charAt(++cursor); + if (yych <= 'e') { + if (yych <= '\'') { + if (yych == '"') { gotoCase = 22; continue; }; + if (yych <= '&') { gotoCase = 18; continue; }; + } else { + if (yych <= '\\') { + if (yych <= '[') { gotoCase = 18; continue; }; + } else { + if (yych != 'b') { gotoCase = 18; continue; }; + } + } + } else { + if (yych <= 'r') { + if (yych <= 'm') { + if (yych >= 'g') { gotoCase = 18; continue; }; + } else { + if (yych <= 'n') { gotoCase = 22; continue; }; + if (yych <= 'q') { gotoCase = 18; continue; }; + } + } else { + if (yych <= 't') { + if (yych <= 's') { gotoCase = 18; continue; }; + } else { + if (yych != 'v') { gotoCase = 18; continue; }; + } + } + } +case 22: + yyaccept = 0; + YYMARKER = ++cursor; + yych = this._charAt(cursor); +case 23: + if (yych <= '\r') { + if (yych == '\n') { gotoCase = 15; continue; }; + if (yych <= '\f') { gotoCase = 22; continue; }; + { gotoCase = 15; continue; }; + } else { + if (yych <= '"') { + if (yych <= '!') { gotoCase = 22; continue; }; + { gotoCase = 26; continue; }; + } else { + if (yych != '\\') { gotoCase = 22; continue; }; + } + } + ++cursor; + yych = this._charAt(cursor); + if (yych <= 'e') { + if (yych <= '\'') { + if (yych == '"') { gotoCase = 22; continue; }; + if (yych >= '\'') { gotoCase = 22; continue; }; + } else { + if (yych <= '\\') { + if (yych >= '\\') { gotoCase = 22; continue; }; + } else { + if (yych == 'b') { gotoCase = 22; continue; }; + } + } + } else { + if (yych <= 'r') { + if (yych <= 'm') { + if (yych <= 'f') { gotoCase = 22; continue; }; + } else { + if (yych <= 'n') { gotoCase = 22; continue; }; + if (yych >= 'r') { gotoCase = 22; continue; }; + } + } else { + if (yych <= 't') { + if (yych >= 't') { gotoCase = 22; continue; }; + } else { + if (yych == 'v') { gotoCase = 22; continue; }; + } + } + } + cursor = YYMARKER; + { gotoCase = 15; continue; }; +case 26: + ++cursor; + yych = this._charAt(cursor); + { gotoCase = 20; continue; }; +/* *********************************** */ +case this.case_INITIAL: + yych = this._charAt(cursor); + if (yych <= ';') { + if (yych <= '\'') { + if (yych <= '"') { + if (yych <= ' ') { gotoCase = 29; continue; }; + if (yych <= '!') { gotoCase = 31; continue; }; + { gotoCase = 33; continue; }; + } else { + if (yych <= '#') { gotoCase = 34; continue; }; + if (yych <= '$') { gotoCase = 31; continue; }; + if (yych >= '\'') { gotoCase = 35; continue; }; + } + } else { + if (yych <= '.') { + if (yych <= ',') { gotoCase = 29; continue; }; + if (yych <= '-') { gotoCase = 36; continue; }; + { gotoCase = 37; continue; }; + } else { + if (yych <= '/') { gotoCase = 38; continue; }; + if (yych <= '9') { gotoCase = 39; continue; }; + if (yych <= ':') { gotoCase = 41; continue; }; + { gotoCase = 43; continue; }; + } + } + } else { + if (yych <= '^') { + if (yych <= '?') { + if (yych == '=') { gotoCase = 31; continue; }; + } else { + if (yych == '\\') { gotoCase = 29; continue; }; + if (yych <= ']') { gotoCase = 31; continue; }; + } + } else { + if (yych <= 'z') { + if (yych != '`') { gotoCase = 31; continue; }; + } else { + if (yych <= '{') { gotoCase = 45; continue; }; + if (yych == '}') { gotoCase = 47; continue; }; + } + } + } +case 29: + ++cursor; +case 30: + { this.tokenType = null; return cursor; } +case 31: + ++cursor; + yych = this._charAt(cursor); + { gotoCase = 50; continue; }; +case 32: + { + var token = this._line.substring(cursorOnEnter, cursor); + if (this._condition.parseCondition === this._parseConditions.INITIAL) { + if (token === "@media") { + this.tokenType = "css-at-rule"; + this._condition.parseCondition = this._parseConditions.AT_MEDIA_RULE; + } else if (token.indexOf("@") === 0) { + this.tokenType = "css-at-rule"; + this._condition.parseCondition = this._parseConditions.AT_RULE; + } else + this.tokenType = "css-selector"; + } else if ((this._condition.parseCondition === this._parseConditions.AT_MEDIA_RULE || this._condition.parseCondition === this._parseConditions.AT_RULE) && token in this._mediaTypes) + this.tokenType = "css-keyword"; + else if (this._condition.parseCondition === this._parseConditions.PROPERTY && token in this._propertyKeywords) + this.tokenType = "css-property"; + else if (this._isPropertyValue()) { + if (token in this._valueKeywords) + this.tokenType = "css-keyword"; + else if (token in this._colorKeywords) { + // FIXME: this does not convert tokens toLowerCase() for the sake of speed. + this.tokenType = "css-color"; + } else if (token === "!important") + this.tokenType = "css-important"; + } else + this.tokenType = null; + return cursor; + } +case 33: + yyaccept = 0; + yych = this._charAt(YYMARKER = ++cursor); + if (yych <= '-') { + if (yych <= '!') { + if (yych <= '\f') { + if (yych == '\n') { gotoCase = 32; continue; }; + { gotoCase = 128; continue; }; + } else { + if (yych <= '\r') { gotoCase = 32; continue; }; + if (yych <= ' ') { gotoCase = 128; continue; }; + { gotoCase = 126; continue; }; + } + } else { + if (yych <= '$') { + if (yych <= '"') { gotoCase = 115; continue; }; + if (yych <= '#') { gotoCase = 128; continue; }; + { gotoCase = 126; continue; }; + } else { + if (yych == '\'') { gotoCase = 126; continue; }; + if (yych <= ',') { gotoCase = 128; continue; }; + { gotoCase = 126; continue; }; + } + } + } else { + if (yych <= '[') { + if (yych <= '<') { + if (yych <= '.') { gotoCase = 128; continue; }; + if (yych <= '9') { gotoCase = 126; continue; }; + { gotoCase = 128; continue; }; + } else { + if (yych <= '=') { gotoCase = 126; continue; }; + if (yych <= '?') { gotoCase = 128; continue; }; + { gotoCase = 126; continue; }; + } + } else { + if (yych <= '^') { + if (yych <= '\\') { gotoCase = 130; continue; }; + if (yych <= ']') { gotoCase = 126; continue; }; + { gotoCase = 128; continue; }; + } else { + if (yych == '`') { gotoCase = 128; continue; }; + if (yych <= 'z') { gotoCase = 126; continue; }; + { gotoCase = 128; continue; }; + } + } + } +case 34: + yych = this._charAt(++cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 30; continue; }; + if (yych <= '9') { gotoCase = 123; continue; }; + { gotoCase = 30; continue; }; + } else { + if (yych <= 'F') { gotoCase = 123; continue; }; + if (yych <= '`') { gotoCase = 30; continue; }; + if (yych <= 'f') { gotoCase = 123; continue; }; + { gotoCase = 30; continue; }; + } +case 35: + yyaccept = 0; + yych = this._charAt(YYMARKER = ++cursor); + if (yych <= '-') { + if (yych <= '"') { + if (yych <= '\f') { + if (yych == '\n') { gotoCase = 32; continue; }; + { gotoCase = 117; continue; }; + } else { + if (yych <= '\r') { gotoCase = 32; continue; }; + if (yych <= ' ') { gotoCase = 117; continue; }; + { gotoCase = 113; continue; }; + } + } else { + if (yych <= '&') { + if (yych == '$') { gotoCase = 113; continue; }; + { gotoCase = 117; continue; }; + } else { + if (yych <= '\'') { gotoCase = 115; continue; }; + if (yych <= ',') { gotoCase = 117; continue; }; + { gotoCase = 113; continue; }; + } + } + } else { + if (yych <= '[') { + if (yych <= '<') { + if (yych <= '.') { gotoCase = 117; continue; }; + if (yych <= '9') { gotoCase = 113; continue; }; + { gotoCase = 117; continue; }; + } else { + if (yych <= '=') { gotoCase = 113; continue; }; + if (yych <= '?') { gotoCase = 117; continue; }; + { gotoCase = 113; continue; }; + } + } else { + if (yych <= '^') { + if (yych <= '\\') { gotoCase = 119; continue; }; + if (yych <= ']') { gotoCase = 113; continue; }; + { gotoCase = 117; continue; }; + } else { + if (yych == '`') { gotoCase = 117; continue; }; + if (yych <= 'z') { gotoCase = 113; continue; }; + { gotoCase = 117; continue; }; + } + } + } +case 36: + yyaccept = 0; + yych = this._charAt(YYMARKER = ++cursor); + if (yych == '.') { gotoCase = 66; continue; }; + if (yych <= '/') { gotoCase = 50; continue; }; + if (yych <= '9') { gotoCase = 51; continue; }; + { gotoCase = 50; continue; }; +case 37: + yych = this._charAt(++cursor); + if (yych <= '/') { gotoCase = 30; continue; }; + if (yych <= '9') { gotoCase = 69; continue; }; + { gotoCase = 30; continue; }; +case 38: + yyaccept = 0; + yych = this._charAt(YYMARKER = ++cursor); + if (yych == '*') { gotoCase = 105; continue; }; + { gotoCase = 50; continue; }; +case 39: + yyaccept = 1; + yych = this._charAt(YYMARKER = ++cursor); + switch (yych) { + case '!': + case '"': + case '$': + case '\'': + case '-': + case '/': + case '=': + case '@': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + case '[': + case ']': + case 'a': + case 'b': + case 'f': + case 'h': + case 'j': + case 'l': + case 'n': + case 'o': + case 'q': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': { gotoCase = 49; continue; }; + case '%': { gotoCase = 68; continue; }; + case '.': { gotoCase = 66; continue; }; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { gotoCase = 51; continue; }; + case 'H': { gotoCase = 53; continue; }; + case '_': { gotoCase = 54; continue; }; + case 'c': { gotoCase = 55; continue; }; + case 'd': { gotoCase = 56; continue; }; + case 'e': { gotoCase = 57; continue; }; + case 'g': { gotoCase = 58; continue; }; + case 'i': { gotoCase = 59; continue; }; + case 'k': { gotoCase = 60; continue; }; + case 'm': { gotoCase = 61; continue; }; + case 'p': { gotoCase = 62; continue; }; + case 'r': { gotoCase = 63; continue; }; + case 's': { gotoCase = 64; continue; }; + case 't': { gotoCase = 65; continue; }; + default: { gotoCase = 40; continue; }; + } +case 40: + { + if (this._isPropertyValue()) + this.tokenType = "css-number"; + else + this.tokenType = null; + return cursor; + } +case 41: + ++cursor; + { + this.tokenType = null; + if (this._condition.parseCondition === this._parseConditions.PROPERTY) + this._condition.parseCondition = this._parseConditions.PROPERTY_VALUE; + return cursor; + } +case 43: + ++cursor; + { + this.tokenType = null; + if (this._condition.parseCondition === this._parseConditions.AT_RULE) + this._condition.parseCondition = this._parseConditions.INITIAL; + else + this._condition.parseCondition = this._parseConditions.PROPERTY; + return cursor; + } +case 45: + ++cursor; + { + this.tokenType = null; + if (this._condition.parseCondition === this._parseConditions.AT_MEDIA_RULE) + this._condition.parseCondition = this._parseConditions.INITIAL; + else + this._condition.parseCondition = this._parseConditions.PROPERTY; + return cursor; + } +case 47: + ++cursor; + { + this.tokenType = null; + this._condition.parseCondition = this._parseConditions.INITIAL; + return cursor; + } +case 49: + ++cursor; + yych = this._charAt(cursor); +case 50: + if (yych <= '9') { + if (yych <= '&') { + if (yych <= '"') { + if (yych <= ' ') { gotoCase = 32; continue; }; + { gotoCase = 49; continue; }; + } else { + if (yych == '$') { gotoCase = 49; continue; }; + { gotoCase = 32; continue; }; + } + } else { + if (yych <= ',') { + if (yych <= '\'') { gotoCase = 49; continue; }; + { gotoCase = 32; continue; }; + } else { + if (yych == '.') { gotoCase = 32; continue; }; + { gotoCase = 49; continue; }; + } + } + } else { + if (yych <= '\\') { + if (yych <= '=') { + if (yych <= '<') { gotoCase = 32; continue; }; + { gotoCase = 49; continue; }; + } else { + if (yych <= '?') { gotoCase = 32; continue; }; + if (yych <= '[') { gotoCase = 49; continue; }; + { gotoCase = 32; continue; }; + } + } else { + if (yych <= '_') { + if (yych == '^') { gotoCase = 32; continue; }; + { gotoCase = 49; continue; }; + } else { + if (yych <= '`') { gotoCase = 32; continue; }; + if (yych <= 'z') { gotoCase = 49; continue; }; + { gotoCase = 32; continue; }; + } + } + } +case 51: + yyaccept = 1; + YYMARKER = ++cursor; + yych = this._charAt(cursor); + switch (yych) { + case '!': + case '"': + case '$': + case '\'': + case '-': + case '/': + case '=': + case '@': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + case '[': + case ']': + case 'a': + case 'b': + case 'f': + case 'h': + case 'j': + case 'l': + case 'n': + case 'o': + case 'q': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': { gotoCase = 49; continue; }; + case '%': { gotoCase = 68; continue; }; + case '.': { gotoCase = 66; continue; }; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { gotoCase = 51; continue; }; + case 'H': { gotoCase = 53; continue; }; + case '_': { gotoCase = 54; continue; }; + case 'c': { gotoCase = 55; continue; }; + case 'd': { gotoCase = 56; continue; }; + case 'e': { gotoCase = 57; continue; }; + case 'g': { gotoCase = 58; continue; }; + case 'i': { gotoCase = 59; continue; }; + case 'k': { gotoCase = 60; continue; }; + case 'm': { gotoCase = 61; continue; }; + case 'p': { gotoCase = 62; continue; }; + case 'r': { gotoCase = 63; continue; }; + case 's': { gotoCase = 64; continue; }; + case 't': { gotoCase = 65; continue; }; + default: { gotoCase = 40; continue; }; + } +case 53: + yych = this._charAt(++cursor); + if (yych == 'z') { gotoCase = 64; continue; }; + { gotoCase = 50; continue; }; +case 54: + yych = this._charAt(++cursor); + if (yych == '_') { gotoCase = 102; continue; }; + { gotoCase = 50; continue; }; +case 55: + yych = this._charAt(++cursor); + if (yych == 'm') { gotoCase = 64; continue; }; + { gotoCase = 50; continue; }; +case 56: + yych = this._charAt(++cursor); + if (yych == 'e') { gotoCase = 101; continue; }; + { gotoCase = 50; continue; }; +case 57: + yych = this._charAt(++cursor); + if (yych == 'm') { gotoCase = 64; continue; }; + if (yych == 'x') { gotoCase = 64; continue; }; + { gotoCase = 50; continue; }; +case 58: + yych = this._charAt(++cursor); + if (yych == 'r') { gotoCase = 99; continue; }; + { gotoCase = 50; continue; }; +case 59: + yych = this._charAt(++cursor); + if (yych == 'n') { gotoCase = 64; continue; }; + { gotoCase = 50; continue; }; +case 60: + yych = this._charAt(++cursor); + if (yych == 'H') { gotoCase = 98; continue; }; + { gotoCase = 50; continue; }; +case 61: + yych = this._charAt(++cursor); + if (yych == 'm') { gotoCase = 64; continue; }; + if (yych == 's') { gotoCase = 64; continue; }; + { gotoCase = 50; continue; }; +case 62: + yych = this._charAt(++cursor); + if (yych <= 's') { + if (yych == 'c') { gotoCase = 64; continue; }; + { gotoCase = 50; continue; }; + } else { + if (yych <= 't') { gotoCase = 64; continue; }; + if (yych == 'x') { gotoCase = 64; continue; }; + { gotoCase = 50; continue; }; + } +case 63: + yych = this._charAt(++cursor); + if (yych == 'a') { gotoCase = 96; continue; }; + if (yych == 'e') { gotoCase = 97; continue; }; + { gotoCase = 50; continue; }; +case 64: + yych = this._charAt(++cursor); + if (yych <= '9') { + if (yych <= '&') { + if (yych <= '"') { + if (yych <= ' ') { gotoCase = 40; continue; }; + { gotoCase = 49; continue; }; + } else { + if (yych == '$') { gotoCase = 49; continue; }; + { gotoCase = 40; continue; }; + } + } else { + if (yych <= ',') { + if (yych <= '\'') { gotoCase = 49; continue; }; + { gotoCase = 40; continue; }; + } else { + if (yych == '.') { gotoCase = 40; continue; }; + { gotoCase = 49; continue; }; + } + } + } else { + if (yych <= '\\') { + if (yych <= '=') { + if (yych <= '<') { gotoCase = 40; continue; }; + { gotoCase = 49; continue; }; + } else { + if (yych <= '?') { gotoCase = 40; continue; }; + if (yych <= '[') { gotoCase = 49; continue; }; + { gotoCase = 40; continue; }; + } + } else { + if (yych <= '_') { + if (yych == '^') { gotoCase = 40; continue; }; + { gotoCase = 49; continue; }; + } else { + if (yych <= '`') { gotoCase = 40; continue; }; + if (yych <= 'z') { gotoCase = 49; continue; }; + { gotoCase = 40; continue; }; + } + } + } +case 65: + yych = this._charAt(++cursor); + if (yych == 'u') { gotoCase = 94; continue; }; + { gotoCase = 50; continue; }; +case 66: + yych = this._charAt(++cursor); + if (yych <= '/') { gotoCase = 67; continue; }; + if (yych <= '9') { gotoCase = 69; continue; }; +case 67: + cursor = YYMARKER; + if (yyaccept <= 0) { + { gotoCase = 32; continue; }; + } else { + { gotoCase = 40; continue; }; + } +case 68: + yych = this._charAt(++cursor); + { gotoCase = 40; continue; }; +case 69: + yyaccept = 1; + YYMARKER = ++cursor; + yych = this._charAt(cursor); + if (yych <= 'f') { + if (yych <= 'H') { + if (yych <= '/') { + if (yych == '%') { gotoCase = 68; continue; }; + { gotoCase = 40; continue; }; + } else { + if (yych <= '9') { gotoCase = 69; continue; }; + if (yych <= 'G') { gotoCase = 40; continue; }; + { gotoCase = 81; continue; }; + } + } else { + if (yych <= 'b') { + if (yych == '_') { gotoCase = 73; continue; }; + { gotoCase = 40; continue; }; + } else { + if (yych <= 'c') { gotoCase = 75; continue; }; + if (yych <= 'd') { gotoCase = 78; continue; }; + if (yych >= 'f') { gotoCase = 40; continue; }; + } + } + } else { + if (yych <= 'm') { + if (yych <= 'i') { + if (yych <= 'g') { gotoCase = 79; continue; }; + if (yych <= 'h') { gotoCase = 40; continue; }; + { gotoCase = 77; continue; }; + } else { + if (yych == 'k') { gotoCase = 82; continue; }; + if (yych <= 'l') { gotoCase = 40; continue; }; + { gotoCase = 76; continue; }; + } + } else { + if (yych <= 'q') { + if (yych == 'p') { gotoCase = 74; continue; }; + { gotoCase = 40; continue; }; + } else { + if (yych <= 'r') { gotoCase = 72; continue; }; + if (yych <= 's') { gotoCase = 68; continue; }; + if (yych <= 't') { gotoCase = 80; continue; }; + { gotoCase = 40; continue; }; + } + } + } + yych = this._charAt(++cursor); + if (yych == 'm') { gotoCase = 68; continue; }; + if (yych == 'x') { gotoCase = 68; continue; }; + { gotoCase = 67; continue; }; +case 72: + yych = this._charAt(++cursor); + if (yych == 'a') { gotoCase = 92; continue; }; + if (yych == 'e') { gotoCase = 93; continue; }; + { gotoCase = 67; continue; }; +case 73: + yych = this._charAt(++cursor); + if (yych == '_') { gotoCase = 89; continue; }; + { gotoCase = 67; continue; }; +case 74: + yych = this._charAt(++cursor); + if (yych <= 's') { + if (yych == 'c') { gotoCase = 68; continue; }; + { gotoCase = 67; continue; }; + } else { + if (yych <= 't') { gotoCase = 68; continue; }; + if (yych == 'x') { gotoCase = 68; continue; }; + { gotoCase = 67; continue; }; + } +case 75: + yych = this._charAt(++cursor); + if (yych == 'm') { gotoCase = 68; continue; }; + { gotoCase = 67; continue; }; +case 76: + yych = this._charAt(++cursor); + if (yych == 'm') { gotoCase = 68; continue; }; + if (yych == 's') { gotoCase = 68; continue; }; + { gotoCase = 67; continue; }; +case 77: + yych = this._charAt(++cursor); + if (yych == 'n') { gotoCase = 68; continue; }; + { gotoCase = 67; continue; }; +case 78: + yych = this._charAt(++cursor); + if (yych == 'e') { gotoCase = 88; continue; }; + { gotoCase = 67; continue; }; +case 79: + yych = this._charAt(++cursor); + if (yych == 'r') { gotoCase = 86; continue; }; + { gotoCase = 67; continue; }; +case 80: + yych = this._charAt(++cursor); + if (yych == 'u') { gotoCase = 84; continue; }; + { gotoCase = 67; continue; }; +case 81: + yych = this._charAt(++cursor); + if (yych == 'z') { gotoCase = 68; continue; }; + { gotoCase = 67; continue; }; +case 82: + yych = this._charAt(++cursor); + if (yych != 'H') { gotoCase = 67; continue; }; + yych = this._charAt(++cursor); + if (yych == 'z') { gotoCase = 68; continue; }; + { gotoCase = 67; continue; }; +case 84: + yych = this._charAt(++cursor); + if (yych != 'r') { gotoCase = 67; continue; }; + yych = this._charAt(++cursor); + if (yych == 'n') { gotoCase = 68; continue; }; + { gotoCase = 67; continue; }; +case 86: + yych = this._charAt(++cursor); + if (yych != 'a') { gotoCase = 67; continue; }; + yych = this._charAt(++cursor); + if (yych == 'd') { gotoCase = 68; continue; }; + { gotoCase = 67; continue; }; +case 88: + yych = this._charAt(++cursor); + if (yych == 'g') { gotoCase = 68; continue; }; + { gotoCase = 67; continue; }; +case 89: + yych = this._charAt(++cursor); + if (yych != 'q') { gotoCase = 67; continue; }; + yych = this._charAt(++cursor); + if (yych != 'e') { gotoCase = 67; continue; }; + yych = this._charAt(++cursor); + if (yych == 'm') { gotoCase = 68; continue; }; + { gotoCase = 67; continue; }; +case 92: + yych = this._charAt(++cursor); + if (yych == 'd') { gotoCase = 68; continue; }; + { gotoCase = 67; continue; }; +case 93: + yych = this._charAt(++cursor); + if (yych == 'm') { gotoCase = 68; continue; }; + { gotoCase = 67; continue; }; +case 94: + yych = this._charAt(++cursor); + if (yych != 'r') { gotoCase = 50; continue; }; + yych = this._charAt(++cursor); + if (yych == 'n') { gotoCase = 64; continue; }; + { gotoCase = 50; continue; }; +case 96: + yych = this._charAt(++cursor); + if (yych == 'd') { gotoCase = 64; continue; }; + { gotoCase = 50; continue; }; +case 97: + yych = this._charAt(++cursor); + if (yych == 'm') { gotoCase = 64; continue; }; + { gotoCase = 50; continue; }; +case 98: + yych = this._charAt(++cursor); + if (yych == 'z') { gotoCase = 64; continue; }; + { gotoCase = 50; continue; }; +case 99: + yych = this._charAt(++cursor); + if (yych != 'a') { gotoCase = 50; continue; }; + yych = this._charAt(++cursor); + if (yych == 'd') { gotoCase = 64; continue; }; + { gotoCase = 50; continue; }; +case 101: + yych = this._charAt(++cursor); + if (yych == 'g') { gotoCase = 64; continue; }; + { gotoCase = 50; continue; }; +case 102: + yych = this._charAt(++cursor); + if (yych != 'q') { gotoCase = 50; continue; }; + yych = this._charAt(++cursor); + if (yych != 'e') { gotoCase = 50; continue; }; + yych = this._charAt(++cursor); + if (yych == 'm') { gotoCase = 64; continue; }; + { gotoCase = 50; continue; }; +case 105: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '\f') { + if (yych == '\n') { gotoCase = 109; continue; }; + { gotoCase = 105; continue; }; + } else { + if (yych <= '\r') { gotoCase = 109; continue; }; + if (yych != '*') { gotoCase = 105; continue; }; + } +case 107: + ++cursor; + yych = this._charAt(cursor); + if (yych == '*') { gotoCase = 107; continue; }; + if (yych == '/') { gotoCase = 111; continue; }; + { gotoCase = 105; continue; }; +case 109: + ++cursor; + this.setLexCondition(this._lexConditions.COMMENT); + { this.tokenType = "css-comment"; return cursor; } +case 111: + ++cursor; + { this.tokenType = "css-comment"; return cursor; } +case 113: + yyaccept = 0; + YYMARKER = ++cursor; + yych = this._charAt(cursor); + if (yych <= '-') { + if (yych <= '"') { + if (yych <= '\f') { + if (yych == '\n') { gotoCase = 32; continue; }; + { gotoCase = 117; continue; }; + } else { + if (yych <= '\r') { gotoCase = 32; continue; }; + if (yych <= ' ') { gotoCase = 117; continue; }; + { gotoCase = 113; continue; }; + } + } else { + if (yych <= '&') { + if (yych == '$') { gotoCase = 113; continue; }; + { gotoCase = 117; continue; }; + } else { + if (yych <= '\'') { gotoCase = 115; continue; }; + if (yych <= ',') { gotoCase = 117; continue; }; + { gotoCase = 113; continue; }; + } + } + } else { + if (yych <= '[') { + if (yych <= '<') { + if (yych <= '.') { gotoCase = 117; continue; }; + if (yych <= '9') { gotoCase = 113; continue; }; + { gotoCase = 117; continue; }; + } else { + if (yych <= '=') { gotoCase = 113; continue; }; + if (yych <= '?') { gotoCase = 117; continue; }; + { gotoCase = 113; continue; }; + } + } else { + if (yych <= '^') { + if (yych <= '\\') { gotoCase = 119; continue; }; + if (yych <= ']') { gotoCase = 113; continue; }; + { gotoCase = 117; continue; }; + } else { + if (yych == '`') { gotoCase = 117; continue; }; + if (yych <= 'z') { gotoCase = 113; continue; }; + { gotoCase = 117; continue; }; + } + } + } +case 115: + ++cursor; + if ((yych = this._charAt(cursor)) <= '9') { + if (yych <= '&') { + if (yych <= '"') { + if (yych >= '!') { gotoCase = 49; continue; }; + } else { + if (yych == '$') { gotoCase = 49; continue; }; + } + } else { + if (yych <= ',') { + if (yych <= '\'') { gotoCase = 49; continue; }; + } else { + if (yych != '.') { gotoCase = 49; continue; }; + } + } + } else { + if (yych <= '\\') { + if (yych <= '=') { + if (yych >= '=') { gotoCase = 49; continue; }; + } else { + if (yych <= '?') { gotoCase = 116; continue; }; + if (yych <= '[') { gotoCase = 49; continue; }; + } + } else { + if (yych <= '_') { + if (yych != '^') { gotoCase = 49; continue; }; + } else { + if (yych <= '`') { gotoCase = 116; continue; }; + if (yych <= 'z') { gotoCase = 49; continue; }; + } + } + } +case 116: + { return this._stringToken(cursor, true); } +case 117: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '\r') { + if (yych == '\n') { gotoCase = 67; continue; }; + if (yych <= '\f') { gotoCase = 117; continue; }; + { gotoCase = 67; continue; }; + } else { + if (yych <= '\'') { + if (yych <= '&') { gotoCase = 117; continue; }; + { gotoCase = 122; continue; }; + } else { + if (yych != '\\') { gotoCase = 117; continue; }; + } + } +case 119: + ++cursor; + yych = this._charAt(cursor); + if (yych <= 'a') { + if (yych <= '!') { + if (yych <= '\n') { + if (yych <= '\t') { gotoCase = 67; continue; }; + } else { + if (yych != '\r') { gotoCase = 67; continue; }; + } + } else { + if (yych <= '\'') { + if (yych <= '"') { gotoCase = 117; continue; }; + if (yych <= '&') { gotoCase = 67; continue; }; + { gotoCase = 117; continue; }; + } else { + if (yych == '\\') { gotoCase = 117; continue; }; + { gotoCase = 67; continue; }; + } + } + } else { + if (yych <= 'q') { + if (yych <= 'f') { + if (yych <= 'b') { gotoCase = 117; continue; }; + if (yych <= 'e') { gotoCase = 67; continue; }; + { gotoCase = 117; continue; }; + } else { + if (yych == 'n') { gotoCase = 117; continue; }; + { gotoCase = 67; continue; }; + } + } else { + if (yych <= 't') { + if (yych == 's') { gotoCase = 67; continue; }; + { gotoCase = 117; continue; }; + } else { + if (yych == 'v') { gotoCase = 117; continue; }; + { gotoCase = 67; continue; }; + } + } + } + ++cursor; + this.setLexCondition(this._lexConditions.SSTRING); + { return this._stringToken(cursor); } +case 122: + yych = this._charAt(++cursor); + { gotoCase = 116; continue; }; +case 123: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 125; continue; }; + if (yych <= '9') { gotoCase = 123; continue; }; + } else { + if (yych <= 'F') { gotoCase = 123; continue; }; + if (yych <= '`') { gotoCase = 125; continue; }; + if (yych <= 'f') { gotoCase = 123; continue; }; + } +case 125: + { + if (this._isPropertyValue()) + this.tokenType = "css-color"; + else + this.tokenType = null; + return cursor; + } +case 126: + yyaccept = 0; + YYMARKER = ++cursor; + yych = this._charAt(cursor); + if (yych <= '-') { + if (yych <= '!') { + if (yych <= '\f') { + if (yych == '\n') { gotoCase = 32; continue; }; + } else { + if (yych <= '\r') { gotoCase = 32; continue; }; + if (yych >= '!') { gotoCase = 126; continue; }; + } + } else { + if (yych <= '$') { + if (yych <= '"') { gotoCase = 115; continue; }; + if (yych >= '$') { gotoCase = 126; continue; }; + } else { + if (yych == '\'') { gotoCase = 126; continue; }; + if (yych >= '-') { gotoCase = 126; continue; }; + } + } + } else { + if (yych <= '[') { + if (yych <= '<') { + if (yych <= '.') { gotoCase = 128; continue; }; + if (yych <= '9') { gotoCase = 126; continue; }; + } else { + if (yych <= '=') { gotoCase = 126; continue; }; + if (yych >= '@') { gotoCase = 126; continue; }; + } + } else { + if (yych <= '^') { + if (yych <= '\\') { gotoCase = 130; continue; }; + if (yych <= ']') { gotoCase = 126; continue; }; + } else { + if (yych == '`') { gotoCase = 128; continue; }; + if (yych <= 'z') { gotoCase = 126; continue; }; + } + } + } +case 128: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '\r') { + if (yych == '\n') { gotoCase = 67; continue; }; + if (yych <= '\f') { gotoCase = 128; continue; }; + { gotoCase = 67; continue; }; + } else { + if (yych <= '"') { + if (yych <= '!') { gotoCase = 128; continue; }; + { gotoCase = 122; continue; }; + } else { + if (yych != '\\') { gotoCase = 128; continue; }; + } + } +case 130: + ++cursor; + yych = this._charAt(cursor); + if (yych <= 'a') { + if (yych <= '!') { + if (yych <= '\n') { + if (yych <= '\t') { gotoCase = 67; continue; }; + } else { + if (yych != '\r') { gotoCase = 67; continue; }; + } + } else { + if (yych <= '\'') { + if (yych <= '"') { gotoCase = 128; continue; }; + if (yych <= '&') { gotoCase = 67; continue; }; + { gotoCase = 128; continue; }; + } else { + if (yych == '\\') { gotoCase = 128; continue; }; + { gotoCase = 67; continue; }; + } + } + } else { + if (yych <= 'q') { + if (yych <= 'f') { + if (yych <= 'b') { gotoCase = 128; continue; }; + if (yych <= 'e') { gotoCase = 67; continue; }; + { gotoCase = 128; continue; }; + } else { + if (yych == 'n') { gotoCase = 128; continue; }; + { gotoCase = 67; continue; }; + } + } else { + if (yych <= 't') { + if (yych == 's') { gotoCase = 67; continue; }; + { gotoCase = 128; continue; }; + } else { + if (yych == 'v') { gotoCase = 128; continue; }; + { gotoCase = 67; continue; }; + } + } + } + ++cursor; + this.setLexCondition(this._lexConditions.DSTRING); + { return this._stringToken(cursor); } +/* *********************************** */ +case this.case_SSTRING: + yych = this._charAt(cursor); + if (yych <= '\r') { + if (yych == '\n') { gotoCase = 137; continue; }; + if (yych <= '\f') { gotoCase = 136; continue; }; + { gotoCase = 137; continue; }; + } else { + if (yych <= '\'') { + if (yych <= '&') { gotoCase = 136; continue; }; + { gotoCase = 139; continue; }; + } else { + if (yych == '\\') { gotoCase = 141; continue; }; + { gotoCase = 136; continue; }; + } + } +case 135: + { return this._stringToken(cursor); } +case 136: + yyaccept = 0; + yych = this._charAt(YYMARKER = ++cursor); + { gotoCase = 143; continue; }; +case 137: + ++cursor; +case 138: + { this.tokenType = null; return cursor; } +case 139: + ++cursor; +case 140: + this.setLexCondition(this._lexConditions.INITIAL); + { return this._stringToken(cursor, true); } +case 141: + yych = this._charAt(++cursor); + if (yych <= 'e') { + if (yych <= '\'') { + if (yych == '"') { gotoCase = 142; continue; }; + if (yych <= '&') { gotoCase = 138; continue; }; + } else { + if (yych <= '\\') { + if (yych <= '[') { gotoCase = 138; continue; }; + } else { + if (yych != 'b') { gotoCase = 138; continue; }; + } + } + } else { + if (yych <= 'r') { + if (yych <= 'm') { + if (yych >= 'g') { gotoCase = 138; continue; }; + } else { + if (yych <= 'n') { gotoCase = 142; continue; }; + if (yych <= 'q') { gotoCase = 138; continue; }; + } + } else { + if (yych <= 't') { + if (yych <= 's') { gotoCase = 138; continue; }; + } else { + if (yych != 'v') { gotoCase = 138; continue; }; + } + } + } +case 142: + yyaccept = 0; + YYMARKER = ++cursor; + yych = this._charAt(cursor); +case 143: + if (yych <= '\r') { + if (yych == '\n') { gotoCase = 135; continue; }; + if (yych <= '\f') { gotoCase = 142; continue; }; + { gotoCase = 135; continue; }; + } else { + if (yych <= '\'') { + if (yych <= '&') { gotoCase = 142; continue; }; + { gotoCase = 146; continue; }; + } else { + if (yych != '\\') { gotoCase = 142; continue; }; + } + } + ++cursor; + yych = this._charAt(cursor); + if (yych <= 'e') { + if (yych <= '\'') { + if (yych == '"') { gotoCase = 142; continue; }; + if (yych >= '\'') { gotoCase = 142; continue; }; + } else { + if (yych <= '\\') { + if (yych >= '\\') { gotoCase = 142; continue; }; + } else { + if (yych == 'b') { gotoCase = 142; continue; }; + } + } + } else { + if (yych <= 'r') { + if (yych <= 'm') { + if (yych <= 'f') { gotoCase = 142; continue; }; + } else { + if (yych <= 'n') { gotoCase = 142; continue; }; + if (yych >= 'r') { gotoCase = 142; continue; }; + } + } else { + if (yych <= 't') { + if (yych >= 't') { gotoCase = 142; continue; }; + } else { + if (yych == 'v') { gotoCase = 142; continue; }; + } + } + } + cursor = YYMARKER; + { gotoCase = 135; continue; }; +case 146: + ++cursor; + yych = this._charAt(cursor); + { gotoCase = 140; continue; }; + } + + } + } +} + +WebInspector.SourceCSSTokenizer.prototype.__proto__ = WebInspector.SourceTokenizer.prototype; +/* SourceHTMLTokenizer.js */ + +/* Generated by re2c 0.13.5 on Fri May 6 13:47:06 2011 */ +/* + * 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. + */ + +// Generate js file as follows: +// +// re2c -isc WebCore/inspector/front-end/SourceHTMLTokenizer.re2js \ +// | sed 's|^yy\([^:]*\)*\:|case \1:|' \ +// | sed 's|[*]cursor[+][+]|this._charAt(cursor++)|' \ +// | sed 's|[[*][+][+]cursor|this._charAt(++cursor)|' \ +// | sed 's|[*]cursor|this._charAt(cursor)|' \ +// | sed 's|yych = \*\([^;]*\)|yych = this._charAt\1|' \ +// | sed 's|{ gotoCase = \([^; continue; };]*\)|{ gotoCase = \1; continue; }|' \ +// | sed 's|unsigned\ int|var|' \ +// | sed 's|var\ yych|case 1: case 1: var yych|' + +/** + * @constructor + * @extends {WebInspector.SourceTokenizer} + */ +WebInspector.SourceHTMLTokenizer = function() +{ + WebInspector.SourceTokenizer.call(this); + + // The order is determined by the generated code. + this._lexConditions = { + INITIAL: 0, + COMMENT: 1, + DOCTYPE: 2, + TAG: 3, + DSTRING: 4, + SSTRING: 5 + }; + this.case_INITIAL = 1000; + this.case_COMMENT = 1001; + this.case_DOCTYPE = 1002; + this.case_TAG = 1003; + this.case_DSTRING = 1004; + this.case_SSTRING = 1005; + + this._parseConditions = { + INITIAL: 0, + ATTRIBUTE: 1, + ATTRIBUTE_VALUE: 2, + LINKIFY: 4, + A_NODE: 8, + SCRIPT: 16, + STYLE: 32 + }; + + this.condition = this.createInitialCondition(); +} + +WebInspector.SourceHTMLTokenizer.prototype = { + createInitialCondition: function() + { + return { lexCondition: this._lexConditions.INITIAL, parseCondition: this._parseConditions.INITIAL }; + }, + + set line(line) { + if (this._condition.internalJavaScriptTokenizerCondition) { + var match = /<\/script/i.exec(line); + if (match) { + this._internalJavaScriptTokenizer.line = line.substring(0, match.index); + } else + this._internalJavaScriptTokenizer.line = line; + } else if (this._condition.internalCSSTokenizerCondition) { + var match = /<\/style/i.exec(line); + if (match) { + this._internalCSSTokenizer.line = line.substring(0, match.index); + } else + this._internalCSSTokenizer.line = line; + } + this._line = line; + }, + + _isExpectingAttribute: function() + { + return this._condition.parseCondition & this._parseConditions.ATTRIBUTE; + }, + + _isExpectingAttributeValue: function() + { + return this._condition.parseCondition & this._parseConditions.ATTRIBUTE_VALUE; + }, + + _setExpectingAttribute: function() + { + if (this._isExpectingAttributeValue()) + this._condition.parseCondition ^= this._parseConditions.ATTRIBUTE_VALUE; + this._condition.parseCondition |= this._parseConditions.ATTRIBUTE; + }, + + _setExpectingAttributeValue: function() + { + if (this._isExpectingAttribute()) + this._condition.parseCondition ^= this._parseConditions.ATTRIBUTE; + this._condition.parseCondition |= this._parseConditions.ATTRIBUTE_VALUE; + }, + + /** + * @param {boolean=} stringEnds + */ + _stringToken: function(cursor, stringEnds) + { + if (!this._isExpectingAttributeValue()) { + this.tokenType = null; + return cursor; + } + this.tokenType = this._attrValueTokenType(); + if (stringEnds) + this._setExpectingAttribute(); + return cursor; + }, + + _attrValueTokenType: function() + { + if (this._condition.parseCondition & this._parseConditions.LINKIFY) { + if (this._condition.parseCondition & this._parseConditions.A_NODE) + return "html-external-link"; + return "html-resource-link"; + } + return "html-attribute-value"; + }, + + get _internalJavaScriptTokenizer() + { + return WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer("text/javascript"); + }, + + get _internalCSSTokenizer() + { + return WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer("text/css"); + }, + + scriptStarted: function(cursor) + { + this._condition.internalJavaScriptTokenizerCondition = this._internalJavaScriptTokenizer.createInitialCondition(); + }, + + scriptEnded: function(cursor) + { + }, + + styleSheetStarted: function(cursor) + { + this._condition.internalCSSTokenizerCondition = this._internalCSSTokenizer.createInitialCondition(); + }, + + styleSheetEnded: function(cursor) + { + }, + + nextToken: function(cursor) + { + if (this._condition.internalJavaScriptTokenizerCondition) { + // Re-set line to force detection first. + this.line = this._line; + if (cursor !== this._internalJavaScriptTokenizer._line.length) { + // Tokenizer is stateless, so restore its condition before tokenizing and save it after. + this._internalJavaScriptTokenizer.condition = this._condition.internalJavaScriptTokenizerCondition; + var result = this._internalJavaScriptTokenizer.nextToken(cursor); + this.tokenType = this._internalJavaScriptTokenizer.tokenType; + this._condition.internalJavaScriptTokenizerCondition = this._internalJavaScriptTokenizer.condition; + return result; + } else if (cursor !== this._line.length) + delete this._condition.internalJavaScriptTokenizerCondition; + } else if (this._condition.internalCSSTokenizerCondition) { + // Re-set line to force detection first. + this.line = this._line; + if (cursor !== this._internalCSSTokenizer._line.length) { + // Tokenizer is stateless, so restore its condition before tokenizing and save it after. + this._internalCSSTokenizer.condition = this._condition.internalCSSTokenizerCondition; + var result = this._internalCSSTokenizer.nextToken(cursor); + this.tokenType = this._internalCSSTokenizer.tokenType; + this._condition.internalCSSTokenizerCondition = this._internalCSSTokenizer.condition; + return result; + } else if (cursor !== this._line.length) + delete this._condition.internalCSSTokenizerCondition; + } + + var cursorOnEnter = cursor; + var gotoCase = 1; + var YYMARKER; + while (1) { + switch (gotoCase) + // Following comment is replaced with generated state machine. + + { + case 1: var yych; + var yyaccept = 0; + if (this.getLexCondition() < 3) { + if (this.getLexCondition() < 1) { + { gotoCase = this.case_INITIAL; continue; }; + } else { + if (this.getLexCondition() < 2) { + { gotoCase = this.case_COMMENT; continue; }; + } else { + { gotoCase = this.case_DOCTYPE; continue; }; + } + } + } else { + if (this.getLexCondition() < 4) { + { gotoCase = this.case_TAG; continue; }; + } else { + if (this.getLexCondition() < 5) { + { gotoCase = this.case_DSTRING; continue; }; + } else { + { gotoCase = this.case_SSTRING; continue; }; + } + } + } +/* *********************************** */ +case this.case_COMMENT: + + yych = this._charAt(cursor); + if (yych <= '\f') { + if (yych == '\n') { gotoCase = 4; continue; }; + { gotoCase = 3; continue; }; + } else { + if (yych <= '\r') { gotoCase = 4; continue; }; + if (yych == '-') { gotoCase = 6; continue; }; + { gotoCase = 3; continue; }; + } +case 2: + { this.tokenType = "html-comment"; return cursor; } +case 3: + yyaccept = 0; + yych = this._charAt(YYMARKER = ++cursor); + { gotoCase = 9; continue; }; +case 4: + ++cursor; +case 5: + { this.tokenType = null; return cursor; } +case 6: + yyaccept = 1; + yych = this._charAt(YYMARKER = ++cursor); + if (yych != '-') { gotoCase = 5; continue; }; +case 7: + ++cursor; + yych = this._charAt(cursor); + if (yych == '>') { gotoCase = 10; continue; }; +case 8: + yyaccept = 0; + YYMARKER = ++cursor; + yych = this._charAt(cursor); +case 9: + if (yych <= '\f') { + if (yych == '\n') { gotoCase = 2; continue; }; + { gotoCase = 8; continue; }; + } else { + if (yych <= '\r') { gotoCase = 2; continue; }; + if (yych == '-') { gotoCase = 12; continue; }; + { gotoCase = 8; continue; }; + } +case 10: + ++cursor; + this.setLexCondition(this._lexConditions.INITIAL); + { this.tokenType = "html-comment"; return cursor; } +case 12: + ++cursor; + yych = this._charAt(cursor); + if (yych == '-') { gotoCase = 7; continue; }; + cursor = YYMARKER; + if (yyaccept <= 0) { + { gotoCase = 2; continue; }; + } else { + { gotoCase = 5; continue; }; + } +/* *********************************** */ +case this.case_DOCTYPE: + yych = this._charAt(cursor); + if (yych <= '\f') { + if (yych == '\n') { gotoCase = 18; continue; }; + { gotoCase = 17; continue; }; + } else { + if (yych <= '\r') { gotoCase = 18; continue; }; + if (yych == '>') { gotoCase = 20; continue; }; + { gotoCase = 17; continue; }; + } +case 16: + { this.tokenType = "html-doctype"; return cursor; } +case 17: + yych = this._charAt(++cursor); + { gotoCase = 23; continue; }; +case 18: + ++cursor; + { this.tokenType = null; return cursor; } +case 20: + ++cursor; + this.setLexCondition(this._lexConditions.INITIAL); + { this.tokenType = "html-doctype"; return cursor; } +case 22: + ++cursor; + yych = this._charAt(cursor); +case 23: + if (yych <= '\f') { + if (yych == '\n') { gotoCase = 16; continue; }; + { gotoCase = 22; continue; }; + } else { + if (yych <= '\r') { gotoCase = 16; continue; }; + if (yych == '>') { gotoCase = 16; continue; }; + { gotoCase = 22; continue; }; + } +/* *********************************** */ +case this.case_DSTRING: + yych = this._charAt(cursor); + if (yych <= '\f') { + if (yych == '\n') { gotoCase = 28; continue; }; + { gotoCase = 27; continue; }; + } else { + if (yych <= '\r') { gotoCase = 28; continue; }; + if (yych == '"') { gotoCase = 30; continue; }; + { gotoCase = 27; continue; }; + } +case 26: + { return this._stringToken(cursor); } +case 27: + yych = this._charAt(++cursor); + { gotoCase = 34; continue; }; +case 28: + ++cursor; + { this.tokenType = null; return cursor; } +case 30: + ++cursor; +case 31: + this.setLexCondition(this._lexConditions.TAG); + { return this._stringToken(cursor, true); } +case 32: + yych = this._charAt(++cursor); + { gotoCase = 31; continue; }; +case 33: + ++cursor; + yych = this._charAt(cursor); +case 34: + if (yych <= '\f') { + if (yych == '\n') { gotoCase = 26; continue; }; + { gotoCase = 33; continue; }; + } else { + if (yych <= '\r') { gotoCase = 26; continue; }; + if (yych == '"') { gotoCase = 32; continue; }; + { gotoCase = 33; continue; }; + } +/* *********************************** */ +case this.case_INITIAL: + yych = this._charAt(cursor); + if (yych == '<') { gotoCase = 39; continue; }; + ++cursor; + { this.tokenType = null; return cursor; } +case 39: + yyaccept = 0; + yych = this._charAt(YYMARKER = ++cursor); + if (yych <= '/') { + if (yych == '!') { gotoCase = 44; continue; }; + if (yych >= '/') { gotoCase = 41; continue; }; + } else { + if (yych <= 'S') { + if (yych >= 'S') { gotoCase = 42; continue; }; + } else { + if (yych == 's') { gotoCase = 42; continue; }; + } + } +case 40: + this.setLexCondition(this._lexConditions.TAG); + { + if (this._condition.parseCondition & (this._parseConditions.SCRIPT | this._parseConditions.STYLE)) { + // Do not tokenize script and style tag contents, keep lexer state, even though processing "<". + this.setLexCondition(this._lexConditions.INITIAL); + this.tokenType = null; + return cursor; + } + + this._condition.parseCondition = this._parseConditions.INITIAL; + this.tokenType = "html-tag"; + return cursor; + } +case 41: + yyaccept = 0; + yych = this._charAt(YYMARKER = ++cursor); + if (yych == 'S') { gotoCase = 73; continue; }; + if (yych == 's') { gotoCase = 73; continue; }; + { gotoCase = 40; continue; }; +case 42: + yych = this._charAt(++cursor); + if (yych <= 'T') { + if (yych == 'C') { gotoCase = 62; continue; }; + if (yych >= 'T') { gotoCase = 63; continue; }; + } else { + if (yych <= 'c') { + if (yych >= 'c') { gotoCase = 62; continue; }; + } else { + if (yych == 't') { gotoCase = 63; continue; }; + } + } +case 43: + cursor = YYMARKER; + { gotoCase = 40; continue; }; +case 44: + yych = this._charAt(++cursor); + if (yych <= 'C') { + if (yych != '-') { gotoCase = 43; continue; }; + } else { + if (yych <= 'D') { gotoCase = 46; continue; }; + if (yych == 'd') { gotoCase = 46; continue; }; + { gotoCase = 43; continue; }; + } + yych = this._charAt(++cursor); + if (yych == '-') { gotoCase = 54; continue; }; + { gotoCase = 43; continue; }; +case 46: + yych = this._charAt(++cursor); + if (yych == 'O') { gotoCase = 47; continue; }; + if (yych != 'o') { gotoCase = 43; continue; }; +case 47: + yych = this._charAt(++cursor); + if (yych == 'C') { gotoCase = 48; continue; }; + if (yych != 'c') { gotoCase = 43; continue; }; +case 48: + yych = this._charAt(++cursor); + if (yych == 'T') { gotoCase = 49; continue; }; + if (yych != 't') { gotoCase = 43; continue; }; +case 49: + yych = this._charAt(++cursor); + if (yych == 'Y') { gotoCase = 50; continue; }; + if (yych != 'y') { gotoCase = 43; continue; }; +case 50: + yych = this._charAt(++cursor); + if (yych == 'P') { gotoCase = 51; continue; }; + if (yych != 'p') { gotoCase = 43; continue; }; +case 51: + yych = this._charAt(++cursor); + if (yych == 'E') { gotoCase = 52; continue; }; + if (yych != 'e') { gotoCase = 43; continue; }; +case 52: + ++cursor; + this.setLexCondition(this._lexConditions.DOCTYPE); + { this.tokenType = "html-doctype"; return cursor; } +case 54: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '\f') { + if (yych == '\n') { gotoCase = 57; continue; }; + { gotoCase = 54; continue; }; + } else { + if (yych <= '\r') { gotoCase = 57; continue; }; + if (yych != '-') { gotoCase = 54; continue; }; + } + ++cursor; + yych = this._charAt(cursor); + if (yych == '-') { gotoCase = 59; continue; }; + { gotoCase = 43; continue; }; +case 57: + ++cursor; + this.setLexCondition(this._lexConditions.COMMENT); + { this.tokenType = "html-comment"; return cursor; } +case 59: + ++cursor; + yych = this._charAt(cursor); + if (yych != '>') { gotoCase = 54; continue; }; + ++cursor; + { this.tokenType = "html-comment"; return cursor; } +case 62: + yych = this._charAt(++cursor); + if (yych == 'R') { gotoCase = 68; continue; }; + if (yych == 'r') { gotoCase = 68; continue; }; + { gotoCase = 43; continue; }; +case 63: + yych = this._charAt(++cursor); + if (yych == 'Y') { gotoCase = 64; continue; }; + if (yych != 'y') { gotoCase = 43; continue; }; +case 64: + yych = this._charAt(++cursor); + if (yych == 'L') { gotoCase = 65; continue; }; + if (yych != 'l') { gotoCase = 43; continue; }; +case 65: + yych = this._charAt(++cursor); + if (yych == 'E') { gotoCase = 66; continue; }; + if (yych != 'e') { gotoCase = 43; continue; }; +case 66: + ++cursor; + this.setLexCondition(this._lexConditions.TAG); + { + if (this._condition.parseCondition & this._parseConditions.STYLE) { + // Do not tokenize style tag contents, keep lexer state, even though processing "<". + this.setLexCondition(this._lexConditions.INITIAL); + this.tokenType = null; + return cursor; + } + this.tokenType = "html-tag"; + this._condition.parseCondition = this._parseConditions.STYLE; + this._setExpectingAttribute(); + return cursor; + } +case 68: + yych = this._charAt(++cursor); + if (yych == 'I') { gotoCase = 69; continue; }; + if (yych != 'i') { gotoCase = 43; continue; }; +case 69: + yych = this._charAt(++cursor); + if (yych == 'P') { gotoCase = 70; continue; }; + if (yych != 'p') { gotoCase = 43; continue; }; +case 70: + yych = this._charAt(++cursor); + if (yych == 'T') { gotoCase = 71; continue; }; + if (yych != 't') { gotoCase = 43; continue; }; +case 71: + ++cursor; + this.setLexCondition(this._lexConditions.TAG); + { + if (this._condition.parseCondition & this._parseConditions.SCRIPT) { + // Do not tokenize script tag contents, keep lexer state, even though processing "<". + this.setLexCondition(this._lexConditions.INITIAL); + this.tokenType = null; + return cursor; + } + this.tokenType = "html-tag"; + this._condition.parseCondition = this._parseConditions.SCRIPT; + this._setExpectingAttribute(); + return cursor; + } +case 73: + yych = this._charAt(++cursor); + if (yych <= 'T') { + if (yych == 'C') { gotoCase = 75; continue; }; + if (yych <= 'S') { gotoCase = 43; continue; }; + } else { + if (yych <= 'c') { + if (yych <= 'b') { gotoCase = 43; continue; }; + { gotoCase = 75; continue; }; + } else { + if (yych != 't') { gotoCase = 43; continue; }; + } + } + yych = this._charAt(++cursor); + if (yych == 'Y') { gotoCase = 81; continue; }; + if (yych == 'y') { gotoCase = 81; continue; }; + { gotoCase = 43; continue; }; +case 75: + yych = this._charAt(++cursor); + if (yych == 'R') { gotoCase = 76; continue; }; + if (yych != 'r') { gotoCase = 43; continue; }; +case 76: + yych = this._charAt(++cursor); + if (yych == 'I') { gotoCase = 77; continue; }; + if (yych != 'i') { gotoCase = 43; continue; }; +case 77: + yych = this._charAt(++cursor); + if (yych == 'P') { gotoCase = 78; continue; }; + if (yych != 'p') { gotoCase = 43; continue; }; +case 78: + yych = this._charAt(++cursor); + if (yych == 'T') { gotoCase = 79; continue; }; + if (yych != 't') { gotoCase = 43; continue; }; +case 79: + ++cursor; + this.setLexCondition(this._lexConditions.TAG); + { + this.tokenType = "html-tag"; + this._condition.parseCondition = this._parseConditions.INITIAL; + this.scriptEnded(cursor - 8); + return cursor; + } +case 81: + yych = this._charAt(++cursor); + if (yych == 'L') { gotoCase = 82; continue; }; + if (yych != 'l') { gotoCase = 43; continue; }; +case 82: + yych = this._charAt(++cursor); + if (yych == 'E') { gotoCase = 83; continue; }; + if (yych != 'e') { gotoCase = 43; continue; }; +case 83: + ++cursor; + this.setLexCondition(this._lexConditions.TAG); + { + this.tokenType = "html-tag"; + this._condition.parseCondition = this._parseConditions.INITIAL; + this.styleSheetEnded(cursor - 7); + return cursor; + } +/* *********************************** */ +case this.case_SSTRING: + yych = this._charAt(cursor); + if (yych <= '\f') { + if (yych == '\n') { gotoCase = 89; continue; }; + { gotoCase = 88; continue; }; + } else { + if (yych <= '\r') { gotoCase = 89; continue; }; + if (yych == '\'') { gotoCase = 91; continue; }; + { gotoCase = 88; continue; }; + } +case 87: + { return this._stringToken(cursor); } +case 88: + yych = this._charAt(++cursor); + { gotoCase = 95; continue; }; +case 89: + ++cursor; + { this.tokenType = null; return cursor; } +case 91: + ++cursor; +case 92: + this.setLexCondition(this._lexConditions.TAG); + { return this._stringToken(cursor, true); } +case 93: + yych = this._charAt(++cursor); + { gotoCase = 92; continue; }; +case 94: + ++cursor; + yych = this._charAt(cursor); +case 95: + if (yych <= '\f') { + if (yych == '\n') { gotoCase = 87; continue; }; + { gotoCase = 94; continue; }; + } else { + if (yych <= '\r') { gotoCase = 87; continue; }; + if (yych == '\'') { gotoCase = 93; continue; }; + { gotoCase = 94; continue; }; + } +/* *********************************** */ +case this.case_TAG: + yych = this._charAt(cursor); + if (yych <= '&') { + if (yych <= '\r') { + if (yych == '\n') { gotoCase = 100; continue; }; + if (yych >= '\r') { gotoCase = 100; continue; }; + } else { + if (yych <= ' ') { + if (yych >= ' ') { gotoCase = 100; continue; }; + } else { + if (yych == '"') { gotoCase = 102; continue; }; + } + } + } else { + if (yych <= '>') { + if (yych <= ';') { + if (yych <= '\'') { gotoCase = 103; continue; }; + } else { + if (yych <= '<') { gotoCase = 100; continue; }; + if (yych <= '=') { gotoCase = 104; continue; }; + { gotoCase = 106; continue; }; + } + } else { + if (yych <= '[') { + if (yych >= '[') { gotoCase = 100; continue; }; + } else { + if (yych == ']') { gotoCase = 100; continue; }; + } + } + } + ++cursor; + yych = this._charAt(cursor); + { gotoCase = 119; continue; }; +case 99: + { + if (this._condition.parseCondition === this._parseConditions.SCRIPT || this._condition.parseCondition === this._parseConditions.STYLE) { + // Fall through if expecting attributes. + this.tokenType = null; + return cursor; + } + + if (this._condition.parseCondition === this._parseConditions.INITIAL) { + this.tokenType = "html-tag"; + this._setExpectingAttribute(); + var token = this._line.substring(cursorOnEnter, cursor); + if (token === "a") + this._condition.parseCondition |= this._parseConditions.A_NODE; + else if (this._condition.parseCondition & this._parseConditions.A_NODE) + this._condition.parseCondition ^= this._parseConditions.A_NODE; + } else if (this._isExpectingAttribute()) { + var token = this._line.substring(cursorOnEnter, cursor); + if (token === "href" || token === "src") + this._condition.parseCondition |= this._parseConditions.LINKIFY; + else if (this._condition.parseCondition |= this._parseConditions.LINKIFY) + this._condition.parseCondition ^= this._parseConditions.LINKIFY; + this.tokenType = "html-attribute-name"; + } else if (this._isExpectingAttributeValue()) + this.tokenType = this._attrValueTokenType(); + else + this.tokenType = null; + return cursor; + } +case 100: + ++cursor; + { this.tokenType = null; return cursor; } +case 102: + yyaccept = 0; + yych = this._charAt(YYMARKER = ++cursor); + { gotoCase = 115; continue; }; +case 103: + yyaccept = 0; + yych = this._charAt(YYMARKER = ++cursor); + { gotoCase = 109; continue; }; +case 104: + ++cursor; + { + if (this._isExpectingAttribute()) + this._setExpectingAttributeValue(); + this.tokenType = null; + return cursor; + } +case 106: + ++cursor; + this.setLexCondition(this._lexConditions.INITIAL); + { + this.tokenType = "html-tag"; + if (this._condition.parseCondition & this._parseConditions.SCRIPT) { + this.scriptStarted(cursor); + // Do not tokenize script tag contents. + return cursor; + } + + if (this._condition.parseCondition & this._parseConditions.STYLE) { + this.styleSheetStarted(cursor); + // Do not tokenize style tag contents. + return cursor; + } + + this._condition.parseCondition = this._parseConditions.INITIAL; + return cursor; + } +case 108: + ++cursor; + yych = this._charAt(cursor); +case 109: + if (yych <= '\f') { + if (yych != '\n') { gotoCase = 108; continue; }; + } else { + if (yych <= '\r') { gotoCase = 110; continue; }; + if (yych == '\'') { gotoCase = 112; continue; }; + { gotoCase = 108; continue; }; + } +case 110: + ++cursor; + this.setLexCondition(this._lexConditions.SSTRING); + { return this._stringToken(cursor); } +case 112: + ++cursor; + { return this._stringToken(cursor, true); } +case 114: + ++cursor; + yych = this._charAt(cursor); +case 115: + if (yych <= '\f') { + if (yych != '\n') { gotoCase = 114; continue; }; + } else { + if (yych <= '\r') { gotoCase = 116; continue; }; + if (yych == '"') { gotoCase = 112; continue; }; + { gotoCase = 114; continue; }; + } +case 116: + ++cursor; + this.setLexCondition(this._lexConditions.DSTRING); + { return this._stringToken(cursor); } +case 118: + ++cursor; + yych = this._charAt(cursor); +case 119: + if (yych <= '"') { + if (yych <= '\r') { + if (yych == '\n') { gotoCase = 99; continue; }; + if (yych <= '\f') { gotoCase = 118; continue; }; + { gotoCase = 99; continue; }; + } else { + if (yych == ' ') { gotoCase = 99; continue; }; + if (yych <= '!') { gotoCase = 118; continue; }; + { gotoCase = 99; continue; }; + } + } else { + if (yych <= '>') { + if (yych == '\'') { gotoCase = 99; continue; }; + if (yych <= ';') { gotoCase = 118; continue; }; + { gotoCase = 99; continue; }; + } else { + if (yych <= '[') { + if (yych <= 'Z') { gotoCase = 118; continue; }; + { gotoCase = 99; continue; }; + } else { + if (yych == ']') { gotoCase = 99; continue; }; + { gotoCase = 118; continue; }; + } + } + } + } + + } + } +} + +WebInspector.SourceHTMLTokenizer.prototype.__proto__ = WebInspector.SourceTokenizer.prototype; +/* SourceJavaScriptTokenizer.js */ + +/* Generated by re2c 0.13.5 on Fri May 13 20:01:13 2011 */ +/* + * 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. + */ + +// Generate js file as follows: +// +// re2c -isc WebCore/inspector/front-end/SourceJavaScriptTokenizer.re2js \ +// | sed 's|^yy\([^:]*\)*\:|case \1:|' \ +// | sed 's|[*]cursor[+][+]|this._charAt(cursor++)|' \ +// | sed 's|[[*][+][+]cursor|this._charAt(++cursor)|' \ +// | sed 's|[*]cursor|this._charAt(cursor)|' \ +// | sed 's|yych = \*\([^;]*\)|yych = this._charAt\1|' \ +// | sed 's|{ gotoCase = \([^; continue; };]*\)|{ gotoCase = \1; continue; }|' \ +// | sed 's|yych <= \(0x[0-9a-fA-f]+\)|yych <= String.fromCharCode(\1)|' \ +// | sed 's|unsigned\ int|var|' \ +// | sed 's|var\ yych|case 1: case 1: var yych|' + +/** + * @constructor + * @extends {WebInspector.SourceTokenizer} + */ +WebInspector.SourceJavaScriptTokenizer = function() +{ + WebInspector.SourceTokenizer.call(this); + + this._keywords = [ + "null", "true", "false", "break", "case", "catch", "const", "default", "finally", "for", + "instanceof", "new", "var", "continue", "function", "return", "void", "delete", "if", + "this", "do", "while", "else", "in", "switch", "throw", "try", "typeof", "debugger", + "class", "enum", "export", "extends", "import", "super", "get", "set", "with" + ].keySet(); + + this._lexConditions = { + DIV: 0, + NODIV: 1, + COMMENT: 2, + DSTRING: 3, + SSTRING: 4, + REGEX: 5 + }; + + this.case_DIV = 1000; + this.case_NODIV = 1001; + this.case_COMMENT = 1002; + this.case_DSTRING = 1003; + this.case_SSTRING = 1004; + this.case_REGEX = 1005; + + this.condition = this.createInitialCondition(); +} + +WebInspector.SourceJavaScriptTokenizer.prototype = { + createInitialCondition: function() + { + return { lexCondition: this._lexConditions.NODIV }; + }, + + nextToken: function(cursor) + { + var cursorOnEnter = cursor; + var gotoCase = 1; + var YYMARKER; + while (1) { + switch (gotoCase) + // Following comment is replaced with generated state machine. + + { + case 1: var yych; + var yyaccept = 0; + if (this.getLexCondition() < 3) { + if (this.getLexCondition() < 1) { + { gotoCase = this.case_DIV; continue; }; + } else { + if (this.getLexCondition() < 2) { + { gotoCase = this.case_NODIV; continue; }; + } else { + { gotoCase = this.case_COMMENT; continue; }; + } + } + } else { + if (this.getLexCondition() < 4) { + { gotoCase = this.case_DSTRING; continue; }; + } else { + if (this.getLexCondition() < 5) { + { gotoCase = this.case_SSTRING; continue; }; + } else { + { gotoCase = this.case_REGEX; continue; }; + } + } + } +/* *********************************** */ +case this.case_COMMENT: + + yych = this._charAt(cursor); + if (yych <= '\f') { + if (yych == '\n') { gotoCase = 4; continue; }; + { gotoCase = 3; continue; }; + } else { + if (yych <= '\r') { gotoCase = 4; continue; }; + if (yych == '*') { gotoCase = 6; continue; }; + { gotoCase = 3; continue; }; + } +case 2: + { this.tokenType = "javascript-comment"; return cursor; } +case 3: + yyaccept = 0; + yych = this._charAt(YYMARKER = ++cursor); + { gotoCase = 12; continue; }; +case 4: + ++cursor; + { this.tokenType = null; return cursor; } +case 6: + yyaccept = 1; + yych = this._charAt(YYMARKER = ++cursor); + if (yych == '*') { gotoCase = 9; continue; }; + if (yych != '/') { gotoCase = 11; continue; }; +case 7: + ++cursor; + this.setLexCondition(this._lexConditions.NODIV); + { this.tokenType = "javascript-comment"; return cursor; } +case 9: + ++cursor; + yych = this._charAt(cursor); + if (yych == '*') { gotoCase = 9; continue; }; + if (yych == '/') { gotoCase = 7; continue; }; +case 11: + yyaccept = 0; + YYMARKER = ++cursor; + yych = this._charAt(cursor); +case 12: + if (yych <= '\f') { + if (yych == '\n') { gotoCase = 2; continue; }; + { gotoCase = 11; continue; }; + } else { + if (yych <= '\r') { gotoCase = 2; continue; }; + if (yych == '*') { gotoCase = 9; continue; }; + { gotoCase = 11; continue; }; + } +/* *********************************** */ +case this.case_DIV: + yych = this._charAt(cursor); + if (yych <= '9') { + if (yych <= '(') { + if (yych <= '#') { + if (yych <= ' ') { gotoCase = 15; continue; }; + if (yych <= '!') { gotoCase = 17; continue; }; + if (yych <= '"') { gotoCase = 19; continue; }; + } else { + if (yych <= '%') { + if (yych <= '$') { gotoCase = 20; continue; }; + { gotoCase = 22; continue; }; + } else { + if (yych <= '&') { gotoCase = 23; continue; }; + if (yych <= '\'') { gotoCase = 24; continue; }; + { gotoCase = 25; continue; }; + } + } + } else { + if (yych <= ',') { + if (yych <= ')') { gotoCase = 26; continue; }; + if (yych <= '*') { gotoCase = 28; continue; }; + if (yych <= '+') { gotoCase = 29; continue; }; + { gotoCase = 25; continue; }; + } else { + if (yych <= '.') { + if (yych <= '-') { gotoCase = 30; continue; }; + { gotoCase = 31; continue; }; + } else { + if (yych <= '/') { gotoCase = 32; continue; }; + if (yych <= '0') { gotoCase = 34; continue; }; + { gotoCase = 36; continue; }; + } + } + } + } else { + if (yych <= '\\') { + if (yych <= '>') { + if (yych <= ';') { gotoCase = 25; continue; }; + if (yych <= '<') { gotoCase = 37; continue; }; + if (yych <= '=') { gotoCase = 38; continue; }; + { gotoCase = 39; continue; }; + } else { + if (yych <= '@') { + if (yych <= '?') { gotoCase = 25; continue; }; + } else { + if (yych <= 'Z') { gotoCase = 20; continue; }; + if (yych <= '[') { gotoCase = 25; continue; }; + { gotoCase = 40; continue; }; + } + } + } else { + if (yych <= 'z') { + if (yych <= '^') { + if (yych <= ']') { gotoCase = 25; continue; }; + { gotoCase = 41; continue; }; + } else { + if (yych != '`') { gotoCase = 20; continue; }; + } + } else { + if (yych <= '|') { + if (yych <= '{') { gotoCase = 25; continue; }; + { gotoCase = 42; continue; }; + } else { + if (yych <= '~') { gotoCase = 25; continue; }; + if (yych >= 0x80) { gotoCase = 20; continue; }; + } + } + } + } +case 15: + ++cursor; +case 16: + { this.tokenType = null; return cursor; } +case 17: + ++cursor; + if ((yych = this._charAt(cursor)) == '=') { gotoCase = 115; continue; }; +case 18: + this.setLexCondition(this._lexConditions.NODIV); + { this.tokenType = null; return cursor; } +case 19: + yyaccept = 0; + yych = this._charAt(YYMARKER = ++cursor); + if (yych == '\n') { gotoCase = 16; continue; }; + if (yych == '\r') { gotoCase = 16; continue; }; + { gotoCase = 107; continue; }; +case 20: + yyaccept = 1; + yych = this._charAt(YYMARKER = ++cursor); + { gotoCase = 50; continue; }; +case 21: + { + var token = this._line.substring(cursorOnEnter, cursor); + if (this._keywords[token] === true && token !== "__proto__") + this.tokenType = "javascript-keyword"; + else + this.tokenType = "javascript-ident"; + return cursor; + } +case 22: + yych = this._charAt(++cursor); + if (yych == '=') { gotoCase = 43; continue; }; + { gotoCase = 18; continue; }; +case 23: + yych = this._charAt(++cursor); + if (yych == '&') { gotoCase = 43; continue; }; + if (yych == '=') { gotoCase = 43; continue; }; + { gotoCase = 18; continue; }; +case 24: + yyaccept = 0; + yych = this._charAt(YYMARKER = ++cursor); + if (yych == '\n') { gotoCase = 16; continue; }; + if (yych == '\r') { gotoCase = 16; continue; }; + { gotoCase = 96; continue; }; +case 25: + yych = this._charAt(++cursor); + { gotoCase = 18; continue; }; +case 26: + ++cursor; + { this.tokenType = null; return cursor; } +case 28: + yych = this._charAt(++cursor); + if (yych == '=') { gotoCase = 43; continue; }; + { gotoCase = 18; continue; }; +case 29: + yych = this._charAt(++cursor); + if (yych == '+') { gotoCase = 43; continue; }; + if (yych == '=') { gotoCase = 43; continue; }; + { gotoCase = 18; continue; }; +case 30: + yych = this._charAt(++cursor); + if (yych == '-') { gotoCase = 43; continue; }; + if (yych == '=') { gotoCase = 43; continue; }; + { gotoCase = 18; continue; }; +case 31: + yych = this._charAt(++cursor); + if (yych <= '/') { gotoCase = 18; continue; }; + if (yych <= '9') { gotoCase = 89; continue; }; + { gotoCase = 18; continue; }; +case 32: + yyaccept = 2; + yych = this._charAt(YYMARKER = ++cursor); + if (yych <= '.') { + if (yych == '*') { gotoCase = 78; continue; }; + } else { + if (yych <= '/') { gotoCase = 80; continue; }; + if (yych == '=') { gotoCase = 77; continue; }; + } +case 33: + this.setLexCondition(this._lexConditions.NODIV); + { this.tokenType = null; return cursor; } +case 34: + yyaccept = 3; + yych = this._charAt(YYMARKER = ++cursor); + if (yych <= 'E') { + if (yych <= '/') { + if (yych == '.') { gotoCase = 63; continue; }; + } else { + if (yych <= '7') { gotoCase = 72; continue; }; + if (yych >= 'E') { gotoCase = 62; continue; }; + } + } else { + if (yych <= 'd') { + if (yych == 'X') { gotoCase = 74; continue; }; + } else { + if (yych <= 'e') { gotoCase = 62; continue; }; + if (yych == 'x') { gotoCase = 74; continue; }; + } + } +case 35: + { this.tokenType = "javascript-number"; return cursor; } +case 36: + yyaccept = 3; + yych = this._charAt(YYMARKER = ++cursor); + if (yych <= '9') { + if (yych == '.') { gotoCase = 63; continue; }; + if (yych <= '/') { gotoCase = 35; continue; }; + { gotoCase = 60; continue; }; + } else { + if (yych <= 'E') { + if (yych <= 'D') { gotoCase = 35; continue; }; + { gotoCase = 62; continue; }; + } else { + if (yych == 'e') { gotoCase = 62; continue; }; + { gotoCase = 35; continue; }; + } + } +case 37: + yych = this._charAt(++cursor); + if (yych <= ';') { gotoCase = 18; continue; }; + if (yych <= '<') { gotoCase = 59; continue; }; + if (yych <= '=') { gotoCase = 43; continue; }; + { gotoCase = 18; continue; }; +case 38: + yych = this._charAt(++cursor); + if (yych == '=') { gotoCase = 58; continue; }; + { gotoCase = 18; continue; }; +case 39: + yych = this._charAt(++cursor); + if (yych <= '<') { gotoCase = 18; continue; }; + if (yych <= '=') { gotoCase = 43; continue; }; + if (yych <= '>') { gotoCase = 56; continue; }; + { gotoCase = 18; continue; }; +case 40: + yyaccept = 0; + yych = this._charAt(YYMARKER = ++cursor); + if (yych == 'u') { gotoCase = 44; continue; }; + { gotoCase = 16; continue; }; +case 41: + yych = this._charAt(++cursor); + if (yych == '=') { gotoCase = 43; continue; }; + { gotoCase = 18; continue; }; +case 42: + yych = this._charAt(++cursor); + if (yych == '=') { gotoCase = 43; continue; }; + if (yych != '|') { gotoCase = 18; continue; }; +case 43: + yych = this._charAt(++cursor); + { gotoCase = 18; continue; }; +case 44: + yych = this._charAt(++cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 45; continue; }; + if (yych <= '9') { gotoCase = 46; continue; }; + } else { + if (yych <= 'F') { gotoCase = 46; continue; }; + if (yych <= '`') { gotoCase = 45; continue; }; + if (yych <= 'f') { gotoCase = 46; continue; }; + } +case 45: + cursor = YYMARKER; + if (yyaccept <= 1) { + if (yyaccept <= 0) { + { gotoCase = 16; continue; }; + } else { + { gotoCase = 21; continue; }; + } + } else { + if (yyaccept <= 2) { + { gotoCase = 33; continue; }; + } else { + { gotoCase = 35; continue; }; + } + } +case 46: + yych = this._charAt(++cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 45; continue; }; + if (yych >= ':') { gotoCase = 45; continue; }; + } else { + if (yych <= 'F') { gotoCase = 47; continue; }; + if (yych <= '`') { gotoCase = 45; continue; }; + if (yych >= 'g') { gotoCase = 45; continue; }; + } +case 47: + yych = this._charAt(++cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 45; continue; }; + if (yych >= ':') { gotoCase = 45; continue; }; + } else { + if (yych <= 'F') { gotoCase = 48; continue; }; + if (yych <= '`') { gotoCase = 45; continue; }; + if (yych >= 'g') { gotoCase = 45; continue; }; + } +case 48: + yych = this._charAt(++cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 45; continue; }; + if (yych >= ':') { gotoCase = 45; continue; }; + } else { + if (yych <= 'F') { gotoCase = 49; continue; }; + if (yych <= '`') { gotoCase = 45; continue; }; + if (yych >= 'g') { gotoCase = 45; continue; }; + } +case 49: + yyaccept = 1; + YYMARKER = ++cursor; + yych = this._charAt(cursor); +case 50: + if (yych <= '[') { + if (yych <= '/') { + if (yych == '$') { gotoCase = 49; continue; }; + { gotoCase = 21; continue; }; + } else { + if (yych <= '9') { gotoCase = 49; continue; }; + if (yych <= '@') { gotoCase = 21; continue; }; + if (yych <= 'Z') { gotoCase = 49; continue; }; + { gotoCase = 21; continue; }; + } + } else { + if (yych <= '_') { + if (yych <= '\\') { gotoCase = 51; continue; }; + if (yych <= '^') { gotoCase = 21; continue; }; + { gotoCase = 49; continue; }; + } else { + if (yych <= '`') { gotoCase = 21; continue; }; + if (yych <= 'z') { gotoCase = 49; continue; }; + if (yych <= String.fromCharCode(0x7F)) { gotoCase = 21; continue; }; + { gotoCase = 49; continue; }; + } + } +case 51: + ++cursor; + yych = this._charAt(cursor); + if (yych != 'u') { gotoCase = 45; continue; }; + ++cursor; + yych = this._charAt(cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 45; continue; }; + if (yych >= ':') { gotoCase = 45; continue; }; + } else { + if (yych <= 'F') { gotoCase = 53; continue; }; + if (yych <= '`') { gotoCase = 45; continue; }; + if (yych >= 'g') { gotoCase = 45; continue; }; + } +case 53: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 45; continue; }; + if (yych >= ':') { gotoCase = 45; continue; }; + } else { + if (yych <= 'F') { gotoCase = 54; continue; }; + if (yych <= '`') { gotoCase = 45; continue; }; + if (yych >= 'g') { gotoCase = 45; continue; }; + } +case 54: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 45; continue; }; + if (yych >= ':') { gotoCase = 45; continue; }; + } else { + if (yych <= 'F') { gotoCase = 55; continue; }; + if (yych <= '`') { gotoCase = 45; continue; }; + if (yych >= 'g') { gotoCase = 45; continue; }; + } +case 55: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 45; continue; }; + if (yych <= '9') { gotoCase = 49; continue; }; + { gotoCase = 45; continue; }; + } else { + if (yych <= 'F') { gotoCase = 49; continue; }; + if (yych <= '`') { gotoCase = 45; continue; }; + if (yych <= 'f') { gotoCase = 49; continue; }; + { gotoCase = 45; continue; }; + } +case 56: + yych = this._charAt(++cursor); + if (yych <= '<') { gotoCase = 18; continue; }; + if (yych <= '=') { gotoCase = 43; continue; }; + if (yych >= '?') { gotoCase = 18; continue; }; + yych = this._charAt(++cursor); + if (yych == '=') { gotoCase = 43; continue; }; + { gotoCase = 18; continue; }; +case 58: + yych = this._charAt(++cursor); + if (yych == '=') { gotoCase = 43; continue; }; + { gotoCase = 18; continue; }; +case 59: + yych = this._charAt(++cursor); + if (yych == '=') { gotoCase = 43; continue; }; + { gotoCase = 18; continue; }; +case 60: + yyaccept = 3; + YYMARKER = ++cursor; + yych = this._charAt(cursor); + if (yych <= '9') { + if (yych == '.') { gotoCase = 63; continue; }; + if (yych <= '/') { gotoCase = 35; continue; }; + { gotoCase = 60; continue; }; + } else { + if (yych <= 'E') { + if (yych <= 'D') { gotoCase = 35; continue; }; + } else { + if (yych != 'e') { gotoCase = 35; continue; }; + } + } +case 62: + yych = this._charAt(++cursor); + if (yych <= ',') { + if (yych == '+') { gotoCase = 69; continue; }; + { gotoCase = 45; continue; }; + } else { + if (yych <= '-') { gotoCase = 69; continue; }; + if (yych <= '/') { gotoCase = 45; continue; }; + if (yych <= '9') { gotoCase = 70; continue; }; + { gotoCase = 45; continue; }; + } +case 63: + yyaccept = 3; + YYMARKER = ++cursor; + yych = this._charAt(cursor); + if (yych <= 'D') { + if (yych <= '/') { gotoCase = 35; continue; }; + if (yych <= '9') { gotoCase = 63; continue; }; + { gotoCase = 35; continue; }; + } else { + if (yych <= 'E') { gotoCase = 65; continue; }; + if (yych != 'e') { gotoCase = 35; continue; }; + } +case 65: + yych = this._charAt(++cursor); + if (yych <= ',') { + if (yych != '+') { gotoCase = 45; continue; }; + } else { + if (yych <= '-') { gotoCase = 66; continue; }; + if (yych <= '/') { gotoCase = 45; continue; }; + if (yych <= '9') { gotoCase = 67; continue; }; + { gotoCase = 45; continue; }; + } +case 66: + yych = this._charAt(++cursor); + if (yych <= '/') { gotoCase = 45; continue; }; + if (yych >= ':') { gotoCase = 45; continue; }; +case 67: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '/') { gotoCase = 35; continue; }; + if (yych <= '9') { gotoCase = 67; continue; }; + { gotoCase = 35; continue; }; +case 69: + yych = this._charAt(++cursor); + if (yych <= '/') { gotoCase = 45; continue; }; + if (yych >= ':') { gotoCase = 45; continue; }; +case 70: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '/') { gotoCase = 35; continue; }; + if (yych <= '9') { gotoCase = 70; continue; }; + { gotoCase = 35; continue; }; +case 72: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '/') { gotoCase = 35; continue; }; + if (yych <= '7') { gotoCase = 72; continue; }; + { gotoCase = 35; continue; }; +case 74: + yych = this._charAt(++cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 45; continue; }; + if (yych >= ':') { gotoCase = 45; continue; }; + } else { + if (yych <= 'F') { gotoCase = 75; continue; }; + if (yych <= '`') { gotoCase = 45; continue; }; + if (yych >= 'g') { gotoCase = 45; continue; }; + } +case 75: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 35; continue; }; + if (yych <= '9') { gotoCase = 75; continue; }; + { gotoCase = 35; continue; }; + } else { + if (yych <= 'F') { gotoCase = 75; continue; }; + if (yych <= '`') { gotoCase = 35; continue; }; + if (yych <= 'f') { gotoCase = 75; continue; }; + { gotoCase = 35; continue; }; + } +case 77: + yych = this._charAt(++cursor); + { gotoCase = 33; continue; }; +case 78: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '\f') { + if (yych == '\n') { gotoCase = 85; continue; }; + { gotoCase = 78; continue; }; + } else { + if (yych <= '\r') { gotoCase = 85; continue; }; + if (yych == '*') { gotoCase = 83; continue; }; + { gotoCase = 78; continue; }; + } +case 80: + ++cursor; + yych = this._charAt(cursor); + if (yych == '\n') { gotoCase = 82; continue; }; + if (yych != '\r') { gotoCase = 80; continue; }; +case 82: + { this.tokenType = "javascript-comment"; return cursor; } +case 83: + ++cursor; + yych = this._charAt(cursor); + if (yych == '*') { gotoCase = 83; continue; }; + if (yych == '/') { gotoCase = 87; continue; }; + { gotoCase = 78; continue; }; +case 85: + ++cursor; + this.setLexCondition(this._lexConditions.COMMENT); + { this.tokenType = "javascript-comment"; return cursor; } +case 87: + ++cursor; + { this.tokenType = "javascript-comment"; return cursor; } +case 89: + yyaccept = 3; + YYMARKER = ++cursor; + yych = this._charAt(cursor); + if (yych <= 'D') { + if (yych <= '/') { gotoCase = 35; continue; }; + if (yych <= '9') { gotoCase = 89; continue; }; + { gotoCase = 35; continue; }; + } else { + if (yych <= 'E') { gotoCase = 91; continue; }; + if (yych != 'e') { gotoCase = 35; continue; }; + } +case 91: + yych = this._charAt(++cursor); + if (yych <= ',') { + if (yych != '+') { gotoCase = 45; continue; }; + } else { + if (yych <= '-') { gotoCase = 92; continue; }; + if (yych <= '/') { gotoCase = 45; continue; }; + if (yych <= '9') { gotoCase = 93; continue; }; + { gotoCase = 45; continue; }; + } +case 92: + yych = this._charAt(++cursor); + if (yych <= '/') { gotoCase = 45; continue; }; + if (yych >= ':') { gotoCase = 45; continue; }; +case 93: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '/') { gotoCase = 35; continue; }; + if (yych <= '9') { gotoCase = 93; continue; }; + { gotoCase = 35; continue; }; +case 95: + ++cursor; + yych = this._charAt(cursor); +case 96: + if (yych <= '\r') { + if (yych == '\n') { gotoCase = 45; continue; }; + if (yych <= '\f') { gotoCase = 95; continue; }; + { gotoCase = 45; continue; }; + } else { + if (yych <= '\'') { + if (yych <= '&') { gotoCase = 95; continue; }; + { gotoCase = 98; continue; }; + } else { + if (yych != '\\') { gotoCase = 95; continue; }; + } + } + ++cursor; + yych = this._charAt(cursor); + if (yych <= 'a') { + if (yych <= '!') { + if (yych <= '\n') { + if (yych <= '\t') { gotoCase = 45; continue; }; + { gotoCase = 101; continue; }; + } else { + if (yych == '\r') { gotoCase = 101; continue; }; + { gotoCase = 45; continue; }; + } + } else { + if (yych <= '\'') { + if (yych <= '"') { gotoCase = 95; continue; }; + if (yych <= '&') { gotoCase = 45; continue; }; + { gotoCase = 95; continue; }; + } else { + if (yych == '\\') { gotoCase = 95; continue; }; + { gotoCase = 45; continue; }; + } + } + } else { + if (yych <= 'q') { + if (yych <= 'f') { + if (yych <= 'b') { gotoCase = 95; continue; }; + if (yych <= 'e') { gotoCase = 45; continue; }; + { gotoCase = 95; continue; }; + } else { + if (yych == 'n') { gotoCase = 95; continue; }; + { gotoCase = 45; continue; }; + } + } else { + if (yych <= 't') { + if (yych == 's') { gotoCase = 45; continue; }; + { gotoCase = 95; continue; }; + } else { + if (yych <= 'u') { gotoCase = 100; continue; }; + if (yych <= 'v') { gotoCase = 95; continue; }; + { gotoCase = 45; continue; }; + } + } + } +case 98: + ++cursor; + { this.tokenType = "javascript-string"; return cursor; } +case 100: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 45; continue; }; + if (yych <= '9') { gotoCase = 103; continue; }; + { gotoCase = 45; continue; }; + } else { + if (yych <= 'F') { gotoCase = 103; continue; }; + if (yych <= '`') { gotoCase = 45; continue; }; + if (yych <= 'f') { gotoCase = 103; continue; }; + { gotoCase = 45; continue; }; + } +case 101: + ++cursor; + this.setLexCondition(this._lexConditions.SSTRING); + { this.tokenType = "javascript-string"; return cursor; } +case 103: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 45; continue; }; + if (yych >= ':') { gotoCase = 45; continue; }; + } else { + if (yych <= 'F') { gotoCase = 104; continue; }; + if (yych <= '`') { gotoCase = 45; continue; }; + if (yych >= 'g') { gotoCase = 45; continue; }; + } +case 104: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 45; continue; }; + if (yych >= ':') { gotoCase = 45; continue; }; + } else { + if (yych <= 'F') { gotoCase = 105; continue; }; + if (yych <= '`') { gotoCase = 45; continue; }; + if (yych >= 'g') { gotoCase = 45; continue; }; + } +case 105: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 45; continue; }; + if (yych <= '9') { gotoCase = 95; continue; }; + { gotoCase = 45; continue; }; + } else { + if (yych <= 'F') { gotoCase = 95; continue; }; + if (yych <= '`') { gotoCase = 45; continue; }; + if (yych <= 'f') { gotoCase = 95; continue; }; + { gotoCase = 45; continue; }; + } +case 106: + ++cursor; + yych = this._charAt(cursor); +case 107: + if (yych <= '\r') { + if (yych == '\n') { gotoCase = 45; continue; }; + if (yych <= '\f') { gotoCase = 106; continue; }; + { gotoCase = 45; continue; }; + } else { + if (yych <= '"') { + if (yych <= '!') { gotoCase = 106; continue; }; + { gotoCase = 98; continue; }; + } else { + if (yych != '\\') { gotoCase = 106; continue; }; + } + } + ++cursor; + yych = this._charAt(cursor); + if (yych <= 'a') { + if (yych <= '!') { + if (yych <= '\n') { + if (yych <= '\t') { gotoCase = 45; continue; }; + { gotoCase = 110; continue; }; + } else { + if (yych == '\r') { gotoCase = 110; continue; }; + { gotoCase = 45; continue; }; + } + } else { + if (yych <= '\'') { + if (yych <= '"') { gotoCase = 106; continue; }; + if (yych <= '&') { gotoCase = 45; continue; }; + { gotoCase = 106; continue; }; + } else { + if (yych == '\\') { gotoCase = 106; continue; }; + { gotoCase = 45; continue; }; + } + } + } else { + if (yych <= 'q') { + if (yych <= 'f') { + if (yych <= 'b') { gotoCase = 106; continue; }; + if (yych <= 'e') { gotoCase = 45; continue; }; + { gotoCase = 106; continue; }; + } else { + if (yych == 'n') { gotoCase = 106; continue; }; + { gotoCase = 45; continue; }; + } + } else { + if (yych <= 't') { + if (yych == 's') { gotoCase = 45; continue; }; + { gotoCase = 106; continue; }; + } else { + if (yych <= 'u') { gotoCase = 109; continue; }; + if (yych <= 'v') { gotoCase = 106; continue; }; + { gotoCase = 45; continue; }; + } + } + } +case 109: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 45; continue; }; + if (yych <= '9') { gotoCase = 112; continue; }; + { gotoCase = 45; continue; }; + } else { + if (yych <= 'F') { gotoCase = 112; continue; }; + if (yych <= '`') { gotoCase = 45; continue; }; + if (yych <= 'f') { gotoCase = 112; continue; }; + { gotoCase = 45; continue; }; + } +case 110: + ++cursor; + this.setLexCondition(this._lexConditions.DSTRING); + { this.tokenType = "javascript-string"; return cursor; } +case 112: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 45; continue; }; + if (yych >= ':') { gotoCase = 45; continue; }; + } else { + if (yych <= 'F') { gotoCase = 113; continue; }; + if (yych <= '`') { gotoCase = 45; continue; }; + if (yych >= 'g') { gotoCase = 45; continue; }; + } +case 113: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 45; continue; }; + if (yych >= ':') { gotoCase = 45; continue; }; + } else { + if (yych <= 'F') { gotoCase = 114; continue; }; + if (yych <= '`') { gotoCase = 45; continue; }; + if (yych >= 'g') { gotoCase = 45; continue; }; + } +case 114: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 45; continue; }; + if (yych <= '9') { gotoCase = 106; continue; }; + { gotoCase = 45; continue; }; + } else { + if (yych <= 'F') { gotoCase = 106; continue; }; + if (yych <= '`') { gotoCase = 45; continue; }; + if (yych <= 'f') { gotoCase = 106; continue; }; + { gotoCase = 45; continue; }; + } +case 115: + ++cursor; + if ((yych = this._charAt(cursor)) == '=') { gotoCase = 43; continue; }; + { gotoCase = 18; continue; }; +/* *********************************** */ +case this.case_DSTRING: + yych = this._charAt(cursor); + if (yych <= '\r') { + if (yych == '\n') { gotoCase = 120; continue; }; + if (yych <= '\f') { gotoCase = 119; continue; }; + { gotoCase = 120; continue; }; + } else { + if (yych <= '"') { + if (yych <= '!') { gotoCase = 119; continue; }; + { gotoCase = 122; continue; }; + } else { + if (yych == '\\') { gotoCase = 124; continue; }; + { gotoCase = 119; continue; }; + } + } +case 118: + { this.tokenType = "javascript-string"; return cursor; } +case 119: + yyaccept = 0; + yych = this._charAt(YYMARKER = ++cursor); + { gotoCase = 126; continue; }; +case 120: + ++cursor; +case 121: + { this.tokenType = null; return cursor; } +case 122: + ++cursor; +case 123: + this.setLexCondition(this._lexConditions.NODIV); + { this.tokenType = "javascript-string"; return cursor; } +case 124: + yyaccept = 1; + yych = this._charAt(YYMARKER = ++cursor); + if (yych <= 'e') { + if (yych <= '\'') { + if (yych == '"') { gotoCase = 125; continue; }; + if (yych <= '&') { gotoCase = 121; continue; }; + } else { + if (yych <= '\\') { + if (yych <= '[') { gotoCase = 121; continue; }; + } else { + if (yych != 'b') { gotoCase = 121; continue; }; + } + } + } else { + if (yych <= 'r') { + if (yych <= 'm') { + if (yych >= 'g') { gotoCase = 121; continue; }; + } else { + if (yych <= 'n') { gotoCase = 125; continue; }; + if (yych <= 'q') { gotoCase = 121; continue; }; + } + } else { + if (yych <= 't') { + if (yych <= 's') { gotoCase = 121; continue; }; + } else { + if (yych <= 'u') { gotoCase = 127; continue; }; + if (yych >= 'w') { gotoCase = 121; continue; }; + } + } + } +case 125: + yyaccept = 0; + YYMARKER = ++cursor; + yych = this._charAt(cursor); +case 126: + if (yych <= '\r') { + if (yych == '\n') { gotoCase = 118; continue; }; + if (yych <= '\f') { gotoCase = 125; continue; }; + { gotoCase = 118; continue; }; + } else { + if (yych <= '"') { + if (yych <= '!') { gotoCase = 125; continue; }; + { gotoCase = 133; continue; }; + } else { + if (yych == '\\') { gotoCase = 132; continue; }; + { gotoCase = 125; continue; }; + } + } +case 127: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 128; continue; }; + if (yych <= '9') { gotoCase = 129; continue; }; + } else { + if (yych <= 'F') { gotoCase = 129; continue; }; + if (yych <= '`') { gotoCase = 128; continue; }; + if (yych <= 'f') { gotoCase = 129; continue; }; + } +case 128: + cursor = YYMARKER; + if (yyaccept <= 0) { + { gotoCase = 118; continue; }; + } else { + { gotoCase = 121; continue; }; + } +case 129: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 128; continue; }; + if (yych >= ':') { gotoCase = 128; continue; }; + } else { + if (yych <= 'F') { gotoCase = 130; continue; }; + if (yych <= '`') { gotoCase = 128; continue; }; + if (yych >= 'g') { gotoCase = 128; continue; }; + } +case 130: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 128; continue; }; + if (yych >= ':') { gotoCase = 128; continue; }; + } else { + if (yych <= 'F') { gotoCase = 131; continue; }; + if (yych <= '`') { gotoCase = 128; continue; }; + if (yych >= 'g') { gotoCase = 128; continue; }; + } +case 131: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 128; continue; }; + if (yych <= '9') { gotoCase = 125; continue; }; + { gotoCase = 128; continue; }; + } else { + if (yych <= 'F') { gotoCase = 125; continue; }; + if (yych <= '`') { gotoCase = 128; continue; }; + if (yych <= 'f') { gotoCase = 125; continue; }; + { gotoCase = 128; continue; }; + } +case 132: + ++cursor; + yych = this._charAt(cursor); + if (yych <= 'e') { + if (yych <= '\'') { + if (yych == '"') { gotoCase = 125; continue; }; + if (yych <= '&') { gotoCase = 128; continue; }; + { gotoCase = 125; continue; }; + } else { + if (yych <= '\\') { + if (yych <= '[') { gotoCase = 128; continue; }; + { gotoCase = 125; continue; }; + } else { + if (yych == 'b') { gotoCase = 125; continue; }; + { gotoCase = 128; continue; }; + } + } + } else { + if (yych <= 'r') { + if (yych <= 'm') { + if (yych <= 'f') { gotoCase = 125; continue; }; + { gotoCase = 128; continue; }; + } else { + if (yych <= 'n') { gotoCase = 125; continue; }; + if (yych <= 'q') { gotoCase = 128; continue; }; + { gotoCase = 125; continue; }; + } + } else { + if (yych <= 't') { + if (yych <= 's') { gotoCase = 128; continue; }; + { gotoCase = 125; continue; }; + } else { + if (yych <= 'u') { gotoCase = 127; continue; }; + if (yych <= 'v') { gotoCase = 125; continue; }; + { gotoCase = 128; continue; }; + } + } + } +case 133: + ++cursor; + yych = this._charAt(cursor); + { gotoCase = 123; continue; }; +/* *********************************** */ +case this.case_NODIV: + yych = this._charAt(cursor); + if (yych <= '9') { + if (yych <= '(') { + if (yych <= '#') { + if (yych <= ' ') { gotoCase = 136; continue; }; + if (yych <= '!') { gotoCase = 138; continue; }; + if (yych <= '"') { gotoCase = 140; continue; }; + } else { + if (yych <= '%') { + if (yych <= '$') { gotoCase = 141; continue; }; + { gotoCase = 143; continue; }; + } else { + if (yych <= '&') { gotoCase = 144; continue; }; + if (yych <= '\'') { gotoCase = 145; continue; }; + { gotoCase = 146; continue; }; + } + } + } else { + if (yych <= ',') { + if (yych <= ')') { gotoCase = 147; continue; }; + if (yych <= '*') { gotoCase = 149; continue; }; + if (yych <= '+') { gotoCase = 150; continue; }; + { gotoCase = 146; continue; }; + } else { + if (yych <= '.') { + if (yych <= '-') { gotoCase = 151; continue; }; + { gotoCase = 152; continue; }; + } else { + if (yych <= '/') { gotoCase = 153; continue; }; + if (yych <= '0') { gotoCase = 154; continue; }; + { gotoCase = 156; continue; }; + } + } + } + } else { + if (yych <= '\\') { + if (yych <= '>') { + if (yych <= ';') { gotoCase = 146; continue; }; + if (yych <= '<') { gotoCase = 157; continue; }; + if (yych <= '=') { gotoCase = 158; continue; }; + { gotoCase = 159; continue; }; + } else { + if (yych <= '@') { + if (yych <= '?') { gotoCase = 146; continue; }; + } else { + if (yych <= 'Z') { gotoCase = 141; continue; }; + if (yych <= '[') { gotoCase = 146; continue; }; + { gotoCase = 160; continue; }; + } + } + } else { + if (yych <= 'z') { + if (yych <= '^') { + if (yych <= ']') { gotoCase = 146; continue; }; + { gotoCase = 161; continue; }; + } else { + if (yych != '`') { gotoCase = 141; continue; }; + } + } else { + if (yych <= '|') { + if (yych <= '{') { gotoCase = 146; continue; }; + { gotoCase = 162; continue; }; + } else { + if (yych <= '~') { gotoCase = 146; continue; }; + if (yych >= 0x80) { gotoCase = 141; continue; }; + } + } + } + } +case 136: + ++cursor; +case 137: + { this.tokenType = null; return cursor; } +case 138: + ++cursor; + if ((yych = this._charAt(cursor)) == '=') { gotoCase = 260; continue; }; +case 139: + { this.tokenType = null; return cursor; } +case 140: + yyaccept = 0; + yych = this._charAt(YYMARKER = ++cursor); + if (yych == '\n') { gotoCase = 137; continue; }; + if (yych == '\r') { gotoCase = 137; continue; }; + { gotoCase = 252; continue; }; +case 141: + yyaccept = 1; + yych = this._charAt(YYMARKER = ++cursor); + { gotoCase = 170; continue; }; +case 142: + this.setLexCondition(this._lexConditions.DIV); + { + var token = this._line.substring(cursorOnEnter, cursor); + if (this._keywords[token] === true && token !== "__proto__") + this.tokenType = "javascript-keyword"; + else + this.tokenType = "javascript-ident"; + return cursor; + } +case 143: + yych = this._charAt(++cursor); + if (yych == '=') { gotoCase = 163; continue; }; + { gotoCase = 139; continue; }; +case 144: + yych = this._charAt(++cursor); + if (yych == '&') { gotoCase = 163; continue; }; + if (yych == '=') { gotoCase = 163; continue; }; + { gotoCase = 139; continue; }; +case 145: + yyaccept = 0; + yych = this._charAt(YYMARKER = ++cursor); + if (yych == '\n') { gotoCase = 137; continue; }; + if (yych == '\r') { gotoCase = 137; continue; }; + { gotoCase = 241; continue; }; +case 146: + yych = this._charAt(++cursor); + { gotoCase = 139; continue; }; +case 147: + ++cursor; + this.setLexCondition(this._lexConditions.DIV); + { this.tokenType = null; return cursor; } +case 149: + yych = this._charAt(++cursor); + if (yych == '=') { gotoCase = 163; continue; }; + { gotoCase = 139; continue; }; +case 150: + yych = this._charAt(++cursor); + if (yych == '+') { gotoCase = 163; continue; }; + if (yych == '=') { gotoCase = 163; continue; }; + { gotoCase = 139; continue; }; +case 151: + yych = this._charAt(++cursor); + if (yych == '-') { gotoCase = 163; continue; }; + if (yych == '=') { gotoCase = 163; continue; }; + { gotoCase = 139; continue; }; +case 152: + yych = this._charAt(++cursor); + if (yych <= '/') { gotoCase = 139; continue; }; + if (yych <= '9') { gotoCase = 234; continue; }; + { gotoCase = 139; continue; }; +case 153: + yyaccept = 0; + yych = this._charAt(YYMARKER = ++cursor); + if (yych <= '*') { + if (yych <= '\f') { + if (yych == '\n') { gotoCase = 137; continue; }; + { gotoCase = 197; continue; }; + } else { + if (yych <= '\r') { gotoCase = 137; continue; }; + if (yych <= ')') { gotoCase = 197; continue; }; + { gotoCase = 202; continue; }; + } + } else { + if (yych <= 'Z') { + if (yych == '/') { gotoCase = 204; continue; }; + { gotoCase = 197; continue; }; + } else { + if (yych <= '[') { gotoCase = 200; continue; }; + if (yych <= '\\') { gotoCase = 199; continue; }; + if (yych <= ']') { gotoCase = 137; continue; }; + { gotoCase = 197; continue; }; + } + } +case 154: + yyaccept = 2; + yych = this._charAt(YYMARKER = ++cursor); + if (yych <= 'E') { + if (yych <= '/') { + if (yych == '.') { gotoCase = 183; continue; }; + } else { + if (yych <= '7') { gotoCase = 192; continue; }; + if (yych >= 'E') { gotoCase = 182; continue; }; + } + } else { + if (yych <= 'd') { + if (yych == 'X') { gotoCase = 194; continue; }; + } else { + if (yych <= 'e') { gotoCase = 182; continue; }; + if (yych == 'x') { gotoCase = 194; continue; }; + } + } +case 155: + this.setLexCondition(this._lexConditions.DIV); + { this.tokenType = "javascript-number"; return cursor; } +case 156: + yyaccept = 2; + yych = this._charAt(YYMARKER = ++cursor); + if (yych <= '9') { + if (yych == '.') { gotoCase = 183; continue; }; + if (yych <= '/') { gotoCase = 155; continue; }; + { gotoCase = 180; continue; }; + } else { + if (yych <= 'E') { + if (yych <= 'D') { gotoCase = 155; continue; }; + { gotoCase = 182; continue; }; + } else { + if (yych == 'e') { gotoCase = 182; continue; }; + { gotoCase = 155; continue; }; + } + } +case 157: + yych = this._charAt(++cursor); + if (yych <= ';') { gotoCase = 139; continue; }; + if (yych <= '<') { gotoCase = 179; continue; }; + if (yych <= '=') { gotoCase = 163; continue; }; + { gotoCase = 139; continue; }; +case 158: + yych = this._charAt(++cursor); + if (yych == '=') { gotoCase = 178; continue; }; + { gotoCase = 139; continue; }; +case 159: + yych = this._charAt(++cursor); + if (yych <= '<') { gotoCase = 139; continue; }; + if (yych <= '=') { gotoCase = 163; continue; }; + if (yych <= '>') { gotoCase = 176; continue; }; + { gotoCase = 139; continue; }; +case 160: + yyaccept = 0; + yych = this._charAt(YYMARKER = ++cursor); + if (yych == 'u') { gotoCase = 164; continue; }; + { gotoCase = 137; continue; }; +case 161: + yych = this._charAt(++cursor); + if (yych == '=') { gotoCase = 163; continue; }; + { gotoCase = 139; continue; }; +case 162: + yych = this._charAt(++cursor); + if (yych == '=') { gotoCase = 163; continue; }; + if (yych != '|') { gotoCase = 139; continue; }; +case 163: + yych = this._charAt(++cursor); + { gotoCase = 139; continue; }; +case 164: + yych = this._charAt(++cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 165; continue; }; + if (yych <= '9') { gotoCase = 166; continue; }; + } else { + if (yych <= 'F') { gotoCase = 166; continue; }; + if (yych <= '`') { gotoCase = 165; continue; }; + if (yych <= 'f') { gotoCase = 166; continue; }; + } +case 165: + cursor = YYMARKER; + if (yyaccept <= 1) { + if (yyaccept <= 0) { + { gotoCase = 137; continue; }; + } else { + { gotoCase = 142; continue; }; + } + } else { + if (yyaccept <= 2) { + { gotoCase = 155; continue; }; + } else { + { gotoCase = 217; continue; }; + } + } +case 166: + yych = this._charAt(++cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 165; continue; }; + if (yych >= ':') { gotoCase = 165; continue; }; + } else { + if (yych <= 'F') { gotoCase = 167; continue; }; + if (yych <= '`') { gotoCase = 165; continue; }; + if (yych >= 'g') { gotoCase = 165; continue; }; + } +case 167: + yych = this._charAt(++cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 165; continue; }; + if (yych >= ':') { gotoCase = 165; continue; }; + } else { + if (yych <= 'F') { gotoCase = 168; continue; }; + if (yych <= '`') { gotoCase = 165; continue; }; + if (yych >= 'g') { gotoCase = 165; continue; }; + } +case 168: + yych = this._charAt(++cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 165; continue; }; + if (yych >= ':') { gotoCase = 165; continue; }; + } else { + if (yych <= 'F') { gotoCase = 169; continue; }; + if (yych <= '`') { gotoCase = 165; continue; }; + if (yych >= 'g') { gotoCase = 165; continue; }; + } +case 169: + yyaccept = 1; + YYMARKER = ++cursor; + yych = this._charAt(cursor); +case 170: + if (yych <= '[') { + if (yych <= '/') { + if (yych == '$') { gotoCase = 169; continue; }; + { gotoCase = 142; continue; }; + } else { + if (yych <= '9') { gotoCase = 169; continue; }; + if (yych <= '@') { gotoCase = 142; continue; }; + if (yych <= 'Z') { gotoCase = 169; continue; }; + { gotoCase = 142; continue; }; + } + } else { + if (yych <= '_') { + if (yych <= '\\') { gotoCase = 171; continue; }; + if (yych <= '^') { gotoCase = 142; continue; }; + { gotoCase = 169; continue; }; + } else { + if (yych <= '`') { gotoCase = 142; continue; }; + if (yych <= 'z') { gotoCase = 169; continue; }; + if (yych <= String.fromCharCode(0x7F)) { gotoCase = 142; continue; }; + { gotoCase = 169; continue; }; + } + } +case 171: + ++cursor; + yych = this._charAt(cursor); + if (yych != 'u') { gotoCase = 165; continue; }; + ++cursor; + yych = this._charAt(cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 165; continue; }; + if (yych >= ':') { gotoCase = 165; continue; }; + } else { + if (yych <= 'F') { gotoCase = 173; continue; }; + if (yych <= '`') { gotoCase = 165; continue; }; + if (yych >= 'g') { gotoCase = 165; continue; }; + } +case 173: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 165; continue; }; + if (yych >= ':') { gotoCase = 165; continue; }; + } else { + if (yych <= 'F') { gotoCase = 174; continue; }; + if (yych <= '`') { gotoCase = 165; continue; }; + if (yych >= 'g') { gotoCase = 165; continue; }; + } +case 174: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 165; continue; }; + if (yych >= ':') { gotoCase = 165; continue; }; + } else { + if (yych <= 'F') { gotoCase = 175; continue; }; + if (yych <= '`') { gotoCase = 165; continue; }; + if (yych >= 'g') { gotoCase = 165; continue; }; + } +case 175: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 165; continue; }; + if (yych <= '9') { gotoCase = 169; continue; }; + { gotoCase = 165; continue; }; + } else { + if (yych <= 'F') { gotoCase = 169; continue; }; + if (yych <= '`') { gotoCase = 165; continue; }; + if (yych <= 'f') { gotoCase = 169; continue; }; + { gotoCase = 165; continue; }; + } +case 176: + yych = this._charAt(++cursor); + if (yych <= '<') { gotoCase = 139; continue; }; + if (yych <= '=') { gotoCase = 163; continue; }; + if (yych >= '?') { gotoCase = 139; continue; }; + yych = this._charAt(++cursor); + if (yych == '=') { gotoCase = 163; continue; }; + { gotoCase = 139; continue; }; +case 178: + yych = this._charAt(++cursor); + if (yych == '=') { gotoCase = 163; continue; }; + { gotoCase = 139; continue; }; +case 179: + yych = this._charAt(++cursor); + if (yych == '=') { gotoCase = 163; continue; }; + { gotoCase = 139; continue; }; +case 180: + yyaccept = 2; + YYMARKER = ++cursor; + yych = this._charAt(cursor); + if (yych <= '9') { + if (yych == '.') { gotoCase = 183; continue; }; + if (yych <= '/') { gotoCase = 155; continue; }; + { gotoCase = 180; continue; }; + } else { + if (yych <= 'E') { + if (yych <= 'D') { gotoCase = 155; continue; }; + } else { + if (yych != 'e') { gotoCase = 155; continue; }; + } + } +case 182: + yych = this._charAt(++cursor); + if (yych <= ',') { + if (yych == '+') { gotoCase = 189; continue; }; + { gotoCase = 165; continue; }; + } else { + if (yych <= '-') { gotoCase = 189; continue; }; + if (yych <= '/') { gotoCase = 165; continue; }; + if (yych <= '9') { gotoCase = 190; continue; }; + { gotoCase = 165; continue; }; + } +case 183: + yyaccept = 2; + YYMARKER = ++cursor; + yych = this._charAt(cursor); + if (yych <= 'D') { + if (yych <= '/') { gotoCase = 155; continue; }; + if (yych <= '9') { gotoCase = 183; continue; }; + { gotoCase = 155; continue; }; + } else { + if (yych <= 'E') { gotoCase = 185; continue; }; + if (yych != 'e') { gotoCase = 155; continue; }; + } +case 185: + yych = this._charAt(++cursor); + if (yych <= ',') { + if (yych != '+') { gotoCase = 165; continue; }; + } else { + if (yych <= '-') { gotoCase = 186; continue; }; + if (yych <= '/') { gotoCase = 165; continue; }; + if (yych <= '9') { gotoCase = 187; continue; }; + { gotoCase = 165; continue; }; + } +case 186: + yych = this._charAt(++cursor); + if (yych <= '/') { gotoCase = 165; continue; }; + if (yych >= ':') { gotoCase = 165; continue; }; +case 187: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '/') { gotoCase = 155; continue; }; + if (yych <= '9') { gotoCase = 187; continue; }; + { gotoCase = 155; continue; }; +case 189: + yych = this._charAt(++cursor); + if (yych <= '/') { gotoCase = 165; continue; }; + if (yych >= ':') { gotoCase = 165; continue; }; +case 190: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '/') { gotoCase = 155; continue; }; + if (yych <= '9') { gotoCase = 190; continue; }; + { gotoCase = 155; continue; }; +case 192: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '/') { gotoCase = 155; continue; }; + if (yych <= '7') { gotoCase = 192; continue; }; + { gotoCase = 155; continue; }; +case 194: + yych = this._charAt(++cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 165; continue; }; + if (yych >= ':') { gotoCase = 165; continue; }; + } else { + if (yych <= 'F') { gotoCase = 195; continue; }; + if (yych <= '`') { gotoCase = 165; continue; }; + if (yych >= 'g') { gotoCase = 165; continue; }; + } +case 195: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 155; continue; }; + if (yych <= '9') { gotoCase = 195; continue; }; + { gotoCase = 155; continue; }; + } else { + if (yych <= 'F') { gotoCase = 195; continue; }; + if (yych <= '`') { gotoCase = 155; continue; }; + if (yych <= 'f') { gotoCase = 195; continue; }; + { gotoCase = 155; continue; }; + } +case 197: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '.') { + if (yych <= '\n') { + if (yych <= '\t') { gotoCase = 197; continue; }; + { gotoCase = 165; continue; }; + } else { + if (yych == '\r') { gotoCase = 165; continue; }; + { gotoCase = 197; continue; }; + } + } else { + if (yych <= '[') { + if (yych <= '/') { gotoCase = 220; continue; }; + if (yych <= 'Z') { gotoCase = 197; continue; }; + { gotoCase = 228; continue; }; + } else { + if (yych <= '\\') { gotoCase = 227; continue; }; + if (yych <= ']') { gotoCase = 165; continue; }; + { gotoCase = 197; continue; }; + } + } +case 199: + yych = this._charAt(++cursor); + if (yych == '\n') { gotoCase = 165; continue; }; + if (yych == '\r') { gotoCase = 165; continue; }; + { gotoCase = 197; continue; }; +case 200: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '*') { + if (yych <= '\f') { + if (yych == '\n') { gotoCase = 165; continue; }; + { gotoCase = 200; continue; }; + } else { + if (yych <= '\r') { gotoCase = 165; continue; }; + if (yych <= ')') { gotoCase = 200; continue; }; + { gotoCase = 165; continue; }; + } + } else { + if (yych <= '[') { + if (yych == '/') { gotoCase = 165; continue; }; + { gotoCase = 200; continue; }; + } else { + if (yych <= '\\') { gotoCase = 215; continue; }; + if (yych <= ']') { gotoCase = 213; continue; }; + { gotoCase = 200; continue; }; + } + } +case 202: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '\f') { + if (yych == '\n') { gotoCase = 209; continue; }; + { gotoCase = 202; continue; }; + } else { + if (yych <= '\r') { gotoCase = 209; continue; }; + if (yych == '*') { gotoCase = 207; continue; }; + { gotoCase = 202; continue; }; + } +case 204: + ++cursor; + yych = this._charAt(cursor); + if (yych == '\n') { gotoCase = 206; continue; }; + if (yych != '\r') { gotoCase = 204; continue; }; +case 206: + { this.tokenType = "javascript-comment"; return cursor; } +case 207: + ++cursor; + yych = this._charAt(cursor); + if (yych == '*') { gotoCase = 207; continue; }; + if (yych == '/') { gotoCase = 211; continue; }; + { gotoCase = 202; continue; }; +case 209: + ++cursor; + this.setLexCondition(this._lexConditions.COMMENT); + { this.tokenType = "javascript-comment"; return cursor; } +case 211: + ++cursor; + { this.tokenType = "javascript-comment"; return cursor; } +case 213: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '*') { + if (yych <= '\f') { + if (yych == '\n') { gotoCase = 165; continue; }; + { gotoCase = 213; continue; }; + } else { + if (yych <= '\r') { gotoCase = 165; continue; }; + if (yych <= ')') { gotoCase = 213; continue; }; + { gotoCase = 197; continue; }; + } + } else { + if (yych <= 'Z') { + if (yych == '/') { gotoCase = 220; continue; }; + { gotoCase = 213; continue; }; + } else { + if (yych <= '[') { gotoCase = 218; continue; }; + if (yych <= '\\') { gotoCase = 216; continue; }; + { gotoCase = 213; continue; }; + } + } +case 215: + ++cursor; + yych = this._charAt(cursor); + if (yych == '\n') { gotoCase = 165; continue; }; + if (yych == '\r') { gotoCase = 165; continue; }; + { gotoCase = 200; continue; }; +case 216: + yyaccept = 3; + YYMARKER = ++cursor; + yych = this._charAt(cursor); + if (yych == '\n') { gotoCase = 217; continue; }; + if (yych != '\r') { gotoCase = 213; continue; }; +case 217: + this.setLexCondition(this._lexConditions.REGEX); + { this.tokenType = "javascript-regexp"; return cursor; } +case 218: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '*') { + if (yych <= '\f') { + if (yych == '\n') { gotoCase = 165; continue; }; + { gotoCase = 218; continue; }; + } else { + if (yych <= '\r') { gotoCase = 165; continue; }; + if (yych <= ')') { gotoCase = 218; continue; }; + { gotoCase = 165; continue; }; + } + } else { + if (yych <= '[') { + if (yych == '/') { gotoCase = 165; continue; }; + { gotoCase = 218; continue; }; + } else { + if (yych <= '\\') { gotoCase = 225; continue; }; + if (yych <= ']') { gotoCase = 223; continue; }; + { gotoCase = 218; continue; }; + } + } +case 220: + ++cursor; + yych = this._charAt(cursor); + if (yych <= 'h') { + if (yych == 'g') { gotoCase = 220; continue; }; + } else { + if (yych <= 'i') { gotoCase = 220; continue; }; + if (yych == 'm') { gotoCase = 220; continue; }; + } + { this.tokenType = "javascript-regexp"; return cursor; } +case 223: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '*') { + if (yych <= '\f') { + if (yych == '\n') { gotoCase = 165; continue; }; + { gotoCase = 223; continue; }; + } else { + if (yych <= '\r') { gotoCase = 165; continue; }; + if (yych <= ')') { gotoCase = 223; continue; }; + { gotoCase = 197; continue; }; + } + } else { + if (yych <= 'Z') { + if (yych == '/') { gotoCase = 220; continue; }; + { gotoCase = 223; continue; }; + } else { + if (yych <= '[') { gotoCase = 218; continue; }; + if (yych <= '\\') { gotoCase = 226; continue; }; + { gotoCase = 223; continue; }; + } + } +case 225: + ++cursor; + yych = this._charAt(cursor); + if (yych == '\n') { gotoCase = 165; continue; }; + if (yych == '\r') { gotoCase = 165; continue; }; + { gotoCase = 218; continue; }; +case 226: + yyaccept = 3; + YYMARKER = ++cursor; + yych = this._charAt(cursor); + if (yych == '\n') { gotoCase = 217; continue; }; + if (yych == '\r') { gotoCase = 217; continue; }; + { gotoCase = 223; continue; }; +case 227: + yyaccept = 3; + YYMARKER = ++cursor; + yych = this._charAt(cursor); + if (yych == '\n') { gotoCase = 217; continue; }; + if (yych == '\r') { gotoCase = 217; continue; }; + { gotoCase = 197; continue; }; +case 228: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '*') { + if (yych <= '\f') { + if (yych == '\n') { gotoCase = 165; continue; }; + { gotoCase = 228; continue; }; + } else { + if (yych <= '\r') { gotoCase = 165; continue; }; + if (yych <= ')') { gotoCase = 228; continue; }; + { gotoCase = 165; continue; }; + } + } else { + if (yych <= '[') { + if (yych == '/') { gotoCase = 165; continue; }; + { gotoCase = 228; continue; }; + } else { + if (yych <= '\\') { gotoCase = 232; continue; }; + if (yych >= '^') { gotoCase = 228; continue; }; + } + } +case 230: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '*') { + if (yych <= '\f') { + if (yych == '\n') { gotoCase = 165; continue; }; + { gotoCase = 230; continue; }; + } else { + if (yych <= '\r') { gotoCase = 165; continue; }; + if (yych <= ')') { gotoCase = 230; continue; }; + { gotoCase = 197; continue; }; + } + } else { + if (yych <= 'Z') { + if (yych == '/') { gotoCase = 220; continue; }; + { gotoCase = 230; continue; }; + } else { + if (yych <= '[') { gotoCase = 228; continue; }; + if (yych <= '\\') { gotoCase = 233; continue; }; + { gotoCase = 230; continue; }; + } + } +case 232: + ++cursor; + yych = this._charAt(cursor); + if (yych == '\n') { gotoCase = 165; continue; }; + if (yych == '\r') { gotoCase = 165; continue; }; + { gotoCase = 228; continue; }; +case 233: + yyaccept = 3; + YYMARKER = ++cursor; + yych = this._charAt(cursor); + if (yych == '\n') { gotoCase = 217; continue; }; + if (yych == '\r') { gotoCase = 217; continue; }; + { gotoCase = 230; continue; }; +case 234: + yyaccept = 2; + YYMARKER = ++cursor; + yych = this._charAt(cursor); + if (yych <= 'D') { + if (yych <= '/') { gotoCase = 155; continue; }; + if (yych <= '9') { gotoCase = 234; continue; }; + { gotoCase = 155; continue; }; + } else { + if (yych <= 'E') { gotoCase = 236; continue; }; + if (yych != 'e') { gotoCase = 155; continue; }; + } +case 236: + yych = this._charAt(++cursor); + if (yych <= ',') { + if (yych != '+') { gotoCase = 165; continue; }; + } else { + if (yych <= '-') { gotoCase = 237; continue; }; + if (yych <= '/') { gotoCase = 165; continue; }; + if (yych <= '9') { gotoCase = 238; continue; }; + { gotoCase = 165; continue; }; + } +case 237: + yych = this._charAt(++cursor); + if (yych <= '/') { gotoCase = 165; continue; }; + if (yych >= ':') { gotoCase = 165; continue; }; +case 238: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '/') { gotoCase = 155; continue; }; + if (yych <= '9') { gotoCase = 238; continue; }; + { gotoCase = 155; continue; }; +case 240: + ++cursor; + yych = this._charAt(cursor); +case 241: + if (yych <= '\r') { + if (yych == '\n') { gotoCase = 165; continue; }; + if (yych <= '\f') { gotoCase = 240; continue; }; + { gotoCase = 165; continue; }; + } else { + if (yych <= '\'') { + if (yych <= '&') { gotoCase = 240; continue; }; + { gotoCase = 243; continue; }; + } else { + if (yych != '\\') { gotoCase = 240; continue; }; + } + } + ++cursor; + yych = this._charAt(cursor); + if (yych <= 'a') { + if (yych <= '!') { + if (yych <= '\n') { + if (yych <= '\t') { gotoCase = 165; continue; }; + { gotoCase = 246; continue; }; + } else { + if (yych == '\r') { gotoCase = 246; continue; }; + { gotoCase = 165; continue; }; + } + } else { + if (yych <= '\'') { + if (yych <= '"') { gotoCase = 240; continue; }; + if (yych <= '&') { gotoCase = 165; continue; }; + { gotoCase = 240; continue; }; + } else { + if (yych == '\\') { gotoCase = 240; continue; }; + { gotoCase = 165; continue; }; + } + } + } else { + if (yych <= 'q') { + if (yych <= 'f') { + if (yych <= 'b') { gotoCase = 240; continue; }; + if (yych <= 'e') { gotoCase = 165; continue; }; + { gotoCase = 240; continue; }; + } else { + if (yych == 'n') { gotoCase = 240; continue; }; + { gotoCase = 165; continue; }; + } + } else { + if (yych <= 't') { + if (yych == 's') { gotoCase = 165; continue; }; + { gotoCase = 240; continue; }; + } else { + if (yych <= 'u') { gotoCase = 245; continue; }; + if (yych <= 'v') { gotoCase = 240; continue; }; + { gotoCase = 165; continue; }; + } + } + } +case 243: + ++cursor; + { this.tokenType = "javascript-string"; return cursor; } +case 245: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 165; continue; }; + if (yych <= '9') { gotoCase = 248; continue; }; + { gotoCase = 165; continue; }; + } else { + if (yych <= 'F') { gotoCase = 248; continue; }; + if (yych <= '`') { gotoCase = 165; continue; }; + if (yych <= 'f') { gotoCase = 248; continue; }; + { gotoCase = 165; continue; }; + } +case 246: + ++cursor; + this.setLexCondition(this._lexConditions.SSTRING); + { this.tokenType = "javascript-string"; return cursor; } +case 248: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 165; continue; }; + if (yych >= ':') { gotoCase = 165; continue; }; + } else { + if (yych <= 'F') { gotoCase = 249; continue; }; + if (yych <= '`') { gotoCase = 165; continue; }; + if (yych >= 'g') { gotoCase = 165; continue; }; + } +case 249: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 165; continue; }; + if (yych >= ':') { gotoCase = 165; continue; }; + } else { + if (yych <= 'F') { gotoCase = 250; continue; }; + if (yych <= '`') { gotoCase = 165; continue; }; + if (yych >= 'g') { gotoCase = 165; continue; }; + } +case 250: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 165; continue; }; + if (yych <= '9') { gotoCase = 240; continue; }; + { gotoCase = 165; continue; }; + } else { + if (yych <= 'F') { gotoCase = 240; continue; }; + if (yych <= '`') { gotoCase = 165; continue; }; + if (yych <= 'f') { gotoCase = 240; continue; }; + { gotoCase = 165; continue; }; + } +case 251: + ++cursor; + yych = this._charAt(cursor); +case 252: + if (yych <= '\r') { + if (yych == '\n') { gotoCase = 165; continue; }; + if (yych <= '\f') { gotoCase = 251; continue; }; + { gotoCase = 165; continue; }; + } else { + if (yych <= '"') { + if (yych <= '!') { gotoCase = 251; continue; }; + { gotoCase = 243; continue; }; + } else { + if (yych != '\\') { gotoCase = 251; continue; }; + } + } + ++cursor; + yych = this._charAt(cursor); + if (yych <= 'a') { + if (yych <= '!') { + if (yych <= '\n') { + if (yych <= '\t') { gotoCase = 165; continue; }; + { gotoCase = 255; continue; }; + } else { + if (yych == '\r') { gotoCase = 255; continue; }; + { gotoCase = 165; continue; }; + } + } else { + if (yych <= '\'') { + if (yych <= '"') { gotoCase = 251; continue; }; + if (yych <= '&') { gotoCase = 165; continue; }; + { gotoCase = 251; continue; }; + } else { + if (yych == '\\') { gotoCase = 251; continue; }; + { gotoCase = 165; continue; }; + } + } + } else { + if (yych <= 'q') { + if (yych <= 'f') { + if (yych <= 'b') { gotoCase = 251; continue; }; + if (yych <= 'e') { gotoCase = 165; continue; }; + { gotoCase = 251; continue; }; + } else { + if (yych == 'n') { gotoCase = 251; continue; }; + { gotoCase = 165; continue; }; + } + } else { + if (yych <= 't') { + if (yych == 's') { gotoCase = 165; continue; }; + { gotoCase = 251; continue; }; + } else { + if (yych <= 'u') { gotoCase = 254; continue; }; + if (yych <= 'v') { gotoCase = 251; continue; }; + { gotoCase = 165; continue; }; + } + } + } +case 254: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 165; continue; }; + if (yych <= '9') { gotoCase = 257; continue; }; + { gotoCase = 165; continue; }; + } else { + if (yych <= 'F') { gotoCase = 257; continue; }; + if (yych <= '`') { gotoCase = 165; continue; }; + if (yych <= 'f') { gotoCase = 257; continue; }; + { gotoCase = 165; continue; }; + } +case 255: + ++cursor; + this.setLexCondition(this._lexConditions.DSTRING); + { this.tokenType = "javascript-string"; return cursor; } +case 257: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 165; continue; }; + if (yych >= ':') { gotoCase = 165; continue; }; + } else { + if (yych <= 'F') { gotoCase = 258; continue; }; + if (yych <= '`') { gotoCase = 165; continue; }; + if (yych >= 'g') { gotoCase = 165; continue; }; + } +case 258: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 165; continue; }; + if (yych >= ':') { gotoCase = 165; continue; }; + } else { + if (yych <= 'F') { gotoCase = 259; continue; }; + if (yych <= '`') { gotoCase = 165; continue; }; + if (yych >= 'g') { gotoCase = 165; continue; }; + } +case 259: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 165; continue; }; + if (yych <= '9') { gotoCase = 251; continue; }; + { gotoCase = 165; continue; }; + } else { + if (yych <= 'F') { gotoCase = 251; continue; }; + if (yych <= '`') { gotoCase = 165; continue; }; + if (yych <= 'f') { gotoCase = 251; continue; }; + { gotoCase = 165; continue; }; + } +case 260: + ++cursor; + if ((yych = this._charAt(cursor)) == '=') { gotoCase = 163; continue; }; + { gotoCase = 139; continue; }; +/* *********************************** */ +case this.case_REGEX: + yych = this._charAt(cursor); + if (yych <= '.') { + if (yych <= '\n') { + if (yych <= '\t') { gotoCase = 264; continue; }; + { gotoCase = 265; continue; }; + } else { + if (yych == '\r') { gotoCase = 265; continue; }; + { gotoCase = 264; continue; }; + } + } else { + if (yych <= '[') { + if (yych <= '/') { gotoCase = 267; continue; }; + if (yych <= 'Z') { gotoCase = 264; continue; }; + { gotoCase = 269; continue; }; + } else { + if (yych <= '\\') { gotoCase = 270; continue; }; + if (yych <= ']') { gotoCase = 265; continue; }; + { gotoCase = 264; continue; }; + } + } +case 263: + { this.tokenType = "javascript-regexp"; return cursor; } +case 264: + yyaccept = 0; + yych = this._charAt(YYMARKER = ++cursor); + { gotoCase = 272; continue; }; +case 265: + ++cursor; +case 266: + { this.tokenType = null; return cursor; } +case 267: + ++cursor; + yych = this._charAt(cursor); + { gotoCase = 278; continue; }; +case 268: + this.setLexCondition(this._lexConditions.NODIV); + { this.tokenType = "javascript-regexp"; return cursor; } +case 269: + yyaccept = 1; + yych = this._charAt(YYMARKER = ++cursor); + if (yych <= '\r') { + if (yych == '\n') { gotoCase = 266; continue; }; + if (yych <= '\f') { gotoCase = 276; continue; }; + { gotoCase = 266; continue; }; + } else { + if (yych <= '*') { + if (yych <= ')') { gotoCase = 276; continue; }; + { gotoCase = 266; continue; }; + } else { + if (yych == '/') { gotoCase = 266; continue; }; + { gotoCase = 276; continue; }; + } + } +case 270: + yych = this._charAt(++cursor); + if (yych == '\n') { gotoCase = 266; continue; }; + if (yych == '\r') { gotoCase = 266; continue; }; +case 271: + yyaccept = 0; + YYMARKER = ++cursor; + yych = this._charAt(cursor); +case 272: + if (yych <= '.') { + if (yych <= '\n') { + if (yych <= '\t') { gotoCase = 271; continue; }; + { gotoCase = 263; continue; }; + } else { + if (yych == '\r') { gotoCase = 263; continue; }; + { gotoCase = 271; continue; }; + } + } else { + if (yych <= '[') { + if (yych <= '/') { gotoCase = 277; continue; }; + if (yych <= 'Z') { gotoCase = 271; continue; }; + { gotoCase = 275; continue; }; + } else { + if (yych <= '\\') { gotoCase = 273; continue; }; + if (yych <= ']') { gotoCase = 263; continue; }; + { gotoCase = 271; continue; }; + } + } +case 273: + ++cursor; + yych = this._charAt(cursor); + if (yych == '\n') { gotoCase = 274; continue; }; + if (yych != '\r') { gotoCase = 271; continue; }; +case 274: + cursor = YYMARKER; + if (yyaccept <= 0) { + { gotoCase = 263; continue; }; + } else { + { gotoCase = 266; continue; }; + } +case 275: + ++cursor; + yych = this._charAt(cursor); +case 276: + if (yych <= '*') { + if (yych <= '\f') { + if (yych == '\n') { gotoCase = 274; continue; }; + { gotoCase = 275; continue; }; + } else { + if (yych <= '\r') { gotoCase = 274; continue; }; + if (yych <= ')') { gotoCase = 275; continue; }; + { gotoCase = 274; continue; }; + } + } else { + if (yych <= '[') { + if (yych == '/') { gotoCase = 274; continue; }; + { gotoCase = 275; continue; }; + } else { + if (yych <= '\\') { gotoCase = 281; continue; }; + if (yych <= ']') { gotoCase = 279; continue; }; + { gotoCase = 275; continue; }; + } + } +case 277: + ++cursor; + yych = this._charAt(cursor); +case 278: + if (yych <= 'h') { + if (yych == 'g') { gotoCase = 277; continue; }; + { gotoCase = 268; continue; }; + } else { + if (yych <= 'i') { gotoCase = 277; continue; }; + if (yych == 'm') { gotoCase = 277; continue; }; + { gotoCase = 268; continue; }; + } +case 279: + yyaccept = 0; + YYMARKER = ++cursor; + yych = this._charAt(cursor); + if (yych <= '*') { + if (yych <= '\f') { + if (yych == '\n') { gotoCase = 263; continue; }; + { gotoCase = 279; continue; }; + } else { + if (yych <= '\r') { gotoCase = 263; continue; }; + if (yych <= ')') { gotoCase = 279; continue; }; + { gotoCase = 271; continue; }; + } + } else { + if (yych <= 'Z') { + if (yych == '/') { gotoCase = 277; continue; }; + { gotoCase = 279; continue; }; + } else { + if (yych <= '[') { gotoCase = 275; continue; }; + if (yych <= '\\') { gotoCase = 282; continue; }; + { gotoCase = 279; continue; }; + } + } +case 281: + ++cursor; + yych = this._charAt(cursor); + if (yych == '\n') { gotoCase = 274; continue; }; + if (yych == '\r') { gotoCase = 274; continue; }; + { gotoCase = 275; continue; }; +case 282: + ++cursor; + yych = this._charAt(cursor); + if (yych == '\n') { gotoCase = 274; continue; }; + if (yych == '\r') { gotoCase = 274; continue; }; + { gotoCase = 279; continue; }; +/* *********************************** */ +case this.case_SSTRING: + yych = this._charAt(cursor); + if (yych <= '\r') { + if (yych == '\n') { gotoCase = 287; continue; }; + if (yych <= '\f') { gotoCase = 286; continue; }; + { gotoCase = 287; continue; }; + } else { + if (yych <= '\'') { + if (yych <= '&') { gotoCase = 286; continue; }; + { gotoCase = 289; continue; }; + } else { + if (yych == '\\') { gotoCase = 291; continue; }; + { gotoCase = 286; continue; }; + } + } +case 285: + { this.tokenType = "javascript-string"; return cursor; } +case 286: + yyaccept = 0; + yych = this._charAt(YYMARKER = ++cursor); + { gotoCase = 293; continue; }; +case 287: + ++cursor; +case 288: + { this.tokenType = null; return cursor; } +case 289: + ++cursor; +case 290: + this.setLexCondition(this._lexConditions.NODIV); + { this.tokenType = "javascript-string"; return cursor; } +case 291: + yyaccept = 1; + yych = this._charAt(YYMARKER = ++cursor); + if (yych <= 'e') { + if (yych <= '\'') { + if (yych == '"') { gotoCase = 292; continue; }; + if (yych <= '&') { gotoCase = 288; continue; }; + } else { + if (yych <= '\\') { + if (yych <= '[') { gotoCase = 288; continue; }; + } else { + if (yych != 'b') { gotoCase = 288; continue; }; + } + } + } else { + if (yych <= 'r') { + if (yych <= 'm') { + if (yych >= 'g') { gotoCase = 288; continue; }; + } else { + if (yych <= 'n') { gotoCase = 292; continue; }; + if (yych <= 'q') { gotoCase = 288; continue; }; + } + } else { + if (yych <= 't') { + if (yych <= 's') { gotoCase = 288; continue; }; + } else { + if (yych <= 'u') { gotoCase = 294; continue; }; + if (yych >= 'w') { gotoCase = 288; continue; }; + } + } + } +case 292: + yyaccept = 0; + YYMARKER = ++cursor; + yych = this._charAt(cursor); +case 293: + if (yych <= '\r') { + if (yych == '\n') { gotoCase = 285; continue; }; + if (yych <= '\f') { gotoCase = 292; continue; }; + { gotoCase = 285; continue; }; + } else { + if (yych <= '\'') { + if (yych <= '&') { gotoCase = 292; continue; }; + { gotoCase = 300; continue; }; + } else { + if (yych == '\\') { gotoCase = 299; continue; }; + { gotoCase = 292; continue; }; + } + } +case 294: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 295; continue; }; + if (yych <= '9') { gotoCase = 296; continue; }; + } else { + if (yych <= 'F') { gotoCase = 296; continue; }; + if (yych <= '`') { gotoCase = 295; continue; }; + if (yych <= 'f') { gotoCase = 296; continue; }; + } +case 295: + cursor = YYMARKER; + if (yyaccept <= 0) { + { gotoCase = 285; continue; }; + } else { + { gotoCase = 288; continue; }; + } +case 296: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 295; continue; }; + if (yych >= ':') { gotoCase = 295; continue; }; + } else { + if (yych <= 'F') { gotoCase = 297; continue; }; + if (yych <= '`') { gotoCase = 295; continue; }; + if (yych >= 'g') { gotoCase = 295; continue; }; + } +case 297: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 295; continue; }; + if (yych >= ':') { gotoCase = 295; continue; }; + } else { + if (yych <= 'F') { gotoCase = 298; continue; }; + if (yych <= '`') { gotoCase = 295; continue; }; + if (yych >= 'g') { gotoCase = 295; continue; }; + } +case 298: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '@') { + if (yych <= '/') { gotoCase = 295; continue; }; + if (yych <= '9') { gotoCase = 292; continue; }; + { gotoCase = 295; continue; }; + } else { + if (yych <= 'F') { gotoCase = 292; continue; }; + if (yych <= '`') { gotoCase = 295; continue; }; + if (yych <= 'f') { gotoCase = 292; continue; }; + { gotoCase = 295; continue; }; + } +case 299: + ++cursor; + yych = this._charAt(cursor); + if (yych <= 'e') { + if (yych <= '\'') { + if (yych == '"') { gotoCase = 292; continue; }; + if (yych <= '&') { gotoCase = 295; continue; }; + { gotoCase = 292; continue; }; + } else { + if (yych <= '\\') { + if (yych <= '[') { gotoCase = 295; continue; }; + { gotoCase = 292; continue; }; + } else { + if (yych == 'b') { gotoCase = 292; continue; }; + { gotoCase = 295; continue; }; + } + } + } else { + if (yych <= 'r') { + if (yych <= 'm') { + if (yych <= 'f') { gotoCase = 292; continue; }; + { gotoCase = 295; continue; }; + } else { + if (yych <= 'n') { gotoCase = 292; continue; }; + if (yych <= 'q') { gotoCase = 295; continue; }; + { gotoCase = 292; continue; }; + } + } else { + if (yych <= 't') { + if (yych <= 's') { gotoCase = 295; continue; }; + { gotoCase = 292; continue; }; + } else { + if (yych <= 'u') { gotoCase = 294; continue; }; + if (yych <= 'v') { gotoCase = 292; continue; }; + { gotoCase = 295; continue; }; + } + } + } +case 300: + ++cursor; + yych = this._charAt(cursor); + { gotoCase = 290; continue; }; + } + + } + } +} + +WebInspector.SourceJavaScriptTokenizer.prototype.__proto__ = WebInspector.SourceTokenizer.prototype; +/* FontView.js */ + +/* + * 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. + * 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. + */ + +/** + * @extends {WebInspector.ResourceView} + * @constructor + */ +WebInspector.FontView = function(resource) +{ + WebInspector.ResourceView.call(this, resource); + + this.element.addStyleClass("font"); +} + +WebInspector.FontView._fontPreviewLines = [ "ABCDEFGHIJKLM", "NOPQRSTUVWXYZ", "abcdefghijklm", "nopqrstuvwxyz", "1234567890" ]; + +WebInspector.FontView._fontId = 0; + +WebInspector.FontView._measureFontSize = 50; + +WebInspector.FontView.prototype = { + hasContent: function() + { + return true; + }, + + _createContentIfNeeded: function() + { + if (this.fontPreviewElement) + return; + + var uniqueFontName = "WebInspectorFontPreview" + (++WebInspector.FontView._fontId); + + this.fontStyleElement = document.createElement("style"); + this.fontStyleElement.textContent = "@font-face { font-family: \"" + uniqueFontName + "\"; src: url(" + this.resource.url + "); }"; + document.head.appendChild(this.fontStyleElement); + + var fontPreview = document.createElement("div"); + for (var i = 0; i < WebInspector.FontView._fontPreviewLines.length; ++i) { + if (i > 0) + fontPreview.appendChild(document.createElement("br")); + fontPreview.appendChild(document.createTextNode(WebInspector.FontView._fontPreviewLines[i])); + } + this.fontPreviewElement = fontPreview.cloneNode(true); + this.fontPreviewElement.style.setProperty("font-family", uniqueFontName); + this.fontPreviewElement.style.setProperty("visibility", "hidden"); + + this._dummyElement = fontPreview; + this._dummyElement.style.visibility = "hidden"; + this._dummyElement.style.zIndex = "-1"; + this._dummyElement.style.display = "inline"; + this._dummyElement.style.position = "absolute"; + this._dummyElement.style.setProperty("font-family", uniqueFontName); + this._dummyElement.style.setProperty("font-size", WebInspector.FontView._measureFontSize + "px"); + + this.element.appendChild(this.fontPreviewElement); + }, + + wasShown: function() + { + this._createContentIfNeeded(); + + this.updateFontPreviewSize(); + }, + + onResize: function() + { + if (this._inResize) + return; + + this._inResize = true; + try { + this.updateFontPreviewSize(); + } finally { + delete this._inResize; + } + }, + + _measureElement: function() + { + this.element.appendChild(this._dummyElement); + var result = { width: this._dummyElement.offsetWidth, height: this._dummyElement.offsetHeight }; + this.element.removeChild(this._dummyElement); + + return result; + }, + + updateFontPreviewSize: function() + { + if (!this.fontPreviewElement || !this.isShowing()) + return; + + this.fontPreviewElement.style.removeProperty("visibility"); + var dimension = this._measureElement(); + + const height = dimension.height; + const width = dimension.width; + + // Subtract some padding. This should match the paddings in the CSS plus room for the scrollbar. + const containerWidth = this.element.offsetWidth - 50; + const containerHeight = this.element.offsetHeight - 30; + + if (!height || !width || !containerWidth || !containerHeight) { + this.fontPreviewElement.style.removeProperty("font-size"); + return; + } + + var widthRatio = containerWidth / width; + var heightRatio = containerHeight / height; + var finalFontSize = Math.floor(WebInspector.FontView._measureFontSize * Math.min(widthRatio, heightRatio)) - 2; + + this.fontPreviewElement.style.setProperty("font-size", finalFontSize + "px", null); + } +} + +WebInspector.FontView.prototype.__proto__ = WebInspector.ResourceView.prototype; +/* ImageView.js */ + +/* + * 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. + * 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. + */ + +/** + * @extends {WebInspector.ResourceView} + * @constructor + */ +WebInspector.ImageView = function(resource) +{ + WebInspector.ResourceView.call(this, resource); + + this.element.addStyleClass("image"); +} + +WebInspector.ImageView.prototype = { + hasContent: function() + { + return true; + }, + + wasShown: function() + { + this._createContentIfNeeded(); + }, + + _createContentIfNeeded: function() + { + if (this._container) + return; + + var imageContainer = document.createElement("div"); + imageContainer.className = "image"; + this.element.appendChild(imageContainer); + + var imagePreviewElement = document.createElement("img"); + imagePreviewElement.addStyleClass("resource-image-view"); + imageContainer.appendChild(imagePreviewElement); + imagePreviewElement.addEventListener("contextmenu", this._contextMenu.bind(this), true); + + this._container = document.createElement("div"); + this._container.className = "info"; + this.element.appendChild(this._container); + + var imageNameElement = document.createElement("h1"); + imageNameElement.className = "title"; + imageNameElement.textContent = this.resource.displayName; + this._container.appendChild(imageNameElement); + + var infoListElement = document.createElement("dl"); + infoListElement.className = "infoList"; + + this.resource.populateImageSource(imagePreviewElement); + + function onImageLoad() + { + var content = this.resource.content; + if (content) + var resourceSize = this._base64ToSize(content); + else + var resourceSize = this.resource.resourceSize; + + var imageProperties = [ + { name: WebInspector.UIString("Dimensions"), value: WebInspector.UIString("%d × %d", imagePreviewElement.naturalWidth, imagePreviewElement.naturalHeight) }, + { name: WebInspector.UIString("File size"), value: Number.bytesToString(resourceSize) }, + { name: WebInspector.UIString("MIME type"), value: this.resource.mimeType } + ]; + + infoListElement.removeChildren(); + for (var i = 0; i < imageProperties.length; ++i) { + var dt = document.createElement("dt"); + dt.textContent = imageProperties[i].name; + infoListElement.appendChild(dt); + var dd = document.createElement("dd"); + dd.textContent = imageProperties[i].value; + infoListElement.appendChild(dd); + } + var dt = document.createElement("dt"); + dt.textContent = WebInspector.UIString("URL"); + infoListElement.appendChild(dt); + var dd = document.createElement("dd"); + var externalResource = true; + dd.appendChild(WebInspector.linkifyURLAsNode(this.resource.url, undefined, undefined, externalResource)); + infoListElement.appendChild(dd); + + this._container.appendChild(infoListElement); + } + imagePreviewElement.addEventListener("load", onImageLoad.bind(this), false); + }, + + _base64ToSize: function(content) + { + if (!content.length) + return 0; + var size = (content.length || 0) * 3 / 4; + if (content.length > 0 && content[content.length - 1] === "=") + size--; + if (content.length > 1 && content[content.length - 2] === "=") + size--; + return size; + }, + + _contextMenu: function(event) + { + var contextMenu = new WebInspector.ContextMenu(); + contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Copy image URL" : "Copy Image URL"), this._copyImageURL.bind(this)); + contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Open image in new tab" : "Open Image in New Tab"), this._openInNewTab.bind(this)); + contextMenu.show(event); + }, + + _copyImageURL: function(event) + { + InspectorFrontendHost.copyText(this.resource.url); + }, + + _openInNewTab: function(event) + { + InspectorFrontendHost.openInNewTab(this.resource.url); + } +} + +WebInspector.ImageView.prototype.__proto__ = WebInspector.ResourceView.prototype; +/* DatabaseTableView.js */ + +/* + * Copyright (C) 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 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 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. + */ + +/** + * @constructor + * @extends {WebInspector.View} + */ +WebInspector.DatabaseTableView = function(database, tableName) +{ + WebInspector.View.call(this); + + this.database = database; + this.tableName = tableName; + + this.element.addStyleClass("storage-view"); + this.element.addStyleClass("table"); + + this.refreshButton = new WebInspector.StatusBarButton(WebInspector.UIString("Refresh"), "refresh-storage-status-bar-item"); + this.refreshButton.addEventListener("click", this._refreshButtonClicked, this); +} + +WebInspector.DatabaseTableView.prototype = { + wasShown: function() + { + this.update(); + }, + + get statusBarItems() + { + return [this.refreshButton.element]; + }, + + /** + * @param {string} tableName + * @return {string} + */ + _escapeTableName: function(tableName) + { + return tableName.replace(/\"/g, "\"\""); + }, + + update: function() + { + this.database.executeSql("SELECT * FROM \"" + this._escapeTableName(this.tableName) + "\"", this._queryFinished.bind(this), this._queryError.bind(this)); + }, + + _queryFinished: function(columnNames, values) + { + this.detachChildViews(); + this.element.removeChildren(); + + var dataGrid = WebInspector.DataGrid.createSortableDataGrid(columnNames, values); + if (!dataGrid) { + this._emptyView = new WebInspector.EmptyView(WebInspector.UIString("The “%sâ€\ntable is empty.", this.tableName)); + this._emptyView.show(this.element); + return; + } + dataGrid.show(this.element); + dataGrid.autoSizeColumns(5); + }, + + _queryError: function(error) + { + this.detachChildViews(); + this.element.removeChildren(); + + var errorMsgElement = document.createElement("div"); + errorMsgElement.className = "storage-table-error"; + errorMsgElement.textContent = WebInspector.UIString("An error occurred trying to\nread the “%s†table.", this.tableName); + this.element.appendChild(errorMsgElement); + }, + + _refreshButtonClicked: function(event) + { + this.update(); + } +} + +WebInspector.DatabaseTableView.prototype.__proto__ = WebInspector.View.prototype; +/* DatabaseQueryView.js */ + +/* + * Copyright (C) 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 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 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. + */ + +/** + * @constructor + * @extends {WebInspector.View} + */ +WebInspector.DatabaseQueryView = function(database) +{ + WebInspector.View.call(this); + + this.database = database; + + this.element.addStyleClass("storage-view"); + this.element.addStyleClass("query"); + this.element.addStyleClass("monospace"); + this.element.addEventListener("selectstart", this._selectStart.bind(this), false); + + this._promptElement = document.createElement("div"); + this._promptElement.className = "database-query-prompt"; + this._promptElement.appendChild(document.createElement("br")); + this._promptElement.addEventListener("keydown", this._promptKeyDown.bind(this), true); + this.element.appendChild(this._promptElement); + + this.prompt = new WebInspector.TextPromptWithHistory(this.completions.bind(this), " "); + this.prompt.attach(this._promptElement); + + this.element.addEventListener("click", this._messagesClicked.bind(this), true); +} + +WebInspector.DatabaseQueryView.Events = { + SchemaUpdated: "SchemaUpdated" +} + +WebInspector.DatabaseQueryView.prototype = { + _messagesClicked: function() + { + if (!this.prompt.isCaretInsidePrompt() && window.getSelection().isCollapsed) + this.prompt.moveCaretToEndOfPrompt(); + }, + + completions: function(wordRange, force, completionsReadyCallback) + { + var prefix = wordRange.toString().toLowerCase(); + if (!prefix.length && !force) + return; + + var results = []; + + function accumulateMatches(textArray) + { + for (var i = 0; i < textArray.length; ++i) { + var text = textArray[i].toLowerCase(); + if (text.length < prefix.length) + continue; + if (text.indexOf(prefix) !== 0) + continue; + results.push(textArray[i]); + } + } + + function tableNamesCallback(tableNames) + { + accumulateMatches(tableNames.map(function(name) { return name + " " })); + accumulateMatches(["SELECT ", "FROM ", "WHERE ", "LIMIT ", "DELETE FROM ", "CREATE ", "DROP ", "TABLE ", "INDEX ", "UPDATE ", "INSERT INTO ", "VALUES ("]); + + completionsReadyCallback(results); + } + this.database.getTableNames(tableNamesCallback); + }, + + _selectStart: function(event) + { + if (this._selectionTimeout) + clearTimeout(this._selectionTimeout); + + this.prompt.clearAutoComplete(); + + function moveBackIfOutside() + { + delete this._selectionTimeout; + if (!this.prompt.isCaretInsidePrompt() && window.getSelection().isCollapsed) + this.prompt.moveCaretToEndOfPrompt(); + this.prompt.autoCompleteSoon(); + } + + this._selectionTimeout = setTimeout(moveBackIfOutside.bind(this), 100); + }, + + _promptKeyDown: function(event) + { + if (isEnterKey(event)) { + this._enterKeyPressed(event); + return; + } + }, + + _enterKeyPressed: function(event) + { + event.preventDefault(); + event.stopPropagation(); + + this.prompt.clearAutoComplete(true); + + var query = this.prompt.text; + if (!query.length) + return; + + this.prompt.pushHistoryItem(query); + this.prompt.text = ""; + + this.database.executeSql(query, this._queryFinished.bind(this, query), this._queryError.bind(this, query)); + }, + + _queryFinished: function(query, columnNames, values) + { + var dataGrid = WebInspector.DataGrid.createSortableDataGrid(columnNames, values); + var trimmedQuery = query.trim(); + + if (dataGrid) { + dataGrid.element.addStyleClass("inline"); + this._appendViewQueryResult(trimmedQuery, dataGrid); + dataGrid.autoSizeColumns(5); + } + + if (trimmedQuery.match(/^create /i) || trimmedQuery.match(/^drop table /i)) + this.dispatchEventToListeners(WebInspector.DatabaseQueryView.Events.SchemaUpdated, this.database); + }, + + _queryError: function(query, error) + { + if (error.message) + var message = error.message; + else if (error.code == 2) + var message = WebInspector.UIString("Database no longer has expected version."); + else + var message = WebInspector.UIString("An unexpected error %s occurred.", error.code); + + this._appendErrorQueryResult(query, message); + }, + + /** + * @param {string} query + * @param {WebInspector.View} view + */ + _appendViewQueryResult: function(query, view) + { + var resultElement = this._appendQueryResult(query); + view.show(resultElement); + + this._promptElement.scrollIntoView(false); + }, + + /** + * @param {string} query + * @param {string} errorText + */ + _appendErrorQueryResult: function(query, errorText) + { + var resultElement = this._appendQueryResult(query); + resultElement.addStyleClass("error") + resultElement.textContent = errorText; + + this._promptElement.scrollIntoView(false); + }, + + _appendQueryResult: function(query) + { + var element = document.createElement("div"); + element.className = "database-user-query"; + this.element.insertBefore(element, this.prompt.proxyElement); + + var commandTextElement = document.createElement("span"); + commandTextElement.className = "database-query-text"; + commandTextElement.textContent = query; + element.appendChild(commandTextElement); + + var resultElement = document.createElement("div"); + resultElement.className = "database-query-result"; + element.appendChild(resultElement); + return resultElement; + } +} + +WebInspector.DatabaseQueryView.prototype.__proto__ = WebInspector.View.prototype; +/* ProfileLauncherView.js */ + +/* + * Copyright (C) 2011 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. + */ + +/** + * @constructor + * @extends {WebInspector.View} + */ +WebInspector.ProfileLauncherView = function(profilesPanel) +{ + WebInspector.View.call(this); + + this._panel = profilesPanel; + this._profileRunning = false; + this._optionIdPrefix = "profile-type-"; + + this.element.addStyleClass("profile-launcher-view"); + this.element.addStyleClass("panel-enabler-view"); + + this._contentElement = document.createElement("div"); + this._contentElement.className = "profile-launcher-view-content"; + this.element.appendChild(this._contentElement); + + var header = this._contentElement.createChild("h1"); + header.textContent = WebInspector.UIString("Select profiling type"); + + this._profileTypeSelectorForm = this._contentElement.createChild("form"); + this._contentElement.createChild("div", "flexible-space"); + + this._boundProfileTypeChangeListener = this._profileTypeChanged.bind(this); + + this._controlButton = this._contentElement.createChild("button", "control-profiling"); + this._controlButton.addEventListener("click", this._controlButtonClicked.bind(this), false); + this._updateControls(); +} + +WebInspector.ProfileLauncherView.EventTypes = { + ProfileTypeSelected: "profile-type-selected" +} + +WebInspector.ProfileLauncherView.prototype = { + setUpEventListeners: function() + { + this._panel.addEventListener(WebInspector.ProfilesPanel.EventTypes.ProfileStarted, this._onProfileStarted, this); + this._panel.addEventListener(WebInspector.ProfilesPanel.EventTypes.ProfileFinished, this._onProfileFinished, this); + }, + + addProfileType: function(profileType) + { + var checked = !this._profileTypeSelectorForm.children.length; + var labelElement = this._profileTypeSelectorForm.createChild("label"); + labelElement.textContent = profileType.name; + var optionElement = document.createElement("input"); + labelElement.insertBefore(optionElement, labelElement.firstChild); + optionElement.type = "radio"; + optionElement.name = "profile-type"; + var optionId = this._optionIdPrefix + profileType.id; + optionElement.id = optionId; + if (checked) { + optionElement.checked = checked; + this.dispatchEventToListeners(WebInspector.ProfileLauncherView.EventTypes.ProfileTypeSelected, profileType); + } + optionElement.addEventListener("change", this._boundProfileTypeChangeListener, false); + var descriptionElement = labelElement.createChild("p"); + descriptionElement.textContent = profileType.description; + }, + + _controlButtonClicked: function() + { + this._panel.toggleRecordButton(); + }, + + _updateControls: function() + { + if (this._isProfiling) { + this._profileTypeSelectorForm.disabled = true; + this._controlButton.addStyleClass("running"); + this._controlButton.textContent = WebInspector.UIString("Stop"); + } else { + this._profileTypeSelectorForm.disabled = false; + this._controlButton.removeStyleClass("running"); + this._controlButton.textContent = WebInspector.UIString("Start"); + } + }, + + _profileTypeChanged: function(event) + { + var selectedProfileType = this._panel.getProfileType(event.target.id.substring(this._optionIdPrefix.length)); + this.dispatchEventToListeners(WebInspector.ProfileLauncherView.EventTypes.ProfileTypeSelected, selectedProfileType); + }, + + _onProfileStarted: function(event) + { + this._isProfiling = true; + this._updateControls(); + }, + + _onProfileFinished: function(event) + { + this._isProfiling = false; + this._updateControls(); + } +} + +WebInspector.ProfileLauncherView.prototype.__proto__ = WebInspector.View.prototype; +/* ProfileDataGridTree.js */ + +/* + * Copyright (C) 2009 280 North 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 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 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. + */ + +WebInspector.ProfileDataGridNode = function(profileView, profileNode, owningTree, hasChildren) +{ + this.profileView = profileView; + this.profileNode = profileNode; + + WebInspector.DataGridNode.call(this, null, hasChildren); + + this.addEventListener("populate", this._populate, this); + + this.tree = owningTree; + + this.childrenByCallUID = {}; + this.lastComparator = null; + + this.callUID = profileNode.callUID; + this.selfTime = profileNode.selfTime; + this.totalTime = profileNode.totalTime; + this.functionName = profileNode.functionName; + this.numberOfCalls = profileNode.numberOfCalls; + this.url = profileNode.url; +} + +WebInspector.ProfileDataGridNode.prototype = { + get data() + { + function formatMilliseconds(time) + { + return Number.secondsToString(time / 1000, !Capabilities.samplingCPUProfiler); + } + + var data = {}; + + data["function"] = this.functionName; + data["calls"] = this.numberOfCalls; + + if (this.profileView.showSelfTimeAsPercent.get()) + data["self"] = WebInspector.UIString("%.2f%%", this.selfPercent); + else + data["self"] = formatMilliseconds(this.selfTime); + + if (this.profileView.showTotalTimeAsPercent.get()) + data["total"] = WebInspector.UIString("%.2f%%", this.totalPercent); + else + data["total"] = formatMilliseconds(this.totalTime); + + if (this.profileView.showAverageTimeAsPercent.get()) + data["average"] = WebInspector.UIString("%.2f%%", this.averagePercent); + else + data["average"] = formatMilliseconds(this.averageTime); + + return data; + }, + + createCell: function(columnIdentifier) + { + var cell = WebInspector.DataGridNode.prototype.createCell.call(this, columnIdentifier); + + if (columnIdentifier === "self" && this._searchMatchedSelfColumn) + cell.addStyleClass("highlight"); + else if (columnIdentifier === "total" && this._searchMatchedTotalColumn) + cell.addStyleClass("highlight"); + else if (columnIdentifier === "average" && this._searchMatchedAverageColumn) + cell.addStyleClass("highlight"); + else if (columnIdentifier === "calls" && this._searchMatchedCallsColumn) + cell.addStyleClass("highlight"); + + if (columnIdentifier !== "function") + return cell; + + if (this.profileNode._searchMatchedFunctionColumn) + cell.addStyleClass("highlight"); + + if (this.profileNode.url) { + // FIXME(62725): profileNode should reference a debugger location. + var lineNumber = this.profileNode.lineNumber ? this.profileNode.lineNumber - 1 : 0; + var urlElement = this.profileView._linkifier.linkifyLocation(this.profileNode.url, lineNumber, 0, "profile-node-file"); + urlElement.style.maxWidth = "75%"; + cell.insertBefore(urlElement, cell.firstChild); + } + + return cell; + }, + + select: function(supressSelectedEvent) + { + WebInspector.DataGridNode.prototype.select.call(this, supressSelectedEvent); + this.profileView._dataGridNodeSelected(this); + }, + + deselect: function(supressDeselectedEvent) + { + WebInspector.DataGridNode.prototype.deselect.call(this, supressDeselectedEvent); + this.profileView._dataGridNodeDeselected(this); + }, + + sort: function(/*Function*/ comparator, /*Boolean*/ force) + { + var gridNodeGroups = [[this]]; + + for (var gridNodeGroupIndex = 0; gridNodeGroupIndex < gridNodeGroups.length; ++gridNodeGroupIndex) { + var gridNodes = gridNodeGroups[gridNodeGroupIndex]; + var count = gridNodes.length; + + for (var index = 0; index < count; ++index) { + var gridNode = gridNodes[index]; + + // If the grid node is collapsed, then don't sort children (save operation for later). + // If the grid node has the same sorting as previously, then there is no point in sorting it again. + if (!force && (!gridNode.expanded || gridNode.lastComparator === comparator)) { + if (gridNode.children.length) + gridNode.shouldRefreshChildren = true; + continue; + } + + gridNode.lastComparator = comparator; + + var children = gridNode.children; + var childCount = children.length; + + if (childCount) { + children.sort(comparator); + + for (var childIndex = 0; childIndex < childCount; ++childIndex) + children[childIndex]._recalculateSiblings(childIndex); + + gridNodeGroups.push(children); + } + } + } + }, + + insertChild: function(/*ProfileDataGridNode*/ profileDataGridNode, index) + { + WebInspector.DataGridNode.prototype.insertChild.call(this, profileDataGridNode, index); + + this.childrenByCallUID[profileDataGridNode.callUID] = profileDataGridNode; + }, + + removeChild: function(/*ProfileDataGridNode*/ profileDataGridNode) + { + WebInspector.DataGridNode.prototype.removeChild.call(this, profileDataGridNode); + + delete this.childrenByCallUID[profileDataGridNode.callUID]; + }, + + removeChildren: function(/*ProfileDataGridNode*/ profileDataGridNode) + { + WebInspector.DataGridNode.prototype.removeChildren.call(this); + + this.childrenByCallUID = {}; + }, + + findChild: function(/*Node*/ node) + { + if (!node) + return null; + return this.childrenByCallUID[node.callUID]; + }, + + get averageTime() + { + return this.selfTime / Math.max(1, this.numberOfCalls); + }, + + get averagePercent() + { + return this.averageTime / this.tree.totalTime * 100.0; + }, + + get selfPercent() + { + return this.selfTime / this.tree.totalTime * 100.0; + }, + + get totalPercent() + { + return this.totalTime / this.tree.totalTime * 100.0; + }, + + get _parent() + { + return this.parent !== this.dataGrid ? this.parent : this.tree; + }, + + _populate: function(event) + { + this._sharedPopulate(); + + if (this._parent) { + var currentComparator = this._parent.lastComparator; + + if (currentComparator) + this.sort(currentComparator, true); + } + + if (this.removeEventListener) + this.removeEventListener("populate", this._populate, this); + }, + + // When focusing and collapsing we modify lots of nodes in the tree. + // This allows us to restore them all to their original state when we revert. + _save: function() + { + if (this._savedChildren) + return; + + this._savedSelfTime = this.selfTime; + this._savedTotalTime = this.totalTime; + this._savedNumberOfCalls = this.numberOfCalls; + + this._savedChildren = this.children.slice(); + }, + + // When focusing and collapsing we modify lots of nodes in the tree. + // This allows us to restore them all to their original state when we revert. + _restore: function() + { + if (!this._savedChildren) + return; + + this.selfTime = this._savedSelfTime; + this.totalTime = this._savedTotalTime; + this.numberOfCalls = this._savedNumberOfCalls; + + this.removeChildren(); + + var children = this._savedChildren; + var count = children.length; + + for (var index = 0; index < count; ++index) { + children[index]._restore(); + this.appendChild(children[index]); + } + }, + + _merge: function(child, shouldAbsorb) + { + this.selfTime += child.selfTime; + + if (!shouldAbsorb) { + this.totalTime += child.totalTime; + this.numberOfCalls += child.numberOfCalls; + } + + var children = this.children.slice(); + + this.removeChildren(); + + var count = children.length; + + for (var index = 0; index < count; ++index) { + if (!shouldAbsorb || children[index] !== child) + this.appendChild(children[index]); + } + + children = child.children.slice(); + count = children.length; + + for (var index = 0; index < count; ++index) { + var orphanedChild = children[index], + existingChild = this.childrenByCallUID[orphanedChild.callUID]; + + if (existingChild) + existingChild._merge(orphanedChild, false); + else + this.appendChild(orphanedChild); + } + } +} + +WebInspector.ProfileDataGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype; + +WebInspector.ProfileDataGridTree = function(profileView, profileNode) +{ + this.tree = this; + this.children = []; + + this.profileView = profileView; + + this.totalTime = profileNode.totalTime; + this.lastComparator = null; + + this.childrenByCallUID = {}; +} + +WebInspector.ProfileDataGridTree.prototype = { + get expanded() + { + return true; + }, + + appendChild: function(child) + { + this.insertChild(child, this.children.length); + }, + + insertChild: function(child, index) + { + this.children.splice(index, 0, child); + this.childrenByCallUID[child.callUID] = child; + }, + + removeChildren: function() + { + this.children = []; + this.childrenByCallUID = {}; + }, + + findChild: WebInspector.ProfileDataGridNode.prototype.findChild, + sort: WebInspector.ProfileDataGridNode.prototype.sort, + + _save: function() + { + if (this._savedChildren) + return; + + this._savedTotalTime = this.totalTime; + this._savedChildren = this.children.slice(); + }, + + restore: function() + { + if (!this._savedChildren) + return; + + this.children = this._savedChildren; + this.totalTime = this._savedTotalTime; + + var children = this.children; + var count = children.length; + + for (var index = 0; index < count; ++index) + children[index]._restore(); + + this._savedChildren = null; + } +} + +WebInspector.ProfileDataGridTree.propertyComparators = [{}, {}]; + +WebInspector.ProfileDataGridTree.propertyComparator = function(/*String*/ property, /*Boolean*/ isAscending) +{ + var comparator = this.propertyComparators[(isAscending ? 1 : 0)][property]; + + if (!comparator) { + if (isAscending) { + comparator = function(lhs, rhs) + { + if (lhs[property] < rhs[property]) + return -1; + + if (lhs[property] > rhs[property]) + return 1; + + return 0; + } + } else { + comparator = function(lhs, rhs) + { + if (lhs[property] > rhs[property]) + return -1; + + if (lhs[property] < rhs[property]) + return 1; + + return 0; + } + } + + this.propertyComparators[(isAscending ? 1 : 0)][property] = comparator; + } + + return comparator; +} +/* BottomUpProfileDataGridTree.js */ + +/* + * Copyright (C) 2009 280 North 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 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 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. + */ + +// Bottom Up Profiling shows the entire callstack backwards: +// The root node is a representation of each individual function called, and each child of that node represents +// a reverse-callstack showing how many of those calls came from it. So, unlike top-down, the statistics in +// each child still represent the root node. We have to be particularly careful of recursion with this mode +// because a root node can represent itself AND an ancestor. + +WebInspector.BottomUpProfileDataGridNode = function(/*ProfileView*/ profileView, /*ProfileNode*/ profileNode, /*BottomUpProfileDataGridTree*/ owningTree) +{ + WebInspector.ProfileDataGridNode.call(this, profileView, profileNode, owningTree, this._willHaveChildren(profileNode)); + + this._remainingNodeInfos = []; +} + +WebInspector.BottomUpProfileDataGridNode.prototype = { + _takePropertiesFromProfileDataGridNode: function(/*ProfileDataGridNode*/ profileDataGridNode) + { + this._save(); + + this.selfTime = profileDataGridNode.selfTime; + this.totalTime = profileDataGridNode.totalTime; + this.numberOfCalls = profileDataGridNode.numberOfCalls; + }, + + // When focusing, we keep just the members of the callstack. + _keepOnlyChild: function(/*ProfileDataGridNode*/ child) + { + this._save(); + + this.removeChildren(); + this.appendChild(child); + }, + + _exclude: function(aCallUID) + { + if (this._remainingNodeInfos) + this._populate(); + + this._save(); + + var children = this.children; + var index = this.children.length; + + while (index--) + children[index]._exclude(aCallUID); + + var child = this.childrenByCallUID[aCallUID]; + + if (child) + this._merge(child, true); + }, + + _restore: function() + { + WebInspector.ProfileDataGridNode.prototype._restore(); + + if (!this.children.length) + this.hasChildren = this._willHaveChildren(); + }, + + _merge: function(/*ProfileDataGridNode*/ child, /*Boolean*/ shouldAbsorb) + { + this.selfTime -= child.selfTime; + + WebInspector.ProfileDataGridNode.prototype._merge.call(this, child, shouldAbsorb); + }, + + _sharedPopulate: function() + { + var remainingNodeInfos = this._remainingNodeInfos; + var count = remainingNodeInfos.length; + + for (var index = 0; index < count; ++index) { + var nodeInfo = remainingNodeInfos[index]; + var ancestor = nodeInfo.ancestor; + var focusNode = nodeInfo.focusNode; + var child = this.findChild(ancestor); + + // If we already have this child, then merge the data together. + if (child) { + var totalTimeAccountedFor = nodeInfo.totalTimeAccountedFor; + + child.selfTime += focusNode.selfTime; + child.numberOfCalls += focusNode.numberOfCalls; + + if (!totalTimeAccountedFor) + child.totalTime += focusNode.totalTime; + } else { + // If not, add it as a true ancestor. + // In heavy mode, we take our visual identity from ancestor node... + var child = new WebInspector.BottomUpProfileDataGridNode(this.profileView, ancestor, this.tree); + + if (ancestor !== focusNode) { + // but the actual statistics from the "root" node (bottom of the callstack). + child.selfTime = focusNode.selfTime; + child.totalTime = focusNode.totalTime; + child.numberOfCalls = focusNode.numberOfCalls; + } + + this.appendChild(child); + } + + var parent = ancestor.parent; + if (parent && parent.parent) { + nodeInfo.ancestor = parent; + child._remainingNodeInfos.push(nodeInfo); + } + } + + delete this._remainingNodeInfos; + }, + + _willHaveChildren: function(profileNode) + { + profileNode = profileNode || this.profileNode; + // In bottom up mode, our parents are our children since we display an inverted tree. + // However, we don't want to show the very top parent since it is redundant. + return !!(profileNode.parent && profileNode.parent.parent); + } +} + +WebInspector.BottomUpProfileDataGridNode.prototype.__proto__ = WebInspector.ProfileDataGridNode.prototype; + +WebInspector.BottomUpProfileDataGridTree = function(/*ProfileView*/ aProfileView, /*ProfileNode*/ aProfileNode) +{ + WebInspector.ProfileDataGridTree.call(this, aProfileView, aProfileNode); + + // Iterate each node in pre-order. + var profileNodeUIDs = 0; + var profileNodeGroups = [[], [aProfileNode]]; + var visitedProfileNodesForCallUID = {}; + + this._remainingNodeInfos = []; + + for (var profileNodeGroupIndex = 0; profileNodeGroupIndex < profileNodeGroups.length; ++profileNodeGroupIndex) { + var parentProfileNodes = profileNodeGroups[profileNodeGroupIndex]; + var profileNodes = profileNodeGroups[++profileNodeGroupIndex]; + var count = profileNodes.length; + + for (var index = 0; index < count; ++index) { + var profileNode = profileNodes[index]; + + if (!profileNode.UID) + profileNode.UID = ++profileNodeUIDs; + + if (profileNode.head && profileNode !== profileNode.head) { + // The total time of this ancestor is accounted for if we're in any form of recursive cycle. + var visitedNodes = visitedProfileNodesForCallUID[profileNode.callUID]; + var totalTimeAccountedFor = false; + + if (!visitedNodes) { + visitedNodes = {} + visitedProfileNodesForCallUID[profileNode.callUID] = visitedNodes; + } else { + // The total time for this node has already been accounted for iff one of it's parents has already been visited. + // We can do this check in this style because we are traversing the tree in pre-order. + var parentCount = parentProfileNodes.length; + for (var parentIndex = 0; parentIndex < parentCount; ++parentIndex) { + if (visitedNodes[parentProfileNodes[parentIndex].UID]) { + totalTimeAccountedFor = true; + break; + } + } + } + + visitedNodes[profileNode.UID] = true; + + this._remainingNodeInfos.push({ ancestor:profileNode, focusNode:profileNode, totalTimeAccountedFor:totalTimeAccountedFor }); + } + + var children = profileNode.children; + if (children.length) { + profileNodeGroups.push(parentProfileNodes.concat([profileNode])) + profileNodeGroups.push(children); + } + } + } + + // Populate the top level nodes. + WebInspector.BottomUpProfileDataGridNode.prototype._populate.call(this); + + return this; +} + +WebInspector.BottomUpProfileDataGridTree.prototype = { + // When focusing, we keep the entire callstack up to this ancestor. + focus: function(/*ProfileDataGridNode*/ profileDataGridNode) + { + if (!profileDataGridNode) + return; + + this._save(); + + var currentNode = profileDataGridNode; + var focusNode = profileDataGridNode; + + while (currentNode.parent && (currentNode instanceof WebInspector.ProfileDataGridNode)) { + currentNode._takePropertiesFromProfileDataGridNode(profileDataGridNode); + + focusNode = currentNode; + currentNode = currentNode.parent; + + if (currentNode instanceof WebInspector.ProfileDataGridNode) + currentNode._keepOnlyChild(focusNode); + } + + this.children = [focusNode]; + this.totalTime = profileDataGridNode.totalTime; + }, + + exclude: function(/*ProfileDataGridNode*/ profileDataGridNode) + { + if (!profileDataGridNode) + return; + + this._save(); + + var excludedCallUID = profileDataGridNode.callUID; + var excludedTopLevelChild = this.childrenByCallUID[excludedCallUID]; + + // If we have a top level node that is excluded, get rid of it completely (not keeping children), + // since bottom up data relies entirely on the root node. + if (excludedTopLevelChild) + this.children.remove(excludedTopLevelChild); + + var children = this.children; + var count = children.length; + + for (var index = 0; index < count; ++index) + children[index]._exclude(excludedCallUID); + + if (this.lastComparator) + this.sort(this.lastComparator, true); + }, + + _sharedPopulate: WebInspector.BottomUpProfileDataGridNode.prototype._sharedPopulate +} + +WebInspector.BottomUpProfileDataGridTree.prototype.__proto__ = WebInspector.ProfileDataGridTree.prototype; + +/* TopDownProfileDataGridTree.js */ + +/* + * Copyright (C) 2009 280 North 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 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 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. + */ + +WebInspector.TopDownProfileDataGridNode = function(/*ProfileView*/ profileView, /*ProfileNode*/ profileNode, /*TopDownProfileDataGridTree*/ owningTree) +{ + var hasChildren = (profileNode.children && profileNode.children.length); + + WebInspector.ProfileDataGridNode.call(this, profileView, profileNode, owningTree, hasChildren); + + this._remainingChildren = profileNode.children; +} + +WebInspector.TopDownProfileDataGridNode.prototype = { + _sharedPopulate: function() + { + var children = this._remainingChildren; + var childrenLength = children.length; + + for (var i = 0; i < childrenLength; ++i) + this.appendChild(new WebInspector.TopDownProfileDataGridNode(this.profileView, children[i], this.tree)); + + this._remainingChildren = null; + }, + + _exclude: function(aCallUID) + { + if (this._remainingChildren) + this._populate(); + + this._save(); + + var children = this.children; + var index = this.children.length; + + while (index--) + children[index]._exclude(aCallUID); + + var child = this.childrenByCallUID[aCallUID]; + + if (child) + this._merge(child, true); + } +} + +WebInspector.TopDownProfileDataGridNode.prototype.__proto__ = WebInspector.ProfileDataGridNode.prototype; + +WebInspector.TopDownProfileDataGridTree = function(/*ProfileView*/ profileView, /*ProfileNode*/ profileNode) +{ + WebInspector.ProfileDataGridTree.call(this, profileView, profileNode); + + this._remainingChildren = profileNode.children; + + WebInspector.TopDownProfileDataGridNode.prototype._populate.call(this); +} + +WebInspector.TopDownProfileDataGridTree.prototype = { + focus: function(/*ProfileDataGridNode*/ profileDataGrideNode) + { + if (!profileDataGrideNode) + return; + + this._save(); + profileDataGrideNode.savePosition(); + + this.children = [profileDataGrideNode]; + this.totalTime = profileDataGrideNode.totalTime; + }, + + exclude: function(/*ProfileDataGridNode*/ profileDataGrideNode) + { + if (!profileDataGrideNode) + return; + + this._save(); + + var excludedCallUID = profileDataGrideNode.callUID; + + WebInspector.TopDownProfileDataGridNode.prototype._exclude.call(this, excludedCallUID); + + if (this.lastComparator) + this.sort(this.lastComparator, true); + }, + + restore: function() + { + if (!this._savedChildren) + return; + + this.children[0].restorePosition(); + + WebInspector.ProfileDataGridTree.prototype.restore.call(this); + }, + + _merge: WebInspector.TopDownProfileDataGridNode.prototype._merge, + + _sharedPopulate: WebInspector.TopDownProfileDataGridNode.prototype._sharedPopulate +} + +WebInspector.TopDownProfileDataGridTree.prototype.__proto__ = WebInspector.ProfileDataGridTree.prototype; +/* ProfileView.js */ + +/* + * Copyright (C) 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 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 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. + */ + +// FIXME: Rename the file. + +WebInspector.CPUProfileView = function(profile) +{ + WebInspector.View.call(this); + + this.element.addStyleClass("profile-view"); + + this.showSelfTimeAsPercent = WebInspector.settings.createSetting("cpuProfilerShowSelfTimeAsPercent", true); + this.showTotalTimeAsPercent = WebInspector.settings.createSetting("cpuProfilerShowTotalTimeAsPercent", true); + this.showAverageTimeAsPercent = WebInspector.settings.createSetting("cpuProfilerShowAverageTimeAsPercent", true); + this._viewType = WebInspector.settings.createSetting("cpuProfilerView", WebInspector.CPUProfileView._TypeHeavy); + + var columns = { "self": { title: WebInspector.UIString("Self"), width: "72px", sort: "descending", sortable: true }, + "total": { title: WebInspector.UIString("Total"), width: "72px", sortable: true }, + "average": { title: WebInspector.UIString("Average"), width: "72px", sortable: true }, + "calls": { title: WebInspector.UIString("Calls"), width: "54px", sortable: true }, + "function": { title: WebInspector.UIString("Function"), disclosure: true, sortable: true } }; + + if (Capabilities.samplingCPUProfiler) { + delete columns.average; + delete columns.calls; + } + + this.dataGrid = new WebInspector.DataGrid(columns); + this.dataGrid.addEventListener("sorting changed", this._sortData, this); + this.dataGrid.element.addEventListener("mousedown", this._mouseDownInDataGrid.bind(this), true); + this.dataGrid.show(this.element); + + this.viewSelectElement = document.createElement("select"); + this.viewSelectElement.className = "status-bar-item"; + this.viewSelectElement.addEventListener("change", this._changeView.bind(this), false); + + var heavyViewOption = document.createElement("option"); + heavyViewOption.label = WebInspector.UIString("Heavy (Bottom Up)"); + var treeViewOption = document.createElement("option"); + treeViewOption.label = WebInspector.UIString("Tree (Top Down)"); + this.viewSelectElement.appendChild(heavyViewOption); + this.viewSelectElement.appendChild(treeViewOption); + this.viewSelectElement.selectedIndex = this._viewType.get() === WebInspector.CPUProfileView._TypeHeavy ? 0 : 1; + + this.percentButton = new WebInspector.StatusBarButton("", "percent-time-status-bar-item"); + this.percentButton.addEventListener("click", this._percentClicked.bind(this), false); + + this.focusButton = new WebInspector.StatusBarButton(WebInspector.UIString("Focus selected function."), "focus-profile-node-status-bar-item"); + this.focusButton.disabled = true; + this.focusButton.addEventListener("click", this._focusClicked.bind(this), false); + + this.excludeButton = new WebInspector.StatusBarButton(WebInspector.UIString("Exclude selected function."), "exclude-profile-node-status-bar-item"); + this.excludeButton.disabled = true; + this.excludeButton.addEventListener("click", this._excludeClicked.bind(this), false); + + this.resetButton = new WebInspector.StatusBarButton(WebInspector.UIString("Restore all functions."), "reset-profile-status-bar-item"); + this.resetButton.visible = false; + this.resetButton.addEventListener("click", this._resetClicked.bind(this), false); + + this.profile = profile; + + function profileCallback(error, profile) + { + if (error) + return; + + if (!profile.head) { + // Profiling was tentatively terminated with the "Clear all profiles." button. + return; + } + this.profile.head = profile.head; + this._assignParentsInProfile(); + this._changeView(); + this._updatePercentButton(); + } + + this._linkifier = WebInspector.debuggerPresentationModel.createLinkifier(new WebInspector.DebuggerPresentationModel.DefaultLinkifierFormatter(30)); + + ProfilerAgent.getProfile(this.profile.typeId, this.profile.uid, profileCallback.bind(this)); +} + +WebInspector.CPUProfileView._TypeTree = "Tree"; +WebInspector.CPUProfileView._TypeHeavy = "Heavy"; + +WebInspector.CPUProfileView.prototype = { + get statusBarItems() + { + return [this.viewSelectElement, this.percentButton.element, this.focusButton.element, this.excludeButton.element, this.resetButton.element]; + }, + + get profile() + { + return this._profile; + }, + + set profile(profile) + { + this._profile = profile; + }, + + get bottomUpProfileDataGridTree() + { + if (!this._bottomUpProfileDataGridTree) { + if (this.profile.bottomUpHead) + this._bottomUpProfileDataGridTree = new WebInspector.TopDownProfileDataGridTree(this, this.profile.bottomUpHead); + else + this._bottomUpProfileDataGridTree = new WebInspector.BottomUpProfileDataGridTree(this, this.profile.head); + } + return this._bottomUpProfileDataGridTree; + }, + + get topDownProfileDataGridTree() + { + if (!this._topDownProfileDataGridTree) + this._topDownProfileDataGridTree = new WebInspector.TopDownProfileDataGridTree(this, this.profile.head); + return this._topDownProfileDataGridTree; + }, + + get currentTree() + { + return this._currentTree; + }, + + set currentTree(tree) + { + this._currentTree = tree; + this.refresh(); + }, + + get topDownTree() + { + if (!this._topDownTree) { + this._topDownTree = WebInspector.TopDownTreeFactory.create(this.profile.head); + this._sortProfile(this._topDownTree); + } + + return this._topDownTree; + }, + + get bottomUpTree() + { + if (!this._bottomUpTree) { + this._bottomUpTree = WebInspector.BottomUpTreeFactory.create(this.profile.head); + this._sortProfile(this._bottomUpTree); + } + + return this._bottomUpTree; + }, + + willHide: function() + { + this._currentSearchResultIndex = -1; + }, + + refresh: function() + { + var selectedProfileNode = this.dataGrid.selectedNode ? this.dataGrid.selectedNode.profileNode : null; + + this.dataGrid.removeChildren(); + + var children = this.profileDataGridTree.children; + var count = children.length; + + for (var index = 0; index < count; ++index) + this.dataGrid.appendChild(children[index]); + + if (selectedProfileNode) + selectedProfileNode.selected = true; + }, + + refreshVisibleData: function() + { + var child = this.dataGrid.children[0]; + while (child) { + child.refresh(); + child = child.traverseNextNode(false, null, true); + } + }, + + refreshShowAsPercents: function() + { + this._updatePercentButton(); + this.refreshVisibleData(); + }, + + searchCanceled: function() + { + if (this._searchResults) { + for (var i = 0; i < this._searchResults.length; ++i) { + var profileNode = this._searchResults[i].profileNode; + + delete profileNode._searchMatchedSelfColumn; + delete profileNode._searchMatchedTotalColumn; + delete profileNode._searchMatchedCallsColumn; + delete profileNode._searchMatchedFunctionColumn; + + profileNode.refresh(); + } + } + + delete this._searchFinishedCallback; + this._currentSearchResultIndex = -1; + this._searchResults = []; + }, + + performSearch: function(query, finishedCallback) + { + // Call searchCanceled since it will reset everything we need before doing a new search. + this.searchCanceled(); + + query = query.trim(); + + if (!query.length) + return; + + this._searchFinishedCallback = finishedCallback; + + var greaterThan = (query.indexOf(">") === 0); + var lessThan = (query.indexOf("<") === 0); + var equalTo = (query.indexOf("=") === 0 || ((greaterThan || lessThan) && query.indexOf("=") === 1)); + var percentUnits = (query.lastIndexOf("%") === (query.length - 1)); + var millisecondsUnits = (query.length > 2 && query.lastIndexOf("ms") === (query.length - 2)); + var secondsUnits = (!millisecondsUnits && query.lastIndexOf("s") === (query.length - 1)); + + var queryNumber = parseFloat(query); + if (greaterThan || lessThan || equalTo) { + if (equalTo && (greaterThan || lessThan)) + queryNumber = parseFloat(query.substring(2)); + else + queryNumber = parseFloat(query.substring(1)); + } + + var queryNumberMilliseconds = (secondsUnits ? (queryNumber * 1000) : queryNumber); + + // Make equalTo implicitly true if it wasn't specified there is no other operator. + if (!isNaN(queryNumber) && !(greaterThan || lessThan)) + equalTo = true; + + function matchesQuery(/*ProfileDataGridNode*/ profileDataGridNode) + { + delete profileDataGridNode._searchMatchedSelfColumn; + delete profileDataGridNode._searchMatchedTotalColumn; + delete profileDataGridNode._searchMatchedAverageColumn; + delete profileDataGridNode._searchMatchedCallsColumn; + delete profileDataGridNode._searchMatchedFunctionColumn; + + if (percentUnits) { + if (lessThan) { + if (profileDataGridNode.selfPercent < queryNumber) + profileDataGridNode._searchMatchedSelfColumn = true; + if (profileDataGridNode.totalPercent < queryNumber) + profileDataGridNode._searchMatchedTotalColumn = true; + if (profileDataGridNode.averagePercent < queryNumberMilliseconds) + profileDataGridNode._searchMatchedAverageColumn = true; + } else if (greaterThan) { + if (profileDataGridNode.selfPercent > queryNumber) + profileDataGridNode._searchMatchedSelfColumn = true; + if (profileDataGridNode.totalPercent > queryNumber) + profileDataGridNode._searchMatchedTotalColumn = true; + if (profileDataGridNode.averagePercent < queryNumberMilliseconds) + profileDataGridNode._searchMatchedAverageColumn = true; + } + + if (equalTo) { + if (profileDataGridNode.selfPercent == queryNumber) + profileDataGridNode._searchMatchedSelfColumn = true; + if (profileDataGridNode.totalPercent == queryNumber) + profileDataGridNode._searchMatchedTotalColumn = true; + if (profileDataGridNode.averagePercent < queryNumberMilliseconds) + profileDataGridNode._searchMatchedAverageColumn = true; + } + } else if (millisecondsUnits || secondsUnits) { + if (lessThan) { + if (profileDataGridNode.selfTime < queryNumberMilliseconds) + profileDataGridNode._searchMatchedSelfColumn = true; + if (profileDataGridNode.totalTime < queryNumberMilliseconds) + profileDataGridNode._searchMatchedTotalColumn = true; + if (profileDataGridNode.averageTime < queryNumberMilliseconds) + profileDataGridNode._searchMatchedAverageColumn = true; + } else if (greaterThan) { + if (profileDataGridNode.selfTime > queryNumberMilliseconds) + profileDataGridNode._searchMatchedSelfColumn = true; + if (profileDataGridNode.totalTime > queryNumberMilliseconds) + profileDataGridNode._searchMatchedTotalColumn = true; + if (profileDataGridNode.averageTime > queryNumberMilliseconds) + profileDataGridNode._searchMatchedAverageColumn = true; + } + + if (equalTo) { + if (profileDataGridNode.selfTime == queryNumberMilliseconds) + profileDataGridNode._searchMatchedSelfColumn = true; + if (profileDataGridNode.totalTime == queryNumberMilliseconds) + profileDataGridNode._searchMatchedTotalColumn = true; + if (profileDataGridNode.averageTime == queryNumberMilliseconds) + profileDataGridNode._searchMatchedAverageColumn = true; + } + } else { + if (equalTo && profileDataGridNode.numberOfCalls == queryNumber) + profileDataGridNode._searchMatchedCallsColumn = true; + if (greaterThan && profileDataGridNode.numberOfCalls > queryNumber) + profileDataGridNode._searchMatchedCallsColumn = true; + if (lessThan && profileDataGridNode.numberOfCalls < queryNumber) + profileDataGridNode._searchMatchedCallsColumn = true; + } + + if (profileDataGridNode.functionName.hasSubstring(query, true) || profileDataGridNode.url.hasSubstring(query, true)) + profileDataGridNode._searchMatchedFunctionColumn = true; + + if (profileDataGridNode._searchMatchedSelfColumn || + profileDataGridNode._searchMatchedTotalColumn || + profileDataGridNode._searchMatchedAverageColumn || + profileDataGridNode._searchMatchedCallsColumn || + profileDataGridNode._searchMatchedFunctionColumn) + { + profileDataGridNode.refresh(); + return true; + } + + return false; + } + + var current = this.profileDataGridTree.children[0]; + + while (current) { + if (matchesQuery(current)) { + this._searchResults.push({ profileNode: current }); + } + + current = current.traverseNextNode(false, null, false); + } + + finishedCallback(this, this._searchResults.length); + }, + + jumpToFirstSearchResult: function() + { + if (!this._searchResults || !this._searchResults.length) + return; + this._currentSearchResultIndex = 0; + this._jumpToSearchResult(this._currentSearchResultIndex); + }, + + jumpToLastSearchResult: function() + { + if (!this._searchResults || !this._searchResults.length) + return; + this._currentSearchResultIndex = (this._searchResults.length - 1); + this._jumpToSearchResult(this._currentSearchResultIndex); + }, + + jumpToNextSearchResult: function() + { + if (!this._searchResults || !this._searchResults.length) + return; + if (++this._currentSearchResultIndex >= this._searchResults.length) + this._currentSearchResultIndex = 0; + this._jumpToSearchResult(this._currentSearchResultIndex); + }, + + jumpToPreviousSearchResult: function() + { + if (!this._searchResults || !this._searchResults.length) + return; + if (--this._currentSearchResultIndex < 0) + this._currentSearchResultIndex = (this._searchResults.length - 1); + this._jumpToSearchResult(this._currentSearchResultIndex); + }, + + showingFirstSearchResult: function() + { + return (this._currentSearchResultIndex === 0); + }, + + showingLastSearchResult: function() + { + return (this._searchResults && this._currentSearchResultIndex === (this._searchResults.length - 1)); + }, + + _jumpToSearchResult: function(index) + { + var searchResult = this._searchResults[index]; + if (!searchResult) + return; + + var profileNode = searchResult.profileNode; + profileNode.revealAndSelect(); + }, + + _changeView: function() + { + if (!this.profile) + return; + + if (this.viewSelectElement.selectedIndex == 1) { + this.profileDataGridTree = this.topDownProfileDataGridTree; + this._sortProfile(); + this._viewType.set(WebInspector.CPUProfileView._TypeTree); + } else if (this.viewSelectElement.selectedIndex == 0) { + this.profileDataGridTree = this.bottomUpProfileDataGridTree; + this._sortProfile(); + this._viewType.set(WebInspector.CPUProfileView._TypeHeavy); + } + + if (!this.currentQuery || !this._searchFinishedCallback || !this._searchResults) + return; + + // The current search needs to be performed again. First negate out previous match + // count by calling the search finished callback with a negative number of matches. + // Then perform the search again the with same query and callback. + this._searchFinishedCallback(this, -this._searchResults.length); + this.performSearch(this.currentQuery, this._searchFinishedCallback); + }, + + _percentClicked: function(event) + { + var currentState = this.showSelfTimeAsPercent.get() && this.showTotalTimeAsPercent.get() && this.showAverageTimeAsPercent.get(); + this.showSelfTimeAsPercent.set(!currentState); + this.showTotalTimeAsPercent.set(!currentState); + this.showAverageTimeAsPercent.set(!currentState); + this.refreshShowAsPercents(); + }, + + _updatePercentButton: function() + { + if (this.showSelfTimeAsPercent.get() && this.showTotalTimeAsPercent.get() && this.showAverageTimeAsPercent.get()) { + this.percentButton.title = WebInspector.UIString("Show absolute total and self times."); + this.percentButton.toggled = true; + } else { + this.percentButton.title = WebInspector.UIString("Show total and self times as percentages."); + this.percentButton.toggled = false; + } + }, + + _focusClicked: function(event) + { + if (!this.dataGrid.selectedNode) + return; + + this.resetButton.visible = true; + this.profileDataGridTree.focus(this.dataGrid.selectedNode); + this.refresh(); + this.refreshVisibleData(); + }, + + _excludeClicked: function(event) + { + var selectedNode = this.dataGrid.selectedNode + + if (!selectedNode) + return; + + selectedNode.deselect(); + + this.resetButton.visible = true; + this.profileDataGridTree.exclude(selectedNode); + this.refresh(); + this.refreshVisibleData(); + }, + + _resetClicked: function(event) + { + this.resetButton.visible = false; + this.profileDataGridTree.restore(); + this._linkifier.reset(); + this.refresh(); + this.refreshVisibleData(); + }, + + _dataGridNodeSelected: function(node) + { + this.focusButton.disabled = false; + this.excludeButton.disabled = false; + }, + + _dataGridNodeDeselected: function(node) + { + this.focusButton.disabled = true; + this.excludeButton.disabled = true; + }, + + _sortData: function(event) + { + this._sortProfile(this.profile); + }, + + _sortProfile: function() + { + var sortAscending = this.dataGrid.sortOrder === "ascending"; + var sortColumnIdentifier = this.dataGrid.sortColumnIdentifier; + var sortProperty = { + "average": "averageTime", + "self": "selfTime", + "total": "totalTime", + "calls": "numberOfCalls", + "function": "functionName" + }[sortColumnIdentifier]; + + this.profileDataGridTree.sort(WebInspector.ProfileDataGridTree.propertyComparator(sortProperty, sortAscending)); + + this.refresh(); + }, + + _mouseDownInDataGrid: function(event) + { + if (event.detail < 2) + return; + + var cell = event.target.enclosingNodeOrSelfWithNodeName("td"); + if (!cell || (!cell.hasStyleClass("total-column") && !cell.hasStyleClass("self-column") && !cell.hasStyleClass("average-column"))) + return; + + if (cell.hasStyleClass("total-column")) + this.showTotalTimeAsPercent.set(!this.showTotalTimeAsPercent.get()); + else if (cell.hasStyleClass("self-column")) + this.showSelfTimeAsPercent.set(!this.showSelfTimeAsPercent.get()); + else if (cell.hasStyleClass("average-column")) + this.showAverageTimeAsPercent.set(!this.showAverageTimeAsPercent.get()); + + this.refreshShowAsPercents(); + + event.preventDefault(); + event.stopPropagation(); + }, + + _assignParentsInProfile: function() + { + var head = this.profile.head; + head.parent = null; + head.head = null; + var nodesToTraverse = [ { parent: head, children: head.children } ]; + while (nodesToTraverse.length > 0) { + var pair = nodesToTraverse.shift(); + var parent = pair.parent; + var children = pair.children; + var length = children.length; + for (var i = 0; i < length; ++i) { + children[i].head = head; + children[i].parent = parent; + if (children[i].children.length > 0) + nodesToTraverse.push({ parent: children[i], children: children[i].children }); + } + } + } +} + +WebInspector.CPUProfileView.prototype.__proto__ = WebInspector.View.prototype; + +WebInspector.CPUProfileType = function() +{ + WebInspector.ProfileType.call(this, WebInspector.CPUProfileType.TypeId, WebInspector.UIString("Collect JavaScript CPU Profile")); + this._recording = false; + WebInspector.CPUProfileType.instance = this; +} + +WebInspector.CPUProfileType.TypeId = "CPU"; + +WebInspector.CPUProfileType.prototype = { + get buttonTooltip() + { + return this._recording ? WebInspector.UIString("Stop CPU profiling.") : WebInspector.UIString("Start CPU profiling."); + }, + + buttonClicked: function() + { + if (this._recording) { + this.stopRecordingProfile(); + WebInspector.networkManager.enableResourceTracking(); + } else { + WebInspector.networkManager.disableResourceTracking(); + this.startRecordingProfile(); + } + }, + + get treeItemTitle() + { + return WebInspector.UIString("CPU PROFILES"); + }, + + get description() + { + return WebInspector.UIString("CPU profiles show where the execution time is spent in your page's JavaScript functions."); + }, + + isRecordingProfile: function() + { + return this._recording; + }, + + startRecordingProfile: function() + { + this._recording = true; + ProfilerAgent.start(); + }, + + stopRecordingProfile: function() + { + this._recording = false; + ProfilerAgent.stop(); + }, + + setRecordingProfile: function(isProfiling) + { + this._recording = isProfiling; + }, + + createSidebarTreeElementForProfile: function(profile) + { + return new WebInspector.ProfileSidebarTreeElement(profile, WebInspector.UIString("Profile %d"), "profile-sidebar-tree-item"); + }, + + createView: function(profile) + { + return new WebInspector.CPUProfileView(profile); + } +} + +WebInspector.CPUProfileType.prototype.__proto__ = WebInspector.ProfileType.prototype; +/* CSSSelectorProfileView.js */ + +/* + * Copyright (C) 2011 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: + * 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 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 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. + */ + +/** + * @constructor + * @extends WebInspector.DataGridNode + * @param {WebInspector.CSSSelectorProfileView} profileView + */ +WebInspector.CSSSelectorDataGridNode = function(profileView, data) +{ + WebInspector.DataGridNode.call(this, data, false); + this._profileView = profileView; +} + +WebInspector.CSSSelectorDataGridNode.prototype = { + get data() + { + var data = {}; + data.selector = this._data.selector; + data.matches = this._data.matchCount; + + if (this._profileView.showTimeAsPercent.get()) + data.time = Number(this._data.timePercent).toFixed(1) + "%"; + else + data.time = Number.secondsToString(this._data.time / 1000, true); + + return data; + }, + + get rawData() + { + return this._data; + }, + + createCell: function(columnIdentifier) + { + var cell = WebInspector.DataGridNode.prototype.createCell.call(this, columnIdentifier); + if (columnIdentifier === "selector" && cell.firstChild) { + cell.firstChild.title = this.rawData.selector; + return cell; + } + + if (columnIdentifier !== "source") + return cell; + + cell.removeChildren(); + + if (this.rawData.url) { + var wrapperDiv = cell.createChild("div"); + wrapperDiv.appendChild(WebInspector.linkifyResourceAsNode(this.rawData.url, this.rawData.lineNumber)); + } + + return cell; + } +} + +WebInspector.CSSSelectorDataGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype; + +/** + * @constructor + * @extends WebInspector.View + * @param {CSSAgent.SelectorProfile} profile + */ +WebInspector.CSSSelectorProfileView = function(profile) +{ + WebInspector.View.call(this); + + this.element.addStyleClass("profile-view"); + + this.showTimeAsPercent = WebInspector.settings.createSetting("selectorProfilerShowTimeAsPercent", true); + + var columns = { "selector": { title: WebInspector.UIString("Selector"), width: "550px", sortable: true }, + "source": { title: WebInspector.UIString("Source"), width: "100px", sortable: true }, + "time": { title: WebInspector.UIString("Total"), width: "72px", sort: "descending", sortable: true }, + "matches": { title: WebInspector.UIString("Matches"), width: "72px", sortable: true } }; + + this.dataGrid = new WebInspector.DataGrid(columns); + this.dataGrid.element.addStyleClass("selector-profile-view"); + this.dataGrid.addEventListener("sorting changed", this._sortProfile, this); + this.dataGrid.element.addEventListener("mousedown", this._mouseDownInDataGrid.bind(this), true); + this.dataGrid.show(this.element); + + this.percentButton = new WebInspector.StatusBarButton("", "percent-time-status-bar-item"); + this.percentButton.addEventListener("click", this._percentClicked, this); + + this.profile = profile; + + this._createProfileNodes(); + this._sortProfile(); + this._updatePercentButton(); +} + +WebInspector.CSSSelectorProfileView.prototype = { + get statusBarItems() + { + return [this.percentButton.element]; + }, + + get profile() + { + return this._profile; + }, + + set profile(profile) + { + this._profile = profile; + }, + + _createProfileNodes: function() + { + var data = this.profile.data; + if (!data) { + // The profiler may have been terminated with the "Clear all profiles." button. + return; + } + + this.profile.children = []; + for (var i = 0; i < data.length; ++i) { + data[i].timePercent = data[i].time * 100 / this.profile.totalTime; + var node = new WebInspector.CSSSelectorDataGridNode(this, data[i]); + this.profile.children.push(node); + } + }, + + rebuildGridItems: function() + { + this.dataGrid.removeChildren(); + + var children = this.profile.children; + var count = children.length; + + for (var index = 0; index < count; ++index) + this.dataGrid.appendChild(children[index]); + }, + + refreshData: function() + { + var child = this.dataGrid.children[0]; + while (child) { + child.refresh(); + child = child.traverseNextNode(false, null, true); + } + }, + + refreshShowAsPercents: function() + { + this._updatePercentButton(); + this.refreshData(); + }, + + _percentClicked: function(event) + { + this.showTimeAsPercent.set(!this.showTimeAsPercent.get()); + this.refreshShowAsPercents(); + }, + + _updatePercentButton: function() + { + if (this.showTimeAsPercent.get()) { + this.percentButton.title = WebInspector.UIString("Show absolute times."); + this.percentButton.toggled = true; + } else { + this.percentButton.title = WebInspector.UIString("Show times as percentages."); + this.percentButton.toggled = false; + } + }, + + _sortProfile: function() + { + var sortAscending = this.dataGrid.sortOrder === "ascending"; + var sortColumnIdentifier = this.dataGrid.sortColumnIdentifier; + + function selectorComparator(a, b) + { + var result = b.rawData.selector.localeCompare(a.rawData.selector); + return sortAscending ? -result : result; + } + + function sourceComparator(a, b) + { + var aRawData = a.rawData; + var bRawData = b.rawData; + var result = bRawData.url.localeCompare(aRawData.url); + if (!result) + result = bRawData.lineNumber - aRawData.lineNumber; + return sortAscending ? -result : result; + } + + function timeComparator(a, b) + { + const result = b.rawData.time - a.rawData.time; + return sortAscending ? -result : result; + } + + function matchesComparator(a, b) + { + const result = b.rawData.matchCount - a.rawData.matchCount; + return sortAscending ? -result : result; + } + + var comparator; + switch (sortColumnIdentifier) { + case "time": + comparator = timeComparator; + break; + case "matches": + comparator = matchesComparator; + break; + case "selector": + comparator = selectorComparator; + break; + case "source": + comparator = sourceComparator; + break; + } + + this.profile.children.sort(comparator); + + this.rebuildGridItems(); + }, + + _mouseDownInDataGrid: function(event) + { + if (event.detail < 2) + return; + + var cell = event.target.enclosingNodeOrSelfWithNodeName("td"); + if (!cell) + return; + + if (cell.hasStyleClass("time-column")) + this.showTimeAsPercent.set(!this.showTimeAsPercent.get()); + else + return; + + this.refreshShowAsPercents(); + + event.preventDefault(); + event.stopPropagation(); + } +} + +WebInspector.CSSSelectorProfileView.prototype.__proto__ = WebInspector.View.prototype; + +/** + * @constructor + */ +WebInspector.CSSSelectorProfileType = function() +{ + WebInspector.ProfileType.call(this, WebInspector.CSSSelectorProfileType.TypeId, WebInspector.UIString("Collect CSS Selector Profile")); + this._recording = false; + this._profileUid = 1; + WebInspector.CSSSelectorProfileType.instance = this; +} + +WebInspector.CSSSelectorProfileType.TypeId = "SELECTOR"; + +WebInspector.CSSSelectorProfileType.prototype = { + get buttonTooltip() + { + return this._recording ? WebInspector.UIString("Stop CSS selector profiling.") : WebInspector.UIString("Start CSS selector profiling."); + }, + + buttonClicked: function() + { + if (this._recording) + this.stopRecordingProfile(); + else + this.startRecordingProfile(); + }, + + get treeItemTitle() + { + return WebInspector.UIString("CSS SELECTOR PROFILES"); + }, + + get description() + { + return WebInspector.UIString("CSS selector profiles show how long the selector matching has taken in total and how many times a certain selector has matched DOM elements (the results are approximate due to matching algorithm optimizations.)"); + }, + + reset: function() + { + this._profileUid = 1; + }, + + isRecordingProfile: function() + { + return this._recording; + }, + + setRecordingProfile: function(isProfiling) + { + this._recording = isProfiling; + }, + + startRecordingProfile: function() + { + this._recording = true; + CSSAgent.startSelectorProfiler(); + WebInspector.panels.profiles.setRecordingProfile(WebInspector.CSSSelectorProfileType.TypeId, true); + }, + + stopRecordingProfile: function() + { + function callback(error, profile) + { + if (error) + return; + + profile.uid = this._profileUid++; + profile.title = WebInspector.UIString("Profile %d", profile.uid) + String.sprintf(" (%s)", Number.secondsToString(profile.totalTime / 1000)); + profile.typeId = WebInspector.CSSSelectorProfileType.TypeId; + WebInspector.panels.profiles.addProfileHeader(profile); + WebInspector.panels.profiles.setRecordingProfile(WebInspector.CSSSelectorProfileType.TypeId, false); + } + + this._recording = false; + CSSAgent.stopSelectorProfiler(callback.bind(this)); + }, + + createSidebarTreeElementForProfile: function(profile) + { + return new WebInspector.ProfileSidebarTreeElement(profile, profile.title, "profile-sidebar-tree-item"); + }, + + createView: function(profile) + { + return new WebInspector.CSSSelectorProfileView(profile); + } +} + +WebInspector.CSSSelectorProfileType.prototype.__proto__ = WebInspector.ProfileType.prototype; +/* PartialQuickSort.js */ + +/* + * Copyright (C) 2011 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. + */ + +Object.defineProperty(Array.prototype, "sortRange", { value: +/** @this {Array} */ +function(comparator, leftBound, rightBound, k) +{ + function swap(array, i1, i2) + { + var temp = array[i1]; + array[i1] = array[i2]; + array[i2] = temp; + } + + function partition(array, comparator, left, right, pivotIndex) + { + var pivotValue = array[pivotIndex]; + swap(array, right, pivotIndex); + var storeIndex = left; + for (var i = left; i < right; ++i) { + if (comparator(array[i], pivotValue) < 0) { + swap(array, storeIndex, i); + ++storeIndex; + } + } + swap(array, right, storeIndex); + return storeIndex; + } + + function quickSortFirstK(array, comparator, left, right, k) + { + if (right <= left) + return; + var pivotIndex = Math.floor(Math.random() * (right - left)) + left; + var pivotNewIndex = partition(array, comparator, left, right, pivotIndex); + quickSortFirstK(array, comparator, left, pivotNewIndex - 1, k); + if (pivotNewIndex < left + k - 1) + quickSortFirstK(array, comparator, pivotNewIndex + 1, right, k); + } + + if (leftBound === 0 && rightBound === (this.length - 1) && k === this.length) + this.sort(comparator); + else + quickSortFirstK(this, comparator, leftBound, rightBound, k); + return this; +}}); +/* HeapSnapshot.js */ + +/* + * Copyright (C) 2011 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. + */ + +WebInspector.HeapSnapshotLoader = function() +{ + this._json = ""; + this._state = "find-snapshot-info"; + this._snapshot = {}; +} + +WebInspector.HeapSnapshotLoader.prototype = { + _findBalancedCurlyBrackets: function() + { + var counter = 0; + var openingBracket = "{".charCodeAt(0), closingBracket = "}".charCodeAt(0); + for (var i = 0, l = this._json.length; i < l; ++i) { + var character = this._json.charCodeAt(i); + if (character === openingBracket) + ++counter; + else if (character === closingBracket) { + if (--counter === 0) + return i + 1; + } + } + return -1; + }, + + finishLoading: function() + { + if (!this._json) + return null; + this._parseStringsArray(); + this._json = ""; + var result = new WebInspector.HeapSnapshot(this._snapshot); + this._json = ""; + this._snapshot = {}; + return result; + }, + + _parseNodes: function() + { + var index = 0; + var char0 = "0".charCodeAt(0), char9 = "9".charCodeAt(0), closingBracket = "]".charCodeAt(0); + var length = this._json.length; + while (true) { + while (index < length) { + var code = this._json.charCodeAt(index); + if (char0 <= code && code <= char9) + break; + else if (code === closingBracket) { + this._json = this._json.slice(index + 1); + // Shave off provisionally allocated space. + this._snapshot.nodes = this._snapshot.nodes.slice(0); + return false; + } + ++index; + } + if (index === length) { + this._json = ""; + return true; + } + var startIndex = index; + while (index < length) { + var code = this._json.charCodeAt(index); + if (char0 > code || code > char9) + break; + ++index; + } + if (index === length) { + this._json = this._json.slice(startIndex); + return true; + } + this._snapshot.nodes.push(parseInt(this._json.slice(startIndex, index))); + } + }, + + _parseStringsArray: function() + { + var closingBracketIndex = this._json.lastIndexOf("]"); + if (closingBracketIndex === -1) + throw new Error("Incomplete JSON"); + this._json = this._json.slice(0, closingBracketIndex + 1); + this._snapshot.strings = JSON.parse(this._json); + }, + + pushJSONChunk: function(chunk) + { + this._json += chunk; + switch (this._state) { + case "find-snapshot-info": { + var snapshotToken = "\"snapshot\""; + var snapshotTokenIndex = this._json.indexOf(snapshotToken); + if (snapshotTokenIndex === -1) + throw new Error("Snapshot token not found"); + this._json = this._json.slice(snapshotTokenIndex + snapshotToken.length + 1); + this._state = "parse-snapshot-info"; + this.pushJSONChunk(""); + break; + } + case "parse-snapshot-info": { + var closingBracketIndex = this._findBalancedCurlyBrackets(); + if (closingBracketIndex === -1) + return; + this._snapshot.snapshot = JSON.parse(this._json.slice(0, closingBracketIndex)); + this._json = this._json.slice(closingBracketIndex); + this._state = "find-nodes"; + this.pushJSONChunk(""); + break; + } + case "find-nodes": { + var nodesToken = "\"nodes\""; + var nodesTokenIndex = this._json.indexOf(nodesToken); + if (nodesTokenIndex === -1) + return; + var bracketIndex = this._json.indexOf("[", nodesTokenIndex); + if (bracketIndex === -1) + return; + this._json = this._json.slice(bracketIndex + 1); + this._state = "parse-nodes-meta-info"; + this.pushJSONChunk(""); + break; + } + case "parse-nodes-meta-info": { + var closingBracketIndex = this._findBalancedCurlyBrackets(); + if (closingBracketIndex === -1) + return; + this._snapshot.nodes = [JSON.parse(this._json.slice(0, closingBracketIndex))]; + this._json = this._json.slice(closingBracketIndex); + this._state = "parse-nodes"; + this.pushJSONChunk(""); + break; + } + case "parse-nodes": { + if (this._parseNodes()) + return; + this._state = "find-strings"; + this.pushJSONChunk(""); + break; + } + case "find-strings": { + var stringsToken = "\"strings\""; + var stringsTokenIndex = this._json.indexOf(stringsToken); + if (stringsTokenIndex === -1) + return; + var bracketIndex = this._json.indexOf("[", stringsTokenIndex); + if (bracketIndex === -1) + return; + this._json = this._json.slice(bracketIndex); + this._state = "accumulate-strings"; + break; + } + case "accumulate-strings": + break; + } + } +}; + +WebInspector.HeapSnapshotArraySlice = function(snapshot, arrayName, start, end) +{ + // Note: we don't reference snapshot contents directly to avoid + // holding references to big chunks of data. + this._snapshot = snapshot; + this._arrayName = arrayName; + this._start = start; + this.length = end - start; +} + +WebInspector.HeapSnapshotArraySlice.prototype = { + item: function(index) + { + return this._snapshot[this._arrayName][this._start + index]; + }, + + slice: function(start, end) + { + if (typeof end === "undefined") + end = start + this._start + this.length; + return this._snapshot[this._arrayName].slice(this._start + start, end); + } +} + +WebInspector.HeapSnapshotEdge = function(snapshot, edges, edgeIndex) +{ + this._snapshot = snapshot; + this._edges = edges; + this.edgeIndex = edgeIndex || 0; +} + +WebInspector.HeapSnapshotEdge.prototype = { + clone: function() + { + return new WebInspector.HeapSnapshotEdge(this._snapshot, this._edges, this.edgeIndex); + }, + + get hasStringName() + { + if (!this.isShortcut) + return this._hasStringName; + return isNaN(parseInt(this._name, 10)); + }, + + get isElement() + { + return this._type() === this._snapshot._edgeElementType; + }, + + get isHidden() + { + return this._type() === this._snapshot._edgeHiddenType; + }, + + get isWeak() + { + return this._type() === this._snapshot._edgeWeakType; + }, + + get isInternal() + { + return this._type() === this._snapshot._edgeInternalType; + }, + + get isInvisible() + { + return this._type() === this._snapshot._edgeInvisibleType; + }, + + get isShortcut() + { + return this._type() === this._snapshot._edgeShortcutType; + }, + + get name() + { + if (!this.isShortcut) + return this._name; + var numName = parseInt(this._name, 10); + return isNaN(numName) ? this._name : numName; + }, + + get node() + { + return new WebInspector.HeapSnapshotNode(this._snapshot, this.nodeIndex); + }, + + get nodeIndex() + { + return this._edges.item(this.edgeIndex + this._snapshot._edgeToNodeOffset); + }, + + get rawEdges() + { + return this._edges; + }, + + toString: function() + { + switch (this.type) { + case "context": return "->" + this.name; + case "element": return "[" + this.name + "]"; + case "weak": return "[[" + this.name + "]]"; + case "property": + return this.name.indexOf(" ") === -1 ? "." + this.name : "[\"" + this.name + "\"]"; + case "shortcut": + var name = this.name; + if (typeof name === "string") + return this.name.indexOf(" ") === -1 ? "." + this.name : "[\"" + this.name + "\"]"; + else + return "[" + this.name + "]"; + case "internal": + case "hidden": + case "invisible": + return "{" + this.name + "}"; + }; + return "?" + this.name + "?"; + }, + + get type() + { + return this._snapshot._edgeTypes[this._type()]; + }, + + get _hasStringName() + { + return !this.isElement && !this.isHidden && !this.isWeak; + }, + + get _name() + { + return this._hasStringName ? this._snapshot._strings[this._nameOrIndex] : this._nameOrIndex; + }, + + get _nameOrIndex() + { + return this._edges.item(this.edgeIndex + this._snapshot._edgeNameOffset); + }, + + _type: function() + { + return this._edges.item(this.edgeIndex + this._snapshot._edgeTypeOffset); + } +}; + +WebInspector.HeapSnapshotEdgeIterator = function(edge) +{ + this.edge = edge; +} + +WebInspector.HeapSnapshotEdgeIterator.prototype = { + first: function() + { + this.edge.edgeIndex = 0; + }, + + hasNext: function() + { + return this.edge.edgeIndex < this.edge._edges.length; + }, + + get index() + { + return this.edge.edgeIndex; + }, + + set index(newIndex) + { + this.edge.edgeIndex = newIndex; + }, + + get item() + { + return this.edge; + }, + + next: function() + { + this.edge.edgeIndex += this.edge._snapshot._edgeFieldsCount; + } +}; + +WebInspector.HeapSnapshotRetainerEdge = function(snapshot, retainers, retainerIndex) +{ + this._snapshot = snapshot; + this._retainers = retainers; + this.retainerIndex = retainerIndex || 0; +} + +WebInspector.HeapSnapshotRetainerEdge.prototype = { + clone: function() + { + return new WebInspector.HeapSnapshotRetainerEdge(this._snapshot, this._retainers, this.retainerIndex); + }, + + get hasStringName() + { + return this._edge.hasStringName; + }, + + get isElement() + { + return this._edge.isElement; + }, + + get isHidden() + { + return this._edge.isHidden; + }, + + get isInternal() + { + return this._edge.isInternal; + }, + + get isInvisible() + { + return this._edge.isInvisible; + }, + + get isShortcut() + { + return this._edge.isShortcut; + }, + + get isWeak() + { + return this._edge.isWeak; + }, + + get name() + { + return this._edge.name; + }, + + get node() + { + return this._node; + }, + + get nodeIndex() + { + return this._nodeIndex; + }, + + get retainerIndex() + { + return this._retainerIndex; + }, + + set retainerIndex(newIndex) + { + if (newIndex !== this._retainerIndex) { + this._retainerIndex = newIndex; + this._setupEdge(); + } + }, + + _setupEdge: function() + { + var globalEdgeIndex = this._retainers.item(this._retainerIndex); + this._nodeIndex = this._snapshot._findNearestNodeIndex(globalEdgeIndex); + this._node = new WebInspector.HeapSnapshotNode(this._snapshot, this._nodeIndex); + var edgeIndex = globalEdgeIndex - this._nodeIndex - this._snapshot._firstEdgeOffset; + this._edge = new WebInspector.HeapSnapshotEdge(this._snapshot, this._node.rawEdges, edgeIndex); + }, + + toString: function() + { + return this._edge.toString(); + }, + + get type() + { + return this._edge.type; + } +} + +WebInspector.HeapSnapshotRetainerEdgeIterator = function(retainer) +{ + this.retainer = retainer; +} + +WebInspector.HeapSnapshotRetainerEdgeIterator.prototype = { + first: function() + { + this.retainer.retainerIndex = 0; + }, + + hasNext: function() + { + return this.retainer.retainerIndex < this.retainer._retainers.length; + }, + + get index() + { + return this.retainer.retainerIndex; + }, + + set index(newIndex) + { + this.retainer.retainerIndex = newIndex; + }, + + get item() + { + return this.retainer; + }, + + next: function() + { + ++this.retainer.retainerIndex; + } +}; + +WebInspector.HeapSnapshotNode = function(snapshot, nodeIndex) +{ + this._snapshot = snapshot; + this._firstNodeIndex = nodeIndex; + this.nodeIndex = nodeIndex; +} + +WebInspector.HeapSnapshotNode.prototype = { + get canBeQueried() + { + var flags = this._snapshot._flagsOfNode(this); + return !!(flags & this._snapshot._nodeFlags.canBeQueried); + }, + + get className() + { + switch (this.type) { + case "hidden": + return WebInspector.UIString("(system)"); + case "object": { + var commentPos = this.name.indexOf("/"); + return commentPos !== -1 ? this.name.substring(0, commentPos).trimRight() : this.name; + } + case "native": { + var entitiesCountPos = this.name.indexOf("/"); + return entitiesCountPos !== -1 ? this.name.substring(0, entitiesCountPos).trimRight() : this.name; + } + case "code": + return WebInspector.UIString("(compiled code)"); + default: + return "(" + this.type + ")"; + } + }, + + get dominatorIndex() + { + return this._nodes[this.nodeIndex + this._snapshot._dominatorOffset]; + }, + + get edges() + { + return new WebInspector.HeapSnapshotEdgeIterator(new WebInspector.HeapSnapshotEdge(this._snapshot, this.rawEdges)); + }, + + get edgesCount() + { + return this._nodes[this.nodeIndex + this._snapshot._edgesCountOffset]; + }, + + get flags() + { + return this._snapshot._flagsOfNode(this); + }, + + get id() + { + return this._nodes[this.nodeIndex + this._snapshot._nodeIdOffset]; + }, + + get instancesCount() + { + return this._nodes[this.nodeIndex + this._snapshot._nodeInstancesCountOffset]; + }, + + get isHidden() + { + return this._type() === this._snapshot._nodeHiddenType; + }, + + get isDOMWindow() + { + return this.name.substr(0, 9) === "DOMWindow"; + }, + + get isNativeRoot() + { + return this.name === "(Native objects)"; + }, + + get isDetachedDOMTree() + { + return this.className === "Detached DOM tree"; + }, + + get isRoot() + { + return this.nodeIndex === this._snapshot._rootNodeIndex; + }, + + get name() + { + return this._snapshot._strings[this._name()]; + }, + + get rawEdges() + { + var firstEdgeIndex = this._firstEdgeIndex(); + return new WebInspector.HeapSnapshotArraySlice(this._snapshot, "_nodes", firstEdgeIndex, firstEdgeIndex + this.edgesCount * this._snapshot._edgeFieldsCount); + }, + + get retainedSize() + { + return this._nodes[this.nodeIndex + this._snapshot._nodeRetainedSizeOffset]; + }, + + get retainers() + { + return new WebInspector.HeapSnapshotRetainerEdgeIterator(new WebInspector.HeapSnapshotRetainerEdge(this._snapshot, this._snapshot._retainersForNode(this))); + }, + + get selfSize() + { + return this._nodes[this.nodeIndex + this._snapshot._nodeSelfSizeOffset]; + }, + + get type() + { + return this._snapshot._nodeTypes[this._type()]; + }, + + _name: function() + { + return this._nodes[this.nodeIndex + this._snapshot._nodeNameOffset]; + }, + + get _nodes() + { + return this._snapshot._nodes; + }, + + _firstEdgeIndex: function() + { + return this.nodeIndex + this._snapshot._firstEdgeOffset; + }, + + get _nextNodeIndex() + { + return this._firstEdgeIndex() + this.edgesCount * this._snapshot._edgeFieldsCount; + }, + + _type: function() + { + return this._nodes[this.nodeIndex + this._snapshot._nodeTypeOffset]; + } +}; + +WebInspector.HeapSnapshotNodeIterator = function(node) +{ + this.node = node; +} + +WebInspector.HeapSnapshotNodeIterator.prototype = { + first: function() + { + this.node.nodeIndex = this.node._firstNodeIndex; + }, + + hasNext: function() + { + return this.node.nodeIndex < this.node._nodes.length; + }, + + get index() + { + return this.node.nodeIndex; + }, + + set index(newIndex) + { + this.node.nodeIndex = newIndex; + }, + + get item() + { + return this.node; + }, + + next: function() + { + this.node.nodeIndex = this.node._nextNodeIndex; + } +} + +WebInspector.HeapSnapshot = function(profile) +{ + this.uid = profile.snapshot.uid; + this._nodes = profile.nodes; + this._strings = profile.strings; + + this._init(); +} + +WebInspector.HeapSnapshot.prototype = { + _init: function() + { + this._metaNodeIndex = 0; + this._rootNodeIndex = 1; + var meta = this._nodes[this._metaNodeIndex]; + this._nodeTypeOffset = meta.fields.indexOf("type"); + this._nodeNameOffset = meta.fields.indexOf("name"); + this._nodeIdOffset = meta.fields.indexOf("id"); + this._nodeInstancesCountOffset = this._nodeIdOffset; + this._nodeSelfSizeOffset = meta.fields.indexOf("self_size"); + this._nodeRetainedSizeOffset = meta.fields.indexOf("retained_size"); + this._dominatorOffset = meta.fields.indexOf("dominator"); + this._edgesCountOffset = meta.fields.indexOf("children_count"); + this._firstEdgeOffset = meta.fields.indexOf("children"); + this._nodeTypes = meta.types[this._nodeTypeOffset]; + this._nodeHiddenType = this._nodeTypes.indexOf("hidden"); + var edgesMeta = meta.types[this._firstEdgeOffset]; + this._edgeFieldsCount = edgesMeta.fields.length; + this._edgeTypeOffset = edgesMeta.fields.indexOf("type"); + this._edgeNameOffset = edgesMeta.fields.indexOf("name_or_index"); + this._edgeToNodeOffset = edgesMeta.fields.indexOf("to_node"); + this._edgeTypes = edgesMeta.types[this._edgeTypeOffset]; + this._edgeElementType = this._edgeTypes.indexOf("element"); + this._edgeHiddenType = this._edgeTypes.indexOf("hidden"); + this._edgeInternalType = this._edgeTypes.indexOf("internal"); + this._edgeShortcutType = this._edgeTypes.indexOf("shortcut"); + this._edgeWeakType = this._edgeTypes.indexOf("weak"); + this._edgeInvisibleType = this._edgeTypes.length; + this._edgeTypes.push("invisible"); + + this._nodeFlags = { // bit flags + canBeQueried: 1, + detachedDOMTreeNode: 2, + }; + + this._markInvisibleEdges(); + }, + + dispose: function() + { + delete this._nodes; + delete this._strings; + delete this._retainers; + delete this._retainerIndex; + delete this._nodeIndex; + if (this._aggregates) { + delete this._aggregates; + delete this._aggregatesSortedFlags; + } + delete this._baseNodeIds; + delete this._dominatedNodes; + delete this._dominatedIndex; + delete this._flags; + }, + + get _allNodes() + { + return new WebInspector.HeapSnapshotNodeIterator(this.rootNode); + }, + + get nodeCount() + { + if (this._nodeCount) + return this._nodeCount; + + this._nodeCount = 0; + for (var iter = this._allNodes; iter.hasNext(); iter.next()) + ++this._nodeCount; + return this._nodeCount; + }, + + nodeFieldValuesByIndex: function(fieldName, indexes) + { + var node = new WebInspector.HeapSnapshotNode(this); + var result = new Array(indexes.length); + for (var i = 0, l = indexes.length; i < l; ++i) { + node.nodeIndex = indexes[i]; + result[i] = node[fieldName]; + } + return result; + }, + + get rootNode() + { + return new WebInspector.HeapSnapshotNode(this, this._rootNodeIndex); + }, + + get maxNodeId() + { + if (typeof this._maxNodeId === "number") + return this._maxNodeId; + this._maxNodeId = 0; + for (var iter = this._allNodes; iter.hasNext(); iter.next()) { + var id = iter.node.id; + if ((id % 2) && id > this._maxNodeId) + this._maxNodeId = id; + } + return this._maxNodeId; + }, + + get rootNodeIndex() + { + return this._rootNodeIndex; + }, + + get totalSize() + { + return this.rootNode.retainedSize; + }, + + _retainersForNode: function(node) + { + if (!this._retainers) + this._buildRetainers(); + + var retIndexFrom = this._getRetainerIndex(node.nodeIndex); + var retIndexTo = this._getRetainerIndex(node._nextNodeIndex); + return new WebInspector.HeapSnapshotArraySlice(this, "_retainers", retIndexFrom, retIndexTo); + }, + + _dominatedNodesOfNode: function(node) + { + if (!this._dominatedNodes) + this._buildDominatedNodes(); + + var dominatedIndexFrom = this._getDominatedIndex(node.nodeIndex); + var dominatedIndexTo = this._getDominatedIndex(node._nextNodeIndex); + return new WebInspector.HeapSnapshotArraySlice(this, "_dominatedNodes", dominatedIndexFrom, dominatedIndexTo); + }, + + _flagsOfNode: function(node) + { + if (!this._flags) + this._calculateFlags(); + return this._flags[node.nodeIndex]; + }, + + aggregates: function(sortedIndexes, key, filterString) + { + if (!this._aggregates) { + this._aggregates = {}; + this._aggregatesSortedFlags = {}; + } + + var aggregates = this._aggregates[key]; + if (aggregates) { + if (sortedIndexes && !this._aggregatesSortedFlags[key]) { + this._sortAggregateIndexes(aggregates); + this._aggregatesSortedFlags[key] = sortedIndexes; + } + return aggregates; + } + + var filter; + if (filterString) + filter = this._parseFilter(filterString); + + aggregates = this._buildAggregates(filter); + + if (sortedIndexes) + this._sortAggregateIndexes(aggregates); + + this._aggregatesSortedFlags[key] = sortedIndexes; + this._aggregates[key] = aggregates; + + return aggregates; + }, + + _buildReverseIndex: function(indexArrayName, backRefsArrayName, indexCallback, dataCallback) + { + if (!this._nodeIndex) + this._buildNodeIndex(); + + // Builds up two arrays: + // - "backRefsArray" is a continuous array, where each node owns an + // interval (can be empty) with corresponding back references. + // - "indexArray" is an array of indexes in the "backRefsArray" + // with the same positions as in the _nodeIndex. + var indexArray = this[indexArrayName] = new Array(this._nodeIndex.length); + for (var i = 0, l = indexArray.length; i < l; ++i) + indexArray[i] = 0; + for (var nodesIter = this._allNodes; nodesIter.hasNext(); nodesIter.next()) { + indexCallback(nodesIter.node, function (position) { ++indexArray[position]; }); + } + var backRefsCount = 0; + for (i = 0, l = indexArray.length; i < l; ++i) + backRefsCount += indexArray[i]; + var backRefsArray = this[backRefsArrayName] = new Array(backRefsCount + 1); + // Put in the first slot of each backRefsArray slice the count of entries + // that will be filled. + var backRefsPosition = 0; + for (i = 0, l = indexArray.length; i < l; ++i) { + backRefsCount = backRefsArray[backRefsPosition] = indexArray[i]; + indexArray[i] = backRefsPosition; + backRefsPosition += backRefsCount; + } + for (nodesIter = this._allNodes; nodesIter.hasNext(); nodesIter.next()) { + dataCallback(nodesIter.node, + function (backRefIndex) { return backRefIndex + (--backRefsArray[backRefIndex]); }, + function (backRefIndex, destIndex) { backRefsArray[backRefIndex] = destIndex; }); + } + }, + + _buildRetainers: function() + { + this._buildReverseIndex( + "_retainerIndex", + "_retainers", + (function (node, callback) + { + for (var edgesIter = node.edges; edgesIter.hasNext(); edgesIter.next()) + callback(this._findNodePositionInIndex(edgesIter.edge.nodeIndex)); + }).bind(this), + (function (node, indexCallback, dataCallback) + { + for (var edgesIter = node.edges; edgesIter.hasNext(); edgesIter.next()) { + var edge = edgesIter.edge; + var retIndex = this._getRetainerIndex(edge.nodeIndex); + dataCallback(indexCallback(retIndex), node.nodeIndex + this._firstEdgeOffset + edge.edgeIndex); + } + }).bind(this)); + }, + + _buildAggregates: function(filter) + { + var aggregates = {}; + for (var iter = this._allNodes; iter.hasNext(); iter.next()) { + var node = iter.node; + if (filter && !filter(node)) + continue; + if (node.type !== "native" && node.selfSize === 0) + continue; + var className = node.className; + if (className === "Document DOM tree") + continue; + if (className === "Detached DOM tree") + continue; + var nameMatters = node.type === "object" || node.type === "native"; + if (!aggregates.hasOwnProperty(className)) + aggregates[className] = { count: 0, self: 0, maxRet: 0, type: node.type, name: nameMatters ? node.name : null, idxs: [] }; + var clss = aggregates[className]; + ++clss.count; + clss.self += node.selfSize; + if (node.retainedSize > clss.maxRet) + clss.maxRet = node.retainedSize; + clss.idxs.push(node.nodeIndex); + } + // Shave off provisionally allocated space. + for (var className in aggregates) + aggregates[className].idxs = aggregates[className].idxs.slice(0); + return aggregates; + }, + + _sortAggregateIndexes: function(aggregates) + { + var nodeA = new WebInspector.HeapSnapshotNode(this); + var nodeB = new WebInspector.HeapSnapshotNode(this); + for (var clss in aggregates) + aggregates[clss].idxs.sort( + function(idxA, idxB) { + nodeA.nodeIndex = idxA; + nodeB.nodeIndex = idxB; + return nodeA.id < nodeB.id ? -1 : 1; + }); + }, + + _buildNodeIndex: function() + { + var count = this.nodeCount; + this._nodeIndex = new Array(count + 1); + count = 0; + for (var nodesIter = this._allNodes; nodesIter.hasNext(); nodesIter.next(), ++count) + this._nodeIndex[count] = nodesIter.index; + this._nodeIndex[count] = this._nodes.length; + }, + + _findNodePositionInIndex: function(index) + { + return binarySearch(index, this._nodeIndex, this._numbersComparator); + }, + + _findNearestNodeIndex: function(index) + { + var result = this._findNodePositionInIndex(index); + if (result < 0) { + result = -result - 1; + nodeIndex = this._nodeIndex[result]; + // Binary search can return either maximum lower value, or minimum higher value. + if (nodeIndex > index) + nodeIndex = this._nodeIndex[result - 1]; + } else + var nodeIndex = this._nodeIndex[result]; + return nodeIndex; + }, + + _getRetainerIndex: function(nodeIndex) + { + var nodePosition = this._findNodePositionInIndex(nodeIndex); + return this._retainerIndex[nodePosition]; + }, + + _buildDominatedNodes: function() + { + this._buildReverseIndex( + "_dominatedIndex", + "_dominatedNodes", + (function (node, callback) + { + var dominatorIndex = node.dominatorIndex; + if (dominatorIndex !== node.nodeIndex) + callback(this._findNodePositionInIndex(dominatorIndex)); + }).bind(this), + (function (node, indexCallback, dataCallback) + { + var dominatorIndex = node.dominatorIndex; + if (dominatorIndex !== node.nodeIndex) { + var dominatedIndex = this._getDominatedIndex(dominatorIndex); + dataCallback(indexCallback(dominatedIndex), node.nodeIndex); + } + }).bind(this)); + }, + + _getDominatedIndex: function(nodeIndex) + { + var nodePosition = this._findNodePositionInIndex(nodeIndex); + return this._dominatedIndex[nodePosition]; + }, + + _markInvisibleEdges: function() + { + // Mark hidden edges of global objects as invisible. + // FIXME: This is a temporary measure. Normally, we should + // really hide all hidden nodes. + for (var iter = this.rootNode.edges; iter.hasNext(); iter.next()) { + var edge = iter.edge; + if (!edge.isShortcut) + continue; + var node = edge.node; + var propNames = {}; + for (var innerIter = node.edges; innerIter.hasNext(); innerIter.next()) { + var globalObjEdge = innerIter.edge; + if (globalObjEdge.isShortcut) + propNames[globalObjEdge._nameOrIndex] = true; + } + for (innerIter.first(); innerIter.hasNext(); innerIter.next()) { + var globalObjEdge = innerIter.edge; + if (!globalObjEdge.isShortcut + && globalObjEdge.node.isHidden + && globalObjEdge._hasStringName + && (globalObjEdge._nameOrIndex in propNames)) + this._nodes[globalObjEdge._edges._start + globalObjEdge.edgeIndex + this._edgeTypeOffset] = this._edgeInvisibleType; + } + } + }, + + _numbersComparator: function(a, b) + { + return a < b ? -1 : (a > b ? 1 : 0); + }, + + _markDetachedDOMTreeNodes: function() + { + var flag = this._nodeFlags.detachedDOMTreeNode; + var nativeRoot; + for (var iter = this.rootNode.edges; iter.hasNext(); iter.next()) { + var node = iter.edge.node; + if (node.isNativeRoot) { + nativeRoot = node; + break; + } + } + + if (!nativeRoot) + return; + + for (var iter = nativeRoot.edges; iter.hasNext(); iter.next()) { + var node = iter.edge.node; + if (node.isDetachedDOMTree) { + for (var edgesIter = node.edges; edgesIter.hasNext(); edgesIter.next()) + this._flags[edgesIter.edge.node.nodeIndex] |= flag; + } + } + }, + + _markQueriableHeapObjects: function() + { + // Allow runtime properties query for objects accessible from DOMWindow objects + // via regular properties, and for DOM wrappers. Trying to access random objects + // can cause a crash due to insonsistent state of internal properties of wrappers. + var flag = this._nodeFlags.canBeQueried; + + var list = []; + for (var iter = this.rootNode.edges; iter.hasNext(); iter.next()) { + if (iter.edge.node.isDOMWindow) + list.push(iter.edge.node); + } + + while (list.length) { + var node = list.pop(); + if (this._flags[node.nodeIndex] & flag) + continue; + this._flags[node.nodeIndex] |= flag; + for (var iter = node.edges; iter.hasNext(); iter.next()) { + var edge = iter.edge; + var node = edge.node; + if (this._flags[node.nodeIndex]) + continue; + if (edge.isHidden || edge.isInvisible) + continue; + var name = edge.name; + if (!name) + continue; + if (edge.isInternal && name !== "native") + continue; + list.push(node); + } + } + }, + + _calculateFlags: function() + { + this._flags = new Array(this.nodeCount); + this._markDetachedDOMTreeNodes(); + this._markQueriableHeapObjects(); + }, + + baseSnapshotHasNode: function(baseSnapshotId, className, nodeId) + { + return this._baseNodeIds[baseSnapshotId][className].binaryIndexOf(nodeId, this._numbersComparator) !== -1; + }, + + pushBaseIds: function(baseSnapshotId, className, nodeIds) + { + if (!this._baseNodeIds) + this._baseNodeIds = []; + if (!this._baseNodeIds[baseSnapshotId]) + this._baseNodeIds[baseSnapshotId] = {}; + this._baseNodeIds[baseSnapshotId][className] = nodeIds; + }, + + createDiff: function(className) + { + return new WebInspector.HeapSnapshotsDiff(this, className); + }, + + _parseFilter: function(filter) + { + if (!filter) + return null; + var parsedFilter = eval("(function(){return " + filter + "})()"); + return parsedFilter.bind(this); + }, + + createEdgesProvider: function(nodeIndex, filter) + { + return new WebInspector.HeapSnapshotEdgesProvider(this, nodeIndex, this._parseFilter(filter)); + }, + + createRetainingEdgesProvider: function(nodeIndex, filter) + { + var node = new WebInspector.HeapSnapshotNode(this, nodeIndex); + return new WebInspector.HeapSnapshotEdgesProvider(this, nodeIndex, this._parseFilter(filter), node.retainers); + }, + + createNodesProvider: function(filter) + { + return new WebInspector.HeapSnapshotNodesProvider(this, this._parseFilter(filter)); + }, + + createNodesProviderForClass: function(className, aggregatesKey) + { + return new WebInspector.HeapSnapshotNodesProvider(this, null, this.aggregates(false, aggregatesKey)[className].idxs); + }, + + createNodesProviderForDominator: function(nodeIndex, filter) + { + var node = new WebInspector.HeapSnapshotNode(this, nodeIndex); + return new WebInspector.HeapSnapshotNodesProvider(this, this._parseFilter(filter), this._dominatedNodesOfNode(node)); + }, + + createPathFinder: function(targetNodeIndex, skipHidden) + { + return new WebInspector.HeapSnapshotPathFinder(this, targetNodeIndex, skipHidden); + }, + + updateStaticData: function() + { + return {nodeCount: this.nodeCount, rootNodeIndex: this._rootNodeIndex, totalSize: this.totalSize, uid: this.uid, nodeFlags: this._nodeFlags, maxNodeId: this.maxNodeId}; + } +}; + +WebInspector.HeapSnapshotFilteredOrderedIterator = function(iterator, filter, unfilteredIterationOrder) +{ + this._filter = filter; + this._iterator = iterator; + this._unfilteredIterationOrder = unfilteredIterationOrder; + this._iterationOrder = null; + this._position = 0; + this._currentComparator = null; + this._lastComparator = null; +} + +WebInspector.HeapSnapshotFilteredOrderedIterator.prototype = { + _createIterationOrder: function() + { + if (this._iterationOrder) + return; + if (this._unfilteredIterationOrder && !this._filter) { + this._iterationOrder = this._unfilteredIterationOrder.slice(0); + this._unfilteredIterationOrder = null; + return; + } + this._iterationOrder = []; + var iterator = this._iterator; + if (!this._unfilteredIterationOrder && !this._filter) { + for (iterator.first(); iterator.hasNext(); iterator.next()) + this._iterationOrder.push(iterator.index); + } else if (!this._unfilteredIterationOrder) { + for (iterator.first(); iterator.hasNext(); iterator.next()) { + if (this._filter(iterator.item)) + this._iterationOrder.push(iterator.index); + } + } else { + var order = this._unfilteredIterationOrder.constructor === Array ? + this._unfilteredIterationOrder : this._unfilteredIterationOrder.slice(0); + for (var i = 0, l = order.length; i < l; ++i) { + iterator.index = order[i]; + if (this._filter(iterator.item)) + this._iterationOrder.push(iterator.index); + } + this._unfilteredIterationOrder = null; + } + }, + + first: function() + { + this._position = 0; + }, + + hasNext: function() + { + return this._position < this._iterationOrder.length; + }, + + get isEmpty() + { + if (this._iterationOrder) + return !this._iterationOrder.length; + if (this._unfilteredIterationOrder && !this._filter) + return !this._unfilteredIterationOrder.length; + var iterator = this._iterator; + if (!this._unfilteredIterationOrder && !this._filter) { + iterator.first(); + return !iterator.hasNext(); + } else if (!this._unfilteredIterationOrder) { + for (iterator.first(); iterator.hasNext(); iterator.next()) + if (this._filter(iterator.item)) + return false; + } else { + var order = this._unfilteredIterationOrder.constructor === Array ? + this._unfilteredIterationOrder : this._unfilteredIterationOrder.slice(0); + for (var i = 0, l = order.length; i < l; ++i) { + iterator.index = order[i]; + if (this._filter(iterator.item)) + return false; + } + } + return true; + }, + + get item() + { + this._iterator.index = this._iterationOrder[this._position]; + return this._iterator.item; + }, + + get length() + { + this._createIterationOrder(); + return this._iterationOrder.length; + }, + + next: function() + { + ++this._position; + }, + + serializeNextItems: function(count) + { + this._createIterationOrder(); + var result = new Array(count); + if (this._lastComparator !== this._currentComparator) + this.sort(this._currentComparator, this._position, this._iterationOrder.length - 1, count); + for (var i = 0 ; i < count && this.hasNext(); ++i, this.next()) + result[i] = this._serialize(this.item); + result.length = i; + result.hasNext = this.hasNext(); + result.totalLength = this._iterationOrder.length; + return result; + }, + + sortAndRewind: function(comparator) + { + this._lastComparator = this._currentComparator; + this._currentComparator = comparator; + var result = this._lastComparator !== this._currentComparator; + if (result) + this.first(); + return result; + } +} + +WebInspector.HeapSnapshotFilteredOrderedIterator.prototype.createComparator = function(fieldNames) +{ + return {fieldName1:fieldNames[0], ascending1:fieldNames[1], fieldName2:fieldNames[2], ascending2:fieldNames[3]}; +} + +WebInspector.HeapSnapshotEdgesProvider = function(snapshot, nodeIndex, filter, iter) +{ + this.snapshot = snapshot; + var node = new WebInspector.HeapSnapshotNode(snapshot, nodeIndex); + var edgesIter = iter || new WebInspector.HeapSnapshotEdgeIterator(new WebInspector.HeapSnapshotEdge(snapshot, node.rawEdges)); + WebInspector.HeapSnapshotFilteredOrderedIterator.call(this, edgesIter, filter); +} + +WebInspector.HeapSnapshotEdgesProvider.prototype = { + _serialize: function(edge) + { + return {name: edge.name, node: WebInspector.HeapSnapshotNodesProvider.prototype._serialize(edge.node), nodeIndex: edge.nodeIndex, type: edge.type}; + }, + + sort: function(comparator, leftBound, rightBound, count) + { + var fieldName1 = comparator.fieldName1; + var fieldName2 = comparator.fieldName2; + var ascending1 = comparator.ascending1; + var ascending2 = comparator.ascending2; + + var edgeA = this._iterator.item.clone(); + var edgeB = edgeA.clone(); + var nodeA = new WebInspector.HeapSnapshotNode(this.snapshot); + var nodeB = new WebInspector.HeapSnapshotNode(this.snapshot); + + function sortByEdgeFieldName(ascending, indexA, indexB) + { + edgeA.edgeIndex = indexA; + edgeB.edgeIndex = indexB; + if (edgeB.name === "__proto__") return -1; + if (edgeA.name === "__proto__") return 1; + var result = + edgeA.hasStringName === edgeB.hasStringName ? + (edgeA.name < edgeB.name ? -1 : (edgeA.name > edgeB.name ? 1 : 0)) : + (edgeA.hasStringName ? -1 : 1); + return ascending ? result : -result; + } + + function sortByNodeField(fieldName, ascending, indexA, indexB) + { + edgeA.edgeIndex = indexA; + edgeB.edgeIndex = indexB; + nodeA.nodeIndex = edgeA.nodeIndex; + nodeB.nodeIndex = edgeB.nodeIndex; + var valueA = nodeA[fieldName]; + var valueB = nodeB[fieldName]; + var result = valueA < valueB ? -1 : (valueA > valueB ? 1 : 0); + return ascending ? result : -result; + } + + function sortByEdgeAndNode(indexA, indexB) { + var result = sortByEdgeFieldName(ascending1, indexA, indexB); + if (result === 0) + result = sortByNodeField(fieldName2, ascending2, indexA, indexB); + return result; + } + + function sortByNodeAndEdge(indexA, indexB) { + var result = sortByNodeField(fieldName1, ascending1, indexA, indexB); + if (result === 0) + result = sortByEdgeFieldName(ascending2, indexA, indexB); + return result; + } + + function sortByNodeAndNode(indexA, indexB) { + var result = sortByNodeField(fieldName1, ascending1, indexA, indexB); + if (result === 0) + result = sortByNodeField(fieldName2, ascending2, indexA, indexB); + return result; + } + + if (fieldName1 === "!edgeName") + this._iterationOrder.sortRange(sortByEdgeAndNode, leftBound, rightBound, count); + else if (fieldName2 === "!edgeName") + this._iterationOrder.sortRange(sortByNodeAndEdge, leftBound, rightBound, count); + else + this._iterationOrder.sortRange(sortByNodeAndNode, leftBound, rightBound, count); + } +}; + +WebInspector.HeapSnapshotEdgesProvider.prototype.__proto__ = WebInspector.HeapSnapshotFilteredOrderedIterator.prototype; + +WebInspector.HeapSnapshotNodesProvider = function(snapshot, filter, nodeIndexes) +{ + this.snapshot = snapshot; + WebInspector.HeapSnapshotFilteredOrderedIterator.call(this, snapshot._allNodes, filter, nodeIndexes); +} + +WebInspector.HeapSnapshotNodesProvider.prototype = { + _serialize: function(node) + { + return {id: node.id, name: node.name, nodeIndex: node.nodeIndex, retainedSize: node.retainedSize, selfSize: node.selfSize, type: node.type, flags: node.flags}; + }, + + sort: function(comparator, leftBound, rightBound, count) + { + var fieldName1 = comparator.fieldName1; + var fieldName2 = comparator.fieldName2; + var ascending1 = comparator.ascending1; + var ascending2 = comparator.ascending2; + + var nodeA = new WebInspector.HeapSnapshotNode(this.snapshot); + var nodeB = new WebInspector.HeapSnapshotNode(this.snapshot); + + function sortByNodeField(fieldName, ascending, indexA, indexB) + { + nodeA.nodeIndex = indexA; + nodeB.nodeIndex = indexB; + var valueA = nodeA[fieldName]; + var valueB = nodeB[fieldName]; + var result = valueA < valueB ? -1 : (valueA > valueB ? 1 : 0); + return ascending ? result : -result; + } + + function sortByComparator(indexA, indexB) { + var result = sortByNodeField(fieldName1, ascending1, indexA, indexB); + if (result === 0) + result = sortByNodeField(fieldName2, ascending2, indexA, indexB); + return result; + } + + this._iterationOrder.sortRange(sortByComparator, leftBound, rightBound, count); + } +}; + +WebInspector.HeapSnapshotNodesProvider.prototype.__proto__ = WebInspector.HeapSnapshotFilteredOrderedIterator.prototype; + +WebInspector.HeapSnapshotPathFinder = function(snapshot, targetNodeIndex, skipHidden) +{ + this._snapshot = snapshot; + this._maxLength = 1; + this._lengthLimit = 15; + this._targetNodeIndex = targetNodeIndex; + this._currentPath = null; + this._skipHidden = skipHidden; + this._rootChildren = this._fillRootChildren(); +} + +WebInspector.HeapSnapshotPathFinder.prototype = { + findNext: function() + { + for (var i = 0; i < 100000; ++i) { + if (!this._buildNextPath()) { + if (++this._maxLength >= this._lengthLimit) + return null; + this._currentPath = null; + if (!this._buildNextPath()) + return null; + } + if (this._isPathFound()) + return {path:this._pathToString(this._currentPath), route:this._pathToRoute(this._currentPath), len:this._currentPath.length}; + } + + return false; + }, + + updateRoots: function(filter) + { + if (filter) + filter = eval("(function(){return " + filter + "})()"); + this._rootChildren = this._fillRootChildren(filter); + this._reset(); + }, + + _reset: function() + { + this._maxLength = 1; + this._currentPath = null; + }, + + _fillRootChildren: function(filter) + { + var result = []; + for (var iter = this._snapshot.rootNode.edges; iter.hasNext(); iter.next()) { + if (!filter) { + if (!iter.edge.isShortcut) + result[iter.edge.nodeIndex] = true; + } else if (filter(iter.edge.node)) { + result[iter.edge.nodeIndex] = true; + } + } + return result; + }, + + _appendToCurrentPath: function(iter) + { + this._currentPath._cache[this._lastEdge.nodeIndex] = true; + this._currentPath.push(iter); + }, + + _removeLastFromCurrentPath: function() + { + this._currentPath.pop(); + delete this._currentPath._cache[this._lastEdge.nodeIndex]; + }, + + _hasInPath: function(nodeIndex) + { + return this._targetNodeIndex === nodeIndex + || !!this._currentPath._cache[nodeIndex]; + }, + + _isPathFound: function() + { + return this._currentPath.length === this._maxLength + && this._lastEdge.nodeIndex in this._rootChildren; + }, + + get _lastEdgeIter() + { + return this._currentPath[this._currentPath.length - 1]; + }, + + get _lastEdge() + { + return this._lastEdgeIter.item; + }, + + _skipEdge: function(edge) + { + return edge.isInvisible + || (this._skipHidden && (edge.isHidden || edge.node.isHidden)) + || edge.isWeak + || this._hasInPath(edge.nodeIndex); + }, + + _nextEdgeIter: function() + { + var iter = this._lastEdgeIter; + while (iter.hasNext() && this._skipEdge(iter.item)) + iter.next(); + return iter; + }, + + _buildNextPath: function() + { + if (this._currentPath !== null) { + var iter = this._lastEdgeIter; + while (true) { + iter.next(); + iter = this._nextEdgeIter(); + if (iter.hasNext()) + return true; + while (true) { + if (this._currentPath.length > 1) { + this._removeLastFromCurrentPath(); + iter = this._lastEdgeIter; + iter.next(); + iter = this._nextEdgeIter(); + if (iter.hasNext()) { + while (this._currentPath.length < this._maxLength) { + iter = this._nextEdgeIter(); + if (iter.hasNext()) + this._appendToCurrentPath(iter.item.node.retainers); + else + return true; + } + return true; + } + } else + return false; + } + } + } else { + var node = new WebInspector.HeapSnapshotNode(this._snapshot, this._targetNodeIndex); + this._currentPath = [node.retainers]; + this._currentPath._cache = {}; + while (this._currentPath.length < this._maxLength) { + var iter = this._nextEdgeIter(); + if (iter.hasNext()) + this._appendToCurrentPath(iter.item.node.retainers); + else + break; + } + return true; + } + }, + + _nodeToString: function(node) + { + if (node.id === 1) + return node.name; + else + return node.name + "@" + node.id; + }, + + _pathToString: function(path) + { + if (!path) + return ""; + var sPath = []; + for (var j = 0; j < path.length; ++j) + sPath.push(path[j].item.toString()); + sPath.push(this._nodeToString(path[path.length - 1].item.node)); + sPath.reverse(); + return sPath.join(""); + }, + + _pathToRoute: function(path) + { + if (!path) + return []; + var route = []; + route.push(this._targetNodeIndex); + for (var i = 0; i < path.length; ++i) + route.push(path[i].item.nodeIndex); + route.reverse(); + return route; + } +}; + +WebInspector.HeapSnapshotsDiff = function(snapshot, className) +{ + this._snapshot = snapshot; + this._className = className; +}; + +WebInspector.HeapSnapshotsDiff.prototype = { + calculate: function() + { + var aggregates = this._snapshot.aggregates(true)[this._className]; + var indexes = aggregates ? aggregates.idxs : []; + var i = 0, l = this._baseIds.length; + var j = 0, m = indexes.length; + var diff = { addedCount: 0, removedCount: 0, addedSize: 0, removedSize: 0 }; + + var nodeB = new WebInspector.HeapSnapshotNode(this._snapshot, indexes[j]); + while (i < l && j < m) { + var nodeAId = this._baseIds[i]; + if (nodeAId < nodeB.id) { + diff.removedCount++; + diff.removedSize += this._baseSelfSizes[i]; + ++i; + } else if (nodeAId > nodeB.id) { + diff.addedCount++; + diff.addedSize += nodeB.selfSize; + nodeB.nodeIndex = indexes[++j]; + } else { + ++i; + nodeB.nodeIndex = indexes[++j]; + } + } + while (i < l) { + diff.removedCount++; + diff.removedSize += this._baseSelfSizes[i]; + ++i; + } + while (j < m) { + diff.addedCount++; + diff.addedSize += nodeB.selfSize; + nodeB.nodeIndex = indexes[++j]; + } + diff.countDelta = diff.addedCount - diff.removedCount; + diff.sizeDelta = diff.addedSize - diff.removedSize; + return diff; + }, + + pushBaseIds: function(baseIds) + { + this._baseIds = baseIds; + }, + + pushBaseSelfSizes: function(baseSelfSizes) + { + this._baseSelfSizes = baseSelfSizes; + } +}; +/* HeapSnapshotProxy.js */ + +/* + * Copyright (C) 2011 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 copyrightdd + * 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. + */ + +WebInspector.HeapSnapshotRealWorker = function() +{ + this._worker = new Worker("HeapSnapshotWorker.js"); + this._worker.addEventListener("message", this._messageReceived.bind(this), false); +} + +WebInspector.HeapSnapshotRealWorker.prototype = { + _messageReceived: function(event) + { + this.dispatchEventToListeners("message", event.data); + }, + + postMessage: function(message) + { + this._worker.postMessage(message); + }, + + terminate: function() + { + this._worker.terminate(); + } +}; + +WebInspector.HeapSnapshotRealWorker.prototype.__proto__ = WebInspector.Object.prototype; + +WebInspector.HeapSnapshotFakeWorker = function() +{ + this._dispatcher = new WebInspector.HeapSnapshotWorkerDispatcher(window, this._postMessageFromWorker.bind(this)); +} + +WebInspector.HeapSnapshotFakeWorker.prototype = { + postMessage: function(message) + { + function dispatch() + { + if (this._dispatcher) + this._dispatcher.dispatchMessage({data: message}); + } + setTimeout(dispatch.bind(this), 0); + }, + + terminate: function() + { + this._dispatcher = null; + }, + + _postMessageFromWorker: function(message) + { + function send() + { + this.dispatchEventToListeners("message", message); + } + setTimeout(send.bind(this), 0); + } +}; + +WebInspector.HeapSnapshotFakeWorker.prototype.__proto__ = WebInspector.Object.prototype; + +WebInspector.HeapSnapshotWorker = function() +{ + this._nextObjectId = 1; + this._nextCallId = 1; + this._callbacks = []; + this._previousCallbacks = []; + // There is no support for workers in Chromium DRT. + this._worker = typeof InspectorTest === "undefined" ? new WebInspector.HeapSnapshotRealWorker() : new WebInspector.HeapSnapshotFakeWorker(); + this._worker.addEventListener("message", this._messageReceived.bind(this), false); +} + +WebInspector.HeapSnapshotWorker.prototype = { + createObject: function(constructorName) + { + var proxyConstructorFunction = this._findFunction(constructorName + "Proxy"); + var objectId = this._nextObjectId++; + var proxy = new proxyConstructorFunction(this, objectId); + this._postMessage({callId: this._nextCallId++, disposition: "create", objectId: objectId, methodName: constructorName}); + return proxy; + }, + + dispose: function() + { + this._worker.terminate(); + if (this._interval) + clearInterval(this._interval); + }, + + disposeObject: function(objectId) + { + this._postMessage({callId: this._nextCallId++, disposition: "dispose", objectId: objectId}); + }, + + callGetter: function(callback, objectId, getterName) + { + var callId = this._nextCallId++; + this._callbacks[callId] = callback; + this._postMessage({callId: callId, disposition: "getter", objectId: objectId, methodName: getterName}); + }, + + callFactoryMethod: function(callback, objectId, methodName, proxyConstructorName) + { + var callId = this._nextCallId++; + var methodArguments = Array.prototype.slice.call(arguments, 4); + var newObjectId = this._nextObjectId++; + var proxyConstructorFunction = this._findFunction(proxyConstructorName); + if (callback) { + function wrapCallback(remoteResult) + { + callback(remoteResult ? new proxyConstructorFunction(this, newObjectId) : null); + } + this._callbacks[callId] = wrapCallback.bind(this); + this._postMessage({callId: callId, disposition: "factory", objectId: objectId, methodName: methodName, methodArguments: methodArguments, newObjectId: newObjectId}); + return null; + } else { + this._postMessage({callId: callId, disposition: "factory", objectId: objectId, methodName: methodName, methodArguments: methodArguments, newObjectId: newObjectId}); + return new proxyConstructorFunction(this, newObjectId); + } + }, + + callMethod: function(callback, objectId, methodName) + { + var callId = this._nextCallId++; + var methodArguments = Array.prototype.slice.call(arguments, 3); + if (callback) + this._callbacks[callId] = callback; + this._postMessage({callId: callId, disposition: "method", objectId: objectId, methodName: methodName, methodArguments: methodArguments}); + }, + + startCheckingForLongRunningCalls: function() + { + this._checkLongRunningCalls(); + this._interval = setInterval(this._checkLongRunningCalls.bind(this), 300); + }, + + _checkLongRunningCalls: function() + { + for (var callId in this._previousCallbacks) + if (!(callId in this._callbacks)) + delete this._previousCallbacks[callId]; + var hasLongRunningCalls = false; + for (callId in this._previousCallbacks) { + hasLongRunningCalls = true; + break; + } + this.dispatchEventToListeners("wait", hasLongRunningCalls); + for (callId in this._callbacks) + this._previousCallbacks[callId] = true; + }, + + _findFunction: function(name) + { + var path = name.split("."); + var result = window; + for (var i = 0; i < path.length; ++i) + result = result[path[i]]; + return result; + }, + + _messageReceived: function(event) + { + var data = event.data; + if (!this._callbacks[data.callId]) + return; + var callback = this._callbacks[data.callId]; + delete this._callbacks[data.callId]; + callback(data.result); + }, + + _postMessage: function(message) + { + this._worker.postMessage(message); + } +}; + +WebInspector.HeapSnapshotWorker.prototype.__proto__ = WebInspector.Object.prototype; + +WebInspector.HeapSnapshotProxyObject = function(worker, objectId) +{ + this._worker = worker; + this._objectId = objectId; +} + +WebInspector.HeapSnapshotProxyObject.prototype = { + _callWorker: function(workerMethodName, args) + { + args.splice(1, 0, this._objectId); + return this._worker[workerMethodName].apply(this._worker, args); + }, + + dispose: function() + { + this._worker.disposeObject(this._objectId); + }, + + disposeWorker: function() + { + this._worker.dispose(); + }, + + callFactoryMethod: function(callback, methodName, proxyConstructorName) + { + return this._callWorker("callFactoryMethod", Array.prototype.slice.call(arguments, 0)); + }, + + callGetter: function(callback, getterName) + { + return this._callWorker("callGetter", Array.prototype.slice.call(arguments, 0)); + }, + + callMethod: function(callback, methodName) + { + return this._callWorker("callMethod", Array.prototype.slice.call(arguments, 0)); + }, + + get worker() { + return this._worker; + } +}; + +WebInspector.HeapSnapshotLoaderProxy = function(worker, objectId) +{ + WebInspector.HeapSnapshotProxyObject.call(this, worker, objectId); + this._loading = false; + this._loaded = false; +} + +WebInspector.HeapSnapshotLoaderProxy.prototype = { + finishLoading: function(callback) + { + if (!this._loading) + return false; + var loadCallbacks = this._onLoadCallbacks; + loadCallbacks.splice(0, 0, callback); + delete this._onLoadCallbacks; + this._loading = false; + this._loaded = true; + function callLoadCallbacks(snapshotProxy) + { + for (var i = 0; i < loadCallbacks.length; ++i) + loadCallbacks[i](snapshotProxy); + } + function updateStaticData(snapshotProxy) + { + this.dispose(); + snapshotProxy.updateStaticData(callLoadCallbacks); + } + this.callFactoryMethod(updateStaticData.bind(this), "finishLoading", "WebInspector.HeapSnapshotProxy"); + return true; + }, + + get loaded() + { + return this._loaded; + }, + + startLoading: function(callback) + { + if (!this._loading) { + this._onLoadCallbacks = [callback]; + this._loading = true; + return true; + } else { + this._onLoadCallbacks.push(callback); + return false; + } + }, + + pushJSONChunk: function(chunk) + { + if (!this._loading) + return; + this.callMethod(null, "pushJSONChunk", chunk); + } +}; + +WebInspector.HeapSnapshotLoaderProxy.prototype.__proto__ = WebInspector.HeapSnapshotProxyObject.prototype; + +WebInspector.HeapSnapshotProxy = function(worker, objectId) +{ + WebInspector.HeapSnapshotProxyObject.call(this, worker, objectId); +} + +WebInspector.HeapSnapshotProxy.prototype = { + aggregates: function(sortedIndexes, key, filter, callback) + { + this.callMethod(callback, "aggregates", sortedIndexes, key, filter); + }, + + createDiff: function(className) + { + return this.callFactoryMethod(null, "createDiff", "WebInspector.HeapSnapshotsDiffProxy", className); + }, + + createEdgesProvider: function(nodeIndex, filter) + { + return this.callFactoryMethod(null, "createEdgesProvider", "WebInspector.HeapSnapshotProviderProxy", nodeIndex, filter); + }, + + createRetainingEdgesProvider: function(nodeIndex, filter) + { + return this.callFactoryMethod(null, "createRetainingEdgesProvider", "WebInspector.HeapSnapshotProviderProxy", nodeIndex, filter); + }, + + createNodesProvider: function(filter) + { + return this.callFactoryMethod(null, "createNodesProvider", "WebInspector.HeapSnapshotProviderProxy", filter); + }, + + createNodesProviderForClass: function(className, aggregatesKey) + { + return this.callFactoryMethod(null, "createNodesProviderForClass", "WebInspector.HeapSnapshotProviderProxy", className, aggregatesKey); + }, + + createNodesProviderForDominator: function(nodeIndex, filter) + { + return this.callFactoryMethod(null, "createNodesProviderForDominator", "WebInspector.HeapSnapshotProviderProxy", nodeIndex, filter); + }, + + createPathFinder: function(targetNodeIndex, skipHidden) + { + return this.callFactoryMethod(null, "createPathFinder", "WebInspector.HeapSnapshotPathFinderProxy", targetNodeIndex, skipHidden); + }, + + dispose: function() + { + this.disposeWorker(); + }, + + finishLoading: function() + { + return false; + }, + + get loaded() + { + return !!this._objectId; + }, + + get maxNodeId() + { + return this._staticData.maxNodeId; + }, + + get nodeCount() + { + return this._staticData.nodeCount; + }, + + nodeFieldValuesByIndex: function(fieldName, indexes, callback) + { + this.callMethod(callback, "nodeFieldValuesByIndex", fieldName, indexes); + }, + + get nodeFlags() + { + return this._staticData.nodeFlags; + }, + + pushBaseIds: function(snapshotId, className, nodeIds) + { + this.callMethod(null, "pushBaseIds", snapshotId, className, nodeIds); + }, + + get rootNodeIndex() + { + return this._staticData.rootNodeIndex; + }, + + updateStaticData: function(callback) + { + function dataReceived(staticData) + { + this._staticData = staticData; + callback(this); + } + this.callMethod(dataReceived.bind(this), "updateStaticData"); + }, + + startLoading: function(callback) + { + setTimeout(callback.bind(null, this), 0); + return false; + }, + + get totalSize() + { + return this._staticData.totalSize; + }, + + get uid() + { + return this._staticData.uid; + } +}; + +WebInspector.HeapSnapshotProxy.prototype.__proto__ = WebInspector.HeapSnapshotProxyObject.prototype; + +WebInspector.HeapSnapshotProviderProxy = function(worker, objectId) +{ + WebInspector.HeapSnapshotProxyObject.call(this, worker, objectId); +} + +WebInspector.HeapSnapshotProviderProxy.prototype = { + isEmpty: function(callback) + { + this.callGetter(callback, "isEmpty"); + }, + + serializeNextItems: function(count, callback) + { + this.callMethod(callback, "serializeNextItems", count); + }, + + sortAndRewind: function(comparator, callback) + { + this.callMethod(callback, "sortAndRewind", comparator); + } +}; + +WebInspector.HeapSnapshotProviderProxy.prototype.__proto__ = WebInspector.HeapSnapshotProxyObject.prototype; + +WebInspector.HeapSnapshotPathFinderProxy = function(worker, objectId) +{ + WebInspector.HeapSnapshotProxyObject.call(this, worker, objectId); +} + +WebInspector.HeapSnapshotPathFinderProxy.prototype = { + findNext: function(callback) + { + this.callMethod(callback, "findNext"); + }, + + updateRoots: function(filter) + { + this.callMethod(null, "updateRoots", filter); + } +}; + +WebInspector.HeapSnapshotPathFinderProxy.prototype.__proto__ = WebInspector.HeapSnapshotProxyObject.prototype; + +WebInspector.HeapSnapshotsDiffProxy = function(worker, objectId) +{ + WebInspector.HeapSnapshotProxyObject.call(this, worker, objectId); +} + +WebInspector.HeapSnapshotsDiffProxy.prototype = { + calculate: function(callback) + { + this.callMethod(callback, "calculate"); + }, + + pushBaseIds: function(baseIds) + { + this.callMethod(null, "pushBaseIds", baseIds); + }, + + pushBaseSelfSizes: function(baseSelfSizes) + { + this.callMethod(null, "pushBaseSelfSizes", baseSelfSizes); + } +}; + +WebInspector.HeapSnapshotsDiffProxy.prototype.__proto__ = WebInspector.HeapSnapshotProxyObject.prototype; +/* HeapSnapshotWorkerDispatcher.js */ + +/* + * Copyright (C) 2011 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. + */ + +WebInspector.HeapSnapshotWorkerDispatcher = function(globalObject, postMessage) +{ + this._objects = []; + this._global = globalObject; + this._postMessage = postMessage; +} + +WebInspector.HeapSnapshotWorkerDispatcher.prototype = { + _findFunction: function(name) + { + var path = name.split("."); + var result = this._global; + for (var i = 0; i < path.length; ++i) + result = result[path[i]]; + return result; + }, + + dispatchMessage: function(event) + { + var data = event.data; + switch (data.disposition) { + case "create": { + var constructorFunction = this._findFunction(data.methodName); + this._objects[data.objectId] = new constructorFunction(); + this._postMessage({callId: data.callId}); + break; + } + case "dispose": { + delete this._objects[data.objectId]; + this._postMessage({callId: data.callId}); + break; + } + case "getter": { + var object = this._objects[data.objectId]; + var result = object[data.methodName]; + this._postMessage({callId: data.callId, result: result}); + break; + } + case "factory": { + var object = this._objects[data.objectId]; + var result = object[data.methodName].apply(object, data.methodArguments); + if (result) + this._objects[data.newObjectId] = result; + this._postMessage({callId: data.callId, result: !!result}); + break; + } + case "method": { + var object = this._objects[data.objectId]; + var result = object[data.methodName].apply(object, data.methodArguments); + this._postMessage({callId: data.callId, result: result}); + break; + } + } + } +}; +/* DetailedHeapshotGridNodes.js */ + +/* + * Copyright (C) 2011 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. + */ + +WebInspector.HeapSnapshotGridNode = function(tree, hasChildren) +{ + WebInspector.DataGridNode.call(this, null, hasChildren); + this._defaultPopulateCount = tree._defaultPopulateCount; + this._provider = null; + this.addEventListener("populate", this._populate, this); +} + +WebInspector.HeapSnapshotGridNode.prototype = { + createCell: function(columnIdentifier) + { + var cell = WebInspector.DataGridNode.prototype.createCell.call(this, columnIdentifier); + if (this._searchMatched) + cell.addStyleClass("highlight"); + return cell; + }, + + dispose: function() + { + if (this._provider) + this._provider.dispose(); + for (var node = this.children[0]; node; node = node.traverseNextNode(true, this, true)) + if (node.dispose) + node.dispose(); + }, + + hasHoverMessage: false, + + queryObjectContent: function(callback) + { + }, + + _populate: function(event) + { + this.removeEventListener("populate", this._populate, this); + function sorted(ignored) + { + this.populateChildren(); + } + this._provider.sortAndRewind(this.comparator(), sorted.bind(this)); + }, + + populateChildren: function(provider, howMany, atIndex, afterPopulate, suppressNotifyAboutCompletion) + { + if (!howMany && provider) { + howMany = provider.instanceCount; + provider.instanceCount = 0; + } + provider = provider || this._provider; + if (!("instanceCount" in provider)) + provider.instanceCount = 0; + howMany = howMany || this._defaultPopulateCount; + atIndex = atIndex || this.children.length; + var haveSavedChildren = !!this._savedChildren; + if (haveSavedChildren) { + haveSavedChildren = false; + for (var c in this._savedChildren) { + haveSavedChildren = true; + break; + } + } + + var part = 0; + function callSerialize() + { + if (part >= howMany) + return; + part += this._defaultPopulateCount; + provider.serializeNextItems(this._defaultPopulateCount, childrenRetrieved.bind(this)); + } + function childrenRetrieved(items) + { + var length = items.totalLength; + for (var i = 0, l = items.length; i < l; ++i) { + var item = items[i]; + if (haveSavedChildren) { + var hash = this._childHashForEntity(item); + if (hash in this._savedChildren) { + this.insertChild(this._savedChildren[hash], atIndex++); + continue; + } + } + this.insertChild(this._createChildNode(item, provider, this), atIndex++); + } + provider.instanceCount += items.length; + if (part < howMany) { + setTimeout(callSerialize.bind(this), 0); + return; + } + + if (items.hasNext) + this.insertChild(new WebInspector.ShowMoreDataGridNode(this.populateChildren.bind(this, provider), this._defaultPopulateCount, length), atIndex++); + if (afterPopulate) + afterPopulate(); + if (!suppressNotifyAboutCompletion) { + function notify() + { + this.dispatchEventToListeners("populate complete"); + } + setTimeout(notify.bind(this), 0); + } + } + setTimeout(callSerialize.bind(this), 0); + }, + + _saveChildren: function() + { + this._savedChildren = {}; + for (var i = 0, childrenCount = this.children.length; i < childrenCount; ++i) { + var child = this.children[i]; + if (child.expanded) + this._savedChildren[this._childHashForNode(child)] = child; + } + }, + + sort: function() + { + this.dataGrid.recursiveSortingEnter(); + function afterSort(sorted) + { + if (!sorted) { + this.dataGrid.recursiveSortingLeave(); + return; + } + this._saveChildren(); + this.removeChildren(); + + function afterPopulate() + { + for (var i = 0, l = this.children.length; i < l; ++i) { + var child = this.children[i]; + if (child.expanded) + child.sort(); + } + this.dataGrid.recursiveSortingLeave(); + } + this.populateChildren(this._provider, null, null, afterPopulate.bind(this)); + } + this._provider.sortAndRewind(this.comparator(), afterSort.bind(this)); + } +}; + +WebInspector.HeapSnapshotGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype; + +WebInspector.HeapSnapshotGenericObjectNode = function(tree, node) +{ + WebInspector.HeapSnapshotGridNode.call(this, tree, false); + this._name = node.name; + this._type = node.type; + this._shallowSize = node.selfSize; + this._retainedSize = node.retainedSize; + this.snapshotNodeId = node.id; + this.snapshotNodeIndex = node.nodeIndex; + if (this._type === "string") + this.hasHoverMessage = true; + else if (this._type === "object" && this.isDOMWindow(this._name)) { + this._name = this.shortenWindowURL(this._name, false); + this.hasHoverMessage = true; + } else if (node.flags & tree.snapshot.nodeFlags.canBeQueried) + this.hasHoverMessage = true; + if (node.flags & tree.snapshot.nodeFlags.detachedDOMTreeNode) + this.detachedDOMTreeNode = true; +}; + +WebInspector.HeapSnapshotGenericObjectNode.prototype = { + createCell: function(columnIdentifier) + { + var cell = columnIdentifier !== "object" ? WebInspector.DataGridNode.prototype.createCell.call(this, columnIdentifier) : this._createObjectCell(); + if (this._searchMatched) + cell.addStyleClass("highlight"); + return cell; + }, + + _createObjectCell: function() + { + var cell = document.createElement("td"); + cell.className = "object-column"; + var div = document.createElement("div"); + div.className = "source-code event-properties"; + div.style.overflow = "hidden"; + var data = this.data["object"]; + if (this._prefixObjectCell) + this._prefixObjectCell(div, data); + var valueSpan = document.createElement("span"); + valueSpan.className = "value console-formatted-" + data.valueStyle; + valueSpan.textContent = data.value; + div.appendChild(valueSpan); + cell.appendChild(div); + cell.addStyleClass("disclosure"); + if (this.depth) + cell.style.setProperty("padding-left", (this.depth * this.dataGrid.indentWidth) + "px"); + return cell; + }, + + get _countPercent() + { + return this._count / this.dataGrid.snapshot.nodeCount * 100.0; + }, + + get data() + { + var data = this._emptyData(); + + var value = this._name; + var valueStyle = "object"; + switch (this._type) { + case "string": + value = "\"" + value + "\""; + valueStyle = "string"; + break; + case "regexp": + value = "/" + value + "/"; + valueStyle = "string"; + break; + case "closure": + value = "function " + value + "()"; + valueStyle = "function"; + break; + case "number": + valueStyle = "number"; + break; + case "hidden": + valueStyle = "null"; + break; + case "array": + if (!value) + value = "[]"; + else + value += " []"; + break; + }; + if (this.hasHoverMessage) + valueStyle += " highlight"; + if (this.detachedDOMTreeNode) + valueStyle += " detached-dom-tree-node"; + data["object"] = { valueStyle: valueStyle, value: value + " @" + this.snapshotNodeId }; + + var view = this.dataGrid.snapshotView; + data["shallowSize"] = view.showShallowSizeAsPercent ? WebInspector.UIString("%.2f%%", this._shallowSizePercent) : Number.bytesToString(this._shallowSize); + data["retainedSize"] = view.showRetainedSizeAsPercent ? WebInspector.UIString("%.2f%%", this._retainedSizePercent) : Number.bytesToString(this._retainedSize); + + return this._enhanceData ? this._enhanceData(data) : data; + }, + + queryObjectContent: function(callback) + { + if (this._type === "string") + callback(WebInspector.RemoteObject.fromPrimitiveValue(this._name)); + else { + function formatResult(error, object) + { + if (!error && object.type) + callback(WebInspector.RemoteObject.fromPayload(object), !!error); + else + callback(WebInspector.RemoteObject.fromPrimitiveValue(WebInspector.UIString("Not available"))); + } + ProfilerAgent.getObjectByHeapObjectId(this.snapshotNodeId, formatResult); + } + }, + + get _retainedSizePercent() + { + return this._retainedSize / this.dataGrid.snapshot.totalSize * 100.0; + }, + + get _shallowSizePercent() + { + return this._shallowSize / this.dataGrid.snapshot.totalSize * 100.0; + }, + + _updateHasChildren: function() + { + function isEmptyCallback(isEmpty) + { + this.hasChildren = !isEmpty; + } + this._provider.isEmpty(isEmptyCallback.bind(this)); + }, + + isDOMWindow: function(fullName) + { + return fullName.substr(0, 9) === "DOMWindow"; + }, + + shortenWindowURL: function(fullName, hasObjectId) + { + var startPos = fullName.indexOf("/"); + var endPos = hasObjectId ? fullName.indexOf("@") : fullName.length; + if (startPos !== -1 && endPos !== -1) { + var fullURL = fullName.substring(startPos + 1, endPos).trimLeft(); + var url = fullURL.trimURL(); + if (url.length > 40) + url = url.trimMiddle(40); + return fullName.substr(0, startPos + 2) + url + fullName.substr(endPos); + } else + return fullName; + } +} + +WebInspector.HeapSnapshotGenericObjectNode.prototype.__proto__ = WebInspector.HeapSnapshotGridNode.prototype; + +WebInspector.HeapSnapshotObjectNode = function(tree, isFromBaseSnapshot, edge) +{ + WebInspector.HeapSnapshotGenericObjectNode.call(this, tree, edge.node); + this._referenceName = edge.name; + this._referenceType = edge.type; + this._isFromBaseSnapshot = isFromBaseSnapshot; + this._provider = this._createProvider(!isFromBaseSnapshot ? tree.snapshot : tree.baseSnapshot, edge.nodeIndex, tree); + this._updateHasChildren(); +} + +WebInspector.HeapSnapshotObjectNode.prototype = { + _createChildNode: function(item) + { + return new WebInspector.HeapSnapshotObjectNode(this.dataGrid, this._isFromBaseSnapshot, item); + }, + + _createProvider: function(snapshot, nodeIndex, tree) + { + var showHiddenData = WebInspector.settings.showHeapSnapshotObjectsHiddenProperties.get(); + var filter = "function(edge) {" + + " return !edge.isInvisible" + + " && (" + showHiddenData + " || (!edge.isHidden && !edge.node.isHidden));" + + "}"; + if (tree.showRetainingEdges) + return snapshot.createRetainingEdgesProvider(nodeIndex, filter); + else + return snapshot.createEdgesProvider(nodeIndex, filter); + }, + + _childHashForEntity: function(edge) + { + return edge.type + "#" + edge.name; + }, + + _childHashForNode: function(childNode) + { + return childNode._referenceType + "#" + childNode._referenceName; + }, + + comparator: function() + { + var sortAscending = this.dataGrid.sortOrder === "ascending"; + var sortColumnIdentifier = this.dataGrid.sortColumnIdentifier; + var sortFields = { + object: ["!edgeName", sortAscending, "retainedSize", false], + count: ["!edgeName", true, "retainedSize", false], + shallowSize: ["selfSize", sortAscending, "!edgeName", true], + retainedSize: ["retainedSize", sortAscending, "!edgeName", true] + }[sortColumnIdentifier] || ["!edgeName", true, "retainedSize", false]; + return WebInspector.HeapSnapshotFilteredOrderedIterator.prototype.createComparator(sortFields); + }, + + _emptyData: function() + { + return {count:"", addedCount: "", removedCount: "", countDelta:"", addedSize: "", removedSize: "", sizeDelta: ""}; + }, + + _enhanceData: function(data) + { + var name = this._referenceName; + if (name === "") name = "(empty)"; + var nameClass = "name"; + switch (this._referenceType) { + case "context": + nameClass = "console-formatted-number"; + break; + case "internal": + case "hidden": + nameClass = "console-formatted-null"; + break; + } + data["object"].nameClass = nameClass; + data["object"].name = name; + return data; + }, + + _prefixObjectCell: function(div, data) + { + var nameSpan = document.createElement("span"); + nameSpan.className = data.nameClass; + nameSpan.textContent = data.name; + var separatorSpan = document.createElement("span"); + separatorSpan.className = "separator"; + separatorSpan.textContent = ": "; + div.appendChild(nameSpan); + div.appendChild(separatorSpan); + } +} + +WebInspector.HeapSnapshotObjectNode.prototype.__proto__ = WebInspector.HeapSnapshotGenericObjectNode.prototype; + +WebInspector.HeapSnapshotInstanceNode = function(tree, baseSnapshot, snapshot, node) +{ + WebInspector.HeapSnapshotGenericObjectNode.call(this, tree, node); + this._isDeletedNode = !!baseSnapshot; + this._provider = this._createProvider(baseSnapshot || snapshot, node.nodeIndex); + this._updateHasChildren(); +}; + +WebInspector.HeapSnapshotInstanceNode.prototype = { + _createChildNode: function(item) + { + return new WebInspector.HeapSnapshotObjectNode(this.dataGrid, this._isDeletedNode, item); + }, + + _createProvider: function(snapshot, nodeIndex) + { + var showHiddenData = WebInspector.DetailedHeapshotView.prototype.showHiddenData; + return snapshot.createEdgesProvider( + nodeIndex, + "function(edge) {" + + " return !edge.isInvisible" + + " && (" + showHiddenData + " || (!edge.isHidden && !edge.node.isHidden));" + + "}"); + }, + + _childHashForEntity: function(edge) + { + return edge.type + "#" + edge.name; + }, + + _childHashForNode: function(childNode) + { + return childNode._referenceType + "#" + childNode._referenceName; + }, + + comparator: function() + { + var sortAscending = this.dataGrid.sortOrder === "ascending"; + var sortColumnIdentifier = this.dataGrid.sortColumnIdentifier; + var sortFields = { + object: ["!edgeName", sortAscending, "retainedSize", false], + count: ["!edgeName", true, "retainedSize", false], + addedSize: ["selfSize", sortAscending, "!edgeName", true], + removedSize: ["selfSize", sortAscending, "!edgeName", true], + shallowSize: ["selfSize", sortAscending, "!edgeName", true], + retainedSize: ["retainedSize", sortAscending, "!edgeName", true] + }[sortColumnIdentifier] || ["!edgeName", true, "retainedSize", false]; + return WebInspector.HeapSnapshotFilteredOrderedIterator.prototype.createComparator(sortFields); + }, + + _emptyData: function() + { + return {count:"", countDelta:"", sizeDelta: ""}; + }, + + _enhanceData: function(data) + { + if (this._isDeletedNode) { + data["addedCount"] = ""; + data["addedSize"] = ""; + data["removedCount"] = "\u2022"; + data["removedSize"] = Number.bytesToString(this._shallowSize); + } else { + data["addedCount"] = "\u2022"; + data["addedSize"] = Number.bytesToString(this._shallowSize); + data["removedCount"] = ""; + data["removedSize"] = ""; + } + return data; + }, + + get isDeletedNode() + { + return this._isDeletedNode; + } +} + +WebInspector.HeapSnapshotInstanceNode.prototype.__proto__ = WebInspector.HeapSnapshotGenericObjectNode.prototype; + +WebInspector.HeapSnapshotConstructorNode = function(tree, className, aggregate, aggregatesKey) +{ + WebInspector.HeapSnapshotGridNode.call(this, tree, aggregate.count > 0); + this._name = className; + this._count = aggregate.count; + this._shallowSize = aggregate.self; + this._retainedSize = aggregate.maxRet; + this._provider = this._createNodesProvider(tree.snapshot, className, aggregatesKey); +} + +WebInspector.HeapSnapshotConstructorNode.prototype = { + _createChildNode: function(item) + { + return new WebInspector.HeapSnapshotInstanceNode(this.dataGrid, null, this.dataGrid.snapshot, item); + }, + + _createNodesProvider: function(snapshot, className, aggregatesKey) + { + return snapshot.createNodesProviderForClass(className, aggregatesKey); + }, + + comparator: function() + { + var sortAscending = this.dataGrid.sortOrder === "ascending"; + var sortColumnIdentifier = this.dataGrid.sortColumnIdentifier; + var sortFields = { + object: ["id", sortAscending, "retainedSize", false], + count: ["id", true, "retainedSize", false], + shallowSize: ["selfSize", sortAscending, "id", true], + retainedSize: ["retainedSize", sortAscending, "id", true] + }[sortColumnIdentifier]; + return WebInspector.HeapSnapshotFilteredOrderedIterator.prototype.createComparator(sortFields); + }, + + _childHashForEntity: function(node) + { + return node.id; + }, + + _childHashForNode: function(childNode) + { + return childNode.snapshotNodeId; + }, + + get data() + { + var data = {object: this._name, count: this._count}; + var view = this.dataGrid.snapshotView; + data["count"] = view.showCountAsPercent ? WebInspector.UIString("%.2f%%", this._countPercent) : this._count; + data["shallowSize"] = view.showShallowSizeAsPercent ? WebInspector.UIString("%.2f%%", this._shallowSizePercent) : Number.bytesToString(this._shallowSize); + data["retainedSize"] = "> " + (view.showRetainedSizeAsPercent ? WebInspector.UIString("%.2f%%", this._retainedSizePercent) : Number.bytesToString(this._retainedSize)); + return data; + }, + + get _countPercent() + { + return this._count / this.dataGrid.snapshot.nodeCount * 100.0; + }, + + get _retainedSizePercent() + { + return this._retainedSize / this.dataGrid.snapshot.totalSize * 100.0; + }, + + get _shallowSizePercent() + { + return this._shallowSize / this.dataGrid.snapshot.totalSize * 100.0; + } +}; + +WebInspector.HeapSnapshotConstructorNode.prototype.__proto__ = WebInspector.HeapSnapshotGridNode.prototype; + +WebInspector.HeapSnapshotIteratorsTuple = function(it1, it2) +{ + this._it1 = it1; + this._it2 = it2; +} + +WebInspector.HeapSnapshotIteratorsTuple.prototype = { + dispose: function() + { + this._it1.dispose(); + this._it2.dispose(); + }, + + sortAndRewind: function(comparator, callback) + { + function afterSort(ignored) + { + this._it2.sortAndRewind(comparator, callback); + } + this._it1.sortAndRewind(comparator, afterSort.bind(this)); + } +}; + +WebInspector.HeapSnapshotDiffNode = function(tree, className, baseAggregate, aggregate) +{ + WebInspector.HeapSnapshotGridNode.call(this, tree, true); + this._name = className; + this._baseIndexes = baseAggregate ? baseAggregate.idxs : []; + this._indexes = aggregate ? aggregate.idxs : []; + this._provider = this._createNodesProvider(tree.baseSnapshot, tree.snapshot, aggregate ? aggregate.type : baseAggregate.type, className); +} + +WebInspector.HeapSnapshotDiffNode.prototype = { + calculateDiff: function(dataGrid, callback) + { + var diff = dataGrid.snapshot.createDiff(this._name); + + function diffCalculated(diffResult) + { + diff.dispose(); + this._addedCount = diffResult.addedCount; + this._removedCount = diffResult.removedCount; + this._countDelta = diffResult.countDelta; + this._addedSize = diffResult.addedSize; + this._removedSize = diffResult.removedSize; + this._sizeDelta = diffResult.sizeDelta; + this._baseIndexes = null; + this._indexes = null; + callback(this._addedSize === 0 && this._removedSize === 0); + } + function baseSelfSizesReceived(baseSelfSizes) + { + diff.pushBaseSelfSizes(baseSelfSizes); + diff.calculate(diffCalculated.bind(this)); + } + function baseIdsReceived(baseIds) + { + diff.pushBaseIds(baseIds); + dataGrid.snapshot.pushBaseIds(dataGrid.baseSnapshot.uid, this._name, baseIds); + dataGrid.baseSnapshot.nodeFieldValuesByIndex("selfSize", this._baseIndexes, baseSelfSizesReceived.bind(this)); + } + function idsReceived(ids) + { + dataGrid.baseSnapshot.pushBaseIds(dataGrid.snapshot.uid, this._name, ids); + } + dataGrid.baseSnapshot.nodeFieldValuesByIndex("id", this._baseIndexes, baseIdsReceived.bind(this)); + dataGrid.snapshot.nodeFieldValuesByIndex("id", this._indexes, idsReceived.bind(this)); + }, + + _createChildNode: function(item, provider) + { + if (provider === this._provider._it1) + return new WebInspector.HeapSnapshotInstanceNode(this.dataGrid, null, provider.snapshot, item); + else + return new WebInspector.HeapSnapshotInstanceNode(this.dataGrid, provider.snapshot, null, item); + }, + + _createNodesProvider: function(baseSnapshot, snapshot, nodeType, nodeClassName) + { + var className = this._name; + return new WebInspector.HeapSnapshotIteratorsTuple( + createProvider(snapshot, baseSnapshot), createProvider(baseSnapshot, snapshot)); + + function createProvider(snapshot, otherSnapshot) + { + var otherSnapshotId = otherSnapshot.uid; + var provider = snapshot.createNodesProvider( + "function (node) {" + + " return node.type === \"" + nodeType + "\" " + + (nodeClassName !== null ? "&& node.className === \"" + nodeClassName + "\"" : "") + + " && !this.baseSnapshotHasNode(" + otherSnapshotId + ", \"" + className + "\", node.id);" + + "}"); + provider.snapshot = snapshot; + return provider; + } + }, + + _childHashForEntity: function(node) + { + return node.id; + }, + + _childHashForNode: function(childNode) + { + return childNode.snapshotNodeId; + }, + + comparator: function() + { + var sortAscending = this.dataGrid.sortOrder === "ascending"; + var sortColumnIdentifier = this.dataGrid.sortColumnIdentifier; + var sortFields = { + object: ["id", sortAscending, "selfSize", false], + addedCount: ["selfSize", sortAscending, "id", true], + removedCount: ["selfSize", sortAscending, "id", true], + countDelta: ["selfSize", sortAscending, "id", true], + addedSize: ["selfSize", sortAscending, "id", true], + removedSize: ["selfSize", sortAscending, "id", true], + sizeDelta: ["selfSize", sortAscending, "id", true] + }[sortColumnIdentifier]; + return WebInspector.HeapSnapshotFilteredOrderedIterator.prototype.createComparator(sortFields); + }, + + populateChildren: function(provider, howMany, atIndex, afterPopulate) + { + if (!provider && !howMany) { + var firstProviderPopulated = function() + { + WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, this._provider._it2, this._defaultPopulateCount, atIndex, afterPopulate); + }; + WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, this._provider._it1, this._defaultPopulateCount, atIndex, firstProviderPopulated.bind(this), true); + } else if (!howMany) { + var firstProviderPopulated = function() + { + WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, this._provider._it2, null, atIndex, afterPopulate); + }; + WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, this._provider._it1, null, atIndex, firstProviderPopulated.bind(this), true); + } else + WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, provider, howMany, atIndex, afterPopulate); + }, + + _signForDelta: function(delta) + { + if (delta === 0) + return ""; + if (delta > 0) + return "+"; + else + return "\u2212"; // Math minus sign, same width as plus. + }, + + get data() + { + var data = {object: this._name}; + + data["addedCount"] = this._addedCount; + data["removedCount"] = this._removedCount; + data["countDelta"] = WebInspector.UIString("%s%d", this._signForDelta(this._countDelta), Math.abs(this._countDelta)); + data["addedSize"] = Number.bytesToString(this._addedSize); + data["removedSize"] = Number.bytesToString(this._removedSize); + data["sizeDelta"] = WebInspector.UIString("%s%s", this._signForDelta(this._sizeDelta), Number.bytesToString(Math.abs(this._sizeDelta))); + + return data; + } +}; + +WebInspector.HeapSnapshotDiffNode.prototype.__proto__ = WebInspector.HeapSnapshotGridNode.prototype; + +WebInspector.HeapSnapshotDominatorObjectNode = function(tree, node) +{ + WebInspector.HeapSnapshotGenericObjectNode.call(this, tree, node); + this._provider = this._createProvider(tree.snapshot, node.nodeIndex); + this._updateHasChildren(); +}; + +WebInspector.HeapSnapshotDominatorObjectNode.prototype = { + _createChildNode: function(item) + { + return new WebInspector.HeapSnapshotDominatorObjectNode(this.dataGrid, item); + }, + + _createProvider: function(snapshot, nodeIndex) + { + var showHiddenData = WebInspector.DetailedHeapshotView.prototype.showHiddenData; + return snapshot.createNodesProviderForDominator(nodeIndex, + "function (node) {" + + " return " + showHiddenData + " || !node.isHidden;" + + "}"); + }, + + _childHashForEntity: function(node) + { + return node.id; + }, + + _childHashForNode: function(childNode) + { + return childNode.snapshotNodeId; + }, + + comparator: function() + { + var sortAscending = this.dataGrid.sortOrder === "ascending"; + var sortColumnIdentifier = this.dataGrid.sortColumnIdentifier; + var sortFields = { + object: ["id", sortAscending, "retainedSize", false], + shallowSize: ["selfSize", sortAscending, "id", true], + retainedSize: ["retainedSize", sortAscending, "id", true] + }[sortColumnIdentifier]; + return WebInspector.HeapSnapshotFilteredOrderedIterator.prototype.createComparator(sortFields); + }, + + _emptyData: function() + { + return {}; + } +}; + +WebInspector.HeapSnapshotDominatorObjectNode.prototype.__proto__ = WebInspector.HeapSnapshotGenericObjectNode.prototype; + +function MixInSnapshotNodeFunctions(sourcePrototype, targetPrototype) +{ + targetPrototype._childHashForEntity = sourcePrototype._childHashForEntity; + targetPrototype._childHashForNode = sourcePrototype._childHashForNode; + targetPrototype.comparator = sourcePrototype.comparator; + targetPrototype._createChildNode = sourcePrototype._createChildNode; + targetPrototype._createProvider = sourcePrototype._createProvider; + targetPrototype.dispose = sourcePrototype.dispose; + targetPrototype.populateChildren = sourcePrototype.populateChildren; + targetPrototype._saveChildren = sourcePrototype._saveChildren; + targetPrototype.sort = sourcePrototype.sort; +} +/* DetailedHeapshotView.js */ + +/* + * Copyright (C) 2011 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. + */ + +WebInspector.HeapSnapshotSortableDataGrid = function(columns) +{ + WebInspector.DataGrid.call(this, columns); + this.addEventListener("sorting changed", this.sortingChanged, this); +} + +WebInspector.HeapSnapshotSortableDataGrid.prototype = { + dispose: function() + { + for (var i = 0, l = this.children.length; i < l; ++i) + this.children[i].dispose(); + }, + + resetSortingCache: function() + { + delete this._lastSortColumnIdentifier; + delete this._lastSortAscending; + }, + + sortingChanged: function() + { + var sortAscending = this.sortOrder === "ascending"; + var sortColumnIdentifier = this.sortColumnIdentifier; + if (this._lastSortColumnIdentifier === sortColumnIdentifier && this._lastSortAscending === sortAscending) + return; + this._lastSortColumnIdentifier = sortColumnIdentifier; + this._lastSortAscending = sortAscending; + var sortFields = this._sortFields(sortColumnIdentifier, sortAscending); + + function SortByTwoFields(nodeA, nodeB) + { + var field1 = nodeA[sortFields[0]]; + var field2 = nodeB[sortFields[0]]; + var result = field1 < field2 ? -1 : (field1 > field2 ? 1 : 0); + if (!sortFields[1]) + result = -result; + if (result !== 0) + return result; + field1 = nodeA[sortFields[2]]; + field2 = nodeB[sortFields[2]]; + result = field1 < field2 ? -1 : (field1 > field2 ? 1 : 0); + if (!sortFields[3]) + result = -result; + return result; + } + this._performSorting(SortByTwoFields); + }, + + _performSorting: function(sortFunction) + { + this.recursiveSortingEnter(); + var children = this.children; + this.removeChildren(); + children.sort(sortFunction); + for (var i = 0, l = children.length; i < l; ++i) { + var child = children[i]; + this.appendChild(child); + if (child.expanded) + child.sort(); + } + this.recursiveSortingLeave(); + }, + + recursiveSortingEnter: function() + { + if (!("_recursiveSortingDepth" in this)) + this._recursiveSortingDepth = 1; + else + ++this._recursiveSortingDepth; + }, + + recursiveSortingLeave: function() + { + if (!("_recursiveSortingDepth" in this)) + return; + if (!--this._recursiveSortingDepth) { + delete this._recursiveSortingDepth; + this.dispatchEventToListeners("sorting complete"); + } + } +}; + +WebInspector.HeapSnapshotSortableDataGrid.prototype.__proto__ = WebInspector.DataGrid.prototype; + +WebInspector.HeapSnapshotContainmentDataGrid = function() +{ + var columns = { + object: { title: WebInspector.UIString("Object"), disclosure: true, sortable: true, sort: "ascending" }, + shallowSize: { title: WebInspector.UIString("Shallow Size"), width: "90px", sortable: true }, + retainedSize: { title: WebInspector.UIString("Retained Size"), width: "90px", sortable: true } + }; + WebInspector.HeapSnapshotSortableDataGrid.call(this, columns); +} + +WebInspector.HeapSnapshotContainmentDataGrid.prototype = { + _defaultPopulateCount: 100, + + expandRoute: function(route) + { + function nextStep(parent, hopIndex) + { + if (hopIndex >= route.length) { + parent.element.scrollIntoViewIfNeeded(true); + parent.select(); + return; + } + var nodeIndex = route[hopIndex]; + for (var i = 0, l = parent.children.length; i < l; ++i) { + var child = parent.children[i]; + if (child.snapshotNodeIndex === nodeIndex) { + if (child.expanded) + nextStep(child, hopIndex + 1); + else { + function afterExpand() + { + child.removeEventListener("populate complete", afterExpand, null); + var lastChild = child.children[child.children.length - 1]; + if (!lastChild.showAll) + nextStep(child, hopIndex + 1); + else { + child.addEventListener("populate complete", afterExpand, null); + lastChild.showAll.click(); + } + } + child.addEventListener("populate complete", afterExpand, null); + child.expand(); + } + break; + } + } + } + nextStep(this, 0); + }, + + setDataSource: function(snapshotView, snapshot, nodeIndex) + { + this.snapshotView = snapshotView; + this.snapshot = snapshot; + this.snapshotNodeIndex = nodeIndex || this.snapshot.rootNodeIndex; + this._provider = this._createProvider(snapshot, this.snapshotNodeIndex, this); + this.sort(); + }, + + sortingChanged: function() + { + this.sort(); + } +}; + +MixInSnapshotNodeFunctions(WebInspector.HeapSnapshotObjectNode.prototype, WebInspector.HeapSnapshotContainmentDataGrid.prototype); +WebInspector.HeapSnapshotContainmentDataGrid.prototype.__proto__ = WebInspector.HeapSnapshotSortableDataGrid.prototype; + +WebInspector.HeapSnapshotRetainmentDataGrid = function() +{ + this.showRetainingEdges = true; + WebInspector.HeapSnapshotContainmentDataGrid.call(this); +} + +WebInspector.HeapSnapshotRetainmentDataGrid.prototype = { + reset: function() + { + this.removeChildren(); + this.resetSortingCache(); + }, +} + +WebInspector.HeapSnapshotRetainmentDataGrid.prototype.__proto__ = WebInspector.HeapSnapshotContainmentDataGrid.prototype; + +WebInspector.HeapSnapshotConstructorsDataGrid = function() +{ + var columns = { + object: { title: WebInspector.UIString("Constructor"), disclosure: true, sortable: true }, + count: { title: WebInspector.UIString("#"), width: "45px", sortable: true }, + shallowSize: { title: WebInspector.UIString("Shallow Size"), width: "90px", sortable: true }, + retainedSize: { title: WebInspector.UIString("Retained Size"), width: "90px", sort: "descending", sortable: true } + }; + WebInspector.HeapSnapshotSortableDataGrid.call(this, columns); + this._filterProfileIndex = -1; +} + +WebInspector.HeapSnapshotConstructorsDataGrid.prototype = { + _defaultPopulateCount: 100, + + _sortFields: function(sortColumn, sortAscending) + { + return { + object: ["_name", sortAscending, "_count", false], + count: ["_count", sortAscending, "_name", true], + shallowSize: ["_shallowSize", sortAscending, "_name", true], + retainedSize: ["_retainedSize", sortAscending, "_name", true] + }[sortColumn]; + }, + + setDataSource: function(snapshotView, snapshot) + { + this.snapshotView = snapshotView; + this.snapshot = snapshot; + if (this._filterProfileIndex === -1) + this.populateChildren(); + }, + + populateChildren: function() + { + function aggregatesReceived(key, aggregates) + { + for (var constructor in aggregates) + this.appendChild(new WebInspector.HeapSnapshotConstructorNode(this, constructor, aggregates[constructor], key)); + this.sortingChanged(); + } + + if (this._filterProfileIndex === -1) { + this.snapshot.aggregates(false, "allObjects", null, aggregatesReceived.bind(this, "allObjects")); + return; + } + + this.dispose(); + this.removeChildren(); + this.resetSortingCache(); + + var key = this._minNodeId + ".." + this._maxNodeId; + var filter = "function(node) { var id = node.id; return id > " + this._minNodeId + " && id <= " + this._maxNodeId + "; }"; + this.snapshot.aggregates(false, key, filter, aggregatesReceived.bind(this, key)); + }, + + _filterSelectIndexChanged: function(loader, profileIndex) + { + this._filterProfileIndex = profileIndex; + + delete this._maxNodeId; + delete this._minNodeId; + + if (this._filterProfileIndex === -1) { + this.populateChildren(); + return; + } + + function firstSnapshotLoaded(snapshot) + { + this._maxNodeId = snapshot.maxNodeId; + if (profileIndex > 0) + loader(profileIndex - 1, secondSnapshotLoaded.bind(this)); + else { + this._minNodeId = 0; + this.populateChildren(); + } + } + + function secondSnapshotLoaded(snapshot) + { + this._minNodeId = snapshot.maxNodeId; + this.populateChildren(); + } + + loader(profileIndex, firstSnapshotLoaded.bind(this)); + }, +}; + +WebInspector.HeapSnapshotConstructorsDataGrid.prototype.__proto__ = WebInspector.HeapSnapshotSortableDataGrid.prototype; + +WebInspector.HeapSnapshotDiffDataGrid = function() +{ + var columns = { + object: { title: WebInspector.UIString("Constructor"), disclosure: true, sortable: true }, + addedCount: { title: WebInspector.UIString("# New"), width: "72px", sortable: true, sort: "descending" }, + removedCount: { title: WebInspector.UIString("# Deleted"), width: "72px", sortable: true }, + // \u0394 is a Greek delta letter. + countDelta: { title: "\u0394", width: "40px", sortable: true }, + addedSize: { title: WebInspector.UIString("Alloc. Size"), width: "72px", sortable: true }, + removedSize: { title: WebInspector.UIString("Freed Size"), width: "72px", sortable: true }, + sizeDelta: { title: "\u0394", width: "72px", sortable: true } + }; + WebInspector.HeapSnapshotSortableDataGrid.call(this, columns); +} + +WebInspector.HeapSnapshotDiffDataGrid.prototype = { + _defaultPopulateCount: 50, + + _sortFields: function(sortColumn, sortAscending) + { + return { + object: ["_name", sortAscending, "_count", false], + addedCount: ["_addedCount", sortAscending, "_name", true], + removedCount: ["_removedCount", sortAscending, "_name", true], + countDelta: ["_countDelta", sortAscending, "_name", true], + addedSize: ["_addedSize", sortAscending, "_name", true], + removedSize: ["_removedSize", sortAscending, "_name", true], + sizeDelta: ["_sizeDelta", sortAscending, "_name", true] + }[sortColumn]; + }, + + setDataSource: function(snapshotView, snapshot) + { + this.snapshotView = snapshotView; + this.snapshot = snapshot; + }, + + _baseProfileIndexChanged: function(loader, profileIndex) + { + loader(profileIndex, this.setBaseDataSource.bind(this)); + }, + + setBaseDataSource: function(baseSnapshot) + { + this.baseSnapshot = baseSnapshot; + this.dispose(); + this.removeChildren(); + this.resetSortingCache(); + if (this.baseSnapshot === this.snapshot) { + this.dispatchEventToListeners("sorting complete"); + return; + } + this.populateChildren(); + }, + + populateChildren: function() + { + function baseAggregatesReceived(baseClasses) + { + function aggregatesReceived(classes) + { + var nodeCount = 0; + var nodes = []; + for (var clss in baseClasses) + nodes.push(new WebInspector.HeapSnapshotDiffNode(this, clss, baseClasses[clss], classes[clss])); + for (clss in classes) { + if (!(clss in baseClasses)) + nodes.push(new WebInspector.HeapSnapshotDiffNode(this, clss, null, classes[clss])); + } + nodeCount = nodes.length; + function addNodeIfNonZeroDiff(boundNode, zeroDiff) + { + if (!zeroDiff) + this.appendChild(boundNode); + if (!--nodeCount) + this.sortingChanged(); + } + for (var i = 0, l = nodes.length; i < l; ++i) { + var node = nodes[i]; + node.calculateDiff(this, addNodeIfNonZeroDiff.bind(this, node)); + } + } + this.snapshot.aggregates(true, "allObjects", null, aggregatesReceived.bind(this)); + } + this.baseSnapshot.aggregates(true, "allObjects", null, baseAggregatesReceived.bind(this)); + } +}; + +WebInspector.HeapSnapshotDiffDataGrid.prototype.__proto__ = WebInspector.HeapSnapshotSortableDataGrid.prototype; + +WebInspector.HeapSnapshotDominatorsDataGrid = function() +{ + var columns = { + object: { title: WebInspector.UIString("Object"), disclosure: true, sortable: true }, + shallowSize: { title: WebInspector.UIString("Shallow Size"), width: "90px", sortable: true }, + retainedSize: { title: WebInspector.UIString("Retained Size"), width: "90px", sort: "descending", sortable: true } + }; + WebInspector.HeapSnapshotSortableDataGrid.call(this, columns); +} + +WebInspector.HeapSnapshotDominatorsDataGrid.prototype = { + _defaultPopulateCount: 25, + + setDataSource: function(snapshotView, snapshot) + { + this.snapshotView = snapshotView; + this.snapshot = snapshot; + this.snapshotNodeIndex = this.snapshot.rootNodeIndex; + this._provider = this._createProvider(snapshot, this.snapshotNodeIndex); + this.sort(); + }, + + sortingChanged: function() + { + this.sort(); + } +}; + +MixInSnapshotNodeFunctions(WebInspector.HeapSnapshotDominatorObjectNode.prototype, WebInspector.HeapSnapshotDominatorsDataGrid.prototype); +WebInspector.HeapSnapshotDominatorsDataGrid.prototype.__proto__ = WebInspector.HeapSnapshotSortableDataGrid.prototype; + +WebInspector.DetailedHeapshotView = function(parent, profile) +{ + WebInspector.View.call(this); + + this.element.addStyleClass("detailed-heapshot-view"); + + this.parent = parent; + this.parent.addEventListener("profile added", this._updateBaseOptions, this); + this.parent.addEventListener("profile added", this._updateFilterOptions, this); + + this.showCountAsPercent = false; + this.showShallowSizeAsPercent = false; + this.showRetainedSizeAsPercent = false; + + this.viewsContainer = document.createElement("div"); + this.viewsContainer.addStyleClass("views-container"); + this.element.appendChild(this.viewsContainer); + + this.containmentView = new WebInspector.View(); + this.containmentView.element.addStyleClass("view"); + this.containmentDataGrid = new WebInspector.HeapSnapshotContainmentDataGrid(); + this.containmentDataGrid.element.addEventListener("click", this._mouseClickInContentsGrid.bind(this), true); + this.containmentDataGrid.element.addEventListener("mousedown", this._mouseDownInContentsGrid.bind(this), true); + this.containmentDataGrid.show(this.containmentView.element); + + this.constructorsView = new WebInspector.View(); + this.constructorsView.element.addStyleClass("view"); + this.constructorsDataGrid = new WebInspector.HeapSnapshotConstructorsDataGrid(); + this.constructorsDataGrid.element.addEventListener("click", this._mouseClickInContentsGrid.bind(this), true); + this.constructorsDataGrid.element.addEventListener("mousedown", this._mouseDownInContentsGrid.bind(this), true); + this.constructorsDataGrid.show(this.constructorsView.element); + + this.diffView = new WebInspector.View(); + this.diffView.element.addStyleClass("view"); + this.diffDataGrid = new WebInspector.HeapSnapshotDiffDataGrid(); + this.diffDataGrid.element.addEventListener("click", this._mouseClickInContentsGrid.bind(this), true); + this.diffDataGrid.show(this.diffView.element); + + this.dominatorView = new WebInspector.View(); + this.dominatorView.element.addStyleClass("view"); + this.dominatorDataGrid = new WebInspector.HeapSnapshotDominatorsDataGrid(); + this.dominatorDataGrid.element.addEventListener("click", this._mouseClickInContentsGrid.bind(this), true); + this.dominatorDataGrid.element.addEventListener("mousedown", this._mouseDownInContentsGrid.bind(this), true); + this.dominatorDataGrid.show(this.dominatorView.element); + + this.retainmentViewHeader = document.createElement("div"); + this.retainmentViewHeader.addStyleClass("retainers-view-header"); + this.retainmentViewHeader.addEventListener("mousedown", this._startRetainersHeaderDragging.bind(this), true); + var retainingPathsTitleDiv = document.createElement("div"); + retainingPathsTitleDiv.className = "title"; + var retainingPathsTitle = document.createElement("span"); + retainingPathsTitle.textContent = WebInspector.UIString("Object's retaining tree"); + retainingPathsTitleDiv.appendChild(retainingPathsTitle); + this.retainmentViewHeader.appendChild(retainingPathsTitleDiv); + this.element.appendChild(this.retainmentViewHeader); + + this.retainmentView = new WebInspector.View(); + this.retainmentView.element.addStyleClass("view"); + this.retainmentView.element.addStyleClass("retaining-paths-view"); + this.retainmentDataGrid = new WebInspector.HeapSnapshotRetainmentDataGrid(); + this.retainmentDataGrid.element.addEventListener("click", this._mouseClickInRetainmentGrid.bind(this), true); + this.retainmentDataGrid.show(this.retainmentView.element); + this.retainmentView.show(this.element); + this.retainmentDataGrid.reset(); + + this.dataGrid = this.constructorsDataGrid; + this.currentView = this.constructorsView; + + this.viewSelectElement = document.createElement("select"); + this.viewSelectElement.className = "status-bar-item"; + this.viewSelectElement.addEventListener("change", this._changeView.bind(this), false); + + this.views = [{title: "Summary", view: this.constructorsView, grid: this.constructorsDataGrid}, + {title: "Comparison", view: this.diffView, grid: this.diffDataGrid}, + {title: "Containment", view: this.containmentView, grid: this.containmentDataGrid}, + {title: "Dominators", view: this.dominatorView, grid: this.dominatorDataGrid}]; + this.views.current = 0; + for (var i = 0; i < this.views.length; ++i) { + var view = this.views[i]; + var option = document.createElement("option"); + option.label = WebInspector.UIString(view.title); + this.viewSelectElement.appendChild(option); + } + + this._profileUid = profile.uid; + + this.baseSelectElement = document.createElement("select"); + this.baseSelectElement.className = "status-bar-item hidden"; + this.baseSelectElement.addEventListener("change", this._changeBase.bind(this), false); + this._updateBaseOptions(); + + this.filterSelectElement = document.createElement("select"); + this.filterSelectElement.className = "status-bar-item"; + this.filterSelectElement.addEventListener("change", this._changeFilter.bind(this), false); + this._updateFilterOptions(); + + this.percentButton = new WebInspector.StatusBarButton("", "percent-time-status-bar-item status-bar-item"); + this.percentButton.addEventListener("click", this._percentClicked.bind(this), false); + this.helpButton = new WebInspector.StatusBarButton("", "heapshot-help-status-bar-item status-bar-item"); + this.helpButton.addEventListener("click", this._helpClicked.bind(this), false); + + var popoverHelper = new WebInspector.ObjectPopoverHelper(this.element, this._getHoverAnchor.bind(this), this._showObjectPopover.bind(this), null, true); + + this._loadProfile(this._profileUid, profileCallback.bind(this)); + + function profileCallback() + { + var list = this._profiles(); + var profileIndex; + for (var i = 0; i < list.length; ++i) { + if (list[i].uid === this._profileUid) { + profileIndex = i; + break; + } + } + + if (profileIndex > 0) + this.baseSelectElement.selectedIndex = profileIndex - 1; + else + this.baseSelectElement.selectedIndex = profileIndex; + this.dataGrid.setDataSource(this, this.profileWrapper); + this._updatePercentButton(); + } +} + +WebInspector.DetailedHeapshotView.prototype = { + dispose: function() + { + this.profileWrapper.dispose(); + if (this.baseProfile) + this.baseProfileWrapper.dispose(); + this.containmentDataGrid.dispose(); + this.constructorsDataGrid.dispose(); + this.diffDataGrid.dispose(); + this.dominatorDataGrid.dispose(); + this.retainmentDataGrid.dispose(); + }, + + get statusBarItems() + { + return [this.viewSelectElement, this.baseSelectElement, this.filterSelectElement, this.percentButton.element, this.helpButton.element]; + }, + + get profile() + { + return this.parent.getProfile(WebInspector.DetailedHeapshotProfileType.TypeId, this._profileUid); + }, + + get profileWrapper() + { + return this.profile.proxy; + }, + + get baseProfile() + { + return this.parent.getProfile(WebInspector.DetailedHeapshotProfileType.TypeId, this._baseProfileUid); + }, + + get baseProfileWrapper() + { + return this.baseProfile.proxy; + }, + + wasShown: function() + { + if (!this.profileWrapper.loaded) + this._loadProfile(this._profileUid, profileCallback1.bind(this)); + else + profileCallback1.call(this); + + function profileCallback1() { + if (this.baseProfile && !this.baseProfileWrapper.loaded) + this._loadProfile(this._baseProfileUid, profileCallback2.bind(this)); + else + profileCallback2.call(this); + } + + function profileCallback2() { + this.currentView.show(this.viewsContainer); + } + }, + + willHide: function() + { + this._currentSearchResultIndex = -1; + }, + + onResize: function() + { + var height = this.retainmentView.element.clientHeight; + this._updateRetainmentViewHeight(height); + }, + + refreshShowAsPercents: function() + { + this._updatePercentButton(); + this.refreshVisibleData(); + }, + + searchCanceled: function() + { + if (this._searchResults) { + for (var i = 0; i < this._searchResults.length; ++i) { + var node = this._searchResults[i].node; + delete node._searchMatched; + node.refresh(); + } + } + + delete this._searchFinishedCallback; + this._currentSearchResultIndex = -1; + this._searchResults = []; + }, + + performSearch: function(query, finishedCallback) + { + // Call searchCanceled since it will reset everything we need before doing a new search. + this.searchCanceled(); + + query = query.trim(); + + if (!query.length) + return; + if (this.currentView !== this.constructorsView && this.currentView !== this.diffView) + return; + + this._searchFinishedCallback = finishedCallback; + + function matchesByName(gridNode) { + return ("name" in gridNode) && gridNode.name.hasSubstring(query, true); + } + + function matchesById(gridNode) { + return ("snapshotNodeId" in gridNode) && gridNode.snapshotNodeId === query; + } + + var matchPredicate; + if (query.charAt(0) !== "@") + matchPredicate = matchesByName; + else { + query = parseInt(query.substring(1), 10); + matchPredicate = matchesById; + } + + function matchesQuery(gridNode) + { + delete gridNode._searchMatched; + if (matchPredicate(gridNode)) { + gridNode._searchMatched = true; + gridNode.refresh(); + return true; + } + return false; + } + + var current = this.dataGrid.children[0]; + var depth = 0; + var info = {}; + + // Restrict to type nodes and instances. + const maxDepth = 1; + + while (current) { + if (matchesQuery(current)) + this._searchResults.push({ node: current }); + current = current.traverseNextNode(false, null, (depth >= maxDepth), info); + depth += info.depthChange; + } + + finishedCallback(this, this._searchResults.length); + }, + + jumpToFirstSearchResult: function() + { + if (!this._searchResults || !this._searchResults.length) + return; + this._currentSearchResultIndex = 0; + this._jumpToSearchResult(this._currentSearchResultIndex); + }, + + jumpToLastSearchResult: function() + { + if (!this._searchResults || !this._searchResults.length) + return; + this._currentSearchResultIndex = (this._searchResults.length - 1); + this._jumpToSearchResult(this._currentSearchResultIndex); + }, + + jumpToNextSearchResult: function() + { + if (!this._searchResults || !this._searchResults.length) + return; + if (++this._currentSearchResultIndex >= this._searchResults.length) + this._currentSearchResultIndex = 0; + this._jumpToSearchResult(this._currentSearchResultIndex); + }, + + jumpToPreviousSearchResult: function() + { + if (!this._searchResults || !this._searchResults.length) + return; + if (--this._currentSearchResultIndex < 0) + this._currentSearchResultIndex = (this._searchResults.length - 1); + this._jumpToSearchResult(this._currentSearchResultIndex); + }, + + showingFirstSearchResult: function() + { + return (this._currentSearchResultIndex === 0); + }, + + showingLastSearchResult: function() + { + return (this._searchResults && this._currentSearchResultIndex === (this._searchResults.length - 1)); + }, + + _jumpToSearchResult: function(index) + { + var searchResult = this._searchResults[index]; + if (!searchResult) + return; + + var node = searchResult.node; + node.revealAndSelect(); + }, + + refreshVisibleData: function() + { + var child = this.dataGrid.children[0]; + while (child) { + child.refresh(); + child = child.traverseNextNode(false, null, true); + } + }, + + _changeBase: function() + { + if (this._baseProfileUid === this._profiles()[this.baseSelectElement.selectedIndex].uid) + return; + + this._baseProfileUid = this._profiles()[this.baseSelectElement.selectedIndex].uid; + this.dataGrid._baseProfileIndexChanged(this._loadProfileByIndex.bind(this), this.baseSelectElement.selectedIndex); + + if (!this.currentQuery || !this._searchFinishedCallback || !this._searchResults) + return; + + // The current search needs to be performed again. First negate out previous match + // count by calling the search finished callback with a negative number of matches. + // Then perform the search again with the same query and callback. + this._searchFinishedCallback(this, -this._searchResults.length); + this.performSearch(this.currentQuery, this._searchFinishedCallback); + }, + + _changeFilter: function() + { + var profileIndex = this.filterSelectElement.selectedIndex - 1; + this.dataGrid._filterSelectIndexChanged(this._loadProfileByIndex.bind(this), profileIndex); + + if (!this.currentQuery || !this._searchFinishedCallback || !this._searchResults) + return; + + // The current search needs to be performed again. First negate out previous match + // count by calling the search finished callback with a negative number of matches. + // Then perform the search again with the same query and callback. + this._searchFinishedCallback(this, -this._searchResults.length); + this.performSearch(this.currentQuery, this._searchFinishedCallback); + }, + + _profiles: function() + { + return WebInspector.panels.profiles.getProfiles(WebInspector.DetailedHeapshotProfileType.TypeId); + }, + + _loadProfile: function(profileUid, callback) + { + WebInspector.panels.profiles.loadHeapSnapshot(profileUid, callback); + }, + + _loadProfileByIndex: function(profileIndex, callback) + { + var profileUid = this._profiles()[profileIndex].uid; + WebInspector.panels.profiles.loadHeapSnapshot(profileUid, callback); + }, + + isDetailedSnapshot: function(snapshot) + { + var s = new WebInspector.HeapSnapshot(snapshot); + for (var iter = s.rootNode.edges; iter.hasNext(); iter.next()) + if (iter.edge.node.name === "(GC roots)") + return true; + return false; + }, + + processLoadedSnapshot: function(profile, snapshot) + { + profile.nodes = snapshot.nodes; + profile.strings = snapshot.strings; + var s = new WebInspector.HeapSnapshot(profile); + profile.sidebarElement.subtitle = Number.bytesToString(s.totalSize); + }, + + _mouseClickInContentsGrid: function(event) + { + var cell = event.target.enclosingNodeOrSelfWithNodeName("td"); + if (!cell || (!cell.hasStyleClass("object-column"))) + return; + var row = event.target.enclosingNodeOrSelfWithNodeName("tr"); + if (!row) + return; + var nodeItem = row._dataGridNode; + if (!nodeItem || nodeItem.isEventWithinDisclosureTriangle(event)) + return; + if (nodeItem.snapshotNodeIndex) + this.retainmentDataGrid.setDataSource(this, nodeItem.isDeletedNode ? nodeItem.dataGrid.baseSnapshot : nodeItem.dataGrid.snapshot, nodeItem.snapshotNodeIndex, nodeItem.isDeletedNode ? this.baseSelectElement.childNodes[this.baseSelectElement.selectedIndex].label + " | " : ""); + else + this.retainmentDataGrid.reset(); + }, + + _mouseDownInContentsGrid: function(event) + { + if (event.detail < 2) + return; + + var cell = event.target.enclosingNodeOrSelfWithNodeName("td"); + if (!cell || (!cell.hasStyleClass("count-column") && !cell.hasStyleClass("shallowSize-column") && !cell.hasStyleClass("retainedSize-column"))) + return; + + if (cell.hasStyleClass("count-column")) + this.showCountAsPercent = !this.showCountAsPercent; + else if (cell.hasStyleClass("shallowSize-column")) + this.showShallowSizeAsPercent = !this.showShallowSizeAsPercent; + else if (cell.hasStyleClass("retainedSize-column")) + this.showRetainedSizeAsPercent = !this.showRetainedSizeAsPercent; + this.refreshShowAsPercents(); + + event.preventDefault(); + event.stopPropagation(); + }, + + _mouseClickInRetainmentGrid: function(event) + { + var cell = event.target.enclosingNodeOrSelfWithNodeName("td"); + if (!cell || (!cell.hasStyleClass("path-column"))) + return; + var row = event.target.enclosingNodeOrSelfWithNodeName("tr"); + var nodeItem = row._dataGridNode; + if (!nodeItem || !nodeItem.route) + return; + function expandRoute() + { + this.dataGrid.expandRoute(nodeItem.route); + } + this.changeView("Containment", expandRoute.bind(this)); + }, + + changeView: function(viewTitle, callback) + { + var viewIndex = null; + for (var i = 0; i < this.views.length; ++i) + if (this.views[i].title === viewTitle) { + viewIndex = i; + break; + } + if (this.views.current === viewIndex) { + setTimeout(callback, 0); + return; + } + var grid = this.views[viewIndex].grid; + function sortingComplete() + { + grid.removeEventListener("sorting complete", sortingComplete, this); + setTimeout(callback, 0); + } + this.views[viewIndex].grid.addEventListener("sorting complete", sortingComplete, this); + this.viewSelectElement.selectedIndex = viewIndex; + this._changeView({target: {selectedIndex: viewIndex}}); + }, + + _changeView: function(event) + { + if (!event || !this._profileUid) + return; + if (event.target.selectedIndex === this.views.current) + return; + + this.views.current = event.target.selectedIndex; + this.currentView.detach(); + var view = this.views[this.views.current]; + this.currentView = view.view; + this.dataGrid = view.grid; + this.currentView.show(this.viewsContainer); + this.refreshVisibleData(); + this.dataGrid.updateWidths(); + + if (this.currentView === this.diffView) { + this.baseSelectElement.removeStyleClass("hidden"); + if (!this.dataGrid.snapshotView) { + this._changeBase(); + this.dataGrid.setDataSource(this, this.profileWrapper); + } + } else { + this.baseSelectElement.addStyleClass("hidden"); + if (!this.dataGrid.snapshotView) + this.dataGrid.setDataSource(this, this.profileWrapper); + } + + if (this.currentView === this.constructorsView) + this.filterSelectElement.removeStyleClass("hidden"); + else + this.filterSelectElement.addStyleClass("hidden"); + + if (!this.currentQuery || !this._searchFinishedCallback || !this._searchResults) + return; + + // The current search needs to be performed again. First negate out previous match + // count by calling the search finished callback with a negative number of matches. + // Then perform the search again the with same query and callback. + this._searchFinishedCallback(this, -this._searchResults.length); + this.performSearch(this.currentQuery, this._searchFinishedCallback); + }, + + _getHoverAnchor: function(target) + { + var span = target.enclosingNodeOrSelfWithNodeName("span"); + if (!span) + return; + var row = target.enclosingNodeOrSelfWithNodeName("tr"); + if (!row) + return; + var gridNode = row._dataGridNode; + if (!gridNode.hasHoverMessage) + return; + span.node = gridNode; + return span; + }, + + get _isShowingAsPercent() + { + return this.showCountAsPercent && this.showShallowSizeAsPercent && this.showRetainedSizeAsPercent; + }, + + _percentClicked: function(event) + { + var currentState = this._isShowingAsPercent; + this.showCountAsPercent = !currentState; + this.showShallowSizeAsPercent = !currentState; + this.showRetainedSizeAsPercent = !currentState; + this.refreshShowAsPercents(); + }, + + _showObjectPopover: function(element, showCallback) + { + element.node.queryObjectContent(showCallback); + }, + + _helpClicked: function(event) + { + if (!this._helpPopoverContentElement) { + var refTypes = ["a:", "console-formatted-name", WebInspector.UIString("property"), + "0:", "console-formatted-name", WebInspector.UIString("element"), + "a:", "console-formatted-number", WebInspector.UIString("context var"), + "a:", "console-formatted-null", WebInspector.UIString("system prop")]; + var objTypes = [" a ", "console-formatted-object", "Object", + "\"a\"", "console-formatted-string", "String", + "/a/", "console-formatted-string", "RegExp", + "a()", "console-formatted-function", "Function", + "a[]", "console-formatted-object", "Array", + "num", "console-formatted-number", "Number", + " a ", "console-formatted-null", "System"]; + + var contentElement = document.createElement("table"); + contentElement.className = "heapshot-help"; + var headerRow = document.createElement("tr"); + var propsHeader = document.createElement("th"); + propsHeader.textContent = WebInspector.UIString("Property types:"); + headerRow.appendChild(propsHeader); + var objsHeader = document.createElement("th"); + objsHeader.textContent = WebInspector.UIString("Object types:"); + headerRow.appendChild(objsHeader); + contentElement.appendChild(headerRow); + var len = Math.max(refTypes.length, objTypes.length); + for (var i = 0; i < len; i += 3) { + var row = document.createElement("tr"); + var refCell = document.createElement("td"); + if (refTypes[i]) + appendHelp(refTypes, i, refCell); + row.appendChild(refCell); + var objCell = document.createElement("td"); + if (objTypes[i]) + appendHelp(objTypes, i, objCell); + row.appendChild(objCell); + contentElement.appendChild(row); + } + this._helpPopoverContentElement = contentElement; + this.helpPopover = new WebInspector.Popover(); + + function appendHelp(help, index, cell) + { + var div = document.createElement("div"); + div.className = "source-code event-properties"; + var name = document.createElement("span"); + name.textContent = help[index]; + name.className = help[index + 1]; + div.appendChild(name); + var desc = document.createElement("span"); + desc.textContent = " " + help[index + 2]; + div.appendChild(desc); + cell.appendChild(div); + } + } + if (this.helpPopover.visible) + this.helpPopover.hide(); + else + this.helpPopover.show(this._helpPopoverContentElement, this.helpButton.element); + }, + + _startRetainersHeaderDragging: function(event) + { + if (!this.isShowing()) + return; + + WebInspector.elementDragStart(this.retainmentViewHeader, this._retainersHeaderDragging.bind(this), this._endRetainersHeaderDragging.bind(this), event, "row-resize"); + this._previousDragPosition = event.pageY; + event.stopPropagation(); + }, + + _retainersHeaderDragging: function(event) + { + var height = this.retainmentView.element.clientHeight; + height += this._previousDragPosition - event.pageY; + this._previousDragPosition = event.pageY; + this._updateRetainmentViewHeight(height); + event.preventDefault(); + event.stopPropagation(); + }, + + _endRetainersHeaderDragging: function(event) + { + WebInspector.elementDragEnd(event); + delete this._previousDragPosition; + event.stopPropagation(); + }, + + _updateRetainmentViewHeight: function(height) + { + height = Number.constrain(height, Preferences.minConsoleHeight, this.element.clientHeight - Preferences.minConsoleHeight); + this.viewsContainer.style.bottom = (height + this.retainmentViewHeader.clientHeight) + "px"; + this.retainmentView.element.style.height = height + "px"; + this.retainmentViewHeader.style.bottom = height + "px"; + }, + + _updateBaseOptions: function() + { + var list = this._profiles(); + // We're assuming that snapshots can only be added. + if (this.baseSelectElement.length === list.length) + return; + + for (var i = this.baseSelectElement.length, n = list.length; i < n; ++i) { + var baseOption = document.createElement("option"); + var title = list[i].title; + if (!title.indexOf(UserInitiatedProfileName)) + title = WebInspector.UIString("Snapshot %d", title.substring(UserInitiatedProfileName.length + 1)); + baseOption.label = title; + this.baseSelectElement.appendChild(baseOption); + } + }, + + _updateFilterOptions: function() + { + var list = this._profiles(); + // We're assuming that snapshots can only be added. + if (this.filterSelectElement.length - 1 === list.length) + return; + + if (!this.filterSelectElement.length) { + var filterOption = document.createElement("option"); + filterOption.label = WebInspector.UIString("All objects"); + this.filterSelectElement.appendChild(filterOption); + } + + for (var i = this.filterSelectElement.length - 1, n = list.length; i < n; ++i) { + var filterOption = document.createElement("option"); + var title = list[i].title; + if (!title.indexOf(UserInitiatedProfileName)) { + if (!i) + title = WebInspector.UIString("Objects allocated before Snapshot %d", title.substring(UserInitiatedProfileName.length + 1)); + else + title = WebInspector.UIString("Objects allocated between Snapshots %d and %d", title.substring(UserInitiatedProfileName.length + 1) - 1, title.substring(UserInitiatedProfileName.length + 1)); + } + filterOption.label = title; + this.filterSelectElement.appendChild(filterOption); + } + }, + + _updatePercentButton: function() + { + if (this._isShowingAsPercent) { + this.percentButton.title = WebInspector.UIString("Show absolute counts and sizes."); + this.percentButton.toggled = true; + } else { + this.percentButton.title = WebInspector.UIString("Show counts and sizes as percentages."); + this.percentButton.toggled = false; + } + } +}; + +WebInspector.DetailedHeapshotView.prototype.__proto__ = WebInspector.View.prototype; + +WebInspector.settings.showHeapSnapshotObjectsHiddenProperties = WebInspector.settings.createSetting("showHeaSnapshotObjectsHiddenProperties", false); + +WebInspector.DetailedHeapshotProfileType = function() +{ + WebInspector.ProfileType.call(this, WebInspector.DetailedHeapshotProfileType.TypeId, WebInspector.UIString("Take Heap Snapshot")); +} + +WebInspector.DetailedHeapshotProfileType.TypeId = "HEAP"; + +WebInspector.DetailedHeapshotProfileType.prototype = { + get buttonTooltip() + { + return WebInspector.UIString("Take heap snapshot."); + }, + + buttonClicked: function() + { + WebInspector.panels.profiles.takeHeapSnapshot(); + }, + + get treeItemTitle() + { + return WebInspector.UIString("HEAP SNAPSHOTS"); + }, + + get description() + { + return WebInspector.UIString("Heap snapshot profiles show memory distribution among your page's JavaScript objects and related DOM nodes."); + }, + + createSidebarTreeElementForProfile: function(profile) + { + return new WebInspector.ProfileSidebarTreeElement(profile, WebInspector.UIString("Snapshot %d"), "heap-snapshot-sidebar-tree-item"); + }, + + createView: function(profile) + { + return new WebInspector.DetailedHeapshotView(WebInspector.panels.profiles, profile); + } +} + +WebInspector.DetailedHeapshotProfileType.prototype.__proto__ = WebInspector.ProfileType.prototype; +/* DebuggerModel.js */ + +/* + * 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. + * * 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. + */ + +/** + * @constructor + * @extends {WebInspector.Object} + */ +WebInspector.DebuggerModel = function() +{ + this._debuggerPausedDetails = null; + /** + * @type {Object.} + */ + this._scripts = {}; + + this._canSetScriptSource = false; + + InspectorBackend.registerDebuggerDispatcher(new WebInspector.DebuggerDispatcher(this)); +} + +/** + * @constructor + * @param {Array.} callFrames + * @param {string} reason + * @param {*} auxData + */ +WebInspector.DebuggerPausedDetails = function(callFrames, reason, auxData) +{ + this.callFrames = callFrames; + this.reason = reason; + this.auxData = auxData; +} + +/** + * @constructor + * @extends {DebuggerAgent.Location} + * @param {number} lineNumber + * @param {number} columnNumber + */ +WebInspector.DebuggerModel.Location = function(lineNumber, columnNumber) +{ + this.lineNumber = lineNumber; + this.columnNumber = columnNumber; +} + +WebInspector.DebuggerModel.Events = { + DebuggerWasEnabled: "debugger-was-enabled", + DebuggerWasDisabled: "debugger-was-disabled", + DebuggerPaused: "debugger-paused", + DebuggerResumed: "debugger-resumed", + ParsedScriptSource: "parsed-script-source", + FailedToParseScriptSource: "failed-to-parse-script-source", + BreakpointResolved: "breakpoint-resolved", + GlobalObjectCleared: "global-object-cleared" +} + +WebInspector.DebuggerModel.BreakReason = { + DOM: "DOM", + EventListener: "EventListener", + XHR: "XHR", + Exception: "exception" +} + +WebInspector.DebuggerModel.prototype = { + enableDebugger: function() + { + function callback(error, result) + { + this._canSetScriptSource = result; + } + DebuggerAgent.canSetScriptSource(callback.bind(this)); + DebuggerAgent.enable(this._debuggerWasEnabled.bind(this)); + }, + + disableDebugger: function() + { + DebuggerAgent.disable(this._debuggerWasDisabled.bind(this)); + }, + + /** + * @return {boolean} + */ + canSetScriptSource: function() + { + return this._canSetScriptSource; + }, + + _debuggerWasEnabled: function() + { + this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerWasEnabled); + }, + + _debuggerWasDisabled: function() + { + this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerWasDisabled); + }, + + /** + * @param {DebuggerAgent.Location} location + */ + continueToLocation: function(location) + { + DebuggerAgent.continueToLocation(location); + }, + + /** + * @param {DebuggerAgent.Location} location + * @param {string} condition + * @param {function()} callback + */ + setBreakpointByScriptLocation: function(location, condition, callback) + { + var script = this.scriptForSourceID(location.scriptId); + if (script.sourceURL) + this.setBreakpoint(script.sourceURL, location.lineNumber, location.columnNumber, condition, callback); + else + this.setBreakpointBySourceId(location, condition, callback); + }, + + /** + * @param {string} url + * @param {number} lineNumber + * @param {number=} columnNumber + * @param {string=} condition + * @param {function(?DebuggerAgent.BreakpointId, Array.=)=} callback + */ + setBreakpoint: function(url, lineNumber, columnNumber, condition, callback) + { + // Adjust column if needed. + var minColumnNumber = 0; + for (var id in this._scripts) { + var script = this._scripts[id]; + if (url === script.sourceURL && lineNumber === script.lineOffset) + minColumnNumber = minColumnNumber ? Math.min(minColumnNumber, script.columnOffset) : script.columnOffset; + } + columnNumber = Math.max(columnNumber, minColumnNumber); + + /** + * @this {WebInspector.DebuggerModel} + * @param {?Protocol.Error} error + * @param {DebuggerAgent.BreakpointId} breakpointId + * @param {Array.=} locations + */ + function didSetBreakpoint(error, breakpointId, locations) + { + if (callback) + callback(error ? null : breakpointId, locations); + } + DebuggerAgent.setBreakpointByUrl(lineNumber, url, undefined, columnNumber, condition, didSetBreakpoint.bind(this)); + WebInspector.userMetrics.ScriptsBreakpointSet.record(); + }, + + /** + * @param {DebuggerAgent.Location} location + * @param {string} condition + * @param {function(?DebuggerAgent.BreakpointId, Array.)=} callback + */ + setBreakpointBySourceId: function(location, condition, callback) + { + /** + * @this {WebInspector.DebuggerModel} + * @param {?Protocol.Error} error + * @param {DebuggerAgent.BreakpointId} breakpointId + * @param {DebuggerAgent.Location} actualLocation + */ + function didSetBreakpoint(error, breakpointId, actualLocation) + { + if (callback) + callback(error ? null : breakpointId, [actualLocation]); + } + DebuggerAgent.setBreakpoint(location, condition, didSetBreakpoint.bind(this)); + WebInspector.userMetrics.ScriptsBreakpointSet.record(); + }, + + /** + * @param {DebuggerAgent.BreakpointId} breakpointId + * @param {function(?Protocol.Error)=} callback + */ + removeBreakpoint: function(breakpointId, callback) + { + DebuggerAgent.removeBreakpoint(breakpointId, callback); + }, + + /** + * @param {DebuggerAgent.BreakpointId} breakpointId + * @param {DebuggerAgent.Location} location + */ + _breakpointResolved: function(breakpointId, location) + { + this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.BreakpointResolved, {breakpointId: breakpointId, location: location}); + }, + + _globalObjectCleared: function() + { + this._debuggerPausedDetails = null; + this._scripts = {}; + this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.GlobalObjectCleared); + }, + + /** + * @return {Object.} + */ + get scripts() + { + return this._scripts; + }, + + /** + * @param {DebuggerAgent.ScriptId} scriptId + * @return {WebInspector.Script|undefined} + */ + scriptForSourceID: function(scriptId) + { + return this._scripts[scriptId]; + }, + + /** + * @param {string} url + */ + scriptsForURL: function(url) + { + return this.queryScripts(function(s) { return s.sourceURL === url; }); + }, + + /** + * @param {function(WebInspector.Script):boolean} filter + */ + queryScripts: function(filter) + { + var scripts = []; + for (var scriptId in this._scripts) { + var script = this._scripts[scriptId]; + if (filter(script)) + scripts.push(script); + } + return scripts; + }, + + /** + * @param {DebuggerAgent.ScriptId} scriptId + * @param {string} newSource + * @param {function(?Protocol.Error)} callback + */ + setScriptSource: function(scriptId, newSource, callback) + { + this._scripts[scriptId].editSource(newSource, this._didEditScriptSource.bind(this, scriptId, newSource, callback)); + }, + + /** + * @param {DebuggerAgent.ScriptId} scriptId + * @param {string} newSource + * @param {function(?Protocol.Error)} callback + * @param {?Protocol.Error} error + * @param {Array.=} callFrames + */ + _didEditScriptSource: function(scriptId, newSource, callback, error, callFrames) + { + if (!error && callFrames && callFrames.length) + this._debuggerPausedDetails.callFrames = callFrames; + callback(error); + }, + + /** + * @return {Array.} + */ + get callFrames() + { + return this._debuggerPausedDetails ? this._debuggerPausedDetails.callFrames : null; + }, + + /** + * @return {?WebInspector.DebuggerPausedDetails} + */ + get debuggerPausedDetails() + { + return this._debuggerPausedDetails; + }, + + /** + * @param {Array.} callFrames + * @param {string} reason + * @param {*} auxData + */ + _pausedScript: function(callFrames, reason, auxData) + { + this._debuggerPausedDetails = new WebInspector.DebuggerPausedDetails(callFrames, reason, auxData); + this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerPaused, this._debuggerPausedDetails); + }, + + _resumedScript: function() + { + this._debuggerPausedDetails = null; + this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerResumed); + }, + + /** + * @param {DebuggerAgent.ScriptId} scriptId + * @param {string} sourceURL + * @param {number} startLine + * @param {number} startColumn + * @param {number} endLine + * @param {number} endColumn + * @param {boolean} isContentScript + */ + _parsedScriptSource: function(scriptId, sourceURL, startLine, startColumn, endLine, endColumn, isContentScript, sourceMapURL) + { + var script = new WebInspector.Script(scriptId, sourceURL, startLine, startColumn, endLine, endColumn, isContentScript, sourceMapURL); + this._scripts[scriptId] = script; + this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.ParsedScriptSource, script); + }, + + /** + * @param {string} sourceURL + * @param {string} source + * @param {number} startingLine + * @param {number} errorLine + * @param {string} errorMessage + */ + _failedToParseScriptSource: function(sourceURL, source, startingLine, errorLine, errorMessage) + { + var script = new WebInspector.Script("", sourceURL, startingLine, 0, 0, 0, false); + this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.FailedToParseScriptSource, script); + } +} + +WebInspector.DebuggerModel.prototype.__proto__ = WebInspector.Object.prototype; + +WebInspector.DebuggerEventTypes = { + JavaScriptPause: 0, + JavaScriptBreakpoint: 1, + NativeBreakpoint: 2 +}; + +/** + * @constructor + * @implements {DebuggerAgent.Dispatcher} + * @param {WebInspector.DebuggerModel} debuggerModel + */ +WebInspector.DebuggerDispatcher = function(debuggerModel) +{ + this._debuggerModel = debuggerModel; +} + +WebInspector.DebuggerDispatcher.prototype = { + /** + * @param {Array.} callFrames + * @param {string} reason + * @param {*} auxData + */ + paused: function(callFrames, reason, auxData) + { + this._debuggerModel._pausedScript(callFrames, reason, auxData); + }, + + resumed: function() + { + this._debuggerModel._resumedScript(); + }, + + globalObjectCleared: function() + { + this._debuggerModel._globalObjectCleared(); + }, + + /** + * @param {DebuggerAgent.ScriptId} scriptId + * @param {string} sourceURL + * @param {number} startLine + * @param {number} startColumn + * @param {number} endLine + * @param {number} endColumn + * @param {boolean=} isContentScript + */ + scriptParsed: function(scriptId, sourceURL, startLine, startColumn, endLine, endColumn, isContentScript, sourceMapURL) + { + this._debuggerModel._parsedScriptSource(scriptId, sourceURL, startLine, startColumn, endLine, endColumn, !!isContentScript, sourceMapURL); + }, + + /** + * @param {string} sourceURL + * @param {string} source + * @param {number} startingLine + * @param {number} errorLine + * @param {string} errorMessage + */ + scriptFailedToParse: function(sourceURL, source, startingLine, errorLine, errorMessage) + { + this._debuggerModel._failedToParseScriptSource(sourceURL, source, startingLine, errorLine, errorMessage); + }, + + /** + * @param {DebuggerAgent.BreakpointId} breakpointId + * @param {DebuggerAgent.Location} location + */ + breakpointResolved: function(breakpointId, location) + { + this._debuggerModel._breakpointResolved(breakpointId, location); + } +} + +/** + * @type {?WebInspector.DebuggerModel} + */ +WebInspector.debuggerModel = null; +/* DebuggerPresentationModel.js */ + +/* + * Copyright (C) 2011 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. + */ + +/** + * @constructor + * @extends {WebInspector.Object} + */ +WebInspector.DebuggerPresentationModel = function() +{ + // FIXME: apply formatter from outside as a generic mapping. + this._formatter = new WebInspector.ScriptFormatter(); + this._rawSourceCodes = []; + this._rawSourceCodeForScriptId = {}; + this._rawSourceCodeForURL = {}; + this._rawSourceCodeForDocumentURL = {}; + this._presentationCallFrames = []; + + this._breakpointManager = new WebInspector.BreakpointManager(WebInspector.settings.breakpoints, this._breakpointAdded.bind(this), this._breakpointRemoved.bind(this), WebInspector.debuggerModel); + + WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.ParsedScriptSource, this._parsedScriptSource, this); + WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.FailedToParseScriptSource, this._failedToParseScriptSource, this); + WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this); + WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerResumed, this._debuggerResumed, this); + WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.GlobalObjectCleared, this._debuggerReset, this); + + WebInspector.console.addEventListener(WebInspector.ConsoleModel.Events.MessageAdded, this._consoleMessageAdded, this); + WebInspector.console.addEventListener(WebInspector.ConsoleModel.Events.ConsoleCleared, this._consoleCleared, this); + + new WebInspector.DebuggerPresentationModelResourceBinding(this); +} + +WebInspector.DebuggerPresentationModel.Events = { + UISourceCodeAdded: "source-file-added", + UISourceCodeReplaced: "source-file-replaced", + UISourceCodeRemoved: "source-file-removed", + ConsoleMessageAdded: "console-message-added", + ConsoleMessagesCleared: "console-messages-cleared", + BreakpointAdded: "breakpoint-added", + BreakpointRemoved: "breakpoint-removed", + DebuggerPaused: "debugger-paused", + DebuggerResumed: "debugger-resumed", + DebuggerReset: "debugger-reset", + CallFrameSelected: "call-frame-selected", + ConsoleCommandEvaluatedInSelectedCallFrame: "console-command-evaluated-in-selected-call-frame", + ExecutionLineChanged: "execution-line-changed" +} + +WebInspector.DebuggerPresentationModel.prototype = { + /** + * @param {WebInspector.DebuggerPresentationModel.LinkifierFormatter=} formatter + */ + createLinkifier: function(formatter) + { + return new WebInspector.DebuggerPresentationModel.Linkifier(this, formatter); + }, + + /** + * @param {WebInspector.PresentationCallFrame} callFrame + * @return {WebInspector.DebuggerPresentationModel.CallFramePlacard} + */ + createPlacard: function(callFrame) + { + return new WebInspector.DebuggerPresentationModel.CallFramePlacard(callFrame); + }, + + /** + * @param {DebuggerAgent.Location} rawLocation + * @return {?WebInspector.UILocation} + */ + rawLocationToUILocation: function(rawLocation) + { + var rawSourceCode = this._rawSourceCodeForScriptId[rawLocation.scriptId]; + if (!rawSourceCode.sourceMapping) + return null; + return rawSourceCode.sourceMapping.rawLocationToUILocation(rawLocation); + }, + + /** + * @param {WebInspector.Event} event + */ + _parsedScriptSource: function(event) + { + var script = /** @type {WebInspector.Script} */ event.data; + this._addScript(script); + }, + + /** + * @param {WebInspector.Event} event + */ + _failedToParseScriptSource: function(event) + { + var script = /** @type {WebInspector.Script} */ event.data; + this._addScript(script); + }, + + /** + * @param {WebInspector.Script} script + */ + _addScript: function(script) + { + var resource = null; + var isInlineScript = false; + if (script.isInlineScript()) { + resource = WebInspector.networkManager.inflightResourceForURL(script.sourceURL) || WebInspector.resourceForURL(script.sourceURL); + if (resource && resource.type === WebInspector.Resource.Type.Document) { + isInlineScript = true; + var rawSourceCode = this._rawSourceCodeForDocumentURL[script.sourceURL]; + if (rawSourceCode) { + rawSourceCode.addScript(script); + this._bindScriptToRawSourceCode(script, rawSourceCode); + return; + } + } + } + + var compilerSourceMapping = null; + if (WebInspector.settings.sourceMapsEnabled.get() && script.sourceMapURL) + compilerSourceMapping = new WebInspector.ClosureCompilerSourceMapping(script.sourceMapURL, script.sourceURL); + + var rawSourceCode = new WebInspector.RawSourceCode(script.scriptId, script, resource, this._formatter, this._formatSource, compilerSourceMapping); + this._rawSourceCodes.push(rawSourceCode); + this._bindScriptToRawSourceCode(script, rawSourceCode); + + if (isInlineScript) + this._rawSourceCodeForDocumentURL[script.sourceURL] = rawSourceCode; + + if (rawSourceCode.sourceMapping) + this._updateSourceMapping(rawSourceCode, null); + rawSourceCode.addEventListener(WebInspector.RawSourceCode.Events.SourceMappingUpdated, this._sourceMappingUpdated, this); + }, + + /** + * @param {WebInspector.Script} script + * @param {WebInspector.RawSourceCode} rawSourceCode + */ + _bindScriptToRawSourceCode: function(script, rawSourceCode) + { + this._rawSourceCodeForScriptId[script.scriptId] = rawSourceCode; + this._rawSourceCodeForURL[script.sourceURL] = rawSourceCode; + }, + + /** + * @param {WebInspector.Event} event + */ + _sourceMappingUpdated: function(event) + { + var rawSourceCode = /** @type {WebInspector.RawSourceCode} */ event.target; + var oldSourceMapping = /** @type {WebInspector.RawSourceCode.SourceMapping} */ event.data["oldSourceMapping"]; + this._updateSourceMapping(rawSourceCode, oldSourceMapping); + }, + + /** + * @return {Array.} + */ + uiSourceCodes: function() + { + var result = []; + for (var i = 0; i < this._rawSourceCodes.length; ++i) { + var uiSourceCodeList = this._rawSourceCodes[i].sourceMapping.uiSourceCodeList(); + for (var j = 0; j < uiSourceCodeList.length; ++j) + result.push(uiSourceCodeList[j]); + } + return result; + }, + + /** + * @param {WebInspector.RawSourceCode} rawSourceCode + * @param {WebInspector.RawSourceCode.SourceMapping} oldSourceMapping + */ + _updateSourceMapping: function(rawSourceCode, oldSourceMapping) + { + if (oldSourceMapping) { + var oldUISourceCodeList = oldSourceMapping.uiSourceCodeList(); + for (var i = 0; i < oldUISourceCodeList.length; ++i) { + var breakpoints = this._breakpointManager.breakpointsForUISourceCode(oldUISourceCodeList[i]); + for (var lineNumber in breakpoints) { + var breakpoint = breakpoints[lineNumber]; + this._breakpointRemoved(breakpoint); + delete breakpoint.uiSourceCode; + } + } + } + + this._restoreBreakpoints(rawSourceCode); + this._restoreConsoleMessages(rawSourceCode); + + if (!oldSourceMapping) { + var uiSourceCodeList = rawSourceCode.sourceMapping.uiSourceCodeList(); + for (var i = 0; i < uiSourceCodeList.length; ++i) + this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.UISourceCodeAdded, uiSourceCodeList[i]); + } else { + var eventData = { uiSourceCodeList: rawSourceCode.sourceMapping.uiSourceCodeList(), oldUISourceCodeList: oldSourceMapping.uiSourceCodeList() }; + this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.UISourceCodeReplaced, eventData); + } + }, + + /** + * @param {WebInspector.RawSourceCode} rawSourceCode + */ + _restoreBreakpoints: function(rawSourceCode) + { + var uiSourceCodeList = rawSourceCode.sourceMapping.uiSourceCodeList(); + for (var i = 0; i < uiSourceCodeList.length; ++i) { + var uiSourceCode = uiSourceCodeList[i]; + this._breakpointManager.uiSourceCodeAdded(uiSourceCode); + var breakpoints = this._breakpointManager.breakpointsForUISourceCode(uiSourceCode); + for (var lineNumber in breakpoints) + this._breakpointAdded(breakpoints[lineNumber]); + } + + }, + + /** + * @param {WebInspector.RawSourceCode} rawSourceCode + */ + _restoreConsoleMessages: function(rawSourceCode) + { + var messages = rawSourceCode.messages; + for (var i = 0; i < messages.length; ++i) + messages[i]._presentationMessage = this._createPresentationMessage(messages[i], rawSourceCode.sourceMapping); + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + * @return {boolean} + */ + canEditScriptSource: function(uiSourceCode) + { + if (!WebInspector.debuggerModel.canSetScriptSource() || this._formatSource) + return false; + var rawSourceCode = uiSourceCode.rawSourceCode; + var script = this._scriptForRawSourceCode(rawSourceCode); + return script && !script.lineOffset && !script.columnOffset; + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + * @param {string} newSource + * @param {function(?Protocol.Error)} callback + */ + setScriptSource: function(uiSourceCode, newSource, callback) + { + var rawSourceCode = uiSourceCode.rawSourceCode; + var script = this._scriptForRawSourceCode(rawSourceCode); + + /** + * @this {WebInspector.DebuggerPresentationModel} + * @param {?Protocol.Error} error + */ + function didEditScriptSource(error) + { + callback(error); + if (error) + return; + + var resource = WebInspector.resourceForURL(rawSourceCode.url); + if (resource) + resource.addRevision(newSource); + + uiSourceCode.contentChanged(newSource); + + if (WebInspector.debuggerModel.callFrames) + this._debuggerPaused(); + } + WebInspector.debuggerModel.setScriptSource(script.scriptId, newSource, didEditScriptSource.bind(this)); + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + * @param {string} oldSource + * @param {string} newSource + */ + _updateBreakpointsAfterLiveEdit: function(uiSourceCode, oldSource, newSource) + { + var breakpoints = this._breakpointManager.breakpointsForUISourceCode(uiSourceCode); + + // Clear and re-create breakpoints according to text diff. + var diff = Array.diff(oldSource.split("\n"), newSource.split("\n")); + for (var lineNumber in breakpoints) { + var breakpoint = breakpoints[lineNumber]; + + this.removeBreakpoint(uiSourceCode, parseInt(lineNumber, 10)); + + var newLineNumber = diff.left[lineNumber].row; + if (newLineNumber === undefined) { + for (var i = lineNumber - 1; i >= 0; --i) { + if (diff.left[i].row === undefined) + continue; + var shiftedLineNumber = diff.left[i].row + lineNumber - i; + if (shiftedLineNumber < diff.right.length) { + var originalLineNumber = diff.right[shiftedLineNumber].row; + if (originalLineNumber === lineNumber || originalLineNumber === undefined) + newLineNumber = shiftedLineNumber; + } + break; + } + } + if (newLineNumber !== undefined) + this.setBreakpoint(uiSourceCode, newLineNumber, breakpoint.condition, breakpoint.enabled); + } + }, + + /** + * @param {boolean} formatSource + */ + setFormatSource: function(formatSource) + { + if (this._formatSource === formatSource) + return; + + this._formatSource = formatSource; + this._breakpointManager.reset(); + for (var i = 0; i < this._rawSourceCodes.length; ++i) + this._rawSourceCodes[i].setFormatted(this._formatSource); + }, + + /** + * @param {WebInspector.Event} event + */ + _consoleMessageAdded: function(event) + { + var message = /** @type {WebInspector.ConsoleMessage} */ event.data; + if (!message.url || !message.isErrorOrWarning()) + return; + + var rawSourceCode = this._rawSourceCodeForScriptWithURL(message.url); + if (!rawSourceCode) + return; + + rawSourceCode.messages.push(message); + if (rawSourceCode.sourceMapping) { + message._presentationMessage = this._createPresentationMessage(message, rawSourceCode.sourceMapping); + this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.ConsoleMessageAdded, message._presentationMessage); + } + }, + + /** + * @param {WebInspector.ConsoleMessage} message + * @param {WebInspector.RawSourceCode.SourceMapping} sourceMapping + * @return {WebInspector.PresentationConsoleMessage} + */ + _createPresentationMessage: function(message, sourceMapping) + { + // FIXME(62725): stack trace line/column numbers are one-based. + var lineNumber = message.stackTrace ? message.stackTrace[0].lineNumber - 1 : message.line - 1; + var columnNumber = message.stackTrace ? message.stackTrace[0].columnNumber - 1 : 0; + var uiLocation = sourceMapping.rawLocationToUILocation(/** @type {DebuggerAgent.Location} */ { lineNumber: lineNumber, columnNumber: columnNumber }); + var presentationMessage = new WebInspector.PresentationConsoleMessage(uiLocation.uiSourceCode, uiLocation.lineNumber, message); + return presentationMessage; + }, + + _consoleCleared: function() + { + for (var i = 0; i < this._rawSourceCodes.length; ++i) + this._rawSourceCodes[i].messages = []; + this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.ConsoleMessagesCleared); + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + * @param {number} lineNumber + */ + continueToLine: function(uiSourceCode, lineNumber) + { + // FIXME: use RawSourceCode.uiLocationToRawLocation. + var rawLocation = uiSourceCode.rawSourceCode.sourceMapping.uiLocationToRawLocation(uiSourceCode, lineNumber, 0); + WebInspector.debuggerModel.continueToLocation(rawLocation); + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + * @return {Array.} + */ + breakpointsForUISourceCode: function(uiSourceCode) + { + var breakpointsMap = this._breakpointManager.breakpointsForUISourceCode(uiSourceCode); + var breakpointsList = []; + for (var lineNumber in breakpointsMap) + breakpointsList.push(breakpointsMap[lineNumber]); + return breakpointsList; + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + * @return {Array.} + */ + messagesForUISourceCode: function(uiSourceCode) + { + var rawSourceCode = uiSourceCode.rawSourceCode; + var messages = []; + for (var i = 0; i < rawSourceCode.messages.length; ++i) + messages.push(rawSourceCode.messages[i]._presentationMessage); + return messages; + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + * @param {number} lineNumber + * @param {string} condition + * @param {boolean} enabled + */ + setBreakpoint: function(uiSourceCode, lineNumber, condition, enabled) + { + this._breakpointManager.setBreakpoint(uiSourceCode, lineNumber, condition, enabled); + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + * @param {number} lineNumber + * @param {boolean} enabled + */ + setBreakpointEnabled: function(uiSourceCode, lineNumber, enabled) + { + var breakpoint = this.findBreakpoint(uiSourceCode, lineNumber); + if (!breakpoint) + return; + this._breakpointManager.removeBreakpoint(uiSourceCode, lineNumber); + this._breakpointManager.setBreakpoint(uiSourceCode, lineNumber, breakpoint.condition, enabled); + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + * @param {number} lineNumber + * @param {string} condition + * @param {boolean} enabled + */ + updateBreakpoint: function(uiSourceCode, lineNumber, condition, enabled) + { + this._breakpointManager.removeBreakpoint(uiSourceCode, lineNumber); + this._breakpointManager.setBreakpoint(uiSourceCode, lineNumber, condition, enabled); + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + * @param {number} lineNumber + */ + removeBreakpoint: function(uiSourceCode, lineNumber) + { + this._breakpointManager.removeBreakpoint(uiSourceCode, lineNumber); + }, + + /** + */ + removeAllBreakpoints: function() + { + this._breakpointManager.removeAllBreakpoints(); + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + * @param {number} lineNumber + * @return {WebInspector.Breakpoint|undefined} + */ + findBreakpoint: function(uiSourceCode, lineNumber) + { + return this._breakpointManager.breakpointsForUISourceCode(uiSourceCode)[lineNumber]; + }, + + /** + * @param {WebInspector.Breakpoint} breakpoint + */ + _breakpointAdded: function(breakpoint) + { + if (breakpoint.uiSourceCode) + this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.BreakpointAdded, breakpoint); + }, + + /** + * @param {WebInspector.Breakpoint} breakpoint + */ + _breakpointRemoved: function(breakpoint) + { + if (breakpoint.uiSourceCode) + this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.BreakpointRemoved, breakpoint); + }, + + _debuggerPaused: function() + { + var callFrames = WebInspector.debuggerModel.callFrames; + this._presentationCallFrames = []; + for (var i = 0; i < callFrames.length; ++i) { + var callFrame = callFrames[i]; + var script = WebInspector.debuggerModel.scriptForSourceID(callFrame.location.scriptId); + if (!script) + continue; + var rawSourceCode = this._rawSourceCodeForScript(script); + this._presentationCallFrames.push(new WebInspector.PresentationCallFrame(callFrame, i, this, rawSourceCode)); + } + var details = WebInspector.debuggerModel.debuggerPausedDetails; + this.selectedCallFrame = this._presentationCallFrames[0]; + this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.DebuggerPaused, { callFrames: this._presentationCallFrames, details: details }); + }, + + _debuggerResumed: function() + { + this._presentationCallFrames = []; + this.selectedCallFrame = null; + this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.DebuggerResumed); + }, + + get paused() + { + return !!WebInspector.debuggerModel.debuggerPausedDetails; + }, + + set selectedCallFrame(callFrame) + { + if (this._selectedCallFrame) + this._selectedCallFrame.rawSourceCode.removeEventListener(WebInspector.RawSourceCode.Events.SourceMappingUpdated, this._dispatchExecutionLineChanged, this); + this._selectedCallFrame = callFrame; + if (!this._selectedCallFrame) + return; + + this._selectedCallFrame.rawSourceCode.forceUpdateSourceMapping(); + this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.CallFrameSelected, callFrame); + + this._selectedCallFrame.rawSourceCode.addEventListener(WebInspector.RawSourceCode.Events.SourceMappingUpdated, this._dispatchExecutionLineChanged, this); + }, + + get selectedCallFrame() + { + return this._selectedCallFrame; + }, + + /** + * @param {function(?WebInspector.RemoteObject, boolean, RuntimeAgent.RemoteObject=)} callback + */ + evaluateInSelectedCallFrame: function(code, objectGroup, includeCommandLineAPI, returnByValue, callback) + { + /** + * @param {?RuntimeAgent.RemoteObject} result + * @param {boolean} wasThrown + */ + function didEvaluate(result, wasThrown) + { + if (returnByValue) + callback(null, wasThrown, wasThrown ? null : result); + else + callback(WebInspector.RemoteObject.fromPayload(result), wasThrown); + + if (objectGroup === "console") + this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.ConsoleCommandEvaluatedInSelectedCallFrame); + } + + this.selectedCallFrame.evaluate(code, objectGroup, includeCommandLineAPI, returnByValue, didEvaluate.bind(this)); + }, + + /** + * @param {function(Object)} callback + */ + getSelectedCallFrameVariables: function(callback) + { + var result = { this: true }; + + var selectedCallFrame = this.selectedCallFrame; + if (!selectedCallFrame) + callback(result); + + var pendingRequests = 0; + + function propertiesCollected(properties) + { + for (var i = 0; properties && i < properties.length; ++i) + result[properties[i].name] = true; + if (--pendingRequests == 0) + callback(result); + } + + for (var i = 0; i < selectedCallFrame.scopeChain.length; ++i) { + var scope = selectedCallFrame.scopeChain[i]; + var object = WebInspector.RemoteObject.fromPayload(scope.object); + pendingRequests++; + object.getAllProperties(propertiesCollected); + } + }, + + /** + * @param {WebInspector.Event} event + */ + _dispatchExecutionLineChanged: function(event) + { + this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.ExecutionLineChanged, this.executionLineLocation); + }, + + /** + * @type {WebInspector.UILocation} + */ + get executionLineLocation() + { + if (!this._selectedCallFrame.rawSourceCode.sourceMapping) + return; + + var rawLocation = this._selectedCallFrame._callFrame.location; + var uiLocation = this._selectedCallFrame.rawSourceCode.sourceMapping.rawLocationToUILocation(rawLocation); + return uiLocation; + }, + + /** + * @param {string} sourceURL + */ + _rawSourceCodeForScriptWithURL: function(sourceURL) + { + return this._rawSourceCodeForURL[sourceURL]; + }, + + /** + * @param {WebInspector.Script} script + */ + _rawSourceCodeForScript: function(script) + { + return this._rawSourceCodeForScriptId[script.scriptId]; + }, + + /** + * @param {WebInspector.RawSourceCode} rawSourceCode + */ + _scriptForRawSourceCode: function(rawSourceCode) + { + /** + * @this {WebInspector.DebuggerPresentationModel} + * @param {WebInspector.Script} script + * @return {boolean} + */ + function filter(script) + { + return script.scriptId === rawSourceCode.id; + } + return WebInspector.debuggerModel.queryScripts(filter.bind(this))[0]; + }, + + _debuggerReset: function() + { + for (var i = 0; i < this._rawSourceCodes.length; ++i) { + var rawSourceCode = this._rawSourceCodes[i]; + if (rawSourceCode.sourceMapping) { + var uiSourceCodeList = rawSourceCode.sourceMapping.uiSourceCodeList(); + for (var j = 0; j < uiSourceCodeList.length; ++j) + this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.UISourceCodeRemoved, uiSourceCodeList[j]); + } + rawSourceCode.removeAllListeners(); + } + this._rawSourceCodes = []; + this._rawSourceCodeForScriptId = {}; + this._rawSourceCodeForURL = {}; + this._rawSourceCodeForDocumentURL = {}; + this._presentationCallFrames = []; + this._selectedCallFrame = null; + this._breakpointManager.debuggerReset(); + this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.DebuggerReset); + } +} + +WebInspector.DebuggerPresentationModel.prototype.__proto__ = WebInspector.Object.prototype; + +/** + * @constructor + * @param {WebInspector.UISourceCode} uiSourceCode + * @param {number} lineNumber + * @param {WebInspector.ConsoleMessage} originalMessage + */ +WebInspector.PresentationConsoleMessage = function(uiSourceCode, lineNumber, originalMessage) +{ + this.uiSourceCode = uiSourceCode; + this.lineNumber = lineNumber; + this.originalMessage = originalMessage; +} + +/** + * @constructor + * @param {DebuggerAgent.CallFrame} callFrame + * @param {number} index + * @param {WebInspector.DebuggerPresentationModel} model + * @param {WebInspector.RawSourceCode} rawSourceCode + */ +WebInspector.PresentationCallFrame = function(callFrame, index, model, rawSourceCode) +{ + this._callFrame = callFrame; + this._index = index; + this._model = model; + this._rawSourceCode = rawSourceCode; +} + +WebInspector.PresentationCallFrame.prototype = { + /** + * @return {string} + */ + get type() + { + return this._callFrame.type; + }, + + /** + * @return {Array.} + */ + get scopeChain() + { + return this._callFrame.scopeChain; + }, + + /** + * @return {RuntimeAgent.RemoteObject} + */ + get this() + { + return this._callFrame.this; + }, + + /** + * @return {number} + */ + get index() + { + return this._index; + }, + + /** + * @return {WebInspector.RawSourceCode} + */ + get rawSourceCode() + { + return this._rawSourceCode; + }, + + /** + * @param {string} code + * @param {string} objectGroup + * @param {boolean} includeCommandLineAPI + * @param {boolean} returnByValue + * @param {function(?RuntimeAgent.RemoteObject, boolean=)=} callback + */ + evaluate: function(code, objectGroup, includeCommandLineAPI, returnByValue, callback) + { + /** + * @this {WebInspector.PresentationCallFrame} + * @param {?Protocol.Error} error + * @param {RuntimeAgent.RemoteObject} result + * @param {boolean=} wasThrown + */ + function didEvaluateOnCallFrame(error, result, wasThrown) + { + if (error) { + console.error(error); + callback(null, false); + return; + } + callback(result, wasThrown); + } + DebuggerAgent.evaluateOnCallFrame(this._callFrame.callFrameId, code, objectGroup, includeCommandLineAPI, returnByValue, didEvaluateOnCallFrame.bind(this)); + }, + + /** + * @param {function(WebInspector.UILocation)} callback + */ + uiLocation: function(callback) + { + function sourceMappingReady() + { + this._rawSourceCode.removeEventListener(WebInspector.RawSourceCode.Events.SourceMappingUpdated, sourceMappingReady, this); + callback(this._rawSourceCode.sourceMapping.rawLocationToUILocation(this._callFrame.location)); + } + if (this._rawSourceCode.sourceMapping) + sourceMappingReady.call(this); + else + this._rawSourceCode.addEventListener(WebInspector.RawSourceCode.Events.SourceMappingUpdated, sourceMappingReady, this); + } +} + +/** + * @constructor + * @extends {WebInspector.Placard} + * @param {WebInspector.PresentationCallFrame} callFrame + */ +WebInspector.DebuggerPresentationModel.CallFramePlacard = function(callFrame) +{ + WebInspector.Placard.call(this, callFrame._callFrame.functionName || WebInspector.UIString("(anonymous function)"), ""); + this._callFrame = callFrame; + var rawSourceCode = callFrame._rawSourceCode; + if (rawSourceCode.sourceMapping) + this._update(); + rawSourceCode.addEventListener(WebInspector.RawSourceCode.Events.SourceMappingUpdated, this._update, this); +} + +WebInspector.DebuggerPresentationModel.CallFramePlacard.prototype = { + discard: function() + { + this._callFrame._rawSourceCode.removeEventListener(WebInspector.RawSourceCode.Events.SourceMappingUpdated, this._update, this); + }, + + _update: function() + { + var rawSourceCode = this._callFrame._rawSourceCode; + var uiLocation = rawSourceCode.sourceMapping.rawLocationToUILocation(this._callFrame._callFrame.location); + this.subtitle = WebInspector.displayNameForURL(uiLocation.uiSourceCode.url) + ":" + (uiLocation.lineNumber + 1); + } +} + +WebInspector.DebuggerPresentationModel.CallFramePlacard.prototype.__proto__ = WebInspector.Placard.prototype; + +/** + * @constructor + * @implements {WebInspector.ResourceDomainModelBinding} + * @param {WebInspector.DebuggerPresentationModel} model + */ +WebInspector.DebuggerPresentationModelResourceBinding = function(model) +{ + this._presentationModel = model; + WebInspector.Resource.registerDomainModelBinding(WebInspector.Resource.Type.Script, this); +} + +WebInspector.DebuggerPresentationModelResourceBinding.prototype = { + /** + * @param {WebInspector.Resource} resource + */ + canSetContent: function(resource) + { + var rawSourceCode = this._presentationModel._rawSourceCodeForScriptWithURL(resource.url) + if (!rawSourceCode) + return false; + return this._presentationModel.canEditScriptSource(rawSourceCode.sourceMapping.uiSourceCodeList()[0]); + }, + + /** + * @param {WebInspector.Resource} resource + * @param {string} content + * @param {boolean} majorChange + * @param {function(?string)} userCallback + */ + setContent: function(resource, content, majorChange, userCallback) + { + if (!majorChange) + return; + + var rawSourceCode = this._presentationModel._rawSourceCodeForScriptWithURL(resource.url); + if (!rawSourceCode) { + userCallback("Resource is not editable"); + return; + } + + resource.requestContent(this._setContentWithInitialContent.bind(this, rawSourceCode.sourceMapping.uiSourceCodeList()[0], content, userCallback)); + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + * @param {string} content + * @param {function(?string)} userCallback + * @param {?string} oldContent + * @param {?string} oldContentEncoded + */ + _setContentWithInitialContent: function(uiSourceCode, content, userCallback, oldContent, oldContentEncoded) + { + /** + * @this {WebInspector.DebuggerPresentationModelResourceBinding} + * @param {?string} error + */ + function callback(error) + { + if (userCallback) + userCallback(error); + if (!error) + this._presentationModel._updateBreakpointsAfterLiveEdit(uiSourceCode, oldContent || "", content); + } + this._presentationModel.setScriptSource(uiSourceCode, content, callback.bind(this)); + } +} + +/** + * @interface + */ +WebInspector.DebuggerPresentationModel.LinkifierFormatter = function() +{ +} + +WebInspector.DebuggerPresentationModel.LinkifierFormatter.prototype = { + /** + * @param {WebInspector.RawSourceCode} rawSourceCode + * @param {Element} anchor + */ + formatRawSourceCodeAnchor: function(rawSourceCode, anchor) { }, +} + +/** + * @constructor + * @implements {WebInspector.DebuggerPresentationModel.LinkifierFormatter} + * @param {number=} maxLength + */ +WebInspector.DebuggerPresentationModel.DefaultLinkifierFormatter = function(maxLength) +{ + this._maxLength = maxLength; +} + +WebInspector.DebuggerPresentationModel.DefaultLinkifierFormatter.prototype = { + /** + * @param {WebInspector.RawSourceCode} rawSourceCode + * @param {Element} anchor + */ + formatRawSourceCodeAnchor: function(rawSourceCode, anchor) + { + var uiLocation = rawSourceCode.sourceMapping.rawLocationToUILocation(anchor.rawLocation); + + anchor.textContent = WebInspector.formatLinkText(uiLocation.uiSourceCode.url, uiLocation.lineNumber); + + var text = WebInspector.formatLinkText(uiLocation.uiSourceCode.url, uiLocation.lineNumber); + if (this._maxLength) + text = text.trimMiddle(this._maxLength); + anchor.textContent = text; + } +} + +WebInspector.DebuggerPresentationModel.DefaultLinkifierFormatter.prototype.__proto__ = WebInspector.DebuggerPresentationModel.LinkifierFormatter.prototype; + +/** + * @constructor + * @param {WebInspector.DebuggerPresentationModel} model + * @param {WebInspector.DebuggerPresentationModel.LinkifierFormatter=} formatter + */ +WebInspector.DebuggerPresentationModel.Linkifier = function(model, formatter) +{ + this._model = model; + this._formatter = formatter || new WebInspector.DebuggerPresentationModel.DefaultLinkifierFormatter(); + this._anchorsForRawSourceCode = {}; +} + +WebInspector.DebuggerPresentationModel.Linkifier.prototype = { + /** + * @param {string} sourceURL + * @param {number} lineNumber + * @param {number=} columnNumber + * @param {string=} classes + */ + linkifyLocation: function(sourceURL, lineNumber, columnNumber, classes) + { + var rawSourceCode = this._model._rawSourceCodeForScriptWithURL(sourceURL); + if (!rawSourceCode) + return WebInspector.linkifyResourceAsNode(sourceURL, lineNumber, classes); + + return this.linkifyRawSourceCode(rawSourceCode, lineNumber, columnNumber, classes); + }, + + /** + * @param {WebInspector.RawSourceCode} rawSourceCode + * @param {number=} lineNumber + * @param {number=} columnNumber + * @param {string=} classes + */ + linkifyRawSourceCode: function(rawSourceCode, lineNumber, columnNumber, classes) + { + var anchor = WebInspector.linkifyURLAsNode(rawSourceCode.url, "", classes, false); + anchor.rawLocation = { lineNumber: lineNumber, columnNumber: columnNumber }; + + var anchors = this._anchorsForRawSourceCode[rawSourceCode.id]; + if (!anchors) { + anchors = []; + this._anchorsForRawSourceCode[rawSourceCode.id] = anchors; + rawSourceCode.addEventListener(WebInspector.RawSourceCode.Events.SourceMappingUpdated, this._updateSourceAnchors, this); + } + + if (rawSourceCode.sourceMapping) + this._updateAnchor(rawSourceCode, anchor); + anchors.push(anchor); + return anchor; + }, + + reset: function() + { + for (var id in this._anchorsForRawSourceCode) { + if (this._model._rawSourceCodeForScriptId[id]) // In case of navigation the list of rawSourceCodes is empty. + this._model._rawSourceCodeForScriptId[id].removeEventListener(WebInspector.RawSourceCode.Events.SourceMappingUpdated, this._updateSourceAnchors, this); + } + this._anchorsForRawSourceCode = {}; + }, + + /** + * @param {WebInspector.Event} event + */ + _updateSourceAnchors: function(event) + { + var rawSourceCode = /** @type {WebInspector.RawSourceCode} */ event.target; + var anchors = this._anchorsForRawSourceCode[rawSourceCode.id]; + for (var i = 0; i < anchors.length; ++i) + this._updateAnchor(rawSourceCode, anchors[i]); + }, + + /** + * @param {WebInspector.RawSourceCode} rawSourceCode + * @param {Element} anchor + */ + _updateAnchor: function(rawSourceCode, anchor) + { + var uiLocation = rawSourceCode.sourceMapping.rawLocationToUILocation(anchor.rawLocation); + anchor.preferredPanel = "scripts"; + anchor.uiSourceCode = uiLocation.uiSourceCode; + anchor.lineNumber = uiLocation.lineNumber; + + this._formatter.formatRawSourceCodeAnchor(rawSourceCode, anchor); + } +} + +WebInspector.DebuggerPresentationModelResourceBinding.prototype.__proto__ = WebInspector.ResourceDomainModelBinding.prototype; + +/** + * @type {?WebInspector.DebuggerPresentationModel} + */ +WebInspector.debuggerPresentationModel = null; +/* BreakpointManager.js */ + +/* + * Copyright (C) 2011 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. + */ + +/** + * @constructor + * @param {WebInspector.Setting} breakpointStorage + * @param {function(WebInspector.Breakpoint)} breakpointAddedDelegate + * @param {function(WebInspector.Breakpoint)} breakpointRemovedDelegate + * @param {WebInspector.DebuggerModel} debuggerModel + */ +WebInspector.BreakpointManager = function(breakpointStorage, breakpointAddedDelegate, breakpointRemovedDelegate, debuggerModel) +{ + this._breakpointStorage = breakpointStorage; + this._breakpointAddedDelegate = breakpointAddedDelegate; + this._breakpointRemovedDelegate = breakpointRemovedDelegate; + /** + * @type {Object.>} + */ + this._breakpointsByUILocation = {}; + + this._debuggerModel = debuggerModel; + + /** + * @type {Object.} + */ + this._breakpointsByDebuggerId = {}; + this._debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointResolved, this._breakpointResolved, this); + + var breakpoints = this._breakpointStorage.get(); + for (var i = 0; i < breakpoints.length; ++i) { + var breakpoint = WebInspector.Breakpoint.deserialize(breakpoints[i]); + if (!this._breakpoint(breakpoint.uiSourceCodeId, breakpoint.lineNumber)) + this._addBreakpointToUI(breakpoint); + } +} + +WebInspector.BreakpointManager.prototype = { + /** + * @param {WebInspector.UISourceCode} uiSourceCode + */ + uiSourceCodeAdded: function(uiSourceCode) + { + var breakpoints = this._breakpoints(uiSourceCode.id); + for (var lineNumber in breakpoints) { + var breakpoint = breakpoints[lineNumber]; + breakpoint.uiSourceCode = uiSourceCode; + this._materializeBreakpoint(breakpoint, uiSourceCode.rawSourceCode.sourceMapping, uiSourceCode); + if (breakpoint._debuggerLocation) + this._breakpointDebuggerLocationChanged(breakpoint); + } + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + */ + breakpointsForUISourceCode: function(uiSourceCode) + { + return this._breakpoints(uiSourceCode.id); + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + * @param {number} lineNumber + * @param {string} condition + * @param {boolean} enabled + */ + setBreakpoint: function(uiSourceCode, lineNumber, condition, enabled) + { + if (this._breakpoint(uiSourceCode.id, lineNumber)) + return; + + var persistent = !!uiSourceCode.url; + var breakpoint = new WebInspector.Breakpoint(uiSourceCode.id, lineNumber, condition, enabled, persistent); + breakpoint.uiSourceCode = uiSourceCode; + this._addBreakpointToUI(breakpoint); + this._materializeBreakpoint(breakpoint, uiSourceCode.rawSourceCode.sourceMapping, uiSourceCode); + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + * @param {number} lineNumber + */ + removeBreakpoint: function(uiSourceCode, lineNumber) + { + var breakpoint = this._breakpoint(uiSourceCode.id, lineNumber); + if (!breakpoint) + return; + this._removeBreakpoint(breakpoint); + }, + + /** + * @param {WebInspector.Breakpoint} breakpoint + */ + _removeBreakpoint: function(breakpoint) + { + this._deleteBreakpointFromUI(breakpoint); + this._removeBreakpointFromDebugger(breakpoint); + }, + + removeAllBreakpoints: function() + { + this._forEachBreakpoint(this._removeBreakpoint.bind(this)); + }, + + /** + * @param {WebInspector.Breakpoint} breakpoint + * @param {WebInspector.RawSourceCode.SourceMapping} sourceMapping + * @param {WebInspector.UISourceCode} uiSourceCode + */ + _materializeBreakpoint: function(breakpoint, sourceMapping, uiSourceCode) + { + if (!breakpoint.enabled || breakpoint._materialized) + return; + + breakpoint._materialized = true; + var rawLocation = sourceMapping.uiLocationToRawLocation(uiSourceCode, breakpoint.lineNumber, 0); + this._setBreakpointInDebugger(breakpoint, rawLocation); + }, + + /** + * @param {WebInspector.Breakpoint} breakpoint + */ + _breakpointDebuggerLocationChanged: function(breakpoint) + { + if (!breakpoint.uiSourceCode) + return; + var uiLocation = breakpoint.uiSourceCode.rawSourceCode.sourceMapping.rawLocationToUILocation(breakpoint._debuggerLocation); + if (uiLocation.lineNumber === breakpoint.lineNumber) + return; + + if (!this._moveBreakpointInUI(breakpoint, uiLocation.lineNumber)) + this._removeBreakpointFromDebugger(breakpoint); + }, + + /** + * @param {WebInspector.Breakpoint} breakpoint + */ + _addBreakpointToUI: function(breakpoint) + { + console.assert(!this._breakpoint(breakpoint.uiSourceCodeId, breakpoint.lineNumber)); + this._breakpoints(breakpoint.uiSourceCodeId)[breakpoint.lineNumber] = breakpoint; + this._saveBreakpoints(); + this._breakpointAddedDelegate(breakpoint); + }, + + /** + * @param {WebInspector.Breakpoint} breakpoint + */ + _deleteBreakpointFromUI: function(breakpoint) + { + console.assert(this._breakpoint(breakpoint.uiSourceCodeId, breakpoint.lineNumber) === breakpoint); + delete this._breakpoints(breakpoint.uiSourceCodeId)[breakpoint.lineNumber]; + this._saveBreakpoints(); + this._breakpointRemovedDelegate(breakpoint); + }, + + /** + * @param {WebInspector.Breakpoint} breakpoint + * @param {number} lineNumber + * @return {boolean} + */ + _moveBreakpointInUI: function(breakpoint, lineNumber) + { + this._deleteBreakpointFromUI(breakpoint); + if (this._breakpoint(breakpoint.uiSourceCodeId, lineNumber)) + return false; + breakpoint.lineNumber = lineNumber; + this._addBreakpointToUI(breakpoint); + return true; + }, + + /** + * @param {string} uiSourceCodeId + * @return {?Object.} + */ + _breakpoints: function(uiSourceCodeId) + { + if (!this._breakpointsByUILocation[uiSourceCodeId]) + this._breakpointsByUILocation[uiSourceCodeId] = {}; + return this._breakpointsByUILocation[uiSourceCodeId]; + }, + + /** + * @param {string} uiSourceCodeId + * @param {number} lineNumber + * @return {?WebInspector.Breakpoint} + */ + _breakpoint: function(uiSourceCodeId, lineNumber) + { + return this._breakpoints(uiSourceCodeId)[String(lineNumber)]; + }, + + /** + * @param {function(WebInspector.Breakpoint)} handler + */ + _forEachBreakpoint: function(handler) + { + for (var uiSourceCodeId in this._breakpointsByUILocation) { + var breakpoints = this._breakpointsByUILocation[uiSourceCodeId]; + for (var lineNumber in breakpoints) + handler(breakpoints[lineNumber]); + } + }, + + /** + * @param {WebInspector.Breakpoint} breakpoint + * @param {DebuggerAgent.Location} rawLocation + */ + _setBreakpointInDebugger: function(breakpoint, rawLocation) + { + /** + * @this {WebInspector.BreakpointManager} + * @param {DebuggerAgent.BreakpointId} breakpointId + * @param {Array.} locations + */ + function didSetBreakpoint(breakpointId, locations) + { + if (breakpoint === this._breakpoint(breakpoint.uiSourceCodeId, breakpoint.lineNumber)) { + if (!breakpointId) { + this._deleteBreakpointFromUI(breakpoint); + return; + } + } else { + if (breakpointId) + this._debuggerModel.removeBreakpoint(breakpointId); + return; + } + + this._breakpointsByDebuggerId[breakpointId] = breakpoint; + breakpoint._debuggerId = breakpointId; + breakpoint._debuggerLocation = locations[0]; + if (breakpoint._debuggerLocation) + this._breakpointDebuggerLocationChanged(breakpoint); + } + this._debuggerModel.setBreakpointByScriptLocation(rawLocation, breakpoint.condition, didSetBreakpoint.bind(this)); + }, + + /** + * @param {WebInspector.Breakpoint} breakpoint + */ + _removeBreakpointFromDebugger: function(breakpoint) + { + if (!("_debuggerId" in breakpoint)) + return; + this._debuggerModel.removeBreakpoint(breakpoint._debuggerId); + delete this._breakpointsByDebuggerId[breakpoint._debuggerId]; + delete breakpoint._debuggerId; + delete breakpoint._debuggerLocation; + }, + + /** + * @param {WebInspector.Event} event + */ + _breakpointResolved: function(event) + { + var breakpoint = this._breakpointsByDebuggerId[event.data["breakpointId"]]; + breakpoint._debuggerLocation = event.data["location"]; + this._breakpointDebuggerLocationChanged(breakpoint); + }, + + _saveBreakpoints: function() + { + var serializedBreakpoints = []; + /** + * @this {WebInspector.BreakpointManager} + * @param {WebInspector.Breakpoint} breakpoint + */ + function serializePersistent(breakpoint) + { + if (breakpoint.persistent) + serializedBreakpoints.push(breakpoint.serialize()); + } + this._forEachBreakpoint(serializePersistent.bind(this)); + this._breakpointStorage.set(serializedBreakpoints); + }, + + reset: function() + { + /** + * @this {WebInspector.BreakpointManager} + * @param {WebInspector.Breakpoint} breakpoint + */ + function resetBreakpoint(breakpoint) + { + this._removeBreakpointFromDebugger(breakpoint); + delete breakpoint._materialized; + } + this._forEachBreakpoint(resetBreakpoint.bind(this)); + }, + + debuggerReset: function() + { + /** + * @this {WebInspector.BreakpointManager} + * @param {WebInspector.Breakpoint} breakpoint + */ + function resetOrDeleteBreakpoint(breakpoint) + { + if (breakpoint.persistent) { + delete breakpoint.uiSourceCode; + delete breakpoint._debuggerLocation; + } else { + this._deleteBreakpointFromUI(breakpoint); + delete this._breakpointsByDebuggerId[breakpoint._debuggerId]; + } + } + this._forEachBreakpoint(resetOrDeleteBreakpoint.bind(this)); + + for (var id in this._breakpointsByUILocation) { + var empty = true; + for (var lineNumber in this._breakpointsByUILocation[id]) { + empty = false; + break; + } + if (empty) + delete this._breakpointsByUILocation[id]; + } + } +} + +/** + * @constructor + * @param {string} uiSourceCodeId + * @param {number} lineNumber + * @param {string} condition + * @param {boolean} enabled + * @param {boolean} persistent + */ +WebInspector.Breakpoint = function(uiSourceCodeId, lineNumber, condition, enabled, persistent) +{ + this.uiSourceCodeId = uiSourceCodeId; + this.lineNumber = lineNumber; + this.condition = condition; + this.enabled = enabled; + this.persistent = persistent; +} + +WebInspector.Breakpoint.prototype = { + /** + * @return {Object} + */ + serialize: function() + { + var serializedBreakpoint = {}; + serializedBreakpoint.sourceFileId = this.uiSourceCodeId; + serializedBreakpoint.lineNumber = this.lineNumber; + serializedBreakpoint.condition = this.condition; + serializedBreakpoint.enabled = this.enabled; + return serializedBreakpoint; + } +} + +/** + * @param {Object} serializedBreakpoint + * @return {WebInspector.Breakpoint} + */ +WebInspector.Breakpoint.deserialize = function(serializedBreakpoint) +{ + return new WebInspector.Breakpoint( + serializedBreakpoint.sourceFileId, + serializedBreakpoint.lineNumber, + serializedBreakpoint.condition, + serializedBreakpoint.enabled, + true); +} +/* UISourceCode.js */ + +/* + * Copyright (C) 2011 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. + */ + +/** + * @constructor + * @extends {WebInspector.Object} + * @param {string} id + * @param {string} url + * @param {WebInspector.RawSourceCode} rawSourceCode + * @param {WebInspector.ContentProvider} contentProvider + */ +WebInspector.UISourceCode = function(id, url, rawSourceCode, contentProvider) +{ + this._id = id; + this._url = url; + this._rawSourceCode = rawSourceCode; + this._contentProvider = contentProvider; + this.isContentScript = false; + /** + * @type Array. + */ + this._requestContentCallbacks = []; +} + +WebInspector.UISourceCode.Events = { + ContentChanged: "content-changed" +} + +WebInspector.UISourceCode.prototype = { + /** + * @return {string} + */ + get id() + { + return this._id; + }, + + /** + * @return {string} + */ + get url() + { + return this._url; + }, + + /** + * @return {WebInspector.RawSourceCode} + */ + get rawSourceCode() + { + return this._rawSourceCode; + }, + + /** + * @param {function(string,string)} callback + */ + requestContent: function(callback) + { + if (this._contentLoaded) { + callback(this._mimeType, this._content); + return; + } + + this._requestContentCallbacks.push(callback); + if (this._requestContentCallbacks.length === 1) + this._contentProvider.requestContent(this._didRequestContent.bind(this)); + }, + + /** + * @param {string} newContent + */ + contentChanged: function(newContent) + { + console.assert(this._contentLoaded); + this._content = newContent; + this.dispatchEventToListeners(WebInspector.UISourceCode.Events.ContentChanged); + }, + + /** + * @param {string} query + * @param {boolean} caseSensitive + * @param {boolean} isRegex + * @param {function(Array.)} callback + */ + searchInContent: function(query, caseSensitive, isRegex, callback) + { + this._contentProvider.searchInContent(query, caseSensitive, isRegex, callback); + }, + + /** + * @type {string} + */ + get domain() + { + if (typeof(this._domain) === "undefined") + this._parseURL(); + + return this._domain; + }, + + /** + * @type {string} + */ + get folderName() + { + if (typeof(this._folderName) === "undefined") + this._parseURL(); + + return this._folderName; + }, + + /** + * @type {string} + */ + get fileName() + { + if (typeof(this._fileName) === "undefined") + this._parseURL(); + + return this._fileName; + }, + + /** + * @type {string} + */ + get displayName() + { + if (typeof(this._displayName) === "undefined") + this._parseURL(); + + return this._displayName; + }, + + _parseURL: function() + { + var parsedURL = this.url.asParsedURL(); + var url = parsedURL ? parsedURL.path : this.url; + + var folderName = ""; + var fileName = url; + + var pathLength = fileName.indexOf("?"); + if (pathLength === -1) + pathLength = fileName.length; + + var fromIndex = fileName.lastIndexOf("/", pathLength - 2); + if (fromIndex !== -1) { + folderName = fileName.substring(0, fromIndex); + fileName = fileName.substring(fromIndex + 1); + } + + var indexOfQuery = fileName.indexOf("?"); + if (indexOfQuery === -1) + indexOfQuery = fileName.length; + var lastPathComponent = fileName.substring(0, indexOfQuery); + var queryParams = fileName.substring(indexOfQuery, fileName.length); + + const maxDisplayNameLength = 30; + const minDisplayQueryParamLength = 5; + + var maxDisplayQueryParamLength = Math.max(minDisplayQueryParamLength, maxDisplayNameLength - lastPathComponent.length); + var displayQueryParams = queryParams.trimEnd(maxDisplayQueryParamLength); + var displayLastPathComponent = lastPathComponent.trimMiddle(maxDisplayNameLength - displayQueryParams.length); + var displayName = displayLastPathComponent + displayQueryParams; + if (!displayName) + displayName = WebInspector.UIString("(program)"); + + if (folderName.length > 80) + folderName = "\u2026" + folderName.substring(folderName.length - 80); + + this._domain = parsedURL ? parsedURL.host : ""; + this._folderName = folderName; + this._fileName = fileName; + this._displayName = displayName; + }, + + /** + * @param {string} mimeType + * @param {string} content + */ + _didRequestContent: function(mimeType, content) + { + this._contentLoaded = true; + this._mimeType = mimeType; + this._content = content; + + for (var i = 0; i < this._requestContentCallbacks.length; ++i) + this._requestContentCallbacks[i](mimeType, content); + this._requestContentCallbacks = []; + } +} + +WebInspector.UISourceCode.prototype.__proto__ = WebInspector.Object.prototype; + +/** + * @interface + */ +WebInspector.ContentProvider = function() { } +WebInspector.ContentProvider.prototype = { + /** + * @param {function(string,string)} callback + */ + requestContent: function(callback) { }, + + /** + * @param {string} query + * @param {boolean} caseSensitive + * @param {boolean} isRegex + * @param {function(Array.)} callback + */ + searchInContent: function(query, caseSensitive, isRegex, callback) { } +} + +/** + * @constructor + * @param {number} lineNumber + * @param {string} lineContent + */ +WebInspector.ContentProvider.SearchMatch = function(lineNumber, lineContent) { + this.lineNumber = lineNumber; + this.lineContent = lineContent; +} +/* ContentProviders.js */ + +/* + * Copyright (C) 2011 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. + */ + +/** + * @constructor + * @implements {WebInspector.ContentProvider} + */ +WebInspector.ScriptContentProvider = function(script) +{ + this._mimeType = "text/javascript"; + this._script = script; +} + +WebInspector.ScriptContentProvider.prototype = { + /** + * @param {function(string,string)} callback + */ + requestContent: function(callback) + { + function didRequestSource(source) + { + callback(this._mimeType, source); + } + this._script.requestSource(didRequestSource.bind(this)); + }, + + /** + * @param {string} query + * @param {boolean} caseSensitive + * @param {boolean} isRegex + * @param {function(Array.)} callback + */ + searchInContent: function(query, caseSensitive, isRegex, callback) + { + this._script.searchInContent(query, caseSensitive, isRegex, callback); + } +} + +WebInspector.ScriptContentProvider.prototype.__proto__ = WebInspector.ContentProvider.prototype; + +/** + * @constructor + * @implements {WebInspector.ContentProvider} + */ +WebInspector.ConcatenatedScriptsContentProvider = function(scripts) +{ + this._mimeType = "text/html"; + this._scripts = scripts; +} + +WebInspector.ConcatenatedScriptsContentProvider.scriptOpenTag = ""; + +WebInspector.ConcatenatedScriptsContentProvider.prototype = { + /** + * @return {Array.} + */ + _sortedScripts: function() + { + if (this._sortedScriptsArray) + return this._sortedScriptsArray; + + this._sortedScriptsArray = []; + + var scripts = this._scripts.slice(); + scripts.sort(function(x, y) { return x.lineOffset - y.lineOffset || x.columnOffset - y.columnOffset; }); + + var scriptOpenTagLength = WebInspector.ConcatenatedScriptsContentProvider.scriptOpenTag.length; + var scriptCloseTagLength = WebInspector.ConcatenatedScriptsContentProvider.scriptCloseTag.length; + + this._sortedScriptsArray.push(scripts[0]); + for (var i = 1; i < scripts.length; ++i) { + var previousScript = this._sortedScriptsArray[this._sortedScriptsArray.length - 1]; + + var lineNumber = previousScript.endLine; + var columnNumber = previousScript.endColumn + scriptCloseTagLength + scriptOpenTagLength; + + if (lineNumber < scripts[i].lineOffset || (lineNumber === scripts[i].lineOffset && columnNumber <= scripts[i].columnOffset)) + this._sortedScriptsArray.push(scripts[i]); + } + return this._sortedScriptsArray; + }, + + /** + * @param {function(string,string)} callback + */ + requestContent: function(callback) + { + var scripts = this._sortedScripts(); + var sources = []; + function didRequestSource(source) + { + sources.push(source); + if (sources.length == scripts.length) + callback(this._mimeType, this._concatenateScriptsContent(scripts, sources)); + } + for (var i = 0; i < scripts.length; ++i) + scripts[i].requestSource(didRequestSource.bind(this)); + }, + + /** + * @param {string} query + * @param {boolean} caseSensitive + * @param {boolean} isRegex + * @param {function(Array.)} callback + */ + searchInContent: function(query, caseSensitive, isRegex, callback) + { + var results = {}; + var scripts = this._sortedScripts(); + var scriptsLeft = scripts.length; + + function maybeCallback() + { + if (scriptsLeft) + return; + + var result = []; + for (var i = 0; i < scripts.length; ++i) + result = result.concat(results[scripts[i].scriptId]); + callback(result); + } + + /** + * @param {WebInspector.Script} script + * @param {Array.} searchMatches + */ + function searchCallback(script, searchMatches) + { + results[script.scriptId] = []; + for (var i = 0; i < searchMatches.length; ++i) { + var searchMatch = new WebInspector.ContentProvider.SearchMatch(searchMatches[i].lineNumber + script.lineOffset, searchMatches[i].lineContent); + results[script.scriptId].push(searchMatch); + } + scriptsLeft--; + maybeCallback.call(this); + } + + maybeCallback(); + for (var i = 0; i < scripts.length; ++i) + scripts[i].searchInContent(query, caseSensitive, isRegex, searchCallback.bind(this, scripts[i])); + }, + + /** + * @return {string} + */ + _concatenateScriptsContent: function(scripts, sources) + { + var content = ""; + var lineNumber = 0; + var columnNumber = 0; + + var scriptOpenTag = WebInspector.ConcatenatedScriptsContentProvider.scriptOpenTag; + var scriptCloseTag = WebInspector.ConcatenatedScriptsContentProvider.scriptCloseTag; + for (var i = 0; i < scripts.length; ++i) { + // Fill the gap with whitespace characters. + for (var newLinesCount = scripts[i].lineOffset - lineNumber; newLinesCount > 0; --newLinesCount) { + columnNumber = 0; + content += "\n"; + } + for (var spacesCount = scripts[i].columnOffset - columnNumber - scriptOpenTag.length; spacesCount > 0; --spacesCount) + content += " "; + + // Add script tag. + content += scriptOpenTag; + content += sources[i]; + content += scriptCloseTag; + lineNumber = scripts[i].endLine; + columnNumber = scripts[i].endColumn + scriptCloseTag.length; + } + + return content; + } +} + +WebInspector.ConcatenatedScriptsContentProvider.prototype.__proto__ = WebInspector.ContentProvider.prototype; + +/** + * @constructor + * @implements {WebInspector.ContentProvider} + */ +WebInspector.ResourceContentProvider = function(resource) +{ + this._mimeType = resource.type === WebInspector.Resource.Type.Script ? "text/javascript" : "text/html"; + this._resource = resource; +}; + +WebInspector.ResourceContentProvider.prototype = { + /** + * @param {function(string,string)} callback + */ + requestContent: function(callback) + { + function didRequestContent(content) + { + callback(this._mimeType, content); + } + this._resource.requestContent(didRequestContent.bind(this)); + }, + + /** + * @param {string} query + * @param {boolean} caseSensitive + * @param {boolean} isRegex + * @param {function(Array.)} callback + */ + searchInContent: function(query, caseSensitive, isRegex, callback) + { + this._resource.searchInContent(query, caseSensitive, isRegex, callback); + } +} + +WebInspector.ResourceContentProvider.prototype.__proto__ = WebInspector.ContentProvider.prototype; + +/** + * @constructor + * @implements {WebInspector.ContentProvider} + */ +WebInspector.CompilerSourceMappingContentProvider = function(sourceURL, compilerSourceMapping) +{ + this._mimeType = "text/javascript"; + this._sourceURL = sourceURL; + this._compilerSourceMapping = compilerSourceMapping; +} + +WebInspector.CompilerSourceMappingContentProvider.prototype = { + /** + * @param {function(string,string)} callback + */ + requestContent: function(callback) + { + var sourceCode = this._compilerSourceMapping.loadSourceCode(this._sourceURL); + callback(this._mimeType, sourceCode); + }, + + /** + * @param {string} query + * @param {boolean} caseSensitive + * @param {boolean} isRegex + * @param {function(Array.)} callback + */ + searchInContent: function(query, caseSensitive, isRegex, callback) + { + callback([]); + } +} + +WebInspector.CompilerSourceMappingContentProvider.prototype.__proto__ = WebInspector.ContentProvider.prototype; + +/** + * @constructor + * @implements {WebInspector.ContentProvider} + */ +WebInspector.StaticContentProvider = function(mimeType, content) +{ + this._mimeType = mimeType; + this._content = content; +} + +WebInspector.StaticContentProvider.prototype = { + /** + * @param {function(string,string)} callback + */ + requestContent: function(callback) + { + callback(this._mimeType, this._content); + }, + + /** + * @param {string} query + * @param {boolean} caseSensitive + * @param {boolean} isRegex + * @param {function(Array.)} callback + */ + searchInContent: function(query, caseSensitive, isRegex, callback) + { + function performSearch() + { + var regex = createSearchRegex(query, caseSensitive, isRegex); + + var result = []; + var lineEndings = this._content.lineEndings(); + for (var i = 0; i < lineEndings.length; ++i) { + var lineStart = i > 0 ? lineEndings[i - 1] + 1 : 0; + var lineEnd = lineEndings[i]; + var lineContent = this._content.substring(lineStart, lineEnd); + if (lineContent.length > 0 && lineContent.charAt(lineContent.length - 1) === "\r") + lineContent = lineContent.substring(0, lineContent.length - 1) + + if (regex.exec(lineContent)) + result.push(new WebInspector.ContentProvider.SearchMatch(i, lineContent)); + } + callback(result); + } + + // searchInContent should call back later. + window.setTimeout(performSearch.bind(this), 0); + } +} + +WebInspector.StaticContentProvider.prototype.__proto__ = WebInspector.ContentProvider.prototype; +/* RawSourceCode.js */ + +/* + * Copyright (C) 2011 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. + */ + +// RawSourceCode represents JavaScript resource or HTML resource with inlined scripts +// as it came from network. + +/** + * @constructor + * @extends {WebInspector.Object} + * @param {string} id + * @param {WebInspector.Script} script + * @param {WebInspector.Resource} resource + * @param {WebInspector.ScriptFormatter} formatter + * @param {boolean} formatted + * @param {WebInspector.CompilerSourceMapping} compilerSourceMapping + */ +WebInspector.RawSourceCode = function(id, script, resource, formatter, formatted, compilerSourceMapping) +{ + this.id = id; + this.url = script.sourceURL; + this.isContentScript = script.isContentScript; + this._scripts = [script]; + this._formatter = formatter; + this._formatted = formatted; + this._compilerSourceMapping = compilerSourceMapping; + this._resource = resource; + this.messages = []; + + this._useTemporaryContent = !this._compilerSourceMapping && this._resource && !this._resource.finished; + this._hasNewScripts = true; + if (!this._useTemporaryContent) + this._updateSourceMapping(); + else if (this._resource) + this._resource.addEventListener("finished", this._resourceFinished.bind(this)); +} + +WebInspector.RawSourceCode.Events = { + SourceMappingUpdated: "source-mapping-updated" +} + +WebInspector.RawSourceCode.prototype = { + /** + * @param {WebInspector.Script} script + */ + addScript: function(script) + { + this._scripts.push(script); + this._hasNewScripts = true; + }, + + /** + * @return {WebInspector.RawSourceCode.SourceMapping} + */ + get sourceMapping() + { + return this._sourceMapping; + }, + + /** + * @param {boolean} formatted + */ + setFormatted: function(formatted) + { + if (this._formatted === formatted) + return; + this._formatted = formatted; + if (!this._compilerSourceMapping) + this._updateSourceMapping(); + }, + + _resourceFinished: function() + { + if (this._compilerSourceMapping) + return; + this._useTemporaryContent = false; + this._updateSourceMapping(); + }, + + /** + * @param {number} lineNumber + * @param {number=} columnNumber + * @return {WebInspector.Script} + */ + _scriptForRawLocation: function(lineNumber, columnNumber) + { + var closestScript = this._scripts[0]; + for (var i = 1; i < this._scripts.length; ++i) { + var script = this._scripts[i]; + if (script.lineOffset > lineNumber || (script.lineOffset === lineNumber && script.columnOffset > columnNumber)) + continue; + if (script.lineOffset > closestScript.lineOffset || + (script.lineOffset === closestScript.lineOffset && script.columnOffset > closestScript.columnOffset)) + closestScript = script; + } + return closestScript; + }, + + /** + * @param {WebInspector.Script} script + */ + forceUpdateSourceMapping: function(script) + { + if (!this._useTemporaryContent || !this._hasNewScripts) + return; + this._hasNewScripts = false; + this._updateSourceMapping(); + }, + + _updateSourceMapping: function() + { + if (this._updatingSourceMapping) { + this._updateNeeded = true; + return; + } + this._updatingSourceMapping = true; + this._updateNeeded = false; + + this._createSourceMapping(didCreateSourceMapping.bind(this)); + + /** + * @this {WebInspector.RawSourceCode} + * @param {WebInspector.RawSourceCode.SourceMapping} sourceMapping + */ + function didCreateSourceMapping(sourceMapping) + { + this._updatingSourceMapping = false; + if (sourceMapping && !this._updateNeeded) + this._saveSourceMapping(sourceMapping); + else + this._updateSourceMapping(); + } + }, + + _createContentProvider: function() + { + if (this._resource && this._resource.finished) + return new WebInspector.ResourceContentProvider(this._resource); + if (this._scripts.length === 1 && !this._scripts[0].lineOffset && !this._scripts[0].columnOffset) + return new WebInspector.ScriptContentProvider(this._scripts[0]); + return new WebInspector.ConcatenatedScriptsContentProvider(this._scripts); + }, + + /** + * @param {function(WebInspector.RawSourceCode.SourceMapping)} callback + */ + _createSourceMapping: function(callback) + { + if (this._compilerSourceMapping) { + var success = this._compilerSourceMapping.load(); + if (!success) { + delete this._compilerSourceMapping; + callback(null); + return; + } + var uiSourceCodeList = []; + var sourceURLs = this._compilerSourceMapping.sources(); + for (var i = 0; i < sourceURLs.length; ++i) { + var sourceURL = sourceURLs[i]; + var contentProvider = new WebInspector.CompilerSourceMappingContentProvider(sourceURL, this._compilerSourceMapping); + var uiSourceCode = this._createUISourceCode(sourceURL, sourceURL, contentProvider); + uiSourceCodeList.push(uiSourceCode); + } + var sourceMapping = new WebInspector.RawSourceCode.CompilerSourceMapping(this, uiSourceCodeList, this._compilerSourceMapping); + callback(sourceMapping); + return; + } + + var originalContentProvider = this._createContentProvider(); + if (!this._formatted) { + var uiSourceCode = this._createUISourceCode(this.url, this.url, originalContentProvider); + var sourceMapping = new WebInspector.RawSourceCode.PlainSourceMapping(this, uiSourceCode); + callback(sourceMapping); + return; + } + + /** + * @this {WebInspector.RawSourceCode} + * @param {string} mimeType + * @param {string} content + */ + function didRequestContent(mimeType, content) + { + /** + * @this {WebInspector.RawSourceCode} + * @param {string} formattedContent + * @param {WebInspector.FormattedSourceMapping} mapping + */ + function didFormatContent(formattedContent, mapping) + { + var contentProvider = new WebInspector.StaticContentProvider(mimeType, formattedContent) + var uiSourceCode = this._createUISourceCode("deobfuscated:" + this.url, this.url, contentProvider); + var sourceMapping = new WebInspector.RawSourceCode.FormattedSourceMapping(this, uiSourceCode, mapping); + callback(sourceMapping); + } + this._formatter.formatContent(mimeType, content, didFormatContent.bind(this)); + } + originalContentProvider.requestContent(didRequestContent.bind(this)); + }, + + /** + * @param {string} id + * @param {string} url + * @param {WebInspector.ContentProvider} contentProvider + */ + _createUISourceCode: function(id, url, contentProvider) + { + var uiSourceCode = new WebInspector.UISourceCode(id, url, this, contentProvider); + uiSourceCode.isContentScript = this.isContentScript; + return uiSourceCode; + }, + + /** + * @param {WebInspector.RawSourceCode.SourceMapping} sourceMapping + */ + _saveSourceMapping: function(sourceMapping) + { + var oldSourceMapping; + if (this._sourceMapping) + oldSourceMapping = this._sourceMapping; + this._sourceMapping = sourceMapping; + this.dispatchEventToListeners(WebInspector.RawSourceCode.Events.SourceMappingUpdated, { oldSourceMapping: oldSourceMapping }); + } +} + +WebInspector.RawSourceCode.prototype.__proto__ = WebInspector.Object.prototype; + +/** + * @interface + */ +WebInspector.RawSourceCode.SourceMapping = function() +{ +} + +WebInspector.RawSourceCode.SourceMapping.prototype = { + /** + * @param {DebuggerAgent.Location} rawLocation + * @return {WebInspector.UILocation} + */ + rawLocationToUILocation: function(rawLocation) { }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + * @param {number} lineNumber + * @param {number} columnNumber + * @return {DebuggerAgent.Location} + */ + uiLocationToRawLocation: function(uiSourceCode, lineNumber, columnNumber) { } +} + +/** + * @constructor + * @implements {WebInspector.RawSourceCode.SourceMapping} + * @param {WebInspector.RawSourceCode} rawSourceCode + * @param {WebInspector.UISourceCode} uiSourceCode + */ +WebInspector.RawSourceCode.PlainSourceMapping = function(rawSourceCode, uiSourceCode) +{ + this._rawSourceCode = rawSourceCode; + this._uiSourceCodeList = [uiSourceCode]; +} + +WebInspector.RawSourceCode.PlainSourceMapping.prototype = { + /** + * @param {DebuggerAgent.Location} rawLocation + * @return {WebInspector.UILocation} + */ + rawLocationToUILocation: function(rawLocation) + { + return new WebInspector.UILocation(this._uiSourceCodeList[0], rawLocation.lineNumber, rawLocation.columnNumber || 0); + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + * @param {number} lineNumber + * @param {number} columnNumber + * @return {DebuggerAgent.Location} + */ + uiLocationToRawLocation: function(uiSourceCode, lineNumber, columnNumber) + { + console.assert(uiSourceCode === this._uiSourceCodeList[0]); + var rawLocation = { lineNumber: lineNumber, columnNumber: columnNumber }; + rawLocation.scriptId = this._rawSourceCode._scriptForRawLocation(rawLocation.lineNumber, rawLocation.columnNumber).scriptId; + return /** @type {DebuggerAgent.Location} */ rawLocation; + }, + + /** + * @return {Array.} + */ + uiSourceCodeList: function() + { + return this._uiSourceCodeList; + } +} + +/** + * @constructor + * @implements {WebInspector.RawSourceCode.SourceMapping} + * @param {WebInspector.RawSourceCode} rawSourceCode + * @param {WebInspector.UISourceCode} uiSourceCode + * @param {WebInspector.FormattedSourceMapping} mapping + */ +WebInspector.RawSourceCode.FormattedSourceMapping = function(rawSourceCode, uiSourceCode, mapping) +{ + this._rawSourceCode = rawSourceCode; + this._uiSourceCodeList = [uiSourceCode]; + this._mapping = mapping; +} + +WebInspector.RawSourceCode.FormattedSourceMapping.prototype = { + /** + * @param {DebuggerAgent.Location} rawLocation + */ + rawLocationToUILocation: function(rawLocation) + { + var location = this._mapping.originalToFormatted(rawLocation); + return new WebInspector.UILocation(this._uiSourceCodeList[0], location.lineNumber, location.columnNumber || 0); + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + * @param {number} lineNumber + * @param {number} columnNumber + * @return {DebuggerAgent.Location} + */ + uiLocationToRawLocation: function(uiSourceCode, lineNumber, columnNumber) + { + console.assert(uiSourceCode === this._uiSourceCodeList[0]); + var rawLocation = this._mapping.formattedToOriginal(new WebInspector.DebuggerModel.Location(lineNumber, columnNumber)); + rawLocation.scriptId = this._rawSourceCode._scriptForRawLocation(rawLocation.lineNumber, rawLocation.columnNumber).scriptId; + return rawLocation; + }, + + /** + * @return {Array.} + */ + uiSourceCodeList: function() + { + return this._uiSourceCodeList; + } +} + +/** + * @constructor + * @implements {WebInspector.RawSourceCode.SourceMapping} + * @param {WebInspector.RawSourceCode} rawSourceCode + * @param {Array.} uiSourceCodeList + * @param {WebInspector.CompilerSourceMapping} mapping + */ +WebInspector.RawSourceCode.CompilerSourceMapping = function(rawSourceCode, uiSourceCodeList, mapping) +{ + this._rawSourceCode = rawSourceCode; + this._uiSourceCodeList = uiSourceCodeList; + this._mapping = mapping; + this._uiSourceCodeByURL = {}; + for (var i = 0; i < uiSourceCodeList.length; ++i) + this._uiSourceCodeByURL[uiSourceCodeList[i].url] = uiSourceCodeList[i]; +} + +WebInspector.RawSourceCode.CompilerSourceMapping.prototype = { + /** + * @param {DebuggerAgent.Location} rawLocation + */ + rawLocationToUILocation: function(rawLocation) + { + var location = this._mapping.compiledLocationToSourceLocation(rawLocation.lineNumber, rawLocation.columnNumber || 0); + var uiSourceCode = this._uiSourceCodeByURL[location.sourceURL]; + return new WebInspector.UILocation(uiSourceCode, location.lineNumber, location.columnNumber); + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + * @param {number} lineNumber + * @param {number} columnNumber + * @return {DebuggerAgent.Location} + */ + uiLocationToRawLocation: function(uiSourceCode, lineNumber, columnNumber) + { + var rawLocation = this._mapping.sourceLocationToCompiledLocation(uiSourceCode.url, lineNumber); + rawLocation.scriptId = this._rawSourceCode._scriptForRawLocation(rawLocation.lineNumber, rawLocation.columnNumber).scriptId; + return rawLocation; + }, + + /** + * @return {Array.} + */ + uiSourceCodeList: function() + { + return this._uiSourceCodeList; + } +} + +/** + * @constructor + * @param {WebInspector.UISourceCode} uiSourceCode + * @param {number} lineNumber + * @param {number} columnNumber + */ +WebInspector.UILocation = function(uiSourceCode, lineNumber, columnNumber) +{ + this.uiSourceCode = uiSourceCode; + this.lineNumber = lineNumber; + this.columnNumber = columnNumber; +} +/* CompilerSourceMapping.js */ + +/* + * Copyright (C) 2011 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. + */ + +/** + * @interface + */ +WebInspector.CompilerSourceMapping = function() +{ +} + +WebInspector.CompilerSourceMapping.prototype = { + /** + * @param {number} lineNumber + * @param {number} columnNumber + * @return {Object} + */ + compiledLocationToSourceLocation: function(lineNumber, columnNumber) { }, + + /** + * @param {string} sourceURL + * @param {number} lineNumber + * @return {DebuggerAgent.Location} + */ + sourceLocationToCompiledLocation: function(sourceURL, lineNumber) { }, + + /** + * @return {Array.} + */ + sources: function() { } +} + +/** + * @constructor + */ +WebInspector.ClosureCompilerSourceMappingPayload = function() +{ + this.mappings = ""; + this.sourceRoot = ""; + this.sources = []; +} + +/** + * Implements Source Map V3 consumer. See http://code.google.com/p/closure-compiler/wiki/SourceMaps + * for format description. + * @implements {WebInspector.CompilerSourceMapping} + * @constructor + * @param {string} sourceMappingURL + * @param {string} scriptSourceOrigin + */ +WebInspector.ClosureCompilerSourceMapping = function(sourceMappingURL, scriptSourceOrigin) +{ + if (!WebInspector.ClosureCompilerSourceMapping.prototype._base64Map) { + const base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + WebInspector.ClosureCompilerSourceMapping.prototype._base64Map = {}; + for (var i = 0; i < base64Digits.length; ++i) + WebInspector.ClosureCompilerSourceMapping.prototype._base64Map[base64Digits.charAt(i)] = i; + } + + this._sourceMappingURL = this._canonicalizeURL(sourceMappingURL, scriptSourceOrigin); + this._mappings = []; + this._reverseMappingsBySourceURL = {}; +} + +WebInspector.ClosureCompilerSourceMapping.prototype = { + /** + * @return {boolean} + */ + load: function() + { + try { + // FIXME: make sendRequest async. + var response = InspectorFrontendHost.loadResourceSynchronously(this._sourceMappingURL); + if (response.slice(0, 3) === ")]}") + response = response.substring(response.indexOf('\n')); + this._parseMappingPayload(JSON.parse(response)); + return true + } catch(e) { + console.error(e.message); + return false; + } + }, + + /** + * @param {number} lineNumber + * @param {number} columnNumber + * @return {Object} + */ + compiledLocationToSourceLocation: function(lineNumber, columnNumber) + { + var mapping = this._findMapping(lineNumber, columnNumber); + return { sourceURL: mapping[2], lineNumber: mapping[3], columnNumber: mapping[4] }; + }, + + sourceLocationToCompiledLocation: function(sourceURL, lineNumber) + { + var mappings = this._reverseMappingsBySourceURL[sourceURL]; + for ( ; lineNumber < mappings.length; ++lineNumber) { + var mapping = mappings[lineNumber]; + if (mapping) + return { lineNumber: mapping[0], columnNumber: mapping[1] }; + } + }, + + /** + * @return {Array.} + */ + sources: function() + { + var sources = []; + for (var sourceURL in this._reverseMappingsBySourceURL) + sources.push(sourceURL); + return sources; + }, + + /** + * @param {string} sourceURL + * @return {string} + */ + loadSourceCode: function(sourceURL) + { + try { + // FIXME: make sendRequest async. + return InspectorFrontendHost.loadResourceSynchronously(sourceURL); + } catch(e) { + console.error(e.message); + return ""; + } + }, + + _findMapping: function(lineNumber, columnNumber) + { + var first = 0; + var count = this._mappings.length; + while (count > 1) { + var step = count >> 1; + var middle = first + step; + var mapping = this._mappings[middle]; + if (lineNumber < mapping[0] || (lineNumber == mapping[0] && columnNumber < mapping[1])) + count = step; + else { + first = middle; + count -= step; + } + } + return this._mappings[first]; + }, + + _parseMappingPayload: function(mappingPayload) + { + if (mappingPayload.sections) + this._parseSections(mappingPayload.sections); + else + this._parseMap(mappingPayload, 0, 0); + }, + + _parseSections: function(sections) + { + for (var i = 0; i < sections.length; ++i) { + var section = sections[i]; + this._parseMap(section.map, section.offset.line, section.offset.column) + } + }, + + _parseMap: function(map, lineNumber, columnNumber) + { + var sourceIndex = 0; + var sourceLineNumber = 0; + var sourceColumnNumber = 0; + var nameIndex = 0; + + var sources = []; + for (var i = 0; i < map.sources.length; ++i) { + var sourceURL = map.sources[i]; + if (map.sourceRoot) + sourceURL = map.sourceRoot + "/" + sourceURL; + var url = this._canonicalizeURL(sourceURL, this._sourceMappingURL); + sources.push(url); + if (!this._reverseMappingsBySourceURL[url]) + this._reverseMappingsBySourceURL[url] = []; + } + + var stringCharIterator = new WebInspector.ClosureCompilerSourceMapping.StringCharIterator(map.mappings); + var sourceURL = sources[sourceIndex]; + var reverseMappings = this._reverseMappingsBySourceURL[sourceURL]; + + while (true) { + if (stringCharIterator.peek() === ",") + stringCharIterator.next(); + else { + while (stringCharIterator.peek() === ";") { + lineNumber += 1; + columnNumber = 0; + stringCharIterator.next(); + } + if (!stringCharIterator.hasNext()) + break; + } + + columnNumber += this._decodeVLQ(stringCharIterator); + if (!this._isSeparator(stringCharIterator.peek())) { + var sourceIndexDelta = this._decodeVLQ(stringCharIterator); + if (sourceIndexDelta) { + sourceIndex += sourceIndexDelta; + sourceURL = sources[sourceIndex]; + reverseMappings = this._reverseMappingsBySourceURL[sourceURL]; + } + sourceLineNumber += this._decodeVLQ(stringCharIterator); + sourceColumnNumber += this._decodeVLQ(stringCharIterator); + if (!this._isSeparator(stringCharIterator.peek())) + nameIndex += this._decodeVLQ(stringCharIterator); + + this._mappings.push([lineNumber, columnNumber, sourceURL, sourceLineNumber, sourceColumnNumber]); + if (!reverseMappings[sourceLineNumber]) + reverseMappings[sourceLineNumber] = [lineNumber, columnNumber]; + } + } + }, + + _isSeparator: function(char) + { + return char === "," || char === ";"; + }, + + _decodeVLQ: function(stringCharIterator) + { + // Read unsigned value. + var result = 0; + var shift = 0; + do { + var digit = this._base64Map[stringCharIterator.next()]; + result += (digit & this._VLQ_BASE_MASK) << shift; + shift += this._VLQ_BASE_SHIFT; + } while (digit & this._VLQ_CONTINUATION_MASK); + + // Fix the sign. + var negative = result & 1; + result >>= 1; + return negative ? -result : result; + }, + + _canonicalizeURL: function(url, baseURL) + { + if (!url || !baseURL || url.asParsedURL()) + return url; + + var base = baseURL.asParsedURL(); + if (!base) + return url; + + var baseHost = base.scheme + "://" + base.host + (base.port ? ":" + base.port : ""); + if (url[0] === "/") + return baseHost + url; + return baseHost + base.firstPathComponents + url; + }, + + _VLQ_BASE_SHIFT: 5, + _VLQ_BASE_MASK: (1 << 5) - 1, + _VLQ_CONTINUATION_MASK: 1 << 5 +} + +/** + * @constructor + */ +WebInspector.ClosureCompilerSourceMapping.StringCharIterator = function(string) +{ + this._string = string; + this._position = 0; +} + +WebInspector.ClosureCompilerSourceMapping.StringCharIterator.prototype = { + next: function() + { + return this._string.charAt(this._position++); + }, + + peek: function() + { + return this._string.charAt(this._position); + }, + + hasNext: function() + { + return this._position < this._string.length; + } +} +/* ScriptsSearchScope.js */ + +/* + * Copyright (C) 2011 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: + * + * 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 GOOGLE INC. 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 GOOGLE INC. + * 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. + */ + +/** + * @constructor + * @implements {WebInspector.SearchScope} + */ +WebInspector.ScriptsSearchScope = function() +{ + // FIXME: Add title once it is used by search controller. + WebInspector.SearchScope.call(this) + this._searchId = 0; +} + +WebInspector.ScriptsSearchScope.prototype = { + /** + * @param {WebInspector.SearchConfig} searchConfig + * @param {function(Object)} searchResultCallback + * @param {function(boolean)} searchFinishedCallback + */ + performSearch: function(searchConfig, searchResultCallback, searchFinishedCallback) + { + this.stopSearch(); + + var uiSourceCodes = this._sortedUISourceCodes(); + var uiSourceCodeIndex = 0; + + function filterOutContentScripts(uiSourceCode) + { + return !uiSourceCode.isContentScript; + } + + if (!WebInspector.settings.searchInContentScripts.get()) + uiSourceCodes = uiSourceCodes.filter(filterOutContentScripts); + + function continueSearch() + { + // FIXME: Enable support for counting matches for incremental search. + // FIXME: Enable support for bounding search results/matches number to keep inspector responsive. + if (uiSourceCodeIndex < uiSourceCodes.length) { + var uiSourceCode = uiSourceCodes[uiSourceCodeIndex++]; + uiSourceCode.searchInContent(searchConfig.query, !searchConfig.ignoreCase, searchConfig.isRegex, searchCallbackWrapper.bind(this, this._searchId, uiSourceCode)); + } else + searchFinishedCallback(true); + } + + function searchCallbackWrapper(searchId, uiSourceCode, searchMatches) + { + if (searchId !== this._searchId) { + searchFinishedCallback(false); + return; + } + + var searchResult = new WebInspector.FileBasedSearchResultsPane.SearchResult(uiSourceCode, searchMatches); + searchResultCallback(searchResult); + continueSearch.call(this); + } + + continueSearch.call(this); + return uiSourceCodes.length; + }, + + stopSearch: function() + { + ++this._searchId; + }, + + /** + * @param {WebInspector.SearchConfig} searchConfig + */ + createSearchResultsPane: function(searchConfig) + { + return new WebInspector.ScriptsSearchResultsPane(searchConfig); + }, + + /** + * @return {Array.} + */ + _sortedUISourceCodes: function() + { + function filterOutAnonymous(uiSourceCode) + { + return !!uiSourceCode.url; + } + + function comparator(a, b) + { + return a.url.localeCompare(b.url); + } + + var uiSourceCodes = WebInspector.debuggerPresentationModel.uiSourceCodes(); + + uiSourceCodes = uiSourceCodes.filter(filterOutAnonymous); + uiSourceCodes.sort(comparator); + + return uiSourceCodes; + } +} + +WebInspector.ScriptsSearchScope.prototype.__proto__ = WebInspector.SearchScope.prototype; + +/** + * @constructor + * @extends {WebInspector.FileBasedSearchResultsPane} + * @param {WebInspector.SearchConfig} searchConfig + */ +WebInspector.ScriptsSearchResultsPane = function(searchConfig) +{ + WebInspector.FileBasedSearchResultsPane.call(this, searchConfig) + + this._linkifier = WebInspector.debuggerPresentationModel.createLinkifier(new WebInspector.ScriptsSearchResultsPane.LinkifierFormatter()); +} + +WebInspector.ScriptsSearchResultsPane.prototype = { + /** + * @param {Object} file + * @param {number} lineNumber + * @param {number} columnNumber + */ + createAnchor: function(file, lineNumber, columnNumber) + { + + var uiSourceCode = file; + var rawSourceCode = uiSourceCode.rawSourceCode; + var rawLocation = rawSourceCode.sourceMapping.uiLocationToRawLocation(uiSourceCode, lineNumber, columnNumber); + var anchor = this._linkifier.linkifyRawSourceCode(uiSourceCode.rawSourceCode, rawLocation.lineNumber, rawLocation.columnNumber); + anchor.removeChildren(); + return anchor; + }, + + /** + * @param {Object} file + * @return {string} + */ + fileName: function(file) + { + var uiSourceCode = file; + return uiSourceCode.url; + }, +} + +WebInspector.ScriptsSearchResultsPane.prototype.__proto__ = WebInspector.FileBasedSearchResultsPane.prototype; + +/** + * @constructor + * @implements {WebInspector.DebuggerPresentationModel.LinkifierFormatter} + */ +WebInspector.ScriptsSearchResultsPane.LinkifierFormatter = function() +{ +} + +WebInspector.ScriptsSearchResultsPane.LinkifierFormatter.prototype = { + /** + * @param {WebInspector.RawSourceCode} rawSourceCode + * @param {Element} anchor + */ + formatRawSourceCodeAnchor: function(rawSourceCode, anchor) + { + // Empty because we don't want to ever update anchor contents after creation. + } +} + +WebInspector.ScriptsSearchResultsPane.LinkifierFormatter.prototype.__proto__ = WebInspector.DebuggerPresentationModel.LinkifierFormatter.prototype; + +WebInspector.settings.searchInContentScripts = WebInspector.settings.createSetting("searchInContentScripts", false); +/* DOMAgent.js */ + +/* + * Copyright (C) 2009, 2010 Google Inc. All rights reserved. + * Copyright (C) 2009 Joseph Pecoraro + * + * 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. + */ + +/** + * @constructor + * @param {WebInspector.DOMAgent} domAgent + * @param {?WebInspector.DOMDocument} doc + * @param {DOMAgent.Node} payload + */ +WebInspector.DOMNode = function(domAgent, doc, payload) { + this._domAgent = domAgent; + this.ownerDocument = doc; + + this.id = payload.nodeId; + this._nodeType = payload.nodeType; + this._nodeName = payload.nodeName; + this._localName = payload.localName; + this._nodeValue = payload.nodeValue; + + this._attributes = []; + this._attributesMap = {}; + if (payload.attributes) + this._setAttributesPayload(payload.attributes); + + this._childNodeCount = payload.childNodeCount; + this.children = null; + + this.nextSibling = null; + this.previousSibling = null; + this.firstChild = null; + this.lastChild = null; + this.parentNode = null; + + if (payload.children) + this._setChildrenPayload(payload.children); + + if (payload.contentDocument) { + this._contentDocument = new WebInspector.DOMDocument(domAgent, payload.contentDocument); + this.children = [this._contentDocument]; + this._renumber(); + } + + if (this._nodeType === Node.ELEMENT_NODE) { + // HTML and BODY from internal iframes should not overwrite top-level ones. + if (this.ownerDocument && !this.ownerDocument.documentElement && this._nodeName === "HTML") + this.ownerDocument.documentElement = this; + if (this.ownerDocument && !this.ownerDocument.body && this._nodeName === "BODY") + this.ownerDocument.body = this; + } else if (this._nodeType === Node.DOCUMENT_TYPE_NODE) { + this.publicId = payload.publicId; + this.systemId = payload.systemId; + this.internalSubset = payload.internalSubset; + } else if (this._nodeType === Node.ATTRIBUTE_NODE) { + this.name = payload.name; + this.value = payload.value; + } +} + +WebInspector.DOMNode.prototype = { + /** + * @return {boolean} + */ + hasAttributes: function() + { + return this._attributes.length > 0; + }, + + /** + * @return {boolean} + */ + hasChildNodes: function() + { + return this._childNodeCount > 0; + }, + + /** + * @return {number} + */ + nodeType: function() + { + return this._nodeType; + }, + + /** + * @return {string} + */ + nodeName: function() + { + return this._nodeName; + }, + + /** + * @return {string} + */ + nodeNameInCorrectCase: function() + { + return this.isXMLNode() ? this.nodeName() : this.nodeName().toLowerCase(); + }, + + /** + * @param {string} name + * @param {function(?Protocol.Error)=} callback + */ + setNodeName: function(name, callback) + { + DOMAgent.setNodeName(this.id, name, WebInspector.domAgent._markRevision(this, callback)); + }, + + /** + * @return {string} + */ + localName: function() + { + return this._localName; + }, + + /** + * @return {string} + */ + nodeValue: function() + { + return this._nodeValue; + }, + + /** + * @param {string} value + * @param {function(?Protocol.Error)=} callback + */ + setNodeValue: function(value, callback) + { + DOMAgent.setNodeValue(this.id, value, WebInspector.domAgent._markRevision(this, callback)); + }, + + /** + * @param {string} name + * @return {string} + */ + getAttribute: function(name) + { + var attr = this._attributesMap[name]; + return attr ? attr.value : undefined; + }, + + /** + * @param {string} name + * @param {string} text + * @param {function(?Protocol.Error)=} callback + */ + setAttribute: function(name, text, callback) + { + DOMAgent.setAttributesAsText(this.id, text, name, WebInspector.domAgent._markRevision(this, callback)); + }, + + /** + * @param {string} name + * @param {string} value + * @param {function(?Protocol.Error)=} callback + */ + setAttributeValue: function(name, value, callback) + { + DOMAgent.setAttributeValue(this.id, name, value, WebInspector.domAgent._markRevision(this, callback)); + }, + + /** + * @return {Object} + */ + attributes: function() + { + return this._attributes; + }, + + /** + * @param {string} name + * @param {function(?Protocol.Error)=} callback + */ + removeAttribute: function(name, callback) + { + function mycallback(error, success) + { + if (!error) { + delete this._attributesMap[name]; + for (var i = 0; i < this._attributes.length; ++i) { + if (this._attributes[i].name === name) { + this._attributes.splice(i, 1); + break; + } + } + } + + WebInspector.domAgent._markRevision(this, callback)(error); + } + DOMAgent.removeAttribute(this.id, name, mycallback.bind(this)); + }, + + /** + * @param {function(Array.)=} callback + */ + getChildNodes: function(callback) + { + if (this.children) { + if (callback) + callback(this.children); + return; + } + + /** + * @this {WebInspector.DOMNode} + * @param {?Protocol.Error} error + */ + function mycallback(error) + { + if (!error && callback) + callback(this.children); + } + + DOMAgent.requestChildNodes(this.id, mycallback.bind(this)); + }, + + /** + * @param {function(?Protocol.Error)=} callback + */ + getOuterHTML: function(callback) + { + DOMAgent.getOuterHTML(this.id, callback); + }, + + /** + * @param {string} html + * @param {function(?Protocol.Error)=} callback + */ + setOuterHTML: function(html, callback) + { + DOMAgent.setOuterHTML(this.id, html, WebInspector.domAgent._markRevision(this, callback)); + }, + + /** + * @param {function(?Protocol.Error)=} callback + */ + removeNode: function(callback) + { + DOMAgent.removeNode(this.id, WebInspector.domAgent._markRevision(this, callback)); + }, + + copyNode: function() + { + function copy(error, text) + { + if (!error) + InspectorFrontendHost.copyText(text); + } + DOMAgent.getOuterHTML(this.id, copy); + }, + + /** + * @param {function(?Protocol.Error)=} callback + */ + eventListeners: function(callback) + { + DOMAgent.getEventListenersForNode(this.id, callback); + }, + + /** + * @return {string} + */ + path: function() + { + var path = []; + var node = this; + while (node && "index" in node && node._nodeName.length) { + path.push([node.index, node._nodeName]); + node = node.parentNode; + } + path.reverse(); + return path.join(","); + }, + + /** + * @param {boolean} justSelector + * @return {string} + */ + appropriateSelectorFor: function(justSelector) + { + var lowerCaseName = this.localName() || this.nodeName().toLowerCase(); + + var id = this.getAttribute("id"); + if (id) { + var selector = "#" + id; + return (justSelector ? selector : lowerCaseName + selector); + } + + var className = this.getAttribute("class"); + if (className) { + var selector = "." + className.replace(/\s+/, "."); + return (justSelector ? selector : lowerCaseName + selector); + } + + if (lowerCaseName === "input" && this.getAttribute("type")) + return lowerCaseName + "[type=\"" + this.getAttribute("type") + "\"]"; + + return lowerCaseName; + }, + + /** + * @param {WebInspector.DOMNode} node + * @return {boolean} + */ + isAncestor: function(node) + { + if (!node) + return false; + + var currentNode = node.parentNode; + while (currentNode) { + if (this === currentNode) + return true; + currentNode = currentNode.parentNode; + } + return false; + }, + + /** + * @param {WebInspector.DOMNode} descendant + * @return {boolean} + */ + isDescendant: function(descendant) + { + return descendant !== null && descendant.isAncestor(this); + }, + + /** + * @param {Array.} attrs + */ + _setAttributesPayload: function(attrs) + { + this._attributes = []; + this._attributesMap = {}; + for (var i = 0; i < attrs.length; i += 2) + this._addAttribute(attrs[i], attrs[i + 1]); + }, + + /** + * @param {WebInspector.DOMNode} prev + * @param {DOMAgent.Node} payload + * @return {WebInspector.DOMNode} + */ + _insertChild: function(prev, payload) + { + var node = new WebInspector.DOMNode(this._domAgent, this.ownerDocument, payload); + if (!prev) { + if (!this.children) { + // First node + this.children = [ node ]; + } else + this.children.unshift(node); + } else + this.children.splice(this.children.indexOf(prev) + 1, 0, node); + this._renumber(); + return node; + }, + + /** + * @param {WebInspector.DOMNode} node + */ + _removeChild: function(node) + { + this.children.splice(this.children.indexOf(node), 1); + node.parentNode = null; + this._renumber(); + }, + + /** + * @param {Array.} payloads + */ + _setChildrenPayload: function(payloads) + { + // We set children in the constructor. + if (this._contentDocument) + return; + + this.children = []; + for (var i = 0; i < payloads.length; ++i) { + var payload = payloads[i]; + var node = new WebInspector.DOMNode(this._domAgent, this.ownerDocument, payload); + this.children.push(node); + } + this._renumber(); + }, + + _renumber: function() + { + this._childNodeCount = this.children.length; + if (this._childNodeCount == 0) { + this.firstChild = null; + this.lastChild = null; + return; + } + this.firstChild = this.children[0]; + this.lastChild = this.children[this._childNodeCount - 1]; + for (var i = 0; i < this._childNodeCount; ++i) { + var child = this.children[i]; + child.index = i; + child.nextSibling = i + 1 < this._childNodeCount ? this.children[i + 1] : null; + child.previousSibling = i - 1 >= 0 ? this.children[i - 1] : null; + child.parentNode = this; + } + }, + + /** + * @param {string} name + * @param {string} value + */ + _addAttribute: function(name, value) + { + var attr = { + name: name, + value: value, + _node: this + }; + this._attributesMap[name] = attr; + this._attributes.push(attr); + }, + + /** + * @param {string} name + * @param {string} value + */ + _setAttribute: function(name, value) + { + var attr = this._attributesMap[name]; + if (attr) + attr.value = value; + else + this._addAttribute(name, value); + }, + + /** + * @param {string} name + */ + _removeAttribute: function(name) + { + var attr = this._attributesMap[name]; + if (attr) { + this._attributes.remove(attr); + delete this._attributesMap[name]; + } + }, + + /** + * @param {WebInspector.DOMNode} targetNode + * @param {?WebInspector.DOMNode} anchorNode + * @param {function(?Protocol.Error)=} callback + */ + moveTo: function(targetNode, anchorNode, callback) + { + DOMAgent.moveTo(this.id, targetNode.id, anchorNode ? anchorNode.id : undefined, WebInspector.domAgent._markRevision(this, callback)); + }, + + /** + * @return {boolean} + */ + isXMLNode: function() + { + return !!this.ownerDocument && !!this.ownerDocument.xmlVersion; + } +} + +/** + * @extends {WebInspector.DOMNode} + * @constructor + * @param {WebInspector.DOMAgent} domAgent + * @param {DOMAgent.Node} payload + */ +WebInspector.DOMDocument = function(domAgent, payload) +{ + WebInspector.DOMNode.call(this, domAgent, this, payload); + this.documentURL = payload.documentURL || ""; + this.xmlVersion = payload.xmlVersion; + domAgent._idToDOMNode[this.id] = this; + this._listeners = {}; +} + +WebInspector.DOMDocument.prototype.__proto__ = WebInspector.DOMNode.prototype; + +/** + * @extends {WebInspector.Object} + * @constructor + */ +WebInspector.DOMAgent = function() { + /** @type {Object|undefined} */ + this._idToDOMNode = {}; + this._document = null; + this._attributeLoadNodeIds = {}; + InspectorBackend.registerDOMDispatcher(new WebInspector.DOMDispatcher(this)); + if (WebInspector.experimentsSettings.freeFlowDOMEditing.isEnabled()) + new WebInspector.DOMModelResourceBinding(this); +} + +WebInspector.DOMAgent.Events = { + AttrModified: "AttrModified", + AttrRemoved: "AttrRemoved", + CharacterDataModified: "CharacterDataModified", + NodeInserted: "NodeInserted", + NodeRemoved: "NodeRemoved", + DocumentUpdated: "DocumentUpdated", + ChildNodeCountUpdated: "ChildNodeCountUpdated", + InspectElementRequested: "InspectElementRequested", + StyleInvalidated: "StyleInvalidated" +} + +WebInspector.DOMAgent.prototype = { + /** + * @param {function(WebInspector.DOMDocument)=} callback + */ + requestDocument: function(callback) + { + if (this._document) { + if (callback) + callback(this._document); + return; + } + + if (this._pendingDocumentRequestCallbacks) { + this._pendingDocumentRequestCallbacks.push(callback); + return; + } + + this._pendingDocumentRequestCallbacks = [callback]; + + /** + * @this {WebInspector.DOMAgent} + * @param {?Protocol.Error} error + * @param {DOMAgent.Node} root + */ + function onDocumentAvailable(error, root) + { + if (!error) + this._setDocument(root); + + for (var i = 0; i < this._pendingDocumentRequestCallbacks.length; ++i) { + var callback = this._pendingDocumentRequestCallbacks[i]; + if (callback) + callback(this._document); + } + delete this._pendingDocumentRequestCallbacks; + } + + DOMAgent.getDocument(onDocumentAvailable.bind(this)); + }, + + /** + * @param {RuntimeAgent.RemoteObjectId} objectId + * @param {function()=} callback + */ + pushNodeToFrontend: function(objectId, callback) + { + this._dispatchWhenDocumentAvailable(DOMAgent.requestNode.bind(DOMAgent, objectId), callback); + }, + + /** + * @param {string} path + * @param {function(?WebInspector.DOMNode)=} callback + */ + pushNodeByPathToFrontend: function(path, callback) + { + var callbackCast = /** @type {function(*)} */ callback; + this._dispatchWhenDocumentAvailable(DOMAgent.pushNodeByPathToFrontend.bind(DOMAgent, path), callbackCast); + }, + + /** + * @param {function(*)=} callback + * @return {function(?Protocol.Error,*=)|undefined} + */ + _wrapClientCallback: function(callback) + { + if (!callback) + return; + return function(error, result) + { + if (error) + console.error("Error during DOMAgent operation: " + error); + callback(error ? null : result); + } + }, + + /** + * @param {function(function()=)} func + * @param {function(*)=} callback + */ + _dispatchWhenDocumentAvailable: function(func, callback) + { + var callbackWrapper = /** @type {function(?Protocol.Error, *=)} */ this._wrapClientCallback(callback); + + function onDocumentAvailable() + { + if (this._document) + func(callbackWrapper); + else { + if (callbackWrapper) + callbackWrapper("No document"); + } + } + this.requestDocument(onDocumentAvailable.bind(this)); + }, + + /** + * @param {DOMAgent.NodeId} nodeId + * @param {string} name + * @param {string} value + */ + _attributeModified: function(nodeId, name, value) + { + var node = this._idToDOMNode[nodeId]; + if (!node) + return; + node._setAttribute(name, value); + this.dispatchEventToListeners(WebInspector.DOMAgent.Events.AttrModified, { node: node, name: name }); + }, + + /** + * @param {DOMAgent.NodeId} nodeId + * @param {string} name + */ + _attributeRemoved: function(nodeId, name) + { + var node = this._idToDOMNode[nodeId]; + if (!node) + return; + node._removeAttribute(name); + this.dispatchEventToListeners(WebInspector.DOMAgent.Events.AttrRemoved, { node: node, name: name }); + }, + + /** + * @param {Array.} nodeIds + */ + _inlineStyleInvalidated: function(nodeIds) + { + for (var i = 0; i < nodeIds.length; ++i) + this._attributeLoadNodeIds[nodeIds[i]] = true; + if ("_loadNodeAttributesTimeout" in this) + return; + this._loadNodeAttributesTimeout = setTimeout(this._loadNodeAttributes.bind(this), 0); + }, + + _loadNodeAttributes: function() + { + /** + * @this {WebInspector.DOMAgent} + * @param {DOMAgent.NodeId} nodeId + * @param {?Protocol.Error} error + * @param {Array.} attributes + */ + function callback(nodeId, error, attributes) + { + if (error) { + console.error("Error during DOMAgent operation: " + error); + return; + } + var node = this._idToDOMNode[nodeId]; + if (node) { + node._setAttributesPayload(attributes); + this.dispatchEventToListeners(WebInspector.DOMAgent.Events.AttrModified, { node: node, name: "style" }); + this.dispatchEventToListeners(WebInspector.DOMAgent.Events.StyleInvalidated, node); + } + } + + delete this._loadNodeAttributesTimeout; + + for (var nodeId in this._attributeLoadNodeIds) { + var nodeIdAsNumber = parseInt(nodeId, 10); + DOMAgent.getAttributes(nodeIdAsNumber, callback.bind(this, nodeIdAsNumber)); + } + this._attributeLoadNodeIds = {}; + }, + + /** + * @param {DOMAgent.NodeId} nodeId + * @param {string} newValue + */ + _characterDataModified: function(nodeId, newValue) + { + var node = this._idToDOMNode[nodeId]; + node._nodeValue = newValue; + this.dispatchEventToListeners(WebInspector.DOMAgent.Events.CharacterDataModified, node); + }, + + /** + * @param {DOMAgent.NodeId} nodeId + * @return {WebInspector.DOMNode|undefined} + */ + nodeForId: function(nodeId) + { + return this._idToDOMNode[nodeId]; + }, + + _documentUpdated: function() + { + this._setDocument(null); + }, + + /** + * @param {DOMAgent.Node} payload + */ + _setDocument: function(payload) + { + this._idToDOMNode = {}; + if (payload && "nodeId" in payload) { + this._document = new WebInspector.DOMDocument(this, payload); + if (this._document.children) + this._bindNodes(this._document.children); + } else + this._document = null; + this.dispatchEventToListeners(WebInspector.DOMAgent.Events.DocumentUpdated, this._document); + }, + + /** + * @param {DOMAgent.Node} payload + */ + _setDetachedRoot: function(payload) + { + var root = new WebInspector.DOMNode(this, null, payload); + this._idToDOMNode[payload.nodeId] = root; + }, + + /** + * @param {DOMAgent.NodeId} parentId + * @param {Array.} payloads + */ + _setChildNodes: function(parentId, payloads) + { + if (!parentId && payloads.length) { + this._setDetachedRoot(payloads[0]); + return; + } + + var parent = this._idToDOMNode[parentId]; + parent._setChildrenPayload(payloads); + this._bindNodes(parent.children); + }, + + /** + * @param {Array.} children + */ + _bindNodes: function(children) + { + for (var i = 0; i < children.length; ++i) { + var child = children[i]; + this._idToDOMNode[child.id] = child; + if (child.children) + this._bindNodes(child.children); + } + }, + + /** + * @param {DOMAgent.NodeId} nodeId + * @param {number} newValue + */ + _childNodeCountUpdated: function(nodeId, newValue) + { + var node = this._idToDOMNode[nodeId]; + node._childNodeCount = newValue; + this.dispatchEventToListeners(WebInspector.DOMAgent.Events.ChildNodeCountUpdated, node); + }, + + /** + * @param {DOMAgent.NodeId} parentId + * @param {DOMAgent.NodeId} prevId + * @param {DOMAgent.Node} payload + */ + _childNodeInserted: function(parentId, prevId, payload) + { + var parent = this._idToDOMNode[parentId]; + var prev = this._idToDOMNode[prevId]; + var node = parent._insertChild(prev, payload); + this._idToDOMNode[node.id] = node; + this.dispatchEventToListeners(WebInspector.DOMAgent.Events.NodeInserted, node); + }, + + /** + * @param {DOMAgent.NodeId} parentId + * @param {DOMAgent.NodeId} nodeId + */ + _childNodeRemoved: function(parentId, nodeId) + { + var parent = this._idToDOMNode[parentId]; + var node = this._idToDOMNode[nodeId]; + parent._removeChild(node); + this.dispatchEventToListeners(WebInspector.DOMAgent.Events.NodeRemoved, {node:node, parent:parent}); + delete this._idToDOMNode[nodeId]; + }, + + /** + * @param {number} nodeId + */ + inspectElement: function(nodeId) + { + var node = this._idToDOMNode[nodeId]; + if (node) + this.dispatchEventToListeners(WebInspector.DOMAgent.Events.InspectElementRequested, node); + }, + + /** + * @param {string} query + * @param {function(number)} searchCallback + */ + performSearch: function(query, searchCallback) + { + this.cancelSearch(); + + /** + * @param {?Protocol.Error} error + * @param {string} searchId + * @param {number} resultsCount + */ + function callback(error, searchId, resultsCount) + { + this._searchId = searchId; + searchCallback(resultsCount); + } + DOMAgent.performSearch(query, callback.bind(this)); + }, + + /** + * @param {number} index + * @param {?function(DOMAgent.Node)} callback + */ + searchResult: function(index, callback) + { + if (this._searchId) { + /** + * @param {?Protocol.Error} error + * @param {Array.} nodeIds + */ + function mycallback(error, nodeIds) + { + if (error) { + console.error(error); + callback(null); + return; + } + if (nodeIds.length != 1) + return; + + callback(this._idToDOMNode[nodeIds[0]]); + } + DOMAgent.getSearchResults(this._searchId, index, index + 1, mycallback.bind(this)); + } else + callback(null); + }, + + cancelSearch: function() + { + if (this._searchId) { + DOMAgent.discardSearchResults(this._searchId); + delete this._searchId; + } + }, + + /** + * @param {DOMAgent.NodeId} nodeId + * @param {string} selectors + * @param {function(?DOMAgent.NodeId)=} callback + */ + querySelector: function(nodeId, selectors, callback) + { + var callbackCast = /** @type {function(*)|undefined} */callback; + DOMAgent.querySelector(nodeId, selectors, this._wrapClientCallback(callbackCast)); + }, + + /** + * @param {DOMAgent.NodeId} nodeId + * @param {string} selectors + * @param {function(?Array.)=} callback + */ + querySelectorAll: function(nodeId, selectors, callback) + { + var callbackCast = /** @type {function(*)|undefined} */callback; + DOMAgent.querySelectorAll(nodeId, selectors, this._wrapClientCallback(callbackCast)); + }, + + /** + * @param {?number} nodeId + * @param {string=} mode + */ + highlightDOMNode: function(nodeId, mode) + { + if (this._hideDOMNodeHighlightTimeout) { + clearTimeout(this._hideDOMNodeHighlightTimeout); + delete this._hideDOMNodeHighlightTimeout; + } + + this._highlightedDOMNodeId = nodeId; + if (nodeId) + DOMAgent.highlightNode(nodeId, this._buildHighlightConfig(mode)); + else + DOMAgent.hideHighlight(); + }, + + hideDOMNodeHighlight: function() + { + this.highlightDOMNode(0); + }, + + /** + * @param {?DOMAgent.NodeId} nodeId + */ + highlightDOMNodeForTwoSeconds: function(nodeId) + { + this.highlightDOMNode(nodeId); + this._hideDOMNodeHighlightTimeout = setTimeout(this.hideDOMNodeHighlight.bind(this), 2000); + }, + + /** + * @param {boolean} enabled + * @param {function()=} callback + */ + setInspectModeEnabled: function(enabled, callback) + { + DOMAgent.setInspectModeEnabled(enabled, this._buildHighlightConfig(), callback); + }, + + /** + * @param {string=} mode + */ + _buildHighlightConfig: function(mode) + { + mode = mode || "all"; + var highlightConfig = { showInfo: mode === "all" }; + if (mode === "all" || mode === "content") + highlightConfig.contentColor = WebInspector.Color.PageHighlight.Content.toProtocolRGBA(); + + if (mode === "all" || mode === "padding") + highlightConfig.paddingColor = WebInspector.Color.PageHighlight.Padding.toProtocolRGBA(); + + if (mode === "all" || mode === "border") + highlightConfig.borderColor = WebInspector.Color.PageHighlight.Border.toProtocolRGBA(); + + if (mode === "all" || mode === "margin") + highlightConfig.marginColor = WebInspector.Color.PageHighlight.Margin.toProtocolRGBA(); + + return highlightConfig; + }, + + /** + * @param {WebInspector.DOMNode} node + * @param {function(?Protocol.Error)=} callback + * @return {function(?Protocol.Error)} + */ + _markRevision: function(node, callback) + { + function wrapperFunction(error) + { + if (callback) + callback(error); + if (error || !WebInspector.experimentsSettings.freeFlowDOMEditing.isEnabled()) + return; + if (this._captureDOMTimer) + clearTimeout(this._captureDOMTimer); + this._captureDOMTimer = setTimeout(this._captureDOM.bind(this, node), 500); + } + return wrapperFunction.bind(this); + }, + + /** + * @param {WebInspector.DOMNode} node + */ + _captureDOM: function(node) + { + delete this._captureDOMTimer; + if (!node.ownerDocument) + return; + + function callback(error, text) + { + if (error) { + console.error(error); + return; + } + + var url = node.ownerDocument.documentURL; + if (!url) + return; + + var resource = WebInspector.resourceForURL(url); + if (!resource) + return; + + resource.addRevision(text); + } + DOMAgent.getOuterHTML(node.ownerDocument.id, callback); + + } +} + +WebInspector.DOMAgent.prototype.__proto__ = WebInspector.Object.prototype; + +/** + * @constructor + * @implements {DOMAgent.Dispatcher} + * @param {WebInspector.DOMAgent} domAgent + */ +WebInspector.DOMDispatcher = function(domAgent) +{ + this._domAgent = domAgent; +} + +WebInspector.DOMDispatcher.prototype = { + documentUpdated: function() + { + this._domAgent._documentUpdated(); + }, + + /** + * @param {DOMAgent.NodeId} nodeId + * @param {string} name + * @param {string} value + */ + attributeModified: function(nodeId, name, value) + { + this._domAgent._attributeModified(nodeId, name, value); + }, + + /** + * @param {DOMAgent.NodeId} nodeId + * @param {string} name + */ + attributeRemoved: function(nodeId, name) + { + this._domAgent._attributeRemoved(nodeId, name); + }, + + /** + * @param {Array.} nodeIds + */ + inlineStyleInvalidated: function(nodeIds) + { + this._domAgent._inlineStyleInvalidated(nodeIds); + }, + + /** + * @param {DOMAgent.NodeId} nodeId + * @param {string} characterData + */ + characterDataModified: function(nodeId, characterData) + { + this._domAgent._characterDataModified(nodeId, characterData); + }, + + /** + * @param {DOMAgent.NodeId} parentId + * @param {Array.} payloads + */ + setChildNodes: function(parentId, payloads) + { + this._domAgent._setChildNodes(parentId, payloads); + }, + + /** + * @param {DOMAgent.NodeId} nodeId + * @param {number} childNodeCount + */ + childNodeCountUpdated: function(nodeId, childNodeCount) + { + this._domAgent._childNodeCountUpdated(nodeId, childNodeCount); + }, + + /** + * @param {DOMAgent.NodeId} parentNodeId + * @param {DOMAgent.NodeId} previousNodeId + * @param {DOMAgent.Node} payload + */ + childNodeInserted: function(parentNodeId, previousNodeId, payload) + { + this._domAgent._childNodeInserted(parentNodeId, previousNodeId, payload); + }, + + /** + * @param {DOMAgent.NodeId} parentNodeId + * @param {DOMAgent.NodeId} nodeId + */ + childNodeRemoved: function(parentNodeId, nodeId) + { + this._domAgent._childNodeRemoved(parentNodeId, nodeId); + } +} + +/** + * @type {?WebInspector.DOMAgent} + */ +WebInspector.domAgent = null; + +/** + * @constructor + * @implements {WebInspector.ResourceDomainModelBinding} + */ +WebInspector.DOMModelResourceBinding = function(domAgent) +{ + this._domAgent = domAgent; + WebInspector.Resource.registerDomainModelBinding(WebInspector.Resource.Type.Document, this); +} + +WebInspector.DOMModelResourceBinding.prototype = { + setContent: function(resource, content, majorChange, userCallback) + { + var frameId = resource.frameId; + if (!frameId) + return; + + PageAgent.setDocumentContent(frameId, content, callbackWrapper); + + function callbackWrapper(error) + { + if (majorChange) + resource.addRevision(content); + if (userCallback) + userCallback(error); + } + }, + + canSetContent: function() + { + return true; + } +} + +WebInspector.DOMModelResourceBinding.prototype.__proto__ = WebInspector.ResourceDomainModelBinding.prototype; +/* TimelineAgent.js */ + +/* + * 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. + */ + +/** + * @constructor + */ +WebInspector.TimelineAgent = function() { + // Not implemented. +} + +// Must be kept in sync with InspectorTimelineAgent.h +WebInspector.TimelineAgent.RecordType = { + EventDispatch: "EventDispatch", + Layout: "Layout", + RecalculateStyles: "RecalculateStyles", + Paint: "Paint", + ParseHTML: "ParseHTML", + + + TimerInstall: "TimerInstall", + TimerRemove: "TimerRemove", + TimerFire: "TimerFire", + + XHRReadyStateChange: "XHRReadyStateChange", + XHRLoad: "XHRLoad", + EvaluateScript: "EvaluateScript", + + TimeStamp: "TimeStamp", + + MarkLoad: "MarkLoad", + MarkDOMContent: "MarkDOMContent", + + ScheduleResourceRequest: "ScheduleResourceRequest", + ResourceSendRequest: "ResourceSendRequest", + ResourceReceiveResponse: "ResourceReceiveResponse", + ResourceReceivedData: "ResourceReceivedData", + ResourceFinish: "ResourceFinish", + + FunctionCall: "FunctionCall", + GCEvent: "GCEvent", + + RegisterAnimationFrameCallback: "RegisterAnimationFrameCallback", + CancelAnimationFrameCallback: "CancelAnimationFrameCallback", + FireAnimationFrameEvent: "FireAnimationFrameEvent" +} +/* TimelinePanel.js */ + +/* + * Copyright (C) 2011 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. + */ + +/** + * @constructor + * @extends {WebInspector.Panel} + */ +WebInspector.TimelinePanel = function() +{ + WebInspector.Panel.call(this, "timeline"); + this.registerRequiredCSS("timelinePanel.css"); + + this.element.appendChild(this._createTopPane()); + this.element.addEventListener("contextmenu", this._contextMenu.bind(this), true); + this.element.tabIndex = 0; + + this._sidebarBackgroundElement = document.createElement("div"); + this._sidebarBackgroundElement.className = "sidebar split-view-sidebar-left timeline-sidebar-background"; + this.element.appendChild(this._sidebarBackgroundElement); + + this.createSplitViewWithSidebarTree(); + this._containerElement = this.splitView.element; + this._containerElement.id = "timeline-container"; + this._containerElement.addEventListener("scroll", this._onScroll.bind(this), false); + + var itemsTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("RECORDS"), {}, true); + this.sidebarTree.appendChild(itemsTreeElement); + + this._sidebarListElement = document.createElement("div"); + this.sidebarElement.appendChild(this._sidebarListElement); + + this._containerContentElement = this.splitView.mainElement; + this._containerContentElement.id = "resources-container-content"; + + this._timelineGrid = new WebInspector.TimelineGrid(); + this._itemsGraphsElement = this._timelineGrid.itemsGraphsElement; + this._itemsGraphsElement.id = "timeline-graphs"; + this._itemsGraphsElement.addEventListener("mousewheel", this._overviewPane.scrollWindow.bind(this._overviewPane), true); + this._containerContentElement.appendChild(this._timelineGrid.element); + + this._topGapElement = document.createElement("div"); + this._topGapElement.className = "timeline-gap"; + this._itemsGraphsElement.appendChild(this._topGapElement); + + this._graphRowsElement = document.createElement("div"); + this._itemsGraphsElement.appendChild(this._graphRowsElement); + + this._bottomGapElement = document.createElement("div"); + this._bottomGapElement.className = "timeline-gap"; + this._itemsGraphsElement.appendChild(this._bottomGapElement); + + this._expandElements = document.createElement("div"); + this._expandElements.id = "orphan-expand-elements"; + this._itemsGraphsElement.appendChild(this._expandElements); + + this._rootRecord = this._createRootRecord(); + this._sendRequestRecords = {}; + this._scheduledResourceRequests = {}; + this._timerRecords = {}; + this._registeredAnimationCallbackRecords = {}; + + this._calculator = new WebInspector.TimelineCalculator(); + this._calculator._showShortEvents = false; + var shortRecordThresholdTitle = Number.secondsToString(WebInspector.TimelinePanel.shortRecordThreshold); + this._showShortRecordsTitleText = WebInspector.UIString("Show the records that are shorter than %s", shortRecordThresholdTitle); + this._hideShortRecordsTitleText = WebInspector.UIString("Hide the records that are shorter than %s", shortRecordThresholdTitle); + this._createStatusbarButtons(); + + this._boundariesAreValid = true; + this._scrollTop = 0; + + this._popoverHelper = new WebInspector.PopoverHelper(this._containerElement, this._getPopoverAnchor.bind(this), this._showPopover.bind(this)); + this._containerElement.addEventListener("mousemove", this._mouseMove.bind(this), false); + this._containerElement.addEventListener("mouseout", this._mouseOut.bind(this), false); + + // Disable short events filter by default. + this.toggleFilterButton.toggled = true; + this._calculator._showShortEvents = this.toggleFilterButton.toggled; + this._timeStampRecords = []; + this._expandOffset = 15; + + this._createFileSelector(); + this._model = new WebInspector.TimelineModel(this); + + this._registerShortcuts(); + WebInspector.timelineManager.addEventListener(WebInspector.TimelineManager.EventTypes.TimelineEventRecorded, this._onTimelineEventRecorded, this); + this._linkifier = WebInspector.debuggerPresentationModel.createLinkifier(); +} + +// Define row height, should be in sync with styles for timeline graphs. +WebInspector.TimelinePanel.rowHeight = 18; +WebInspector.TimelinePanel.shortRecordThreshold = 0.015; + +WebInspector.TimelinePanel.prototype = { + _linkifyLocation: function(url, lineNumber, columnNumber) + { + // FIXME(62725): stack trace line/column numbers are one-based. + lineNumber = lineNumber ? lineNumber - 1 : lineNumber; + columnNumber = columnNumber ? columnNumber - 1 : 0; + return this._linkifier.linkifyLocation(url, lineNumber, columnNumber, "timeline-details"); + }, + + _linkifyCallFrame: function(callFrame) + { + return this._linkifyLocation(callFrame.url, callFrame.lineNumber, callFrame.columnNumber); + }, + + _createTopPane: function() { + var topPaneElement = document.createElement("div"); + topPaneElement.id = "timeline-overview-panel"; + + this._topPaneSidebarElement = document.createElement("div"); + this._topPaneSidebarElement.id = "timeline-overview-sidebar"; + + var overviewTreeElement = document.createElement("ol"); + overviewTreeElement.className = "sidebar-tree"; + this._topPaneSidebarElement.appendChild(overviewTreeElement); + topPaneElement.appendChild(this._topPaneSidebarElement); + + var topPaneSidebarTree = new TreeOutline(overviewTreeElement); + var timelinesOverviewItem = new WebInspector.SidebarTreeElement("resources-time-graph-sidebar-item", WebInspector.UIString("Timelines")); + topPaneSidebarTree.appendChild(timelinesOverviewItem); + timelinesOverviewItem.revealAndSelect(false); + timelinesOverviewItem.onselect = this._timelinesOverviewItemSelected.bind(this); + + var memoryOverviewItem = new WebInspector.SidebarTreeElement("resources-size-graph-sidebar-item", WebInspector.UIString("Memory")); + topPaneSidebarTree.appendChild(memoryOverviewItem); + memoryOverviewItem.onselect = this._memoryOverviewItemSelected.bind(this); + + this._overviewPane = new WebInspector.TimelineOverviewPane(this.categories); + this._overviewPane.addEventListener("window changed", this._windowChanged, this); + this._overviewPane.addEventListener("filter changed", this._refresh, this); + topPaneElement.appendChild(this._overviewPane.element); + + var separatorElement = document.createElement("div"); + separatorElement.id = "timeline-overview-separator"; + topPaneElement.appendChild(separatorElement); + return topPaneElement; + }, + + get toolbarItemLabel() + { + return WebInspector.UIString("Timeline"); + }, + + get statusBarItems() + { + return [this.toggleFilterButton.element, this.toggleTimelineButton.element, this.garbageCollectButton.element, this.clearButton.element, this._overviewPane.statusBarFilters]; + }, + + get categories() + { + if (!this._categories) { + this._categories = { + loading: new WebInspector.TimelineCategory("loading", WebInspector.UIString("Loading"), "rgb(47,102,236)"), + scripting: new WebInspector.TimelineCategory("scripting", WebInspector.UIString("Scripting"), "rgb(157,231,119)"), + rendering: new WebInspector.TimelineCategory("rendering", WebInspector.UIString("Rendering"), "rgb(164,60,255)") + }; + } + return this._categories; + }, + + get defaultFocusedElement() + { + return this.element; + }, + + get _recordStyles() + { + if (!this._recordStylesArray) { + var recordTypes = WebInspector.TimelineAgent.RecordType; + var recordStyles = {}; + recordStyles[recordTypes.EventDispatch] = { title: WebInspector.UIString("Event"), category: this.categories.scripting }; + recordStyles[recordTypes.Layout] = { title: WebInspector.UIString("Layout"), category: this.categories.rendering }; + recordStyles[recordTypes.RecalculateStyles] = { title: WebInspector.UIString("Recalculate Style"), category: this.categories.rendering }; + recordStyles[recordTypes.Paint] = { title: WebInspector.UIString("Paint"), category: this.categories.rendering }; + recordStyles[recordTypes.ParseHTML] = { title: WebInspector.UIString("Parse"), category: this.categories.loading }; + recordStyles[recordTypes.TimerInstall] = { title: WebInspector.UIString("Install Timer"), category: this.categories.scripting }; + recordStyles[recordTypes.TimerRemove] = { title: WebInspector.UIString("Remove Timer"), category: this.categories.scripting }; + recordStyles[recordTypes.TimerFire] = { title: WebInspector.UIString("Timer Fired"), category: this.categories.scripting }; + recordStyles[recordTypes.XHRReadyStateChange] = { title: WebInspector.UIString("XHR Ready State Change"), category: this.categories.scripting }; + recordStyles[recordTypes.XHRLoad] = { title: WebInspector.UIString("XHR Load"), category: this.categories.scripting }; + recordStyles[recordTypes.EvaluateScript] = { title: WebInspector.UIString("Evaluate Script"), category: this.categories.scripting }; + recordStyles[recordTypes.TimeStamp] = { title: WebInspector.UIString("Stamp"), category: this.categories.scripting }; + recordStyles[recordTypes.ResourceSendRequest] = { title: WebInspector.UIString("Send Request"), category: this.categories.loading }; + recordStyles[recordTypes.ResourceReceiveResponse] = { title: WebInspector.UIString("Receive Response"), category: this.categories.loading }; + recordStyles[recordTypes.ResourceFinish] = { title: WebInspector.UIString("Finish Loading"), category: this.categories.loading }; + recordStyles[recordTypes.FunctionCall] = { title: WebInspector.UIString("Function Call"), category: this.categories.scripting }; + recordStyles[recordTypes.ResourceReceivedData] = { title: WebInspector.UIString("Receive Data"), category: this.categories.loading }; + recordStyles[recordTypes.GCEvent] = { title: WebInspector.UIString("GC Event"), category: this.categories.scripting }; + recordStyles[recordTypes.MarkDOMContent] = { title: WebInspector.UIString("DOMContent event"), category: this.categories.scripting }; + recordStyles[recordTypes.MarkLoad] = { title: WebInspector.UIString("Load event"), category: this.categories.scripting }; + recordStyles[recordTypes.ScheduleResourceRequest] = { title: WebInspector.UIString("Schedule Request"), category: this.categories.loading }; + recordStyles[recordTypes.RegisterAnimationFrameCallback] = { title: WebInspector.UIString("Register Animation Callback"), category: this.categories.scripting }; + recordStyles[recordTypes.CancelAnimationFrameCallback] = { title: WebInspector.UIString("Cancel Animation Callback"), category: this.categories.scripting }; + recordStyles[recordTypes.FireAnimationFrameEvent] = { title: WebInspector.UIString("Animation Frame Event"), category: this.categories.scripting }; + this._recordStylesArray = recordStyles; + } + return this._recordStylesArray; + }, + + _createStatusbarButtons: function() + { + this.toggleTimelineButton = new WebInspector.StatusBarButton(WebInspector.UIString("Record"), "record-profile-status-bar-item"); + this.toggleTimelineButton.addEventListener("click", this._toggleTimelineButtonClicked, this); + + this.clearButton = new WebInspector.StatusBarButton(WebInspector.UIString("Clear"), "clear-status-bar-item"); + this.clearButton.addEventListener("click", this._clearPanel, this); + + this.toggleFilterButton = new WebInspector.StatusBarButton(this._hideShortRecordsTitleText, "timeline-filter-status-bar-item"); + this.toggleFilterButton.addEventListener("click", this._toggleFilterButtonClicked, this); + + this.garbageCollectButton = new WebInspector.StatusBarButton(WebInspector.UIString("Collect Garbage"), "garbage-collect-status-bar-item"); + this.garbageCollectButton.addEventListener("click", this._garbageCollectButtonClicked, this); + + this.recordsCounter = document.createElement("span"); + this.recordsCounter.className = "timeline-records-counter"; + }, + + _registerShortcuts: function() + { + var shortcut = WebInspector.KeyboardShortcut; + var modifiers = shortcut.Modifiers; + var section = WebInspector.shortcutsScreen.section(WebInspector.UIString("Timeline Panel")); + + this._shortcuts[shortcut.makeKey("e", modifiers.CtrlOrMeta)] = this._toggleTimelineButtonClicked.bind(this); + section.addKey(shortcut.shortcutToString("e", modifiers.CtrlOrMeta), WebInspector.UIString("Start/stop recording")); + + this._shortcuts[shortcut.makeKey("s", modifiers.CtrlOrMeta)] = this._saveToFile.bind(this); + section.addKey(shortcut.shortcutToString("s", modifiers.CtrlOrMeta), WebInspector.UIString("Save Timeline data\u2026")); + + this._shortcuts[shortcut.makeKey("o", modifiers.CtrlOrMeta)] = this._fileSelectorElement.click.bind(this._fileSelectorElement); + section.addKey(shortcut.shortcutToString("o", modifiers.CtrlOrMeta), WebInspector.UIString("Load Timeline data\u2026")); + }, + + _createFileSelector: function() + { + if (this._fileSelectorElement) + this.element.removeChild(this._fileSelectorElement); + + var fileSelectorElement = document.createElement("input"); + fileSelectorElement.type = "file"; + fileSelectorElement.style.zIndex = -1; + fileSelectorElement.style.position = "absolute"; + fileSelectorElement.onchange = this._loadFromFile.bind(this); + this.element.appendChild(fileSelectorElement); + this._fileSelectorElement = fileSelectorElement; + }, + + _contextMenu: function(event) + { + var contextMenu = new WebInspector.ContextMenu(); + contextMenu.appendItem(WebInspector.UIString("&Save Timeline data\u2026"), this._saveToFile.bind(this)); + contextMenu.appendItem(WebInspector.UIString("L&oad Timeline data\u2026"), this._fileSelectorElement.click.bind(this._fileSelectorElement)); + contextMenu.show(event); + }, + + _saveToFile: function() + { + this._model._saveToFile(); + }, + + _loadFromFile: function() + { + if (this.toggleTimelineButton.toggled) + WebInspector.timelineManager.stop(); + + this._clearPanel(); + + this._model._loadFromFile(this._fileSelectorElement.files[0]); + this._createFileSelector(); + }, + + _updateRecordsCounter: function() + { + this.recordsCounter.textContent = WebInspector.UIString("%d of %d captured records are visible", this._rootRecord._visibleRecordsCount, this._rootRecord._allRecordsCount); + }, + + _updateEventDividers: function() + { + this._timelineGrid.removeEventDividers(); + var clientWidth = this._graphRowsElement.offsetWidth - this._expandOffset; + var dividers = []; + for (var i = 0; i < this._timeStampRecords.length; ++i) { + var record = this._timeStampRecords[i]; + var positions = this._calculator.computeBarGraphWindowPosition(record, clientWidth); + var dividerPosition = Math.round(positions.left); + if (dividerPosition < 0 || dividerPosition >= clientWidth || dividers[dividerPosition]) + continue; + var divider = this._createEventDivider(record); + divider.style.left = (dividerPosition + this._expandOffset) + "px"; + dividers[dividerPosition] = divider; + } + this._timelineGrid.addEventDividers(dividers); + this._overviewPane.updateEventDividers(this._timeStampRecords, this._createEventDivider.bind(this)); + }, + + _createEventDivider: function(record) + { + var eventDivider = document.createElement("div"); + eventDivider.className = "resources-event-divider"; + var recordTypes = WebInspector.TimelineAgent.RecordType; + + var eventDividerPadding = document.createElement("div"); + eventDividerPadding.className = "resources-event-divider-padding"; + eventDividerPadding.title = record.title; + + if (record.type === recordTypes.MarkDOMContent) + eventDivider.className += " resources-blue-divider"; + else if (record.type === recordTypes.MarkLoad) + eventDivider.className += " resources-red-divider"; + else if (record.type === recordTypes.TimeStamp) { + eventDivider.className += " resources-orange-divider"; + eventDividerPadding.title = record.data["message"]; + } + eventDividerPadding.appendChild(eventDivider); + return eventDividerPadding; + }, + + _timelinesOverviewItemSelected: function(event) + { + this._overviewPane.showTimelines(); + }, + + _memoryOverviewItemSelected: function(event) + { + this._overviewPane.showMemoryGraph(this._rootRecord.children); + }, + + _toggleTimelineButtonClicked: function() + { + if (this.toggleTimelineButton.toggled) + WebInspector.timelineManager.stop(); + else { + this._clearPanel(); + WebInspector.timelineManager.start(30); + WebInspector.userMetrics.TimelineStarted.record(); + } + this.toggleTimelineButton.toggled = !this.toggleTimelineButton.toggled; + }, + + _toggleFilterButtonClicked: function() + { + this.toggleFilterButton.toggled = !this.toggleFilterButton.toggled; + this._calculator._showShortEvents = this.toggleFilterButton.toggled; + this.toggleFilterButton.element.title = this._calculator._showShortEvents ? this._hideShortRecordsTitleText : this._showShortRecordsTitleText; + this._scheduleRefresh(true); + }, + + _garbageCollectButtonClicked: function() + { + ProfilerAgent.collectGarbage(); + }, + + _onTimelineEventRecorded: function(event) + { + if (this.toggleTimelineButton.toggled) + this._addRecordToTimeline(event.data); + }, + + _addRecordToTimeline: function(record) + { + this._model._addRecord(record); + this._innerAddRecordToTimeline(record, this._rootRecord); + this._scheduleRefresh(false); + }, + + _findParentRecord: function(record) + { + var recordTypes = WebInspector.TimelineAgent.RecordType; + var parentRecord; + if (record.type === recordTypes.ResourceReceiveResponse || + record.type === recordTypes.ResourceFinish || + record.type === recordTypes.ResourceReceivedData) + parentRecord = this._sendRequestRecords[record.data["requestId"]]; + else if (record.type === recordTypes.TimerFire) + parentRecord = this._timerRecords[record.data["timerId"]]; + else if (record.type === recordTypes.ResourceSendRequest) + parentRecord = this._scheduledResourceRequests[record.data["url"]]; + return parentRecord; + }, + + _innerAddRecordToTimeline: function(record, parentRecord) + { + var connectedToOldRecord = false; + var recordTypes = WebInspector.TimelineAgent.RecordType; + + if (record.type === recordTypes.RegisterAnimationFrameCallback) { + this._registeredAnimationCallbackRecords[record.data["id"]] = record; + return; + } + + if (record.type === recordTypes.MarkDOMContent || record.type === recordTypes.MarkLoad) + parentRecord = null; // No bar entry for load events. + else if (parentRecord === this._rootRecord || + record.type === recordTypes.ResourceReceiveResponse || + record.type === recordTypes.ResourceFinish || + record.type === recordTypes.ResourceReceivedData) { + var newParentRecord = this._findParentRecord(record); + if (newParentRecord) { + parentRecord = newParentRecord; + connectedToOldRecord = true; + } + } + + var children = record.children; + var scriptDetails; + if (record.data && record.data["scriptName"]) { + scriptDetails = { + scriptName: record.data["scriptName"], + scriptLine: record.data["scriptLine"] + } + }; + + if ((record.type === recordTypes.TimerFire || record.type === recordTypes.FireAnimationFrameEvent) && children && children.length) { + var childRecord = children[0]; + if (childRecord.type === recordTypes.FunctionCall) { + scriptDetails = { + scriptName: childRecord.data["scriptName"], + scriptLine: childRecord.data["scriptLine"] + }; + children = childRecord.children.concat(children.slice(1)); + } + } + + var formattedRecord = new WebInspector.TimelinePanel.FormattedRecord(record, parentRecord, this, scriptDetails); + + if (record.type === recordTypes.MarkDOMContent || record.type === recordTypes.MarkLoad) { + this._timeStampRecords.push(formattedRecord); + return; + } + + ++this._rootRecord._allRecordsCount; + formattedRecord.collapsed = (parentRecord === this._rootRecord); + + var childrenCount = children ? children.length : 0; + for (var i = 0; i < childrenCount; ++i) + this._innerAddRecordToTimeline(children[i], formattedRecord); + + formattedRecord._calculateAggregatedStats(this.categories); + + if (connectedToOldRecord) { + record = formattedRecord; + do { + var parent = record.parent; + parent._cpuTime += formattedRecord._cpuTime; + if (parent._lastChildEndTime < record._lastChildEndTime) + parent._lastChildEndTime = record._lastChildEndTime; + for (var category in formattedRecord._aggregatedStats) + parent._aggregatedStats[category] += formattedRecord._aggregatedStats[category]; + record = parent; + } while (record.parent); + } else + if (parentRecord !== this._rootRecord) + parentRecord._selfTime -= formattedRecord.endTime - formattedRecord.startTime; + + // Keep bar entry for mark timeline since nesting might be interesting to the user. + if (record.type === recordTypes.TimeStamp) + this._timeStampRecords.push(formattedRecord); + }, + + sidebarResized: function(event) + { + var width = event.data; + this._sidebarBackgroundElement.style.width = width + "px"; + this._topPaneSidebarElement.style.width = width + "px"; + this._scheduleRefresh(false); + this._overviewPane.sidebarResized(width); + }, + + onResize: function() + { + this._closeRecordDetails(); + this._scheduleRefresh(false); + }, + + _createRootRecord: function() + { + var rootRecord = {}; + rootRecord.children = []; + rootRecord._visibleRecordsCount = 0; + rootRecord._allRecordsCount = 0; + rootRecord._aggregatedStats = {}; + return rootRecord; + }, + + _clearPanel: function() + { + this._timeStampRecords = []; + this._sendRequestRecords = {}; + this._scheduledResourceRequests = {}; + this._timerRecords = {}; + this._registeredAnimationCallbackRecords = {}; + this._rootRecord = this._createRootRecord(); + this._boundariesAreValid = false; + this._overviewPane.reset(); + this._adjustScrollPosition(0); + this._refresh(); + this._closeRecordDetails(); + this._model._reset(); + this._linkifier.reset(); + }, + + elementsToRestoreScrollPositionsFor: function() + { + return [this._containerElement]; + }, + + wasShown: function() + { + WebInspector.Panel.prototype.wasShown.call(this); + this._refresh(); + WebInspector.drawer.currentPanelCounters = this.recordsCounter; + }, + + willHide: function() + { + this._closeRecordDetails(); + WebInspector.drawer.currentPanelCounters = null; + WebInspector.Panel.prototype.willHide.call(this); + }, + + _onScroll: function(event) + { + this._closeRecordDetails(); + var scrollTop = this._containerElement.scrollTop; + var dividersTop = Math.max(0, scrollTop); + this._timelineGrid.setScrollAndDividerTop(scrollTop, dividersTop); + this._scheduleRefresh(true); + }, + + _windowChanged: function() + { + this._closeRecordDetails(); + this._scheduleRefresh(false); + }, + + _scheduleRefresh: function(preserveBoundaries) + { + this._closeRecordDetails(); + this._boundariesAreValid &= preserveBoundaries; + + if (!this.isShowing()) + return; + + if (preserveBoundaries) + this._refresh(); + else + if (!this._refreshTimeout) + this._refreshTimeout = setTimeout(this._refresh.bind(this), 100); + }, + + _refresh: function() + { + if (this._refreshTimeout) { + clearTimeout(this._refreshTimeout); + delete this._refreshTimeout; + } + + this._overviewPane.update(this._rootRecord.children, this._calculator._showShortEvents); + this._refreshRecords(!this._boundariesAreValid); + this._updateRecordsCounter(); + if(!this._boundariesAreValid) + this._updateEventDividers(); + this._boundariesAreValid = true; + }, + + _updateBoundaries: function() + { + this._calculator.reset(); + this._calculator.windowLeft = this._overviewPane.windowLeft; + this._calculator.windowRight = this._overviewPane.windowRight; + + for (var i = 0; i < this._rootRecord.children.length; ++i) + this._calculator.updateBoundaries(this._rootRecord.children[i]); + + this._calculator.calculateWindow(); + }, + + /** + * @param {boolean=} parentIsCollapsed + */ + _addToRecordsWindow: function(record, recordsWindow, parentIsCollapsed) + { + if (!this._calculator._showShortEvents && !record.isLong()) + return; + var percentages = this._calculator.computeBarGraphPercentages(record); + if (percentages.start < 100 && percentages.endWithChildren >= 0 && !record.category.hidden) { + ++this._rootRecord._visibleRecordsCount; + ++record.parent._invisibleChildrenCount; + if (!parentIsCollapsed) + recordsWindow.push(record); + } + + var index = recordsWindow.length; + record._invisibleChildrenCount = 0; + for (var i = 0; i < record.children.length; ++i) + this._addToRecordsWindow(record.children[i], recordsWindow, parentIsCollapsed || record.collapsed); + record._visibleChildrenCount = recordsWindow.length - index; + }, + + _filterRecords: function() + { + var recordsInWindow = []; + this._rootRecord._visibleRecordsCount = 0; + for (var i = 0; i < this._rootRecord.children.length; ++i) + this._addToRecordsWindow(this._rootRecord.children[i], recordsInWindow); + return recordsInWindow; + }, + + _refreshRecords: function(updateBoundaries) + { + if (updateBoundaries) + this._updateBoundaries(); + + var recordsInWindow = this._filterRecords(); + + // Calculate the visible area. + this._scrollTop = this._containerElement.scrollTop; + var visibleTop = this._scrollTop; + var visibleBottom = visibleTop + this._containerElement.clientHeight; + + const rowHeight = WebInspector.TimelinePanel.rowHeight; + + // Convert visible area to visible indexes. Always include top-level record for a visible nested record. + var startIndex = Math.max(0, Math.min(Math.floor(visibleTop / rowHeight) - 1, recordsInWindow.length - 1)); + var endIndex = Math.min(recordsInWindow.length, Math.ceil(visibleBottom / rowHeight)); + + // Resize gaps first. + const top = (startIndex * rowHeight) + "px"; + this._topGapElement.style.height = top; + this.sidebarElement.style.top = top; + this.splitView.sidebarResizerElement.style.top = top; + this._bottomGapElement.style.height = (recordsInWindow.length - endIndex) * rowHeight + "px"; + + // Update visible rows. + var listRowElement = this._sidebarListElement.firstChild; + var width = this._graphRowsElement.offsetWidth; + this._itemsGraphsElement.removeChild(this._graphRowsElement); + var graphRowElement = this._graphRowsElement.firstChild; + var scheduleRefreshCallback = this._scheduleRefresh.bind(this, true); + this._itemsGraphsElement.removeChild(this._expandElements); + this._expandElements.removeChildren(); + + for (var i = 0; i < endIndex; ++i) { + var record = recordsInWindow[i]; + var isEven = !(i % 2); + + if (i < startIndex) { + var lastChildIndex = i + record._visibleChildrenCount; + if (lastChildIndex >= startIndex && lastChildIndex < endIndex) { + var expandElement = new WebInspector.TimelineExpandableElement(this._expandElements); + expandElement._update(record, i, this._calculator.computeBarGraphWindowPosition(record, width - this._expandOffset)); + } + } else { + if (!listRowElement) { + listRowElement = new WebInspector.TimelineRecordListRow().element; + this._sidebarListElement.appendChild(listRowElement); + } + if (!graphRowElement) { + graphRowElement = new WebInspector.TimelineRecordGraphRow(this._itemsGraphsElement, scheduleRefreshCallback).element; + this._graphRowsElement.appendChild(graphRowElement); + } + + listRowElement.row.update(record, isEven, this._calculator, visibleTop); + graphRowElement.row.update(record, isEven, this._calculator, width, this._expandOffset, i); + + listRowElement = listRowElement.nextSibling; + graphRowElement = graphRowElement.nextSibling; + } + } + + // Remove extra rows. + while (listRowElement) { + var nextElement = listRowElement.nextSibling; + listRowElement.row.dispose(); + listRowElement = nextElement; + } + while (graphRowElement) { + var nextElement = graphRowElement.nextSibling; + graphRowElement.row.dispose(); + graphRowElement = nextElement; + } + + this._itemsGraphsElement.insertBefore(this._graphRowsElement, this._bottomGapElement); + this._itemsGraphsElement.appendChild(this._expandElements); + this.splitView.sidebarResizerElement.style.height = this.sidebarElement.clientHeight + "px"; + // Reserve some room for expand / collapse controls to the left for records that start at 0ms. + var timelinePaddingLeft = this._calculator.windowLeft === 0 ? this._expandOffset : 0; + if (updateBoundaries) + this._timelineGrid.updateDividers(true, this._calculator, timelinePaddingLeft); + this._adjustScrollPosition((recordsInWindow.length + 1) * rowHeight); + }, + + _adjustScrollPosition: function(totalHeight) + { + // Prevent the container from being scrolled off the end. + if ((this._containerElement.scrollTop + this._containerElement.offsetHeight) > totalHeight + 1) + this._containerElement.scrollTop = (totalHeight - this._containerElement.offsetHeight); + }, + + _getPopoverAnchor: function(element) + { + return element.enclosingNodeOrSelfWithClass("timeline-graph-bar") || element.enclosingNodeOrSelfWithClass("timeline-tree-item"); + }, + + _mouseOut: function(e) + { + this._hideRectHighlight(); + }, + + _mouseMove: function(e) + { + var anchor = this._getPopoverAnchor(e.target); + + if (anchor && anchor.row._record.type === "Paint") + this._highlightRect(anchor.row._record); + else + this._hideRectHighlight(); + }, + + _highlightRect: function(record) + { + if (this._highlightedRect === record.data) + return; + this._highlightedRect = record.data; + DOMAgent.highlightRect(this._highlightedRect.x, this._highlightedRect.y, this._highlightedRect.width, this._highlightedRect.height, WebInspector.Color.PageHighlight.Content.toProtocolRGBA(), WebInspector.Color.PageHighlight.ContentOutline.toProtocolRGBA()); + }, + + _hideRectHighlight: function() + { + if (this._highlightedRect) { + delete this._highlightedRect; + DOMAgent.hideHighlight(); + } + }, + + _showPopover: function(anchor, popover) + { + var record = anchor.row._record; + popover.show(record._generatePopupContent(this._calculator, this.categories), anchor); + }, + + _closeRecordDetails: function() + { + this._popoverHelper.hidePopover(); + } +} + +WebInspector.TimelinePanel.prototype.__proto__ = WebInspector.Panel.prototype; + +/** + * @constructor + */ +WebInspector.TimelineCategory = function(name, title, color) +{ + this.name = name; + this.title = title; + this.color = color; +} + +/** + * @constructor + */ +WebInspector.TimelineCalculator = function() +{ + this.reset(); + this.windowLeft = 0.0; + this.windowRight = 1.0; +} + +WebInspector.TimelineCalculator.prototype = { + computeBarGraphPercentages: function(record) + { + var start = (record.startTime - this.minimumBoundary) / this.boundarySpan * 100; + var end = (record.startTime + record._selfTime - this.minimumBoundary) / this.boundarySpan * 100; + var endWithChildren = (record._lastChildEndTime - this.minimumBoundary) / this.boundarySpan * 100; + var cpuWidth = record._cpuTime / this.boundarySpan * 100; + return {start: start, end: end, endWithChildren: endWithChildren, cpuWidth: cpuWidth}; + }, + + computeBarGraphWindowPosition: function(record, clientWidth) + { + const minWidth = 5; + const borderWidth = 4; + var workingArea = clientWidth - minWidth - borderWidth; + var percentages = this.computeBarGraphPercentages(record); + var left = percentages.start / 100 * workingArea; + var width = (percentages.end - percentages.start) / 100 * workingArea + minWidth; + var widthWithChildren = (percentages.endWithChildren - percentages.start) / 100 * workingArea; + var cpuWidth = percentages.cpuWidth / 100 * workingArea + minWidth; + if (percentages.endWithChildren > percentages.end) + widthWithChildren += borderWidth + minWidth; + return {left: left, width: width, widthWithChildren: widthWithChildren, cpuWidth: cpuWidth}; + }, + + calculateWindow: function() + { + this.minimumBoundary = this._absoluteMinimumBoundary + this.windowLeft * (this._absoluteMaximumBoundary - this._absoluteMinimumBoundary); + this.maximumBoundary = this._absoluteMinimumBoundary + this.windowRight * (this._absoluteMaximumBoundary - this._absoluteMinimumBoundary); + this.boundarySpan = this.maximumBoundary - this.minimumBoundary; + }, + + reset: function() + { + this._absoluteMinimumBoundary = -1; + this._absoluteMaximumBoundary = -1; + }, + + updateBoundaries: function(record) + { + var lowerBound = record.startTime; + if (this._absoluteMinimumBoundary === -1 || lowerBound < this._absoluteMinimumBoundary) + this._absoluteMinimumBoundary = lowerBound; + + const minimumTimeFrame = 0.1; + const minimumDeltaForZeroSizeEvents = 0.01; + var upperBound = Math.max(record._lastChildEndTime + minimumDeltaForZeroSizeEvents, lowerBound + minimumTimeFrame); + if (this._absoluteMaximumBoundary === -1 || upperBound > this._absoluteMaximumBoundary) + this._absoluteMaximumBoundary = upperBound; + }, + + formatValue: function(value) + { + return Number.secondsToString(value + this.minimumBoundary - this._absoluteMinimumBoundary); + } +} + +/** + * @constructor + */ +WebInspector.TimelineRecordListRow = function() +{ + this.element = document.createElement("div"); + this.element.row = this; + this.element.style.cursor = "pointer"; + var iconElement = document.createElement("span"); + iconElement.className = "timeline-tree-icon"; + this.element.appendChild(iconElement); + + this._typeElement = document.createElement("span"); + this._typeElement.className = "type"; + this.element.appendChild(this._typeElement); + + var separatorElement = document.createElement("span"); + separatorElement.className = "separator"; + separatorElement.textContent = " "; + + this._dataElement = document.createElement("span"); + this._dataElement.className = "data dimmed"; + + this.element.appendChild(separatorElement); + this.element.appendChild(this._dataElement); +} + +WebInspector.TimelineRecordListRow.prototype = { + update: function(record, isEven, calculator, offset) + { + this._record = record; + this._calculator = calculator; + this._offset = offset; + + this.element.className = "timeline-tree-item timeline-category-" + record.category.name + (isEven ? " even" : ""); + this._typeElement.textContent = record.title; + + if (this._dataElement.firstChild) + this._dataElement.removeChildren(); + if (record.details) { + var detailsContainer = document.createElement("span"); + if (typeof record.details === "object") { + detailsContainer.appendChild(document.createTextNode("(")); + detailsContainer.appendChild(record.details); + detailsContainer.appendChild(document.createTextNode(")")); + } else + detailsContainer.textContent = "(" + record.details + ")"; + this._dataElement.appendChild(detailsContainer); + } + }, + + dispose: function() + { + this.element.parentElement.removeChild(this.element); + } +} + +/** + * @constructor + */ +WebInspector.TimelineRecordGraphRow = function(graphContainer, scheduleRefresh) +{ + this.element = document.createElement("div"); + this.element.row = this; + + this._barAreaElement = document.createElement("div"); + this._barAreaElement.className = "timeline-graph-bar-area"; + this.element.appendChild(this._barAreaElement); + + this._barWithChildrenElement = document.createElement("div"); + this._barWithChildrenElement.className = "timeline-graph-bar with-children"; + this._barWithChildrenElement.row = this; + this._barAreaElement.appendChild(this._barWithChildrenElement); + + this._barCpuElement = document.createElement("div"); + this._barCpuElement.className = "timeline-graph-bar cpu" + this._barCpuElement.row = this; + this._barAreaElement.appendChild(this._barCpuElement); + + this._barElement = document.createElement("div"); + this._barElement.className = "timeline-graph-bar"; + this._barElement.row = this; + this._barAreaElement.appendChild(this._barElement); + + this._expandElement = new WebInspector.TimelineExpandableElement(graphContainer); + this._expandElement._element.addEventListener("click", this._onClick.bind(this)); + + this._scheduleRefresh = scheduleRefresh; +} + +WebInspector.TimelineRecordGraphRow.prototype = { + update: function(record, isEven, calculator, clientWidth, expandOffset, index) + { + this._record = record; + this.element.className = "timeline-graph-side timeline-category-" + record.category.name + (isEven ? " even" : ""); + var barPosition = calculator.computeBarGraphWindowPosition(record, clientWidth - expandOffset); + this._barWithChildrenElement.style.left = barPosition.left + expandOffset + "px"; + this._barWithChildrenElement.style.width = barPosition.widthWithChildren + "px"; + this._barElement.style.left = barPosition.left + expandOffset + "px"; + this._barElement.style.width = barPosition.width + "px"; + this._barCpuElement.style.left = barPosition.left + expandOffset + "px"; + this._barCpuElement.style.width = barPosition.cpuWidth + "px"; + this._expandElement._update(record, index, barPosition); + }, + + _onClick: function(event) + { + this._record.collapsed = !this._record.collapsed; + this._scheduleRefresh(false); + }, + + dispose: function() + { + this.element.parentElement.removeChild(this.element); + this._expandElement._dispose(); + } +} + +/** + * @constructor + */ +WebInspector.TimelinePanel.FormattedRecord = function(record, parentRecord, panel, scriptDetails) +{ + this._panel = panel; + var recordTypes = WebInspector.TimelineAgent.RecordType; + var style = panel._recordStyles[record.type]; + this.parent = parentRecord; + if (parentRecord) + parentRecord.children.push(this); + this.category = style.category; + this.title = style.title; + this.startTime = record.startTime / 1000; + this.data = record.data; + this.type = record.type; + this.endTime = (typeof record.endTime !== "undefined") ? record.endTime / 1000 : this.startTime; + this._selfTime = this.endTime - this.startTime; + this._lastChildEndTime = this.endTime; + if (record.stackTrace && record.stackTrace.length) + this.stackTrace = record.stackTrace; + this.totalHeapSize = record.totalHeapSize; + this.usedHeapSize = record.usedHeapSize; + if (record.data && record.data["url"]) + this.url = record.data["url"]; + if (scriptDetails) { + this.scriptName = scriptDetails.scriptName; + this.scriptLine = scriptDetails.scriptLine; + } + // Make resource receive record last since request was sent; make finish record last since response received. + if (record.type === recordTypes.ResourceSendRequest) { + panel._sendRequestRecords[record.data["requestId"]] = this; + } else if (record.type === recordTypes.ScheduleResourceRequest) { + panel._scheduledResourceRequests[record.data["url"]] = this; + } else if (record.type === recordTypes.ResourceReceiveResponse) { + var sendRequestRecord = panel._sendRequestRecords[record.data["requestId"]]; + if (sendRequestRecord) { // False if we started instrumentation in the middle of request. + this.url = sendRequestRecord.url; + // Now that we have resource in the collection, recalculate details in order to display short url. + sendRequestRecord._refreshDetails(); + if (sendRequestRecord.parent !== panel._rootRecord && sendRequestRecord.parent.type === recordTypes.ScheduleResourceRequest) + sendRequestRecord.parent._refreshDetails(); + } + } else if (record.type === recordTypes.ResourceReceivedData || record.type === recordTypes.ResourceFinish) { + var sendRequestRecord = panel._sendRequestRecords[record.data["requestId"]]; + if (sendRequestRecord) // False for main resource. + this.url = sendRequestRecord.url; + } else if (record.type === recordTypes.TimerInstall) { + this.timeout = record.data["timeout"]; + this.singleShot = record.data["singleShot"]; + panel._timerRecords[record.data["timerId"]] = this; + } else if (record.type === recordTypes.TimerFire) { + var timerInstalledRecord = panel._timerRecords[record.data["timerId"]]; + if (timerInstalledRecord) { + this.callSiteStackTrace = timerInstalledRecord.stackTrace; + this.timeout = timerInstalledRecord.timeout; + this.singleShot = timerInstalledRecord.singleShot; + } + } else if (record.type === recordTypes.FireAnimationFrameEvent) { + var registerCallbackRecord = panel._registeredAnimationCallbackRecords[record.data["id"]]; + if (registerCallbackRecord) + this.callSiteStackTrace = registerCallbackRecord.stackTrace; + } + this._refreshDetails(); +} + +WebInspector.TimelinePanel.FormattedRecord.prototype = { + isLong: function() + { + return (this._lastChildEndTime - this.startTime) > WebInspector.TimelinePanel.shortRecordThreshold; + }, + + get children() + { + if (!this._children) + this._children = []; + return this._children; + }, + + _generateAggregatedInfo: function() + { + var cell = document.createElement("span"); + cell.className = "timeline-aggregated-info"; + for (var index in this._aggregatedStats) { + var label = document.createElement("div"); + label.className = "timeline-aggregated-category timeline-" + index; + cell.appendChild(label); + var text = document.createElement("span"); + text.textContent = Number.secondsToString(this._aggregatedStats[index] + 0.0001); + cell.appendChild(text); + } + return cell; + }, + + _generatePopupContent: function(calculator, categories) + { + var contentHelper = new WebInspector.TimelinePanel.PopupContentHelper(this.title, this._panel); + + if (this._children && this._children.length) { + contentHelper._appendTextRow(WebInspector.UIString("Self Time"), Number.secondsToString(this._selfTime + 0.0001)); + contentHelper._appendElementRow(WebInspector.UIString("Aggregated Time"), this._generateAggregatedInfo()); + } + var text = WebInspector.UIString("%s (at %s)", Number.secondsToString(this._lastChildEndTime - this.startTime), + calculator.formatValue(this.startTime - calculator.minimumBoundary)); + contentHelper._appendTextRow(WebInspector.UIString("Duration"), text); + + const recordTypes = WebInspector.TimelineAgent.RecordType; + + switch (this.type) { + case recordTypes.GCEvent: + contentHelper._appendTextRow(WebInspector.UIString("Collected"), Number.bytesToString(this.data["usedHeapSizeDelta"])); + break; + case recordTypes.TimerInstall: + case recordTypes.TimerFire: + case recordTypes.TimerRemove: + contentHelper._appendTextRow(WebInspector.UIString("Timer ID"), this.data["timerId"]); + if (typeof this.timeout === "number") { + contentHelper._appendTextRow(WebInspector.UIString("Timeout"), Number.secondsToString(this.timeout / 1000)); + contentHelper._appendTextRow(WebInspector.UIString("Repeats"), !this.singleShot); + } + break; + case recordTypes.FireAnimationFrameEvent: + contentHelper._appendTextRow(WebInspector.UIString("Callback ID"), this.data["id"]); + break; + case recordTypes.FunctionCall: + contentHelper._appendLinkRow(WebInspector.UIString("Location"), this.scriptName, this.scriptLine); + break; + case recordTypes.ScheduleResourceRequest: + case recordTypes.ResourceSendRequest: + case recordTypes.ResourceReceiveResponse: + case recordTypes.ResourceReceivedData: + case recordTypes.ResourceFinish: + contentHelper._appendLinkRow(WebInspector.UIString("Resource"), this.url); + if (this.data["requestMethod"]) + contentHelper._appendTextRow(WebInspector.UIString("Request Method"), this.data["requestMethod"]); + if (typeof this.data["statusCode"] === "number") + contentHelper._appendTextRow(WebInspector.UIString("Status Code"), this.data["statusCode"]); + if (this.data["mimeType"]) + contentHelper._appendTextRow(WebInspector.UIString("MIME Type"), this.data["mimeType"]); + break; + case recordTypes.EvaluateScript: + if (this.data && this.url) + contentHelper._appendLinkRow(WebInspector.UIString("Script"), this.url, this.data["lineNumber"]); + break; + case recordTypes.Paint: + contentHelper._appendTextRow(WebInspector.UIString("Location"), WebInspector.UIString("(%d, %d)", this.data["x"], this.data["y"])); + contentHelper._appendTextRow(WebInspector.UIString("Dimensions"), WebInspector.UIString("%d × %d", this.data["width"], this.data["height"])); + case recordTypes.RecalculateStyles: // We don't want to see default details. + break; + default: + if (this.details) + contentHelper._appendTextRow(WebInspector.UIString("Details"), this.details); + break; + } + + if (this.scriptName && this.type !== recordTypes.FunctionCall) + contentHelper._appendLinkRow(WebInspector.UIString("Function Call"), this.scriptName, this.scriptLine); + + if (this.usedHeapSize) + contentHelper._appendTextRow(WebInspector.UIString("Used Heap Size"), WebInspector.UIString("%s of %s", Number.bytesToString(this.usedHeapSize), Number.bytesToString(this.totalHeapSize))); + + if (this.callSiteStackTrace && this.callSiteStackTrace.length) + contentHelper._appendStackTrace(WebInspector.UIString("Call Site stack"), this.callSiteStackTrace); + + if (this.stackTrace) + contentHelper._appendStackTrace(WebInspector.UIString("Call Stack"), this.stackTrace); + + return contentHelper._contentTable; + }, + + _refreshDetails: function() + { + this.details = this._getRecordDetails(); + }, + + _getRecordDetails: function() + { + switch (this.type) { + case WebInspector.TimelineAgent.RecordType.GCEvent: + return WebInspector.UIString("%s collected", Number.bytesToString(this.data["usedHeapSizeDelta"])); + case WebInspector.TimelineAgent.RecordType.TimerFire: + return this.scriptName ? this._panel._linkifyLocation(this.scriptName, this.scriptLine, 0) : this.data["timerId"]; + case WebInspector.TimelineAgent.RecordType.FunctionCall: + return this.scriptName ? this._panel._linkifyLocation(this.scriptName, this.scriptLine, 0) : null; + case WebInspector.TimelineAgent.RecordType.FireAnimationFrameEvent: + return this.scriptName ? this._panel._linkifyLocation(this.scriptName, this.scriptLine, 0) : this.data["id"]; + case WebInspector.TimelineAgent.RecordType.EventDispatch: + return this.data ? this.data["type"] : null; + case WebInspector.TimelineAgent.RecordType.Paint: + return this.data["width"] + "\u2009\u00d7\u2009" + this.data["height"]; + case WebInspector.TimelineAgent.RecordType.TimerInstall: + case WebInspector.TimelineAgent.RecordType.TimerRemove: + return this.stackTrace ? this._panel._linkifyCallFrame(this.stackTrace[0]) : this.data["timerId"]; + case WebInspector.TimelineAgent.RecordType.RegisterAnimationFrameCallback: + case WebInspector.TimelineAgent.RecordType.CancelAnimationFrameCallback: + return this.stackTrace ? this._panel._linkifyCallFrame(this.stackTrace[0]) : this.data["id"]; + case WebInspector.TimelineAgent.RecordType.ParseHTML: + case WebInspector.TimelineAgent.RecordType.RecalculateStyles: + return this.stackTrace ? this._panel._linkifyCallFrame(this.stackTrace[0]) : null; + case WebInspector.TimelineAgent.RecordType.EvaluateScript: + return this.url ? this._panel._linkifyLocation(this.url, this.data["lineNumber"], 0) : null; + case WebInspector.TimelineAgent.RecordType.XHRReadyStateChange: + case WebInspector.TimelineAgent.RecordType.XHRLoad: + case WebInspector.TimelineAgent.RecordType.ScheduleResourceRequest: + case WebInspector.TimelineAgent.RecordType.ResourceSendRequest: + case WebInspector.TimelineAgent.RecordType.ResourceReceivedData: + case WebInspector.TimelineAgent.RecordType.ResourceReceiveResponse: + case WebInspector.TimelineAgent.RecordType.ResourceFinish: + return WebInspector.displayNameForURL(this.url); + case WebInspector.TimelineAgent.RecordType.TimeStamp: + return this.data["message"]; + default: + return null; + } + }, + + _calculateAggregatedStats: function(categories) + { + this._aggregatedStats = {}; + for (var category in categories) + this._aggregatedStats[category] = 0; + this._cpuTime = this._selfTime; + + if (this._children) { + for (var index = this._children.length; index; --index) { + var child = this._children[index - 1]; + this._aggregatedStats[child.category.name] += child._selfTime; + for (var category in categories) + this._aggregatedStats[category] += child._aggregatedStats[category]; + } + for (var category in this._aggregatedStats) + this._cpuTime += this._aggregatedStats[category]; + } + } +} + +/** + * @constructor + */ +WebInspector.TimelinePanel.PopupContentHelper = function(title, panel) +{ + this._panel = panel; + this._contentTable = document.createElement("table");; + var titleCell = this._createCell(WebInspector.UIString("%s - Details", title), "timeline-details-title"); + titleCell.colSpan = 2; + var titleRow = document.createElement("tr"); + titleRow.appendChild(titleCell); + this._contentTable.appendChild(titleRow); +} + +WebInspector.TimelinePanel.PopupContentHelper.prototype = { + /** + * @param {string=} styleName + */ + _createCell: function(content, styleName) + { + var text = document.createElement("label"); + text.appendChild(document.createTextNode(content)); + var cell = document.createElement("td"); + cell.className = "timeline-details"; + if (styleName) + cell.className += " " + styleName; + cell.textContent = content; + return cell; + }, + + _appendTextRow: function(title, content) + { + var row = document.createElement("tr"); + row.appendChild(this._createCell(title, "timeline-details-row-title")); + row.appendChild(this._createCell(content, "timeline-details-row-data")); + this._contentTable.appendChild(row); + }, + + /** + * @param {string=} titleStyle + */ + _appendElementRow: function(title, content, titleStyle) + { + var row = document.createElement("tr"); + var titleCell = this._createCell(title, "timeline-details-row-title"); + if (titleStyle) + titleCell.addStyleClass(titleStyle); + row.appendChild(titleCell); + var cell = document.createElement("td"); + cell.className = "timeline-details"; + cell.appendChild(content); + row.appendChild(cell); + this._contentTable.appendChild(row); + }, + + /** + * @param {number=} scriptLine + */ + _appendLinkRow: function(title, scriptName, scriptLine) + { + var link = this._panel._linkifyLocation(scriptName, scriptLine, 0, "timeline-details"); + this._appendElementRow(title, link); + }, + + _appendStackTrace: function(title, stackTrace) + { + this._appendTextRow("", ""); + var framesTable = document.createElement("table"); + for (var i = 0; i < stackTrace.length; ++i) { + var stackFrame = stackTrace[i]; + var row = document.createElement("tr"); + row.className = "timeline-details"; + row.appendChild(this._createCell(stackFrame.functionName ? stackFrame.functionName : WebInspector.UIString("(anonymous function)"), "timeline-function-name")); + row.appendChild(this._createCell(" @ ")); + var linkCell = document.createElement("td"); + var urlElement = this._panel._linkifyCallFrame(stackFrame); + linkCell.appendChild(urlElement); + row.appendChild(linkCell); + framesTable.appendChild(row); + } + this._appendElementRow(title, framesTable, "timeline-stacktrace-title"); + } +} + +/** + * @constructor + */ +WebInspector.TimelineExpandableElement = function(container) +{ + this._element = document.createElement("div"); + this._element.className = "timeline-expandable"; + + var leftBorder = document.createElement("div"); + leftBorder.className = "timeline-expandable-left"; + this._element.appendChild(leftBorder); + + container.appendChild(this._element); +} + +WebInspector.TimelineExpandableElement.prototype = { + _update: function(record, index, barPosition) + { + const rowHeight = WebInspector.TimelinePanel.rowHeight; + if (record._visibleChildrenCount || record._invisibleChildrenCount) { + this._element.style.top = index * rowHeight + "px"; + this._element.style.left = barPosition.left + "px"; + this._element.style.width = Math.max(12, barPosition.width + 25) + "px"; + if (!record.collapsed) { + this._element.style.height = (record._visibleChildrenCount + 1) * rowHeight + "px"; + this._element.addStyleClass("timeline-expandable-expanded"); + this._element.removeStyleClass("timeline-expandable-collapsed"); + } else { + this._element.style.height = rowHeight + "px"; + this._element.addStyleClass("timeline-expandable-collapsed"); + this._element.removeStyleClass("timeline-expandable-expanded"); + } + this._element.removeStyleClass("hidden"); + } else + this._element.addStyleClass("hidden"); + }, + + _dispose: function() + { + this._element.parentElement.removeChild(this._element); + } +} + +/** + * @constructor + */ +WebInspector.TimelineModel = function(timelinePanel) +{ + this._panel = timelinePanel; + this._records = []; +} + +WebInspector.TimelineModel.prototype = { + _addRecord: function(record) + { + this._records.push(record); + }, + + _loadNextChunk: function(data, index) + { + for (var i = 0; i < 20 && index < data.length; ++i, ++index) + this._panel._addRecordToTimeline(data[index]); + + if (index !== data.length) + setTimeout(this._loadNextChunk.bind(this, data, index), 0); + }, + + _loadFromFile: function(file) + { + function onLoad(e) + { + var data = JSON.parse(e.target.result); + var version = data[0]; + this._loadNextChunk(data, 1); + } + + function onError(e) + { + switch(e.target.error.code) { + case e.target.error.NOT_FOUND_ERR: + WebInspector.log(WebInspector.UIString('Timeline.loadFromFile: File "%s" not found.', file.name)); + break; + case e.target.error.NOT_READABLE_ERR: + WebInspector.log(WebInspector.UIString('Timeline.loadFromFile: File "%s" is not readable', file.name)); + break; + case e.target.error.ABORT_ERR: + break; + default: + WebInspector.log(WebInspector.UIString('Timeline.loadFromFile: An error occurred while reading the file "%s"', file.name)); + } + } + + var reader = new FileReader(); + reader.onload = onLoad.bind(this); + reader.onerror = onError; + reader.readAsText(file); + }, + + _saveToFile: function() + { + var records = ['[' + JSON.stringify(new String(window.navigator.appVersion))]; + for (var i = 0; i < this._records.length; ++i) + records.push(JSON.stringify(this._records[i])); + + records[records.length - 1] = records[records.length - 1] + "]"; + + var now = new Date(); + var suggestedFileName = "TimelineRawData-" + now.toISO8601Compact() + ".json"; + InspectorFrontendHost.saveAs(suggestedFileName, records.join(",\n")); + }, + + _reset: function() + { + this._records = []; + } +} +/* TimelineOverviewPane.js */ + +/* + * 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. + */ + +/** + * @constructor + * @extends {WebInspector.Object} + */ +WebInspector.TimelineOverviewPane = function(categories) +{ + this._categories = categories; + + this.statusBarFilters = document.createElement("div"); + this.statusBarFilters.className = "status-bar-items"; + for (var categoryName in this._categories) { + var category = this._categories[categoryName]; + this.statusBarFilters.appendChild(this._createTimelineCategoryStatusBarCheckbox(category, this._onCheckboxClicked.bind(this, category))); + } + + this._overviewGrid = new WebInspector.TimelineGrid(); + this._overviewGrid.element.id = "timeline-overview-grid"; + this._overviewGrid.itemsGraphsElement.id = "timeline-overview-timelines"; + this._overviewGrid.element.addEventListener("mousedown", this._dragWindow.bind(this), true); + this._overviewGrid.element.addEventListener("mousewheel", this.scrollWindow.bind(this), true); + this._overviewGrid.element.addEventListener("dblclick", this._resizeWindowMaximum.bind(this), true); + + this._heapGraph = new WebInspector.HeapGraph(); + this._heapGraph.element.id = "timeline-overview-memory"; + this._overviewGrid.element.insertBefore(this._heapGraph.element, this._overviewGrid.itemsGraphsElement); + + this.element = this._overviewGrid.element; + + this._categoryGraphs = {}; + var i = 0; + for (var category in this._categories) { + var categoryGraph = new WebInspector.TimelineCategoryGraph(this._categories[category], i++ % 2); + this._categoryGraphs[category] = categoryGraph; + this._overviewGrid.itemsGraphsElement.appendChild(categoryGraph.graphElement); + } + this._overviewGrid.setScrollAndDividerTop(0, 0); + + this._overviewWindowElement = document.createElement("div"); + this._overviewWindowElement.id = "timeline-overview-window"; + this._overviewGrid.element.appendChild(this._overviewWindowElement); + + this._overviewWindowBordersElement = document.createElement("div"); + this._overviewWindowBordersElement.className = "timeline-overview-window-rulers"; + this._overviewGrid.element.appendChild(this._overviewWindowBordersElement); + + var overviewDividersBackground = document.createElement("div"); + overviewDividersBackground.className = "timeline-overview-dividers-background"; + this._overviewGrid.element.appendChild(overviewDividersBackground); + + this._leftResizeElement = document.createElement("div"); + this._leftResizeElement.className = "timeline-window-resizer"; + this._leftResizeElement.style.left = 0; + this._overviewGrid.element.appendChild(this._leftResizeElement); + + this._rightResizeElement = document.createElement("div"); + this._rightResizeElement.className = "timeline-window-resizer timeline-window-resizer-right"; + this._rightResizeElement.style.right = 0; + this._overviewGrid.element.appendChild(this._rightResizeElement); + + this._overviewCalculator = new WebInspector.TimelineOverviewCalculator(); + + this.windowLeft = 0.0; + this.windowRight = 1.0; +} + +WebInspector.TimelineOverviewPane.MinSelectableSize = 12; + +WebInspector.TimelineOverviewPane.WindowScrollSpeedFactor = .3; + +WebInspector.TimelineOverviewPane.ResizerOffset = 3.5; // half pixel because offset values are not rounded but ceiled + +WebInspector.TimelineOverviewPane.prototype = { + showTimelines: function(event) { + this._heapGraph.hide(); + this._overviewGrid.itemsGraphsElement.removeStyleClass("hidden"); + }, + + showMemoryGraph: function(records) { + this._heapGraph.show(); + this._heapGraph.update(records); + this._overviewGrid.itemsGraphsElement.addStyleClass("hidden"); + }, + + _onCheckboxClicked: function (category, event) { + if (event.target.checked) + category.hidden = false; + else + category.hidden = true; + this._categoryGraphs[category.name].dimmed = !event.target.checked; + this.dispatchEventToListeners("filter changed"); + }, + + _forAllRecords: function(recordsArray, callback) + { + if (!recordsArray) + return; + for (var i = 0; i < recordsArray.length; ++i) { + callback(recordsArray[i]); + this._forAllRecords(recordsArray[i].children, callback); + } + }, + + update: function(records, showShortEvents) + { + this._showShortEvents = showShortEvents; + // Clear summary bars. + var timelines = {}; + for (var category in this._categories) { + timelines[category] = []; + this._categoryGraphs[category].clearChunks(); + } + + // Create sparse arrays with 101 cells each to fill with chunks for a given category. + this._overviewCalculator.reset(); + this._forAllRecords(records, this._overviewCalculator.updateBoundaries.bind(this._overviewCalculator)); + + function markPercentagesForRecord(record) + { + if (!(this._showShortEvents || record.isLong())) + return; + var percentages = this._overviewCalculator.computeBarGraphPercentages(record); + + var end = Math.round(percentages.end); + var categoryName = record.category.name; + for (var j = Math.round(percentages.start); j <= end; ++j) + timelines[categoryName][j] = true; + } + this._forAllRecords(records, markPercentagesForRecord.bind(this)); + + // Convert sparse arrays to continuous segments, render graphs for each. + for (var category in this._categories) { + var timeline = timelines[category]; + window.timelineSaved = timeline; + var chunkStart = -1; + for (var j = 0; j < 101; ++j) { + if (timeline[j]) { + if (chunkStart === -1) + chunkStart = j; + } else { + if (chunkStart !== -1) { + this._categoryGraphs[category].addChunk(chunkStart, j); + chunkStart = -1; + } + } + } + if (chunkStart !== -1) { + this._categoryGraphs[category].addChunk(chunkStart, 100); + chunkStart = -1; + } + } + + this._heapGraph.setSize(this._overviewGrid.element.offsetWidth, 60); + if (this._heapGraph.visible) + this._heapGraph.update(records); + + this._overviewGrid.updateDividers(true, this._overviewCalculator); + }, + + updateEventDividers: function(records, dividerConstructor) + { + this._overviewGrid.removeEventDividers(); + var dividers = []; + for (var i = 0; i < records.length; ++i) { + var record = records[i]; + var positions = this._overviewCalculator.computeBarGraphPercentages(record); + var dividerPosition = Math.round(positions.start * 10); + if (dividers[dividerPosition]) + continue; + var divider = dividerConstructor(record); + divider.style.left = positions.start + "%"; + dividers[dividerPosition] = divider; + } + this._overviewGrid.addEventDividers(dividers); + }, + + sidebarResized: function(width) + { + this._overviewGrid.element.style.left = width + "px"; + // Min width = * 31 + this.statusBarFilters.style.left = Math.max(7 * 31, width) + "px"; + }, + + reset: function() + { + this.windowLeft = 0.0; + this.windowRight = 1.0; + this._overviewWindowElement.style.left = "0%"; + this._overviewWindowElement.style.width = "100%"; + this._overviewWindowBordersElement.style.left = "0%"; + this._overviewWindowBordersElement.style.right = "0%"; + this._leftResizeElement.style.left = "0%"; + this._rightResizeElement.style.left = "100%"; + this._overviewCalculator.reset(); + this._overviewGrid.updateDividers(true, this._overviewCalculator); + }, + + _resizeWindow: function(resizeElement, event) + { + WebInspector.elementDragStart(resizeElement, this._windowResizeDragging.bind(this, resizeElement), this._endWindowDragging.bind(this), event, "ew-resize"); + }, + + _windowResizeDragging: function(resizeElement, event) + { + if (resizeElement === this._leftResizeElement) + this._resizeWindowLeft(event.pageX - this._overviewGrid.element.offsetLeft); + else + this._resizeWindowRight(event.pageX - this._overviewGrid.element.offsetLeft); + event.preventDefault(); + }, + + _dragWindow: function(event) + { + var node = event.target; + while (node) { + if (node === this._overviewGrid._dividersLabelBarElement) { + WebInspector.elementDragStart(this._overviewWindowElement, this._windowDragging.bind(this, event.pageX, + this._leftResizeElement.offsetLeft + WebInspector.TimelineOverviewPane.ResizerOffset, this._rightResizeElement.offsetLeft + WebInspector.TimelineOverviewPane.ResizerOffset), this._endWindowDragging.bind(this), event, "ew-resize"); + break; + } else if (node === this._overviewGrid.element) { + var position = event.pageX - this._overviewGrid.element.offsetLeft; + this._overviewWindowSelector = new WebInspector.TimelinePanel.WindowSelector(this._overviewGrid.element, position, event); + WebInspector.elementDragStart(null, this._windowSelectorDragging.bind(this), this._endWindowSelectorDragging.bind(this), event, "ew-resize"); + break; + } else if (node === this._leftResizeElement || node === this._rightResizeElement) { + this._resizeWindow(node, event); + break; + } + node = node.parentNode; + } + }, + + _windowSelectorDragging: function(event) + { + this._overviewWindowSelector._updatePosition(event.pageX - this._overviewGrid.element.offsetLeft); + event.preventDefault(); + }, + + _endWindowSelectorDragging: function(event) + { + WebInspector.elementDragEnd(event); + var window = this._overviewWindowSelector._close(event.pageX - this._overviewGrid.element.offsetLeft); + delete this._overviewWindowSelector; + if (window.end - window.start < WebInspector.TimelineOverviewPane.MinSelectableSize) + if (this._overviewGrid.itemsGraphsElement.offsetWidth - window.end > WebInspector.TimelineOverviewPane.MinSelectableSize) + window.end = window.start + WebInspector.TimelineOverviewPane.MinSelectableSize; + else + window.start = window.end - WebInspector.TimelineOverviewPane.MinSelectableSize; + this._setWindowPosition(window.start, window.end); + }, + + _windowDragging: function(startX, windowLeft, windowRight, event) + { + var delta = event.pageX - startX; + var start = windowLeft + delta; + var end = windowRight + delta; + var windowSize = windowRight - windowLeft; + + if (start < 0) { + start = 0; + end = windowSize; + } + + if (end > this._overviewGrid.element.clientWidth) { + end = this._overviewGrid.element.clientWidth; + start = end - windowSize; + } + this._setWindowPosition(start, end); + + event.preventDefault(); + }, + + _resizeWindowLeft: function(start) + { + // Glue to edge. + if (start < 10) + start = 0; + else if (start > this._rightResizeElement.offsetLeft - 4) + start = this._rightResizeElement.offsetLeft - 4; + this._setWindowPosition(start, null); + }, + + _resizeWindowRight: function(end) + { + // Glue to edge. + if (end > this._overviewGrid.element.clientWidth - 10) + end = this._overviewGrid.element.clientWidth; + else if (end < this._leftResizeElement.offsetLeft + WebInspector.TimelineOverviewPane.MinSelectableSize) + end = this._leftResizeElement.offsetLeft + WebInspector.TimelineOverviewPane.MinSelectableSize; + this._setWindowPosition(null, end); + }, + + _resizeWindowMaximum: function() + { + this._setWindowPosition(0, this._overviewGrid.element.clientWidth); + }, + + _setWindowPosition: function(start, end) + { + const rulerAdjustment = 1 / this._overviewGrid.element.clientWidth; + if (typeof start === "number") { + this.windowLeft = start / this._overviewGrid.element.clientWidth; + this._leftResizeElement.style.left = this.windowLeft * 100 + "%"; + this._overviewWindowElement.style.left = this.windowLeft * 100 + "%"; + this._overviewWindowBordersElement.style.left = (this.windowLeft - rulerAdjustment) * 100 + "%"; + } + if (typeof end === "number") { + this.windowRight = end / this._overviewGrid.element.clientWidth; + this._rightResizeElement.style.left = this.windowRight * 100 + "%"; + } + this._overviewWindowElement.style.width = (this.windowRight - this.windowLeft) * 100 + "%"; + this._overviewWindowBordersElement.style.right = (1 - this.windowRight + 2 * rulerAdjustment) * 100 + "%"; + this.dispatchEventToListeners("window changed"); + }, + + _endWindowDragging: function(event) + { + WebInspector.elementDragEnd(event); + }, + + scrollWindow: function(event) + { + if (typeof event.wheelDeltaX === "number" && event.wheelDeltaX !== 0) + this._windowDragging(event.pageX + Math.round(event.wheelDeltaX * WebInspector.TimelineOverviewPane.WindowScrollSpeedFactor), this._leftResizeElement.offsetLeft + WebInspector.TimelineOverviewPane.ResizerOffset, this._rightResizeElement.offsetLeft + WebInspector.TimelineOverviewPane.ResizerOffset, event); + }, + + _createTimelineCategoryStatusBarCheckbox: function(category, onCheckboxClicked) + { + var labelContainer = document.createElement("div"); + labelContainer.addStyleClass("timeline-category-statusbar-item"); + labelContainer.addStyleClass("timeline-category-" + category.name); + labelContainer.addStyleClass("status-bar-item"); + + var label = document.createElement("label"); + var checkElement = document.createElement("input"); + checkElement.type = "checkbox"; + checkElement.className = "timeline-category-checkbox"; + checkElement.checked = true; + checkElement.addEventListener("click", onCheckboxClicked, false); + label.appendChild(checkElement); + + var typeElement = document.createElement("span"); + typeElement.className = "type"; + typeElement.textContent = category.title; + label.appendChild(typeElement); + + labelContainer.appendChild(label); + return labelContainer; + } + +} + +WebInspector.TimelineOverviewPane.prototype.__proto__ = WebInspector.Object.prototype; + +/** + * @constructor + */ +WebInspector.TimelineOverviewCalculator = function() +{ +} + +WebInspector.TimelineOverviewCalculator.prototype = { + computeBarGraphPercentages: function(record) + { + var start = (record.startTime - this.minimumBoundary) / this.boundarySpan * 100; + var end = (record.endTime - this.minimumBoundary) / this.boundarySpan * 100; + return {start: start, end: end}; + }, + + reset: function() + { + delete this.minimumBoundary; + delete this.maximumBoundary; + }, + + updateBoundaries: function(record) + { + if (typeof this.minimumBoundary === "undefined" || record.startTime < this.minimumBoundary) { + this.minimumBoundary = record.startTime; + return true; + } + if (typeof this.maximumBoundary === "undefined" || record.endTime > this.maximumBoundary) { + this.maximumBoundary = record.endTime; + return true; + } + return false; + }, + + get boundarySpan() + { + return this.maximumBoundary - this.minimumBoundary; + }, + + formatValue: function(value) + { + return Number.secondsToString(value); + } +} + +/** + * @constructor + */ +WebInspector.TimelineCategoryGraph = function(category, isEven) +{ + this._category = category; + + this._graphElement = document.createElement("div"); + this._graphElement.className = "timeline-graph-side timeline-overview-graph-side" + (isEven ? " even" : ""); + + this._barAreaElement = document.createElement("div"); + this._barAreaElement.className = "timeline-graph-bar-area timeline-category-" + category.name; + this._graphElement.appendChild(this._barAreaElement); +} + +WebInspector.TimelineCategoryGraph.prototype = { + get graphElement() + { + return this._graphElement; + }, + + addChunk: function(start, end) + { + var chunk = document.createElement("div"); + chunk.className = "timeline-graph-bar"; + this._barAreaElement.appendChild(chunk); + chunk.style.setProperty("left", start + "%"); + chunk.style.setProperty("width", (end - start) + "%"); + }, + + clearChunks: function() + { + this._barAreaElement.removeChildren(); + }, + + set dimmed(dimmed) + { + if (dimmed) + this._barAreaElement.removeStyleClass("timeline-category-" + this._category.name); + else + this._barAreaElement.addStyleClass("timeline-category-" + this._category.name); + } +} + +/** + * @constructor + */ +WebInspector.TimelinePanel.WindowSelector = function(parent, position, event) +{ + this._startPosition = position; + this._width = parent.offsetWidth; + this._windowSelector = document.createElement("div"); + this._windowSelector.className = "timeline-window-selector"; + this._windowSelector.style.left = this._startPosition + "px"; + this._windowSelector.style.right = this._width - this._startPosition + + "px"; + parent.appendChild(this._windowSelector); +} + +WebInspector.TimelinePanel.WindowSelector.prototype = { + _createSelectorElement: function(parent, left, width, height) + { + var selectorElement = document.createElement("div"); + selectorElement.className = "timeline-window-selector"; + selectorElement.style.left = left + "px"; + selectorElement.style.width = width + "px"; + selectorElement.style.top = "0px"; + selectorElement.style.height = height + "px"; + parent.appendChild(selectorElement); + return selectorElement; + }, + + _close: function(position) + { + position = Math.max(0, Math.min(position, this._width)); + this._windowSelector.parentNode.removeChild(this._windowSelector); + return this._startPosition < position ? {start: this._startPosition, end: position} : {start: position, end: this._startPosition}; + }, + + _updatePosition: function(position) + { + position = Math.max(0, Math.min(position, this._width)); + if (position < this._startPosition) { + this._windowSelector.style.left = position + "px"; + this._windowSelector.style.right = this._width - this._startPosition + "px"; + } else { + this._windowSelector.style.left = this._startPosition + "px"; + this._windowSelector.style.right = this._width - position + "px"; + } + } +} + +/** + * @constructor + */ +WebInspector.HeapGraph = function() { + this._canvas = document.createElement("canvas"); + + this._maxHeapSizeLabel = document.createElement("div"); + this._maxHeapSizeLabel.addStyleClass("memory-graph-label"); + + this._element = document.createElement("div"); + this._element.addStyleClass("hidden"); + this._element.appendChild(this._canvas); + this._element.appendChild(this._maxHeapSizeLabel); +} + +WebInspector.HeapGraph.prototype = { + get element() { + // return this._canvas; + return this._element; + }, + + get visible() { + return !this.element.hasStyleClass("hidden"); + }, + + show: function() { + this.element.removeStyleClass("hidden"); + }, + + hide: function() { + this.element.addStyleClass("hidden"); + }, + + setSize: function(w, h) { + this._canvas.width = w; + this._canvas.height = h - 5; + }, + + update: function(records) + { + if (!records.length) + return; + + var maxTotalHeapSize = 0; + var minTime; + var maxTime; + this._forAllRecords(records, function(r) { + if (r.totalHeapSize && r.totalHeapSize > maxTotalHeapSize) + maxTotalHeapSize = r.totalHeapSize; + + if (typeof minTime === "undefined" || r.startTime < minTime) + minTime = r.startTime; + if (typeof maxTime === "undefined" || r.endTime > maxTime) + maxTime = r.endTime; + }); + + var width = this._canvas.width; + var height = this._canvas.height; + var xFactor = width / (maxTime - minTime); + var yFactor = height / maxTotalHeapSize; + + var histogram = new Array(width); + this._forAllRecords(records, function(r) { + if (!r.usedHeapSize) + return; + var x = Math.round((r.endTime - minTime) * xFactor); + var y = Math.round(r.usedHeapSize * yFactor); + histogram[x] = Math.max(histogram[x] || 0, y); + }); + + var ctx = this._canvas.getContext("2d"); + this._clear(ctx); + + // +1 so that the border always fit into the canvas area. + height = height + 1; + + ctx.beginPath(); + var initialY = 0; + for (var k = 0; k < histogram.length; k++) { + if (histogram[k]) { + initialY = histogram[k]; + break; + } + } + ctx.moveTo(0, height - initialY); + + for (var x = 0; x < histogram.length; x++) { + if (!histogram[x]) + continue; + ctx.lineTo(x, height - histogram[x]); + } + + ctx.lineWidth = 0.5; + ctx.strokeStyle = "rgba(20,0,0,0.8)"; + ctx.stroke(); + + ctx.fillStyle = "rgba(214,225,254, 0.8);"; + ctx.lineTo(width, 60); + ctx.lineTo(0, 60); + ctx.lineTo(0, height - initialY); + ctx.fill(); + ctx.closePath(); + + this._maxHeapSizeLabel.textContent = Number.bytesToString(maxTotalHeapSize); + }, + + _clear: function(ctx) { + ctx.fillStyle = "rgba(255,255,255,0.8)"; + ctx.fillRect(0, 0, this._canvas.width, this._canvas.height); + }, + + _forAllRecords: WebInspector.TimelineOverviewPane.prototype._forAllRecords +} +/* TestController.js */ + +/* + * 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. + */ + +/** + * @constructor + */ +WebInspector.TestController = function() +{ +} + +WebInspector.TestController.prototype = { + notifyDone: function(callId, result) + { + var message = typeof result === "undefined" ? "\"\"" : JSON.stringify(result); + RuntimeAgent.evaluate("didEvaluateForTestInFrontend(" + callId + ", " + message + ")", "test"); + } +} + +WebInspector.evaluateForTestInFrontend = function(callId, script) +{ + function invokeMethod() + { + try { + var result = window.eval(script); + WebInspector.TestController.prototype.notifyDone(callId, result); + } catch (e) { + WebInspector.TestController.prototype.notifyDone(callId, e.toString()); + } + } + InspectorBackend.runAfterPendingDispatches(invokeMethod); +} +/* HelpScreen.js */ + +/* + * 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. + * * 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. + */ + +/** + * @constructor + */ +WebInspector.HelpScreen = function(title) +{ + this._element = document.createElement("div"); + this._element.className = "help-window-outer"; + this._element.addEventListener("keydown", this._onKeyDown.bind(this), false); + this._element.tabIndex = 0; + this._element.addEventListener("focus", this._onBlur.bind(this), false); + + var mainWindow = this._element.createChild("div", "help-window-main"); + var captionWindow = mainWindow.createChild("div", "help-window-caption"); + var closeButton = captionWindow.createChild("button", "help-close-button"); + this.contentElement = mainWindow.createChild("div", "help-content"); + captionWindow.createChild("h1", "help-window-title").textContent = title; + + closeButton.textContent = "\u2716"; // Code stands for HEAVY MULTIPLICATION X. + closeButton.addEventListener("click", this.hide.bind(this), false); + this._closeKeys = [ + WebInspector.KeyboardShortcut.Keys.Enter.code, + WebInspector.KeyboardShortcut.Keys.Esc.code, + WebInspector.KeyboardShortcut.Keys.Space.code, + ]; +} + +WebInspector.HelpScreen.visibleScreen_ = null; + +WebInspector.HelpScreen.prototype = { + show: function(onHide) + { + if (this._isShown) + return; + + if (WebInspector.HelpScreen.visibleScreen_) + WebInspector.HelpScreen.visibleScreen_.hide(); + WebInspector.HelpScreen.visibleScreen_ = this; + + document.body.appendChild(this._element); + this._isShown = true; + this._onHide = onHide; + this._previousFocusElement = WebInspector.currentFocusElement(); + WebInspector.setCurrentFocusElement(this._element); + }, + + hide: function() + { + if (!this._isShown) + return; + + this._isShown = false; + document.body.removeChild(this._element); + WebInspector.setCurrentFocusElement(this._previousFocusElement); + WebInspector.HelpScreen.visibleScreen_ = null; + if (this._onHide) { + this._onHide(); + delete this._onHide; + } + }, + + _onKeyDown: function(event) + { + if (this._isShown && this._closeKeys.indexOf(event.keyCode) >= 0) { + this.hide(); + event.stopPropagation(); + } + }, + + _onBlur: function(event) + { + // Pretend we're modal, grab focus back if we're still shown. + if (this._isShown && !this._element.isSelfOrAncestor(event.target)) + WebInspector.setCurrentFocusElement(this._element); + } +} +/* Dialog.js */ + +/* + * Copyright (C) 2012 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. + */ + +/** + * @constructor + * @param {Element} relativeToElement + * @param {WebInspector.DialogDelegate} delegate + */ +WebInspector.Dialog = function(relativeToElement, delegate) +{ + this._delegate = delegate; + this._relativeToElement = relativeToElement; + + // Install glass pane capturing events. + this._glassPaneElement = document.body.createChild("div"); + this._glassPaneElement.className = "dialog-glass-pane"; + this._glassPaneElement.tabIndex = 0; + this._glassPaneElement.addEventListener("focus", this._onGlassPaneFocus.bind(this), false); + + this._element = this._glassPaneElement.createChild("div"); + this._element.className = "dialog"; + this._element.tabIndex = 0; + this._element.addEventListener("focus", this._onFocus.bind(this), false); + this._element.addEventListener("keydown", this._onKeyDown.bind(this), false); + this._closeKeys = [ + WebInspector.KeyboardShortcut.Keys.Enter.code, + WebInspector.KeyboardShortcut.Keys.Esc.code, + ]; + + delegate.element.addStyleClass("dialog-contents"); + this._element.appendChild(delegate.element); + + this._position(); + this._windowResizeHandler = this._position.bind(this); + window.addEventListener("resize", this._windowResizeHandler, true); + + this._previousFocusElement = WebInspector.currentFocusElement(); + this._delegate.focus(); +} + +/** + * @return {WebInspector.Dialog} + */ +WebInspector.Dialog.currentInstance = function() +{ + return WebInspector.Dialog._instance; +} + +/** + * @param {Element} relativeToElement + * @param {WebInspector.DialogDelegate} delegate + */ +WebInspector.Dialog.show = function(relativeToElement, delegate) +{ + if (WebInspector.Dialog._instance) + return; + WebInspector.Dialog._instance = new WebInspector.Dialog(relativeToElement, delegate); +} + +WebInspector.Dialog.hide = function() +{ + if (!WebInspector.Dialog._instance) + return; + WebInspector.Dialog._instance._hide(); +} + +WebInspector.Dialog.prototype = { + _hide: function() + { + if (this._isHiding) + return; + this._isHiding = true; + + this._delegate.willHide(); + + if (this._element.isSelfOrAncestor(document.activeElement)) + WebInspector.setCurrentFocusElement(this._previousFocusElement); + delete WebInspector.Dialog._instance; + document.body.removeChild(this._glassPaneElement); + window.removeEventListener("resize", this._windowResizeHandler, true); + }, + + _onGlassPaneFocus: function(event) + { + this._hide(); + }, + + _onFocus: function(event) + { + this._delegate.focus(); + }, + + _position: function() + { + this._delegate.position(this._element, this._relativeToElement); + }, + + _onKeyDown: function(event) + { + if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Tab.code) { + event.preventDefault(); + return; + } + + if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Enter.code) + this._delegate.onEnter(); + + if (this._closeKeys.indexOf(event.keyCode) >= 0) { + this._hide(); + event.preventDefault(); + event.stopPropagation(); + } + } +}; + +/** + * @constructor + */ +WebInspector.DialogDelegate = function() +{ +} + +WebInspector.DialogDelegate.prototype = { + /** + * @param {Element} element + * @param {Element} relativeToElement + */ + position: function(element, relativeToElement) + { + var offset = relativeToElement.offsetRelativeToWindow(window); + + var positionX = offset.x + (relativeToElement.offsetWidth - element.offsetWidth) / 2; + positionX = Number.constrain(positionX, 0, window.innerWidth - element.offsetWidth); + + var positionY = offset.y + (relativeToElement.offsetHeight - element.offsetHeight) / 2; + positionY = Number.constrain(positionY, 0, window.innerHeight - element.offsetHeight); + + element.style.left = positionX + "px"; + element.style.top = positionY + "px"; + }, + + focus: function() { }, + + onEnter: function() { }, + + willHide: function() { } +}; +/* GoToLineDialog.js */ + +/* + * 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. + * * 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. + */ + +/** + * @constructor + * @extends {WebInspector.DialogDelegate} + */ +WebInspector.GoToLineDialog = function(view) +{ + WebInspector.DialogDelegate.call(this); + + this.element = document.createElement("div"); + this.element.className = "go-to-line-dialog"; + + this.element.createChild("label").textContent = WebInspector.UIString("Go to line: "); + + this._input = this.element.createChild("input"); + this._input.setAttribute("type", "text"); + this._input.setAttribute("size", 6); + + this._goButton = this.element.createChild("button"); + this._goButton.textContent = WebInspector.UIString("Go"); + this._goButton.addEventListener("click", this._onGoClick.bind(this), false); + + this._view = view; +} + +/** + * @param {WebInspector.Panel} panel + */ +WebInspector.GoToLineDialog.install = function(panel, viewGetter) +{ + function showGoToLineDialog() + { + var view = viewGetter(); + if (view) + WebInspector.GoToLineDialog._show(view); + } + + var goToLineShortcut = WebInspector.GoToLineDialog.createShortcut(); + panel.registerShortcut(goToLineShortcut.key, showGoToLineDialog); +} + +WebInspector.GoToLineDialog._show = function(sourceView) +{ + if (!sourceView || !sourceView.canHighlightLine()) + return; + WebInspector.Dialog.show(sourceView.element, new WebInspector.GoToLineDialog(sourceView)); +} + +WebInspector.GoToLineDialog.createShortcut = function() +{ + var isMac = WebInspector.isMac(); + var shortcut; + if (isMac) + return WebInspector.KeyboardShortcut.makeDescriptor("l", WebInspector.KeyboardShortcut.Modifiers.Meta); + return WebInspector.KeyboardShortcut.makeDescriptor("g", WebInspector.KeyboardShortcut.Modifiers.Ctrl); +} + +WebInspector.GoToLineDialog.prototype = { + focus: function() + { + WebInspector.setCurrentFocusElement(this._input); + this._input.select(); + }, + + _onGoClick: function() + { + this._applyLineNumber(); + WebInspector.Dialog.hide(); + }, + + _applyLineNumber: function() + { + var value = this._input.value; + var lineNumber = parseInt(value, 10) - 1; + if (!isNaN(lineNumber) && lineNumber >= 0) + this._view.highlightLine(lineNumber); + }, + + onEnter: function() + { + this._applyLineNumber(); + } +} + +WebInspector.GoToLineDialog.prototype.__proto__ = WebInspector.DialogDelegate.prototype; +/* FilteredItemSelectionDialog.js */ + +/* + * Copyright (C) 2012 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. + */ + +/** + * @constructor + * @extends {WebInspector.DialogDelegate} + * @param {WebInspector.SelectionDialogContentProvider} delegate + */ +WebInspector.FilteredItemSelectionDialog = function(delegate) +{ + WebInspector.DialogDelegate.call(this); + + var xhr = new XMLHttpRequest(); + xhr.open("GET", "filteredItemSelectionDialog.css", false); + xhr.send(null); + + this.element = document.createElement("div"); + this.element.className = "js-outline-dialog"; + this.element.addEventListener("keydown", this._onKeyDown.bind(this), false); + this.element.addEventListener("mousemove", this._onMouseMove.bind(this), false); + this.element.addEventListener("click", this._onClick.bind(this), false); + var styleElement = this.element.createChild("style"); + styleElement.type = "text/css"; + styleElement.textContent = xhr.responseText; + + this._previousInputLength = 0; + this._itemElements = []; + this._elementIndexes = new Map(); + this._elementHighlightChanges = new Map(); + + this._promptElement = this.element.createChild("input", "monospace"); + this._promptElement.type = "text"; + this._promptElement.setAttribute("spellcheck", "false"); + + this._progressElement = this.element.createChild("div", "progress"); + + this._itemElementsContainer = document.createElement("div"); + this._itemElementsContainer.className = "container monospace"; + this._itemElementsContainer.addEventListener("scroll", this._onScroll.bind(this), false); + this.element.appendChild(this._itemElementsContainer); + + this._delegate = delegate; + + this._delegate.requestItems(this._itemsLoaded.bind(this)); +} + +WebInspector.FilteredItemSelectionDialog.prototype = { + /** + * @param {Element} element + * @param {Element} relativeToElement + */ + position: function(element, relativeToElement) + { + const minWidth = 500; + const minHeight = 204; + var width = Math.max(relativeToElement.offsetWidth * 2 / 3, minWidth); + var height = Math.max(relativeToElement.offsetHeight * 2 / 3, minHeight); + + this.element.style.width = width + "px"; + this.element.style.height = height + "px"; + + const shadowPadding = 10; + element.positionAt( + relativeToElement.totalOffsetLeft() + Math.max(relativeToElement.offsetWidth - width - shadowPadding, shadowPadding), + relativeToElement.totalOffsetTop() + Math.max((relativeToElement.offsetHeight - height) / 2 + shadowPadding, shadowPadding)); + }, + + focus: function() + { + WebInspector.setCurrentFocusElement(this._promptElement); + }, + + willHide: function() + { + if (this._isHiding) + return; + this._isHiding = true; + if (this._filterTimer) + clearTimeout(this._filterTimer); + }, + + onEnter: function() + { + if (!this._selectedElement) + return; + this._delegate.selectItem(this._elementIndexes.get(this._selectedElement)); + }, + + /** + * @param {number} index + * @param {number} chunkLength + * @param {number} chunkIndex + * @param {number} chunkCount + */ + _itemsLoaded: function(index, chunkLength, chunkIndex, chunkCount) + { + var fragment = document.createDocumentFragment(); + var candidateItem = this._selectedElement; + for (var i = index; i < index + chunkLength; ++i) { + var itemElement = this._createItemElement(i, this._delegate.itemTitleAt(i)); + if (this._checkItemAt(i, this._promptElement.value)) { + if (!candidateItem) + candidateItem = itemElement; + } else + this._hideItemElement(itemElement); + fragment.appendChild(itemElement); + } + this._itemElementsContainer.appendChild(fragment); + this._updateSelection(candidateItem); + + if (chunkIndex === chunkCount) + this._progressElement.style.backgroundImage = ""; + else { + const color = "rgb(66, 129, 235)"; + const percent = ((chunkIndex / chunkCount) * 100) + "%"; + this._progressElement.style.backgroundImage = "-webkit-linear-gradient(left, " + color + ", " + color + " " + percent + ", transparent " + percent + ")"; + } + }, + + /** + * @param {number} index + * @param {string} title + */ + _createItemElement: function(index, title) + { + if (this._itemElements[index]) + return this._itemElements[index]; + + var itemElement = document.createElement("div"); + itemElement.className = "item"; + itemElement.textContent = title; + this._elementIndexes.put(itemElement, index); + this._itemElements.push(itemElement); + + return itemElement; + }, + + /** + * @param {Element} itemElement + */ + _hideItemElement: function(itemElement) + { + itemElement.style.display = "none"; + }, + + /** + * @param {Element} itemElement + */ + _itemElementVisible: function(itemElement) + { + return itemElement.style.display !== "none"; + }, + + /** + * @param {Element} itemElement + */ + _showItemElement: function(itemElement) + { + itemElement.style.display = ""; + }, + + /** + * @param {number} index + */ + _checkItemAt: function(index, query) + { + if (!query) + return true; + var regExp = this._createSearchRegExp(query); + var key = this._delegate.itemKeyAt(index); + return regExp.test(key); + }, + + /** + * @param {string=} query + * @param {boolean=} isGlobal + */ + _createSearchRegExp: function(query, isGlobal) + { + var trimmedQuery = query.trim(); + var regExpString = trimmedQuery.escapeForRegExp().replace(/\\\*/g, ".*").replace(/(?!^)([A-Z])/g, "[^A-Z]*$1"); + var isSuffix = (query.charAt(query.length - 1) === " "); + if (isSuffix) + regExpString += "$"; + return new RegExp(regExpString, (trimmedQuery === trimmedQuery.toLowerCase() ? "i" : "") + (isGlobal ? "g" : "")); + }, + + _filterItems: function() + { + delete this._filterTimer; + + var query = this._promptElement.value; + var charsAdded = this._previousInputLength < query.length; + this._previousInputLength = query.length; + query = query.trim(); + + var firstElement; + for (var i = 0; i < this._itemElements.length; ++i) { + var itemElement = this._itemElements[i]; + + if (this._itemElementVisible(itemElement)) { + if (!this._checkItemAt(i, query)) + this._hideItemElement(itemElement); + } else if (!charsAdded && this._checkItemAt(i, query)) + this._showItemElement(itemElement); + + if (!firstElement && this._itemElementVisible(itemElement)) + firstElement = itemElement; + } + + this._updateSelection(firstElement); + if (query) { + this._highlightItems(query); + this._query = query; + } else { + this._clearHighlight(); + delete this._query; + } + }, + + _onKeyDown: function(event) + { + function nextItem(itemElement, isPageScroll, forward) + { + var scrollItemsLeft = isPageScroll && this._rowsPerViewport ? this._rowsPerViewport : 1; + var candidate = itemElement; + var lastVisibleCandidate = candidate; + do { + candidate = forward ? candidate.nextSibling : candidate.previousSibling; + if (!candidate) { + if (isPageScroll) + return lastVisibleCandidate; + else + candidate = forward ? this._itemElementsContainer.firstChild : this._itemElementsContainer.lastChild; + } + if (!this._itemElementVisible(candidate)) + continue; + lastVisibleCandidate = candidate; + --scrollItemsLeft; + } while (scrollItemsLeft && candidate !== this._selectedElement); + + return candidate; + } + + var isPageScroll = false; + + if (this._selectedElement) { + var candidate; + switch (event.keyCode) { + case WebInspector.KeyboardShortcut.Keys.Down.code: + candidate = nextItem.call(this, this._selectedElement, false, true); + break; + case WebInspector.KeyboardShortcut.Keys.Up.code: + candidate = nextItem.call(this, this._selectedElement, false, false); + break; + case WebInspector.KeyboardShortcut.Keys.PageDown.code: + candidate = nextItem.call(this, this._selectedElement, true, true); + break; + case WebInspector.KeyboardShortcut.Keys.PageUp.code: + candidate = nextItem.call(this, this._selectedElement, true, false); + break; + } + + if (candidate) { + this._updateSelection(candidate); + event.preventDefault(); + return; + } + } + + if (event.keyIdentifier !== "Shift" && event.keyIdentifier !== "Ctrl" && event.keyIdentifier !== "Meta" && event.keyIdentifier !== "Left" && event.keyIdentifier !== "Right") + this._scheduleFilter(); + }, + + _scheduleFilter: function() + { + if (this._filterTimer) + return; + this._filterTimer = setTimeout(this._filterItems.bind(this), 0); + }, + + /** + * @param {Element} newSelectedElement + */ + _updateSelection: function(newSelectedElement) + { + if (this._selectedElement === newSelectedElement) + return; + if (this._selectedElement) + this._selectedElement.removeStyleClass("selected"); + + this._selectedElement = newSelectedElement; + if (newSelectedElement) { + newSelectedElement.addStyleClass("selected"); + newSelectedElement.scrollIntoViewIfNeeded(false); + if (!this._itemHeight) { + this._itemHeight = newSelectedElement.offsetHeight; + this._rowsPerViewport = Math.floor(this._itemElementsContainer.offsetHeight / this._itemHeight); + } + } + }, + + _onClick: function(event) + { + var itemElement = event.target.enclosingNodeOrSelfWithClass("item"); + if (!itemElement) + return; + this._updateSelection(itemElement); + this._delegate.selectItem(this._elementIndexes.get(this._selectedElement)); + WebInspector.Dialog.hide(); + }, + + _onMouseMove: function(event) + { + var itemElement = event.target.enclosingNodeOrSelfWithClass("item"); + if (!itemElement) + return; + this._updateSelection(itemElement); + }, + + _onScroll: function() + { + if (this._query) + this._highlightItems(this._query); + else + this._clearHighlight(); + }, + + /** + * @param {string=} query + */ + _highlightItems: function(query) + { + var regex = this._createSearchRegExp(query, true); + for (var i = 0; i < this._delegate.itemsCount(); ++i) { + var itemElement = this._itemElements[i]; + if (this._itemElementVisible(itemElement) && this._itemElementInViewport(itemElement)) + this._highlightItem(itemElement, regex); + } + }, + + _clearHighlight: function() + { + for (var i = 0; i < this._delegate.itemsCount(); ++i) + this._clearElementHighlight(this._itemElements[i]); + }, + + /** + * @param {Element} itemElement + */ + _clearElementHighlight: function(itemElement) + { + var changes = this._elementHighlightChanges.get(itemElement) + if (changes) { + revertDomChanges(changes); + this._elementHighlightChanges.remove(itemElement); + } + }, + + /** + * @param {Element} itemElement + * @param {RegExp} regex + */ + _highlightItem: function(itemElement, regex) + { + this._clearElementHighlight(itemElement); + + var key = this._delegate.itemKeyAt(this._elementIndexes.get(itemElement)); + var ranges = []; + + var match; + while ((match = regex.exec(key)) !== null) { + ranges.push({ offset: match.index, length: regex.lastIndex - match.index }); + } + + var changes = []; + highlightRangesWithStyleClass(itemElement, ranges, "highlight", changes); + + if (changes.length) + this._elementHighlightChanges.put(itemElement, changes); + }, + + /** + * @param {Element} itemElement + * @return {boolean} + */ + _itemElementInViewport: function(itemElement) + { + if (itemElement.offsetTop + this._itemHeight < this._itemElementsContainer.scrollTop) + return false; + if (itemElement.offsetTop > this._itemElementsContainer.scrollTop + this._itemHeight * (this._rowsPerViewport + 1)) + return false; + return true; + } +} + +WebInspector.FilteredItemSelectionDialog.prototype.__proto__ = WebInspector.DialogDelegate.prototype; + +/** + * @interface + */ +WebInspector.SelectionDialogContentProvider = function() +{ +} + +WebInspector.SelectionDialogContentProvider.prototype = { + /** + * @param {number} itemIndex + * @return {string} + */ + itemTitleAt: function(itemIndex) { }, + + /** + * @param {number} itemIndex + * @return {string} + */ + itemKeyAt: function(itemIndex) { }, + + /** + * @return {number} + */ + itemsCount: function() { }, + + /** + * @param {function(number, number, number, number)} callback + */ + requestItems: function(callback) { }, + + /** + * @param {number} itemIndex + */ + selectItem: function(itemIndex) { } +}; + +/** + * @constructor + * @implements {WebInspector.SelectionDialogContentProvider} + */ +WebInspector.JavaScriptOutlineDialog = function(panel, view) +{ + WebInspector.SelectionDialogContentProvider.call(this); + + this._functionItems = []; + + this._panel = panel; + this._view = view; +} + +/** + * @param {{chunk, index, total, id}} data + */ +WebInspector.JavaScriptOutlineDialog.didAddChunk = function(data) +{ + var instance = WebInspector.JavaScriptOutlineDialog._instance; + if (!instance) + return; + + if (data.id !== instance._view.uiSourceCode.id) + return; + + instance._appendItemElements(data.chunk, data.index, data.total); +}, + +WebInspector.JavaScriptOutlineDialog.install = function(panel, viewGetter) +{ + function showJavaScriptOutlineDialog() + { + var view = viewGetter(); + if (view) + WebInspector.JavaScriptOutlineDialog._show(panel, view); + } + + var javaScriptOutlineShortcut = WebInspector.JavaScriptOutlineDialog.createShortcut(); + panel.registerShortcut(javaScriptOutlineShortcut.key, showJavaScriptOutlineDialog); +} + +WebInspector.JavaScriptOutlineDialog._show = function(panel, sourceView) +{ + if (WebInspector.Dialog.currentInstance()) + return; + if (!sourceView || !sourceView.canHighlightLine()) + return; + WebInspector.JavaScriptOutlineDialog._instance = new WebInspector.JavaScriptOutlineDialog(panel, sourceView); + + var filteredItemSelectionDialog = new WebInspector.FilteredItemSelectionDialog(WebInspector.JavaScriptOutlineDialog._instance); + WebInspector.Dialog.show(sourceView.element, filteredItemSelectionDialog); +} + +WebInspector.JavaScriptOutlineDialog.createShortcut = function() +{ + return WebInspector.KeyboardShortcut.makeDescriptor("o", WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta); +} + +WebInspector.JavaScriptOutlineDialog.prototype = { + /** + * @param {number} itemIndex + * @return {string} + */ + itemTitleAt: function(itemIndex) + { + var functionItem = this._functionItems[itemIndex]; + return functionItem.name + (functionItem.arguments ? functionItem.arguments : ""); + }, + + /** + * @param {number} itemIndex + * @return {string} + */ + itemKeyAt: function(itemIndex) + { + return this._functionItems[itemIndex].name; + }, + + /** + * @return {number} + */ + itemsCount: function() + { + return this._functionItems.length; + }, + + /** + * @param {function(number, number, number, number)} callback + */ + requestItems: function(callback) + { + this._itemsAddedCallback = callback; + this._panel.requestVisibleScriptOutline(); + }, + + /** + * @param {number} itemIndex + */ + selectItem: function(itemIndex) + { + var lineNumber = this._functionItems[itemIndex].line; + if (!isNaN(lineNumber) && lineNumber >= 0) + this._view.highlightLine(lineNumber); + this._view.focus(); + delete WebInspector.JavaScriptOutlineDialog._instance; + }, + + /** + * @param {Array.} chunk + * @param {number} chunkIndex + * @param {number} chunkCount + */ + _appendItemElements: function(chunk, chunkIndex, chunkCount) + { + var index = this._functionItems.length; + for (var i = 0; i < chunk.length; ++i) { + this._functionItems.push(chunk[i]); + } + this._itemsAddedCallback(index, chunk.length, chunkIndex, chunkCount); + } +} + +WebInspector.JavaScriptOutlineDialog.prototype.__proto__ = WebInspector.SelectionDialogContentProvider.prototype; + +/** + * @constructor + * @implements {WebInspector.SelectionDialogContentProvider} + * @param {WebInspector.ScriptsPanel} panel + * @param {WebInspector.DebuggerPresentationModel} presentationModel + */ +WebInspector.OpenResourceDialog = function(panel, presentationModel) +{ + WebInspector.SelectionDialogContentProvider.call(this); + + this._panel = panel; + this._uiSourceCodes = presentationModel.uiSourceCodes(); + + function filterOutEmptyURLs(uiSourceCode) + { + return !!uiSourceCode.fileName; + } + + this._uiSourceCodes = this._uiSourceCodes.filter(filterOutEmptyURLs); +} + +/** + * @param {WebInspector.ScriptsPanel} panel + * @param {WebInspector.DebuggerPresentationModel} presentationModel + */ +WebInspector.OpenResourceDialog.install = function(panel, presentationModel, relativeToElement) +{ + function showOpenResourceDialog() + { + WebInspector.OpenResourceDialog._show(panel, presentationModel, relativeToElement); + } + + var openResourceShortcut = WebInspector.OpenResourceDialog.createShortcut(); + panel.registerShortcut(openResourceShortcut.key, showOpenResourceDialog); +} + +/** + * @param {WebInspector.ScriptsPanel} panel + * @param {WebInspector.DebuggerPresentationModel} presentationModel + * @param {Element} relativeToElement + */ +WebInspector.OpenResourceDialog._show = function(panel, presentationModel, relativeToElement) +{ + if (WebInspector.Dialog.currentInstance()) + return; + + var filteredItemSelectionDialog = new WebInspector.FilteredItemSelectionDialog(new WebInspector.OpenResourceDialog(panel, presentationModel)); + WebInspector.Dialog.show(relativeToElement, filteredItemSelectionDialog); +} + +WebInspector.OpenResourceDialog.createShortcut = function() +{ + return WebInspector.KeyboardShortcut.makeDescriptor("t", WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta | WebInspector.KeyboardShortcut.Modifiers.Shift); +} + +WebInspector.OpenResourceDialog.prototype = { + /** + * @param {number} itemIndex + * @return {string} + */ + itemTitleAt: function(itemIndex) + { + return this._uiSourceCodes[itemIndex].fileName; + }, + + /** + * @param {number} itemIndex + * @return {string} + */ + itemKeyAt: function(itemIndex) + { + return this._uiSourceCodes[itemIndex].fileName; + }, + + /** + * @return {number} + */ + itemsCount: function() + { + return this._uiSourceCodes.length; + }, + + /** + * @param {function(number, number, number, number)} callback + */ + requestItems: function(callback) + { + callback(0, this._uiSourceCodes.length, 1, 1); + }, + + /** + * @param {number} itemIndex + */ + selectItem: function(itemIndex) + { + this._panel.showUISourceCode(this._uiSourceCodes[itemIndex]); + } +} + +WebInspector.OpenResourceDialog.prototype.__proto__ = WebInspector.SelectionDialogContentProvider.prototype; +/* SettingsScreen.js */ + +/* + * Copyright (C) 2011 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. + */ + +/** + * @constructor + * @extends {WebInspector.HelpScreen} + */ +WebInspector.SettingsScreen = function() +{ + WebInspector.HelpScreen.call(this, WebInspector.UIString("Settings")); + + this._leftColumnElement = document.createElement("td"); + this._rightColumnElement = document.createElement("td"); + + if (Preferences.showDockToRight) { + var p = this._appendSection(WebInspector.UIString("General")); + p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Dock to right"), WebInspector.settings.dockToRight)); + } + + var p = this._appendSection(WebInspector.UIString("Elements")); + p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Word wrap"), WebInspector.settings.domWordWrap)); + + p = this._appendSection(WebInspector.UIString("Styles")); + p.appendChild(this._createRadioSetting(WebInspector.UIString("Color format"), [ + [ WebInspector.StylesSidebarPane.ColorFormat.Original, WebInspector.UIString("As authored") ], + [ WebInspector.StylesSidebarPane.ColorFormat.HEX, "HEX: #DAC0DE" ], + [ WebInspector.StylesSidebarPane.ColorFormat.RGB, "RGB: rgb(128, 255, 255)" ], + [ WebInspector.StylesSidebarPane.ColorFormat.HSL, "HSL: hsl(300, 80%, 90%)" ] ], WebInspector.settings.colorFormat)); + p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Show user agent styles"), WebInspector.settings.showUserAgentStyles)); + + p = this._appendSection(WebInspector.UIString("Text editor")); + p.appendChild(this._createSelectSetting(WebInspector.UIString("Indent"), [ + [ WebInspector.UIString("2 spaces"), WebInspector.TextEditorModel.Indent.TwoSpaces ], + [ WebInspector.UIString("4 spaces"), WebInspector.TextEditorModel.Indent.FourSpaces ], + [ WebInspector.UIString("8 spaces"), WebInspector.TextEditorModel.Indent.EightSpaces ], + [ WebInspector.UIString("Tab character"), WebInspector.TextEditorModel.Indent.TabCharacter ] + ], WebInspector.settings.textEditorIndent)); + + p = this._appendSection(WebInspector.UIString("Network"), true); + if (Preferences.exposeDisableCache) + p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Disable cache"), WebInspector.settings.cacheDisabled)); + p.appendChild(this._createUserActionControl()); + + p = this._appendSection(WebInspector.UIString("Scripts"), true); + p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Show script folders"), WebInspector.settings.showScriptFolders)); + p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Search in content scripts"), WebInspector.settings.searchInContentScripts)); + p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Enable source maps"), WebInspector.settings.sourceMapsEnabled)); + + p = this._appendSection(WebInspector.UIString("Profiler"), true); + p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Show objects' hidden properties"), WebInspector.settings.showHeapSnapshotObjectsHiddenProperties)); + + p = this._appendSection(WebInspector.UIString("Console"), true); + p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Log XMLHttpRequests"), WebInspector.settings.monitoringXHREnabled)); + p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Preserve log upon navigation"), WebInspector.settings.preserveConsoleLog)); + + if (WebInspector.extensionServer.hasExtensions()) { + var handlerSelector = new WebInspector.HandlerSelector(WebInspector.openAnchorLocationRegistry); + p = this._appendSection(WebInspector.UIString("Extensions"), true); + p.appendChild(this._createCustomSetting(WebInspector.UIString("Open links in"), handlerSelector.element)); + } + + var experiments = WebInspector.experimentsSettings.experiments; + if (WebInspector.experimentsSettings.experimentsEnabled && experiments.length) { + var experimentsSection = this._appendSection(WebInspector.UIString("Experiments"), true); + experimentsSection.appendChild(this._createExperimentsWarningSubsection()); + for (var i = 0; i < experiments.length; ++i) + experimentsSection.appendChild(this._createExperimentCheckbox(experiments[i])); + } + + var table = document.createElement("table"); + table.className = "help-table"; + var tr = document.createElement("tr"); + tr.appendChild(this._leftColumnElement); + tr.appendChild(this._rightColumnElement); + table.appendChild(tr); + this.contentElement.appendChild(table); +} + +WebInspector.SettingsScreen.prototype = { + /** + * @param {string} name + * @param {boolean=} right + */ + _appendSection: function(name, right) + { + var p = document.createElement("p"); + p.className = "help-section"; + var title = document.createElement("div"); + title.className = "help-section-title"; + title.textContent = name; + p.appendChild(title); + this._columnElement(right).appendChild(p); + return p; + }, + + /** + * @return {Element} element + */ + _createExperimentsWarningSubsection: function() + { + var subsection = document.createElement("div"); + var warning = subsection.createChild("span", "settings-experiments-warning-subsection-warning"); + warning.textContent = WebInspector.UIString("WARNING:"); + subsection.appendChild(document.createTextNode(" ")); + var message = subsection.createChild("span", "settings-experiments-warning-subsection-message"); + message.textContent = WebInspector.UIString("These experiments could be dangerous and may require restart."); + return subsection; + }, + + _columnElement: function(right) + { + return right ? this._rightColumnElement : this._leftColumnElement; + }, + + _createCheckboxSetting: function(name, setting) + { + var input = document.createElement("input"); + input.type = "checkbox"; + input.name = name; + input.checked = setting.get(); + function listener() + { + setting.set(input.checked); + } + input.addEventListener("click", listener, false); + + var p = document.createElement("p"); + var label = document.createElement("label"); + label.appendChild(input); + label.appendChild(document.createTextNode(name)); + p.appendChild(label); + return p; + }, + + _createExperimentCheckbox: function(experiment) + { + var input = document.createElement("input"); + input.type = "checkbox"; + input.name = experiment.name; + input.checked = experiment.isEnabled(); + function listener() + { + experiment.setEnabled(input.checked); + } + input.addEventListener("click", listener, false); + + var p = document.createElement("p"); + var label = document.createElement("label"); + label.appendChild(input); + label.appendChild(document.createTextNode(WebInspector.UIString(experiment.title))); + p.appendChild(label); + return p; + }, + + _createSelectSetting: function(name, options, setting) + { + var fieldsetElement = document.createElement("fieldset"); + fieldsetElement.createChild("label").textContent = name; + + var select = document.createElement("select"); + var settingValue = setting.get(); + + for (var i = 0; i < options.length; ++i) { + var option = options[i]; + select.add(new Option(option[0], option[1])); + if (settingValue === option[1]) + select.selectedIndex = i; + } + + function changeListener(e) + { + setting.set(e.target.value); + } + + select.addEventListener("change", changeListener, false); + fieldsetElement.appendChild(select); + + var p = document.createElement("p"); + p.appendChild(fieldsetElement); + return p; + }, + + _createRadioSetting: function(name, options, setting) + { + var pp = document.createElement("p"); + var fieldsetElement = document.createElement("fieldset"); + var legendElement = document.createElement("legend"); + legendElement.textContent = name; + fieldsetElement.appendChild(legendElement); + + function clickListener(e) + { + setting.set(e.target.value); + } + + var settingValue = setting.get(); + for (var i = 0; i < options.length; ++i) { + var p = document.createElement("p"); + var label = document.createElement("label"); + p.appendChild(label); + + var input = document.createElement("input"); + input.type = "radio"; + input.name = setting.name; + input.value = options[i][0]; + input.addEventListener("click", clickListener, false); + if (settingValue == input.value) + input.checked = true; + + label.appendChild(input); + label.appendChild(document.createTextNode(options[i][1])); + + fieldsetElement.appendChild(p); + } + + pp.appendChild(fieldsetElement); + return pp; + }, + + _createCustomSetting: function(name, element) + { + var p = document.createElement("p"); + var fieldsetElement = document.createElement("fieldset"); + fieldsetElement.createChild("label").textContent = name; + fieldsetElement.appendChild(element); + p.appendChild(fieldsetElement); + return p; + }, + + _createUserActionControl: function() + { + var userAgent = WebInspector.settings.userAgent.get(); + + var p = document.createElement("p"); + var labelElement = p.createChild("label"); + var checkboxElement = labelElement.createChild("input"); + checkboxElement.type = "checkbox"; + checkboxElement.checked = !!userAgent; + checkboxElement.addEventListener("click", checkboxClicked.bind(this), false); + labelElement.appendChild(document.createTextNode("Override User Agent")); + + var selectSectionElement; + function checkboxClicked() + { + if (checkboxElement.checked) { + selectSectionElement = this._createUserAgentSelectRowElement(); + p.appendChild(selectSectionElement); + } else { + if (selectSectionElement) { + p.removeChild(selectSectionElement); + selectSectionElement = null; + } + WebInspector.settings.userAgent.set(""); + } + } + + checkboxClicked.call(this); + return p; + }, + + _createUserAgentSelectRowElement: function() + { + var userAgent = WebInspector.settings.userAgent.get(); + const userAgents = [ + ["Internet Explorer 9", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)"], + ["Internet Explorer 8", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)"], + ["Internet Explorer 7", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)"], + + ["Firefox 7 \u2014 Windows", "Mozilla/5.0 (Windows NT 6.1; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1"], + ["Firefox 7 \u2014 Mac", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1"], + ["Firefox 4 \u2014 Windows", "Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1"], + ["Firefox 4 \u2014 Mac", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1"], + + ["iPhone \u2014 iOS 5", "Mozilla/5.0 (iPhone; CPU iPhone OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3"], + ["iPhone \u2014 iOS 4", "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_2 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8H7 Safari/6533.18.5"], + ["iPad \u2014 iOS 5", "Mozilla/5.0 (iPad; CPU OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3"], + ["iPad \u2014 iOS 4", "Mozilla/5.0 (iPad; CPU OS 4_3_2 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8H7 Safari/6533.18.5"], + + ["Android 2.3 \u2014 Nexus S", "Mozilla/5.0 (Linux; U; Android 2.3.6; en-us; Nexus S Build/GRK39F) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"], + [WebInspector.UIString("Other..."), "Other"] + ]; + + var fieldsetElement = document.createElement("fieldset"); + var selectElement = fieldsetElement.createChild("select"); + var otherUserAgentElement = fieldsetElement.createChild("input"); + otherUserAgentElement.value = userAgent; + otherUserAgentElement.title = userAgent; + + var selectionRestored = false; + for (var i = 0; i < userAgents.length; ++i) { + var agent = userAgents[i]; + selectElement.add(new Option(agent[0], agent[1])); + if (userAgent === agent[1]) { + selectElement.selectedIndex = i; + selectionRestored = true; + } + } + + if (!selectionRestored) { + if (!userAgent) + selectElement.selectedIndex = 0; + else + selectElement.selectedIndex = userAgents.length - 1; + } + + selectElement.addEventListener("change", selectionChanged.bind(this), false); + + function selectionChanged() + { + var value = selectElement.options[selectElement.selectedIndex].value; + if (value !== "Other") { + WebInspector.settings.userAgent.set(value); + otherUserAgentElement.value = value; + otherUserAgentElement.title = value; + otherUserAgentElement.disabled = true; + } else { + otherUserAgentElement.disabled = false; + otherUserAgentElement.focus(); + } + } + + fieldsetElement.addEventListener("dblclick", textDoubleClicked.bind(this), false); + otherUserAgentElement.addEventListener("blur", textChanged.bind(this), false); + + function textDoubleClicked() + { + selectElement.selectedIndex = userAgents.length - 1; + selectionChanged.call(this); + } + + function textChanged() + { + WebInspector.settings.userAgent.set(otherUserAgentElement.value); + } + + selectionChanged.call(this); + return fieldsetElement; + } +} + +WebInspector.SettingsScreen.prototype.__proto__ = WebInspector.HelpScreen.prototype; +/* ShortcutsScreen.js */ + +/* + * 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. + * * 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. + */ + +/** + * @constructor + * @extends {WebInspector.HelpScreen} + */ +WebInspector.ShortcutsScreen = function() +{ + WebInspector.HelpScreen.call(this, WebInspector.UIString("Keyboard Shortcuts")); + this._sections = {}; + this._tableReady = false; +} + +WebInspector.ShortcutsScreen.prototype = { + section: function(name) + { + var section = this._sections[name]; + if (!section) + this._sections[name] = section = new WebInspector.ShortcutsSection(name); + return section; + }, + + show: function(onHide) + { + this._buildTable(this.contentElement, 2); + WebInspector.HelpScreen.prototype.show.call(this, onHide); + }, + + _buildTable: function(parent, nColumns) + { + if (this._tableReady) + return; + this._tableReady = true; + + var height = 0; + var orderedSections = []; + for (var section in this._sections) { + height += this._sections[section]._height; + orderedSections.push(this._sections[section]) + } + function compareSections(a, b) + { + return a.order - b.order; + } + orderedSections = orderedSections.sort(compareSections); + + const wrapAfter = height / nColumns; + var table = document.createElement("table"); + table.className = "help-table"; + var row = table.createChild("tr"); + + // This manual layout ugliness should be gone once WebKit implements + // pagination hints for CSS columns (break-inside etc). + for (var section = 0; section < orderedSections.length;) { + var td = row.createChild("td"); + td.style.width = (100 / nColumns) + "%"; + var column = td.createChild("table"); + for (var columnHeight = 0; + columnHeight < wrapAfter && section < orderedSections.length; + columnHeight += orderedSections[section]._height, section++) { + orderedSections[section].renderSection(column); + } + } + parent.appendChild(table); + } +} + +WebInspector.ShortcutsScreen.prototype.__proto__ = WebInspector.HelpScreen.prototype; + +/** + * We cannot initialize it here as localized strings are not loaded yet. + * @type {?WebInspector.ShortcutsScreen} + */ +WebInspector.shortcutsScreen = null; + +/** + * @constructor + */ +WebInspector.ShortcutsSection = function(name) +{ + this.name = name; + this._lines = []; + this.order = ++WebInspector.ShortcutsSection._sequenceNumber; +}; + +WebInspector.ShortcutsSection._sequenceNumber = 0; + +WebInspector.ShortcutsSection.prototype = { + addKey: function(key, description) + { + this._addLine(this._renderKey(key), description); + }, + + addRelatedKeys: function(keys, description) + { + this._addLine(this._renderSequence(keys, "/"), description); + }, + + addAlternateKeys: function(keys, description) + { + this._addLine(this._renderSequence(keys, WebInspector.UIString("or")), description); + }, + + _addLine: function(keyElement, description) + { + this._lines.push({ key: keyElement, text: description }) + }, + + renderSection: function(parent) + { + this._renderHeader(parent); + + for (var line = 0; line < this._lines.length; ++line) { + var tr = parent.createChild("tr"); + var td = tr.createChild("td", "help-key-cell"); + td.appendChild(this._lines[line].key); + td.appendChild(document.createTextNode(" : ")); + tr.createChild("td").textContent = this._lines[line].text; + } + }, + + _renderHeader: function(parent) + { + var trHead = parent.createChild("tr"); + + trHead.createChild("th"); + trHead.createChild("th").textContent = this.name; + }, + + _renderSequence: function(sequence, delimiter) + { + var delimiterSpan = this._createSpan("help-key-delimiter", delimiter); + return this._joinNodes(sequence.map(this._renderKey.bind(this)), delimiterSpan); + }, + + _renderKey: function(key) + { + var plus = this._createSpan("help-combine-keys", "+"); + return this._joinNodes(key.split(" + ").map(this._createSpan.bind(this, "help-key monospace")), plus); + }, + + get _height() + { + return this._lines.length + 2; // add some space for header + }, + + _createSpan: function(className, textContent) + { + var node = document.createElement("span"); + node.className = className; + node.textContent = textContent; + return node; + }, + + _joinNodes: function(nodes, delimiter) + { + var result = document.createDocumentFragment(); + for (var i = 0; i < nodes.length; ++i) { + if (i > 0) + result.appendChild(delimiter.cloneNode(true)); + result.appendChild(nodes[i]); + } + return result; + } +} +/* HAREntry.js */ + +/* + * Copyright (C) 2012 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. + */ + +// See http://groups.google.com/group/http-archive-specification/web/har-1-2-spec +// for HAR specification. + +// FIXME: Some fields are not yet supported due to back-end limitations. +// See https://bugs.webkit.org/show_bug.cgi?id=58127 for details. + +/** + * @constructor + * @param {WebInspector.Resource} resource + */ +WebInspector.HAREntry = function(resource) +{ + this._resource = resource; +} + +WebInspector.HAREntry.prototype = { + /** + * @return {Object} + */ + build: function() + { + var entry = { + startedDateTime: new Date(this._resource.startTime * 1000), + time: WebInspector.HAREntry._toMilliseconds(this._resource.duration), + request: this._buildRequest(), + response: this._buildResponse(), + cache: { }, // Not supported yet. + timings: this._buildTimings() + }; + var page = WebInspector.networkLog.pageLoadForResource(this._resource); + if (page) + entry.pageref = "page_" + page.id; + return entry; + }, + + /** + * @return {Object} + */ + _buildRequest: function() + { + var res = { + method: this._resource.requestMethod, + url: this._buildRequestURL(this._resource.url), + httpVersion: this._resource.requestHttpVersion, + headers: this._buildHeaders(this._resource.requestHeaders), + queryString: this._buildParameters(this._resource.queryParameters || []), + cookies: this._buildCookies(this._resource.requestCookies || []), + headersSize: this._resource.requestHeadersSize, + bodySize: this.requestBodySize + }; + if (this._resource.requestFormData) + res.postData = this._buildPostData(); + + return res; + }, + + /** + * @return {Object} + */ + _buildResponse: function() + { + return { + status: this._resource.statusCode, + statusText: this._resource.statusText, + httpVersion: this._resource.responseHttpVersion, + headers: this._buildHeaders(this._resource.responseHeaders), + cookies: this._buildCookies(this._resource.responseCookies || []), + content: this._buildContent(), + redirectURL: this._resource.responseHeaderValue("Location") || "", + headersSize: this._resource.responseHeadersSize, + bodySize: this.responseBodySize + }; + }, + + /** + * @return {Object} + */ + _buildContent: function() + { + var content = { + size: this._resource.resourceSize, + mimeType: this._resource.mimeType, + // text: this._resource.content // TODO: pull out into a boolean flag, as content can be huge (and needs to be requested with an async call) + }; + var compression = this.responseCompression; + if (typeof compression === "number") + content.compression = compression; + return content; + }, + + /** + * @return {Object} + */ + _buildTimings: function() + { + var waitForConnection = this._interval("connectStart", "connectEnd"); + var blocked; + var connect; + var dns = this._interval("dnsStart", "dnsEnd"); + var send = this._interval("sendStart", "sendEnd"); + var ssl = this._interval("sslStart", "sslEnd"); + + if (ssl !== -1 && send !== -1) + send -= ssl; + + if (this._resource.connectionReused) { + connect = -1; + blocked = waitForConnection; + } else { + blocked = 0; + connect = waitForConnection; + if (dns !== -1) + connect -= dns; + } + + return { + blocked: blocked, + dns: dns, + connect: connect, + send: send, + wait: this._interval("sendEnd", "receiveHeadersEnd"), + receive: WebInspector.HAREntry._toMilliseconds(this._resource.receiveDuration), + ssl: ssl + }; + }, + + /** + * @return {Object} + */ + _buildHeaders: function(headers) + { + var result = []; + for (var name in headers) + result.push({ name: name, value: headers[name] }); + return result; + }, + + /** + * @return {Object} + */ + _buildPostData: function() + { + var res = { + mimeType: this._resource.requestHeaderValue("Content-Type"), + text: this._resource.requestFormData + }; + if (this._resource.formParameters) + res.params = this._buildParameters(this._resource.formParameters); + return res; + }, + + /** + * @param {Array.} parameters + * @return {Array.} + */ + _buildParameters: function(parameters) + { + return parameters.slice(); + }, + + /** + * @param {string} url + * @return {string} + */ + _buildRequestURL: function(url) + { + return url.split("#", 2)[0]; + }, + + /** + * @param {Array.} cookies + * @return {Array.} + */ + _buildCookies: function(cookies) + { + return cookies.map(this._buildCookie.bind(this)); + }, + + /** + * @param {WebInspector.Cookie} cookie + * @return {Object} + */ + _buildCookie: function(cookie) + { + return { + name: cookie.name, + value: cookie.value, + path: cookie.path, + domain: cookie.domain, + expires: cookie.expires(new Date(this._resource.startTime * 1000)), + httpOnly: cookie.httpOnly, + secure: cookie.secure + }; + }, + + /** + * @param {string} start + * @param {string} end + * @return {number} + */ + _interval: function(start, end) + { + var timing = this._resource.timing; + if (!timing) + return -1; + var startTime = timing[start]; + return typeof startTime !== "number" || startTime === -1 ? -1 : Math.round(timing[end] - startTime); + }, + + /** + * @return {number} + */ + get requestBodySize() + { + return !this._resource.requestFormData ? 0 : this._resource.requestFormData.length; + }, + + /** + * @return {number} + */ + get responseBodySize() + { + if (this._resource.cached || this._resource.statusCode === 304) + return 0; + return this._resource.transferSize - this._resource.responseHeadersSize + }, + + /** + * @return {number|undefined} + */ + get responseCompression() + { + if (this._resource.cached || this._resource.statusCode === 304) + return; + return this._resource.resourceSize - (this._resource.transferSize - this._resource.responseHeadersSize); + } +} + +/** + * @param {number} time + * @return {number} + */ +WebInspector.HAREntry._toMilliseconds = function(time) +{ + return time === -1 ? -1 : Math.round(time * 1000); +} + +/** + * @constructor + * @param {Array.} resources + */ +WebInspector.HARLog = function(resources) +{ + this._resources = resources; +} + +WebInspector.HARLog.prototype = { + /** + * @return {Object} + */ + build: function() + { + var webKitVersion = /AppleWebKit\/([^ ]+)/.exec(window.navigator.userAgent); + + return { + version: "1.2", + creator: { + name: "WebInspector", + version: webKitVersion ? webKitVersion[1] : "n/a" + }, + pages: this._buildPages(), + entries: this._resources.map(this._convertResource.bind(this)) + } + }, + + /** + * @return {Array} + */ + _buildPages: function() + { + var seenIdentifiers = {}; + var pages = []; + for (var i = 0; i < this._resources.length; ++i) { + var page = WebInspector.networkLog.pageLoadForResource(this._resources[i]); + if (!page || seenIdentifiers[page.id]) + continue; + seenIdentifiers[page.id] = true; + pages.push(this._convertPage(page)); + } + return pages; + }, + + /** + * @param {WebInspector.PageLoad} page + * @return {Object} + */ + _convertPage: function(page) + { + return { + startedDateTime: new Date(page.startTime * 1000), + id: "page_" + page.id, + title: page.url, // We don't have actual page title here. URL is probably better than nothing. + pageTimings: { + onContentLoad: this._pageEventTime(page, page.contentLoadTime), + onLoad: this._pageEventTime(page, page.loadTime) + } + } + }, + + /** + * @param {WebInspector.Resource} resource + * @return {Object} + */ + _convertResource: function(resource) + { + return (new WebInspector.HAREntry(resource)).build(); + }, + + /** + * @param {WebInspector.PageLoad} page + * @param {number} time + * @return {number} + */ + _pageEventTime: function(page, time) + { + var startTime = page.startTime; + if (time === -1 || startTime === -1) + return -1; + return WebInspector.HAREntry._toMilliseconds(time - startTime); + } +} +/* CookieParser.js */ + +/* + * 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. + * * 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. + */ + +// Ideally, we would rely on platform support for parsing a cookie, since +// this would save us from any potential inconsistency. However, exposing +// platform cookie parsing logic would require quite a bit of additional +// plumbing, and at least some platforms lack support for parsing Cookie, +// which is in a format slightly different from Set-Cookie and is normally +// only required on the server side. + +/** + * @constructor + */ +WebInspector.CookieParser = function() +{ +} + +/** + * @constructor + * @param {string} key + * @param {string|undefined} value + * @param {number} position + */ +WebInspector.CookieParser.KeyValue = function(key, value, position) +{ + this.key = key; + this.value = value; + this.position = position; +} + +WebInspector.CookieParser.prototype = { + /** + * @return {Array.} + */ + get cookies() + { + return this._cookies; + }, + + /** + * @param {string|undefined} cookieHeader + * @return {?Array.} + */ + parseCookie: function(cookieHeader) + { + if (!this._initialize(cookieHeader)) + return null; + + for (var kv = this._extractKeyValue(); kv; kv = this._extractKeyValue()) { + if (kv.key.charAt(0) === "$" && this._lastCookie) + this._lastCookie.addAttribute(kv.key.slice(1), kv.value); + else if (kv.key.toLowerCase() !== "$version" && typeof kv.value === "string") + this._addCookie(kv, WebInspector.Cookie.Type.Request); + this._advanceAndCheckCookieDelimiter(); + } + this._flushCookie(); + return this._cookies; + }, + + /** + * @param {string|undefined} setCookieHeader + * @return {?Array.} + */ + parseSetCookie: function(setCookieHeader) + { + if (!this._initialize(setCookieHeader)) + return null; + for (var kv = this._extractKeyValue(); kv; kv = this._extractKeyValue()) { + if (this._lastCookie) + this._lastCookie.addAttribute(kv.key, kv.value); + else + this._addCookie(kv, WebInspector.Cookie.Type.Response); + if (this._advanceAndCheckCookieDelimiter()) + this._flushCookie(); + } + this._flushCookie(); + return this._cookies; + }, + + /** + * @param {string|undefined} headerValue + * @return {boolean} + */ + _initialize: function(headerValue) + { + this._input = headerValue; + if (typeof headerValue !== "string") + return false; + this._cookies = []; + this._lastCookie = null; + this._originalInputLength = this._input.length; + return true; + }, + + _flushCookie: function() + { + if (this._lastCookie) + this._lastCookie.size = this._originalInputLength - this._input.length - this._lastCookiePosition; + this._lastCookie = null; + }, + + /** + * @return {WebInspector.CookieParser.KeyValue} + */ + _extractKeyValue: function() + { + if (!this._input || !this._input.length) + return null; + // Note: RFCs offer an option for quoted values that may contain commas and semicolons. + // Many browsers/platforms do not support this, however (see http://webkit.org/b/16699 + // and http://crbug.com/12361). The logic below matches latest versions of IE, Firefox, + // Chrome and Safari on some old platforms. The latest version of Safari supports quoted + // cookie values, though. + var keyValueMatch = /^[ \t]*([^\s=;]+)[ \t]*(?:=[ \t]*([^;\n]*))?/.exec(this._input); + if (!keyValueMatch) { + console.log("Failed parsing cookie header before: " + this._input); + return null; + } + + var result = new WebInspector.CookieParser.KeyValue(keyValueMatch[1], keyValueMatch[2] && keyValueMatch[2].trim(), this._originalInputLength - this._input.length); + this._input = this._input.slice(keyValueMatch[0].length); + return result; + }, + + /** + * @return {boolean} + */ + _advanceAndCheckCookieDelimiter: function() + { + var match = /^\s*[\n;]\s*/.exec(this._input); + if (!match) + return false; + this._input = this._input.slice(match[0].length); + return match[0].match("\n") !== null; + }, + + /** + * @param {WebInspector.CookieParser.KeyValue} keyValue + * @param {number} type + */ + _addCookie: function(keyValue, type) + { + if (this._lastCookie) + this._lastCookie.size = keyValue.position - this._lastCookiePosition; + // Mozilla bug 169091: Mozilla, IE and Chrome treat single token (w/o "=") as + // specifying a value for a cookie with empty name. + this._lastCookie = keyValue.value ? new WebInspector.Cookie(keyValue.key, keyValue.value, type) : + new WebInspector.Cookie("", keyValue.key, type); + this._lastCookiePosition = keyValue.position; + this._cookies.push(this._lastCookie); + } +}; + +/** + * @param {string|undefined} header + * @return {?Array.} + */ +WebInspector.CookieParser.parseCookie = function(header) +{ + return (new WebInspector.CookieParser()).parseCookie(header); +} + +/** + * @param {string|undefined} header + * @return {?Array.} + */ +WebInspector.CookieParser.parseSetCookie = function(header) +{ + return (new WebInspector.CookieParser()).parseSetCookie(header); +} + +/** + * @constructor + */ +WebInspector.Cookie = function(name, value, type) +{ + this.name = name; + this.value = value; + this.type = type; + this._attributes = {}; +} + +WebInspector.Cookie.prototype = { + /** + * @return {boolean} + */ + get httpOnly() + { + return "httponly" in this._attributes; + }, + + /** + * @return {boolean} + */ + get secure() + { + return "secure" in this._attributes; + }, + + /** + * @return {boolean} + */ + get session() + { + // RFC 2965 suggests using Discard attribute to mark session cookies, but this does not seem to be widely used. + // Check for absence of explicity max-age or expiry date instead. + return !("expries" in this._attributes || "max-age" in this._attributes); + }, + + /** + * @return {string} + */ + get path() + { + return this._attributes["path"]; + }, + + /** + * @return {string} + */ + get domain() + { + return this._attributes["domain"]; + }, + + /** + * @return {Date} + */ + expires: function(requestDate) + { + return this._attributes["expires"] ? new Date(this._attributes["expires"]) : + (this._attributes["max-age"] ? new Date(requestDate.getTime() + 1000 * this._attributes["max-age"]) : null); + }, + + /** + * @return {Object} + */ + get attributes() + { + return this._attributes; + }, + + /** + * @param {string} key + * @param {string} value + */ + addAttribute: function(key, value) + { + this._attributes[key.toLowerCase()] = value; + } +} + +WebInspector.Cookie.Type = { + Request: 0, + Response: 1 +}; +/* Toolbar.js */ + + /* + * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2007 Matt Lilek (pewtermoose@gmail.com). + * Copyright (C) 2009 Joseph Pecoraro + * Copyright (C) 2011 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: + * + * 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. + */ + +/** + * @constructor + */ +WebInspector.Toolbar = function() +{ + this.element = document.getElementById("toolbar"); + this.element.addEventListener("mousedown", this._toolbarDragStart.bind(this), true); + + this._dropdownButton = document.getElementById("toolbar-dropdown-arrow"); + this._dropdownButton.addEventListener("click", this._toggleDropdown.bind(this), false); + + document.getElementById("close-button-left").addEventListener("click", this._onClose, true); + document.getElementById("close-button-right").addEventListener("click", this._onClose, true); +} + +WebInspector.Toolbar.prototype = { + set compact(compact) + { + if (compact) + this.element.addStyleClass("toolbar-small"); + else + this.element.removeStyleClass("toolbar-small"); + this._updateDropdownButtonAndHideDropdown(); + }, + + resize: function() + { + this._updateDropdownButtonAndHideDropdown(); + }, + + addPanel: function(panel) + { + this.element.appendChild(panel.toolbarItem); + this.resize(); + }, + + _toolbarDragStart: function(event) + { + if ((!WebInspector.isCompactMode() && WebInspector.platformFlavor() !== WebInspector.PlatformFlavor.MacLeopard && WebInspector.platformFlavor() !== WebInspector.PlatformFlavor.MacSnowLeopard) || WebInspector.port() == "qt") + return; + + var target = event.target; + if (target.hasStyleClass("toolbar-item") && target.hasStyleClass("toggleable")) + return; + + if (target !== this.element && !target.hasStyleClass("toolbar-item")) + return; + + this.element.lastScreenX = event.screenX; + this.element.lastScreenY = event.screenY; + + WebInspector.elementDragStart(this.element, this._toolbarDrag.bind(this), this._toolbarDragEnd.bind(this), event, (WebInspector.isCompactMode() ? "row-resize" : "default")); + }, + + _toolbarDragEnd: function(event) + { + WebInspector.elementDragEnd(event); + + delete this.element.lastScreenX; + delete this.element.lastScreenY; + }, + + _toolbarDrag: function(event) + { + if (WebInspector.isCompactMode()) { + var height = window.innerHeight - (event.screenY - this.element.lastScreenY); + + InspectorFrontendHost.setAttachedWindowHeight(height); + } else { + var x = event.screenX - this.element.lastScreenX; + var y = event.screenY - this.element.lastScreenY; + + // We cannot call window.moveBy here because it restricts the movement + // of the window at the edges. + InspectorFrontendHost.moveWindowBy(x, y); + } + + this.element.lastScreenX = event.screenX; + this.element.lastScreenY = event.screenY; + + event.preventDefault(); + }, + + _onClose: function() + { + WebInspector.close(); + }, + + _setDropdownVisible: function(visible) + { + if (!this._dropdown) { + if (!visible) + return; + this._dropdown = new WebInspector.ToolbarDropdown(); + } + if (visible) + this._dropdown.show(); + else + this._dropdown.hide(); + }, + + _toggleDropdown: function() + { + this._setDropdownVisible(!this._dropdown || !this._dropdown.visible); + }, + + _updateDropdownButtonAndHideDropdown: function() + { + this._setDropdownVisible(false); + + var toolbar = document.getElementById("toolbar"); + if (this.element.scrollHeight > this.element.clientHeight) + this._dropdownButton.removeStyleClass("hidden"); + else + this._dropdownButton.addStyleClass("hidden"); + } +} + +WebInspector.Toolbar.createPanelToolbarItem = function(panel) +{ + var toolbarItem = document.createElement("button"); + toolbarItem.className = "toolbar-item toggleable"; + toolbarItem.panel = panel; + toolbarItem.addStyleClass(panel._panelName); + function onToolbarItemClicked() + { + WebInspector.toolbar._updateDropdownButtonAndHideDropdown(); + WebInspector.inspectorView.setCurrentPanel(panel); + } + toolbarItem.addEventListener("click", onToolbarItemClicked, false); + + var iconElement = toolbarItem.createChild("div", "toolbar-icon"); + + if ("toolbarItemLabel" in panel) + toolbarItem.createChild("div", "toolbar-label").textContent = panel.toolbarItemLabel; + + if (panel === WebInspector.inspectorView.currentPanel()) + toolbarItem.addStyleClass("toggled-on"); + + return toolbarItem; +} + +/** + * @constructor + */ +WebInspector.ToolbarDropdown = function() +{ + this._toolbar = document.getElementById("toolbar"); + this._arrow = document.getElementById("toolbar-dropdown-arrow"); + this.element = document.createElement("div"); + this.element.id = "toolbar-dropdown"; + this.element.className = "toolbar-small"; + this._contentElement = this.element.createChild("div", "scrollable-content"); + this._contentElement.tabIndex = 0; + this._contentElement.addEventListener("keydown", this._onKeyDown.bind(this), true); +} + +WebInspector.ToolbarDropdown.prototype = { + show: function() + { + if (this.visible) + return; + var style = this.element.style; + this._populate(); + var top = this._arrow.totalOffsetTop() + this._arrow.clientHeight; + this._arrow.addStyleClass("dropdown-visible"); + this.element.style.top = top + "px"; + this.element.style.left = this._arrow.totalOffsetLeft() + "px"; + this._contentElement.style.maxHeight = window.innerHeight - top - 20 + "px"; + this._toolbar.appendChild(this.element); + }, + + hide: function() + { + if (!this.visible) + return; + this._arrow.removeStyleClass("dropdown-visible"); + this.element.parentNode.removeChild(this.element); + this._contentElement.removeChildren(); + }, + + get visible() + { + return !!this.element.parentNode; + }, + + _populate: function() + { + var toolbarItems = this._toolbar.querySelectorAll(".toolbar-item.toggleable"); + + for (var i = 0; i < toolbarItems.length; ++i) { + if (toolbarItems[i].offsetTop > 0) + this._contentElement.appendChild(WebInspector.Toolbar.createPanelToolbarItem(toolbarItems[i].panel)); + } + }, + + _onKeyDown: function(event) + { + if (event.keyCode !== WebInspector.KeyboardShortcut.Keys.Esc.code) + return; + event.stopPropagation(); + this.hide(); + } +} + +/** + * @type {?WebInspector.Toolbar} + */ +WebInspector.toolbar = null; +/* SearchController.js */ + +/* + * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2007 Matt Lilek (pewtermoose@gmail.com). + * Copyright (C) 2009 Joseph Pecoraro + * Copyright (C) 2011 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: + * + * 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. + */ + +/** + * @constructor + */ +WebInspector.SearchController = function() +{ + this.element = document.getElementById("search"); + this._matchesElement = document.getElementById("search-results-matches"); + this._toolbarLabelElement = document.getElementById("search-toolbar-label"); + + this.element.addEventListener("search", this._onSearch.bind(this), false); // when the search is emptied + this.element.addEventListener("mousedown", this._onSearchFieldManualFocus.bind(this), false); // when the search field is manually selected + this.element.addEventListener("keydown", this._onKeyDown.bind(this), true); +} + +WebInspector.SearchController.prototype = { + updateSearchMatchesCount: function(matches, panel) + { + if (!panel) + panel = WebInspector.inspectorView.currentPanel(); + + panel.currentSearchMatches = matches; + + if (panel === WebInspector.inspectorView.currentPanel()) + this._updateSearchMatchesCountAndCurrentMatchIndex(WebInspector.inspectorView.currentPanel().currentQuery && matches); + }, + + updateCurrentMatchIndex: function(currentMatchIndex, panel) + { + if (panel === WebInspector.inspectorView.currentPanel()) + this._updateSearchMatchesCountAndCurrentMatchIndex(panel.currentSearchMatches, currentMatchIndex); + }, + + updateSearchLabel: function() + { + var panelName = WebInspector.inspectorView.currentPanel() && WebInspector.inspectorView.currentPanel().toolbarItemLabel; + if (!panelName) + return; + var newLabel = WebInspector.UIString("Search %s", panelName); + if (WebInspector.isCompactMode()) + this.element.setAttribute("placeholder", newLabel); + else { + this.element.removeAttribute("placeholder"); + this._toolbarLabelElement.textContent = newLabel; + } + }, + + cancelSearch: function() + { + this.element.value = ""; + this._performSearch(""); + }, + + disableSearchUntilExplicitAction: function(event) + { + this._performSearch(""); + }, + + handleShortcut: function(event) + { + var isMac = WebInspector.isMac(); + + switch (event.keyIdentifier) { + case "U+0046": // F key + if (isMac) + var isFindKey = event.metaKey && !event.ctrlKey && !event.altKey && !event.shiftKey; + else + var isFindKey = event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey; + + if (isFindKey) { + this.focusSearchField(); + event.handled = true; + } + break; + + + case "F3": + if (!isMac) { + this.focusSearchField(); + event.handled = true; + } + break; + + case "U+0047": // G key + var currentPanel = WebInspector.inspectorView.currentPanel(); + + if (isMac && event.metaKey && !event.ctrlKey && !event.altKey) { + if (event.shiftKey) { + if (currentPanel.jumpToPreviousSearchResult) + currentPanel.jumpToPreviousSearchResult(); + } else if (currentPanel.jumpToNextSearchResult) + currentPanel.jumpToNextSearchResult(); + event.handled = true; + } + break; + } + }, + + activePanelChanged: function() + { + this.updateSearchLabel(); + + if (!this._currentQuery) + return; + + var panel = WebInspector.inspectorView.currentPanel(); + if (panel.performSearch) { + function performPanelSearch() + { + this._updateSearchMatchesCountAndCurrentMatchIndex(); + + panel.currentQuery = this._currentQuery; + panel.performSearch(this._currentQuery); + } + + // Perform the search on a timeout so the panel switches fast. + setTimeout(performPanelSearch.bind(this), 0); + } else { + // Update to show Not found for panels that can't be searched. + this._updateSearchMatchesCountAndCurrentMatchIndex(); + } + }, + + /** + * @param {?number=} matches + * @param {number=} currentMatchIndex + */ + _updateSearchMatchesCountAndCurrentMatchIndex: function(matches, currentMatchIndex) + { + if (matches == null) { + this._matchesElement.addStyleClass("hidden"); + return; + } + + if (matches) { + if (matches === 1) { + if (currentMatchIndex === 0) + var matchesString = WebInspector.UIString("1 of 1 match"); + else + var matchesString = WebInspector.UIString("1 match"); + } else { + if (typeof currentMatchIndex === "number") + var matchesString = WebInspector.UIString("%d of %d matches", currentMatchIndex + 1, matches); + else + var matchesString = WebInspector.UIString("%d matches", matches); + } + } else + var matchesString = WebInspector.UIString("Not Found"); + + this._matchesElement.removeStyleClass("hidden"); + this._matchesElement.textContent = matchesString; + WebInspector.toolbar.resize(); + }, + + focusSearchField: function() + { + this.element.focus(); + this.element.select(); + }, + + _onSearchFieldManualFocus: function(event) + { + WebInspector.setCurrentFocusElement(event.target); + }, + + _onKeyDown: function(event) + { + // Escape Key will clear the field and clear the search results + if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Esc.code) { + // If focus belongs here and text is empty - nothing to do, return unhandled. + // When search was selected manually and is currently blank, we'd like Esc stay unhandled + // and hit console drawer handler. + if (event.target.value === "" && WebInspector.currentFocusElement() === WebInspector.previousFocusElement()) + return; + event.preventDefault(); + event.stopPropagation(); + + this.cancelSearch(); + WebInspector.setCurrentFocusElement(WebInspector.previousFocusElement()); + if (WebInspector.currentFocusElement() === event.target) + WebInspector.currentFocusElement().select(); + return false; + } + + if (!isEnterKey(event)) + return false; + + // Select all of the text so the user can easily type an entirely new query. + event.target.select(); + + // Only call performSearch if the Enter key was pressed. Otherwise the search + // performance is poor because of searching on every key. The search field has + // the incremental attribute set, so we still get incremental searches. + this._onSearch(event); + + // Call preventDefault since this was the Enter key. This prevents a "search" event + // from firing for key down. This stops performSearch from being called twice in a row. + event.preventDefault(); + }, + + _onSearch: function(event) + { + var forceSearch = event.keyIdentifier === "Enter"; + this._performSearch(event.target.value, forceSearch, event.shiftKey, false); + }, + + /** + * @param {boolean=} forceSearch + * @param {boolean=} isBackwardSearch + * @param {boolean=} repeatSearch + */ + _performSearch: function(query, forceSearch, isBackwardSearch, repeatSearch) + { + var isShortSearch = (query.length < 3); + + // Clear a leftover short search flag due to a non-conflicting forced search. + if (isShortSearch && this._shortSearchWasForcedByKeyEvent && this._currentQuery !== query) + delete this._shortSearchWasForcedByKeyEvent; + + // Indicate this was a forced search on a short query. + if (isShortSearch && forceSearch) + this._shortSearchWasForcedByKeyEvent = true; + + if (!query || !query.length || (!forceSearch && isShortSearch)) { + // Prevent clobbering a short search forced by the user. + if (this._shortSearchWasForcedByKeyEvent) { + delete this._shortSearchWasForcedByKeyEvent; + return; + } + + delete this._currentQuery; + + for (var panelName in WebInspector.panels) { + var panel = WebInspector.panels[panelName]; + var hadCurrentQuery = !!panel.currentQuery; + delete panel.currentQuery; + if (hadCurrentQuery && panel.searchCanceled) + panel.searchCanceled(); + } + + this._updateSearchMatchesCountAndCurrentMatchIndex(); + + return; + } + + var currentPanel = WebInspector.inspectorView.currentPanel(); + if (!repeatSearch && query === currentPanel.currentQuery && currentPanel.currentQuery === this._currentQuery) { + // When this is the same query and a forced search, jump to the next + // search result for a good user experience. + if (forceSearch) { + if (!isBackwardSearch && currentPanel.jumpToNextSearchResult) + currentPanel.jumpToNextSearchResult(); + else if (isBackwardSearch && currentPanel.jumpToPreviousSearchResult) + currentPanel.jumpToPreviousSearchResult(); + } + return; + } + + this._currentQuery = query; + + this._updateSearchMatchesCountAndCurrentMatchIndex(); + + if (!currentPanel.performSearch) + return; + + currentPanel.currentQuery = query; + currentPanel.performSearch(query); + } +} + +/** + * @type {?WebInspector.SearchController} + */ +WebInspector.searchController = null; +/* WorkerManager.js */ + +/* + * Copyright (C) 2011 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. + */ + +/** + * @constructor + * @extends {WebInspector.Object} + */ +WebInspector.WorkerManager = function() +{ + this._workerIdToWindow = {}; + InspectorBackend.registerWorkerDispatcher(new WebInspector.WorkerDispatcher(this)); +} + +WebInspector.WorkerManager.isWorkerFrontend = function() +{ + return !!WebInspector.queryParamsObject["dedicatedWorkerId"] || + !!WebInspector.queryParamsObject["isSharedWorker"]; +} + +WebInspector.WorkerManager.loaded = function() +{ + var workerId = WebInspector.queryParamsObject["dedicatedWorkerId"]; + if (workerId) + WebInspector.WorkerManager._initializeDedicatedWorkerFrontend(workerId); + else + WebInspector.workerManager = new WebInspector.WorkerManager(); +} + +WebInspector.WorkerManager.loadCompleted = function() +{ + // Make sure script execution of dedicated worker is resumed and then paused + // on the first script statement in case we autoattached to it. + if (WebInspector.queryParamsObject["workerPaused"]) { + DebuggerAgent.pause(); + RuntimeAgent.run(calculateTitle); + } else if (WebInspector.WorkerManager.isWorkerFrontend()) + calculateTitle(); + + function calculateTitle() + { + WebInspector.WorkerManager._calculateWorkerInspectorTitle(); + } + + if (WebInspector.workerManager) + WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, WebInspector.workerManager._mainFrameNavigated, WebInspector.workerManager); +} + +WebInspector.WorkerManager._initializeDedicatedWorkerFrontend = function(workerId) +{ + function receiveMessage(event) + { + var message = event.data; + InspectorBackend.dispatch(message); + } + window.addEventListener("message", receiveMessage, true); + + + InspectorBackend.sendMessageObjectToBackend = function(message) + { + window.opener.postMessage({workerId: workerId, command: "sendMessageToBackend", message: message}, "*"); + } + + InspectorFrontendHost.loaded = function() + { + window.opener.postMessage({workerId: workerId, command: "loaded"}, "*"); + } +} + +WebInspector.WorkerManager._calculateWorkerInspectorTitle = function() +{ + var expression = "location.href"; + if (WebInspector.queryParamsObject["isSharedWorker"]) + expression += " + (this.name ? ' (' + this.name + ')' : '')"; + RuntimeAgent.evaluate.invoke({expression:expression, doNotPauseOnExceptions:true, returnByValue: true}, evalCallback.bind(this)); + function evalCallback(error, result, wasThrown) + { + if (error || wasThrown) { + console.error(error); + return; + } + InspectorFrontendHost.inspectedURLChanged(result.value); + } +} + +WebInspector.WorkerManager.Events = { + WorkerAdded: "worker-added", + WorkerRemoved: "worker-removed", + WorkersCleared: "workers-cleared", +} + +WebInspector.WorkerManager.prototype = { + _workerCreated: function(workerId, url, inspectorConnected) + { + if (inspectorConnected) + this._openInspectorWindow(workerId, true); + this.dispatchEventToListeners(WebInspector.WorkerManager.Events.WorkerAdded, {workerId: workerId, url: url, inspectorConnected: inspectorConnected}); + }, + + _workerTerminated: function(workerId) + { + this.closeWorkerInspector(workerId); + this.dispatchEventToListeners(WebInspector.WorkerManager.Events.WorkerRemoved, workerId); + }, + + _sendMessageToWorkerInspector: function(workerId, message) + { + var workerInspectorWindow = this._workerIdToWindow[workerId]; + if (workerInspectorWindow) + workerInspectorWindow.postMessage(message, "*"); + }, + + openWorkerInspector: function(workerId) + { + var existingInspector = this._workerIdToWindow[workerId]; + if (existingInspector) { + existingInspector.focus(); + return; + } + + this._openInspectorWindow(workerId, false); + WorkerAgent.connectToWorker(workerId); + }, + + _openInspectorWindow: function(workerId, workerIsPaused) + { + var url = window.location.href + "&dedicatedWorkerId=" + workerId; + if (workerIsPaused) + url += "&workerPaused=true"; + url = url.replace("docked=true&", ""); + // Set location=0 just to make sure the front-end will be opened in a separate window, not in new tab. + var workerInspectorWindow = window.open(url, undefined, "location=0"); + this._workerIdToWindow[workerId] = workerInspectorWindow; + workerInspectorWindow.addEventListener("beforeunload", this._workerInspectorClosing.bind(this, workerId), true); + + // Listen to beforeunload in detached state and to the InspectorClosing event in case of attached inspector. + window.addEventListener("beforeunload", this._pageInspectorClosing.bind(this), true); + WebInspector.notifications.addEventListener(WebInspector.Events.InspectorClosing, this._pageInspectorClosing, this); + }, + + closeWorkerInspector: function(workerId) + { + var workerInspectorWindow = this._workerIdToWindow[workerId]; + if (workerInspectorWindow) + workerInspectorWindow.close(); + }, + + _mainFrameNavigated: function(event) + { + for (var workerId in this._workerIdToWindow) + this.closeWorkerInspector(workerId); + this.dispatchEventToListeners(WebInspector.WorkerManager.Events.WorkersCleared); + }, + + _pageInspectorClosing: function() + { + this._ignoreWorkerInspectorClosing = true; + for (var workerId in this._workerIdToWindow) { + this._workerIdToWindow[workerId].close(); + WorkerAgent.disconnectFromWorker(parseInt(workerId, 10)); + } + }, + + _workerInspectorClosing: function(workerId, event) + { + if (this._ignoreWorkerInspectorClosing) + return; + delete this._workerIdToWindow[workerId]; + WorkerAgent.disconnectFromWorker(workerId); + }, + + _disconnectedFromWorker: function() + { + function onHide() + { + WebInspector.debuggerModel.removeEventListener(WebInspector.DebuggerModel.Events.GlobalObjectCleared, screen.hide, screen); + } + var screen = new WebInspector.WorkerTerminatedScreen(); + WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.GlobalObjectCleared, screen.hide, screen); + screen.show(onHide.bind(this)); + } +} + +WebInspector.WorkerManager.prototype.__proto__ = WebInspector.Object.prototype; + +/** + * @constructor + * @implements {WorkerAgent.Dispatcher} + */ +WebInspector.WorkerDispatcher = function(workerManager) +{ + this._workerManager = workerManager; + window.addEventListener("message", this._receiveMessage.bind(this), true); +} + +WebInspector.WorkerDispatcher.prototype = { + _receiveMessage: function(event) + { + var workerId = event.data["workerId"]; + workerId = parseInt(workerId, 10); + var command = event.data.command; + var message = event.data.message; + + if (command == "sendMessageToBackend") + WorkerAgent.sendMessageToWorker(workerId, message); + }, + + workerCreated: function(workerId, url, inspectorConnected) + { + this._workerManager._workerCreated(workerId, url, inspectorConnected); + }, + + workerTerminated: function(workerId) + { + this._workerManager._workerTerminated(workerId); + }, + + dispatchMessageFromWorker: function(workerId, message) + { + this._workerManager._sendMessageToWorkerInspector(workerId, message); + }, + + disconnectedFromWorker: function() + { + this._workerManager._disconnectedFromWorker(); + } +} + +/** + * @constructor + * @extends {WebInspector.HelpScreen} + */ +WebInspector.WorkerTerminatedScreen = function() +{ + WebInspector.HelpScreen.call(this, WebInspector.UIString("Inspected worker terminated")); + var p = this.contentElement.createChild("p"); + p.addStyleClass("help-section"); + p.textContent = WebInspector.UIString("Inspected worker has terminated. Once it restarts we will attach to it automatically."); +} + +WebInspector.WorkerTerminatedScreen.prototype.__proto__ = WebInspector.HelpScreen.prototype; +/* UserMetrics.js */ + +/* + * Copyright (C) 2011 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. + */ + +/** + * @constructor + */ +WebInspector.UserMetrics = function() +{ + for (var actionName in WebInspector.UserMetrics._ActionCodes) { + var actionCode = WebInspector.UserMetrics._ActionCodes[actionName]; + this[actionName] = new WebInspector.UserMetrics._Recorder(actionCode); + } + + function settingChanged(trueCode, falseCode, event) + { + if (event.data) + InspectorFrontendHost.recordSettingChanged(trueCode); + else + InspectorFrontendHost.recordSettingChanged(falseCode); + } + + WebInspector.settings.domWordWrap.addChangeListener(settingChanged.bind(this, WebInspector.UserMetrics._SettingCodes.ElementsDOMWrapOn, WebInspector.UserMetrics._SettingCodes.ElementsDOMWrapOff)); + WebInspector.settings.monitoringXHREnabled.addChangeListener(settingChanged.bind(this, WebInspector.UserMetrics._SettingCodes.ConsoleMonitorXHROn, WebInspector.UserMetrics._SettingCodes.ConsoleMonitorXHROff)); + WebInspector.settings.preserveConsoleLog.addChangeListener(settingChanged.bind(this, WebInspector.UserMetrics._SettingCodes.ConsolePreserveLogOn, WebInspector.UserMetrics._SettingCodes.ConsolePreserveLogOff)); + WebInspector.settings.resourcesLargeRows.addChangeListener(settingChanged.bind(this, WebInspector.UserMetrics._SettingCodes.NetworkShowLargeRowsOn, WebInspector.UserMetrics._SettingCodes.NetworkShowLargeRowsOff)); +} + +// Codes below are used to collect UMA histograms in the Chromium port. +// Do not change the values below, additional actions are needed on the Chromium side +// in order to add more codes. + +WebInspector.UserMetrics._ActionCodes = { + WindowDocked: 1, + WindowUndocked: 2, + ScriptsBreakpointSet: 3, + TimelineStarted: 4, + ProfilesCPUProfileTaken: 5, + ProfilesHeapProfileTaken: 6, + AuditsStarted: 7, + ConsoleEvaluated: 8 +} + +WebInspector.UserMetrics._SettingCodes = { + ElementsDOMWrapOn: 1, + ElementsDOMWrapOff: 2, + ConsoleMonitorXHROn: 3, + ConsoleMonitorXHROff: 4, + ConsolePreserveLogOn: 5, + ConsolePreserveLogOff: 6, + NetworkShowLargeRowsOn: 7, + NetworkShowLargeRowsOff: 8 +} + +WebInspector.UserMetrics._PanelCodes = { + elements: 1, + resources: 2, + network: 3, + scripts: 4, + timeline: 5, + profiles: 6, + audits: 7, + console: 8 +} + +WebInspector.UserMetrics.prototype = { + panelShown: function(panelName) + { + InspectorFrontendHost.recordPanelShown(WebInspector.UserMetrics._PanelCodes[panelName] || 0); + } +} + +/** + * @constructor + */ +WebInspector.UserMetrics._Recorder = function(actionCode) +{ + this._actionCode = actionCode; +} + +WebInspector.UserMetrics._Recorder.prototype = { + record: function() + { + InspectorFrontendHost.recordActionTaken(this._actionCode); + } +} + +WebInspector.userMetrics = new WebInspector.UserMetrics(); +/* JavaScriptContextManager.js */ + +/* + * Copyright (C) 2011 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. + */ + +/** + * @constructor + * @extends {WebInspector.Object} + */ +WebInspector.JavaScriptContextManager = function(resourceTreeModel, consoleView) +{ + resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameAdded, this._frameAdded, this); + resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameNavigated, this._frameNavigated, this); + resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameDetached, this._frameDetached, this); + this._consoleView = consoleView; + this._frameIdToContext = {}; +} + +WebInspector.JavaScriptContextManager.prototype = { + _frameAdded: function(event) + { + var frame = event.data; + var context = new WebInspector.FrameEvaluationContext(frame); + this._frameIdToContext[frame.id] = context; + this._consoleView.addContext(context); + }, + + _frameNavigated: function(event) + { + var frame = event.data; + var context = this._frameIdToContext[frame.id]; + if (context) + context._frameNavigated(frame); + }, + + _frameDetached: function(event) + { + var frame = event.data; + var context = this._frameIdToContext[frame.id]; + if (!context) + return; + this._consoleView.removeContext(context); + delete this._frameIdToContext[frame.id]; + }, +} + +WebInspector.JavaScriptContextManager.prototype.__proto__ = WebInspector.Object.prototype; + +/** + * @constructor + * @extends {WebInspector.Object} + */ +WebInspector.FrameEvaluationContext = function(frame) +{ + this._frame = frame; +} + +WebInspector.FrameEvaluationContext.EventTypes = { + Updated: "updated" +} + +WebInspector.FrameEvaluationContext.prototype = +{ + _frameNavigated: function(frame) + { + this._frame = frame; + this.dispatchEventToListeners(WebInspector.FrameEvaluationContext.EventTypes.Updated, this); + }, + + get frameId() + { + return this._frame.id; + }, + + get url() + { + return this._frame.url; + }, + + get displayName() + { + if (!this._frame.parentFrame) + return ""; + var name = this._frame.name || ""; + var subtitle = WebInspector.Resource.displayName(this._frame.url); + if (subtitle) { + if (!name) + return subtitle; + return name + "( " + subtitle + " )"; + } + return "