diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-09-10 19:10:20 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-09-10 19:10:20 +0200 |
commit | 284837daa07b29d6a63a748544a90b1f5842ac5c (patch) | |
tree | ecd258180bde91fe741e0cfd2638beb3c6da7e8e /Source/WebCore/inspector | |
parent | 2e2ba8ff45915f40ed3e014101269c175f2a89a0 (diff) | |
download | qtwebkit-284837daa07b29d6a63a748544a90b1f5842ac5c.tar.gz |
Imported WebKit commit 68645295d2e3e09af2c942f092556f06aa5f8b0d (http://svn.webkit.org/repository/webkit/trunk@128073)
New snapshot
Diffstat (limited to 'Source/WebCore/inspector')
150 files changed, 5869 insertions, 3674 deletions
diff --git a/Source/WebCore/inspector/CodeGeneratorInspector.py b/Source/WebCore/inspector/CodeGeneratorInspector.py index 85222538b..dd9cb11a1 100755 --- a/Source/WebCore/inspector/CodeGeneratorInspector.py +++ b/Source/WebCore/inspector/CodeGeneratorInspector.py @@ -770,6 +770,9 @@ class Writer: if p: self.newline(p) + def get_indent(self): + return self.indent + def get_indented(self, additional_indent): return Writer(self.output, self.indent + additional_indent) @@ -1110,7 +1113,7 @@ class TypeBindings: class ResolveData: main_properties = main optional_properties = optional - ad_hoc_types = ad_hoc_type_context.ad_hoc_type_list + ad_hoc_types = ad_hoc_type_list cls.resolve_data_ = ResolveData @@ -1783,10 +1786,20 @@ ${responseCook} frontend_method = string.Template("""void InspectorFrontend::$domainName::$eventName($parameters) { - RefPtr<InspectorObject> ${eventName}Message = InspectorObject::create(); - ${eventName}Message->setString("method", "$domainName.$eventName"); + RefPtr<InspectorObject> jsonMessage = InspectorObject::create(); + jsonMessage->setString("method", "$domainName.$eventName"); $code if (m_inspectorFrontendChannel) - m_inspectorFrontendChannel->sendMessageToFrontend(${eventName}Message->toJSONString()); + m_inspectorFrontendChannel->sendMessageToFrontend(jsonMessage->toJSONString()); +} +""") + + callback_method = string.Template( +"""InspectorBackendDispatcher::$agentName::$callbackName::$callbackName(PassRefPtr<InspectorBackendDispatcherImpl> backendImpl, int id) : CallbackBase(backendImpl, id) {} + +void InspectorBackendDispatcher::$agentName::$callbackName::sendSuccess($parameters) +{ + RefPtr<InspectorObject> jsonMessage = InspectorObject::create(); +$code sendIfActive(jsonMessage, ErrorString()); } """) @@ -1796,8 +1809,8 @@ $code if (m_inspectorFrontendChannel) #include "InspectorTypeBuilder.h" #include "InspectorValues.h" -#include <PlatformString.h> #include <wtf/PassRefPtr.h> +#include <wtf/text/WTFString.h> namespace WebCore { @@ -1845,11 +1858,33 @@ class InspectorFrontendChannel; typedef String ErrorString; +class InspectorBackendDispatcherImpl; + class InspectorBackendDispatcher: public RefCounted<InspectorBackendDispatcher> { public: static PassRefPtr<InspectorBackendDispatcher> create(InspectorFrontendChannel* inspectorFrontendChannel); virtual ~InspectorBackendDispatcher() { } + class CallbackBase: public RefCounted<CallbackBase> { + public: + CallbackBase(PassRefPtr<InspectorBackendDispatcherImpl> backendImpl, int id); + virtual ~CallbackBase(); + void sendFailure(const ErrorString&); + bool isActive(); + + protected: + void sendIfActive(PassRefPtr<InspectorObject> partialMessage, const ErrorString& invocationError); + + private: + void disable() { m_alreadySent = true; } + + RefPtr<InspectorBackendDispatcherImpl> m_backendImpl; + int m_id; + bool m_alreadySent; + + friend class InspectorBackendDispatcherImpl; + }; + $agentInterfaces $virtualSetters @@ -1920,6 +1955,9 @@ $constructorInit virtual void reportProtocolError(const long* const callId, CommonErrorCode, const String& errorMessage, PassRefPtr<InspectorArray> data) const; using InspectorBackendDispatcher::reportProtocolError; + void sendResponse(long callId, PassRefPtr<InspectorObject> result, const ErrorString& invocationError); + bool isActive() { return m_inspectorFrontendChannel; } + $setters private: $methodDeclarations @@ -2017,6 +2055,11 @@ void InspectorBackendDispatcherImpl::sendResponse(long callId, PassRefPtr<Inspec reportProtocolError(&callId, InvalidParams, errorMessage, protocolErrors); return; } + sendResponse(callId, result, invocationError); +} + +void InspectorBackendDispatcherImpl::sendResponse(long callId, PassRefPtr<InspectorObject> result, const ErrorString& invocationError) +{ if (invocationError.length()) { reportProtocolError(&callId, ServerError, invocationError); return; @@ -2154,6 +2197,30 @@ bool InspectorBackendDispatcher::getCommandName(const String& message, String* r return true; } +InspectorBackendDispatcher::CallbackBase::CallbackBase(PassRefPtr<InspectorBackendDispatcherImpl> backendImpl, int id) + : m_backendImpl(backendImpl), m_id(id), m_alreadySent(false) {} + +InspectorBackendDispatcher::CallbackBase::~CallbackBase() {} + +void InspectorBackendDispatcher::CallbackBase::sendFailure(const ErrorString& error) +{ + ASSERT(error.length()); + sendIfActive(0, error); +} + +bool InspectorBackendDispatcher::CallbackBase::isActive() +{ + return !m_alreadySent && m_backendImpl->isActive(); +} + +void InspectorBackendDispatcher::CallbackBase::sendIfActive(PassRefPtr<InspectorObject> partialMessage, const ErrorString& invocationError) +{ + if (m_alreadySent) + return; + m_backendImpl->sendResponse(m_id, partialMessage, invocationError); + m_alreadySent = true; +} + COMPILE_ASSERT(static_cast<int>(InspectorBackendDispatcher::kMethodNamesEnumSize) == WTF_ARRAY_LENGTH(InspectorBackendDispatcher::commandNames), command_name_array_problem); } // namespace WebCore @@ -2727,59 +2794,41 @@ class Generator: def process_event(json_event, domain_name, frontend_method_declaration_lines): event_name = json_event["name"] - parameter_list = [] - method_line_list = [] - backend_js_event_param_list = [] ad_hoc_type_output = [] frontend_method_declaration_lines.append(ad_hoc_type_output) ad_hoc_type_writer = Writer(ad_hoc_type_output, " ") - if "parameters" in json_event: - method_line_list.append(" RefPtr<InspectorObject> paramsObject = InspectorObject::create();\n") - for json_parameter in json_event["parameters"]: - parameter_name = json_parameter["name"] - - param_type_binding = Generator.resolve_type_and_generate_ad_hoc(json_parameter, event_name, domain_name, ad_hoc_type_writer, "") - - raw_type = param_type_binding.reduce_to_raw_type() - raw_type_binding = RawTypeBinding(raw_type) - optional = bool(json_parameter.get("optional")) + decl_parameter_list = [] - setter_type = raw_type.get_setter_name() - - type_model = param_type_binding.get_type_model() - raw_type_model = raw_type_binding.get_type_model() - if optional: - type_model = type_model.get_optional() - raw_type_model = raw_type_model.get_optional() - - annotated_type = type_model.get_input_param_type_text() - mode_type_binding = param_type_binding - - parameter_list.append("%s %s" % (annotated_type, parameter_name)) - - setter_argument = raw_type_model.get_event_setter_expression_pattern() % parameter_name - if mode_type_binding.get_setter_value_expression_pattern(): - setter_argument = mode_type_binding.get_setter_value_expression_pattern() % setter_argument - - setter_code = " paramsObject->set%s(\"%s\", %s);\n" % (setter_type, parameter_name, setter_argument) - if optional: - setter_code = (" if (%s)\n " % parameter_name) + setter_code - method_line_list.append(setter_code) + json_parameters = json_event.get("parameters") + Generator.generate_send_method(json_parameters, event_name, domain_name, ad_hoc_type_writer, + decl_parameter_list, + Generator.EventMethodStructTemplate, + Generator.frontend_method_list, Templates.frontend_method, {"eventName": event_name}) + backend_js_event_param_list = [] + if json_parameters: + for parameter in json_parameters: + parameter_name = parameter["name"] backend_js_event_param_list.append("\"%s\"" % parameter_name) - method_line_list.append(" %sMessage->setObject(\"params\", paramsObject);\n" % event_name) - frontend_method_declaration_lines.append( - " void %s(%s);\n" % (event_name, ", ".join(parameter_list))) - Generator.frontend_method_list.append(Templates.frontend_method.substitute(None, - domainName=domain_name, eventName=event_name, - parameters=", ".join(parameter_list), - code="".join(method_line_list))) + frontend_method_declaration_lines.append( + " void %s(%s);\n" % (event_name, ", ".join(decl_parameter_list))) Generator.backend_js_domain_initializer_list.append("InspectorBackend.registerEvent(\"%s.%s\", [%s]);\n" % ( domain_name, event_name, ", ".join(backend_js_event_param_list))) + class EventMethodStructTemplate: + @staticmethod + def append_prolog(line_list): + line_list.append(" RefPtr<InspectorObject> paramsObject = InspectorObject::create();\n") + + @staticmethod + def append_epilog(line_list): + line_list.append(" jsonMessage->setObject(\"params\", paramsObject);\n") + + container_name = "paramsObject" + @staticmethod def process_command(json_command, domain_name, agent_field_name, agent_interface_name): json_command_name = json_command["name"] @@ -2800,7 +2849,6 @@ class Generator: method_out_code = "" agent_call_param_list = [] response_cook_list = [] - backend_js_reply_param_list = [] request_message_param = "" js_parameters_text = "" if "parameters" in json_command: @@ -2855,58 +2903,89 @@ class Generator: js_parameters_text = ", ".join(js_param_list) response_cook_text = "" - js_reply_list = "[]" - if "returns" in json_command: - method_out_code += "\n" - for json_return in json_command["returns"]: + if json_command.get("async") == True: + callback_name = Capitalizer.lower_camel_case_to_upper(json_command_name) + "Callback" + + callback_output = [] + callback_writer = Writer(callback_output, ad_hoc_type_writer.get_indent()) + + decl_parameter_list = [] + Generator.generate_send_method(json_command.get("returns"), json_command_name, domain_name, ad_hoc_type_writer, + decl_parameter_list, + Generator.CallbackMethodStructTemplate, + Generator.backend_method_implementation_list, Templates.callback_method, + {"callbackName": callback_name, "agentName": agent_interface_name}) + + callback_writer.newline("class " + callback_name + " : public CallbackBase {\n") + callback_writer.newline("public:\n") + callback_writer.newline(" " + callback_name + "(PassRefPtr<InspectorBackendDispatcherImpl>, int id);\n") + callback_writer.newline(" void sendSuccess(" + ", ".join(decl_parameter_list) + ");\n") + callback_writer.newline("};\n") + + ad_hoc_type_output.append(callback_output) + + method_out_code += " RefPtr<" + agent_interface_name + "::" + callback_name + "> callback = adoptRef(new " + agent_interface_name + "::" + callback_name + "(this, callId));\n" + agent_call_param_list.append(", callback") + response_cook_text += " if (!error.length()) \n" + response_cook_text += " return;\n" + response_cook_text += " callback->disable();\n" + Generator.backend_agent_interface_list.append(", PassRefPtr<%s> callback" % callback_name) + else: + if "returns" in json_command: + method_out_code += "\n" + for json_return in json_command["returns"]: - json_return_name = json_return["name"] + json_return_name = json_return["name"] - optional = bool(json_return.get("optional")) + optional = bool(json_return.get("optional")) - return_type_binding = Generator.resolve_type_and_generate_ad_hoc(json_return, json_command_name, domain_name, ad_hoc_type_writer, agent_interface_name + "::") + return_type_binding = Generator.resolve_type_and_generate_ad_hoc(json_return, json_command_name, domain_name, ad_hoc_type_writer, agent_interface_name + "::") - raw_type = return_type_binding.reduce_to_raw_type() - setter_type = raw_type.get_setter_name() - initializer = raw_type.get_c_initializer() + raw_type = return_type_binding.reduce_to_raw_type() + setter_type = raw_type.get_setter_name() + initializer = raw_type.get_c_initializer() - type_model = return_type_binding.get_type_model() - if optional: - type_model = type_model.get_optional() + type_model = return_type_binding.get_type_model() + if optional: + type_model = type_model.get_optional() - code = " %s out_%s;\n" % (type_model.get_command_return_pass_model().get_return_var_type(), json_return_name) - param = ", %sout_%s" % (type_model.get_command_return_pass_model().get_output_argument_prefix(), json_return_name) - var_name = "out_%s" % json_return_name - setter_argument = type_model.get_command_return_pass_model().get_output_to_raw_expression() % var_name - if return_type_binding.get_setter_value_expression_pattern(): - setter_argument = return_type_binding.get_setter_value_expression_pattern() % setter_argument + code = " %s out_%s;\n" % (type_model.get_command_return_pass_model().get_return_var_type(), json_return_name) + param = ", %sout_%s" % (type_model.get_command_return_pass_model().get_output_argument_prefix(), json_return_name) + var_name = "out_%s" % json_return_name + setter_argument = type_model.get_command_return_pass_model().get_output_to_raw_expression() % var_name + if return_type_binding.get_setter_value_expression_pattern(): + setter_argument = return_type_binding.get_setter_value_expression_pattern() % setter_argument - cook = " result->set%s(\"%s\", %s);\n" % (setter_type, json_return_name, - setter_argument) + cook = " result->set%s(\"%s\", %s);\n" % (setter_type, json_return_name, + setter_argument) - set_condition_pattern = type_model.get_command_return_pass_model().get_set_return_condition() - if set_condition_pattern: - cook = (" if (%s)\n " % (set_condition_pattern % var_name)) + cook - annotated_type = type_model.get_command_return_pass_model().get_output_parameter_type() + set_condition_pattern = type_model.get_command_return_pass_model().get_set_return_condition() + if set_condition_pattern: + cook = (" if (%s)\n " % (set_condition_pattern % var_name)) + cook + annotated_type = type_model.get_command_return_pass_model().get_output_parameter_type() - param_name = "out_%s" % json_return_name - if optional: - param_name = "opt_" + param_name + param_name = "out_%s" % json_return_name + if optional: + param_name = "opt_" + param_name - Generator.backend_agent_interface_list.append(", %s %s" % (annotated_type, param_name)) - response_cook_list.append(cook) + Generator.backend_agent_interface_list.append(", %s %s" % (annotated_type, param_name)) + response_cook_list.append(cook) - method_out_code += code - agent_call_param_list.append(param) + method_out_code += code + agent_call_param_list.append(param) - backend_js_reply_param_list.append("\"%s\"" % json_return_name) + response_cook_text = "".join(response_cook_list) - js_reply_list = "[%s]" % ", ".join(backend_js_reply_param_list) + if len(response_cook_text) != 0: + response_cook_text = " if (!error.length()) {\n" + response_cook_text + " }" - response_cook_text = "".join(response_cook_list) + backend_js_reply_param_list = [] + if "returns" in json_command: + for json_return in json_command["returns"]: + json_return_name = json_return["name"] + backend_js_reply_param_list.append("\"%s\"" % json_return_name) - if len(response_cook_text) != 0: - response_cook_text = " if (!error.length()) {\n" + response_cook_text + " }" + js_reply_list = "[%s]" % ", ".join(backend_js_reply_param_list) Generator.backend_method_implementation_list.append(Templates.backend_method.substitute(None, domainName=domain_name, methodName=json_command_name, @@ -2922,6 +3001,64 @@ class Generator: Generator.backend_js_domain_initializer_list.append("InspectorBackend.registerCommand(\"%s.%s\", [%s], %s);\n" % (domain_name, json_command_name, js_parameters_text, js_reply_list)) Generator.backend_agent_interface_list.append(") = 0;\n") + class CallbackMethodStructTemplate: + @staticmethod + def append_prolog(line_list): + pass + + @staticmethod + def append_epilog(line_list): + pass + + container_name = "jsonMessage" + + # Generates common code for event sending and callback response data sending. + @staticmethod + def generate_send_method(parameters, event_name, domain_name, ad_hoc_type_writer, decl_parameter_list, + method_struct_template, + generator_method_list, method_template, template_params): + method_line_list = [] + if parameters: + method_struct_template.append_prolog(method_line_list) + for json_parameter in parameters: + parameter_name = json_parameter["name"] + + param_type_binding = Generator.resolve_type_and_generate_ad_hoc(json_parameter, event_name, domain_name, ad_hoc_type_writer, "") + + raw_type = param_type_binding.reduce_to_raw_type() + raw_type_binding = RawTypeBinding(raw_type) + + optional = bool(json_parameter.get("optional")) + + setter_type = raw_type.get_setter_name() + + type_model = param_type_binding.get_type_model() + raw_type_model = raw_type_binding.get_type_model() + if optional: + type_model = type_model.get_optional() + raw_type_model = raw_type_model.get_optional() + + annotated_type = type_model.get_input_param_type_text() + mode_type_binding = param_type_binding + + decl_parameter_list.append("%s %s" % (annotated_type, parameter_name)) + + setter_argument = raw_type_model.get_event_setter_expression_pattern() % parameter_name + if mode_type_binding.get_setter_value_expression_pattern(): + setter_argument = mode_type_binding.get_setter_value_expression_pattern() % setter_argument + + setter_code = " %s->set%s(\"%s\", %s);\n" % (method_struct_template.container_name, setter_type, parameter_name, setter_argument) + if optional: + setter_code = (" if (%s)\n " % parameter_name) + setter_code + method_line_list.append(setter_code) + + method_struct_template.append_epilog(method_line_list) + + generator_method_list.append(method_template.substitute(None, + domainName=domain_name, + parameters=", ".join(decl_parameter_list), + code="".join(method_line_list), **template_params)) + @staticmethod def resolve_type_and_generate_ad_hoc(json_param, method_name, domain_name, ad_hoc_type_writer, container_relative_name_prefix_param): param_name = json_param["name"] diff --git a/Source/WebCore/inspector/ContentSearchUtils.cpp b/Source/WebCore/inspector/ContentSearchUtils.cpp index 054da348f..a3f83c2d6 100644 --- a/Source/WebCore/inspector/ContentSearchUtils.cpp +++ b/Source/WebCore/inspector/ContentSearchUtils.cpp @@ -144,7 +144,7 @@ static String findMagicComment(const String& content, const String& name) { String patternString = "//@[\040\t]" + name + "=[\040\t]*([^\\s\'\"]*)[\040\t]*$"; const char* error = 0; - JSC::Yarr::YarrPattern pattern(JSC::UString(patternString.impl()), false, true, &error); + JSC::Yarr::YarrPattern pattern(patternString, false, true, &error); ASSERT(!error); BumpPointerAllocator regexAllocator; OwnPtr<JSC::Yarr::BytecodePattern> bytecodePattern = JSC::Yarr::byteCompile(pattern, ®exAllocator); @@ -153,7 +153,7 @@ static String findMagicComment(const String& content, const String& name) ASSERT(pattern.m_numSubpatterns == 1); Vector<int, 4> matches; matches.resize(4); - unsigned result = JSC::Yarr::interpret(bytecodePattern.get(), JSC::UString(content.impl()), 0, reinterpret_cast<unsigned*>(matches.data())); + unsigned result = JSC::Yarr::interpret(bytecodePattern.get(), content, 0, reinterpret_cast<unsigned*>(matches.data())); if (result == JSC::Yarr::offsetNoMatch) return String(); ASSERT(matches[2] > 0 && matches[3] > 0); diff --git a/Source/WebCore/inspector/ContentSearchUtils.h b/Source/WebCore/inspector/ContentSearchUtils.h index d984c66b4..79d924a8e 100644 --- a/Source/WebCore/inspector/ContentSearchUtils.h +++ b/Source/WebCore/inspector/ContentSearchUtils.h @@ -32,8 +32,8 @@ #if ENABLE(INSPECTOR) #include "InspectorTypeBuilder.h" -#include "PlatformString.h" #include <wtf/Vector.h> +#include <wtf/text/WTFString.h> namespace WebCore { diff --git a/Source/WebCore/inspector/IdentifiersFactory.cpp b/Source/WebCore/inspector/IdentifiersFactory.cpp index b8c6d7f17..c2af2a566 100644 --- a/Source/WebCore/inspector/IdentifiersFactory.cpp +++ b/Source/WebCore/inspector/IdentifiersFactory.cpp @@ -56,8 +56,8 @@ String IdentifiersFactory::requestId(unsigned long identifier) String IdentifiersFactory::addProcessIdPrefixTo(const String& id) { StringBuilder builder; - builder.append(String::number(s_processId)); - builder.append("."); + builder.appendNumber(s_processId); + builder.append('.'); builder.append(id); return builder.toString(); } diff --git a/Source/WebCore/inspector/InjectedScript.cpp b/Source/WebCore/inspector/InjectedScript.cpp index 599668866..6a44ca7b5 100644 --- a/Source/WebCore/inspector/InjectedScript.cpp +++ b/Source/WebCore/inspector/InjectedScript.cpp @@ -38,9 +38,9 @@ #include "InjectedScriptModule.h" #include "InspectorValues.h" #include "Node.h" -#include "PlatformString.h" #include "ScriptFunctionCall.h" #include "SerializedScriptValue.h" +#include <wtf/text/WTFString.h> using WebCore::TypeBuilder::Array; using WebCore::TypeBuilder::Debugger::CallFrame; diff --git a/Source/WebCore/inspector/InjectedScriptBase.cpp b/Source/WebCore/inspector/InjectedScriptBase.cpp index fe0b42812..19c0aa1b5 100644 --- a/Source/WebCore/inspector/InjectedScriptBase.cpp +++ b/Source/WebCore/inspector/InjectedScriptBase.cpp @@ -36,8 +36,8 @@ #include "InspectorInstrumentation.h" #include "InspectorValues.h" -#include "PlatformString.h" #include "ScriptFunctionCall.h" +#include <wtf/text/WTFString.h> using WebCore::TypeBuilder::Runtime::RemoteObject; diff --git a/Source/WebCore/inspector/InjectedScriptExterns.js b/Source/WebCore/inspector/InjectedScriptExterns.js index a24f69773..317087a0d 100644 --- a/Source/WebCore/inspector/InjectedScriptExterns.js +++ b/Source/WebCore/inspector/InjectedScriptExterns.js @@ -114,3 +114,23 @@ function JavaScriptFunction() } var InspectorBackend = { }; + +// http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi +/** + * @constructor + */ +function CallSite() +{ +} +/** + * @return {string} + */ +CallSite.prototype.getFileName = function() { } +/** + * @return {number} + */ +CallSite.prototype.getLineNumber = function() { } +/** + * @return {number} + */ +CallSite.prototype.getColumnNumber = function() { } diff --git a/Source/WebCore/inspector/InjectedScriptManager.h b/Source/WebCore/inspector/InjectedScriptManager.h index 43590d129..ed51c03ef 100644 --- a/Source/WebCore/inspector/InjectedScriptManager.h +++ b/Source/WebCore/inspector/InjectedScriptManager.h @@ -30,11 +30,10 @@ #ifndef InjectedScriptManager_h #define InjectedScriptManager_h -#include "PlatformString.h" #include "ScriptState.h" - #include <wtf/Forward.h> #include <wtf/HashMap.h> +#include <wtf/text/WTFString.h> namespace WebCore { diff --git a/Source/WebCore/inspector/InjectedScriptModule.h b/Source/WebCore/inspector/InjectedScriptModule.h index fbfbaa01d..d88ddec6f 100644 --- a/Source/WebCore/inspector/InjectedScriptModule.h +++ b/Source/WebCore/inspector/InjectedScriptModule.h @@ -32,8 +32,8 @@ #define InjectedScriptModule_h #include "InjectedScriptBase.h" -#include "PlatformString.h" #include "ScriptState.h" +#include <wtf/text/WTFString.h> namespace WebCore { diff --git a/Source/WebCore/inspector/InjectedScriptSource.js b/Source/WebCore/inspector/InjectedScriptSource.js index 56d736691..1688015a4 100644 --- a/Source/WebCore/inspector/InjectedScriptSource.js +++ b/Source/WebCore/inspector/InjectedScriptSource.js @@ -222,12 +222,6 @@ InjectedScript.prototype = { var descriptors = this._propertyDescriptors(object, ownProperties); // Go over properties, wrap object values. - if (descriptors.length === 0 && "arguments" in object) { - // Fill in JSC scope object. - for (var key in object) - descriptors.push({ name: key, value: object[key], writable: false, configurable: false, enumerable: true}); - } - for (var i = 0; i < descriptors.length; ++i) { var descriptor = descriptors[i]; if ("get" in descriptor) @@ -943,16 +937,52 @@ function CommandLineAPIImpl() } CommandLineAPIImpl.prototype = { - $: function() + /** + * @param {string} selector + * @param {Node=} start + */ + $: function (selector, start) + { + if (this._canQuerySelectorOnNode(start)) + return start.querySelector(selector); + + var result = document.querySelector(selector); + if (result) + return result; + if (selector && selector[0] !== "#") { + result = document.getElementById(selector); + if (result) { + console.warn("The console function $() has changed from $=getElementById(id) to $=querySelector(selector). You might try $(\"#%s\")", selector ); + return null; + } + } + return result; + }, + + /** + * @param {string} selector + * @param {Node=} start + */ + $$: function (selector, start) { - return document.getElementById.apply(document, arguments) + if (this._canQuerySelectorOnNode(start)) + return start.querySelectorAll(selector); + return document.querySelectorAll(selector); }, - $$: function() + /** + * @param {Node} node + * @return {boolean} + */ + _canQuerySelectorOnNode: function(node) { - return document.querySelectorAll.apply(document, arguments) + return !!node && InjectedScriptHost.type(node) === "node" && (node.nodeType === Node.ELEMENT_NODE || node.nodeType === Node.DOCUMENT_NODE || node.nodeType === Node.DOCUMENT_FRAGMENT_NODE); }, + /** + * @param {string} xpath + * @param {Node=} context + */ $x: function(xpath, context) { var doc = (context && context.ownerDocument) || inspectedWindow.document; diff --git a/Source/WebCore/inspector/InjectedScriptWebGLModule.h b/Source/WebCore/inspector/InjectedScriptWebGLModule.h index 368898f7c..cff857fd8 100644 --- a/Source/WebCore/inspector/InjectedScriptWebGLModule.h +++ b/Source/WebCore/inspector/InjectedScriptWebGLModule.h @@ -32,8 +32,8 @@ #define InjectedScriptWebGLModule_h #include "InjectedScriptModule.h" -#include "PlatformString.h" #include "ScriptState.h" +#include <wtf/text/WTFString.h> namespace WebCore { diff --git a/Source/WebCore/inspector/InjectedScriptWebGLModuleSource.js b/Source/WebCore/inspector/InjectedScriptWebGLModuleSource.js index 3ace0b245..dd3b5b772 100644 --- a/Source/WebCore/inspector/InjectedScriptWebGLModuleSource.js +++ b/Source/WebCore/inspector/InjectedScriptWebGLModuleSource.js @@ -40,7 +40,7 @@ var TypeUtils = { * http://www.khronos.org/registry/typedarray/specs/latest/#7 * @type {Array.<Function>} */ - typedArrayClasses: (function(typeNames) { + _typedArrayClasses: (function(typeNames) { var result = []; for (var i = 0, n = typeNames.length; i < n; ++i) { if (inspectedWindow[typeNames[i]]) @@ -55,7 +55,7 @@ var TypeUtils = { */ typedArrayClass: function(array) { - var classes = TypeUtils.typedArrayClasses; + var classes = TypeUtils._typedArrayClasses; for (var i = 0, n = classes.length; i < n; ++i) { if (array instanceof classes[i]) return classes[i]; @@ -93,7 +93,7 @@ var TypeUtils = { if (obj instanceof HTMLCanvasElement) { var result = obj.cloneNode(true); - var context = result.getContext("2d"); + var context = Resource.wrappedObject(result.getContext("2d")); context.drawImage(obj, 0, 0); return result; } @@ -121,20 +121,106 @@ var TypeUtils = { */ _dummyCanvas2dContext: function() { - var context = TypeUtils._dummyCanvas2dContext; + var context = TypeUtils._dummyCanvas2dContextInstance; if (!context) { var canvas = inspectedWindow.document.createElement("canvas"); - context = canvas.getContext("2d"); - var contextResource = Resource.forObject(context); - if (contextResource) - context = contextResource.wrappedObject(); - TypeUtils._dummyCanvas2dContext = context; + context = /** @type {CanvasRenderingContext2D} */ Resource.wrappedObject(canvas.getContext("2d")); + TypeUtils._dummyCanvas2dContextInstance = context; } return context; } } /** + * @interface + */ +function StackTrace() +{ +} + +StackTrace.prototype = { + /** + * @param {number} index + * @return {{sourceURL: string, lineNumber: number, columnNumber: number}} + */ + callFrame: function(index) + { + } +} + +/** + * @param {number=} stackTraceLimit + * @param {Function=} topMostFunctionToIgnore + * @return {StackTrace} + */ +StackTrace.create = function(stackTraceLimit, topMostFunctionToIgnore) +{ + if (typeof Error.captureStackTrace === "function") + return new StackTraceV8(stackTraceLimit, topMostFunctionToIgnore || arguments.callee); + // FIXME: Support JSC, and maybe other browsers. + return null; +} + +/** + * @constructor + * @implements {StackTrace} + * @param {number=} stackTraceLimit + * @param {Function=} topMostFunctionToIgnore + * @see http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi + */ +function StackTraceV8(stackTraceLimit, topMostFunctionToIgnore) +{ + StackTrace.call(this); + var oldStackTraceLimit = Error.stackTraceLimit; + if (typeof stackTraceLimit === "number") + Error.stackTraceLimit = stackTraceLimit; + + this._error = /** @type {{stack: Array}} */ {}; + Error.captureStackTrace(this._error, topMostFunctionToIgnore || arguments.callee); + + Error.stackTraceLimit = oldStackTraceLimit; +} + +StackTraceV8.prototype = { + /** + * @override + * @param {number} index + * @return {{sourceURL: string, lineNumber: number, columnNumber: number}} + */ + callFrame: function(index) + { + if (!this._stackTrace) + this._prepareStackTrace(); + return this._stackTrace[index]; + }, + + _prepareStackTrace: function() + { + var oldPrepareStackTrace = Error.prepareStackTrace; + /** + * @param {Object} error + * @param {Array.<CallSite>} structuredStackTrace + * @return {Array.<{sourceURL: string, lineNumber: number, columnNumber: number}>} + */ + Error.prepareStackTrace = function(error, structuredStackTrace) + { + return structuredStackTrace.map(function(callSite) { + return { + sourceURL: callSite.getFileName(), + lineNumber: callSite.getLineNumber(), + columnNumber: callSite.getColumnNumber() + }; + }); + } + this._stackTrace = this._error.stack; + Error.prepareStackTrace = oldPrepareStackTrace; + delete this._error; // No longer needed, free memory. + } +} + +StackTraceV8.prototype.__proto__ = StackTrace.prototype; + +/** * @constructor */ function Cache() @@ -193,13 +279,15 @@ Cache.prototype = { * @param {string} functionName * @param {Array|Arguments} args * @param {Resource|*=} result + * @param {StackTrace=} stackTrace */ -function Call(thisObject, functionName, args, result) +function Call(thisObject, functionName, args, result, stackTrace) { this._thisObject = thisObject; this._functionName = functionName; this._args = Array.prototype.slice.call(args, 0); this._result = result; + this._stackTrace = stackTrace || null; } Call.prototype = { @@ -235,6 +323,30 @@ Call.prototype = { return this._result; }, + /** + * @return {StackTrace} + */ + stackTrace: function() + { + return this._stackTrace; + }, + + /** + * @param {StackTrace} stackTrace + */ + setStackTrace: function(stackTrace) + { + this._stackTrace = stackTrace; + }, + + /** + * @param {*} result + */ + setResult: function(result) + { + this._result = result; + }, + freeze: function() { if (this._freezed) @@ -245,6 +357,50 @@ Call.prototype = { if (!Resource.forObject(this._args[i])) this._args[i] = TypeUtils.clone(this._args[i]); } + }, + + /** + * @param {Cache} cache + * @return {ReplayableCall} + */ + toReplayable: function(cache) + { + this.freeze(); + var thisObject = /** @type {ReplayableResource} */ Resource.toReplayable(this._thisObject, cache); + var result = Resource.toReplayable(this._result, cache); + var args = this._args.map(function(obj) { + return Resource.toReplayable(obj, cache); + }); + return new ReplayableCall(thisObject, this._functionName, args, result, this._stackTrace); + }, + + /** + * @param {ReplayableCall} replayableCall + * @param {Cache} cache + * @return {Call} + */ + replay: function(replayableCall, cache) + { + var replayObject = ReplayableResource.replay(replayableCall.resource(), cache); + var replayFunction = replayObject[replayableCall.functionName()]; + console.assert(typeof replayFunction === "function", "Expected a function to replay"); + var replayArgs = replayableCall.args().map(function(obj) { + return ReplayableResource.replay(obj, cache); + }); + var replayResult = replayFunction.apply(replayObject, replayArgs); + if (replayableCall.result() instanceof ReplayableResource) { + var resource = replayableCall.result().replay(cache); + if (!resource.wrappedObject()) + resource.setWrappedObject(replayResult); + } + + this._thisObject = replayObject; + this._functionName = replayableCall.functionName(); + this._args = replayArgs; + this._result = replayResult; + this._stackTrace = replayableCall.stackTrace(); + this._freezed = true; + return this; } } @@ -254,13 +410,15 @@ Call.prototype = { * @param {string} functionName * @param {Array.<ReplayableResource|*>} args * @param {ReplayableResource|*} result + * @param {StackTrace} stackTrace */ -function ReplayableCall(thisObject, functionName, args, result) +function ReplayableCall(thisObject, functionName, args, result, stackTrace) { this._thisObject = thisObject; this._functionName = functionName; this._args = args; this._result = result; + this._stackTrace = stackTrace; } ReplayableCall.prototype = { @@ -297,12 +455,21 @@ ReplayableCall.prototype = { }, /** + * @return {StackTrace} + */ + stackTrace: function() + { + return this._stackTrace; + }, + + /** * @param {Cache} cache * @return {Call} */ replay: function(cache) { - // FIXME: Do the replay. + var call = Object.create(Call.prototype); + return call.replay(this, cache); } } @@ -338,6 +505,27 @@ Resource.forObject = function(obj) return null; } +/** + * @param {Resource|*} obj + * @return {*} + */ +Resource.wrappedObject = function(obj) +{ + var resource = Resource.forObject(obj); + return resource ? resource.wrappedObject() : obj; +} + +/** + * @param {Resource|*} obj + * @param {Cache} cache + * @return {ReplayableResource|*} + */ +Resource.toReplayable = function(obj, cache) +{ + var resource = Resource.forObject(obj); + return resource ? resource.toReplayable(cache) : obj; +} + Resource.prototype = { /** * @return {number} @@ -400,6 +588,66 @@ Resource.prototype = { }, /** + * @param {Cache} cache + * @return {ReplayableResource} + */ + toReplayable: function(cache) + { + var result = cache.get(this._id); + if (result) + return result; + var data = { + id: this._id + }; + result = new ReplayableResource(this, data); + cache.put(this._id, result); // Put into the cache early to avoid loops. + data.calls = this._calls.map(function(call) { + return call.toReplayable(cache); + }); + this._populateReplayableData(data, cache); + return result; + }, + + /** + * @param {Object} data + * @param {Cache} cache + */ + _populateReplayableData: function(data, cache) + { + // Do nothing. Should be overridden by subclasses. + }, + + /** + * @param {Object} data + * @param {Cache} cache + * @return {Resource} + */ + replay: function(data, cache) + { + var resource = cache.get(data.id); + if (resource) + return resource; + this._id = data.id; + this._resourceManager = null; + this._calls = []; + this._wrappedObject = null; + cache.put(data.id, this); // Put into the cache early to avoid loops. + this._doReplayCalls(data, cache); + console.assert(this._wrappedObject, "Resource should be reconstructed!"); + return this; + }, + + /** + * @param {Object} data + * @param {Cache} cache + */ + _doReplayCalls: function(data, cache) + { + for (var i = 0, n = data.calls.length; i < n; ++i) + this._calls.push(data.calls[i].replay(cache)); + }, + + /** * @param {Call} call */ pushCall: function(call) @@ -409,11 +657,16 @@ Resource.prototype = { }, /** - * @param {Object} object + * @param {!Object} object */ _bindObjectToResource: function(object) { - object["__resourceObject"] = this; + Object.defineProperty(object, "__resourceObject", { + value: this, + writable: false, + enumerable: false, + configurable: true + }); } } @@ -424,6 +677,8 @@ Resource.prototype = { */ function ReplayableResource(originalResource, data) { + this._proto = originalResource.__proto__; + this._data = data; } ReplayableResource.prototype = { @@ -433,19 +688,531 @@ ReplayableResource.prototype = { */ replay: function(cache) { - // FIXME: Do the replay. + var result = Object.create(this._proto); + result = result.replay(this._data, cache) + console.assert(result.__proto__ === this._proto, "Wrong type of a replay result"); + return result; + } +} + +/** + * @param {ReplayableResource|*} obj + * @param {Cache} cache + * @return {*} + */ +ReplayableResource.replay = function(obj, cache) +{ + return (obj instanceof ReplayableResource) ? obj.replay(cache).wrappedObject() : obj; +} + +/** + * @constructor + * @extends {Resource} + */ +function WebGLBoundResource(wrappedObject) +{ + Resource.call(this, wrappedObject); + this._state = {}; +} + +WebGLBoundResource.prototype = { + /** + * @override + * @param {Object} data + * @param {Cache} cache + */ + _populateReplayableData: function(data, cache) + { + var state = this._state; + data.state = {}; + Object.keys(state).forEach(function(parameter) { + data.state[parameter] = Resource.toReplayable(state[parameter], cache); + }); + }, + + /** + * @override + * @param {Object} data + * @param {Cache} cache + */ + _doReplayCalls: function(data, cache) + { + var state = {}; + Object.keys(data.state).forEach(function(parameter) { + state[parameter] = ReplayableResource.replay(data.state[parameter], cache); + }); + this._state = state; + + var gl = this._replayContextResource(data, cache).wrappedObject(); + + var bindingsData = { + TEXTURE_2D: ["bindTexture", "TEXTURE_BINDING_2D"], + TEXTURE_CUBE_MAP: ["bindTexture", "TEXTURE_BINDING_CUBE_MAP"], + ARRAY_BUFFER: ["bindBuffer", "ARRAY_BUFFER_BINDING"], + ELEMENT_ARRAY_BUFFER: ["bindBuffer", "ELEMENT_ARRAY_BUFFER_BINDING"], + FRAMEBUFFER: ["bindFramebuffer", "FRAMEBUFFER_BINDING"], + RENDERBUFFER: ["bindRenderbuffer", "RENDERBUFFER_BINDING"] + }; + var originalBindings = {}; + Object.keys(bindingsData).forEach(function(bindingTarget) { + var bindingParameter = bindingsData[bindingTarget][1]; + originalBindings[bindingTarget] = gl.getParameter(gl[bindingParameter]); + }); + + Resource.prototype._doReplayCalls.call(this, data, cache); + + Object.keys(bindingsData).forEach(function(bindingTarget) { + var bindMethodName = bindingsData[bindingTarget][0]; + gl[bindMethodName].call(gl, gl[bindingTarget], originalBindings[bindingTarget]); + }); + }, + + _replayContextResource: function(data, cache) + { + var calls = data.calls; + for (var i = 0, n = calls.length; i < n; ++i) { + var resource = ReplayableResource.replay(calls[i].resource(), cache); + var contextResource = WebGLRenderingContextResource.forObject(resource); + if (contextResource) + return contextResource; + } + return null; + }, + + /** + * @param {number} target + * @param {string} bindMethodName + */ + pushBinding: function(target, bindMethodName) + { + if (this._state.BINDING !== target) { + this._state.BINDING = target; + this.pushCall(new Call(WebGLRenderingContextResource.forObject(this), bindMethodName, [target, this])); + } + } +} + +WebGLBoundResource.prototype.__proto__ = Resource.prototype; + +/** + * @constructor + * @extends {WebGLBoundResource} + */ +function WebGLTextureResource(wrappedObject) +{ + WebGLBoundResource.call(this, wrappedObject); +} + +WebGLTextureResource.prototype = { + /** + * @override + * @param {Object} data + * @param {Cache} cache + */ + _doReplayCalls: function(data, cache) + { + var gl = this._replayContextResource(data, cache).wrappedObject(); + + var state = {}; + WebGLRenderingContextResource.PixelStoreParameters.forEach(function(parameter) { + state[parameter] = gl.getParameter(gl[parameter]); + }); + + WebGLBoundResource.prototype._doReplayCalls.call(this, data, cache); + + WebGLRenderingContextResource.PixelStoreParameters.forEach(function(parameter) { + gl.pixelStorei(gl[parameter], state[parameter]); + }); + }, + + /** + * @override + * @param {Call} call + */ + pushCall: function(call) + { + var gl = call.resource().wrappedObject(); + WebGLRenderingContextResource.PixelStoreParameters.forEach(function(parameter) { + var value = gl.getParameter(gl[parameter]); + if (this._state[parameter] !== value) { + this._state[parameter] = value; + var pixelStoreCall = new Call(gl, "pixelStorei", [gl[parameter], value]); + WebGLBoundResource.prototype.pushCall.call(this, pixelStoreCall); + } + }, this); + + // FIXME: remove any older calls that no longer contribute to the resource state. + // FIXME: optimize memory usage: maybe it's more efficient to store one texImage2D call instead of many texSubImage2D. + WebGLBoundResource.prototype.pushCall.call(this, call); + }, + + /** + * @param {Call} call + */ + pushCall_texParameterf: function(call) + { + var args = call.args(); + var pname = args[1]; + var param = args[2]; + if (this._state[pname] !== param) { + this._state[pname] = param; + WebGLBoundResource.prototype.pushCall.call(this, call); + } + }, + + /** + * copyTexImage2D and copyTexSubImage2D define a texture image with pixels from the current framebuffer. + * @param {Call} call + */ + pushCall_copyTexImage2D: function(call) + { + var glResource = call.resource(); + var gl = glResource.wrappedObject(); + var framebufferResource = glResource.currentBinding(gl.FRAMEBUFFER); + if (framebufferResource) + this.pushCall(new Call(glResource, "bindFramebuffer", [gl.FRAMEBUFFER, framebufferResource])); + else + console.error("ASSERT_NOT_REACHED: No FRAMEBUFFER bound while calling gl." + call.functionName()); + this.pushCall(call); + } +} + +WebGLTextureResource.prototype.pushCall_texParameteri = WebGLTextureResource.prototype.pushCall_texParameterf; +WebGLTextureResource.prototype.pushCall_copyTexSubImage2D = WebGLTextureResource.prototype.pushCall_copyTexImage2D; + +WebGLTextureResource.prototype.__proto__ = WebGLBoundResource.prototype; + +/** + * @constructor + * @extends {Resource} + */ +function WebGLProgramResource(wrappedObject) +{ + Resource.call(this, wrappedObject); +} + +WebGLProgramResource.prototype = { + /** + * @override + * @param {Object} data + * @param {Cache} cache + */ + _populateReplayableData: function(data, cache) + { + var glResource = WebGLRenderingContextResource.forObject(this); + var gl = glResource.wrappedObject(); + var program = this.wrappedObject(); + + var originalErrors = glResource.getAllErrors(); + + var uniforms = []; + var uniformsCount = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS); + for (var i = 0; i < uniformsCount; ++i) { + var activeInfo = gl.getActiveUniform(program, i); + if (!activeInfo) + continue; + var uniformLocation = gl.getUniformLocation(program, activeInfo.name); + if (!uniformLocation) + continue; + var value = gl.getUniform(program, uniformLocation); + uniforms.push({ + name: activeInfo.name, + type: activeInfo.type, + value: value + }); + } + data.uniforms = uniforms; + + glResource.restoreErrors(originalErrors); + }, + + /** + * @override + * @param {Object} data + * @param {Cache} cache + */ + _doReplayCalls: function(data, cache) + { + Resource.prototype._doReplayCalls.call(this, data, cache); + var gl = WebGLRenderingContextResource.forObject(this).wrappedObject(); + var program = this.wrappedObject(); + + var originalProgram = gl.getParameter(gl.CURRENT_PROGRAM); + var currentProgram = originalProgram; + + data.uniforms.forEach(function(uniform) { + var uniformLocation = gl.getUniformLocation(program, uniform.name); + if (!uniformLocation) + return; + if (currentProgram !== program) { + currentProgram = program; + gl.useProgram(program); + } + var methodName = this._uniformMethodNameByType(gl, uniform.type); + if (methodName.indexOf("Matrix") === -1) + gl[methodName].call(gl, uniformLocation, uniform.value); + else + gl[methodName].call(gl, uniformLocation, false, uniform.value); + }.bind(this)); + + if (currentProgram !== originalProgram) + gl.useProgram(originalProgram); + }, + + /** + * @param {WebGLRenderingContext} gl + * @param {number} type + * @return {string} + */ + _uniformMethodNameByType: function(gl, type) + { + var uniformMethodNames = WebGLProgramResource._uniformMethodNames; + if (!uniformMethodNames) { + uniformMethodNames = {}; + uniformMethodNames[gl.FLOAT] = "uniform1f"; + uniformMethodNames[gl.FLOAT_VEC2] = "uniform2fv"; + uniformMethodNames[gl.FLOAT_VEC3] = "uniform3fv"; + uniformMethodNames[gl.FLOAT_VEC4] = "uniform4fv"; + uniformMethodNames[gl.INT] = "uniform1i"; + uniformMethodNames[gl.BOOL] = "uniform1i"; + uniformMethodNames[gl.SAMPLER_2D] = "uniform1i"; + uniformMethodNames[gl.SAMPLER_CUBE] = "uniform1i"; + uniformMethodNames[gl.INT_VEC2] = "uniform2iv"; + uniformMethodNames[gl.BOOL_VEC2] = "uniform2iv"; + uniformMethodNames[gl.INT_VEC3] = "uniform3iv"; + uniformMethodNames[gl.BOOL_VEC3] = "uniform3iv"; + uniformMethodNames[gl.INT_VEC4] = "uniform4iv"; + uniformMethodNames[gl.BOOL_VEC4] = "uniform4iv"; + uniformMethodNames[gl.FLOAT_MAT2] = "uniformMatrix2fv"; + uniformMethodNames[gl.FLOAT_MAT3] = "uniformMatrix3fv"; + uniformMethodNames[gl.FLOAT_MAT4] = "uniformMatrix4fv"; + WebGLProgramResource._uniformMethodNames = uniformMethodNames; + } + console.assert(uniformMethodNames[type], "Unknown uniform type " + type); + return uniformMethodNames[type]; + }, + + /** + * @override + * @param {Call} call + */ + pushCall: function(call) + { + // FIXME: remove any older calls that no longer contribute to the resource state. + // FIXME: handle multiple attachShader && detachShader. + Resource.prototype.pushCall.call(this, call); + } +} + +WebGLProgramResource.prototype.__proto__ = Resource.prototype; + +/** + * @constructor + * @extends {Resource} + */ +function WebGLShaderResource(wrappedObject) +{ + Resource.call(this, wrappedObject); +} + +WebGLShaderResource.prototype = { + /** + * @override + * @param {Call} call + */ + pushCall: function(call) + { + // FIXME: remove any older calls that no longer contribute to the resource state. + // FIXME: handle multiple shaderSource calls. + Resource.prototype.pushCall.call(this, call); + } +} + +WebGLShaderResource.prototype.__proto__ = Resource.prototype; + +/** + * @constructor + * @extends {WebGLBoundResource} + */ +function WebGLBufferResource(wrappedObject) +{ + WebGLBoundResource.call(this, wrappedObject); +} + +WebGLBufferResource.prototype = { + /** + * @override + * @param {Call} call + */ + pushCall: function(call) + { + // FIXME: remove any older calls that no longer contribute to the resource state. + // FIXME: Optimize memory for bufferSubData. + WebGLBoundResource.prototype.pushCall.call(this, call); + } +} + +WebGLBufferResource.prototype.__proto__ = WebGLBoundResource.prototype; + +/** + * @constructor + * @extends {WebGLBoundResource} + */ +function WebGLFramebufferResource(wrappedObject) +{ + WebGLBoundResource.call(this, wrappedObject); +} + +WebGLFramebufferResource.prototype = { + /** + * @override + * @param {Call} call + */ + pushCall: function(call) + { + // FIXME: remove any older calls that no longer contribute to the resource state. + WebGLBoundResource.prototype.pushCall.call(this, call); + } +} + +WebGLFramebufferResource.prototype.__proto__ = WebGLBoundResource.prototype; + +/** + * @constructor + * @extends {WebGLBoundResource} + */ +function WebGLRenderbufferResource(wrappedObject) +{ + WebGLBoundResource.call(this, wrappedObject); +} + +WebGLRenderbufferResource.prototype = { + /** + * @override + * @param {Call} call + */ + pushCall: function(call) + { + // FIXME: remove any older calls that no longer contribute to the resource state. + WebGLBoundResource.prototype.pushCall.call(this, call); } } +WebGLRenderbufferResource.prototype.__proto__ = WebGLBoundResource.prototype; + /** * @constructor * @extends {Resource} * @param {WebGLRenderingContext} glContext + * @param {Function} replayContextCallback */ -function WebGLRenderingContextResource(glContext) +function WebGLRenderingContextResource(glContext, replayContextCallback) { Resource.call(this, glContext); + this._replayContextCallback = replayContextCallback; this._proxyObject = null; + /** @type {Object.<number, boolean>} */ + this._customErrors = null; +} + +/** + * @const + * @type {Array.<string>} + */ +WebGLRenderingContextResource.GLCapabilities = [ + "BLEND", + "CULL_FACE", + "DEPTH_TEST", + "DITHER", + "POLYGON_OFFSET_FILL", + "SAMPLE_ALPHA_TO_COVERAGE", + "SAMPLE_COVERAGE", + "SCISSOR_TEST", + "STENCIL_TEST" +]; + +/** + * @const + * @type {Array.<string>} + */ +WebGLRenderingContextResource.PixelStoreParameters = [ + "PACK_ALIGNMENT", + "UNPACK_ALIGNMENT", + "UNPACK_COLORSPACE_CONVERSION_WEBGL", + "UNPACK_FLIP_Y_WEBGL", + "UNPACK_PREMULTIPLY_ALPHA_WEBGL" +]; + +/** + * @const + * @type {Array.<string>} + */ +WebGLRenderingContextResource.StateParameters = [ + "ACTIVE_TEXTURE", + "ARRAY_BUFFER_BINDING", + "BLEND_COLOR", + "BLEND_DST_ALPHA", + "BLEND_DST_RGB", + "BLEND_EQUATION_ALPHA", + "BLEND_EQUATION_RGB", + "BLEND_SRC_ALPHA", + "BLEND_SRC_RGB", + "COLOR_CLEAR_VALUE", + "COLOR_WRITEMASK", + "CULL_FACE_MODE", + "CURRENT_PROGRAM", + "DEPTH_CLEAR_VALUE", + "DEPTH_FUNC", + "DEPTH_RANGE", + "DEPTH_WRITEMASK", + "ELEMENT_ARRAY_BUFFER_BINDING", + "FRAMEBUFFER_BINDING", + "FRONT_FACE", + "GENERATE_MIPMAP_HINT", + "LINE_WIDTH", + "PACK_ALIGNMENT", + "POLYGON_OFFSET_FACTOR", + "POLYGON_OFFSET_UNITS", + "RENDERBUFFER_BINDING", + "SAMPLE_COVERAGE_INVERT", + "SAMPLE_COVERAGE_VALUE", + "SCISSOR_BOX", + "STENCIL_BACK_FAIL", + "STENCIL_BACK_FUNC", + "STENCIL_BACK_PASS_DEPTH_FAIL", + "STENCIL_BACK_PASS_DEPTH_PASS", + "STENCIL_BACK_REF", + "STENCIL_BACK_VALUE_MASK", + "STENCIL_BACK_WRITEMASK", + "STENCIL_CLEAR_VALUE", + "STENCIL_FAIL", + "STENCIL_FUNC", + "STENCIL_PASS_DEPTH_FAIL", + "STENCIL_PASS_DEPTH_PASS", + "STENCIL_REF", + "STENCIL_VALUE_MASK", + "STENCIL_WRITEMASK", + "UNPACK_ALIGNMENT", + "UNPACK_COLORSPACE_CONVERSION_WEBGL", + "UNPACK_FLIP_Y_WEBGL", + "UNPACK_PREMULTIPLY_ALPHA_WEBGL", + "VIEWPORT" +]; + +/** + * @param {*} obj + * @return {WebGLRenderingContextResource} + */ +WebGLRenderingContextResource.forObject = function(obj) +{ + var resource = Resource.forObject(obj); + if (!resource || resource instanceof WebGLRenderingContextResource) + return resource; + var call = resource.calls(); + if (!call || !call.length) + return null; + resource = call[0].resource(); + return (resource instanceof WebGLRenderingContextResource) ? resource : null; } WebGLRenderingContextResource.prototype = { @@ -460,39 +1227,321 @@ WebGLRenderingContextResource.prototype = { }, /** + * @return {Array.<number>} + */ + getAllErrors: function() + { + var errors = []; + var gl = this.wrappedObject(); + if (gl) { + while (true) { + var error = gl.getError(); + if (error === gl.NO_ERROR) + break; + this.clearError(error); + errors.push(error); + } + } + if (this._customErrors) { + for (var key in this._customErrors) { + var error = Number(key); + errors.push(error); + } + delete this._customErrors; + } + return errors; + }, + + /** + * @param {Array.<number>} errors + */ + restoreErrors: function(errors) + { + var gl = this.wrappedObject(); + if (gl) { + var wasError = false; + while (gl.getError() !== gl.NO_ERROR) + wasError = true; + console.assert(!wasError, "Error(s) while capturing current WebGL state."); + } + if (!errors.length) + delete this._customErrors; + else { + this._customErrors = {}; + for (var i = 0, n = errors.length; i < n; ++i) + this._customErrors[errors[i]] = true; + } + }, + + /** + * @param {number} error + */ + clearError: function(error) + { + if (this._customErrors) + delete this._customErrors[error]; + }, + + /** + * @return {number} + */ + nextError: function() + { + if (this._customErrors) { + for (var key in this._customErrors) { + var error = Number(key); + delete this._customErrors[error]; + return error; + } + } + delete this._customErrors; + var gl = this.wrappedObject(); + return gl ? gl.NO_ERROR : 0; + }, + + /** + * @override + * @param {Object} data + * @param {Cache} cache + */ + _populateReplayableData: function(data, cache) + { + var gl = this.wrappedObject(); + data.replayContextCallback = this._replayContextCallback; + + var originalErrors = this.getAllErrors(); + + // Take a full GL state snapshot. + var glState = {}; + WebGLRenderingContextResource.GLCapabilities.forEach(function(parameter) { + glState[parameter] = gl.isEnabled(gl[parameter]); + }); + WebGLRenderingContextResource.StateParameters.forEach(function(parameter) { + glState[parameter] = Resource.toReplayable(gl.getParameter(gl[parameter]), cache); + }); + + // VERTEX_ATTRIB_ARRAYS + var maxVertexAttribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS); + var vertexAttribParameters = ["VERTEX_ATTRIB_ARRAY_BUFFER_BINDING", "VERTEX_ATTRIB_ARRAY_ENABLED", "VERTEX_ATTRIB_ARRAY_SIZE", "VERTEX_ATTRIB_ARRAY_STRIDE", "VERTEX_ATTRIB_ARRAY_TYPE", "VERTEX_ATTRIB_ARRAY_NORMALIZED", "CURRENT_VERTEX_ATTRIB"]; + var vertexAttribStates = []; + for (var i = 0; i < maxVertexAttribs; ++i) { + var state = {}; + vertexAttribParameters.forEach(function(attribParameter) { + state[attribParameter] = Resource.toReplayable(gl.getVertexAttrib(i, gl[attribParameter]), cache); + }); + state.VERTEX_ATTRIB_ARRAY_POINTER = gl.getVertexAttribOffset(i, gl.VERTEX_ATTRIB_ARRAY_POINTER); + vertexAttribStates.push(state); + } + glState.vertexAttribStates = vertexAttribStates; + + // TEXTURES + var currentTextureBinding = gl.getParameter(gl.ACTIVE_TEXTURE); + var maxTextureImageUnits = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS); + var textureBindings = []; + for (var i = 0; i < maxTextureImageUnits; ++i) { + gl.activeTexture(gl.TEXTURE0 + i); + var state = { + TEXTURE_2D: Resource.toReplayable(gl.getParameter(gl.TEXTURE_BINDING_2D), cache), + TEXTURE_CUBE_MAP: Resource.toReplayable(gl.getParameter(gl.TEXTURE_BINDING_CUBE_MAP), cache) + }; + textureBindings.push(state); + } + glState.textureBindings = textureBindings; + gl.activeTexture(currentTextureBinding); + + data.glState = glState; + + this.restoreErrors(originalErrors); + }, + + /** + * @override + * @param {Object} data + * @param {Cache} cache + */ + _doReplayCalls: function(data, cache) + { + this._replayContextCallback = data.replayContextCallback; + this._proxyObject = null; + this._customErrors = null; + + var gl = Resource.wrappedObject(this._replayContextCallback()); + this.setWrappedObject(gl); + + var glState = data.glState; + gl.bindFramebuffer(gl.FRAMEBUFFER, ReplayableResource.replay(glState.FRAMEBUFFER_BINDING, cache)); + gl.bindRenderbuffer(gl.RENDERBUFFER, ReplayableResource.replay(glState.RENDERBUFFER_BINDING, cache)); + + // Enable or disable server-side GL capabilities. + WebGLRenderingContextResource.GLCapabilities.forEach(function(parameter) { + console.assert(parameter in glState); + if (glState[parameter]) + gl.enable(gl[parameter]); + else + gl.disable(gl[parameter]); + }); + + gl.blendColor(glState.BLEND_COLOR[0], glState.BLEND_COLOR[1], glState.BLEND_COLOR[2], glState.BLEND_COLOR[3]); + gl.blendEquationSeparate(glState.BLEND_EQUATION_RGB, glState.BLEND_EQUATION_ALPHA); + gl.blendFuncSeparate(glState.BLEND_SRC_RGB, glState.BLEND_DST_RGB, glState.BLEND_SRC_ALPHA, glState.BLEND_DST_ALPHA); + gl.clearColor(glState.COLOR_CLEAR_VALUE[0], glState.COLOR_CLEAR_VALUE[1], glState.COLOR_CLEAR_VALUE[2], glState.COLOR_CLEAR_VALUE[3]); + gl.clearDepth(glState.DEPTH_CLEAR_VALUE); + gl.clearStencil(glState.STENCIL_CLEAR_VALUE); + gl.colorMask(glState.COLOR_WRITEMASK[0], glState.COLOR_WRITEMASK[1], glState.COLOR_WRITEMASK[2], glState.COLOR_WRITEMASK[3]); + gl.cullFace(glState.CULL_FACE_MODE); + gl.depthFunc(glState.DEPTH_FUNC); + gl.depthMask(glState.DEPTH_WRITEMASK); + gl.depthRange(glState.DEPTH_RANGE[0], glState.DEPTH_RANGE[1]); + gl.frontFace(glState.FRONT_FACE); + gl.hint(gl.GENERATE_MIPMAP_HINT, glState.GENERATE_MIPMAP_HINT); + gl.lineWidth(glState.LINE_WIDTH); + + WebGLRenderingContextResource.PixelStoreParameters.forEach(function(parameter) { + gl.pixelStorei(gl[parameter], glState[parameter]); + }); + + gl.polygonOffset(glState.POLYGON_OFFSET_FACTOR, glState.POLYGON_OFFSET_UNITS); + gl.sampleCoverage(glState.SAMPLE_COVERAGE_VALUE, glState.SAMPLE_COVERAGE_INVERT); + gl.stencilFuncSeparate(gl.FRONT, glState.STENCIL_FUNC, glState.STENCIL_REF, glState.STENCIL_VALUE_MASK); + gl.stencilFuncSeparate(gl.BACK, glState.STENCIL_BACK_FUNC, glState.STENCIL_BACK_REF, glState.STENCIL_BACK_VALUE_MASK); + gl.stencilOpSeparate(gl.FRONT, glState.STENCIL_FAIL, glState.STENCIL_PASS_DEPTH_FAIL, glState.STENCIL_PASS_DEPTH_PASS); + gl.stencilOpSeparate(gl.BACK, glState.STENCIL_BACK_FAIL, glState.STENCIL_BACK_PASS_DEPTH_FAIL, glState.STENCIL_BACK_PASS_DEPTH_PASS); + gl.stencilMaskSeparate(gl.FRONT, glState.STENCIL_WRITEMASK); + gl.stencilMaskSeparate(gl.BACK, glState.STENCIL_BACK_WRITEMASK); + + gl.scissor(glState.SCISSOR_BOX[0], glState.SCISSOR_BOX[1], glState.SCISSOR_BOX[2], glState.SCISSOR_BOX[3]); + gl.viewport(glState.VIEWPORT[0], glState.VIEWPORT[1], glState.VIEWPORT[2], glState.VIEWPORT[3]); + + gl.useProgram(ReplayableResource.replay(glState.CURRENT_PROGRAM, cache)); + + // VERTEX_ATTRIB_ARRAYS + var maxVertexAttribs = gl.getParameter(gl.MAX_VERTEX_ATTRIBS); + for (var i = 0; i < maxVertexAttribs; ++i) { + var state = glState.vertexAttribStates[i] || {}; + if (state.VERTEX_ATTRIB_ARRAY_ENABLED) + gl.enableVertexAttribArray(i); + else + gl.disableVertexAttribArray(i); + if (state.CURRENT_VERTEX_ATTRIB) + gl.vertexAttrib4fv(i, state.CURRENT_VERTEX_ATTRIB); + var buffer = ReplayableResource.replay(state.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, cache); + if (buffer) { + gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + gl.vertexAttribPointer(i, state.VERTEX_ATTRIB_ARRAY_SIZE, state.VERTEX_ATTRIB_ARRAY_TYPE, state.VERTEX_ATTRIB_ARRAY_NORMALIZED, state.VERTEX_ATTRIB_ARRAY_STRIDE, state.VERTEX_ATTRIB_ARRAY_POINTER); + } + } + gl.bindBuffer(gl.ARRAY_BUFFER, ReplayableResource.replay(glState.ARRAY_BUFFER_BINDING, cache)); + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ReplayableResource.replay(glState.ELEMENT_ARRAY_BUFFER_BINDING, cache)); + + // TEXTURES + var maxTextureImageUnits = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS); + for (var i = 0; i < maxTextureImageUnits; ++i) { + gl.activeTexture(gl.TEXTURE0 + i); + var state = glState.textureBindings[i] || {}; + gl.bindTexture(gl.TEXTURE_2D, ReplayableResource.replay(state.TEXTURE_2D, cache)); + gl.bindTexture(gl.TEXTURE_CUBE_MAP, ReplayableResource.replay(state.TEXTURE_CUBE_MAP, cache)); + } + gl.activeTexture(glState.ACTIVE_TEXTURE); + + return Resource.prototype._doReplayCalls.call(this, data, cache); + }, + + /** + * @param {Object|number} target + * @return {Resource} + */ + currentBinding: function(target) + { + var resource = Resource.forObject(target); + if (resource) + return resource; + var gl = this.wrappedObject(); + var bindingParameter; + var bindMethodName; + var bindMethodTarget = target; + switch (target) { + case gl.ARRAY_BUFFER: + bindingParameter = gl.ARRAY_BUFFER_BINDING; + bindMethodName = "bindBuffer"; + break; + case gl.ELEMENT_ARRAY_BUFFER: + bindingParameter = gl.ELEMENT_ARRAY_BUFFER_BINDING; + bindMethodName = "bindBuffer"; + break; + case gl.TEXTURE_2D: + bindingParameter = gl.TEXTURE_BINDING_2D; + bindMethodName = "bindTexture"; + break; + case gl.TEXTURE_CUBE_MAP: + case gl.TEXTURE_CUBE_MAP_POSITIVE_X: + case gl.TEXTURE_CUBE_MAP_NEGATIVE_X: + case gl.TEXTURE_CUBE_MAP_POSITIVE_Y: + case gl.TEXTURE_CUBE_MAP_NEGATIVE_Y: + case gl.TEXTURE_CUBE_MAP_POSITIVE_Z: + case gl.TEXTURE_CUBE_MAP_NEGATIVE_Z: + bindingParameter = gl.TEXTURE_BINDING_CUBE_MAP; + bindMethodTarget = gl.TEXTURE_CUBE_MAP; + bindMethodName = "bindTexture"; + break; + case gl.FRAMEBUFFER: + bindingParameter = gl.FRAMEBUFFER_BINDING; + bindMethodName = "bindFramebuffer"; + break; + case gl.RENDERBUFFER: + bindingParameter = gl.RENDERBUFFER_BINDING; + bindMethodName = "bindRenderbuffer"; + break; + default: + console.error("ASSERT_NOT_REACHED: unknown binding target " + target); + return null; + } + resource = Resource.forObject(gl.getParameter(bindingParameter)); + if (resource) + resource.pushBinding(bindMethodTarget, bindMethodName); + return resource; + }, + + /** * @return {Object} */ _wrapObject: function() { - var glContext = this.wrappedObject(); - var proxy = Object.create(glContext.__proto__); // In order to emulate "instanceof". + var gl = this.wrappedObject(); + var proxy = Object.create(gl.__proto__); // In order to emulate "instanceof". var self = this; + var customWrapFunctions = WebGLRenderingContextResource.wrapFunctions(); function processProperty(property) { - if (typeof glContext[property] === "function") { - // FIXME: override GL calls affecting resources states here. - proxy[property] = self._wrapFunction(self, glContext, glContext[property], property); + if (typeof gl[property] === "function") { + var customWrapFunction = customWrapFunctions[property]; + if (customWrapFunction) + proxy[property] = self._wrapCustomFunction(self, gl, gl[property], property, customWrapFunction); + else + proxy[property] = self._wrapFunction(self, gl, gl[property], property); } else if (/^[A-Z0-9_]+$/.test(property)) { // Fast access to enums and constants. - proxy[property] = glContext[property]; + console.assert(typeof gl[property] === "number", "Expected a number for property " + property); + proxy[property] = gl[property]; } else { Object.defineProperty(proxy, property, { get: function() { - return glContext[property]; + return gl[property]; }, set: function(value) { - glContext[property] = value; + console.error("ASSERT_NOT_REACHED: We assume all WebGLRenderingContext attributes are readonly. Trying to mutate " + property); + gl[property] = value; } }); } } - for (var property in glContext) + for (var property in gl) processProperty(property); + this._bindObjectToResource(proxy); return proxy; }, @@ -501,7 +1550,33 @@ WebGLRenderingContextResource.prototype = { * @param {WebGLRenderingContext} originalObject * @param {Function} originalFunction * @param {string} functionName - * @return {*} + * @param {Function} customWrapFunction + * @return {Function} + */ + _wrapCustomFunction: function(resource, originalObject, originalFunction, functionName, customWrapFunction) + { + return function() + { + var manager = resource.manager(); + if (manager) + manager.captureArguments(resource, arguments); + var wrapFunction = new WebGLRenderingContextResource.WrapFunction(originalObject, originalFunction, functionName, arguments); + customWrapFunction.apply(wrapFunction, arguments); + if (manager && manager.capturing()) { + var call = wrapFunction.call(); + call.setStackTrace(StackTrace.create(1, arguments.callee)); + manager.reportCall(call); + } + return wrapFunction.result(); + }; + }, + + /** + * @param {Resource} resource + * @param {WebGLRenderingContext} originalObject + * @param {Function} originalFunction + * @param {string} functionName + * @return {Function} */ _wrapFunction: function(resource, originalObject, originalFunction, functionName) { @@ -512,7 +1587,8 @@ WebGLRenderingContextResource.prototype = { return originalFunction.apply(originalObject, arguments); manager.captureArguments(resource, arguments); var result = originalFunction.apply(originalObject, arguments); - var call = new Call(resource, functionName, arguments, result); + var stackTrace = StackTrace.create(1, arguments.callee); + var call = new Call(resource, functionName, arguments, result, stackTrace); manager.reportCall(call); return result; }; @@ -558,10 +1634,117 @@ WebGLRenderingContextResource.WrapFunction.prototype = { if (!this._call) this._call = new Call(this._glResource, this._functionName, this._args, this.result()); return this._call; + }, + + /** + * @param {*} result + */ + _overrideResult: function(result) + { + var call = this.call(); + call.setResult(result); + this._result = result; } } /** + * @return {Object.<string, Function>} + */ +WebGLRenderingContextResource.wrapFunctions = function() +{ + var wrapFunctions = WebGLRenderingContextResource._wrapFunctions; + if (!wrapFunctions) { + wrapFunctions = Object.create(null); + + /** + * @param {string} methodName + * @param {Function} resourceConstructor + */ + function createResourceWrapFunction(methodName, resourceConstructor) + { + /** @this WebGLRenderingContextResource.WrapFunction */ + wrapFunctions[methodName] = function() + { + var wrappedObject = this.result(); + if (!wrappedObject) + return; + var resource = new resourceConstructor(wrappedObject); + var manager = this._glResource.manager(); + if (manager) + manager.registerResource(resource); + resource.pushCall(this.call()); + } + } + createResourceWrapFunction("createBuffer", WebGLBufferResource); + createResourceWrapFunction("createShader", WebGLShaderResource); + createResourceWrapFunction("createProgram", WebGLProgramResource); + createResourceWrapFunction("createTexture", WebGLTextureResource); + createResourceWrapFunction("createFramebuffer", WebGLFramebufferResource); + createResourceWrapFunction("createRenderbuffer", WebGLRenderbufferResource); + createResourceWrapFunction("getUniformLocation", Resource); + + /** + * @param {string} methodName + */ + function customWrapFunction(methodName) + { + var customPushCall = "pushCall_" + methodName; + /** + * @param {Object|number} target + * @this WebGLRenderingContextResource.WrapFunction + */ + wrapFunctions[methodName] = function(target) + { + var resource = this._glResource.currentBinding(target); + if (!resource) + return; + if (resource[customPushCall]) + resource[customPushCall].call(resource, this.call()); + else + resource.pushCall(this.call()); + } + } + customWrapFunction("attachShader"); + customWrapFunction("bindAttribLocation"); + customWrapFunction("compileShader"); + customWrapFunction("detachShader"); + customWrapFunction("linkProgram"); + customWrapFunction("shaderSource"); + customWrapFunction("bufferData"); + customWrapFunction("bufferSubData"); + customWrapFunction("compressedTexImage2D"); + customWrapFunction("compressedTexSubImage2D"); + customWrapFunction("copyTexImage2D"); + customWrapFunction("copyTexSubImage2D"); + customWrapFunction("generateMipmap"); + customWrapFunction("texImage2D"); + customWrapFunction("texSubImage2D"); + customWrapFunction("texParameterf"); + customWrapFunction("texParameteri"); + customWrapFunction("framebufferRenderbuffer"); + customWrapFunction("framebufferTexture2D"); + customWrapFunction("renderbufferStorage"); + + /** @this WebGLRenderingContextResource.WrapFunction */ + wrapFunctions["getError"] = function() + { + var gl = this._originalObject; + var error = this.result(); + if (error !== gl.NO_ERROR) + this._glResource.clearError(error); + else { + error = this._glResource.nextError(); + if (error !== gl.NO_ERROR) + this._overrideResult(error); + } + } + + WebGLRenderingContextResource._wrapFunctions = wrapFunctions; + } + return wrapFunctions; +} + +/** * @constructor */ function TraceLog() @@ -592,7 +1775,7 @@ TraceLog.prototype = { */ captureResource: function(resource) { - // FIXME: Capture current resource state to start the replay from. + resource.toReplayable(this._replayablesCache); }, /** @@ -600,7 +1783,12 @@ TraceLog.prototype = { */ addCall: function(call) { - // FIXME: Convert the call to a ReplayableCall and push it. + var res = Resource.forObject(call.result()); + if (res) + this.captureResource(res); + var size = this._replayablesCache.size(); + this._replayableCalls.push(call.toReplayable(this._replayablesCache)); + console.assert(this._replayablesCache.size() === size, "Internal error: We should have captured all the resources already by this time."); } } @@ -656,7 +1844,7 @@ TraceLogPlayer.prototype = { // FIXME: Replay all the cached resources first to warm-up. var replayableCalls = this._traceLog.replayableCalls(); while (this._nextReplayStep <= stepNum) - replayableCalls[this._nextReplayStep++].replay(this._replayWorldCache); + replayableCalls[this._nextReplayStep++].replay(this._replayWorldCache); }, replay: function() @@ -789,7 +1977,7 @@ InjectedScript.prototype = { */ wrapWebGLContext: function(glContext) { - var resource = Resource.forObject(glContext) || new WebGLRenderingContextResource(glContext); + var resource = Resource.forObject(glContext) || new WebGLRenderingContextResource(glContext, this._constructWebGLReplayContext.bind(this, glContext)); this._manager.registerResource(resource); var proxy = resource.proxyObject(); return proxy; @@ -829,9 +2017,21 @@ InjectedScript.prototype = { var calls = traceLog.replayableCalls(); for (var i = 0, n = calls.length; i < n; ++i) { var call = calls[i]; - result.calls.push({ - functionName: call.functionName() + "(" + call.args().join(", ") + ") => " + call.result() + var args = call.args().map(function(argument) { + return argument + ""; }); + var stackTrace = call.stackTrace(); + var callFrame = stackTrace ? stackTrace.callFrame(0) || {} : {}; + var traceLogItem = { + functionName: call.functionName(), + arguments: args, + sourceURL: callFrame.sourceURL, + lineNumber: callFrame.lineNumber, + columnNumber: callFrame.columnNumber + }; + if (call.result()) + traceLogItem.result = call.result() + ""; + result.calls.push(traceLogItem); } return result; }, @@ -854,6 +2054,7 @@ InjectedScript.prototype = { return ""; } // Return current screenshot. + // FIXME: Support replaying several canvases simultaneously. return this._replayContext.canvas.toDataURL(); }, @@ -863,6 +2064,37 @@ InjectedScript.prototype = { _makeTraceLogId: function() { return "{\"injectedScriptId\":" + injectedScriptId + ",\"traceLogId\":" + (++this._lastTraceLogId) + "}"; + }, + + /** + * @param {WebGLRenderingContext} originalGlContext + * @return {WebGLRenderingContext} + */ + _constructWebGLReplayContext: function(originalGlContext) + { + var replayContext = originalGlContext["__replayContext"]; + if (!replayContext) { + var canvas = originalGlContext.canvas.cloneNode(true); + var attributes = originalGlContext.getContextAttributes(); + var contextIds = ["experimental-webgl", "webkit-3d", "3d"]; + for (var i = 0, contextId; contextId = contextIds[i]; ++i) { + replayContext = canvas.getContext(contextId, attributes); + if (replayContext) { + replayContext = /** @type {WebGLRenderingContext} */ Resource.wrappedObject(replayContext); + break; + } + } + Object.defineProperty(originalGlContext, "__replayContext", { + value: replayContext, + writable: false, + enumerable: false, + configurable: true + }); + this._replayContext = replayContext; + } else { + // FIXME: Reset the replay GL state and clear the canvas. + } + return replayContext; } } diff --git a/Source/WebCore/inspector/Inspector.json b/Source/WebCore/inspector/Inspector.json index 4aba46a69..8184cc008 100644 --- a/Source/WebCore/inspector/Inspector.json +++ b/Source/WebCore/inspector/Inspector.json @@ -594,17 +594,18 @@ { "name": "enabled", "type": "boolean", "description": "Reporting enabled state." } ], "hidden": true, - "description": "Enables reporting about creation of isolated contexts by means of <code>isolatedContextCreated</code> event. When the reporting gets enabled the event will be sent immediately for each existing isolated context." + "description": "Enables reporting about creation of execution contexts by means of <code>executionContextCreated</code> event. When the reporting gets enabled the event will be sent immediately for each existing execution context." } ], "events": [ { - "name": "isolatedContextCreated", + "name": "executionContextCreated", "parameters": [ - { "name": "context", "$ref": "ExecutionContextDescription", "description": "A newly created isolated contex." } + { "name": "context", "$ref": "ExecutionContextDescription", "description": "A newly created execution contex." } ], - "description": "Issued when new isolated context is created." + "hidden": true, + "description": "Issued when new execution context is created." } ] }, @@ -1073,7 +1074,11 @@ { "id": "Error", "type": "object", - "description": "Database error." + "description": "Database error.", + "properties": [ + { "name": "message", "type": "string", "description": "Error message." }, + { "name": "code", "type": "integer", "description": "Error code." } + ] } ], "commands": [ @@ -1096,13 +1101,15 @@ }, { "name": "executeSQL", + "async": true, "parameters": [ { "name": "databaseId", "$ref": "DatabaseId" }, { "name": "query", "type": "string" } ], "returns": [ - { "name": "success", "type": "boolean" }, - { "name": "transactionId", "type": "integer" } + { "name": "columnNames", "type": "array", "optional": true, "items": { "type": "string" } }, + { "name": "values", "type": "array", "optional": true, "items": { "type": "any" }}, + { "name": "sqlError", "$ref": "Error", "optional": true } ] } ], @@ -1112,21 +1119,6 @@ "parameters": [ { "name": "database", "$ref": "Database" } ] - }, - { - "name": "sqlTransactionSucceeded", - "parameters": [ - { "name": "transactionId", "type": "integer" }, - { "name": "columnNames", "type": "array", "items": { "type": "string" } }, - { "name": "values", "type": "array", "items": { "type": "any" }} - ] - }, - { - "name": "sqlTransactionFailed", - "parameters": [ - { "name": "transactionId", "type": "integer" }, - { "name": "sqlError", "$ref": "Error" } - ] } ] }, @@ -1230,25 +1222,31 @@ }, { "name": "requestDatabaseNamesForFrame", + "async": true, "parameters": [ - { "name": "requestId", "type": "integer", "description": "Request id." }, { "name": "frameId", "$ref": "Network.FrameId", "description": "Frame id." } ], + "returns": [ + { "name": "securityOriginWithDatabaseNames", "$ref": "SecurityOriginWithDatabaseNames", "description": "Frame with database names." } + ], "description": "Requests database names for given frame's security origin." }, { "name": "requestDatabase", + "async": true, "parameters": [ - { "name": "requestId", "type": "integer", "description": "Request id." }, { "name": "frameId", "$ref": "Network.FrameId", "description": "Frame id." }, { "name": "databaseName", "type": "string", "description": "Database name." } ], + "returns": [ + { "name": "databaseWithObjectStores", "$ref": "DatabaseWithObjectStores", "description": "Database with an array of object stores." } + ], "description": "Requests database with given name in given frame." }, { "name": "requestData", + "async": true, "parameters": [ - { "name": "requestId", "type": "integer", "description": "Request id." }, { "name": "frameId", "$ref": "Network.FrameId", "description": "Frame id." }, { "name": "databaseName", "type": "string", "description": "Database name." }, { "name": "objectStoreName", "type": "string", "description": "Object store name." }, @@ -1257,39 +1255,11 @@ { "name": "pageSize", "type": "integer", "description": "Number of records to fetch." }, { "name": "keyRange", "$ref": "KeyRange", "optional": true, "description": "Key range." } ], - "description": "Requests data from object store or index." - } - ], - "events": [ - { - "name": "databaseNamesLoaded", - "parameters": [ - { "name": "requestId", "type": "number", "description": "Request id." }, - { "name": "securityOriginWithDatabaseNames", "$ref": "SecurityOriginWithDatabaseNames", "description": "Frame with database names." } - ] - }, - { - "name": "databaseLoaded", - "parameters": [ - { "name": "requestId", "type": "integer", "description": "Request id." }, - { "name": "databaseWithObjectStores", "$ref": "DatabaseWithObjectStores", "description": "Database with an array of object stores." } - ] - }, - { - "name": "objectStoreDataLoaded", - "parameters": [ - { "name": "requestId", "type": "integer", "description": "Request id." }, + "returns": [ { "name": "objectStoreDataEntries", "type": "array", "items": { "$ref": "DataEntry" }, "description": "Array of object store data entries." }, { "name": "hasMore", "type": "boolean", "description": "If true, there are more entries to fetch in the given range." } - ] - }, - { - "name": "indexDataLoaded", - "parameters": [ - { "name": "requestId", "type": "integer", "description": "Request id." }, - { "name": "indexDataEntries", "type": "array", "items": { "$ref": "DataEntry" }, "description": "Array of index data entries." }, - { "name": "hasMore", "type": "boolean", "description": "If true, there are more entries to fetch in the given range." } - ] + ], + "description": "Requests data from object store or index." } ] }, @@ -1469,11 +1439,6 @@ "hidden": true, "types": [ { - "id": "RequestId", - "type": "integer", - "description": "Request Identifier to glue a request and its completion event." - }, - { "id": "Entry", "type": "object", "properties": [ @@ -1507,37 +1472,44 @@ }, { "name": "requestFileSystemRoot", + "async": true, "parameters": [ { "name": "origin", "type": "string", "description": "Security origin of requesting FileSystem. One of frames in current page needs to have this security origin." }, { "name": "type", "type": "string", "enum": ["temporary", "persistent"], "description": "FileSystem type of requesting FileSystem." } ], "returns": [ - { "name": "requestId", "$ref": "RequestId", "description": "Request identifier. Corresponding fileSystemRootReceived event should have same requestId with this." } + { "name": "errorCode", "type": "integer", "description": "0, if no error. Otherwise, errorCode is set to FileError::ErrorCode value." }, + { "name": "root", "$ref": "Entry", "optional": true, "description": "Contains root of the requested FileSystem if the command completed successfully." } ], - "description": "Returns root directory of the FileSystem as fileSystemRootReceived event, if exists." + "description": "Returns root directory of the FileSystem, if exists." }, { "name": "requestDirectoryContent", + "async": true, "parameters": [ { "name": "url", "type": "string", "description": "URL of the directory that the frontend is requesting to read from." } ], "returns": [ - { "name": "requestId", "$ref": "RequestId", "description": "Request identifier. Corresponding directoryContentReceived event should have same requestId with this." } + { "name": "errorCode", "type": "integer", "description": "0, if no error. Otherwise, errorCode is set to FileError::ErrorCode value." }, + { "name": "entries", "type": "array", "items": { "$ref": "Entry" }, "optional": true, "description": "Contains all entries on directory if the command completed successfully." } ], - "description": "Returns content of the directory as directoryContentReceived event." + "description": "Returns content of the directory." }, { "name": "requestMetadata", + "async": true, "parameters": [ { "name": "url", "type": "string", "description": "URL of the entry that the frontend is requesting to get metadata from." } ], "returns": [ - { "name": "requestId", "$ref": "RequestId", "description": "Request identifier. Corresponding metadataReceived event should have same requestId with this." } + { "name": "errorCode", "type": "integer", "description": "0, if no error. Otherwise, errorCode is set to FileError::ErrorCode value." }, + { "name": "metadata", "$ref": "Metadata", "optional": true, "description": "Contains metadata of the entry if the command completed successfully." } ], - "description": "Returns metadata of the entry as metadataReceived event." + "description": "Returns metadata of the entry." }, { "name": "requestFileContent", + "async": true, "parameters": [ { "name": "url", "type": "string", "description": "URL of the file that the frontend is requesting to read from." }, { "name": "readAsText", "type": "boolean", "description": "True if the content should be read as text, otherwise the result will be returned as base64 encoded text." }, @@ -1546,66 +1518,22 @@ { "name": "charset", "type": "string", "optional": true, "description": "Overrides charset of the content when content is served as text." } ], "returns": [ - { "name": "requestId", "$ref": "RequestId", "description": "Request identifier. Corresponding fileContentReceived event should have same requestId with this." } + { "name": "errorCode", "type": "integer", "description": "0, if no error. Otherwise, errorCode is set to FileError::ErrorCode value." }, + { "name": "content", "type": "string", "optional": true, "description": "Content of the file." }, + { "name": "charset", "type": "string", "optional": true, "description": "Charset of the content if it is served as text." } ], - "description": "Returns content of the file as fileContentReceived event. Result should be sliced into [start, end)." + "description": "Returns content of the file. Result should be sliced into [start, end)." }, { "name": "deleteEntry", + "async": true, "parameters": [ { "name": "url", "type": "string", "description": "URL of the entry to delete." } ], "returns": [ - { "name": "requestId", "$ref": "RequestId", "description": "Request identifier. Corresponding deletionCompleted event should have same requestId with this." } - ], - "description": "Deletes specified entry. If the entry is a directory, the agent deletes children recursively." - } - ], - "events": [ - { - "name": "fileSystemRootReceived", - "parameters": [ - { "name": "requestId", "type": "integer", "description": "Request Identifier that was returned by corresponding requestFileSystemRoot command." }, - { "name": "errorCode", "type": "integer", "description": "0, if no error. Otherwise, errorCode is set to FileError::ErrorCode value." }, - { "name": "root", "$ref": "Entry", "optional": true, "description": "Contains root of the requested FileSystem if the command completed successfully." } - ], - "description": "Completion event of requestFileSystemRoot command." - }, - { - "name": "directoryContentReceived", - "parameters": [ - { "name": "requestId", "type": "integer", "description": "Request Identifier that was returned by corresponding requestDirectoryContent command." }, - { "name": "errorCode", "type": "integer", "description": "0, if no error. Otherwise, errorCode is set to FileError::ErrorCode value." }, - { "name": "entries", "type": "array", "items": { "$ref": "Entry" }, "optional": true, "description": "Contains all entries on directory if the command completed successfully." } - ], - "description": "Completion event of requestDirectoryContent command." - }, - { - "name": "metadataReceived", - "parameters": [ - { "name": "requestId", "type": "integer", "description": "Request Identifier that was returned in response to the corresponding requestMetadata command." }, - { "name": "errorCode", "type": "integer", "description": "0, if no error. Otherwise, errorCode is set to FileError::ErrorCode value." }, - { "name": "metadata", "$ref": "Metadata", "optional": true, "description": "Contains metadata of the entry if the command completed successfully." } - ], - "description": "Completion event of requestMetadata command." - }, - { - "name": "fileContentReceived", - "parameters": [ - { "name": "requestId", "type": "integer", "description": "Request Identifier that was returned in response to the corresponding requestFileContent command." }, - { "name": "errorCode", "type": "integer", "description": "0, if no error. Otherwise, errorCode is set to FileError::ErrorCode value." }, - { "name": "content", "type": "string", "optional": true, "description": "Content of the file." }, - { "name": "charset", "type": "string", "optional": true, "description": "Charset of the content if it is served as text." } - ], - "description": "Completion event of requestFileContent command." - }, - { - "name": "deletionCompleted", - "parameters": [ - { "name": "requestId", "type": "integer", "description": "Request Identifier that was returned in response to the corresponding deleteEntry command." }, { "name": "errorCode", "type": "integer", "description": "0, if no error. Otherwise errorCode is set to FileError::ErrorCode value." } ], - "description": "Completion event of deleteEntry command." + "description": "Deletes specified entry. If the entry is a directory, the agent deletes children recursively." } ] }, @@ -2836,7 +2764,7 @@ "name": "paused", "parameters": [ { "name": "callFrames", "type": "array", "items": { "$ref": "CallFrame" }, "description": "Call stack the virtual machine stopped on." }, - { "name": "reason", "type": "string", "enum": [ "XHR", "DOM", "EventListener", "exception", "other" ], "description": "Pause reason." }, + { "name": "reason", "type": "string", "enum": [ "XHR", "DOM", "EventListener", "exception", "assert", "other" ], "description": "Pause reason." }, { "name": "data", "type": "object", "optional": true, "description": "Object containing break-specific auxiliary properties." } ], "description": "Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria." @@ -3149,7 +3077,12 @@ "id": "Call", "type": "object", "properties": [ - { "name": "functionName", "type": "string" } + { "name": "functionName", "type": "string" }, + { "name": "arguments", "type": "array", "items": { "type": "string" } }, + { "name": "result", "type": "string", "optional": true }, + { "name": "sourceURL", "type": "string", "optional": true }, + { "name": "lineNumber", "type": "integer", "optional": true }, + { "name": "columnNumber", "type": "integer", "optional": true } ] }, { @@ -3157,7 +3090,7 @@ "type": "object", "properties": [ { "name": "id", "$ref": "TraceLogId" }, - { "name": "calls", "type": "array", "items": { "$ref": "Call" }} + { "name": "calls", "type": "array", "items": { "$ref": "Call" } } ] } ], diff --git a/Source/WebCore/inspector/InspectorAgent.h b/Source/WebCore/inspector/InspectorAgent.h index d510a4db9..3e6fd93f2 100644 --- a/Source/WebCore/inspector/InspectorAgent.h +++ b/Source/WebCore/inspector/InspectorAgent.h @@ -31,11 +31,11 @@ #define InspectorAgent_h #include "InspectorBaseAgent.h" -#include "PlatformString.h" #include <wtf/Forward.h> #include <wtf/HashMap.h> #include <wtf/PassOwnPtr.h> #include <wtf/Vector.h> +#include <wtf/text/WTFString.h> namespace WebCore { diff --git a/Source/WebCore/inspector/InspectorCSSAgent.cpp b/Source/WebCore/inspector/InspectorCSSAgent.cpp index 9d62698de..24c7197b6 100644 --- a/Source/WebCore/inspector/InspectorCSSAgent.cpp +++ b/Source/WebCore/inspector/InspectorCSSAgent.cpp @@ -45,6 +45,7 @@ #include "InspectorTypeBuilder.h" #include "InspectorValues.h" #include "InstrumentingAgents.h" +#include "NamedFlowCollection.h" #include "Node.h" #include "NodeList.h" #include "RenderRegion.h" @@ -54,7 +55,6 @@ #include "StyleRule.h" #include "StyleSheetList.h" #include "WebKitNamedFlow.h" -#include "WebKitNamedFlowCollection.h" #include <wtf/CurrentTime.h> #include <wtf/HashSet.h> @@ -133,10 +133,10 @@ private: static unsigned computePseudoClassMask(InspectorArray* pseudoClassArray) { - DEFINE_STATIC_LOCAL(String, active, ("active")); - DEFINE_STATIC_LOCAL(String, hover, ("hover")); - DEFINE_STATIC_LOCAL(String, focus, ("focus")); - DEFINE_STATIC_LOCAL(String, visited, ("visited")); + DEFINE_STATIC_LOCAL(String, active, (ASCIILiteral("active"))); + DEFINE_STATIC_LOCAL(String, hover, (ASCIILiteral("hover"))); + DEFINE_STATIC_LOCAL(String, focus, (ASCIILiteral("focus"))); + DEFINE_STATIC_LOCAL(String, visited, (ASCIILiteral("visited"))); if (!pseudoClassArray || !pseudoClassArray->length()) return PseudoNone; @@ -326,7 +326,7 @@ public: m_oldText = oldText.stripWhiteSpace(); // FIXME: remove this once the model handles this case. if (!m_oldText.endsWith(';')) - m_oldText += ";"; + m_oldText.append(';'); return result; } diff --git a/Source/WebCore/inspector/InspectorCSSAgent.h b/Source/WebCore/inspector/InspectorCSSAgent.h index 2b82b4c7e..931ed3dfb 100644 --- a/Source/WebCore/inspector/InspectorCSSAgent.h +++ b/Source/WebCore/inspector/InspectorCSSAgent.h @@ -27,18 +27,17 @@ #include "CSSSelector.h" #include "ContentSecurityPolicy.h" -#include "Document.h" #include "InspectorBaseAgent.h" #include "InspectorDOMAgent.h" #include "InspectorStyleSheet.h" #include "InspectorValues.h" -#include "PlatformString.h" #include "SecurityContext.h" #include <wtf/HashMap.h> #include <wtf/HashSet.h> #include <wtf/PassRefPtr.h> #include <wtf/RefPtr.h> +#include <wtf/text/WTFString.h> namespace WebCore { @@ -53,7 +52,9 @@ class InspectorFrontend; class InstrumentingAgents; class NameNodeMap; class Node; +class NodeList; class SelectorProfile; +class StyleResolver; #if ENABLE(INSPECTOR) diff --git a/Source/WebCore/inspector/InspectorClient.cpp b/Source/WebCore/inspector/InspectorClient.cpp index 37c7bc2dc..867e0bbd3 100644 --- a/Source/WebCore/inspector/InspectorClient.cpp +++ b/Source/WebCore/inspector/InspectorClient.cpp @@ -55,9 +55,7 @@ bool InspectorClient::doDispatchMessageOnFrontendPage(Page* frontendPage, const if (!scriptController) return false; - String dispatchToFrontend("WebInspector.dispatchMessageFromBackend("); - dispatchToFrontend += message; - dispatchToFrontend += ");"; + String dispatchToFrontend = "WebInspector.dispatchMessageFromBackend(" + message + ");"; // FIXME: This should execute the script in the appropriate world. scriptController->evaluate(ScriptSourceCode(dispatchToFrontend)); diff --git a/Source/WebCore/inspector/InspectorConsoleAgent.cpp b/Source/WebCore/inspector/InspectorConsoleAgent.cpp index c12a56b0d..2f3e2246d 100644 --- a/Source/WebCore/inspector/InspectorConsoleAgent.cpp +++ b/Source/WebCore/inspector/InspectorConsoleAgent.cpp @@ -47,6 +47,7 @@ #include <wtf/CurrentTime.h> #include <wtf/OwnPtr.h> #include <wtf/PassOwnPtr.h> +#include <wtf/text/StringBuilder.h> #include <wtf/text/WTFString.h> namespace WebCore { @@ -249,11 +250,14 @@ void InspectorConsoleAgent::didFailLoading(unsigned long identifier, const Resou return; if (error.isCancellation()) // Report failures only. return; - String message = "Failed to load resource"; - if (!error.localizedDescription().isEmpty()) - message += ": " + error.localizedDescription(); + StringBuilder message; + message.appendLiteral("Failed to load resource"); + if (!error.localizedDescription().isEmpty()) { + message.appendLiteral(": "); + message.append(error.localizedDescription()); + } String requestId = IdentifiersFactory::requestId(identifier); - addConsoleMessage(adoptPtr(new ConsoleMessage(NetworkMessageSource, LogMessageType, ErrorMessageLevel, message, error.failingURL(), requestId))); + addConsoleMessage(adoptPtr(new ConsoleMessage(NetworkMessageSource, LogMessageType, ErrorMessageLevel, message.toString(), error.failingURL(), requestId))); } void InspectorConsoleAgent::setMonitoringXHREnabled(ErrorString*, bool enabled) diff --git a/Source/WebCore/inspector/InspectorController.h b/Source/WebCore/inspector/InspectorController.h index 90996e5e9..0331e13d5 100644 --- a/Source/WebCore/inspector/InspectorController.h +++ b/Source/WebCore/inspector/InspectorController.h @@ -31,10 +31,10 @@ #ifndef InspectorController_h #define InspectorController_h -#include "PlatformString.h" #include <wtf/Forward.h> #include <wtf/HashMap.h> #include <wtf/Noncopyable.h> +#include <wtf/text/WTFString.h> namespace WebCore { diff --git a/Source/WebCore/inspector/InspectorDOMAgent.cpp b/Source/WebCore/inspector/InspectorDOMAgent.cpp index 5929c729f..ed47b5d0a 100644 --- a/Source/WebCore/inspector/InspectorDOMAgent.cpp +++ b/Source/WebCore/inspector/InspectorDOMAgent.cpp @@ -809,12 +809,20 @@ void InspectorDOMAgent::performSearch(ErrorString*, const String& whitespaceTrim unsigned queryLength = whitespaceTrimmedQuery.length(); bool startTagFound = !whitespaceTrimmedQuery.find('<'); bool endTagFound = whitespaceTrimmedQuery.reverseFind('>') + 1 == queryLength; + bool startQuoteFound = !whitespaceTrimmedQuery.find('"'); + bool endQuoteFound = whitespaceTrimmedQuery.reverseFind('"') + 1 == queryLength; + bool exactAttributeMatch = startQuoteFound && endQuoteFound; String tagNameQuery = whitespaceTrimmedQuery; + String attributeQuery = whitespaceTrimmedQuery; if (startTagFound) tagNameQuery = tagNameQuery.right(tagNameQuery.length() - 1); if (endTagFound) tagNameQuery = tagNameQuery.left(tagNameQuery.length() - 1); + if (startQuoteFound) + attributeQuery = attributeQuery.right(attributeQuery.length() - 1); + if (endQuoteFound) + attributeQuery = attributeQuery.left(attributeQuery.length() - 1); Vector<Document*> docs = documents(); ListHashSet<Node*> resultCollector; @@ -854,9 +862,12 @@ void InspectorDOMAgent::performSearch(ErrorString*, const String& whitespaceTrim resultCollector.add(node); break; } - if (attribute->value().find(whitespaceTrimmedQuery) != notFound) { - resultCollector.add(node); - break; + size_t foundPosition = attribute->value().find(attributeQuery); + if (foundPosition != notFound) { + if (!exactAttributeMatch || (!foundPosition && attribute->value().length() == attributeQuery.length())) { + resultCollector.add(node); + break; + } } } break; diff --git a/Source/WebCore/inspector/InspectorDOMDebuggerAgent.h b/Source/WebCore/inspector/InspectorDOMDebuggerAgent.h index 7b111f677..2bffd5825 100644 --- a/Source/WebCore/inspector/InspectorDOMDebuggerAgent.h +++ b/Source/WebCore/inspector/InspectorDOMDebuggerAgent.h @@ -35,10 +35,10 @@ #include "InspectorBaseAgent.h" #include "InspectorDebuggerAgent.h" -#include "PlatformString.h" #include <wtf/HashMap.h> #include <wtf/PassOwnPtr.h> #include <wtf/RefCounted.h> +#include <wtf/text/WTFString.h> namespace WebCore { diff --git a/Source/WebCore/inspector/InspectorDOMStorageAgent.h b/Source/WebCore/inspector/InspectorDOMStorageAgent.h index 6664a8db5..a4f87b0e6 100644 --- a/Source/WebCore/inspector/InspectorDOMStorageAgent.h +++ b/Source/WebCore/inspector/InspectorDOMStorageAgent.h @@ -30,10 +30,10 @@ #define InspectorDOMStorageAgent_h #include "InspectorBaseAgent.h" -#include "PlatformString.h" #include "StorageArea.h" #include <wtf/HashMap.h> #include <wtf/PassOwnPtr.h> +#include <wtf/text/WTFString.h> namespace WebCore { diff --git a/Source/WebCore/inspector/InspectorDatabaseAgent.cpp b/Source/WebCore/inspector/InspectorDatabaseAgent.cpp index 98c9363ae..1099c4059 100644 --- a/Source/WebCore/inspector/InspectorDatabaseAgent.cpp +++ b/Source/WebCore/inspector/InspectorDatabaseAgent.cpp @@ -51,56 +51,35 @@ #include <wtf/Vector.h> +typedef WebCore::InspectorBackendDispatcher::DatabaseCommandHandler::ExecuteSQLCallback ExecuteSQLCallback; + namespace WebCore { namespace DatabaseAgentState { static const char databaseAgentEnabled[] = "databaseAgentEnabled"; }; -class InspectorDatabaseAgent::FrontendProvider : public RefCounted<InspectorDatabaseAgent::FrontendProvider> { -public: - static PassRefPtr<FrontendProvider> create(InspectorFrontend* inspectorFrontend) - { - return adoptRef(new FrontendProvider(inspectorFrontend)); - } - - virtual ~FrontendProvider() { } - - InspectorFrontend::Database* frontend() { return m_inspectorFrontend; } - void clearFrontend() { m_inspectorFrontend = 0; } -private: - FrontendProvider(InspectorFrontend* inspectorFrontend) : m_inspectorFrontend(inspectorFrontend->database()) { } - InspectorFrontend::Database* m_inspectorFrontend; -}; - namespace { -int lastTransactionId = 0; - -void reportTransactionFailed(InspectorFrontend::Database* frontend, int transactionId, SQLError* error) +void reportTransactionFailed(ExecuteSQLCallback* requestCallback, SQLError* error) { - if (!frontend) - return; - RefPtr<InspectorObject> errorObject = InspectorObject::create(); - errorObject->setString("message", error->message()); - errorObject->setNumber("code", error->code()); - frontend->sqlTransactionFailed(transactionId, errorObject); + RefPtr<TypeBuilder::Database::Error> errorObject = TypeBuilder::Database::Error::create() + .setMessage(error->message()) + .setCode(error->code()); + requestCallback->sendSuccess(0, 0, errorObject.release()); } class StatementCallback : public SQLStatementCallback { public: - static PassRefPtr<StatementCallback> create(int transactionId, PassRefPtr<InspectorDatabaseAgent::FrontendProvider> frontendProvider) + static PassRefPtr<StatementCallback> create(PassRefPtr<ExecuteSQLCallback> requestCallback) { - return adoptRef(new StatementCallback(transactionId, frontendProvider)); + return adoptRef(new StatementCallback(requestCallback)); } virtual ~StatementCallback() { } virtual bool handleEvent(SQLTransaction*, SQLResultSet* resultSet) { - if (!m_frontendProvider->frontend()) - return true; - SQLResultSetRowList* rowList = resultSet->rows(); RefPtr<TypeBuilder::Array<String> > columnNames = TypeBuilder::Array<String>::create(); @@ -118,92 +97,84 @@ public: case SQLValue::NullValue: values->addItem(InspectorValue::null()); break; } } - m_frontendProvider->frontend()->sqlTransactionSucceeded(m_transactionId, columnNames, values); + m_requestCallback->sendSuccess(columnNames.release(), values.release(), 0); return true; } private: - StatementCallback(int transactionId, PassRefPtr<InspectorDatabaseAgent::FrontendProvider> frontendProvider) - : m_transactionId(transactionId) - , m_frontendProvider(frontendProvider) { } - int m_transactionId; - RefPtr<InspectorDatabaseAgent::FrontendProvider> m_frontendProvider; + StatementCallback(PassRefPtr<ExecuteSQLCallback> requestCallback) + : m_requestCallback(requestCallback) { } + RefPtr<ExecuteSQLCallback> m_requestCallback; }; class StatementErrorCallback : public SQLStatementErrorCallback { public: - static PassRefPtr<StatementErrorCallback> create(int transactionId, PassRefPtr<InspectorDatabaseAgent::FrontendProvider> frontendProvider) + static PassRefPtr<StatementErrorCallback> create(PassRefPtr<ExecuteSQLCallback> requestCallback) { - return adoptRef(new StatementErrorCallback(transactionId, frontendProvider)); + return adoptRef(new StatementErrorCallback(requestCallback)); } virtual ~StatementErrorCallback() { } virtual bool handleEvent(SQLTransaction*, SQLError* error) { - reportTransactionFailed(m_frontendProvider->frontend(), m_transactionId, error); + reportTransactionFailed(m_requestCallback.get(), error); return true; } private: - StatementErrorCallback(int transactionId, PassRefPtr<InspectorDatabaseAgent::FrontendProvider> frontendProvider) - : m_transactionId(transactionId) - , m_frontendProvider(frontendProvider) { } - int m_transactionId; - RefPtr<InspectorDatabaseAgent::FrontendProvider> m_frontendProvider; + StatementErrorCallback(PassRefPtr<ExecuteSQLCallback> requestCallback) + : m_requestCallback(requestCallback) { } + RefPtr<ExecuteSQLCallback> m_requestCallback; }; class TransactionCallback : public SQLTransactionCallback { public: - static PassRefPtr<TransactionCallback> create(const String& sqlStatement, int transactionId, PassRefPtr<InspectorDatabaseAgent::FrontendProvider> frontendProvider) + static PassRefPtr<TransactionCallback> create(const String& sqlStatement, PassRefPtr<ExecuteSQLCallback> requestCallback) { - return adoptRef(new TransactionCallback(sqlStatement, transactionId, frontendProvider)); + return adoptRef(new TransactionCallback(sqlStatement, requestCallback)); } virtual ~TransactionCallback() { } virtual bool handleEvent(SQLTransaction* transaction) { - if (!m_frontendProvider->frontend()) + if (!m_requestCallback->isActive()) return true; Vector<SQLValue> sqlValues; - RefPtr<SQLStatementCallback> callback(StatementCallback::create(m_transactionId, m_frontendProvider)); - RefPtr<SQLStatementErrorCallback> errorCallback(StatementErrorCallback::create(m_transactionId, m_frontendProvider)); + RefPtr<SQLStatementCallback> callback(StatementCallback::create(m_requestCallback.get())); + RefPtr<SQLStatementErrorCallback> errorCallback(StatementErrorCallback::create(m_requestCallback.get())); ExceptionCode ec = 0; transaction->executeSQL(m_sqlStatement, sqlValues, callback.release(), errorCallback.release(), ec); return true; } private: - TransactionCallback(const String& sqlStatement, int transactionId, PassRefPtr<InspectorDatabaseAgent::FrontendProvider> frontendProvider) + TransactionCallback(const String& sqlStatement, PassRefPtr<ExecuteSQLCallback> requestCallback) : m_sqlStatement(sqlStatement) - , m_transactionId(transactionId) - , m_frontendProvider(frontendProvider) { } + , m_requestCallback(requestCallback) { } String m_sqlStatement; - int m_transactionId; - RefPtr<InspectorDatabaseAgent::FrontendProvider> m_frontendProvider; + RefPtr<ExecuteSQLCallback> m_requestCallback; }; class TransactionErrorCallback : public SQLTransactionErrorCallback { public: - static PassRefPtr<TransactionErrorCallback> create(int transactionId, PassRefPtr<InspectorDatabaseAgent::FrontendProvider> frontendProvider) + static PassRefPtr<TransactionErrorCallback> create(PassRefPtr<ExecuteSQLCallback> requestCallback) { - return adoptRef(new TransactionErrorCallback(transactionId, frontendProvider)); + return adoptRef(new TransactionErrorCallback(requestCallback)); } virtual ~TransactionErrorCallback() { } virtual bool handleEvent(SQLError* error) { - reportTransactionFailed(m_frontendProvider->frontend(), m_transactionId, error); + reportTransactionFailed(m_requestCallback.get(), error); return true; } private: - TransactionErrorCallback(int transactionId, PassRefPtr<InspectorDatabaseAgent::FrontendProvider> frontendProvider) - : m_transactionId(transactionId) - , m_frontendProvider(frontendProvider) { } - int m_transactionId; - RefPtr<InspectorDatabaseAgent::FrontendProvider> m_frontendProvider; + TransactionErrorCallback(PassRefPtr<ExecuteSQLCallback> requestCallback) + : m_requestCallback(requestCallback) { } + RefPtr<ExecuteSQLCallback> m_requestCallback; }; class TransactionSuccessCallback : public VoidCallback { @@ -233,8 +204,8 @@ void InspectorDatabaseAgent::didOpenDatabase(PassRefPtr<Database> database, cons RefPtr<InspectorDatabaseResource> resource = InspectorDatabaseResource::create(database, domain, name, version); m_resources.set(resource->id(), resource); // Resources are only bound while visible. - if (m_frontendProvider && m_enabled) - resource->bind(m_frontendProvider->frontend()); + if (m_frontend && m_enabled) + resource->bind(m_frontend); } void InspectorDatabaseAgent::clearResources() @@ -256,13 +227,12 @@ InspectorDatabaseAgent::~InspectorDatabaseAgent() void InspectorDatabaseAgent::setFrontend(InspectorFrontend* frontend) { - m_frontendProvider = FrontendProvider::create(frontend); + m_frontend = frontend->database(); } void InspectorDatabaseAgent::clearFrontend() { - m_frontendProvider->clearFrontend(); - m_frontendProvider.clear(); + m_frontend = 0; disable(0); } @@ -275,7 +245,7 @@ void InspectorDatabaseAgent::enable(ErrorString*) DatabaseResourcesMap::iterator databasesEnd = m_resources.end(); for (DatabaseResourcesMap::iterator it = m_resources.begin(); it != databasesEnd; ++it) - it->second->bind(m_frontendProvider->frontend()); + it->second->bind(m_frontend); } void InspectorDatabaseAgent::disable(ErrorString*) @@ -309,25 +279,25 @@ void InspectorDatabaseAgent::getDatabaseTableNames(ErrorString* error, const Str } } -void InspectorDatabaseAgent::executeSQL(ErrorString* error, const String& databaseId, const String& query, bool* success, int* transactionId) +void InspectorDatabaseAgent::executeSQL(ErrorString*, const String& databaseId, const String& query, PassRefPtr<ExecuteSQLCallback> prpRequestCallback) { + RefPtr<ExecuteSQLCallback> requestCallback = prpRequestCallback; + if (!m_enabled) { - *error = "Database agent is not enabled"; + requestCallback->sendFailure("Database agent is not enabled"); return; } Database* database = databaseForId(databaseId); if (!database) { - *success = false; + requestCallback->sendFailure("Database not found"); return; } - *transactionId = ++lastTransactionId; - RefPtr<SQLTransactionCallback> callback(TransactionCallback::create(query, *transactionId, m_frontendProvider)); - RefPtr<SQLTransactionErrorCallback> errorCallback(TransactionErrorCallback::create(*transactionId, m_frontendProvider)); + RefPtr<SQLTransactionCallback> callback(TransactionCallback::create(query, requestCallback.get())); + RefPtr<SQLTransactionErrorCallback> errorCallback(TransactionErrorCallback::create(requestCallback.get())); RefPtr<VoidCallback> successCallback(TransactionSuccessCallback::create()); database->transaction(callback.release(), errorCallback.release(), successCallback.release()); - *success = true; } String InspectorDatabaseAgent::databaseId(Database* database) diff --git a/Source/WebCore/inspector/InspectorDatabaseAgent.h b/Source/WebCore/inspector/InspectorDatabaseAgent.h index 2902c6ee2..c7399a1e4 100644 --- a/Source/WebCore/inspector/InspectorDatabaseAgent.h +++ b/Source/WebCore/inspector/InspectorDatabaseAgent.h @@ -32,9 +32,10 @@ #if ENABLE(INSPECTOR) && ENABLE(SQL_DATABASE) #include "InspectorBaseAgent.h" -#include "PlatformString.h" +#include "InspectorFrontend.h" #include <wtf/HashMap.h> #include <wtf/PassOwnPtr.h> +#include <wtf/text/WTFString.h> namespace WebCore { @@ -49,8 +50,6 @@ typedef String ErrorString; class InspectorDatabaseAgent : public InspectorBaseAgent<InspectorDatabaseAgent>, public InspectorBackendDispatcher::DatabaseCommandHandler { public: - class FrontendProvider; - static PassOwnPtr<InspectorDatabaseAgent> create(InstrumentingAgents* instrumentingAgents, InspectorState* state) { return adoptPtr(new InspectorDatabaseAgent(instrumentingAgents, state)); @@ -67,7 +66,7 @@ public: virtual void enable(ErrorString*); virtual void disable(ErrorString*); virtual void getDatabaseTableNames(ErrorString*, const String& databaseId, RefPtr<TypeBuilder::Array<String> >& names); - virtual void executeSQL(ErrorString*, const String& databaseId, const String& query, bool* success, int* transactionId); + virtual void executeSQL(ErrorString*, const String& databaseId, const String& query, PassRefPtr<ExecuteSQLCallback>); // Called from the injected script. String databaseId(Database*); @@ -79,9 +78,9 @@ private: Database* databaseForId(const String& databaseId); InspectorDatabaseResource* findByFileName(const String& fileName); + InspectorFrontend::Database* m_frontend; typedef HashMap<String, RefPtr<InspectorDatabaseResource> > DatabaseResourcesMap; DatabaseResourcesMap m_resources; - RefPtr<FrontendProvider> m_frontendProvider; bool m_enabled; }; diff --git a/Source/WebCore/inspector/InspectorDatabaseResource.h b/Source/WebCore/inspector/InspectorDatabaseResource.h index e1c890275..a6bb0c07c 100644 --- a/Source/WebCore/inspector/InspectorDatabaseResource.h +++ b/Source/WebCore/inspector/InspectorDatabaseResource.h @@ -33,10 +33,10 @@ #if ENABLE(SQL_DATABASE) && ENABLE(INSPECTOR) #include "InspectorFrontend.h" -#include "PlatformString.h" #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> #include <wtf/RefPtr.h> +#include <wtf/text/WTFString.h> namespace WebCore { class Database; diff --git a/Source/WebCore/inspector/InspectorDebuggerAgent.cpp b/Source/WebCore/inspector/InspectorDebuggerAgent.cpp index d6e44d91a..76c9c9530 100644 --- a/Source/WebCore/inspector/InspectorDebuggerAgent.cpp +++ b/Source/WebCore/inspector/InspectorDebuggerAgent.cpp @@ -197,6 +197,12 @@ bool InspectorDebuggerAgent::isPaused() return scriptDebugServer().isPaused(); } +void InspectorDebuggerAgent::addMessageToConsole(MessageSource source, MessageType type) +{ + if (scriptDebugServer().pauseOnExceptionsState() != ScriptDebugServer::DontPauseOnExceptions && source == ConsoleAPIMessageSource && type == AssertMessageType) + breakProgram(InspectorFrontend::Debugger::Reason::Assert, 0); +} + static PassRefPtr<InspectorObject> buildObjectForBreakpointCookie(const String& url, int lineNumber, int columnNumber, const String& condition, bool isRegex) { RefPtr<InspectorObject> breakpointObject = InspectorObject::create(); @@ -588,7 +594,7 @@ PassRefPtr<Array<TypeBuilder::Debugger::CallFrame> > InspectorDebuggerAgent::cur String InspectorDebuggerAgent::sourceMapURLForScript(const Script& script) { - DEFINE_STATIC_LOCAL(String, sourceMapHttpHeader, ("X-SourceMap")); + DEFINE_STATIC_LOCAL(String, sourceMapHttpHeader, (ASCIILiteral("X-SourceMap"))); String sourceMapURL = ContentSearchUtils::findSourceMapURL(script.source); if (!sourceMapURL.isEmpty()) diff --git a/Source/WebCore/inspector/InspectorDebuggerAgent.h b/Source/WebCore/inspector/InspectorDebuggerAgent.h index cd5b703db..962376fb8 100644 --- a/Source/WebCore/inspector/InspectorDebuggerAgent.h +++ b/Source/WebCore/inspector/InspectorDebuggerAgent.h @@ -31,6 +31,7 @@ #define InspectorDebuggerAgent_h #if ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(INSPECTOR) +#include "ConsoleTypes.h" #include "InjectedScript.h" #include "InspectorBaseAgent.h" #include "InspectorFrontend.h" @@ -78,6 +79,7 @@ public: void didClearMainFrameWindowObject(); bool isPaused(); + void addMessageToConsole(MessageSource, MessageType); // Part of the protocol. virtual void setBreakpointsActive(ErrorString*, bool active); diff --git a/Source/WebCore/inspector/InspectorFileSystemAgent.cpp b/Source/WebCore/inspector/InspectorFileSystemAgent.cpp index fb40ed43f..c2722fe3a 100644 --- a/Source/WebCore/inspector/InspectorFileSystemAgent.cpp +++ b/Source/WebCore/inspector/InspectorFileSystemAgent.cpp @@ -68,44 +68,18 @@ using WebCore::TypeBuilder::Array; +typedef WebCore::InspectorBackendDispatcher::FileSystemCommandHandler::RequestFileSystemRootCallback RequestFileSystemRootCallback; +typedef WebCore::InspectorBackendDispatcher::FileSystemCommandHandler::RequestDirectoryContentCallback RequestDirectoryContentCallback; +typedef WebCore::InspectorBackendDispatcher::FileSystemCommandHandler::RequestMetadataCallback RequestMetadataCallback; +typedef WebCore::InspectorBackendDispatcher::FileSystemCommandHandler::RequestFileContentCallback RequestFileContentCallback; +typedef WebCore::InspectorBackendDispatcher::FileSystemCommandHandler::DeleteEntryCallback DeleteEntryCallback; + namespace WebCore { namespace FileSystemAgentState { static const char fileSystemAgentEnabled[] = "fileSystemAgentEnabled"; } -class InspectorFileSystemAgent::FrontendProvider : public RefCounted<FrontendProvider> { - WTF_MAKE_NONCOPYABLE(FrontendProvider); -public: - static PassRefPtr<FrontendProvider> create(InspectorFileSystemAgent* agent, InspectorFrontend::FileSystem* frontend) - { - return adoptRef(new FrontendProvider(agent, frontend)); - } - - InspectorFrontend::FileSystem* frontend() const - { - if (m_agent && m_agent->m_enabled) - return m_frontend; - return 0; - } - - void clear() - { - m_agent = 0; - m_frontend = 0; - } - -private: - FrontendProvider(InspectorFileSystemAgent* agent, InspectorFrontend::FileSystem* frontend) - : m_agent(agent) - , m_frontend(frontend) { } - - InspectorFileSystemAgent* m_agent; - InspectorFrontend::FileSystem* m_frontend; -}; - -typedef InspectorFileSystemAgent::FrontendProvider FrontendProvider; - namespace { template<typename BaseCallback, typename Handler, typename Argument> @@ -142,33 +116,12 @@ public: } }; -class ReportErrorTask : public ScriptExecutionContext::Task { -public: - static PassOwnPtr<ReportErrorTask> create(PassRefPtr<ErrorCallback> errorCallback, FileError::ErrorCode errorCode) - { - return adoptPtr(new ReportErrorTask(errorCallback, errorCode)); - } - - virtual void performTask(ScriptExecutionContext*) OVERRIDE - { - m_errorCallback->handleEvent(FileError::create(m_errorCode).get()); - } - -private: - ReportErrorTask(PassRefPtr<ErrorCallback> errorCallback, FileError::ErrorCode errorCode) - : m_errorCallback(errorCallback) - , m_errorCode(errorCode) { } - - RefPtr<ErrorCallback> m_errorCallback; - FileError::ErrorCode m_errorCode; -}; - class FileSystemRootRequest : public RefCounted<FileSystemRootRequest> { WTF_MAKE_NONCOPYABLE(FileSystemRootRequest); public: - static PassRefPtr<FileSystemRootRequest> create(PassRefPtr<FrontendProvider> frontendProvider, int requestId, const String& type) + static PassRefPtr<FileSystemRootRequest> create(PassRefPtr<RequestFileSystemRootCallback> requestCallback, const String& type) { - return adoptRef(new FileSystemRootRequest(frontendProvider, requestId, type)); + return adoptRef(new FileSystemRootRequest(requestCallback, type)); } void start(ScriptExecutionContext*); @@ -184,19 +137,14 @@ private: void reportResult(FileError::ErrorCode errorCode, PassRefPtr<TypeBuilder::FileSystem::Entry> entry = 0) { - if (!m_frontendProvider || !m_frontendProvider->frontend()) - return; - m_frontendProvider->frontend()->fileSystemRootReceived(m_requestId, static_cast<int>(errorCode), entry); - m_frontendProvider = 0; + m_requestCallback->sendSuccess(static_cast<int>(errorCode), entry); } - FileSystemRootRequest(PassRefPtr<FrontendProvider> frontendProvider, int requestId, const String& type) - : m_frontendProvider(frontendProvider) - , m_requestId(requestId) + FileSystemRootRequest(PassRefPtr<RequestFileSystemRootCallback> requestCallback, const String& type) + : m_requestCallback(requestCallback) , m_type(type) { } - RefPtr<FrontendProvider> m_frontendProvider; - int m_requestId; + RefPtr<RequestFileSystemRootCallback> m_requestCallback; String m_type; }; @@ -211,7 +159,7 @@ void FileSystemRootRequest::start(ScriptExecutionContext* scriptExecutionContext else if (m_type == DOMFileSystemBase::temporaryPathPrefix) type = FileSystemTypeTemporary; else { - scriptExecutionContext->postTask(ReportErrorTask::create(errorCallback, FileError::SYNTAX_ERR)); + errorCallback->handleEvent(FileError::create(FileError::SYNTAX_ERR).get()); return; } @@ -234,9 +182,9 @@ bool FileSystemRootRequest::didGetEntry(Entry* entry) class DirectoryContentRequest : public RefCounted<DirectoryContentRequest> { WTF_MAKE_NONCOPYABLE(DirectoryContentRequest); public: - static PassRefPtr<DirectoryContentRequest> create(PassRefPtr<FrontendProvider> frontendProvider, int requestId, const String& url) + static PassRefPtr<DirectoryContentRequest> create(PassRefPtr<RequestDirectoryContentCallback> requestCallback, const String& url) { - return adoptRef(new DirectoryContentRequest(frontendProvider, requestId, url)); + return adoptRef(new DirectoryContentRequest(requestCallback, url)); } virtual ~DirectoryContentRequest() @@ -258,21 +206,16 @@ private: void reportResult(FileError::ErrorCode errorCode, PassRefPtr<Array<TypeBuilder::FileSystem::Entry> > entries = 0) { - if (!m_frontendProvider || !m_frontendProvider->frontend()) - return; - m_frontendProvider->frontend()->directoryContentReceived(m_requestId, static_cast<int>(errorCode), entries); - m_frontendProvider = 0; + m_requestCallback->sendSuccess(static_cast<int>(errorCode), entries); } - DirectoryContentRequest(PassRefPtr<FrontendProvider> frontendProvider, int requestId, const String& url) - : m_frontendProvider(frontendProvider) - , m_requestId(requestId) + DirectoryContentRequest(PassRefPtr<RequestDirectoryContentCallback> requestCallback, const String& url) + : m_requestCallback(requestCallback) , m_url(ParsedURLString, url) { } void readDirectoryEntries(); - RefPtr<FrontendProvider> m_frontendProvider; - int m_requestId; + RefPtr<RequestDirectoryContentCallback> m_requestCallback; KURL m_url; RefPtr<Array<TypeBuilder::FileSystem::Entry> > m_entries; RefPtr<DirectoryReader> m_directoryReader; @@ -286,7 +229,7 @@ void DirectoryContentRequest::start(ScriptExecutionContext* scriptExecutionConte FileSystemType type; String path; if (!DOMFileSystemBase::crackFileSystemURL(m_url, type, path)) { - scriptExecutionContext->postTask(ReportErrorTask::create(errorCallback, FileError::SYNTAX_ERR)); + errorCallback->handleEvent(FileError::create(FileError::SYNTAX_ERR).get()); return; } @@ -366,9 +309,9 @@ bool DirectoryContentRequest::didReadDirectoryEntries(EntryArray* entries) class MetadataRequest : public RefCounted<MetadataRequest> { WTF_MAKE_NONCOPYABLE(MetadataRequest); public: - static PassRefPtr<MetadataRequest> create(PassRefPtr<FrontendProvider> frontendProvider, int requestId, const String& url) + static PassRefPtr<MetadataRequest> create(PassRefPtr<RequestMetadataCallback> requestCallback, const String& url) { - return adoptRef(new MetadataRequest(frontendProvider, requestId, url)); + return adoptRef(new MetadataRequest(requestCallback, url)); } virtual ~MetadataRequest() @@ -390,19 +333,14 @@ private: void reportResult(FileError::ErrorCode errorCode, PassRefPtr<TypeBuilder::FileSystem::Metadata> metadata = 0) { - if (!m_frontendProvider || !m_frontendProvider->frontend()) - return; - m_frontendProvider->frontend()->metadataReceived(m_requestId, static_cast<int>(errorCode), metadata); - m_frontendProvider = 0; + m_requestCallback->sendSuccess(static_cast<int>(errorCode), metadata); } - MetadataRequest(PassRefPtr<FrontendProvider> frontendProvider, int requestId, const String& url) - : m_frontendProvider(frontendProvider) - , m_requestId(requestId) + MetadataRequest(PassRefPtr<RequestMetadataCallback> requestCallback, const String& url) + : m_requestCallback(requestCallback) , m_url(ParsedURLString, url) { } - RefPtr<FrontendProvider> m_frontendProvider; - int m_requestId; + RefPtr<RequestMetadataCallback> m_requestCallback; KURL m_url; String m_path; bool m_isDirectory; @@ -416,7 +354,7 @@ void MetadataRequest::start(ScriptExecutionContext* scriptExecutionContext) FileSystemType type; if (!DOMFileSystemBase::crackFileSystemURL(m_url, type, m_path)) { - scriptExecutionContext->postTask(ReportErrorTask::create(errorCallback, FileError::SYNTAX_ERR)); + errorCallback->handleEvent(FileError::create(FileError::SYNTAX_ERR).get()); return; } @@ -452,9 +390,9 @@ bool MetadataRequest::didGetMetadata(Metadata* metadata) class FileContentRequest : public EventListener { WTF_MAKE_NONCOPYABLE(FileContentRequest); public: - static PassRefPtr<FileContentRequest> create(PassRefPtr<FrontendProvider> frontendProvider, int requestId, const String& url, bool readAsText, long long start, long long end, const String& charset) + static PassRefPtr<FileContentRequest> create(PassRefPtr<RequestFileContentCallback> requestCallback, const String& url, bool readAsText, long long start, long long end, const String& charset) { - return adoptRef(new FileContentRequest(frontendProvider, requestId, url, readAsText, start, end, charset)); + return adoptRef(new FileContentRequest(requestCallback, url, readAsText, start, end, charset)); } virtual ~FileContentRequest() @@ -490,24 +428,19 @@ private: void reportResult(FileError::ErrorCode errorCode, const String* result = 0, const String* charset = 0) { - if (!m_frontendProvider || !m_frontendProvider->frontend()) - return; - m_frontendProvider->frontend()->fileContentReceived(m_requestId, static_cast<int>(errorCode), result, charset); - m_frontendProvider = 0; + m_requestCallback->sendSuccess(static_cast<int>(errorCode), result, charset); } - FileContentRequest(PassRefPtr<FrontendProvider> frontendProvider, int requestId, const String& url, bool readAsText, long long start, long long end, const String& charset) + FileContentRequest(PassRefPtr<RequestFileContentCallback> requestCallback, const String& url, bool readAsText, long long start, long long end, const String& charset) : EventListener(EventListener::CPPEventListenerType) - , m_frontendProvider(frontendProvider) - , m_requestId(requestId) + , m_requestCallback(requestCallback) , m_url(ParsedURLString, url) , m_readAsText(readAsText) , m_start(start) , m_end(end) , m_charset(charset) { } - RefPtr<FrontendProvider> m_frontendProvider; - int m_requestId; + RefPtr<RequestFileContentCallback> m_requestCallback; KURL m_url; bool m_readAsText; int m_start; @@ -527,7 +460,7 @@ void FileContentRequest::start(ScriptExecutionContext* scriptExecutionContext) FileSystemType type; String path; if (!DOMFileSystemBase::crackFileSystemURL(m_url, type, path)) { - scriptExecutionContext->postTask(ReportErrorTask::create(errorCallback, FileError::SYNTAX_ERR)); + errorCallback->handleEvent(FileError::create(FileError::SYNTAX_ERR).get()); return; } @@ -582,16 +515,16 @@ void FileContentRequest::didRead() RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create(m_mimeType, m_charset, true); String result = decoder->decode(static_cast<char*>(buffer->data()), buffer->byteLength()); - result += decoder->flush(); + result.append(decoder->flush()); m_charset = decoder->encoding().domName(); reportResult(static_cast<FileError::ErrorCode>(0), &result, &m_charset); } class DeleteEntryRequest : public VoidCallback { public: - static PassRefPtr<DeleteEntryRequest> create(PassRefPtr<FrontendProvider> frontendProvider, int requestId, const KURL& url) + static PassRefPtr<DeleteEntryRequest> create(PassRefPtr<DeleteEntryCallback> requestCallback, const KURL& url) { - return adoptRef(new DeleteEntryRequest(frontendProvider, requestId, url)); + return adoptRef(new DeleteEntryRequest(requestCallback, url)); } virtual ~DeleteEntryRequest() @@ -618,19 +551,14 @@ private: void reportResult(FileError::ErrorCode errorCode) { - if (!m_frontendProvider || !m_frontendProvider->frontend()) - return; - m_frontendProvider->frontend()->deletionCompleted(m_requestId, static_cast<int>(errorCode)); - m_frontendProvider = 0; + m_requestCallback->sendSuccess(static_cast<int>(errorCode)); } - DeleteEntryRequest(PassRefPtr<FrontendProvider> frontendProvider, int requestId, const KURL& url) - : m_frontendProvider(frontendProvider) - , m_requestId(requestId) + DeleteEntryRequest(PassRefPtr<DeleteEntryCallback> requestCallback, const KURL& url) + : m_requestCallback(requestCallback) , m_url(url) { } - RefPtr<FrontendProvider> m_frontendProvider; - int m_requestId; + RefPtr<DeleteEntryCallback> m_requestCallback; KURL m_url; }; @@ -643,7 +571,7 @@ void DeleteEntryRequest::start(ScriptExecutionContext* scriptExecutionContext) FileSystemType type; String path; if (!DOMFileSystemBase::crackFileSystemURL(m_url, type, path)) { - scriptExecutionContext->postTask(ReportErrorTask::create(errorCallback, FileError::SYNTAX_ERR)); + errorCallback->handleEvent(FileError::create(FileError::SYNTAX_ERR).get()); return; } @@ -684,8 +612,6 @@ PassOwnPtr<InspectorFileSystemAgent> InspectorFileSystemAgent::create(Instrument InspectorFileSystemAgent::~InspectorFileSystemAgent() { - if (m_frontendProvider) - m_frontendProvider->clear(); m_instrumentingAgents->setInspectorFileSystemAgent(0); } @@ -705,64 +631,59 @@ void InspectorFileSystemAgent::disable(ErrorString*) m_state->setBoolean(FileSystemAgentState::fileSystemAgentEnabled, m_enabled); } -void InspectorFileSystemAgent::requestFileSystemRoot(ErrorString* error, const String& origin, const String& type, int* requestId) +void InspectorFileSystemAgent::requestFileSystemRoot(ErrorString* error, const String& origin, const String& type, PassRefPtr<RequestFileSystemRootCallback> requestCallback) { - if (!assertFrontend(error)) + if (!assertEnabled(error)) return; ScriptExecutionContext* scriptExecutionContext = assertScriptExecutionContextForOrigin(error, SecurityOrigin::createFromString(origin).get()); if (!scriptExecutionContext) return; - *requestId = m_nextRequestId++; - FileSystemRootRequest::create(m_frontendProvider, *requestId, type)->start(scriptExecutionContext); + FileSystemRootRequest::create(requestCallback, type)->start(scriptExecutionContext); } -void InspectorFileSystemAgent::requestDirectoryContent(ErrorString* error, const String& url, int* requestId) +void InspectorFileSystemAgent::requestDirectoryContent(ErrorString* error, const String& url, PassRefPtr<RequestDirectoryContentCallback> requestCallback) { - if (!assertFrontend(error)) + if (!assertEnabled(error)) return; ScriptExecutionContext* scriptExecutionContext = assertScriptExecutionContextForOrigin(error, SecurityOrigin::createFromString(url).get()); if (!scriptExecutionContext) return; - *requestId = m_nextRequestId++; - DirectoryContentRequest::create(m_frontendProvider, *requestId, url)->start(scriptExecutionContext); + DirectoryContentRequest::create(requestCallback, url)->start(scriptExecutionContext); } -void InspectorFileSystemAgent::requestMetadata(ErrorString* error, const String& url, int* requestId) +void InspectorFileSystemAgent::requestMetadata(ErrorString* error, const String& url, PassRefPtr<RequestMetadataCallback> requestCallback) { - if (!assertFrontend(error)) + if (!assertEnabled(error)) return; ScriptExecutionContext* scriptExecutionContext = assertScriptExecutionContextForOrigin(error, SecurityOrigin::createFromString(url).get()); if (!scriptExecutionContext) return; - *requestId = m_nextRequestId++; - MetadataRequest::create(m_frontendProvider, *requestId, url)->start(scriptExecutionContext); + MetadataRequest::create(requestCallback, url)->start(scriptExecutionContext); } -void InspectorFileSystemAgent::requestFileContent(ErrorString* error, const String& url, bool readAsText, const int* start, const int* end, const String* charset, int* requestId) +void InspectorFileSystemAgent::requestFileContent(ErrorString* error, const String& url, bool readAsText, const int* start, const int* end, const String* charset, PassRefPtr<RequestFileContentCallback> requestCallback) { - if (!assertFrontend(error)) + if (!assertEnabled(error)) return; ScriptExecutionContext* scriptExecutionContext = assertScriptExecutionContextForOrigin(error, SecurityOrigin::createFromString(url).get()); if (!scriptExecutionContext) return; - *requestId = m_nextRequestId++; - long long startPosition = start ? *start : 0; long long endPosition = end ? *end : std::numeric_limits<long long>::max(); - FileContentRequest::create(m_frontendProvider, *requestId, url, readAsText, startPosition, endPosition, charset ? *charset : "")->start(scriptExecutionContext); + FileContentRequest::create(requestCallback, url, readAsText, startPosition, endPosition, charset ? *charset : "")->start(scriptExecutionContext); } -void InspectorFileSystemAgent::deleteEntry(ErrorString* error, const String& urlString, int* requestId) +void InspectorFileSystemAgent::deleteEntry(ErrorString* error, const String& urlString, PassRefPtr<DeleteEntryCallback> requestCallback) { - if (!assertFrontend(error)) + if (!assertEnabled(error)) return; KURL url(ParsedURLString, urlString); @@ -771,22 +692,11 @@ void InspectorFileSystemAgent::deleteEntry(ErrorString* error, const String& url if (!scriptExecutionContext) return; - *requestId = m_nextRequestId++; - DeleteEntryRequest::create(m_frontendProvider, *requestId, url)->start(scriptExecutionContext); -} - -void InspectorFileSystemAgent::setFrontend(InspectorFrontend* frontend) -{ - ASSERT(frontend); - m_frontendProvider = FrontendProvider::create(this, frontend->filesystem()); + DeleteEntryRequest::create(requestCallback, url)->start(scriptExecutionContext); } void InspectorFileSystemAgent::clearFrontend() { - if (m_frontendProvider) { - m_frontendProvider->clear(); - m_frontendProvider = 0; - } m_enabled = false; m_state->setBoolean(FileSystemAgentState::fileSystemAgentEnabled, m_enabled); } @@ -800,7 +710,6 @@ InspectorFileSystemAgent::InspectorFileSystemAgent(InstrumentingAgents* instrume : InspectorBaseAgent<InspectorFileSystemAgent>("FileSystem", instrumentingAgents, state) , m_pageAgent(pageAgent) , m_enabled(false) - , m_nextRequestId(1) { ASSERT(instrumentingAgents); ASSERT(state); @@ -808,13 +717,12 @@ InspectorFileSystemAgent::InspectorFileSystemAgent(InstrumentingAgents* instrume m_instrumentingAgents->setInspectorFileSystemAgent(this); } -bool InspectorFileSystemAgent::assertFrontend(ErrorString* error) +bool InspectorFileSystemAgent::assertEnabled(ErrorString* error) { - if (!m_enabled || !m_frontendProvider) { + if (!m_enabled) { *error = "FileSystem agent is not enabled."; return false; } - ASSERT(m_frontendProvider->frontend()); return true; } diff --git a/Source/WebCore/inspector/InspectorFileSystemAgent.h b/Source/WebCore/inspector/InspectorFileSystemAgent.h index f0fca3cae..433bab8c5 100644 --- a/Source/WebCore/inspector/InspectorFileSystemAgent.h +++ b/Source/WebCore/inspector/InspectorFileSystemAgent.h @@ -47,33 +47,28 @@ class SecurityOrigin; class InspectorFileSystemAgent : public InspectorBaseAgent<InspectorFileSystemAgent>, public InspectorBackendDispatcher::FileSystemCommandHandler { public: - class FrontendProvider; - static PassOwnPtr<InspectorFileSystemAgent> create(InstrumentingAgents*, InspectorPageAgent*, InspectorState*); virtual ~InspectorFileSystemAgent(); virtual void enable(ErrorString*) OVERRIDE; virtual void disable(ErrorString*) OVERRIDE; - virtual void requestFileSystemRoot(ErrorString*, const String& origin, const String& typeString, int* requestId) OVERRIDE; - virtual void requestDirectoryContent(ErrorString*, const String& url, int* requestId) OVERRIDE; - virtual void requestMetadata(ErrorString*, const String& url, int* requestId) OVERRIDE; - virtual void requestFileContent(ErrorString*, const String& url, bool readAsText, const int* start, const int* end, const String* charset, int* requestId) OVERRIDE; - virtual void deleteEntry(ErrorString*, const String& url, int* requestId) OVERRIDE; + virtual void requestFileSystemRoot(ErrorString*, const String& origin, const String& typeString, PassRefPtr<RequestFileSystemRootCallback>) OVERRIDE; + virtual void requestDirectoryContent(ErrorString*, const String& url, PassRefPtr<RequestDirectoryContentCallback>) OVERRIDE; + virtual void requestMetadata(ErrorString*, const String& url, PassRefPtr<RequestMetadataCallback>) OVERRIDE; + virtual void requestFileContent(ErrorString*, const String& url, bool readAsText, const int* start, const int* end, const String* charset, PassRefPtr<RequestFileContentCallback>) OVERRIDE; + virtual void deleteEntry(ErrorString*, const String& url, PassRefPtr<DeleteEntryCallback>) OVERRIDE; - virtual void setFrontend(InspectorFrontend*) OVERRIDE; virtual void clearFrontend() OVERRIDE; virtual void restore() OVERRIDE; private: InspectorFileSystemAgent(InstrumentingAgents*, InspectorPageAgent*, InspectorState*); - bool assertFrontend(ErrorString*); + bool assertEnabled(ErrorString*); ScriptExecutionContext* assertScriptExecutionContextForOrigin(ErrorString*, SecurityOrigin*); InspectorPageAgent* m_pageAgent; - RefPtr<FrontendProvider> m_frontendProvider; bool m_enabled; - int m_nextRequestId; }; } // namespace WebCore diff --git a/Source/WebCore/inspector/InspectorFrontendClientLocal.cpp b/Source/WebCore/inspector/InspectorFrontendClientLocal.cpp index cad8042aa..ebd9b219f 100644 --- a/Source/WebCore/inspector/InspectorFrontendClientLocal.cpp +++ b/Source/WebCore/inspector/InspectorFrontendClientLocal.cpp @@ -46,15 +46,16 @@ #include "InspectorFrontendHost.h" #include "InspectorPageAgent.h" #include "Page.h" -#include "PlatformString.h" #include "ScriptFunctionCall.h" #include "ScriptObject.h" +#include "ScriptState.h" #include "Settings.h" #include "Timer.h" #include "UserGestureIndicator.h" #include "WindowFeatures.h" #include <wtf/Deque.h> #include <wtf/text/CString.h> +#include <wtf/text/WTFString.h> namespace WebCore { @@ -111,7 +112,6 @@ void InspectorFrontendClientLocal::Settings::setProperty(const String&, const St InspectorFrontendClientLocal::InspectorFrontendClientLocal(InspectorController* inspectorController, Page* frontendPage, PassOwnPtr<Settings> settings) : m_inspectorController(inspectorController) , m_frontendPage(frontendPage) - , m_frontendScriptState(0) , m_settings(settings) , m_frontendLoaded(false) { @@ -124,7 +124,6 @@ InspectorFrontendClientLocal::~InspectorFrontendClientLocal() if (m_frontendHost) m_frontendHost->disconnectClient(); m_frontendPage = 0; - m_frontendScriptState = 0; m_inspectorController = 0; } @@ -132,10 +131,10 @@ void InspectorFrontendClientLocal::windowObjectCleared() { if (m_frontendHost) m_frontendHost->disconnectClient(); - // FIXME: don't keep reference to the script state - m_frontendScriptState = scriptStateFromPage(debuggerWorld(), m_frontendPage); + + ScriptState* frontendScriptState = scriptStateFromPage(debuggerWorld(), m_frontendPage); m_frontendHost = InspectorFrontendHost::create(this, m_frontendPage); - ScriptGlobalObject::set(m_frontendScriptState, "InspectorFrontendHost", m_frontendHost.get()); + ScriptGlobalObject::set(frontendScriptState, "InspectorFrontendHost", m_frontendHost.get()); } void InspectorFrontendClientLocal::frontendLoaded() diff --git a/Source/WebCore/inspector/InspectorFrontendClientLocal.h b/Source/WebCore/inspector/InspectorFrontendClientLocal.h index 4027397ac..af8493b99 100644 --- a/Source/WebCore/inspector/InspectorFrontendClientLocal.h +++ b/Source/WebCore/inspector/InspectorFrontendClientLocal.h @@ -32,13 +32,13 @@ #define InspectorFrontendClientLocal_h #include "InspectorFrontendClient.h" -#include "PlatformString.h" -#include "ScriptState.h" #include <wtf/Forward.h> #include <wtf/Noncopyable.h> +#include <wtf/text/WTFString.h> namespace WebCore { +class Frame; class InspectorController; class InspectorBackendDispatchTask; class InspectorFrontendHost; @@ -111,8 +111,7 @@ private: friend class FrontendMenuProvider; InspectorController* m_inspectorController; - Page* m_frontendPage; - ScriptState* m_frontendScriptState; + Page* m_frontendPage; // TODO(yurys): this ref shouldn't be needed. RefPtr<InspectorFrontendHost> m_frontendHost; OwnPtr<InspectorFrontendClientLocal::Settings> m_settings; diff --git a/Source/WebCore/inspector/InspectorFrontendHost.h b/Source/WebCore/inspector/InspectorFrontendHost.h index 9633d8296..d5ae51d80 100644 --- a/Source/WebCore/inspector/InspectorFrontendHost.h +++ b/Source/WebCore/inspector/InspectorFrontendHost.h @@ -32,10 +32,9 @@ #include "ConsoleTypes.h" #include "ContextMenu.h" #include "ContextMenuProvider.h" -#include "PlatformString.h" - #include <wtf/RefCounted.h> #include <wtf/Vector.h> +#include <wtf/text/WTFString.h> namespace WebCore { diff --git a/Source/WebCore/inspector/InspectorIndexedDBAgent.cpp b/Source/WebCore/inspector/InspectorIndexedDBAgent.cpp index 33b21b4fd..5dfd99519 100644 --- a/Source/WebCore/inspector/InspectorIndexedDBAgent.cpp +++ b/Source/WebCore/inspector/InspectorIndexedDBAgent.cpp @@ -78,28 +78,16 @@ using WebCore::TypeBuilder::IndexedDB::KeyRange; using WebCore::TypeBuilder::IndexedDB::ObjectStore; using WebCore::TypeBuilder::IndexedDB::ObjectStoreIndex; +typedef WebCore::InspectorBackendDispatcher::IndexedDBCommandHandler::RequestDatabaseNamesForFrameCallback RequestDatabaseNamesForFrameCallback; +typedef WebCore::InspectorBackendDispatcher::IndexedDBCommandHandler::RequestDatabaseCallback RequestDatabaseCallback; +typedef WebCore::InspectorBackendDispatcher::IndexedDBCommandHandler::RequestDataCallback RequestDataCallback; + namespace WebCore { namespace IndexedDBAgentState { static const char indexedDBAgentEnabled[] = "indexedDBAgentEnabled"; }; -class InspectorIndexedDBAgent::FrontendProvider : public RefCounted<InspectorIndexedDBAgent::FrontendProvider> { -public: - static PassRefPtr<FrontendProvider> create(InspectorFrontend* inspectorFrontend) - { - return adoptRef(new FrontendProvider(inspectorFrontend)); - } - - virtual ~FrontendProvider() { } - - InspectorFrontend::IndexedDB* frontend() { return m_inspectorFrontend; } - void clearFrontend() { m_inspectorFrontend = 0; } -private: - FrontendProvider(InspectorFrontend* inspectorFrontend) : m_inspectorFrontend(inspectorFrontend->indexeddb()) { } - InspectorFrontend::IndexedDB* m_inspectorFrontend; -}; - namespace { class InspectorIDBCallback : public IDBCallbacks { @@ -153,16 +141,16 @@ private: class GetDatabaseNamesCallback : public InspectorIDBCallback { public: - static PassRefPtr<GetDatabaseNamesCallback> create(InspectorIndexedDBAgent::FrontendProvider* frontendProvider, int requestId, const String& securityOrigin) + static PassRefPtr<GetDatabaseNamesCallback> create(PassRefPtr<RequestDatabaseNamesForFrameCallback> requestCallback, const String& securityOrigin) { - return adoptRef(new GetDatabaseNamesCallback(frontendProvider, requestId, securityOrigin)); + return adoptRef(new GetDatabaseNamesCallback(requestCallback, securityOrigin)); } virtual ~GetDatabaseNamesCallback() { } virtual void onSuccess(PassRefPtr<DOMStringList> databaseNamesList) { - if (!m_frontendProvider->frontend()) + if (!m_requestCallback->isActive()) return; RefPtr<TypeBuilder::Array<String> > databaseNames = TypeBuilder::Array<String>::create(); @@ -173,16 +161,14 @@ public: .setSecurityOrigin(m_securityOrigin) .setDatabaseNames(databaseNames); - m_frontendProvider->frontend()->databaseNamesLoaded(m_requestId, result); + m_requestCallback->sendSuccess(result); } private: - GetDatabaseNamesCallback(InspectorIndexedDBAgent::FrontendProvider* frontendProvider, int requestId, const String& securityOrigin) - : m_frontendProvider(frontendProvider) - , m_requestId(requestId) + GetDatabaseNamesCallback(PassRefPtr<RequestDatabaseNamesForFrameCallback> requestCallback, const String& securityOrigin) + : m_requestCallback(requestCallback) , m_securityOrigin(securityOrigin) { } - RefPtr<InspectorIndexedDBAgent::FrontendProvider> m_frontendProvider; - int m_requestId; + RefPtr<RequestDatabaseNamesForFrameCallback> m_requestCallback; String m_securityOrigin; }; @@ -300,9 +286,9 @@ static PassRefPtr<KeyPath> keyPathFromIDBKeyPath(const IDBKeyPath& idbKeyPath) class DatabaseLoaderCallback : public ExecutableWithDatabase { public: - static PassRefPtr<DatabaseLoaderCallback> create(InspectorIndexedDBAgent::FrontendProvider* frontendProvider, int requestId) + static PassRefPtr<DatabaseLoaderCallback> create(PassRefPtr<RequestDatabaseCallback> requestCallback) { - return adoptRef(new DatabaseLoaderCallback(frontendProvider, requestId)); + return adoptRef(new DatabaseLoaderCallback(requestCallback)); } virtual ~DatabaseLoaderCallback() { } @@ -311,7 +297,7 @@ public: { RefPtr<IDBDatabaseBackendInterface> idbDatabase = prpDatabase; m_connection.connect(idbDatabase); - if (!m_frontendProvider->frontend()) + if (!m_requestCallback->isActive()) return; const IDBDatabaseMetadata databaseMetadata = idbDatabase->metadata(); @@ -346,15 +332,13 @@ public: .setVersion(databaseMetadata.version) .setObjectStores(objectStores); - m_frontendProvider->frontend()->databaseLoaded(m_requestId, result); + m_requestCallback->sendSuccess(result); } private: - DatabaseLoaderCallback(InspectorIndexedDBAgent::FrontendProvider* frontendProvider, int requestId) - : m_frontendProvider(frontendProvider) - , m_requestId(requestId) { } - RefPtr<InspectorIndexedDBAgent::FrontendProvider> m_frontendProvider; - int m_requestId; + DatabaseLoaderCallback(PassRefPtr<RequestDatabaseCallback> requestCallback) + : m_requestCallback(requestCallback) { } + RefPtr<RequestDatabaseCallback> m_requestCallback; DatabaseConnection m_connection; }; @@ -366,10 +350,10 @@ static PassRefPtr<IDBKey> idbKeyFromInspectorObject(InspectorObject* key) if (!key->getString("type", &type)) return 0; - DEFINE_STATIC_LOCAL(String, number, ("number")); - DEFINE_STATIC_LOCAL(String, string, ("string")); - DEFINE_STATIC_LOCAL(String, date, ("date")); - DEFINE_STATIC_LOCAL(String, array, ("array")); + DEFINE_STATIC_LOCAL(String, number, (ASCIILiteral("number"))); + DEFINE_STATIC_LOCAL(String, string, (ASCIILiteral("string"))); + DEFINE_STATIC_LOCAL(String, date, (ASCIILiteral("date"))); + DEFINE_STATIC_LOCAL(String, array, (ASCIILiteral("array"))); if (type == number) { double number; @@ -475,14 +459,9 @@ class DataLoaderCallback; class OpenCursorCallback : public InspectorIDBCallback { public: - enum CursorType { - ObjectStoreDataCursor, - IndexDataCursor - }; - - static PassRefPtr<OpenCursorCallback> create(PassRefPtr<InspectorIndexedDBAgent::FrontendProvider> frontendProvider, InjectedScript injectedScript, PassRefPtr<DataLoaderCallback> dataLoaderCallback, PassRefPtr<IDBTransactionBackendInterface> idbTransaction, CursorType cursorType, int requestId, int skipCount, unsigned pageSize) + static PassRefPtr<OpenCursorCallback> create(InjectedScript injectedScript, PassRefPtr<DataLoaderCallback> dataLoaderCallback, PassRefPtr<IDBTransactionBackendInterface> idbTransaction, PassRefPtr<RequestDataCallback> requestCallback, int skipCount, unsigned pageSize) { - return adoptRef(new OpenCursorCallback(frontendProvider, injectedScript, dataLoaderCallback, idbTransaction, cursorType, requestId, skipCount, pageSize)); + return adoptRef(new OpenCursorCallback(injectedScript, dataLoaderCallback, idbTransaction, requestCallback, skipCount, pageSize)); } virtual ~OpenCursorCallback() { } @@ -532,43 +511,32 @@ public: void end(bool hasMore) { m_dataLoaderCallback.clear(); - if (!m_frontendProvider->frontend()) + if (!m_requestCallback->isActive()) return; if (m_idbCursor) m_idbCursor->postSuccessHandlerCallback(); m_idbTransaction->didCompleteTaskEvents(); - switch (m_cursorType) { - case ObjectStoreDataCursor: - m_frontendProvider->frontend()->objectStoreDataLoaded(m_requestId, m_result.release(), hasMore); - break; - case IndexDataCursor: - m_frontendProvider->frontend()->indexDataLoaded(m_requestId, m_result.release(), hasMore); - break; - } + m_requestCallback->sendSuccess(m_result.release(), hasMore); } private: - OpenCursorCallback(PassRefPtr<InspectorIndexedDBAgent::FrontendProvider> frontendProvider, InjectedScript injectedScript, PassRefPtr<DataLoaderCallback> dataLoaderCallback, PassRefPtr<IDBTransactionBackendInterface> idbTransaction, CursorType cursorType, int requestId, int skipCount, unsigned pageSize) - : m_frontendProvider(frontendProvider) - , m_injectedScript(injectedScript) + OpenCursorCallback(InjectedScript injectedScript, PassRefPtr<DataLoaderCallback> dataLoaderCallback, PassRefPtr<IDBTransactionBackendInterface> idbTransaction, PassRefPtr<RequestDataCallback> requestCallback, int skipCount, unsigned pageSize) + : m_injectedScript(injectedScript) , m_dataLoaderCallback(dataLoaderCallback) , m_idbTransaction(idbTransaction) - , m_cursorType(cursorType) - , m_requestId(requestId) + , m_requestCallback(requestCallback) , m_skipCount(skipCount) , m_pageSize(pageSize) { m_result = Array<DataEntry>::create(); m_idbTransaction->setCallbacks(InspectorIDBTransactionCallback::create().get()); } - RefPtr<InspectorIndexedDBAgent::FrontendProvider> m_frontendProvider; InjectedScript m_injectedScript; RefPtr<DataLoaderCallback> m_dataLoaderCallback; RefPtr<IDBTransactionBackendInterface> m_idbTransaction; - CursorType m_cursorType; - int m_requestId; + RefPtr<RequestDataCallback> m_requestCallback; int m_skipCount; unsigned m_pageSize; RefPtr<Array<DataEntry> > m_result; @@ -577,9 +545,9 @@ private: class DataLoaderCallback : public ExecutableWithDatabase { public: - static PassRefPtr<DataLoaderCallback> create(PassRefPtr<InspectorIndexedDBAgent::FrontendProvider> frontendProvider, int requestId, const InjectedScript& injectedScript, const String& objectStoreName, const String& indexName, PassRefPtr<IDBKeyRange> idbKeyRange, int skipCount, unsigned pageSize) + static PassRefPtr<DataLoaderCallback> create(PassRefPtr<RequestDataCallback> requestCallback, const InjectedScript& injectedScript, const String& objectStoreName, const String& indexName, PassRefPtr<IDBKeyRange> idbKeyRange, int skipCount, unsigned pageSize) { - return adoptRef(new DataLoaderCallback(frontendProvider, requestId, injectedScript, objectStoreName, indexName, idbKeyRange, skipCount, pageSize)); + return adoptRef(new DataLoaderCallback(requestCallback, injectedScript, objectStoreName, indexName, idbKeyRange, skipCount, pageSize)); } virtual ~DataLoaderCallback() { } @@ -588,7 +556,7 @@ public: { RefPtr<IDBDatabaseBackendInterface> idbDatabase = prpDatabase; m_connection.connect(idbDatabase); - if (!m_frontendProvider->frontend()) + if (!m_requestCallback->isActive()) return; RefPtr<IDBTransactionBackendInterface> idbTransaction = transactionForDatabase(idbDatabase.get(), m_objectStoreName); @@ -598,35 +566,31 @@ public: if (!idbObjectStore) return; + RefPtr<OpenCursorCallback> openCursorCallback = OpenCursorCallback::create(m_injectedScript, this, idbTransaction.get(), m_requestCallback, m_skipCount, m_pageSize); + if (!m_indexName.isEmpty()) { RefPtr<IDBIndexBackendInterface> idbIndex = indexForObjectStore(idbObjectStore.get(), m_indexName); if (!idbIndex) return; - RefPtr<OpenCursorCallback> openCursorCallback = OpenCursorCallback::create(m_frontendProvider, m_injectedScript, this, idbTransaction.get(), OpenCursorCallback::IndexDataCursor, m_requestId, m_skipCount, m_pageSize); - ExceptionCode ec = 0; idbIndex->openCursor(m_idbKeyRange, IDBCursor::NEXT, openCursorCallback, idbTransaction.get(), ec); } else { - RefPtr<OpenCursorCallback> openCursorCallback = OpenCursorCallback::create(m_frontendProvider, m_injectedScript, this, idbTransaction.get(), OpenCursorCallback::ObjectStoreDataCursor, m_requestId, m_skipCount, m_pageSize); - ExceptionCode ec = 0; idbObjectStore->openCursor(m_idbKeyRange, IDBCursor::NEXT, openCursorCallback, IDBTransactionBackendInterface::NormalTask, idbTransaction.get(), ec); } } private: - DataLoaderCallback(PassRefPtr<InspectorIndexedDBAgent::FrontendProvider> frontendProvider, int requestId, const InjectedScript& injectedScript, const String& objectStoreName, const String& indexName, PassRefPtr<IDBKeyRange> idbKeyRange, int skipCount, unsigned pageSize) - : m_frontendProvider(frontendProvider) - , m_requestId(requestId) + DataLoaderCallback(PassRefPtr<RequestDataCallback> requestCallback, const InjectedScript& injectedScript, const String& objectStoreName, const String& indexName, PassRefPtr<IDBKeyRange> idbKeyRange, int skipCount, unsigned pageSize) + : m_requestCallback(requestCallback) , m_injectedScript(injectedScript) , m_objectStoreName(objectStoreName) , m_indexName(indexName) , m_idbKeyRange(idbKeyRange) , m_skipCount(skipCount) , m_pageSize(pageSize) { } - RefPtr<InspectorIndexedDBAgent::FrontendProvider> m_frontendProvider; - int m_requestId; + RefPtr<RequestDataCallback> m_requestCallback; InjectedScript m_injectedScript; String m_objectStoreName; String m_indexName; @@ -649,15 +613,8 @@ InspectorIndexedDBAgent::~InspectorIndexedDBAgent() { } -void InspectorIndexedDBAgent::setFrontend(InspectorFrontend* frontend) -{ - m_frontendProvider = FrontendProvider::create(frontend); -} - void InspectorIndexedDBAgent::clearFrontend() { - m_frontendProvider->clearFrontend(); - m_frontendProvider.clear(); disable(0); } @@ -721,7 +678,7 @@ static IDBFactoryBackendInterface* assertIDBFactory(ErrorString* errorString, Do return idbFactory; } -void InspectorIndexedDBAgent::requestDatabaseNamesForFrame(ErrorString* errorString, int requestId, const String& frameId) +void InspectorIndexedDBAgent::requestDatabaseNamesForFrame(ErrorString* errorString, const String& frameId, PassRefPtr<RequestDatabaseNamesForFrameCallback> requestCallback) { Document* document = assertDocument(errorString, frameId, m_pageAgent); if (!document) @@ -730,12 +687,12 @@ void InspectorIndexedDBAgent::requestDatabaseNamesForFrame(ErrorString* errorStr if (!idbFactory) return; - RefPtr<GetDatabaseNamesCallback> callback = GetDatabaseNamesCallback::create(m_frontendProvider.get(), requestId, document->securityOrigin()->toString()); + RefPtr<GetDatabaseNamesCallback> callback = GetDatabaseNamesCallback::create(requestCallback, document->securityOrigin()->toString()); GroupSettings* groupSettings = document->page()->group().groupSettings(); idbFactory->getDatabaseNames(callback.get(), document->securityOrigin(), document, groupSettings->indexedDBDatabasePath()); } -void InspectorIndexedDBAgent::requestDatabase(ErrorString* errorString, int requestId, const String& frameId, const String& databaseName) +void InspectorIndexedDBAgent::requestDatabase(ErrorString* errorString, const String& frameId, const String& databaseName, PassRefPtr<RequestDatabaseCallback> requestCallback) { Document* document = assertDocument(errorString, frameId, m_pageAgent); if (!document) @@ -744,11 +701,11 @@ void InspectorIndexedDBAgent::requestDatabase(ErrorString* errorString, int requ if (!idbFactory) return; - RefPtr<DatabaseLoaderCallback> databaseLoaderCallback = DatabaseLoaderCallback::create(m_frontendProvider.get(), requestId); + RefPtr<DatabaseLoaderCallback> databaseLoaderCallback = DatabaseLoaderCallback::create(requestCallback); databaseLoaderCallback->start(idbFactory, document->securityOrigin(), document, databaseName); } -void InspectorIndexedDBAgent::requestData(ErrorString* errorString, int requestId, const String& frameId, const String& databaseName, const String& objectStoreName, const String& indexName, int skipCount, int pageSize, const RefPtr<InspectorObject>* keyRange) +void InspectorIndexedDBAgent::requestData(ErrorString* errorString, const String& frameId, const String& databaseName, const String& objectStoreName, const String& indexName, int skipCount, int pageSize, const RefPtr<InspectorObject>* keyRange, PassRefPtr<RequestDataCallback> requestCallback) { Frame* frame = assertFrame(errorString, frameId, m_pageAgent); if (!frame) @@ -768,7 +725,7 @@ void InspectorIndexedDBAgent::requestData(ErrorString* errorString, int requestI return; } - RefPtr<DataLoaderCallback> dataLoaderCallback = DataLoaderCallback::create(m_frontendProvider, requestId, injectedScript, objectStoreName, indexName, idbKeyRange, skipCount, pageSize); + RefPtr<DataLoaderCallback> dataLoaderCallback = DataLoaderCallback::create(requestCallback, injectedScript, objectStoreName, indexName, idbKeyRange, skipCount, pageSize); dataLoaderCallback->start(idbFactory, document->securityOrigin(), document, databaseName); } diff --git a/Source/WebCore/inspector/InspectorIndexedDBAgent.h b/Source/WebCore/inspector/InspectorIndexedDBAgent.h index 869c7ad96..d1d7c37d3 100644 --- a/Source/WebCore/inspector/InspectorIndexedDBAgent.h +++ b/Source/WebCore/inspector/InspectorIndexedDBAgent.h @@ -34,8 +34,8 @@ #if ENABLE(INSPECTOR) && ENABLE(INDEXED_DATABASE) #include "InspectorBaseAgent.h" -#include "PlatformString.h" #include <wtf/PassOwnPtr.h> +#include <wtf/text/WTFString.h> namespace WebCore { @@ -46,30 +46,27 @@ typedef String ErrorString; class InspectorIndexedDBAgent : public InspectorBaseAgent<InspectorIndexedDBAgent>, public InspectorBackendDispatcher::IndexedDBCommandHandler { public: - class FrontendProvider; - static PassOwnPtr<InspectorIndexedDBAgent> create(InstrumentingAgents* instrumentingAgents, InspectorState* state, InjectedScriptManager* injectedScriptManager, InspectorPageAgent* pageAgent) { return adoptPtr(new InspectorIndexedDBAgent(instrumentingAgents, state, injectedScriptManager, pageAgent)); } ~InspectorIndexedDBAgent(); - virtual void setFrontend(InspectorFrontend*); virtual void clearFrontend(); virtual void restore(); // Called from the front-end. virtual void enable(ErrorString*); virtual void disable(ErrorString*); - virtual void requestDatabaseNamesForFrame(ErrorString*, int requestId, const String& frameId); - virtual void requestDatabase(ErrorString*, int requestId, const String& frameId, const String& databaseName); - virtual void requestData(ErrorString*, int requestId, const String& frameId, const String& databaseName, const String& objectStoreName, const String& indexName, int skipCount, int pageSize, const RefPtr<InspectorObject>* keyRange); + virtual void requestDatabaseNamesForFrame(ErrorString*, const String& frameId, PassRefPtr<RequestDatabaseNamesForFrameCallback>); + virtual void requestDatabase(ErrorString*, const String& frameId, const String& databaseName, PassRefPtr<RequestDatabaseCallback>); + virtual void requestData(ErrorString*, const String& frameId, const String& databaseName, const String& objectStoreName, const String& indexName, int skipCount, int pageSize, const RefPtr<InspectorObject>* keyRange, PassRefPtr<RequestDataCallback>); + private: InspectorIndexedDBAgent(InstrumentingAgents*, InspectorState*, InjectedScriptManager*, InspectorPageAgent*); InjectedScriptManager* m_injectedScriptManager; InspectorPageAgent* m_pageAgent; - RefPtr<FrontendProvider> m_frontendProvider; }; } // namespace WebCore diff --git a/Source/WebCore/inspector/InspectorInstrumentation.cpp b/Source/WebCore/inspector/InspectorInstrumentation.cpp index 7ea314c56..41b7bc81a 100644 --- a/Source/WebCore/inspector/InspectorInstrumentation.cpp +++ b/Source/WebCore/inspector/InspectorInstrumentation.cpp @@ -249,6 +249,12 @@ void InspectorInstrumentation::mouseDidMoveOverElementImpl(InstrumentingAgents* domAgent->mouseDidMoveOverElement(result, modifierFlags); } +void InspectorInstrumentation::didScrollImpl(InstrumentingAgents* instrumentingAgents) +{ + if (InspectorPageAgent* pageAgent = instrumentingAgents->inspectorPageAgent()) + pageAgent->didScroll(); +} + bool InspectorInstrumentation::handleMousePressImpl(InstrumentingAgents* instrumentingAgents) { if (InspectorDOMAgent* domAgent = instrumentingAgents->inspectorDOMAgent()) @@ -429,6 +435,12 @@ void InspectorInstrumentation::didCancelFrameImpl(InstrumentingAgents* instrumen timelineAgent->didCancelFrame(); } +void InspectorInstrumentation::didInvalidateLayoutImpl(InstrumentingAgents* instrumentingAgents, Frame* frame) +{ + if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent()) + timelineAgent->didInvalidateLayout(frame); +} + InspectorInstrumentationCookie InspectorInstrumentation::willLayoutImpl(InstrumentingAgents* instrumentingAgents, Frame* frame) { int timelineAgentId = 0; @@ -526,6 +538,8 @@ void InspectorInstrumentation::didRecalculateStyleImpl(const InspectorInstrument void InspectorInstrumentation::didScheduleStyleRecalculationImpl(InstrumentingAgents* instrumentingAgents, Document* document) { + if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTimelineAgent()) + timelineAgent->didScheduleStyleRecalculation(document->frame()); if (InspectorResourceAgent* resourceAgent = instrumentingAgents->inspectorResourceAgent()) resourceAgent->didScheduleStyleRecalculation(document); } @@ -892,6 +906,10 @@ void InspectorInstrumentation::addMessageToConsoleImpl(InstrumentingAgents* inst { if (InspectorConsoleAgent* consoleAgent = instrumentingAgents->inspectorConsoleAgent()) consoleAgent->addMessageToConsole(source, type, level, message, arguments, callStack); +#if ENABLE(JAVASCRIPT_DEBUGGER) + if (InspectorDebuggerAgent* debuggerAgent = instrumentingAgents->inspectorDebuggerAgent()) + debuggerAgent->addMessageToConsole(source, type); +#endif } void InspectorInstrumentation::addMessageToConsoleImpl(InstrumentingAgents* instrumentingAgents, MessageSource source, MessageType type, MessageLevel level, const String& message, const String& scriptId, unsigned lineNumber) diff --git a/Source/WebCore/inspector/InspectorInstrumentation.h b/Source/WebCore/inspector/InspectorInstrumentation.h index e4a79ed38..c25d3722b 100644 --- a/Source/WebCore/inspector/InspectorInstrumentation.h +++ b/Source/WebCore/inspector/InspectorInstrumentation.h @@ -33,7 +33,6 @@ #include "CSSSelector.h" #include "ConsoleTypes.h" -#include "Document.h" #include "Element.h" #include "Frame.h" #include "Page.h" @@ -53,6 +52,7 @@ class CharacterData; class DOMWindow; class DOMWrapperWorld; class Database; +class Document; class Element; class EventContext; class DocumentLoader; @@ -142,8 +142,10 @@ public: static void didFireTimer(const InspectorInstrumentationCookie&); static void didBeginFrame(Page*); static void didCancelFrame(Page*); + static void didInvalidateLayout(Frame*); static InspectorInstrumentationCookie willLayout(Frame*); static void didLayout(const InspectorInstrumentationCookie&); + static void didScroll(Page*); static InspectorInstrumentationCookie willLoadXHR(ScriptExecutionContext*, XMLHttpRequest*); static void didLoadXHR(const InspectorInstrumentationCookie&); static InspectorInstrumentationCookie willPaint(Frame*, GraphicsContext*, const LayoutRect&); @@ -317,8 +319,10 @@ private: static void didFireTimerImpl(const InspectorInstrumentationCookie&); static void didBeginFrameImpl(InstrumentingAgents*); static void didCancelFrameImpl(InstrumentingAgents*); + static void didInvalidateLayoutImpl(InstrumentingAgents*, Frame*); static InspectorInstrumentationCookie willLayoutImpl(InstrumentingAgents*, Frame*); static void didLayoutImpl(const InspectorInstrumentationCookie&); + static void didScrollImpl(InstrumentingAgents*); static InspectorInstrumentationCookie willLoadXHRImpl(InstrumentingAgents*, XMLHttpRequest*, ScriptExecutionContext*); static void didLoadXHRImpl(const InspectorInstrumentationCookie&); static InspectorInstrumentationCookie willPaintImpl(InstrumentingAgents*, GraphicsContext*, const LayoutRect&, Frame*); @@ -810,6 +814,15 @@ inline void InspectorInstrumentation::didCancelFrame(Page* page) #endif } +inline void InspectorInstrumentation::didInvalidateLayout(Frame* frame) +{ +#if ENABLE(INSPECTOR) + FAST_RETURN_IF_NO_FRONTENDS(void()); + if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame)) + didInvalidateLayoutImpl(instrumentingAgents, frame); +#endif +} + inline InspectorInstrumentationCookie InspectorInstrumentation::willLayout(Frame* frame) { #if ENABLE(INSPECTOR) @@ -829,6 +842,15 @@ inline void InspectorInstrumentation::didLayout(const InspectorInstrumentationCo #endif } +inline void InspectorInstrumentation::didScroll(Page* page) +{ +#if ENABLE(INSPECTOR) + FAST_RETURN_IF_NO_FRONTENDS(void()); + if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForPage(page)) + didScrollImpl(instrumentingAgents); +#endif +} + inline InspectorInstrumentationCookie InspectorInstrumentation::willLoadXHR(ScriptExecutionContext* context, XMLHttpRequest* request) { #if ENABLE(INSPECTOR) diff --git a/Source/WebCore/inspector/InspectorMemoryAgent.cpp b/Source/WebCore/inspector/InspectorMemoryAgent.cpp index ea5254aab..e8874cce5 100644 --- a/Source/WebCore/inspector/InspectorMemoryAgent.cpp +++ b/Source/WebCore/inspector/InspectorMemoryAgent.cpp @@ -83,28 +83,9 @@ static const char inspectorDOMData[] = "InspectorDOMData"; static const char inspectorJSHeapData[] = "InspectorJSHeapData"; static const char processPrivateMemory[] = "ProcessPrivateMemory"; -static const char memoryCache[] = "MemoryCache"; -static const char memoryCacheStructures[] = "MemoryCacheStructures"; -static const char cachedResource[] = "CachedResource"; -static const char cachedResourceImage[] = "CachedImages"; -static const char cachedResourceCSS[] = "CachedCssStyleSheets"; -static const char cachedResourceScript[] = "CachedScripts"; -static const char cachedResourceXSL[] = "CachedXslStyleSheets"; -static const char cachedResourceFont[] = "CachedFonts"; -static const char cachedResourceSVG[] = "CachedSVGGraphics"; -static const char cachedResourceShader[] = "CachedShaders"; -static const char cachedResourceXSLT[] = "CachedShadersXSLT"; - static const char renderTreeUsed[] = "RenderTreeUsed"; static const char renderTreeAllocated[] = "RenderTreeAllocated"; -static const char dom[] = "DOM"; -static const char domTreeOther[] = "DOMTreeOther"; -static const char domTreeDOM[] = "DOMTreeDOM"; -static const char domTreeCSS[] = "DOMTreeCSS"; -static const char domTreeBinding[] = "DOMTreeBinding"; -static const char domTreeLoader[] = "DOMTreeLoader"; - static const char domStorageCache[] = "DOMStorageCache"; } @@ -440,20 +421,13 @@ static PassRefPtr<InspectorMemoryBlock> renderTreeInfo(Page* page) return renderTreeAllocated.release(); } -static void addMemoryBlockFor(TypeBuilder::Array<InspectorMemoryBlock>* array, size_t size, const char* name) -{ - RefPtr<InspectorMemoryBlock> result = InspectorMemoryBlock::create().setName(name); - result->setSize(size); - array->addItem(result); -} - namespace { class DOMTreesIterator : public NodeWrapperVisitor { public: - DOMTreesIterator(Page* page, VisitedObjects& visitedObjects) + DOMTreesIterator(Page* page, MemoryInstrumentationImpl& memoryInstrumentation) : m_page(page) - , m_domMemoryUsage(visitedObjects) + , m_memoryInstrumentation(memoryInstrumentation) { } @@ -462,63 +436,56 @@ public: if (node->document() && node->document()->frame() && m_page != node->document()->frame()->page()) return; - m_domMemoryUsage.addRootObject(node); + m_memoryInstrumentation.addRootObject(node); } void visitFrame(Frame* frame) { - m_domMemoryUsage.addRootObject(frame); + m_memoryInstrumentation.addRootObject(frame); } void visitBindings() { - ScriptProfiler::collectBindingMemoryInfo(&m_domMemoryUsage); + ScriptProfiler::collectBindingMemoryInfo(&m_memoryInstrumentation); } void visitMemoryCache() { - m_domMemoryUsage.addRootObject(memoryCache()); + m_memoryInstrumentation.addRootObject(memoryCache()); } PassRefPtr<InspectorMemoryBlock> buildObjectForMemoryCache() const { size_t totalSize = 0; - COMPILE_ASSERT(MemoryInstrumentation::LastTypeEntry == MemoryInstrumentation::CachedResourceXSLT + 1, object_type_enum_was_changed_please_fix_the_implementation); - for (int i = MemoryInstrumentation::MemoryCacheStructures; i < MemoryInstrumentation::LastTypeEntry; ++i) - totalSize += m_domMemoryUsage.totalSize(static_cast<MemoryInstrumentation::ObjectType>(i)); - RefPtr<TypeBuilder::Array<InspectorMemoryBlock> > children = TypeBuilder::Array<InspectorMemoryBlock>::create(); - addMemoryBlockFor(children.get(), m_domMemoryUsage.totalSize(MemoryInstrumentation::MemoryCacheStructures), MemoryBlockName::memoryCacheStructures); - addMemoryBlockFor(children.get(), m_domMemoryUsage.totalSize(MemoryInstrumentation::CachedResource), MemoryBlockName::cachedResource); - addMemoryBlockFor(children.get(), m_domMemoryUsage.totalSize(MemoryInstrumentation::CachedResourceCSS), MemoryBlockName::cachedResourceCSS); - addMemoryBlockFor(children.get(), m_domMemoryUsage.totalSize(MemoryInstrumentation::CachedResourceFont), MemoryBlockName::cachedResourceFont); - addMemoryBlockFor(children.get(), m_domMemoryUsage.totalSize(MemoryInstrumentation::CachedResourceImage), MemoryBlockName::cachedResourceImage); - addMemoryBlockFor(children.get(), m_domMemoryUsage.totalSize(MemoryInstrumentation::CachedResourceScript), MemoryBlockName::cachedResourceScript); - addMemoryBlockFor(children.get(), m_domMemoryUsage.totalSize(MemoryInstrumentation::CachedResourceSVG), MemoryBlockName::cachedResourceSVG); - addMemoryBlockFor(children.get(), m_domMemoryUsage.totalSize(MemoryInstrumentation::CachedResourceShader), MemoryBlockName::cachedResourceShader); - addMemoryBlockFor(children.get(), m_domMemoryUsage.totalSize(MemoryInstrumentation::CachedResourceXSLT), MemoryBlockName::cachedResourceXSLT); - - RefPtr<InspectorMemoryBlock> block = InspectorMemoryBlock::create().setName(MemoryBlockName::memoryCache); + totalSize += addMemoryBlockFor(children.get(), WebCoreMemoryTypes::MemoryCacheStructures); + totalSize += addMemoryBlockFor(children.get(), WebCoreMemoryTypes::CachedResourceRaw); + totalSize += addMemoryBlockFor(children.get(), WebCoreMemoryTypes::CachedResourceCSS); + totalSize += addMemoryBlockFor(children.get(), WebCoreMemoryTypes::CachedResourceFont); + totalSize += addMemoryBlockFor(children.get(), WebCoreMemoryTypes::CachedResourceImage); + totalSize += addMemoryBlockFor(children.get(), WebCoreMemoryTypes::CachedResourceScript); + totalSize += addMemoryBlockFor(children.get(), WebCoreMemoryTypes::CachedResourceSVG); + totalSize += addMemoryBlockFor(children.get(), WebCoreMemoryTypes::CachedResourceShader); + totalSize += addMemoryBlockFor(children.get(), WebCoreMemoryTypes::CachedResourceXSLT); + + RefPtr<InspectorMemoryBlock> block = InspectorMemoryBlock::create().setName(WebCoreMemoryTypes::MemoryCache); block->setSize(totalSize); block->setChildren(children.release()); return block.release(); } - PassRefPtr<InspectorMemoryBlock> buildObjectForDOM() const + PassRefPtr<InspectorMemoryBlock> buildObjectForPage() const { size_t totalSize = 0; - for (int i = MemoryInstrumentation::Other; i < MemoryInstrumentation::MemoryCacheStructures; ++i) - totalSize += m_domMemoryUsage.totalSize(static_cast<MemoryInstrumentation::ObjectType>(i)); RefPtr<TypeBuilder::Array<InspectorMemoryBlock> > domChildren = TypeBuilder::Array<InspectorMemoryBlock>::create(); - addMemoryBlockFor(domChildren.get(), m_domMemoryUsage.totalSize(MemoryInstrumentation::Other), MemoryBlockName::domTreeOther); - addMemoryBlockFor(domChildren.get(), m_domMemoryUsage.totalSize(MemoryInstrumentation::DOM), MemoryBlockName::domTreeDOM); - addMemoryBlockFor(domChildren.get(), m_domMemoryUsage.totalSize(MemoryInstrumentation::CSS), MemoryBlockName::domTreeCSS); - addMemoryBlockFor(domChildren.get(), m_domMemoryUsage.totalSize(MemoryInstrumentation::Binding), MemoryBlockName::domTreeBinding); - addMemoryBlockFor(domChildren.get(), m_domMemoryUsage.totalSize(MemoryInstrumentation::Loader), MemoryBlockName::domTreeLoader); + totalSize += addMemoryBlockFor(domChildren.get(), WebCoreMemoryTypes::DOM); + totalSize += addMemoryBlockFor(domChildren.get(), WebCoreMemoryTypes::CSS); + totalSize += addMemoryBlockFor(domChildren.get(), WebCoreMemoryTypes::Binding); + totalSize += addMemoryBlockFor(domChildren.get(), WebCoreMemoryTypes::Loader); - RefPtr<InspectorMemoryBlock> dom = InspectorMemoryBlock::create().setName(MemoryBlockName::dom); + RefPtr<InspectorMemoryBlock> dom = InspectorMemoryBlock::create().setName(WebCoreMemoryTypes::Page); dom->setSize(totalSize); dom->setChildren(domChildren.release()); return dom.release(); @@ -527,20 +494,31 @@ public: void dumpStatistics(TypeBuilder::Array<InspectorMemoryBlock>* children, InspectorDataCounter* inspectorData) { children->addItem(buildObjectForMemoryCache()); - children->addItem(buildObjectForDOM()); - inspectorData->addComponent(MemoryBlockName::inspectorDOMData, m_domMemoryUsage.selfSize()); + children->addItem(buildObjectForPage()); + + inspectorData->addComponent(MemoryBlockName::inspectorDOMData, m_memoryInstrumentation.selfSize()); } private: + size_t addMemoryBlockFor(TypeBuilder::Array<InspectorMemoryBlock>* array, MemoryObjectType typeName) const + { + RefPtr<InspectorMemoryBlock> result = InspectorMemoryBlock::create().setName(typeName); + size_t size = m_memoryInstrumentation.totalSize(typeName); + result->setSize(size); + array->addItem(result); + return size; + } + Page* m_page; - MemoryInstrumentationImpl m_domMemoryUsage; + MemoryInstrumentationImpl& m_memoryInstrumentation; }; } static void collectDomTreeInfo(Page* page, VisitedObjects& visitedObjects, TypeBuilder::Array<InspectorMemoryBlock>* children, InspectorDataCounter* inspectorData) { - DOMTreesIterator domTreesIterator(page, visitedObjects); + MemoryInstrumentationImpl memoryInstrumentation(visitedObjects); + DOMTreesIterator domTreesIterator(page, memoryInstrumentation); ScriptProfiler::visitNodeWrappers(&domTreesIterator); diff --git a/Source/WebCore/inspector/InspectorOverlay.cpp b/Source/WebCore/inspector/InspectorOverlay.cpp index 981b2552b..4fd42da99 100644 --- a/Source/WebCore/inspector/InspectorOverlay.cpp +++ b/Source/WebCore/inspector/InspectorOverlay.cpp @@ -32,44 +32,30 @@ #include "InspectorOverlay.h" +#include "DocumentLoader.h" #include "Element.h" -#include "Font.h" -#include "FontCache.h" -#include "FontFamily.h" +#include "EmptyClients.h" #include "Frame.h" #include "FrameView.h" #include "GraphicsContext.h" -#include "GraphicsTypes.h" #include "InspectorClient.h" +#include "InspectorOverlayPage.h" +#include "InspectorValues.h" #include "Node.h" #include "Page.h" -#include "Range.h" #include "RenderBoxModelObject.h" #include "RenderInline.h" #include "RenderObject.h" +#include "ScriptSourceCode.h" +#include "ScriptValue.h" #include "Settings.h" #include "StyledElement.h" -#include "TextRun.h" #include <wtf/text/StringBuilder.h> namespace WebCore { namespace { -#if OS(WINDOWS) -static const unsigned fontHeightPx = 12; -#elif OS(MAC_OS_X) || OS(UNIX) -static const unsigned fontHeightPx = 11; -#endif - -const static int rectInflatePx = 4; -const static int borderWidthPx = 1; -const static int tooltipPadding = 4; - -const static int arrowTipOffset = 20; -const static float arrowHeight = 7; -const static float arrowHalfWidth = 7; - Path quadToPath(const FloatQuad& quad) { Path quadPath; @@ -81,7 +67,7 @@ Path quadToPath(const FloatQuad& quad) return quadPath; } -void drawOutlinedQuad(GraphicsContext& context, const FloatQuad& quad, const Color& fillColor, const Color& outlineColor) +void drawOutlinedQuad(GraphicsContext* context, const FloatQuad& quad, const Color& fillColor, const Color& outlineColor) { static const int outlineThickness = 2; @@ -90,269 +76,19 @@ void drawOutlinedQuad(GraphicsContext& context, const FloatQuad& quad, const Col // Clip out the quad, then draw with a 2px stroke to get a pixel // of outline (because inflating a quad is hard) { - context.save(); - context.clipOut(quadPath); + context->save(); + context->clipOut(quadPath); - context.setStrokeThickness(outlineThickness); - context.setStrokeColor(outlineColor, ColorSpaceDeviceRGB); - context.strokePath(quadPath); + context->setStrokeThickness(outlineThickness); + context->setStrokeColor(outlineColor, ColorSpaceDeviceRGB); + context->strokePath(quadPath); - context.restore(); + context->restore(); } // Now do the fill - context.setFillColor(fillColor, ColorSpaceDeviceRGB); - context.fillPath(quadPath); -} - -void drawOutlinedQuadWithClip(GraphicsContext& context, const FloatQuad& quad, const FloatQuad& clipQuad, const Color& fillColor) -{ - context.save(); - Path clipQuadPath = quadToPath(clipQuad); - context.clipOut(clipQuadPath); - drawOutlinedQuad(context, quad, fillColor, Color::transparent); - context.restore(); -} - -void drawHighlightForBox(GraphicsContext& context, const FloatQuad& contentQuad, const FloatQuad& paddingQuad, const FloatQuad& borderQuad, const FloatQuad& marginQuad, const HighlightConfig& highlightConfig) -{ - bool hasMargin = highlightConfig.margin != Color::transparent; - bool hasBorder = highlightConfig.border != Color::transparent; - bool hasPadding = highlightConfig.padding != Color::transparent; - bool hasContent = highlightConfig.content != Color::transparent || highlightConfig.contentOutline != Color::transparent; - - FloatQuad clipQuad; - Color clipColor; - if (hasMargin && (!hasBorder || marginQuad != borderQuad)) { - drawOutlinedQuadWithClip(context, marginQuad, borderQuad, highlightConfig.margin); - clipQuad = borderQuad; - } - if (hasBorder && (!hasPadding || borderQuad != paddingQuad)) { - drawOutlinedQuadWithClip(context, borderQuad, paddingQuad, highlightConfig.border); - clipQuad = paddingQuad; - } - if (hasPadding && (!hasContent || paddingQuad != contentQuad)) { - drawOutlinedQuadWithClip(context, paddingQuad, contentQuad, highlightConfig.padding); - clipQuad = contentQuad; - } - if (hasContent) - drawOutlinedQuad(context, contentQuad, highlightConfig.content, highlightConfig.contentOutline); -} - -void drawHighlightForSVGRenderer(GraphicsContext& context, const Vector<FloatQuad>& absoluteQuads, const HighlightConfig& highlightConfig) -{ - for (size_t i = 0; i < absoluteQuads.size(); ++i) - drawOutlinedQuad(context, absoluteQuads[i], highlightConfig.content, Color::transparent); -} - -int drawSubstring(const TextRun& globalTextRun, int offset, int length, const Color& textColor, const Font& font, GraphicsContext& context, const LayoutRect& titleRect) -{ - context.setFillColor(textColor, ColorSpaceDeviceRGB); - context.drawText(font, globalTextRun, IntPoint(titleRect.pixelSnappedX() + rectInflatePx, titleRect.pixelSnappedY() + font.fontMetrics().height()), offset, offset + length); - return offset + length; -} - -float calculateArrowTipX(const LayoutRect& anchorBox, const LayoutRect& titleRect) -{ - const static int anchorTipOffsetPx = 2; - - int minX = titleRect.x() + arrowHalfWidth; - int maxX = titleRect.maxX() - arrowHalfWidth; - int anchorX = anchorBox.x(); - int anchorMaxX = anchorBox.maxX(); - - int x = titleRect.x() + arrowTipOffset; // Default tooltip position. - if (x < anchorX) - x = anchorX + anchorTipOffsetPx; - else if (x > anchorMaxX) - x = anchorMaxX - anchorTipOffsetPx; - - if (x < minX) - x = minX; - else if (x > maxX) - x = maxX; - - return x; -} - -void setUpFontDescription(FontDescription& fontDescription, WebCore::Settings* settings) -{ -#define TOOLTIP_FONT_FAMILIES(size, ...) \ -static const unsigned tooltipFontFaceSize = size;\ -static const AtomicString* tooltipFontFace[size] = { __VA_ARGS__ }; - -#if OS(WINDOWS) -TOOLTIP_FONT_FAMILIES(2, new AtomicString("Consolas"), new AtomicString("Lucida Console")) -#elif OS(MAC_OS_X) -TOOLTIP_FONT_FAMILIES(2, new AtomicString("Menlo"), new AtomicString("Monaco")) -#elif OS(UNIX) -TOOLTIP_FONT_FAMILIES(1, new AtomicString("dejavu sans mono")) -#endif -// In the default case, we get the settings-provided monospace font. - -#undef TOOLTIP_FONT_FAMILIES - - fontDescription.setRenderingMode(settings->fontRenderingMode()); - fontDescription.setComputedSize(fontHeightPx); - - const AtomicString& fixedFontFamily = settings->fixedFontFamily(); - if (!fixedFontFamily.isEmpty()) { - fontDescription.setGenericFamily(FontDescription::MonospaceFamily); - FontFamily* currentFamily = 0; - for (unsigned i = 0; i < tooltipFontFaceSize; ++i) { - if (!currentFamily) { - fontDescription.firstFamily().setFamily(*tooltipFontFace[i]); - fontDescription.firstFamily().appendFamily(0); - currentFamily = &fontDescription.firstFamily(); - } else { - RefPtr<SharedFontFamily> newFamily = SharedFontFamily::create(); - newFamily->setFamily(*tooltipFontFace[i]); - currentFamily->appendFamily(newFamily); - currentFamily = newFamily.get(); - } - } - RefPtr<SharedFontFamily> newFamily = SharedFontFamily::create(); - newFamily->setFamily(fixedFontFamily); - currentFamily->appendFamily(newFamily); - currentFamily = newFamily.get(); - } -} - -void drawElementTitle(GraphicsContext& context, Node* node, RenderObject* renderer, const IntRect& boundingBox, const IntRect& anchorBox, const FloatRect& visibleRect, WebCore::Settings* settings) -{ - DEFINE_STATIC_LOCAL(Color, backgroundColor, (255, 255, 194)); - DEFINE_STATIC_LOCAL(Color, tagColor, (136, 18, 128)); // Same as .webkit-html-tag. - DEFINE_STATIC_LOCAL(Color, attrColor, (26, 26, 166)); // Same as .webkit-html-attribute-value. - DEFINE_STATIC_LOCAL(Color, normalColor, (Color::black)); - DEFINE_STATIC_LOCAL(Color, pxAndBorderColor, (128, 128, 128)); - - DEFINE_STATIC_LOCAL(String, pxString, ("px")); - const static UChar timesUChar[] = { 0x0020, 0x00D7, 0x0020, 0 }; - DEFINE_STATIC_LOCAL(String, timesString, (timesUChar)); // × string - - FontCachePurgePreventer fontCachePurgePreventer; - - Element* element = static_cast<Element*>(node); - bool isXHTML = element->document()->isXHTMLDocument(); - StringBuilder nodeTitle; - nodeTitle.append(isXHTML ? element->nodeName() : element->nodeName().lower()); - unsigned tagNameLength = nodeTitle.length(); - - const AtomicString& idValue = element->getIdAttribute(); - unsigned idStringLength = 0; - String idString; - if (!idValue.isNull() && !idValue.isEmpty()) { - nodeTitle.append("#"); - nodeTitle.append(idValue); - idStringLength = 1 + idValue.length(); - } - - HashSet<AtomicString> usedClassNames; - unsigned classesStringLength = 0; - if (element->hasClass() && element->isStyledElement()) { - const SpaceSplitString& classNamesString = static_cast<StyledElement*>(element)->classNames(); - size_t classNameCount = classNamesString.size(); - for (size_t i = 0; i < classNameCount; ++i) { - const AtomicString& className = classNamesString[i]; - if (usedClassNames.contains(className)) - continue; - usedClassNames.add(className); - nodeTitle.append("."); - nodeTitle.append(className); - classesStringLength += 1 + className.length(); - } - } - - RenderBoxModelObject* modelObject = renderer->isBoxModelObject() ? toRenderBoxModelObject(renderer) : 0; - - String widthNumberPart = " " + String::number(modelObject ? adjustForAbsoluteZoom(modelObject->pixelSnappedOffsetWidth(), modelObject) : boundingBox.width()); - nodeTitle.append(widthNumberPart); - nodeTitle.append(pxString); - nodeTitle.append(timesString); - String heightNumberPart = String::number(modelObject ? adjustForAbsoluteZoom(modelObject->pixelSnappedOffsetHeight(), modelObject) : boundingBox.height()); - nodeTitle.append(heightNumberPart); - nodeTitle.append(pxString); - - FontDescription desc; - setUpFontDescription(desc, settings); - Font font = Font(desc, 0, 0); - font.update(0); - - TextRun nodeTitleRun(nodeTitle.toString()); - IntPoint titleBasePoint = IntPoint(anchorBox.x(), anchorBox.maxY() - 1); - titleBasePoint.move(rectInflatePx, rectInflatePx); - IntRect titleRect = enclosingIntRect(font.selectionRectForText(nodeTitleRun, titleBasePoint, fontHeightPx)); - titleRect.inflate(rectInflatePx); - - // The initial offsets needed to compensate for a 1px-thick border stroke (which is not a part of the rectangle). - int dx = -borderWidthPx; - int dy = borderWidthPx; - - // If the tip sticks beyond the right of visibleRect, right-align the tip with the said boundary. - if (titleRect.maxX() + dx > visibleRect.maxX()) - dx = visibleRect.maxX() - titleRect.maxX(); - - // If the tip sticks beyond the left of visibleRect, left-align the tip with the said boundary. - if (titleRect.x() + dx < visibleRect.x()) - dx = visibleRect.x() - titleRect.x() - borderWidthPx; - - // If the tip sticks beyond the bottom of visibleRect, show the tip at top of bounding box. - if (titleRect.maxY() + dy > visibleRect.maxY()) { - dy = anchorBox.y() - titleRect.maxY() - borderWidthPx; - // If the tip still sticks beyond the bottom of visibleRect, bottom-align the tip with the said boundary. - if (titleRect.maxY() + dy > visibleRect.maxY()) - dy = visibleRect.maxY() - titleRect.maxY(); - } - - // If the tip sticks beyond the top of visibleRect, show the tip at top of visibleRect. - if (titleRect.y() + dy < visibleRect.y()) - dy = visibleRect.y() - titleRect.y() + borderWidthPx; - - titleRect.move(dx, dy); - - bool isArrowAtTop = titleRect.y() > anchorBox.y(); - titleRect.move(0, tooltipPadding * (isArrowAtTop ? 1 : -1)); - - { - float arrowTipX = calculateArrowTipX(anchorBox, titleRect); - int arrowBaseY = isArrowAtTop ? titleRect.y() : titleRect.maxY(); - int arrowOppositeY = isArrowAtTop ? titleRect.maxY() : titleRect.y(); - - FloatPoint points[8]; - points[0] = FloatPoint(arrowTipX - arrowHalfWidth, arrowBaseY); - points[1] = FloatPoint(arrowTipX, arrowBaseY + arrowHeight * (isArrowAtTop ? -1 : 1)); - points[2] = FloatPoint(arrowTipX + arrowHalfWidth, arrowBaseY); - points[3] = FloatPoint(titleRect.maxX(), arrowBaseY); - points[4] = FloatPoint(titleRect.maxX(), arrowOppositeY); - points[5] = FloatPoint(titleRect.x(), arrowOppositeY); - points[6] = FloatPoint(titleRect.x(), arrowBaseY); - points[7] = points[0]; - - Path path; - path.moveTo(points[0]); - for (int i = 1; i < 8; ++i) - path.addLineTo(points[i]); - - context.save(); - context.translate(0.5f, 0.5f); - context.setStrokeColor(pxAndBorderColor, ColorSpaceDeviceRGB); - context.setFillColor(backgroundColor, ColorSpaceDeviceRGB); - context.setStrokeThickness(borderWidthPx); - context.fillPath(path); - context.strokePath(path); - context.restore(); - } - - int currentPos = 0; - currentPos = drawSubstring(nodeTitleRun, currentPos, tagNameLength, tagColor, font, context, titleRect); - if (idStringLength) - currentPos = drawSubstring(nodeTitleRun, currentPos, idStringLength, attrColor, font, context, titleRect); - if (classesStringLength) - currentPos = drawSubstring(nodeTitleRun, currentPos, classesStringLength, attrColor, font, context, titleRect); - currentPos = drawSubstring(nodeTitleRun, currentPos, widthNumberPart.length(), normalColor, font, context, titleRect); - currentPos = drawSubstring(nodeTitleRun, currentPos, pxString.length() + timesString.length(), pxAndBorderColor, font, context, titleRect); - currentPos = drawSubstring(nodeTitleRun, currentPos, heightNumberPart.length(), normalColor, font, context, titleRect); - drawSubstring(nodeTitleRun, currentPos, pxString.length(), pxAndBorderColor, font, context, titleRect); + context->setFillColor(fillColor, ColorSpaceDeviceRGB); + context->fillPath(quadPath); } static void contentsQuadToPage(const FrameView* mainView, const FrameView* view, FloatQuad& quad) @@ -364,7 +100,7 @@ static void contentsQuadToPage(const FrameView* mainView, const FrameView* view, quad += mainView->scrollOffset(); } -static void getOrDrawNodeHighlight(GraphicsContext* context, Node* node, const HighlightConfig& highlightConfig, Highlight* highlight) +static void buildNodeHighlight(Node* node, const HighlightConfig& highlightConfig, Highlight* highlight) { RenderObject* renderer = node->renderer(); Frame* containingFrame = node->document()->frame(); @@ -372,17 +108,13 @@ static void getOrDrawNodeHighlight(GraphicsContext* context, Node* node, const H if (!renderer || !containingFrame) return; + highlight->setColors(highlightConfig); FrameView* containingView = containingFrame->view(); FrameView* mainView = containingFrame->page()->mainFrame()->view(); IntRect boundingBox = pixelSnappedIntRect(containingView->contentsToRootView(renderer->absoluteBoundingBoxRect())); boundingBox.move(mainView->scrollOffset()); IntRect titleAnchorBox = boundingBox; - FloatRect visibleRect = mainView->visibleContentRect(); - // Don't translate the context if the frame is rendered in page coordinates. - if (context && !mainView->delegatesScrolling()) - context->translate(-visibleRect.x(), -visibleRect.y()); - // RenderSVGRoot should be highlighted through the isBox() code path, all other SVG elements should just dump their absoluteQuads(). #if ENABLE(SVG) bool isSVGRenderer = renderer->node() && renderer->node()->isSVGElement() && !renderer->isSVGRoot(); @@ -395,9 +127,6 @@ static void getOrDrawNodeHighlight(GraphicsContext* context, Node* node, const H renderer->absoluteQuads(highlight->quads); for (size_t i = 0; i < highlight->quads.size(); ++i) contentsQuadToPage(mainView, containingView, highlight->quads[i]); - - if (context) - drawHighlightForSVGRenderer(*context, highlight->quads, highlightConfig); } else if (renderer->isBox() || renderer->isRenderInline()) { LayoutRect contentBox; LayoutRect paddingBox; @@ -449,39 +178,17 @@ static void getOrDrawNodeHighlight(GraphicsContext* context, Node* node, const H highlight->quads.append(absBorderQuad); highlight->quads.append(absPaddingQuad); highlight->quads.append(absContentQuad); - - if (context) - drawHighlightForBox(*context, absContentQuad, absPaddingQuad, absBorderQuad, absMarginQuad, highlightConfig); } - - // Draw node title if necessary. - - if (!node->isElementNode()) - return; - - if (context && highlightConfig.showInfo) - drawElementTitle(*context, node, renderer, pixelSnappedIntRect(boundingBox), pixelSnappedIntRect(titleAnchorBox), visibleRect, containingFrame->settings()); } -static void getOrDrawRectHighlight(GraphicsContext* context, Page* page, IntRect* rect, const HighlightConfig& highlightConfig, Highlight *highlight) +static void buildRectHighlight(Page* page, IntRect* rect, const HighlightConfig& highlightConfig, Highlight *highlight) { if (!page) return; - + highlight->setColors(highlightConfig); FloatRect highlightRect(*rect); - highlight->type = HighlightTypeRects; highlight->quads.append(highlightRect); - - if (context) { - FrameView* view = page->mainFrame()->view(); - if (!view->delegatesScrolling()) { - FloatRect visibleRect = view->visibleContentRect(); - context->translate(-visibleRect.x(), -visibleRect.y()); - } - - drawOutlinedQuad(*context, highlightRect, highlightConfig.content, highlightConfig.contentOutline); - } } } // anonymous namespace @@ -492,14 +199,21 @@ InspectorOverlay::InspectorOverlay(Page* page, InspectorClient* client) { } +InspectorOverlay::~InspectorOverlay() +{ +} + void InspectorOverlay::paint(GraphicsContext& context) { - drawPausedInDebugger(context); - drawNodeHighlight(context); - drawRectHighlight(context); + if (m_pausedInDebuggerMessage.isNull() && !m_highlightNode && !m_highlightRect) + return; + GraphicsContextStateSaver stateSaver(context); + FrameView* view = overlayPage()->mainFrame()->view(); + ASSERT(!view->needsLayout()); + view->paint(&context, IntRect(0, 0, view->width(), view->height())); } -void InspectorOverlay::drawOutline(GraphicsContext& context, const LayoutRect& rect, const Color& color) +void InspectorOverlay::drawOutline(GraphicsContext* context, const LayoutRect& rect, const Color& color) { FloatRect outlineRect = rect; drawOutlinedQuad(context, outlineRect, Color(), color); @@ -511,13 +225,10 @@ void InspectorOverlay::getHighlight(Highlight* highlight) const return; highlight->type = HighlightTypeRects; - if (m_highlightNode) { - highlight->setColors(m_nodeHighlightConfig); - getOrDrawNodeHighlight(0, m_highlightNode.get(), m_nodeHighlightConfig, highlight); - } else { - highlight->setColors(m_rectHighlightConfig); - getOrDrawRectHighlight(0, m_page, m_highlightRect.get(), m_rectHighlightConfig, highlight); - } + if (m_highlightNode) + buildNodeHighlight(m_highlightNode.get(), m_nodeHighlightConfig, highlight); + else + buildRectHighlight(m_page, m_highlightRect.get(), m_rectHighlightConfig, highlight); } void InspectorOverlay::setPausedInDebuggerMessage(const String* message) @@ -554,60 +265,202 @@ Node* InspectorOverlay::highlightedNode() const void InspectorOverlay::update() { - if (m_highlightNode || m_highlightRect || !m_pausedInDebuggerMessage.isNull()) - m_client->highlight(); - else + if (!m_highlightNode && !m_highlightRect && m_pausedInDebuggerMessage.isNull()) { m_client->hideHighlight(); + return; + } + + FrameView* view = m_page->mainFrame()->view(); + FrameView* overlayView = overlayPage()->mainFrame()->view(); + IntRect visibleRect = enclosingIntRect(view->visibleContentRect()); + overlayView->resize(visibleRect.width(), visibleRect.height()); + + // Clear canvas and paint things. + reset(); + + drawNodeHighlight(); + drawRectHighlight(); + drawPausedInDebuggerMessage(); + + // Position DOM elements. + overlayPage()->mainFrame()->document()->recalcStyle(Node::Force); + if (overlayView->needsLayout()) + overlayView->layout(); + + // Kick paint. + m_client->highlight(); +} + +static RefPtr<InspectorObject> buildObjectForPoint(const FloatPoint& point) +{ + RefPtr<InspectorObject> object = InspectorObject::create(); + object->setNumber("x", point.x()); + object->setNumber("y", point.y()); + return object.release(); } -void InspectorOverlay::drawNodeHighlight(GraphicsContext& context) +static RefPtr<InspectorArray> buildArrayForQuad(const FloatQuad& quad) +{ + RefPtr<InspectorArray> array = InspectorArray::create(); + array->pushObject(buildObjectForPoint(quad.p1())); + array->pushObject(buildObjectForPoint(quad.p2())); + array->pushObject(buildObjectForPoint(quad.p3())); + array->pushObject(buildObjectForPoint(quad.p4())); + return array.release(); +} + +static RefPtr<InspectorObject> buildObjectForHighlight(FrameView* mainView, const Highlight& highlight) +{ + RefPtr<InspectorObject> object = InspectorObject::create(); + RefPtr<InspectorArray> array = InspectorArray::create(); + for (size_t i = 0; i < highlight.quads.size(); ++i) + array->pushArray(buildArrayForQuad(highlight.quads[i])); + object->setArray("quads", array.release()); + object->setString("contentColor", highlight.contentColor.serialized()); + object->setString("contentOutlineColor", highlight.contentOutlineColor.serialized()); + object->setString("paddingColor", highlight.paddingColor.serialized()); + object->setString("borderColor", highlight.borderColor.serialized()); + object->setString("marginColor", highlight.marginColor.serialized()); + + FloatRect visibleRect = mainView->visibleContentRect(); + if (!mainView->delegatesScrolling()) { + object->setNumber("scrollX", visibleRect.x()); + object->setNumber("scrollY", visibleRect.y()); + } else { + object->setNumber("scrollX", 0); + object->setNumber("scrollY", 0); + } + + return object.release(); +} + +void InspectorOverlay::drawNodeHighlight() { if (!m_highlightNode) return; Highlight highlight; - getOrDrawNodeHighlight(&context, m_highlightNode.get(), m_nodeHighlightConfig, &highlight); + buildNodeHighlight(m_highlightNode.get(), m_nodeHighlightConfig, &highlight); + RefPtr<InspectorObject> highlightObject = buildObjectForHighlight(m_page->mainFrame()->view(), highlight); + + Node* node = m_highlightNode.get(); + if (node->isElementNode() && m_nodeHighlightConfig.showInfo && node->renderer() && node->document()->frame()) { + RefPtr<InspectorObject> elementInfo = InspectorObject::create(); + Element* element = toElement(node); + bool isXHTML = element->document()->isXHTMLDocument(); + elementInfo->setString("tagName", isXHTML ? element->nodeName() : element->nodeName().lower()); + elementInfo->setString("idValue", element->getIdAttribute()); + HashSet<AtomicString> usedClassNames; + if (element->hasClass() && element->isStyledElement()) { + StringBuilder classNames; + const SpaceSplitString& classNamesString = static_cast<StyledElement*>(element)->classNames(); + size_t classNameCount = classNamesString.size(); + for (size_t i = 0; i < classNameCount; ++i) { + const AtomicString& className = classNamesString[i]; + if (usedClassNames.contains(className)) + continue; + usedClassNames.add(className); + classNames.append('.'); + classNames.append(className); + } + elementInfo->setString("className", classNames.toString()); + } + + RenderObject* renderer = node->renderer(); + Frame* containingFrame = node->document()->frame(); + FrameView* containingView = containingFrame->view(); + IntRect boundingBox = pixelSnappedIntRect(containingView->contentsToRootView(renderer->absoluteBoundingBoxRect())); + RenderBoxModelObject* modelObject = renderer->isBoxModelObject() ? toRenderBoxModelObject(renderer) : 0; + elementInfo->setString("nodeWidth", String::number(modelObject ? adjustForAbsoluteZoom(modelObject->pixelSnappedOffsetWidth(), modelObject) : boundingBox.width())); + elementInfo->setString("nodeHeight", String::number(modelObject ? adjustForAbsoluteZoom(modelObject->pixelSnappedOffsetHeight(), modelObject) : boundingBox.height())); + highlightObject->setObject("elementInfo", elementInfo.release()); + } + evaluateInOverlay("drawNodeHighlight", highlightObject); } -void InspectorOverlay::drawRectHighlight(GraphicsContext& context) +void InspectorOverlay::drawRectHighlight() { if (!m_highlightRect) return; Highlight highlight; - getOrDrawRectHighlight(&context, m_page, m_highlightRect.get(), m_rectHighlightConfig, &highlight); + buildRectHighlight(m_page, m_highlightRect.get(), m_rectHighlightConfig, &highlight); + evaluateInOverlay("highlightRect", buildObjectForHighlight(m_page->mainFrame()->view(), highlight)); } -void InspectorOverlay::drawPausedInDebugger(GraphicsContext& context) +void InspectorOverlay::drawPausedInDebuggerMessage() { - if (m_pausedInDebuggerMessage.isNull()) - return; + if (!m_pausedInDebuggerMessage.isNull()) + evaluateInOverlay("drawPausedInDebuggerMessage", m_pausedInDebuggerMessage); +} - DEFINE_STATIC_LOCAL(Color, backgroundColor, (0, 0, 0, 31)); - DEFINE_STATIC_LOCAL(Color, textBackgroundColor, (255, 255, 194)); - DEFINE_STATIC_LOCAL(Color, borderColor, (128, 128, 128)); +Page* InspectorOverlay::overlayPage() +{ + if (m_overlayPage) + return m_overlayPage.get(); + + static FrameLoaderClient* dummyFrameLoaderClient = new EmptyFrameLoaderClient; + Page::PageClients pageClients; + fillWithEmptyClients(pageClients); + m_overlayPage = adoptPtr(new Page(pageClients)); + + Settings* settings = m_page->settings(); + Settings* overlaySettings = m_overlayPage->settings(); + + overlaySettings->setStandardFontFamily(settings->standardFontFamily()); + overlaySettings->setSerifFontFamily(settings->serifFontFamily()); + overlaySettings->setSansSerifFontFamily(settings->sansSerifFontFamily()); + overlaySettings->setCursiveFontFamily(settings->cursiveFontFamily()); + overlaySettings->setFantasyFontFamily(settings->fantasyFontFamily()); + overlaySettings->setPictographFontFamily(settings->pictographFontFamily()); + overlaySettings->setMinimumFontSize(settings->minimumFontSize()); + overlaySettings->setMinimumLogicalFontSize(settings->minimumLogicalFontSize()); + overlaySettings->setMediaEnabled(false); + overlaySettings->setScriptEnabled(true); + overlaySettings->setPluginsEnabled(false); + + RefPtr<Frame> frame = Frame::create(m_overlayPage.get(), 0, dummyFrameLoaderClient); + frame->setView(FrameView::create(frame.get())); + frame->init(); + FrameLoader* loader = frame->loader(); + frame->view()->setCanHaveScrollbars(false); + frame->view()->setTransparent(true); + ASSERT(loader->activeDocumentLoader()); + loader->activeDocumentLoader()->writer()->setMIMEType("text/html"); + loader->activeDocumentLoader()->writer()->begin(); + loader->activeDocumentLoader()->writer()->addData(reinterpret_cast<const char*>(InspectorOverlayPage_html), sizeof(InspectorOverlayPage_html)); + loader->activeDocumentLoader()->writer()->end(); - Frame* frame = m_page->mainFrame(); - Settings* settings = frame->settings(); - IntRect visibleRect = IntRect(IntPoint(), frame->view()->visibleSize()); +#if OS(WINDOWS) + evaluateInOverlay("setPlatform", "windows"); +#elif OS(MAC_OS_X) + evaluateInOverlay("setPlatform", "mac"); +#elif OS(UNIX) + evaluateInOverlay("setPlatform", "linux"); +#endif - context.setFillColor(backgroundColor, ColorSpaceDeviceRGB); - context.fillRect(visibleRect); + return m_overlayPage.get(); +} - FontDescription desc; - setUpFontDescription(desc, settings); - Font font = Font(desc, 0, 0); - font.update(0); +void InspectorOverlay::reset() +{ + evaluateInOverlay("reset", String::number(m_page->deviceScaleFactor())); +} - TextRun textRun(m_pausedInDebuggerMessage); - IntRect titleRect = enclosingIntRect(font.selectionRectForText(textRun, IntPoint(), fontHeightPx)); - titleRect.inflate(rectInflatePx); - titleRect.setLocation(IntPoint(visibleRect.width() / 2 - titleRect.width() / 2, 0)); +void InspectorOverlay::evaluateInOverlay(const String& method, const String& argument) +{ + RefPtr<InspectorArray> command = InspectorArray::create(); + command->pushString(method); + command->pushString(argument); + overlayPage()->mainFrame()->script()->evaluate(ScriptSourceCode(makeString("dispatch(", command->toJSONString(), ")"))); +} - context.setFillColor(textBackgroundColor, ColorSpaceDeviceRGB); - context.setStrokeColor(borderColor, ColorSpaceDeviceRGB); - context.drawRect(titleRect); - drawSubstring(textRun, 0, m_pausedInDebuggerMessage.length(), Color::black, font, context, titleRect); +void InspectorOverlay::evaluateInOverlay(const String& method, PassRefPtr<InspectorValue> argument) +{ + RefPtr<InspectorArray> command = InspectorArray::create(); + command->pushString(method); + command->pushValue(argument); + overlayPage()->mainFrame()->script()->evaluate(ScriptSourceCode(makeString("dispatch(", command->toJSONString(), ")"))); } } // namespace WebCore diff --git a/Source/WebCore/inspector/InspectorOverlay.h b/Source/WebCore/inspector/InspectorOverlay.h index ac22ff1c3..3cd57591b 100644 --- a/Source/WebCore/inspector/InspectorOverlay.h +++ b/Source/WebCore/inspector/InspectorOverlay.h @@ -32,18 +32,19 @@ #include "Color.h" #include "FloatQuad.h" #include "LayoutTypes.h" -#include "Node.h" #include <wtf/OwnPtr.h> #include <wtf/PassOwnPtr.h> #include <wtf/RefPtr.h> #include <wtf/Vector.h> +#include <wtf/text/WTFString.h> namespace WebCore { class Color; class GraphicsContext; class InspectorClient; +class InspectorValue; class IntRect; class Node; class Page; @@ -66,12 +67,14 @@ struct Highlight { void setColors(const HighlightConfig& highlightConfig) { contentColor = highlightConfig.content; + contentOutlineColor = highlightConfig.contentOutline; paddingColor = highlightConfig.padding; borderColor = highlightConfig.border; marginColor = highlightConfig.margin; } Color contentColor; + Color contentOutlineColor; Color paddingColor; Color borderColor; Color marginColor; @@ -88,9 +91,11 @@ public: { return adoptPtr(new InspectorOverlay(page, client)); } + ~InspectorOverlay(); + void update(); void paint(GraphicsContext&); - void drawOutline(GraphicsContext&, const LayoutRect&, const Color&); + void drawOutline(GraphicsContext*, const LayoutRect&, const Color&); void getHighlight(Highlight*) const; void setPausedInDebuggerMessage(const String*); @@ -104,10 +109,13 @@ public: private: InspectorOverlay(Page*, InspectorClient*); - void update(); - void drawNodeHighlight(GraphicsContext&); - void drawRectHighlight(GraphicsContext&); - void drawPausedInDebugger(GraphicsContext&); + void drawNodeHighlight(); + void drawRectHighlight(); + void drawPausedInDebuggerMessage(); + Page* overlayPage(); + void reset(); + void evaluateInOverlay(const String& method, const String& argument); + void evaluateInOverlay(const String& method, PassRefPtr<InspectorValue> argument); Page* m_page; InspectorClient* m_client; @@ -115,6 +123,7 @@ private: RefPtr<Node> m_highlightNode; HighlightConfig m_nodeHighlightConfig; OwnPtr<IntRect> m_highlightRect; + OwnPtr<Page> m_overlayPage; HighlightConfig m_rectHighlightConfig; }; diff --git a/Source/WebCore/inspector/InspectorOverlayPage.html b/Source/WebCore/inspector/InspectorOverlayPage.html new file mode 100644 index 000000000..8bc9ef667 --- /dev/null +++ b/Source/WebCore/inspector/InspectorOverlayPage.html @@ -0,0 +1,435 @@ +<!-- + 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. + 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. +--> +<!DOCTYPE html> +<html> +<head> +<style> +body { + margin: 0; + padding: 0; +} + +body.platform-mac { + font-size: 11px; + font-family: Menlo, Monaco; +} + +body.platform-windows { + font-size: 12px; + font-family: Consolas, Lucida Console; +} + +body.platform-linux { + font-size: 11px; + font-family: dejavu sans mono; +} + +.fill { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; +} + +.dimmed { + background-color: rgba(0, 0, 0, 0.31); +} + +.message-line { + margin: 10px 0; + text-align: center; +} + +.message-box { + background-color: rgb(255, 255, 194); + border: 1px solid rgb(128, 128, 128); + display: inline-block; + padding: 2px 4px; +} + +.px { + color: rgb(128, 128, 128); +} + +#element-title { + position: absolute; + z-index: 10; +} + +#tag-name { + color: rgb(136, 18, 128); +} + +#node-id { + color: rgb(26, 26, 166); +} +</style> +<script> +const lightGridColor = "rgba(0,0,0,0.2)"; +const darkGridColor = "rgba(0,0,0,0.5)"; +const transparentColor = "rgba(0, 0, 0, 0)"; + +function drawPausedInDebuggerMessage(message) +{ + var pausedInDebugger = document.getElementById("paused-in-debugger"); + pausedInDebugger.textContent = message; + pausedInDebugger.style.visibility = "visible"; + document.body.classList.add("dimmed"); +} + +function _drawGrid(highlight) +{ + context.save(); + + var width = canvas.width; + var height = canvas.height; + + context.fillStyle = "rgba(255, 255, 255, 0.6)"; + context.fillRect(0, 0, canvas.width, 15); + context.fillRect(0, 15, 15, canvas.height); + + context.translate(-highlight.scrollX, 0.5 - highlight.scrollY); + context.lineWidth = 1; + + const gridSubStep = 5; + const gridStep = 50; + + context.strokeStyle = lightGridColor; + + for (var y = gridSubStep; y < highlight.scrollY + height; y += gridSubStep) { + if (!(y % gridStep)) + continue; + context.beginPath(); + context.moveTo(highlight.scrollX, y); + context.lineTo(highlight.scrollX + gridSubStep, y); + context.stroke(); + } + + context.strokeStyle = darkGridColor; + context.fillStyle = darkGridColor; + for (var y = gridStep; y < height + highlight.scrollY; y += gridStep) { + context.beginPath(); + context.moveTo(highlight.scrollX, y); + var markLength = (y % (gridStep * 2)) ? 5 : 8; + context.lineTo(highlight.scrollX + markLength, y); + context.stroke(); + if (!(y % (gridStep * 2))) { + context.save(); + context.translate(highlight.scrollX, y); + context.rotate(-Math.PI / 2); + context.fillText(y, 2, 13); + context.restore(); + } + } + + context.translate(0.5, -0.5); + + context.strokeStyle = lightGridColor; + for (var x = gridSubStep; x < highlight.scrollX + width; x += gridSubStep) { + if (!(x % gridStep)) + continue; + context.beginPath(); + context.moveTo(x, highlight.scrollY); + context.lineTo(x, highlight.scrollY + gridSubStep); + context.stroke(); + } + + context.strokeStyle = darkGridColor; + context.fillStyle = darkGridColor; + for (var x = gridStep; x < width + highlight.scrollX; x += gridStep) { + context.beginPath(); + context.moveTo(x, highlight.scrollY); + var markLength = (x % (gridStep * 2)) ? 5 : 8; + context.lineTo(x, highlight.scrollY + markLength); + context.stroke(); + if (!(x % (gridStep * 2))) + context.fillText(x, x + 2, highlight.scrollY + 13); + } + context.restore(); +} + +function quadToPath(quad) +{ + context.beginPath(); + context.moveTo(quad[0].x, quad[0].y); + context.lineTo(quad[1].x, quad[1].y); + context.lineTo(quad[2].x, quad[2].y); + context.lineTo(quad[3].x, quad[3].y); + context.closePath(); + return context; +} + +function drawOutlinedQuad(quad, fillColor, outlineColor) +{ + context.save(); + context.lineWidth = 2; + quadToPath(quad).clip(); + context.fillStyle = fillColor; + context.fill(); + if (outlineColor) { + context.strokeStyle = outlineColor; + context.stroke(); + } + context.restore(); +} + +function drawOutlinedQuadWithClip(quad, clipQuad, fillColor) +{ + var canvas = document.getElementById("canvas"); + context.fillStyle = fillColor; + context.save(); + context.lineWidth = 0; + quadToPath(quad).fill(); + context.globalCompositeOperation = "destination-out"; + context.fillStyle = "red"; + quadToPath(clipQuad).fill(); + context.restore(); +} + +function quadEquals(quad1, quad2) +{ + return quad1[0].x === quad2[0].x && quad1[0].y === quad2[0].y && + quad1[1].x === quad2[1].x && quad1[1].y === quad2[1].y && + quad1[2].x === quad2[2].x && quad1[2].y === quad2[2].y && + quad1[3].x === quad2[3].x && quad1[3].y === quad2[3].y; +} + +function reset(deviceScaleFactor) +{ + window.canvas = document.getElementById("canvas"); + window.context = canvas.getContext("2d"); + canvas.width = deviceScaleFactor * document.body.offsetWidth; + canvas.height = deviceScaleFactor * document.body.offsetHeight; + canvas.style.width = document.body.offsetWidth + "px"; + canvas.style.height = document.body.offsetHeight + "px"; + context.scale(deviceScaleFactor, deviceScaleFactor); + + document.getElementById("paused-in-debugger").style.visibility = "hidden"; + document.getElementById("element-title").style.visibility = "hidden"; + document.body.classList.remove("dimmed"); +} + +function _drawElementTitle(highlight) +{ + var elementInfo = highlight.elementInfo; + if (!highlight.elementInfo) + return; + + document.getElementById("tag-name").textContent = elementInfo.tagName; + document.getElementById("node-id").textContent = elementInfo.nodeId ? "#" + elementInfo.nodeId : ""; + document.getElementById("class-name").textContent = elementInfo.className || ""; + document.getElementById("node-width").textContent = elementInfo.nodeWidth; + document.getElementById("node-height").textContent = elementInfo.nodeHeight; + var elementTitle = document.getElementById("element-title"); + + var marginQuad = highlight.quads[0]; + + var titleWidth = elementTitle.offsetWidth + 6; + var titleHeight = elementTitle.offsetHeight + 4; + + var anchorTop = marginQuad[0].y; + var anchorBottom = marginQuad[3].y + + const arrowHeight = 7; + var renderArrowUp = false; + var renderArrowDown = false; + + var boxX = Math.max(2, marginQuad[0].x); + if (boxX + titleWidth > canvas.width) + boxX = canvas.width - titleWidth - 2; + + var boxY; + if (anchorTop > canvas.height) { + boxY = canvas.height - titleHeight - arrowHeight; + renderArrowDown = true; + } else if (anchorBottom < 0) { + boxY = arrowHeight; + renderArrowUp = true; + } else if (anchorBottom + titleHeight + arrowHeight < canvas.height) { + boxY = anchorBottom + arrowHeight - 4; + renderArrowUp = true; + } else if (anchorTop - titleHeight - arrowHeight > 0) { + boxY = anchorTop - titleHeight - arrowHeight + 3; + renderArrowDown = true; + } else + boxY = arrowHeight; + + context.save(); + context.translate(0.5, 0.5); + context.beginPath(); + context.moveTo(boxX, boxY); + if (renderArrowUp) { + context.lineTo(boxX + 2 * arrowHeight, boxY); + context.lineTo(boxX + 3 * arrowHeight, boxY - arrowHeight); + context.lineTo(boxX + 4 * arrowHeight, boxY); + } + context.lineTo(boxX + titleWidth, boxY); + context.lineTo(boxX + titleWidth, boxY + titleHeight); + if (renderArrowDown) { + context.lineTo(boxX + 4 * arrowHeight, boxY + titleHeight); + context.lineTo(boxX + 3 * arrowHeight, boxY + titleHeight + arrowHeight); + context.lineTo(boxX + 2 * arrowHeight, boxY + titleHeight); + } + context.lineTo(boxX, boxY + titleHeight); + context.closePath(); + context.fillStyle = "rgb(255, 255, 194)"; + context.fill(); + context.strokeStyle = "rgb(128, 128, 128)"; + context.stroke(); + + context.restore(); + + elementTitle.style.visibility = "visible"; + elementTitle.style.top = (boxY + 3) + "px"; + elementTitle.style.left = (boxX + 3) + "px"; +} + +function _drawRulers(highlight) +{ + context.save(); + context.strokeStyle = "rgba(128, 128, 128, 0.3)"; + context.lineWidth = 1; + context.translate(0.5, 0.5); + var leftmostXForY = {}; + var topmostYForX = {}; + + for (var i = 0; i < highlight.quads.length; ++i) { + var quad = highlight.quads[i]; + for (var j = 0; j < quad.length; ++j) { + var x = quad[j].x; + var y = quad[j].y; + topmostYForX[Math.round(x)] = Math.min(topmostYForX[x] || Number.MAX_VALUE, Math.round(quad[j].y)); + leftmostXForY[Math.round(y)] = Math.min(leftmostXForY[y] || Number.MAX_VALUE, Math.round(quad[j].x)); + } + } + + for (var y in leftmostXForY) { + context.beginPath(); + context.moveTo(0, y); + context.lineTo(leftmostXForY[y], y); + context.stroke(); + } + + for (var x in topmostYForX) { + context.beginPath(); + context.moveTo(x, 0); + context.lineTo(x, topmostYForX[x]); + context.stroke(); + } + + context.restore(); +} + +function drawNodeHighlight(highlight) +{ + if (!highlight.quads.length) { + _drawGrid(highlight); + return; + } + + context.save(); + + for (var i = 0; i < highlight.quads.length; ++i) { + var quad = highlight.quads[i]; + for (var j = 0; j < quad.length; ++j) { + quad[j].x -= highlight.scrollX; + quad[j].y -= highlight.scrollY; + } + } + + var quads = highlight.quads.slice(); + var contentQuad = quads.pop(); + var paddingQuad = quads.pop(); + var borderQuad = quads.pop(); + var marginQuad = quads.pop(); + + var hasContent = contentQuad && highlight.contentColor !== transparentColor || highlight.contentOutlineColor !== transparentColor; + var hasPadding = paddingQuad && highlight.paddingColor !== transparentColor; + var hasBorder = borderQuad && highlight.borderColor !== transparentColor; + var hasMargin = marginQuad && highlight.marginColor !== transparentColor; + + var clipQuad; + if (hasMargin && (!hasBorder || !quadEquals(marginQuad, borderQuad))) { + drawOutlinedQuadWithClip(marginQuad, borderQuad, highlight.marginColor); + clipQuad = borderQuad; + } + if (hasBorder && (!hasPadding || !quadEquals(borderQuad, paddingQuad))) { + drawOutlinedQuadWithClip(borderQuad, paddingQuad, highlight.borderColor); + clipQuad = paddingQuad; + } + if (hasPadding && (!hasContent || !quadEquals(paddingQuad, contentQuad))) { + drawOutlinedQuadWithClip(paddingQuad, contentQuad, highlight.paddingColor); + clipQuad = contentQuad; + } + if (hasContent) + drawOutlinedQuad(contentQuad, highlight.contentColor, highlight.contentOutlineColor); + + _drawGrid(highlight); + _drawElementTitle(highlight); + _drawRulers(highlight); + context.restore(); +} + +function drawRectHighlight(highlight) +{ + context.save(); + drawOutlinedQuad(highlight.quads[0], highlight.contentColor, highlight.contentOutlineColor); + context.restore(); +} + +function setPlatform(platform) +{ + document.body.classList.add("platform-" + platform); +} + +function dispatch(message) +{ + var functionName = message.shift(); + window[functionName].apply(null, message); +} + +function log(text) +{ + var logEntry = document.createElement("div"); + logEntry.textContent = text; + document.getElementById("log").appendChild(logEntry); +} + +</script> +</head> +<body class="fill"> +<div class="message-line"><span class="message-box" id="paused-in-debugger"></span></div> +</body> +<canvas id="canvas" class="fill"></canvas> +<div id="element-title"> + <span id="tag-name"></span><span id="node-id"></span><span id="class-name"></span> + <span id="node-width"></span><span class="px">px</span><span class="px"> × </span><span id="node-height"></span><span class="px">px</span> +</div> +<div id="log"></div> +</html> diff --git a/Source/WebCore/inspector/InspectorPageAgent.cpp b/Source/WebCore/inspector/InspectorPageAgent.cpp index c6b06bfa6..707c7515e 100644 --- a/Source/WebCore/inspector/InspectorPageAgent.cpp +++ b/Source/WebCore/inspector/InspectorPageAgent.cpp @@ -74,11 +74,11 @@ #include "TextEncoding.h" #include "TextResourceDecoder.h" #include "UserGestureIndicator.h" - #include <wtf/CurrentTime.h> #include <wtf/ListHashSet.h> #include <wtf/Vector.h> #include <wtf/text/Base64.h> +#include <wtf/text/StringBuilder.h> using namespace std; @@ -197,8 +197,7 @@ bool InspectorPageAgent::cachedResourceContent(CachedResource* cachedResource, S if (!decoder) return false; String content = decoder->decode(buffer->data(), buffer->size()); - content += decoder->flush(); - *result = content; + *result = content + decoder->flush(); return true; } default: @@ -503,7 +502,7 @@ void InspectorPageAgent::getCookies(ErrorString*, RefPtr<TypeBuilder::Array<Type ListHashSet<Cookie> rawCookiesList; // If we can't get raw cookies - fall back to String representation - String stringCookiesList; + StringBuilder stringCookiesList; // Return value to getRawCookies should be the same for every call because // the return value is platform/network backend specific, and the call will @@ -519,7 +518,7 @@ void InspectorPageAgent::getCookies(ErrorString*, RefPtr<TypeBuilder::Array<Type if (!rawCookiesImplemented) { // FIXME: We need duplication checking for the String representation of cookies. ExceptionCode ec = 0; - stringCookiesList += document->cookie(ec); + stringCookiesList.append(document->cookie(ec)); // Exceptions are thrown by cookie() in sandboxed frames. That won't happen here // because "document" is the document of the main frame of the page. ASSERT(!ec); @@ -539,7 +538,7 @@ void InspectorPageAgent::getCookies(ErrorString*, RefPtr<TypeBuilder::Array<Type *cookiesString = ""; } else { cookies = TypeBuilder::Array<TypeBuilder::Page::Cookie>::create(); - *cookiesString = stringCookiesList; + *cookiesString = stringCookiesList.toString(); } } @@ -899,7 +898,7 @@ void InspectorPageAgent::didPaint() Color(0, 0, 0xFF, 0x3F), }; - m_overlay->drawOutline(*m_lastPaintContext, m_lastPaintRect, colors[colorSelector++ % WTF_ARRAY_LENGTH(colors)]); + m_overlay->drawOutline(m_lastPaintContext, m_lastPaintRect, colors[colorSelector++ % WTF_ARRAY_LENGTH(colors)]); m_lastPaintContext = 0; } @@ -915,6 +914,12 @@ void InspectorPageAgent::didLayout() if (currentWidth && currentHeight) m_client->autoZoomPageToFitWidth(); + m_overlay->update(); +} + +void InspectorPageAgent::didScroll() +{ + m_overlay->update(); } PassRefPtr<TypeBuilder::Page::Frame> InspectorPageAgent::buildObjectForFrame(Frame* frame) diff --git a/Source/WebCore/inspector/InspectorPageAgent.h b/Source/WebCore/inspector/InspectorPageAgent.h index 7b91779f9..7b71b211f 100644 --- a/Source/WebCore/inspector/InspectorPageAgent.h +++ b/Source/WebCore/inspector/InspectorPageAgent.h @@ -38,10 +38,10 @@ #include "GeolocationPosition.h" #include "InspectorBaseAgent.h" #include "InspectorFrontend.h" -#include "PlatformString.h" #include <wtf/HashMap.h> #include <wtf/RefCounted.h> #include <wtf/Vector.h> +#include <wtf/text/WTFString.h> namespace WebCore { @@ -137,6 +137,7 @@ public: void willPaint(GraphicsContext*, const LayoutRect&); void didPaint(); void didLayout(); + void didScroll(); // Inspector Controller API virtual void setFrontend(InspectorFrontend*); diff --git a/Source/WebCore/inspector/InspectorProfilerAgent.cpp b/Source/WebCore/inspector/InspectorProfilerAgent.cpp index 997dd4a09..4540aa7cd 100644 --- a/Source/WebCore/inspector/InspectorProfilerAgent.cpp +++ b/Source/WebCore/inspector/InspectorProfilerAgent.cpp @@ -123,6 +123,7 @@ InspectorProfilerAgent::InspectorProfilerAgent(InstrumentingAgents* instrumentin , m_frontend(0) , m_enabled(false) , m_recordingUserInitiatedProfile(false) + , m_headersRequested(false) , m_currentUserInitiatedProfileNumber(-1) , m_nextUserInitiatedProfileNumber(1) , m_nextUserInitiatedHeapSnapshotNumber(1) @@ -139,7 +140,7 @@ void InspectorProfilerAgent::addProfile(PassRefPtr<ScriptProfile> prpProfile, un { RefPtr<ScriptProfile> profile = prpProfile; m_profiles.add(profile->uid(), profile); - if (m_frontend) + if (m_frontend && m_headersRequested) m_frontend->addProfileHeader(createProfileHeader(*profile)); addProfileFinishedMessageToConsole(profile, lineNumber, sourceURL); } @@ -220,6 +221,7 @@ void InspectorProfilerAgent::disable() if (!m_enabled) return; m_enabled = false; + m_headersRequested = false; PageScriptDebugServer::shared().recompileAllJSFunctionsSoon(); } @@ -242,6 +244,7 @@ String InspectorProfilerAgent::getCurrentUserInitiatedProfileName(bool increment void InspectorProfilerAgent::getProfileHeaders(ErrorString*, RefPtr<TypeBuilder::Array<TypeBuilder::Profiler::ProfileHeader> >& headers) { + m_headersRequested = true; headers = TypeBuilder::Array<TypeBuilder::Profiler::ProfileHeader>::create(); ProfilesMap::iterator profilesEnd = m_profiles.end(); @@ -321,7 +324,7 @@ void InspectorProfilerAgent::resetState() void InspectorProfilerAgent::resetFrontendProfiles() { - if (m_frontend && enabled() + if (m_headersRequested && m_frontend && m_profiles.begin() == m_profiles.end() && m_snapshots.begin() == m_snapshots.end()) m_frontend->resetProfiles(); @@ -346,6 +349,7 @@ void InspectorProfilerAgent::restore() restoreEnablement(); // Revisit this. + m_headersRequested = true; resetFrontendProfiles(); if (m_state->getBoolean(ProfilerAgentState::userInitiatedProfiling)) start(); diff --git a/Source/WebCore/inspector/InspectorProfilerAgent.h b/Source/WebCore/inspector/InspectorProfilerAgent.h index 5082666d7..c35536fae 100644 --- a/Source/WebCore/inspector/InspectorProfilerAgent.h +++ b/Source/WebCore/inspector/InspectorProfilerAgent.h @@ -34,11 +34,11 @@ #include "InspectorBaseAgent.h" #include "InspectorFrontend.h" -#include "PlatformString.h" #include <wtf/Forward.h> #include <wtf/HashMap.h> #include <wtf/Noncopyable.h> #include <wtf/PassOwnPtr.h> +#include <wtf/text/WTFString.h> namespace WebCore { @@ -119,6 +119,7 @@ private: InspectorFrontend::Profiler* m_frontend; bool m_enabled; bool m_recordingUserInitiatedProfile; + bool m_headersRequested; int m_currentUserInitiatedProfileNumber; unsigned m_nextUserInitiatedProfileNumber; unsigned m_nextUserInitiatedHeapSnapshotNumber; diff --git a/Source/WebCore/inspector/InspectorResourceAgent.h b/Source/WebCore/inspector/InspectorResourceAgent.h index 5c9fbe262..f8fc8bd30 100644 --- a/Source/WebCore/inspector/InspectorResourceAgent.h +++ b/Source/WebCore/inspector/InspectorResourceAgent.h @@ -33,11 +33,11 @@ #include "InspectorBaseAgent.h" #include "InspectorFrontend.h" -#include "PlatformString.h" #include <wtf/PassOwnPtr.h> #include <wtf/RefCounted.h> #include <wtf/Vector.h> +#include <wtf/text/WTFString.h> #if ENABLE(INSPECTOR) diff --git a/Source/WebCore/inspector/InspectorState.h b/Source/WebCore/inspector/InspectorState.h index a40e35041..1ec373e77 100644 --- a/Source/WebCore/inspector/InspectorState.h +++ b/Source/WebCore/inspector/InspectorState.h @@ -34,10 +34,9 @@ #if ENABLE(INSPECTOR) #include "InspectorValues.h" -#include "PlatformString.h" - #include <wtf/HashMap.h> #include <wtf/RefCounted.h> +#include <wtf/text/WTFString.h> namespace WebCore { diff --git a/Source/WebCore/inspector/InspectorStyleSheet.cpp b/Source/WebCore/inspector/InspectorStyleSheet.cpp index 83b402d6e..3cf4d489c 100644 --- a/Source/WebCore/inspector/InspectorStyleSheet.cpp +++ b/Source/WebCore/inspector/InspectorStyleSheet.cpp @@ -325,7 +325,7 @@ PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSComputedStyleProperty> > Insp bool InspectorStyle::setPropertyText(unsigned index, const String& propertyText, bool overwrite, String* oldText, ExceptionCode& ec) { ASSERT(m_parentStyleSheet); - DEFINE_STATIC_LOCAL(String, bogusPropertyName, ("-webkit-boguz-propertee")); + DEFINE_STATIC_LOCAL(String, bogusPropertyName, (ASCIILiteral("-webkit-boguz-propertee"))); if (!m_parentStyleSheet->ensureParsedDataReady()) { ec = NOT_FOUND_ERR; @@ -635,7 +635,7 @@ Vector<String> InspectorStyle::longhandProperties(const String& shorthandPropert NewLineAndWhitespace& InspectorStyle::newLineAndWhitespaceDelimiters() const { - DEFINE_STATIC_LOCAL(String, defaultPrefix, (" ")); + DEFINE_STATIC_LOCAL(String, defaultPrefix, (ASCIILiteral(" "))); if (m_formatAcquired) return m_format; @@ -737,12 +737,18 @@ String InspectorStyleSheet::finalURL() const void InspectorStyleSheet::reparseStyleSheet(const String& text) { - CSSStyleSheet::RuleMutationScope mutationScope(m_pageStyleSheet.get()); - m_pageStyleSheet->contents()->clearRules(); - m_pageStyleSheet->contents()->parseString(text); - m_pageStyleSheet->clearChildRuleCSSOMWrappers(); - m_inspectorStyles.clear(); - fireStyleSheetChanged(); + { + // Have a separate scope for clearRules() (bug 95324). + CSSStyleSheet::RuleMutationScope mutationScope(m_pageStyleSheet.get()); + m_pageStyleSheet->contents()->clearRules(); + } + { + CSSStyleSheet::RuleMutationScope mutationScope(m_pageStyleSheet.get()); + m_pageStyleSheet->contents()->parseString(text); + m_pageStyleSheet->clearChildRuleCSSOMWrappers(); + m_inspectorStyles.clear(); + fireStyleSheetChanged(); + } } bool InspectorStyleSheet::setText(const String& text) @@ -795,12 +801,14 @@ bool InspectorStyleSheet::setRuleSelector(const InspectorCSSId& id, const String CSSStyleRule* InspectorStyleSheet::addRule(const String& selector, ExceptionCode& ec) { - String styleSheetText; - bool success = getText(&styleSheetText); + String text; + bool success = getText(&text); if (!success) { ec = NOT_FOUND_ERR; return 0; } + StringBuilder styleSheetText; + styleSheetText.append(text); m_pageStyleSheet->addRule(selector, "", ec); if (ec) @@ -809,13 +817,13 @@ CSSStyleRule* InspectorStyleSheet::addRule(const String& selector, ExceptionCode CSSStyleRule* rule = InspectorCSSAgent::asCSSStyleRule(m_pageStyleSheet->item(m_pageStyleSheet->length() - 1)); ASSERT(rule); - if (styleSheetText.length()) - styleSheetText += "\n"; + if (!styleSheetText.isEmpty()) + styleSheetText.append('\n'); - styleSheetText += selector; - styleSheetText += " {}"; + styleSheetText.append(selector); + styleSheetText.appendLiteral(" {}"); // Using setText() as this operation changes the style sheet rule set. - setText(styleSheetText); + setText(styleSheetText.toString()); fireStyleSheetChanged(); diff --git a/Source/WebCore/inspector/InspectorStyleSheet.h b/Source/WebCore/inspector/InspectorStyleSheet.h index 0af9f3c5a..d426d579f 100644 --- a/Source/WebCore/inspector/InspectorStyleSheet.h +++ b/Source/WebCore/inspector/InspectorStyleSheet.h @@ -31,13 +31,13 @@ #include "InspectorStyleTextEditor.h" #include "InspectorTypeBuilder.h" #include "InspectorValues.h" -#include "PlatformString.h" #include <wtf/HashMap.h> #include <wtf/HashSet.h> #include <wtf/PassRefPtr.h> #include <wtf/RefPtr.h> #include <wtf/Vector.h> +#include <wtf/text/WTFString.h> class ParsedStyleSheet; diff --git a/Source/WebCore/inspector/InspectorStyleTextEditor.cpp b/Source/WebCore/inspector/InspectorStyleTextEditor.cpp index 7976a4abe..059a650b2 100644 --- a/Source/WebCore/inspector/InspectorStyleTextEditor.cpp +++ b/Source/WebCore/inspector/InspectorStyleTextEditor.cpp @@ -104,11 +104,11 @@ void InspectorStyleTextEditor::insertProperty(unsigned index, const String& prop textToSet.insert(formatLineFeed, formattingPrependOffset); } if (!isHTMLLineBreak(m_styleText[propertyStart])) - textToSet += formatLineFeed; + textToSet.append(formatLineFeed); } else { String fullPrefix = formatLineFeed + formatPropertyPrefix; long fullPrefixLength = fullPrefix.length(); - textToSet += fullPrefix; + textToSet.append(fullPrefix); if (insertFirstInSource && (propertyStart < fullPrefixLength || m_styleText.substring(propertyStart - fullPrefixLength, fullPrefixLength) != fullPrefix)) textToSet.insert(fullPrefix, formattingPrependOffset); } diff --git a/Source/WebCore/inspector/InspectorStyleTextEditor.h b/Source/WebCore/inspector/InspectorStyleTextEditor.h index 5c0a22efc..d7502561b 100644 --- a/Source/WebCore/inspector/InspectorStyleTextEditor.h +++ b/Source/WebCore/inspector/InspectorStyleTextEditor.h @@ -26,9 +26,9 @@ #define InspectorStyleTextEditor_h #include "CSSPropertySourceData.h" -#include "PlatformString.h" #include <wtf/Vector.h> +#include <wtf/text/WTFString.h> namespace WebCore { diff --git a/Source/WebCore/inspector/InspectorTimelineAgent.cpp b/Source/WebCore/inspector/InspectorTimelineAgent.cpp index 68ff5e5ea..ebd7a3551 100644 --- a/Source/WebCore/inspector/InspectorTimelineAgent.cpp +++ b/Source/WebCore/inspector/InspectorTimelineAgent.cpp @@ -36,6 +36,7 @@ #include "Event.h" #include "Frame.h" +#include "FrameView.h" #include "IdentifiersFactory.h" #include "InspectorClient.h" #include "InspectorCounters.h" @@ -65,8 +66,10 @@ static const char Program[] = "Program"; static const char EventDispatch[] = "EventDispatch"; static const char BeginFrame[] = "BeginFrame"; -static const char Layout[] = "Layout"; +static const char ScheduleStyleRecalculation[] = "ScheduleStyleRecalculation"; static const char RecalculateStyles[] = "RecalculateStyles"; +static const char InvalidateLayout[] = "InvalidateLayout"; +static const char Layout[] = "Layout"; static const char Paint[] = "Paint"; static const char DecodeImage[] = "DecodeImage"; static const char ResizeImage[] = "ResizeImage"; @@ -227,6 +230,13 @@ void InspectorTimelineAgent::didDispatchEvent() didCompleteCurrentRecord(TimelineRecordType::EventDispatch); } +void InspectorTimelineAgent::didInvalidateLayout(Frame* frame) +{ + if (frame->view()->layoutPending()) + return; + appendRecord(InspectorObject::create(), TimelineRecordType::InvalidateLayout, true, frame); +} + void InspectorTimelineAgent::willLayout(Frame* frame) { pushCurrentRecord(InspectorObject::create(), TimelineRecordType::Layout, true, frame); @@ -237,6 +247,11 @@ void InspectorTimelineAgent::didLayout() didCompleteCurrentRecord(TimelineRecordType::Layout); } +void InspectorTimelineAgent::didScheduleStyleRecalculation(Frame* frame) +{ + appendRecord(InspectorObject::create(), TimelineRecordType::ScheduleStyleRecalculation, true, frame); +} + void InspectorTimelineAgent::willRecalculateStyle(Frame* frame) { pushCurrentRecord(InspectorObject::create(), TimelineRecordType::RecalculateStyles, true, frame); @@ -487,12 +502,16 @@ void InspectorTimelineAgent::innerAddRecordToTimeline(PassRefPtr<InspectorObject } } -void InspectorTimelineAgent::setHeapSizeStatistics(InspectorObject* record) +static size_t getUsedHeapSize() { HeapInfo info; ScriptGCEvent::getHeapSize(info); - record->setNumber("usedHeapSize", info.usedJSHeapSize); - record->setNumber("totalHeapSize", info.totalJSHeapSize); + return info.usedJSHeapSize; +} + +void InspectorTimelineAgent::setHeapSizeStatistics(InspectorObject* record) +{ + record->setNumber("usedHeapSize", getUsedHeapSize()); if (m_state->getBoolean(TimelineAgentState::includeMemoryDetails)) { RefPtr<InspectorObject> counters = InspectorObject::create(); @@ -520,6 +539,9 @@ void InspectorTimelineAgent::didCompleteCurrentRecord(const String& type) entry.record->setObject("data", entry.data); entry.record->setArray("children", entry.children); entry.record->setNumber("endTime", timestamp()); + size_t usedHeapSizeDelta = getUsedHeapSize() - entry.usedHeapSizeAtStart; + if (usedHeapSizeDelta) + entry.record->setNumber("usedHeapSizeDelta", usedHeapSizeDelta); addRecordToTimeline(entry.record, type, entry.frameId); } } @@ -557,7 +579,7 @@ void InspectorTimelineAgent::pushCurrentRecord(PassRefPtr<InspectorObject> data, String frameId; if (frame && m_pageAgent) frameId = m_pageAgent->frameId(frame); - m_recordStack.append(TimelineRecordEntry(record.release(), data, InspectorArray::create(), type, frameId)); + m_recordStack.append(TimelineRecordEntry(record.release(), data, InspectorArray::create(), type, frameId, getUsedHeapSize())); if (hasLowLevelDetails && !m_platformInstrumentationClientInstalledAtStackDepth && !PlatformInstrumentation::hasClient()) { m_platformInstrumentationClientInstalledAtStackDepth = m_recordStack.size(); PlatformInstrumentation::setClient(this); diff --git a/Source/WebCore/inspector/InspectorTimelineAgent.h b/Source/WebCore/inspector/InspectorTimelineAgent.h index 61e8ddc00..0ea54e28f 100644 --- a/Source/WebCore/inspector/InspectorTimelineAgent.h +++ b/Source/WebCore/inspector/InspectorTimelineAgent.h @@ -96,9 +96,11 @@ public: void didBeginFrame(); void didCancelFrame(); + void didInvalidateLayout(Frame*); void willLayout(Frame*); void didLayout(); + void didScheduleStyleRecalculation(Frame*); void willRecalculateStyle(Frame*); void didRecalculateStyle(); @@ -159,8 +161,8 @@ public: private: struct TimelineRecordEntry { - TimelineRecordEntry(PassRefPtr<InspectorObject> record, PassRefPtr<InspectorObject> data, PassRefPtr<InspectorArray> children, const String& type, const String& frameId) - : record(record), data(data), children(children), type(type), frameId(frameId) + TimelineRecordEntry(PassRefPtr<InspectorObject> record, PassRefPtr<InspectorObject> data, PassRefPtr<InspectorArray> children, const String& type, const String& frameId, size_t usedHeapSizeAtStart) + : record(record), data(data), children(children), type(type), frameId(frameId), usedHeapSizeAtStart(usedHeapSizeAtStart) { } RefPtr<InspectorObject> record; @@ -168,6 +170,7 @@ private: RefPtr<InspectorArray> children; String type; String frameId; + size_t usedHeapSizeAtStart; }; InspectorTimelineAgent(InstrumentingAgents*, InspectorPageAgent*, InspectorState*, InspectorType, InspectorClient*); diff --git a/Source/WebCore/inspector/InspectorValues.h b/Source/WebCore/inspector/InspectorValues.h index 743ad03c5..1f0aecb02 100644 --- a/Source/WebCore/inspector/InspectorValues.h +++ b/Source/WebCore/inspector/InspectorValues.h @@ -31,12 +31,12 @@ #ifndef InspectorValues_h #define InspectorValues_h -#include "PlatformString.h" #include <wtf/Forward.h> #include <wtf/HashMap.h> #include <wtf/RefCounted.h> #include <wtf/Vector.h> #include <wtf/text/StringHash.h> +#include <wtf/text/WTFString.h> namespace WebCore { diff --git a/Source/WebCore/inspector/InspectorWebGLAgent.h b/Source/WebCore/inspector/InspectorWebGLAgent.h index 1d3771d22..31b7afcf3 100644 --- a/Source/WebCore/inspector/InspectorWebGLAgent.h +++ b/Source/WebCore/inspector/InspectorWebGLAgent.h @@ -36,10 +36,10 @@ #include "InspectorBaseAgent.h" #include "InspectorFrontend.h" #include "InspectorTypeBuilder.h" -#include "PlatformString.h" #include "ScriptState.h" #include <wtf/PassOwnPtr.h> #include <wtf/PassRefPtr.h> +#include <wtf/text/WTFString.h> namespace WebCore { diff --git a/Source/WebCore/inspector/InspectorWorkerResource.h b/Source/WebCore/inspector/InspectorWorkerResource.h index ef1b8c92f..2b8041fdf 100644 --- a/Source/WebCore/inspector/InspectorWorkerResource.h +++ b/Source/WebCore/inspector/InspectorWorkerResource.h @@ -33,10 +33,10 @@ #if ENABLE(WORKERS) && ENABLE(INSPECTOR) -#include "PlatformString.h" #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> #include <wtf/RefPtr.h> +#include <wtf/text/WTFString.h> namespace WebCore { diff --git a/Source/WebCore/inspector/MemoryInstrumentationImpl.cpp b/Source/WebCore/inspector/MemoryInstrumentationImpl.cpp index 347f72d5f..47a91d5b3 100644 --- a/Source/WebCore/inspector/MemoryInstrumentationImpl.cpp +++ b/Source/WebCore/inspector/MemoryInstrumentationImpl.cpp @@ -39,8 +39,6 @@ namespace WebCore { MemoryInstrumentationImpl::MemoryInstrumentationImpl(VisitedObjects& visitedObjects) : m_visitedObjects(visitedObjects) { - for (int i = 0; i < LastTypeEntry; ++i) - m_totalSizes[i] = 0; } void MemoryInstrumentationImpl::processDeferredInstrumentedPointers() @@ -52,10 +50,12 @@ void MemoryInstrumentationImpl::processDeferredInstrumentedPointers() } } -void MemoryInstrumentationImpl::countObjectSize(ObjectType objectType, size_t size) +void MemoryInstrumentationImpl::countObjectSize(MemoryObjectType objectType, size_t size) { - ASSERT(objectType >= 0 && objectType < LastTypeEntry); - m_totalSizes[objectType] += size; + ASSERT(objectType != GenericMemoryTypes::Undefined); + TypeToSizeMap::AddResult result = m_totalSizes.add(objectType, size); + if (!result.isNewEntry) + result.iterator->second += size; } void MemoryInstrumentationImpl::deferInstrumentedPointer(PassOwnPtr<InstrumentedPointerBase> pointer) diff --git a/Source/WebCore/inspector/MemoryInstrumentationImpl.h b/Source/WebCore/inspector/MemoryInstrumentationImpl.h index 762f190a2..85cbc5e45 100644 --- a/Source/WebCore/inspector/MemoryInstrumentationImpl.h +++ b/Source/WebCore/inspector/MemoryInstrumentationImpl.h @@ -33,6 +33,7 @@ #include "MemoryInstrumentation.h" +#include <wtf/HashMap.h> #include <wtf/HashSet.h> #include <wtf/Vector.h> @@ -45,27 +46,28 @@ public: explicit MemoryInstrumentationImpl(VisitedObjects&); size_t selfSize() const; - size_t totalSize(ObjectType objectType) const + size_t totalSize(MemoryObjectType objectType) const { - ASSERT(objectType >= 0 && objectType < LastTypeEntry); - return m_totalSizes[objectType]; + TypeToSizeMap::const_iterator i = m_totalSizes.find(objectType); + return i == m_totalSizes.end() ? 0 : i->second; } size_t reportedSizeForAllTypes() const { size_t size = 0; - for (int i = 0; i < LastTypeEntry; ++i) - size += m_totalSizes[i]; + for (TypeToSizeMap::const_iterator i = m_totalSizes.begin(); i != m_totalSizes.end(); ++i) + size += i->second; return size; } private: - virtual void countObjectSize(ObjectType, size_t) OVERRIDE; + virtual void countObjectSize(MemoryObjectType, size_t) OVERRIDE; virtual void deferInstrumentedPointer(PassOwnPtr<InstrumentedPointerBase>) OVERRIDE; virtual bool visited(const void*) OVERRIDE; virtual void processDeferredInstrumentedPointers() OVERRIDE; - size_t m_totalSizes[LastTypeEntry]; + typedef HashMap<MemoryObjectType, size_t> TypeToSizeMap; + TypeToSizeMap m_totalSizes; VisitedObjects& m_visitedObjects; Vector<OwnPtr<InstrumentedPointerBase> > m_deferredInstrumentedPointers; }; diff --git a/Source/WebCore/inspector/NetworkResourcesData.cpp b/Source/WebCore/inspector/NetworkResourcesData.cpp index e05d13dec..4416adf76 100644 --- a/Source/WebCore/inspector/NetworkResourcesData.cpp +++ b/Source/WebCore/inspector/NetworkResourcesData.cpp @@ -113,7 +113,7 @@ size_t NetworkResourcesData::ResourceData::decodeDataToContent() ASSERT(!hasContent()); size_t dataLength = m_dataBuffer->size(); m_content = m_decoder->decode(m_dataBuffer->data(), m_dataBuffer->size()); - m_content += m_decoder->flush(); + m_content.append(m_decoder->flush()); m_dataBuffer = nullptr; return contentSizeInBytes(m_content) - dataLength; } diff --git a/Source/WebCore/inspector/PageRuntimeAgent.cpp b/Source/WebCore/inspector/PageRuntimeAgent.cpp index 35d56f5c9..254957a7f 100644 --- a/Source/WebCore/inspector/PageRuntimeAgent.cpp +++ b/Source/WebCore/inspector/PageRuntimeAgent.cpp @@ -160,7 +160,7 @@ void PageRuntimeAgent::notifyContextCreated(const String& frameId, ScriptState* ASSERT(securityOrigin || isPageContext); int executionContextId = injectedScriptManager()->injectedScriptIdFor(scriptState); String name = securityOrigin ? securityOrigin->toString() : ""; - m_frontend->isolatedContextCreated(ExecutionContextDescription::create() + m_frontend->executionContextCreated(ExecutionContextDescription::create() .setId(executionContextId) .setIsPageContext(isPageContext) .setName(name) diff --git a/Source/WebCore/inspector/ScriptArguments.h b/Source/WebCore/inspector/ScriptArguments.h index 26549b6d3..76c0fe71c 100644 --- a/Source/WebCore/inspector/ScriptArguments.h +++ b/Source/WebCore/inspector/ScriptArguments.h @@ -31,11 +31,11 @@ #ifndef ScriptArguments_h #define ScriptArguments_h -#include "PlatformString.h" #include "ScriptState.h" #include <wtf/Forward.h> #include <wtf/RefCounted.h> #include <wtf/Vector.h> +#include <wtf/text/WTFString.h> namespace WebCore { diff --git a/Source/WebCore/inspector/ScriptBreakpoint.h b/Source/WebCore/inspector/ScriptBreakpoint.h index 920fb3f2c..11e8d51c1 100644 --- a/Source/WebCore/inspector/ScriptBreakpoint.h +++ b/Source/WebCore/inspector/ScriptBreakpoint.h @@ -30,7 +30,7 @@ #ifndef ScriptBreakpoint_h #define ScriptBreakpoint_h -#include "PlatformString.h" +#include <wtf/text/WTFString.h> namespace WebCore { diff --git a/Source/WebCore/inspector/ScriptCallFrame.h b/Source/WebCore/inspector/ScriptCallFrame.h index e1922601a..9154104fc 100644 --- a/Source/WebCore/inspector/ScriptCallFrame.h +++ b/Source/WebCore/inspector/ScriptCallFrame.h @@ -35,8 +35,8 @@ #include "InspectorTypeBuilder.h" #endif -#include "PlatformString.h" #include <wtf/Forward.h> +#include <wtf/text/WTFString.h> namespace WebCore { diff --git a/Source/WebCore/inspector/ScriptDebugListener.h b/Source/WebCore/inspector/ScriptDebugListener.h index 72813dedc..579440149 100644 --- a/Source/WebCore/inspector/ScriptDebugListener.h +++ b/Source/WebCore/inspector/ScriptDebugListener.h @@ -32,9 +32,9 @@ #if ENABLE(JAVASCRIPT_DEBUGGER) -#include "PlatformString.h" #include "ScriptState.h" #include <wtf/Forward.h> +#include <wtf/text/WTFString.h> namespace WebCore { class ScriptValue; diff --git a/Source/WebCore/inspector/TimelineRecordFactory.cpp b/Source/WebCore/inspector/TimelineRecordFactory.cpp index e8527b60b..4af5f0257 100644 --- a/Source/WebCore/inspector/TimelineRecordFactory.cpp +++ b/Source/WebCore/inspector/TimelineRecordFactory.cpp @@ -37,6 +37,7 @@ #include "Event.h" #include "InspectorValues.h" #include "IntRect.h" +#include "LayoutTypesInlineMethods.h" #include "ResourceRequest.h" #include "ResourceResponse.h" #include "ScriptCallStack.h" diff --git a/Source/WebCore/inspector/TimelineRecordFactory.h b/Source/WebCore/inspector/TimelineRecordFactory.h index 69c104bd2..ea4064a20 100644 --- a/Source/WebCore/inspector/TimelineRecordFactory.h +++ b/Source/WebCore/inspector/TimelineRecordFactory.h @@ -32,7 +32,7 @@ #define TimelineRecordFactory_h #include "LayoutTypes.h" -#include "PlatformString.h" +#include <wtf/Forward.h> namespace WebCore { diff --git a/Source/WebCore/inspector/compile-front-end.py b/Source/WebCore/inspector/compile-front-end.py index 31eadde70..6baca120c 100755 --- a/Source/WebCore/inspector/compile-front-end.py +++ b/Source/WebCore/inspector/compile-front-end.py @@ -82,6 +82,7 @@ modules = [ "JavaScriptSource.js", "Linkifier.js", "NetworkLog.js", + "NetworkUISourceCodeProvider.js", "PresentationConsoleMessageHelper.js", "SASSSourceMapping.js", "Script.js", @@ -90,8 +91,8 @@ modules = [ "SnippetStorage.js", "SourceMapping.js", "StyleSource.js", + "StylesSourceMapping.js", "TimelineManager.js", - "RawSourceCode.js", "RemoteObject.js", "Resource.js", "ResourceScriptMapping.js", @@ -164,11 +165,14 @@ modules = [ "DOMBreakpointsSidebarPane.js", "DOMPresentationUtils.js", "ElementsTreeOutline.js", + "FontView.js", + "ImageView.js", "NativeBreakpointsSidebarPane.js", - "JavaScriptContextManager.js", "ObjectPopoverHelper.js", "ObjectPropertiesSection.js", + "RuntimeModel.js", "SourceFrame.js", + "ResourceView.js", ] }, { @@ -176,6 +180,7 @@ modules = [ "dependencies": ["components"], "sources": [ "ElementsPanel.js", + "ElementsPanelDescriptor.js", "EventListenersSidebarPane.js", "MetricsSidebarPane.js", "PropertiesSidebarPane.js", @@ -186,8 +191,6 @@ modules = [ "name": "network", "dependencies": ["components"], "sources": [ - "FontView.js", - "ImageView.js", "NetworkItemView.js", "RequestCookiesView.js", "RequestHeadersView.js", @@ -197,7 +200,6 @@ modules = [ "RequestResponseView.js", "RequestTimingView.js", "RequestView.js", - "ResourceView.js", "ResourceWebSocketFrameView.js", "NetworkPanel.js", "NetworkPanelDescriptor.js", @@ -328,6 +330,7 @@ modules = [ "ProfilesPanel.js", "ProfileLauncherView.js", "TopDownProfileDataGridTree.js", + "WebGLProfileView.js", ] }, { @@ -370,11 +373,13 @@ def dump_module(name, recursively, processed_modules): modules_dir = tempfile.mkdtemp() compiler_command = "java -jar ~/closure/compiler.jar --summary_detail_level 3 --compilation_level SIMPLE_OPTIMIZATIONS --warning_level VERBOSE --language_in ECMASCRIPT5 --accept_const_keyword --module_output_path_prefix %s/ \\\n" % modules_dir -process_recursively = len(sys.argv) == 2 +process_recursively = len(sys.argv) > 1 if process_recursively: module_name = sys.argv[1] if module_name != "all": - modules = [modules_by_name[sys.argv[1]]] + modules = [] + for i in range(1, len(sys.argv)): + modules.append(modules_by_name[sys.argv[i]]) for module in modules: command = compiler_command command += " --externs " + inspector_frontend_path + "/externs.js" diff --git a/Source/WebCore/inspector/front-end/AdvancedSearchController.js b/Source/WebCore/inspector/front-end/AdvancedSearchController.js index be51bd764..b500a663b 100644 --- a/Source/WebCore/inspector/front-end/AdvancedSearchController.js +++ b/Source/WebCore/inspector/front-end/AdvancedSearchController.js @@ -500,7 +500,7 @@ WebInspector.FileBasedSearchResultsPane.prototype = { { var anchor = document.createElement("a"); anchor.preferredPanel = "scripts"; - anchor.href = uiSourceCode.url; + anchor.href = sanitizeHref(uiSourceCode.url); anchor.uiSourceCode = uiSourceCode; anchor.lineNumber = lineNumber; return anchor; diff --git a/Source/WebCore/inspector/front-end/AuditFormatters.js b/Source/WebCore/inspector/front-end/AuditFormatters.js index 33c41e8d1..efb04854d 100644 --- a/Source/WebCore/inspector/front-end/AuditFormatters.js +++ b/Source/WebCore/inspector/front-end/AuditFormatters.js @@ -60,7 +60,7 @@ WebInspector.AuditFormatters.Registry = { url: function(url, displayText, allowExternalNavigation) { var a = document.createElement("a"); - a.href = url; + a.href = sanitizeHref(url); a.title = url; a.textContent = displayText || url; if (allowExternalNavigation) diff --git a/Source/WebCore/inspector/front-end/AuditResultView.js b/Source/WebCore/inspector/front-end/AuditResultView.js index 57f57ad85..4cfc43168 100644 --- a/Source/WebCore/inspector/front-end/AuditResultView.js +++ b/Source/WebCore/inspector/front-end/AuditResultView.js @@ -43,17 +43,9 @@ WebInspector.AuditResultView = function(categoryResults) 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; diff --git a/Source/WebCore/inspector/front-end/BreakpointManager.js b/Source/WebCore/inspector/front-end/BreakpointManager.js index 88b63573e..8e9d4b655 100644 --- a/Source/WebCore/inspector/front-end/BreakpointManager.js +++ b/Source/WebCore/inspector/front-end/BreakpointManager.js @@ -47,7 +47,7 @@ WebInspector.BreakpointManager = function(breakpointStorage, debuggerModel, work this._sourceFilesWithRestoredBreakpoints = {}; this._debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointResolved, this._breakpointResolved, this); - this._workspace.addEventListener(WebInspector.Workspace.Events.WorkspaceReset, this._workspaceReset, this); + this._workspace.addEventListener(WebInspector.Workspace.Events.ProjectWillReset, this._workspaceReset, this); this._workspace.addEventListener(WebInspector.UISourceCodeProvider.Events.UISourceCodeAdded, this._uiSourceCodeAdded, this); } diff --git a/Source/WebCore/inspector/front-end/CSSCompletions.js b/Source/WebCore/inspector/front-end/CSSCompletions.js index 84d7cae0b..9e3798535 100644 --- a/Source/WebCore/inspector/front-end/CSSCompletions.js +++ b/Source/WebCore/inspector/front-end/CSSCompletions.js @@ -83,6 +83,13 @@ WebInspector.CSSCompletions.requestCSSNameCompletions = function() CSSAgent.getSupportedCSSProperties(propertyNamesCallback); } +WebInspector.CSSCompletions.cssPropertiesMetainfoKeySet = function() +{ + if (!WebInspector.CSSCompletions._cssPropertiesMetainfoKeySet) + WebInspector.CSSCompletions._cssPropertiesMetainfoKeySet = WebInspector.CSSCompletions.cssPropertiesMetainfo.keySet(); + return WebInspector.CSSCompletions._cssPropertiesMetainfoKeySet; +} + WebInspector.CSSCompletions.prototype = { startsWith: function(prefix) { diff --git a/Source/WebCore/inspector/front-end/CompilerScriptMapping.js b/Source/WebCore/inspector/front-end/CompilerScriptMapping.js index 4d362d0e5..0ffdc28c1 100644 --- a/Source/WebCore/inspector/front-end/CompilerScriptMapping.js +++ b/Source/WebCore/inspector/front-end/CompilerScriptMapping.js @@ -30,17 +30,20 @@ /** * @constructor - * @extends {WebInspector.Object} * @implements {WebInspector.SourceMapping} - * @implements {WebInspector.UISourceCodeProvider} + * @param {WebInspector.Workspace} workspace */ -WebInspector.CompilerScriptMapping = function() +WebInspector.CompilerScriptMapping = function(workspace) { + this._workspace = workspace; this._sourceMapByURL = {}; this._sourceMapForScriptId = {}; this._scriptForSourceMap = new Map(); this._sourceMapForUISourceCode = new Map(); this._uiSourceCodeByURL = {}; + this._originalUISourceCodeForScriptId = {}; + this._scriptForOriginalUISource = new Map(); + this._workspace.addEventListener(WebInspector.Workspace.Events.ProjectWillReset, this._reset, this); } WebInspector.CompilerScriptMapping.prototype = { @@ -52,7 +55,11 @@ WebInspector.CompilerScriptMapping.prototype = { { var debuggerModelLocation = /** @type {WebInspector.DebuggerModel.Location} */ rawLocation; var sourceMap = this._sourceMapForScriptId[debuggerModelLocation.scriptId]; - var entry = sourceMap.findEntry(debuggerModelLocation.lineNumber, debuggerModelLocation.columnNumber || 0); + var lineNumber = debuggerModelLocation.lineNumber; + var columnNumber = debuggerModelLocation.columnNumber || 0; + var entry = sourceMap.findEntry(lineNumber, columnNumber); + if (entry.length === 2) + return new WebInspector.UILocation(this._originalUISourceCodeForScriptId[debuggerModelLocation.scriptId], lineNumber, columnNumber); return new WebInspector.UILocation(this._uiSourceCodeByURL[entry[2]], entry[3], entry[4]); }, @@ -64,45 +71,28 @@ WebInspector.CompilerScriptMapping.prototype = { */ uiLocationToRawLocation: function(uiSourceCode, lineNumber, columnNumber) { + var script = this._scriptForOriginalUISource.get(uiSourceCode); + if (script) + return WebInspector.debuggerModel.createRawLocation(script, lineNumber, columnNumber); var sourceMap = this._sourceMapForUISourceCode.get(uiSourceCode); var entry = sourceMap.findEntryReversed(uiSourceCode.url, lineNumber); return WebInspector.debuggerModel.createRawLocation(this._scriptForSourceMap.get(sourceMap), entry[0], entry[1]); }, /** - * @return {Array.<WebInspector.UISourceCode>} - */ - uiSourceCodes: function() - { - var result = []; - for (var url in this._uiSourceCodeByURL) - result.push(this._uiSourceCodeByURL[url]); - return result; - }, - - /** - * @param {WebInspector.SourceMapParser} sourceMap - * @return {Array.<WebInspector.UISourceCode>} - */ - _uiSourceCodesForSourceMap: function(sourceMap) - { - var result = [] - var sourceURLs = sourceMap.sources(); - for (var i = 0; i < sourceURLs.length; ++i) - result.push(this._uiSourceCodeByURL[sourceURLs[i]]); - return result; - }, - - /** * @param {WebInspector.Script} script */ addScript: function(script) { + var originalUISourceCode = new WebInspector.JavaScriptSource(script.sourceURL, null, script, this, true); + this._originalUISourceCodeForScriptId[script.scriptId] = originalUISourceCode; + this._scriptForOriginalUISource.put(originalUISourceCode, script); + this._workspace.project().addUISourceCode(originalUISourceCode); + var sourceMap = this.loadSourceMapForScript(script); if (this._scriptForSourceMap.get(sourceMap)) { this._sourceMapForScriptId[script.scriptId] = sourceMap; - var uiSourceCodes = this._uiSourceCodesForSourceMap(sourceMap); script.setSourceMapping(this); return; } @@ -119,7 +109,8 @@ WebInspector.CompilerScriptMapping.prototype = { contentProvider = new WebInspector.StaticContentProvider(WebInspector.resourceTypes.Script, sourceContent); else contentProvider = new WebInspector.CompilerSourceMappingContentProvider(sourceURL); - var uiSourceCode = new WebInspector.JavaScriptSource(sourceURL, null, contentProvider, this, false); + var uiSourceCode = new WebInspector.JavaScriptSource(sourceURL, null, contentProvider, false); + uiSourceCode.setSourceMapping(this); uiSourceCode.isContentScript = script.isContentScript; this._uiSourceCodeByURL[sourceURL] = uiSourceCode; this._sourceMapForUISourceCode.put(uiSourceCode, sourceMap); @@ -131,7 +122,7 @@ WebInspector.CompilerScriptMapping.prototype = { script.setSourceMapping(this); for (var i = 0; i < uiSourceCodeList.length; ++i) - this.dispatchEventToListeners(WebInspector.UISourceCodeProvider.Events.UISourceCodeAdded, uiSourceCodeList[i]); + this._workspace.project().addUISourceCode(uiSourceCodeList[i]); }, /** @@ -160,18 +151,18 @@ WebInspector.CompilerScriptMapping.prototype = { return sourceMap; }, - reset: function() + _reset: function() { this._sourceMapByURL = {}; this._sourceMapForScriptId = {}; this._scriptForSourceMap = new Map(); this._sourceMapForUISourceCode = new Map(); this._uiSourceCodeByURL = {}; + this._originalUISourceCodeForScriptId = {}; + this._scriptForOriginalUISource = new Map(); } } -WebInspector.CompilerScriptMapping.prototype.__proto__ = WebInspector.Object.prototype; - /** * @constructor */ @@ -314,22 +305,25 @@ WebInspector.SourceMapParser.prototype = { } 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]; + if (this._isSeparator(stringCharIterator.peek())) { + this._mappings.push([lineNumber, columnNumber]); + continue; + } + + 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]; } }, diff --git a/Source/WebCore/inspector/front-end/ConsoleMessage.js b/Source/WebCore/inspector/front-end/ConsoleMessage.js index 95e217b80..f290a6bad 100644 --- a/Source/WebCore/inspector/front-end/ConsoleMessage.js +++ b/Source/WebCore/inspector/front-end/ConsoleMessage.js @@ -715,7 +715,7 @@ WebInspector.ConsoleMessageImpl.prototype = { */ 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._requestId, this._isOutdated); + return WebInspector.ConsoleMessage.create(this.source, this.level, this._messageText, this.type, this.url, this.line, this.repeatCount, this._parameters, this._stackTrace, this._request ? this._request.requestId : undefined, this._isOutdated); } } diff --git a/Source/WebCore/inspector/front-end/ConsoleView.js b/Source/WebCore/inspector/front-end/ConsoleView.js index 70ef8e4f6..04011165a 100644 --- a/Source/WebCore/inspector/front-end/ConsoleView.js +++ b/Source/WebCore/inspector/front-end/ConsoleView.js @@ -44,12 +44,12 @@ WebInspector.ConsoleView = function(hideContextSelector) this._clearConsoleButton = new WebInspector.StatusBarButton(WebInspector.UIString("Clear console log."), "clear-status-bar-item"); this._clearConsoleButton.addEventListener("click", this._requestClearMessages, this); - this._contextSelector = new WebInspector.StatusBarComboBox(this._updateIsolatedWorldSelector.bind(this), "console-context"); - this._isolatedWorldSelector = new WebInspector.StatusBarComboBox(null, "console-context"); + this._frameSelector = new WebInspector.StatusBarComboBox(this._frameChanged.bind(this), "console-context"); + this._contextSelector = new WebInspector.StatusBarComboBox(this._contextChanged.bind(this), "console-context"); if (hideContextSelector) { + this._frameSelector.element.addStyleClass("hidden"); this._contextSelector.element.addStyleClass("hidden"); - this._isolatedWorldSelector.element.addStyleClass("hidden"); } this.messagesElement = document.createElement("div"); @@ -73,14 +73,17 @@ WebInspector.ConsoleView = function(hideContextSelector) this._filterBarElement = document.createElement("div"); this._filterBarElement.className = "scope-bar status-bar-item"; - function createDividerElement() { + 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) { + + function createFilterElement(category, label) + { var categoryElement = document.createElement("li"); categoryElement.category = category; categoryElement.className = category; @@ -117,6 +120,10 @@ WebInspector.ConsoleView = function(hideContextSelector) this.prompt.attach(this.promptElement); this.prompt.proxyElement.addEventListener("keydown", this._promptKeyDown.bind(this), false); this.prompt.setHistoryData(WebInspector.settings.consoleHistory.get()); + + WebInspector.runtimeModel.contextLists().forEach(this._addFrame, this); + WebInspector.runtimeModel.addEventListener(WebInspector.RuntimeModel.Events.FrameExecutionContextListAdded, this._frameAdded, this); + WebInspector.runtimeModel.addEventListener(WebInspector.RuntimeModel.Events.FrameExecutionContextListRemoved, this._frameRemoved, this); } WebInspector.ConsoleView.Events = { @@ -127,101 +134,118 @@ WebInspector.ConsoleView.Events = { WebInspector.ConsoleView.prototype = { get statusBarItems() { - return [this._clearConsoleButton.element, this._contextSelector.element, this._isolatedWorldSelector.element, this._filterBarElement]; + return [this._clearConsoleButton.element, this._frameSelector.element, this._contextSelector.element, this._filterBarElement]; }, - addContext: function(context) + /** + * @param {WebInspector.Event} event + */ + _frameAdded: function(event) + { + var contextList = /** @type {WebInspector.FrameExecutionContextList} */ event.data; + this._addFrame(contextList); + }, + + /** + * @param {WebInspector.FrameExecutionContextList} contextList + */ + _addFrame: function(contextList) { var option = document.createElement("option"); - option.text = context.displayName; - option.title = context.url; - option._context = context; - context._consoleOption = option; - this._contextSelector.addOption(option); - context.addEventListener(WebInspector.FrameEvaluationContext.EventTypes.Updated, this._contextUpdated, this); - context.addEventListener(WebInspector.FrameEvaluationContext.EventTypes.AddedExecutionContext, this._addedExecutionContext, this); - this._updateIsolatedWorldSelector(); + option.text = contextList.displayName; + option.title = contextList.url; + option._contextList = contextList; + contextList._consoleOption = option; + this._frameSelector.addOption(option); + contextList.addEventListener(WebInspector.FrameExecutionContextList.EventTypes.ContextsUpdated, this._frameUpdated, this); + contextList.addEventListener(WebInspector.FrameExecutionContextList.EventTypes.ContextAdded, this._contextAdded, this); + this._frameChanged(); }, - removeContext: function(context) + /** + * @param {WebInspector.Event} event + */ + _frameRemoved: function(event) { - this._contextSelector.removeOption(context._consoleOption); - this._updateIsolatedWorldSelector(); + var contextList = /** @type {WebInspector.FrameExecutionContextList} */ event.data; + this._frameSelector.removeOption(contextList._consoleOption); + this._frameChanged(); }, - _updateIsolatedWorldSelector: function() + _frameChanged: function() { - var context = this._currentEvaluationContext(); + var context = this._currentFrame(); if (!context) { - this._isolatedWorldSelector.element.addStyleClass("hidden"); + delete this._currentExecutionContext; + this._contextSelector.element.addStyleClass("hidden"); return; } - var isolatedContexts = context.isolatedContexts(); - if (!isolatedContexts.length) { - this._isolatedWorldSelector.element.addStyleClass("hidden"); + var executionContexts = context.executionContexts(); + if (executionContexts.length) + this._currentExecutionContext = executionContexts[0]; + + if (executionContexts.length === 1) { + this._contextSelector.element.addStyleClass("hidden"); return; } - this._isolatedWorldSelector.element.removeStyleClass("hidden"); - this._isolatedWorldSelector.removeOptions(); - this._appendIsolatedContextOption(context.mainWorldContext()); - for (var i = 0; i < isolatedContexts.length; i++) - this._appendIsolatedContextOption(isolatedContexts[i]); + this._contextSelector.element.removeStyleClass("hidden"); + this._contextSelector.removeOptions(); + for (var i = 0; i < executionContexts.length; i++) + this._appendContextOption(executionContexts[i]); }, - _appendIsolatedContextOption: function(isolatedContext) + /** + * @param {WebInspector.ExecutionContext} executionContext + */ + _appendContextOption: function(executionContext) { - if (!isolatedContext) - return; + if (!this._currentExecutionContext) + this._currentExecutionContext = executionContext; var option = document.createElement("option"); - option.text = isolatedContext.name; - option.title = isolatedContext.id; - option._executionContextId = isolatedContext.id; - this._isolatedWorldSelector.addOption(option); - }, - - _contextUpdated: function(event) - { - var context = event.data; - var option = context._consoleOption; - option.text = context.displayName; - option.title = context.url; + option.text = executionContext.name; + option.title = executionContext.id; + option._executionContext = executionContext; + this._contextSelector.addOption(option); }, - _addedExecutionContext: function(event) + /** + * @param {Event} event + */ + _contextChanged: function(event) { - var context = event.data; - if (context === this._currentEvaluationContext()) - this._updateIsolatedWorldSelector(); + var option = this._contextSelector.selectedOption(); + this._currentExecutionContext = option ? option._executionContext : undefined; }, - _currentEvaluationContextId: function() + /** + * @param {WebInspector.Event} event + */ + _frameUpdated: function(event) { - var result = this._currentIsolatedContextId(); - if (result !== undefined) - return result; - var context = this._currentEvaluationContext(); - if (context && context.mainWorldContext()) - return context.mainWorldContext().id; - return undefined; + var contextList = /** {WebInspector.FrameExecutionContextList */ event.data; + var option = contextList._consoleOption; + option.text = contextList.displayName; + option.title = contextList.url; }, - _currentEvaluationContext: function() + /** + * @param {WebInspector.Event} event + */ + _contextAdded: function(event) { - var option = this._contextSelector.selectedOption(); - if (!option) - return undefined; - return option._context; + var contextList = /** {WebInspector.FrameExecutionContextList */ event.data; + if (contextList === this._currentFrame()) + this._frameChanged(); }, - _currentIsolatedContextId: function() + /** + * @return {WebInspector.FrameExecutionContextList|undefined} + */ + _currentFrame: function() { - if (this._isolatedWorldSelector.element.hasStyleClass("hidden")) - return undefined; - var option = this._isolatedWorldSelector.selectedOption(); - if (!option) - return undefined; - return option._executionContextId; + var option = this._frameSelector.selectedOption(); + return option ? option._contextList : undefined; }, _updateFilter: function(e) @@ -361,6 +385,9 @@ WebInspector.ConsoleView.prototype = { delete this._scrollIntoViewTimer; }, + /** + * @param {WebInspector.Event} event + */ _consoleMessageAdded: function(event) { this._appendConsoleMessage(event.data); @@ -550,10 +577,10 @@ WebInspector.ConsoleView.prototype = { return; } - var contextMenu = new WebInspector.ContextMenu(); + if (event.target.enclosingNodeOrSelfWithNodeName("a")) + return; - if (WebInspector.populateHrefContextMenu(contextMenu, null, event)) - contextMenu.appendSeparator(); + var contextMenu = new WebInspector.ContextMenu(); function monitoringXHRItemAction() { @@ -683,8 +710,7 @@ WebInspector.ConsoleView.prototype = { else callback(WebInspector.RemoteObject.fromPayload(result), !!wasThrown); } - var contextId = this._currentEvaluationContextId(); - RuntimeAgent.evaluate(expression, objectGroup, includeCommandLineAPI, doNotPauseOnExceptionsAndMuteConsole, contextId, returnByValue, evalCallback); + RuntimeAgent.evaluate(expression, objectGroup, includeCommandLineAPI, doNotPauseOnExceptionsAndMuteConsole, this._currentExecutionContext ? this._currentExecutionContext.id : undefined, returnByValue, evalCallback); }, evaluateUsingTextPrompt: function(expression, showResultOnly) @@ -709,8 +735,7 @@ WebInspector.ConsoleView.prototype = { runScript: function(scriptId) { - var contextId = WebInspector.consoleView._currentEvaluationContextId(); - DebuggerAgent.runScript(scriptId, contextId, "console", false, runCallback.bind(this)); + DebuggerAgent.runScript(scriptId, this._currentExecutionContext ? this._currentExecutionContext.id : undefined, "console", false, runCallback.bind(this)); WebInspector.userMetrics.ConsoleEvaluated.record(); /** diff --git a/Source/WebCore/inspector/front-end/ContentProviders.js b/Source/WebCore/inspector/front-end/ContentProviders.js index e1c3996f3..9c19953dd 100644 --- a/Source/WebCore/inspector/front-end/ContentProviders.js +++ b/Source/WebCore/inspector/front-end/ContentProviders.js @@ -241,12 +241,14 @@ WebInspector.CompilerSourceMappingContentProvider.prototype.__proto__ = WebInspe * @constructor * @implements {WebInspector.ContentProvider} * @param {WebInspector.ResourceType} contentType - * @param {string} content + * @param {string} content + * @param {string=} mimeType */ -WebInspector.StaticContentProvider = function(contentType, content) +WebInspector.StaticContentProvider = function(contentType, content, mimeType) { this._content = content; this._contentType = contentType; + this._mimeType = mimeType; } WebInspector.StaticContentProvider.prototype = { @@ -271,7 +273,7 @@ WebInspector.StaticContentProvider.prototype = { */ requestContent: function(callback) { - callback(this._content, false, this._contentType.canonicalMimeType()); + callback(this._content, false, this._mimeType || this._contentType.canonicalMimeType()); }, /** diff --git a/Source/WebCore/inspector/front-end/DOMAgent.js b/Source/WebCore/inspector/front-end/DOMAgent.js index 45f201c1d..2f451f565 100644 --- a/Source/WebCore/inspector/front-end/DOMAgent.js +++ b/Source/WebCore/inspector/front-end/DOMAgent.js @@ -736,6 +736,21 @@ WebInspector.DOMNode.prototype = { descendantUserPropertyCount: function(name) { return this._descendantUserPropertyCounters && this._descendantUserPropertyCounters[name] ? this._descendantUserPropertyCounters[name] : 0; + }, + + /** + * @param {string} url + * @return {?string} + */ + resolveURL: function(url) + { + if (!url) + return url; + for (var frameOwnerCandidate = this; frameOwnerCandidate; frameOwnerCandidate = frameOwnerCandidate.parentNode) { + if (frameOwnerCandidate.documentURL) + return WebInspector.ParsedURL.completeURL(frameOwnerCandidate.documentURL, url); + } + return null; } } diff --git a/Source/WebCore/inspector/front-end/DOMPresentationUtils.js b/Source/WebCore/inspector/front-end/DOMPresentationUtils.js index 150fc5f74..905b78f9f 100644 --- a/Source/WebCore/inspector/front-end/DOMPresentationUtils.js +++ b/Source/WebCore/inspector/front-end/DOMPresentationUtils.js @@ -96,3 +96,51 @@ WebInspector.DOMPresentationUtils.linkifyNodeById = function(nodeId) return document.createTextNode(WebInspector.UIString("<node>")); return WebInspector.DOMPresentationUtils.linkifyNodeReference(node); } + +/** + * @param {string} imageURL + * @param {boolean} showDimensions + * @param {function(Element=)} userCallback + * @param {Object=} precomputedDimensions + */ +WebInspector.DOMPresentationUtils.buildImagePreviewContents = function(imageURL, showDimensions, userCallback, precomputedDimensions) +{ + var resource = WebInspector.resourceTreeModel.resourceForURL(imageURL); + if (!resource) { + userCallback(); + return; + } + + var imageElement = document.createElement("img"); + imageElement.addEventListener("load", buildContent, false); + imageElement.addEventListener("error", errorCallback, false); + resource.populateImageSource(imageElement); + + function errorCallback() + { + // Drop the event parameter when invoking userCallback. + userCallback(); + } + + function buildContent() + { + var container = document.createElement("table"); + container.className = "image-preview-container"; + var naturalWidth = precomputedDimensions ? precomputedDimensions.naturalWidth : imageElement.naturalWidth; + var naturalHeight = precomputedDimensions ? precomputedDimensions.naturalHeight : imageElement.naturalHeight; + var offsetWidth = precomputedDimensions ? precomputedDimensions.offsetWidth : naturalWidth; + var offsetHeight = precomputedDimensions ? precomputedDimensions.offsetHeight : naturalHeight; + var description; + if (showDimensions) { + if (offsetHeight === naturalHeight && offsetWidth === naturalWidth) + description = WebInspector.UIString("%d \xd7 %d pixels", offsetWidth, offsetHeight); + else + description = WebInspector.UIString("%d \xd7 %d pixels (Natural: %d \xd7 %d pixels)", offsetWidth, offsetHeight, naturalWidth, naturalHeight); + } + + container.createChild("tr").createChild("td", "image-container").appendChild(imageElement); + if (description) + container.createChild("tr").createChild("td").createChild("span", "description").textContent = description; + userCallback(container); + } +} diff --git a/Source/WebCore/inspector/front-end/Database.js b/Source/WebCore/inspector/front-end/Database.js index 72389c5ab..caaedb587 100644 --- a/Source/WebCore/inspector/front-end/Database.js +++ b/Source/WebCore/inspector/front-end/Database.js @@ -79,12 +79,6 @@ WebInspector.Database.prototype = { this._domain = x; }, - /** @return {string} */ - get displayDomain() - { - return WebInspector.displayDomain(this._domain); - }, - /** * @param {function(Array.<string>)} callback */ @@ -100,22 +94,35 @@ WebInspector.Database.prototype = { /** * @param {string} query - * @param {function(Array.<string>, Array.<*>)} onSuccess - * @param {function(DatabaseAgent.Error)} onError + * @param {function(Array.<string>=, Array.<*>=)} onSuccess + * @param {function(string)} onError */ executeSql: function(query, onSuccess, onError) { - function callback(error, success, transactionId) + /** + * @param {?Protocol.Error} error + * @param {Array.<string>=} columnNames + * @param {Array.<*>=} values + * @param {DatabaseAgent.Error=} errorObj + */ + function callback(error, columnNames, values, errorObj) { if (error) { onError(error); return; } - if (!success) { - onError(WebInspector.UIString("Database not found.")); + if (errorObj) { + var message; + if (errorObj.message) + message = errorObj.message; + else if (errorObj.code == 2) + message = WebInspector.UIString("Database no longer has expected version."); + else + message = WebInspector.UIString("An unexpected error %s occurred.", errorObj.code); + onError(message); return; } - this._model._callbacks[transactionId] = {"onSuccess": onSuccess, "onError": onError}; + onSuccess(columnNames, values); } DatabaseAgent.executeSQL(this._id, query, callback.bind(this)); } @@ -127,7 +134,6 @@ WebInspector.Database.prototype = { */ WebInspector.DatabaseModel = function() { - this._callbacks = {}; this._databases = []; InspectorBackend.registerDatabaseDispatcher(new WebInspector.DatabaseDispatcher(this)); DatabaseAgent.enable(); @@ -165,37 +171,6 @@ WebInspector.DatabaseModel.prototype = { { this._databases.push(database); this.dispatchEventToListeners(WebInspector.DatabaseModel.Events.DatabaseAdded, database); - }, - - /** - * @param {number} transactionId - * @param {Array.<string>} columnNames - * @param {Array.<*>} values - */ - _sqlTransactionSucceeded: function(transactionId, columnNames, values) - { - if (!this._callbacks[transactionId]) - return; - - var callback = this._callbacks[transactionId]["onSuccess"]; - delete this._callbacks[transactionId]; - if (callback) - callback(columnNames, values); - }, - - /** - * @param {number} transactionId - * @param {?DatabaseAgent.Error} errorObj - */ - _sqlTransactionFailed: function(transactionId, errorObj) - { - if (!this._callbacks[transactionId]) - return; - - var callback = this._callbacks[transactionId]["onError"]; - delete this._callbacks[transactionId]; - if (callback) - callback(errorObj); } } @@ -211,8 +186,6 @@ WebInspector.DatabaseDispatcher = function(model) this._model = model; } -WebInspector.DatabaseDispatcher._callbacks = {}; - WebInspector.DatabaseDispatcher.prototype = { /** * @param {DatabaseAgent.Database} payload @@ -225,25 +198,6 @@ WebInspector.DatabaseDispatcher.prototype = { payload.domain, payload.name, payload.version)); - }, - - /** - * @param {number} transactionId - * @param {Array.<string>} columnNames - * @param {Array.<*>} values - */ - sqlTransactionSucceeded: function(transactionId, columnNames, values) - { - this._model._sqlTransactionSucceeded(transactionId, columnNames, values); - }, - - /** - * @param {number} transactionId - * @param {?DatabaseAgent.Error} errorObj - */ - sqlTransactionFailed: function(transactionId, errorObj) - { - this._model._sqlTransactionFailed(transactionId, errorObj); } } diff --git a/Source/WebCore/inspector/front-end/DatabaseQueryView.js b/Source/WebCore/inspector/front-end/DatabaseQueryView.js index 38df46a22..db06c1cb2 100644 --- a/Source/WebCore/inspector/front-end/DatabaseQueryView.js +++ b/Source/WebCore/inspector/front-end/DatabaseQueryView.js @@ -148,18 +148,9 @@ WebInspector.DatabaseQueryView.prototype = { this.dispatchEventToListeners(WebInspector.DatabaseQueryView.Events.SchemaUpdated, this.database); }, - _queryError: function(query, error) + _queryError: function(query, errorMessage) { - if (typeof error === "string") - var message = error; - else 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); + this._appendErrorQueryResult(query, errorMessage); }, /** diff --git a/Source/WebCore/inspector/front-end/DebuggerModel.js b/Source/WebCore/inspector/front-end/DebuggerModel.js index e8e2d4b4f..328c54e8f 100644 --- a/Source/WebCore/inspector/front-end/DebuggerModel.js +++ b/Source/WebCore/inspector/front-end/DebuggerModel.js @@ -94,7 +94,8 @@ WebInspector.DebuggerModel.BreakReason = { DOM: "DOM", EventListener: "EventListener", XHR: "XHR", - Exception: "exception" + Exception: "exception", + Assert: "assert" } WebInspector.DebuggerModel.prototype = { @@ -394,19 +395,6 @@ WebInspector.DebuggerModel.prototype = { }, /** - * @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); - }, - - /** * @param {WebInspector.Script} script * @param {number} lineNumber * @param {number} columnNumber @@ -663,7 +651,6 @@ WebInspector.DebuggerDispatcher.prototype = { */ scriptFailedToParse: function(sourceURL, source, startingLine, errorLine, errorMessage) { - this._debuggerModel._failedToParseScriptSource(sourceURL, source, startingLine, errorLine, errorMessage); }, /** diff --git a/Source/WebCore/inspector/front-end/DebuggerScriptMapping.js b/Source/WebCore/inspector/front-end/DebuggerScriptMapping.js index 9c5034a49..12ce92801 100644 --- a/Source/WebCore/inspector/front-end/DebuggerScriptMapping.js +++ b/Source/WebCore/inspector/front-end/DebuggerScriptMapping.js @@ -31,13 +31,13 @@ /** * @constructor */ -WebInspector.DebuggerScriptMapping = function() +WebInspector.DebuggerScriptMapping = function(workspace) { this._mappings = []; - this._resourceMapping = new WebInspector.ResourceScriptMapping(); + this._resourceMapping = new WebInspector.ResourceScriptMapping(workspace); this._mappings.push(this._resourceMapping); - this._compilerMapping = new WebInspector.CompilerScriptMapping(); + this._compilerMapping = new WebInspector.CompilerScriptMapping(workspace); this._mappings.push(this._compilerMapping); this._snippetMapping = WebInspector.scriptSnippetModel.scriptMapping; this._mappings.push(this._snippetMapping); @@ -48,14 +48,6 @@ WebInspector.DebuggerScriptMapping = function() WebInspector.DebuggerScriptMapping.prototype = { /** - * @return {Array.<WebInspector.UISourceCodeProvider>} - */ - uiSourceCodeProviders: function() - { - return this._mappings; - }, - - /** * @param {WebInspector.Event} event */ _parsedScriptSource: function(event) diff --git a/Source/WebCore/inspector/front-end/DefaultTextEditor.js b/Source/WebCore/inspector/front-end/DefaultTextEditor.js index 0b56980d1..3a45c6a77 100644 --- a/Source/WebCore/inspector/front-end/DefaultTextEditor.js +++ b/Source/WebCore/inspector/front-end/DefaultTextEditor.js @@ -55,7 +55,7 @@ WebInspector.DefaultTextEditor = function(url, delegate) 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._mainPanel = new WebInspector.TextEditorMainPanel(this._delegate, this._textModel, url, syncScrollListener, syncDecorationsForLineListener, enterTextChangeMode, exitTextChangeMode); this._gutterPanel = new WebInspector.TextEditorGutterPanel(this._textModel, syncDecorationsForLineListener, syncLineHeightListener); this._mainPanel.element.addEventListener("scroll", this._handleScrollChanged.bind(this), false); @@ -413,6 +413,9 @@ WebInspector.DefaultTextEditor.prototype = { _contextMenu: function(event) { + var anchor = event.target.enclosingNodeOrSelfWithNodeName("a"); + if (anchor) + return; var contextMenu = new WebInspector.ContextMenu(); var target = event.target.enclosingNodeOrSelfWithClass("webkit-line-number"); if (target) @@ -1208,13 +1211,15 @@ WebInspector.TextEditorGutterChunk.prototype = { /** * @constructor * @extends {WebInspector.TextEditorChunkedPanel} + * @param {WebInspector.TextEditorDelegate} delegate * @param {WebInspector.TextEditorModel} textModel * @param {?string} url */ -WebInspector.TextEditorMainPanel = function(textModel, url, syncScrollListener, syncDecorationsForLineListener, enterTextChangeMode, exitTextChangeMode) +WebInspector.TextEditorMainPanel = function(delegate, textModel, url, syncScrollListener, syncDecorationsForLineListener, enterTextChangeMode, exitTextChangeMode) { WebInspector.TextEditorChunkedPanel.call(this, textModel); + this._delegate = delegate; this._syncScrollListener = syncScrollListener; this._syncDecorationsForLineListener = syncDecorationsForLineListener; this._enterTextChangeMode = enterTextChangeMode; @@ -2091,28 +2096,16 @@ WebInspector.TextEditorMainPanel.prototype = { 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); + span.appendChild(this._delegate.createLink(content, isExternal)); if (quote) span.appendChild(document.createTextNode(quote)); return span; }, - /** - * @param {string=} hrefValue - * @param {boolean=} isExternal - */ - _rewriteHref: function(hrefValue, isExternal) - { - if (!this._url || !hrefValue || hrefValue.indexOf("://") > 0) - return hrefValue; - return WebInspector.ParsedURL.completeURL(this._url, hrefValue); - }, - _handleDOMUpdates: function(e) { if (this._domUpdateCoalescingLevel) diff --git a/Source/WebCore/inspector/front-end/ElementsPanel.js b/Source/WebCore/inspector/front-end/ElementsPanel.js index cdc8f535c..2a4ff973c 100644 --- a/Source/WebCore/inspector/front-end/ElementsPanel.js +++ b/Source/WebCore/inspector/front-end/ElementsPanel.js @@ -336,8 +336,7 @@ WebInspector.ElementsPanel.prototype = { var contextMenu = new WebInspector.ContextMenu(); var populated = this.treeOutline.populateContextMenu(contextMenu, event); - if (populated) - contextMenu.appendSeparator(); + contextMenu.appendSeparator(); contextMenu.appendCheckboxItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Word wrap" : "Word Wrap"), toggleWordWrap.bind(this), WebInspector.settings.domWordWrap.get()); contextMenu.show(event); @@ -433,9 +432,9 @@ WebInspector.ElementsPanel.prototype = { { var listItem = anchor.enclosingNodeOrSelfWithNodeName("li"); if (listItem && listItem.treeElement) - this._loadDimensionsForNode(listItem.treeElement, WebInspector.buildImagePreviewContents.bind(WebInspector, anchor.href, true, showPopover)); + this._loadDimensionsForNode(listItem.treeElement, WebInspector.DOMPresentationUtils.buildImagePreviewContents.bind(WebInspector.DOMPresentationUtils, anchor.href, true, showPopover)); else - WebInspector.buildImagePreviewContents(anchor.href, true, showPopover); + WebInspector.DOMPresentationUtils.buildImagePreviewContents(anchor.href, true, showPopover); /** * @param {Element=} contents @@ -1077,6 +1076,32 @@ WebInspector.ElementsPanel.prototype = { WebInspector.domAgent.highlightDOMNodeForTwoSeconds(nodeId); this.selectDOMNode(node, true); + }, + + /** + * @param {WebInspector.ContextMenu} contextMenu + * @param {Object} target + */ + appendApplicableItems: function(contextMenu, target) + { + if (!(target instanceof WebInspector.RemoteObject)) + return; + var remoteObject = /** @type {WebInspector.RemoteObject} */ target; + if (remoteObject.subtype !== "node") + return; + + function selectNode(nodeId) + { + if (nodeId) + WebInspector.domAgent.inspectElement(nodeId); + } + + function revealElement() + { + remoteObject.pushNodeToFrontend(selectNode); + } + + contextMenu.appendItem(WebInspector.UIString("Reveal in Elements Panel"), revealElement.bind(this)); } } diff --git a/Source/WebCore/inspector/front-end/ElementsPanelDescriptor.js b/Source/WebCore/inspector/front-end/ElementsPanelDescriptor.js new file mode 100644 index 000000000..d524d15a8 --- /dev/null +++ b/Source/WebCore/inspector/front-end/ElementsPanelDescriptor.js @@ -0,0 +1,56 @@ +/* + * 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 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.PanelDescriptor} + * @implements {WebInspector.ContextMenu.Provider} + */ +WebInspector.ElementsPanelDescriptor = function() +{ + WebInspector.PanelDescriptor.call(this, "elements", WebInspector.UIString("Elements"), "ElementsPanel", "ElementsPanel.js"); + WebInspector.ContextMenu.registerProvider(this); +} + +WebInspector.ElementsPanelDescriptor.prototype = { + /** + * @param {WebInspector.ContextMenu} contextMenu + * @param {Object} target + */ + appendApplicableItems: function(contextMenu, target) + { + if (!(target instanceof WebInspector.RemoteObject)) + return; + var remoteObject = /** @type {WebInspector.RemoteObject} */ target; + if (remoteObject.subtype !== "node") + return; + this.panel().appendApplicableItems(contextMenu, target); + } +} + +WebInspector.ElementsPanelDescriptor.prototype.__proto__ = WebInspector.PanelDescriptor.prototype; diff --git a/Source/WebCore/inspector/front-end/ElementsTreeOutline.js b/Source/WebCore/inspector/front-end/ElementsTreeOutline.js index fa3bfe94f..81836364d 100644 --- a/Source/WebCore/inspector/front-end/ElementsTreeOutline.js +++ b/Source/WebCore/inspector/front-end/ElementsTreeOutline.js @@ -71,6 +71,23 @@ WebInspector.ElementsTreeOutline.Events = { SelectedNodeChanged: "SelectedNodeChanged" } +WebInspector.ElementsTreeOutline.MappedCharToEntity = { + "\u00a0": "nbsp", + "\u2002": "ensp", + "\u2003": "emsp", + "\u2009": "thinsp", + "\u200b": "#8203", // ZWSP + "\u200c": "zwnj", + "\u200d": "zwj", + "\u200e": "lrm", + "\u200f": "rlm", + "\u202a": "#8234", // LRE + "\u202b": "#8235", // RLE + "\u202c": "#8236", // PDF + "\u202d": "#8237", // LRO + "\u202e": "#8238" // RLO +} + WebInspector.ElementsTreeOutline.prototype = { _createNodeDecorators: function() { @@ -483,25 +500,17 @@ WebInspector.ElementsTreeOutline.prototype = { if (textNode && textNode.hasStyleClass("bogus")) textNode = null; var commentNode = event.target.enclosingNodeOrSelfWithClass("webkit-html-comment"); - var populated = WebInspector.populateHrefContextMenu(contextMenu, this.selectedDOMNode(), event); - if (textNode && treeElement._populateTextContextMenu) { - if (populated) - contextMenu.appendSeparator(); + contextMenu.appendApplicableItems(event.target); + if (textNode) { + contextMenu.appendSeparator(); treeElement._populateTextContextMenu(contextMenu, textNode); - populated = true; - } else if (isTag && treeElement._populateTagContextMenu) { - if (populated) - contextMenu.appendSeparator(); + } else if (isTag) { + contextMenu.appendSeparator(); treeElement._populateTagContextMenu(contextMenu, event); - populated = true; - } else if (commentNode && treeElement._populateNodeContextMenu) { - if (populated) - contextMenu.appendSeparator(); + } else if (commentNode) { + contextMenu.appendSeparator(); treeElement._populateNodeContextMenu(contextMenu, textNode); - populated = true; } - - return populated; }, adjustCollapsedRange: function() @@ -1310,7 +1319,7 @@ WebInspector.ElementsTreeElement.prototype = { var container = textNode.enclosingNodeOrSelfWithClass("webkit-html-text-node"); if (container) - container.innerText = container.innerText; // Strip the CSS or JS highlighting if present. + container.innerText = textNode._originalContent; // Strip the CSS or JS highlighting if present. 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); @@ -1664,7 +1673,7 @@ WebInspector.ElementsTreeElement.prototype = { attrSpanElement.appendChild(document.createTextNode("=\u200B\"")); if (linkify && (name === "src" || name === "href")) { - var rewrittenHref = WebInspector.resourceURLForRelatedNode(node, value); + var rewrittenHref = node.resolveURL(value); value = value.replace(/([\/;:\)\]\}])/g, "$1\u200B"); if (rewrittenHref === null) { var attrValueElement = attrSpanElement.createChild("span", "webkit-html-attribute-value"); @@ -1711,6 +1720,25 @@ WebInspector.ElementsTreeElement.prototype = { parentElement.appendChild(document.createTextNode("\u200B")); }, + _convertWhitespaceToEntities: function(text) + { + var result = ""; + var lastIndexAfterEntity = 0; + var charToEntity = WebInspector.ElementsTreeOutline.MappedCharToEntity; + for (var i = 0, size = text.length; i < size; ++i) { + var char = text.charAt(i); + if (charToEntity[char]) { + result += text.substring(lastIndexAfterEntity, i) + "&" + charToEntity[char] + ";"; + lastIndexAfterEntity = i + 1; + } + } + if (result) { + result += text.substring(lastIndexAfterEntity); + return result; + } + return text; + }, + _nodeTitleInfo: function(linkify) { var node = this.representedObject; @@ -1749,7 +1777,8 @@ WebInspector.ElementsTreeElement.prototype = { // create a subtree for them if (showInlineText) { var textNodeElement = info.titleDOM.createChild("span", "webkit-html-text-node"); - textNodeElement.textContent = textChild.nodeValue(); + textNodeElement.textContent = this._convertWhitespaceToEntities(textChild.nodeValue()); + textNodeElement._originalContent = textChild.nodeValue(); info.titleDOM.appendChild(document.createTextNode("\u200B")); this._buildTagDOM(info.titleDOM, tagName, true, false); info.hasChildren = false; @@ -1772,7 +1801,8 @@ WebInspector.ElementsTreeElement.prototype = { } else { info.titleDOM.appendChild(document.createTextNode("\"")); var textNodeElement = info.titleDOM.createChild("span", "webkit-html-text-node"); - textNodeElement.textContent = node.nodeValue(); + textNodeElement.textContent = this._convertWhitespaceToEntities(node.nodeValue()); + textNodeElement._originalContent = node.nodeValue(); info.titleDOM.appendChild(document.createTextNode("\"")); } break; @@ -1970,10 +2000,33 @@ WebInspector.ElementsTreeUpdater = function(treeOutline) WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.ChildNodeCountUpdated, this._childNodeCountUpdated, this); this._treeOutline = treeOutline; - this._recentlyModifiedNodes = []; + this._recentlyModifiedNodes = new Map(); } WebInspector.ElementsTreeUpdater.prototype = { + + /** + * @param {!WebInspector.DOMNode} node + * @param {boolean} isUpdated + * @param {WebInspector.DOMNode=} parentNode + */ + _nodeModified: function(node, isUpdated, parentNode) + { + if (this._treeOutline._visible) + this._updateModifiedNodesSoon(); + + var entry = /** @type {WebInspector.ElementsTreeUpdater.UpdateEntry} */ this._recentlyModifiedNodes.get(node); + if (!entry) { + entry = new WebInspector.ElementsTreeUpdater.UpdateEntry(isUpdated, parentNode); + this._recentlyModifiedNodes.put(node, entry); + return; + } + + entry.isUpdated |= isUpdated; + if (parentNode) + entry.parent = parentNode; + }, + _documentUpdated: function(event) { var inspectedRootDocument = event.data; @@ -1988,30 +2041,22 @@ WebInspector.ElementsTreeUpdater.prototype = { _attributesUpdated: function(event) { - this._recentlyModifiedNodes.push({node: event.data.node, updated: true}); - if (this._treeOutline._visible) - this._updateModifiedNodesSoon(); + this._nodeModified(event.data.node, true); }, _characterDataModified: function(event) { - this._recentlyModifiedNodes.push({node: event.data, updated: true}); - if (this._treeOutline._visible) - this._updateModifiedNodesSoon(); + this._nodeModified(event.data, true); }, _nodeInserted: function(event) { - this._recentlyModifiedNodes.push({node: event.data, parent: event.data.parentNode, inserted: true}); - if (this._treeOutline._visible) - this._updateModifiedNodesSoon(); + this._nodeModified(event.data, false, event.data.parentNode); }, _nodeRemoved: function(event) { - this._recentlyModifiedNodes.push({node: event.data.node, parent: event.data.parent, removed: true}); - if (this._treeOutline._visible) - this._updateModifiedNodesSoon(); + this._nodeModified(event.data.node, false, event.data.parent); }, _childNodeCountUpdated: function(event) @@ -2025,7 +2070,7 @@ WebInspector.ElementsTreeUpdater.prototype = { { if (this._updateModifiedNodesTimeout) return; - this._updateModifiedNodesTimeout = setTimeout(this._updateModifiedNodes.bind(this), 0); + this._updateModifiedNodesTimeout = setTimeout(this._updateModifiedNodes.bind(this), 50); }, _updateModifiedNodes: function() @@ -2037,15 +2082,18 @@ WebInspector.ElementsTreeUpdater.prototype = { var updatedParentTreeElements = []; - var hidePanelWhileUpdating = this._recentlyModifiedNodes.length > 10; + var hidePanelWhileUpdating = this._recentlyModifiedNodes.size() > 10; if (hidePanelWhileUpdating) { var treeOutlineContainerElement = this._treeOutline.element.parentNode; this._treeOutline.element.addStyleClass("hidden"); var originalScrollTop = treeOutlineContainerElement ? treeOutlineContainerElement.scrollTop : 0; } - for (var i = 0; i < this._recentlyModifiedNodes.length; ++i) { - var parent = this._recentlyModifiedNodes[i].parent; + var keys = this._recentlyModifiedNodes.keys(); + for (var i = 0, size = keys.length; i < size; ++i) { + var node = keys[i]; + var entry = this._recentlyModifiedNodes.get(node); + var parent = entry.parent; if (parent === this._treeOutline._rootDOMNode) { // Document's children have changed, perform total update. @@ -2054,13 +2102,10 @@ WebInspector.ElementsTreeUpdater.prototype = { return; } - var node = this._recentlyModifiedNodes[i].node; - - if (this._recentlyModifiedNodes[i].updated) { + if (entry.isUpdated) { var nodeItem = this._treeOutline.findTreeElement(node); if (nodeItem) nodeItem.updateTitle(); - continue; } if (!parent) @@ -2083,7 +2128,7 @@ WebInspector.ElementsTreeUpdater.prototype = { treeOutlineContainerElement.scrollTop = originalScrollTop; this._treeOutline.updateSelection(); } - this._recentlyModifiedNodes = []; + this._recentlyModifiedNodes.clear(); }, _reset: function() @@ -2091,6 +2136,18 @@ WebInspector.ElementsTreeUpdater.prototype = { this._treeOutline.rootDOMNode = null; this._treeOutline.selectDOMNode(null, false); WebInspector.domAgent.hideDOMNodeHighlight(); - this._recentlyModifiedNodes = []; + this._recentlyModifiedNodes.clear(); } } + +/** + * @constructor + * @param {boolean} isUpdated + * @param {WebInspector.DOMNode=} parent + */ +WebInspector.ElementsTreeUpdater.UpdateEntry = function(isUpdated, parent) +{ + this.isUpdated = isUpdated; + if (parent) + this.parent = parent; +} diff --git a/Source/WebCore/inspector/front-end/ExtensionServer.js b/Source/WebCore/inspector/front-end/ExtensionServer.js index f9e763ab0..ec3811b69 100644 --- a/Source/WebCore/inspector/front-end/ExtensionServer.js +++ b/Source/WebCore/inspector/front-end/ExtensionServer.js @@ -767,7 +767,7 @@ WebInspector.ExtensionServer.prototype = { var mainFrame = WebInspector.resourceTreeModel.mainFrame; if (!mainFrame) return this._status.E_FAILED("main frame not available yet"); - var context = WebInspector.javaScriptContextManager.contextByFrameAndSecurityOrigin(mainFrame, securityOrigin); + var context = WebInspector.runtimeModel.contextByFrameAndSecurityOrigin(mainFrame, securityOrigin); if (!context) return this._status.E_NOTFOUND(securityOrigin); contextId = context.id; diff --git a/Source/WebCore/inspector/front-end/FileSystemModel.js b/Source/WebCore/inspector/front-end/FileSystemModel.js index 30edd84e8..81439ce80 100644 --- a/Source/WebCore/inspector/front-end/FileSystemModel.js +++ b/Source/WebCore/inspector/front-end/FileSystemModel.js @@ -44,7 +44,7 @@ WebInspector.FileSystemModel = function() WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameNavigated, this._frameNavigated, this); WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameDetached, this._frameDetached, this); - this._agentWrapper = new WebInspector.FileSystemRequestManager(); + FileSystemAgent.enable(); if (WebInspector.resourceTreeModel.mainFrame) this._attachFrameRecursively(WebInspector.resourceTreeModel.mainFrame); @@ -148,7 +148,32 @@ WebInspector.FileSystemModel.prototype = { var types = ["persistent", "temporary"]; for (var i = 0; i < types.length; ++i) - this._agentWrapper.requestFileSystemRoot(origin, types[i], this._fileSystemRootReceived.bind(this, origin, types[i], this._fileSystemsForOrigin[origin])); + this._requestFileSystemRoot(origin, types[i], this._fileSystemRootReceived.bind(this, origin, types[i], this._fileSystemsForOrigin[origin])); + }, + + /** + * @param {string} origin + * @param {string} type + * @param {function(number, FileSystemAgent.Entry=)} callback + */ + _requestFileSystemRoot: function(origin, type, callback) + { + /** + * @param {?Protocol.Error} error + * @param {number} errorCode + * @param {FileSystemAgent.Entry=} backendRootEntry + */ + function innerCallback(error, errorCode, backendRootEntry) + { + if (error) { + callback(FileError.SECURITY_ERR); + return; + } + + callback(errorCode, backendRootEntry); + } + + FileSystemAgent.requestFileSystemRoot(origin, type, innerCallback.bind(this)); }, /** @@ -197,7 +222,7 @@ WebInspector.FileSystemModel.prototype = { */ _fileSystemRootReceived: function(origin, type, store, errorCode, backendRootEntry) { - if (errorCode === 0 && backendRootEntry && this._fileSystemsForOrigin[origin] === store) { + if (!errorCode && backendRootEntry && this._fileSystemsForOrigin[origin] === store) { var fileSystem = new WebInspector.FileSystemModel.FileSystem(this, origin, type, backendRootEntry); store[type] = fileSystem; this._fileSystemAdded(fileSystem); @@ -210,7 +235,36 @@ WebInspector.FileSystemModel.prototype = { */ requestDirectoryContent: function(directory, callback) { - this._agentWrapper.requestDirectoryContent(directory.url, this._directoryContentReceived.bind(this, directory, callback)); + this._requestDirectoryContent(directory.url, this._directoryContentReceived.bind(this, directory, callback)); + }, + + /** + * @param {string} url + * @param {function(number, Array.<FileSystemAgent.Entry>=)} callback + */ + _requestDirectoryContent: function(url, callback) + { + /** + * @param {?Protocol.Error} error + * @param {number} errorCode + * @param {Array.<FileSystemAgent.Entry>=} backendEntries + */ + function innerCallback(error, errorCode, backendEntries) + { + if (error) { + callback(FileError.SECURITY_ERR); + return; + } + + if (errorCode !== 0) { + callback(errorCode, null); + return; + } + + callback(errorCode, backendEntries); + } + + FileSystemAgent.requestDirectoryContent(url, innerCallback.bind(this)); }, /** @@ -221,11 +275,6 @@ WebInspector.FileSystemModel.prototype = { */ _directoryContentReceived: function(parentDirectory, callback, errorCode, backendEntries) { - if (errorCode !== 0) { - callback(errorCode, null); - return; - } - var entries = []; for (var i = 0; i < backendEntries.length; ++i) { if (backendEntries[i].isDirectory) @@ -243,7 +292,22 @@ WebInspector.FileSystemModel.prototype = { */ requestMetadata: function(entry, callback) { - this._agentWrapper.requestMetadata(entry.url, callback); + /** + * @param {?Protocol.Error} error + * @param {number} errorCode + * @param {FileSystemAgent.Metadata=} metadata + */ + function innerCallback(error, errorCode, metadata) + { + if (error) { + callback(FileError.SECURITY_ERR); + return; + } + + callback(errorCode, metadata); + } + + FileSystemAgent.requestMetadata(entry.url, innerCallback.bind(this)); }, /** @@ -256,7 +320,98 @@ WebInspector.FileSystemModel.prototype = { */ requestFileContent: function(file, readAsText, start, end, charset, callback) { - this._agentWrapper.requestFileContent(file.url, readAsText, start, end, charset, callback); + this._requestFileContent(file.url, readAsText, start, end, charset, callback); + }, + + /** + * @param {string} url + * @param {boolean} readAsText + * @param {number=} start + * @param {number=} end + * @param {string=} charset + * @param {function(number, string=, string=)=} callback + */ + _requestFileContent: function(url, readAsText, start, end, charset, callback) + { + /** + * @param {?Protocol.Error} error + * @param {number} errorCode + * @param {string=} content + * @param {string=} charset + */ + function innerCallback(error, errorCode, content, charset) + { + if (error) { + if (callback) + callback(FileError.SECURITY_ERR); + return; + } + + if (callback) + callback(errorCode, content, charset); + } + + FileSystemAgent.requestFileContent(url, readAsText, start, end, charset, innerCallback.bind(this)); + }, + /** + * @param {WebInspector.FileSystemModel.Entry} entry + * @param {function(number)=} callback + */ + deleteEntry: function(entry, callback) + { + var fileSystemModel = this; + if (entry === entry.fileSystem.root) + this._deleteEntry(entry.url, hookFileSystemDeletion); + else + this._deleteEntry(entry.url, callback); + + function hookFileSystemDeletion(errorCode) + { + callback(errorCode); + if (!errorCode) + fileSystemModel._removeFileSystem(entry.fileSystem); + } + }, + + /** + * @param {string} url + * @param {function(number)=} callback + */ + _deleteEntry: function(url, callback) + { + /** + * @param {?Protocol.Error} error + * @param {number} errorCode + */ + function innerCallback(error, errorCode) + { + if (error) { + if (callback) + callback(FileError.SECURITY_ERR); + return; + } + + if (callback) + callback(errorCode); + } + + FileSystemAgent.deleteEntry(url, innerCallback.bind(this)); + }, + + /** + * @param {WebInspector.FileSystemModel.FileSystem} fileSystem + */ + _removeFileSystem: function(fileSystem) + { + var origin = fileSystem.origin; + var type = fileSystem.type; + if (this._fileSystemsForOrigin[origin] && this._fileSystemsForOrigin[origin][type]) { + delete this._fileSystemsForOrigin[origin][type]; + this._fileSystemRemoved(fileSystem); + + if (Object.isEmpty(this._fileSystemsForOrigin[origin])) + delete this._fileSystemsForOrigin[origin]; + } } } @@ -367,6 +522,14 @@ WebInspector.FileSystemModel.Entry.prototype = { requestMetadata: function(callback) { this.fileSystemModel.requestMetadata(this, callback); + }, + + /** + * @param {function(number)} callback + */ + deleteEntry: function(callback) + { + this.fileSystemModel.deleteEntry(this, callback); } } @@ -449,210 +612,3 @@ WebInspector.FileSystemModel.File.prototype = { } WebInspector.FileSystemModel.File.prototype.__proto__ = WebInspector.FileSystemModel.Entry.prototype; - -/** - * @constructor - */ -WebInspector.FileSystemRequestManager = function() -{ - this._pendingFileSystemRootRequests = {}; - this._pendingDirectoryContentRequests = {}; - this._pendingMetadataRequests = {}; - this._pendingFileContentRequests = {}; - - InspectorBackend.registerFileSystemDispatcher(new WebInspector.FileSystemDispatcher(this)); - FileSystemAgent.enable(); -} - -WebInspector.FileSystemRequestManager.prototype = { - /** - * @param {string} origin - * @param {string} type - * @param {function(number, FileSystemAgent.Entry=)=} callback - */ - requestFileSystemRoot: function(origin, type, callback) - { - var store = this._pendingFileSystemRootRequests; - FileSystemAgent.requestFileSystemRoot(origin, type, requestAccepted); - - function requestAccepted(error, requestId) - { - if (error) - callback(FileError.SECURITY_ERR); - else - store[requestId] = callback || function() {}; - } - }, - - /** - * @param {number} requestId - * @param {number} errorCode - * @param {FileSystemAgent.Entry=} backendRootEntry - */ - _fileSystemRootReceived: function(requestId, errorCode, backendRootEntry) - { - var callback = this._pendingFileSystemRootRequests[requestId]; - if (!callback) - return; - delete this._pendingFileSystemRootRequests[requestId]; - callback(errorCode, backendRootEntry); - }, - - /** - * @param {string} url - * @param {function(number, Array.<FileSystemAgent.Entry>=)=} callback - */ - requestDirectoryContent: function(url, callback) - { - var store = this._pendingDirectoryContentRequests; - FileSystemAgent.requestDirectoryContent(url, requestAccepted); - - function requestAccepted(error, requestId) - { - if (error) - callback(FileError.SECURITY_ERR); - else - store[requestId] = callback || function() {}; - } - }, - - /** - * @param {number} requestId - * @param {number} errorCode - * @param {Array.<FileSystemAgent.Entry>=} backendEntries - */ - _directoryContentReceived: function(requestId, errorCode, backendEntries) - { - var callback = /** @type {function(number, Array.<FileSystemAgent.Entry>=)} */ this._pendingDirectoryContentRequests[requestId]; - if (!callback) - return; - delete this._pendingDirectoryContentRequests[requestId]; - callback(errorCode, backendEntries); - }, - - /** - * @param {string} url - * @param {function(number, FileSystemAgent.Metadata=)=} callback - */ - requestMetadata: function(url, callback) - { - var store = this._pendingMetadataRequests; - FileSystemAgent.requestMetadata(url, requestAccepted); - - function requestAccepted(error, requestId) - { - if (error) - callback(FileError.SECURITY_ERR); - else - store[requestId] = callback || function() {}; - } - }, - - _metadataReceived: function(requestId, errorCode, metadata) - { - var callback = this._pendingMetadataRequests[requestId]; - if (!callback) - return; - delete this._pendingMetadataRequests[requestId]; - callback(errorCode, metadata); - }, - - /** - * @param {string} url - * @param {boolean} readAsText - * @param {number=} start - * @param {number=} end - * @param {string=} charset - * @param {function(number, string=, string=)=} callback - */ - requestFileContent: function(url, readAsText, start, end, charset, callback) - { - var store = this._pendingFileContentRequests; - FileSystemAgent.requestFileContent(url, readAsText, start, end, charset, requestAccepted); - - function requestAccepted(error, requestId) - { - if (error) - callback(FileError.SECURITY_ERR); - else - store[requestId] = callback || function() {}; - } - }, - - /** - * @param {number} requestId - * @param {number} errorCode - * @param {string=} content - * @param {string=} charset - */ - _fileContentReceived: function(requestId, errorCode, content, charset) - { - var callback = /** @type {function(number, string=, string=)} */ this._pendingFileContentRequests[requestId]; - if (!callback) - return; - delete this._pendingFileContentRequests[requestId]; - callback(errorCode, content, charset); - } -} - -/** - * @constructor - * @implements {FileSystemAgent.Dispatcher} - * @param {WebInspector.FileSystemRequestManager} agentWrapper - */ -WebInspector.FileSystemDispatcher = function(agentWrapper) -{ - this._agentWrapper = agentWrapper; -} - -WebInspector.FileSystemDispatcher.prototype = { - /** - * @param {number} requestId - * @param {number} errorCode - * @param {FileSystemAgent.Entry=} backendRootEntry - */ - fileSystemRootReceived: function(requestId, errorCode, backendRootEntry) - { - this._agentWrapper._fileSystemRootReceived(requestId, errorCode, backendRootEntry); - }, - - /** - * @param {number} requestId - * @param {number} errorCode - * @param {Array.<FileSystemAgent.Entry>=} backendEntries - */ - directoryContentReceived: function(requestId, errorCode, backendEntries) - { - this._agentWrapper._directoryContentReceived(requestId, errorCode, backendEntries); - }, - - /** - * @param {number} requestId - * @param {number} errorCode - * @param {FileSystemAgent.Metadata=} metadata - */ - metadataReceived: function(requestId, errorCode, metadata) - { - this._agentWrapper._metadataReceived(requestId, errorCode, metadata); - }, - - /** - * @param {number} requestId - * @param {number} errorCode - * @param {string=} content - * @param {string=} charset - */ - fileContentReceived: function(requestId, errorCode, content, charset) - { - this._agentWrapper._fileContentReceived(requestId, errorCode, content, charset); - }, - - /** - * @param {number} requestId - * @param {number} errorCode - */ - deletionCompleted: function(requestId, errorCode) - { - console.error("Not implemented"); - } -} diff --git a/Source/WebCore/inspector/front-end/FileSystemView.js b/Source/WebCore/inspector/front-end/FileSystemView.js index 9b89beab1..60b9f4259 100644 --- a/Source/WebCore/inspector/front-end/FileSystemView.js +++ b/Source/WebCore/inspector/front-end/FileSystemView.js @@ -53,6 +53,10 @@ WebInspector.FileSystemView = function(fileSystem) this._refreshButton = new WebInspector.StatusBarButton(WebInspector.UIString("Refresh"), "refresh-storage-status-bar-item"); this._refreshButton.visible = true; this._refreshButton.addEventListener("click", this._refresh, this); + + this._deleteButton = new WebInspector.StatusBarButton(WebInspector.UIString("Delete"), "delete-storage-status-bar-item"); + this._deleteButton.visible = true; + this._deleteButton.addEventListener("click", this._confirmDelete, this); } WebInspector.FileSystemView.prototype = { @@ -61,7 +65,7 @@ WebInspector.FileSystemView.prototype = { */ get statusBarItems() { - return [this._refreshButton.element]; + return [this._refreshButton.element, this._deleteButton.element]; }, /** @@ -88,6 +92,17 @@ WebInspector.FileSystemView.prototype = { _refresh: function() { this._directoryTree.children[0].refresh(); + }, + + _confirmDelete: function() + { + if (confirm(WebInspector.UIString("Are you sure you want to delete the selected entry?"))) + this._delete(); + }, + + _delete: function() + { + this._directoryTree.selectedTreeElement.deleteEntry(); } } @@ -201,6 +216,17 @@ WebInspector.FileSystemView.EntryTreeElement.prototype = { } } else this._entry.requestDirectoryContent(this._directoryContentReceived.bind(this)); + }, + + deleteEntry: function() + { + this._entry.deleteEntry(this._deletionCompleted.bind(this)); + }, + + _deletionCompleted: function() + { + if (this._entry != this._entry.fileSystem.root) + this.parent.refresh(); } } diff --git a/Source/WebCore/inspector/front-end/FileUtils.js b/Source/WebCore/inspector/front-end/FileUtils.js index 34ec16e50..9d95a531f 100644 --- a/Source/WebCore/inspector/front-end/FileUtils.js +++ b/Source/WebCore/inspector/front-end/FileUtils.js @@ -68,7 +68,7 @@ WebInspector.OutputStream.prototype = { /** * @constructor * @param {!File} file - * @param {!number} chunkSize + * @param {number} chunkSize * @param {!WebInspector.OutputStreamDelegate} delegate */ WebInspector.ChunkedFileReader = function(file, chunkSize, delegate) @@ -78,6 +78,7 @@ WebInspector.ChunkedFileReader = function(file, chunkSize, delegate) this._loadedSize = 0; this._chunkSize = chunkSize; this._delegate = delegate; + this._isCanceled = false; } WebInspector.ChunkedFileReader.prototype = { @@ -96,6 +97,11 @@ WebInspector.ChunkedFileReader.prototype = { this._loadChunk(); }, + cancel: function() + { + this._isCanceled = true; + }, + loadedSize: function() { return this._loadedSize; @@ -116,6 +122,9 @@ WebInspector.ChunkedFileReader.prototype = { */ _onChunkLoaded: function(event) { + if (this._isCanceled) + return; + if (event.target.readyState !== FileReader.DONE) return; @@ -123,6 +132,8 @@ WebInspector.ChunkedFileReader.prototype = { this._loadedSize += data.length; this._output.transferChunk(data); + if (this._isCanceled) + return; this._delegate.onChunkTransferred(this); if (this._loadedSize === this._fileSize) { @@ -146,7 +157,98 @@ WebInspector.ChunkedFileReader.prototype = { } /** - * @param {!function(File)} callback + * @constructor + * @param {string} url + * @param {!WebInspector.OutputStreamDelegate} delegate + */ +WebInspector.ChunkedXHRReader = function(url, delegate) +{ + this._url = url; + this._delegate = delegate; + this._fileSize = 0; + this._loadedSize = 0; + this._isCanceled = false; +} + +WebInspector.ChunkedXHRReader.prototype = { + /** + * @param {!WebInspector.OutputStream} output + */ + start: function(output) + { + this._output = output; + + this._xhr = new XMLHttpRequest(); + this._xhr.open("GET", this._url, true); + this._xhr.onload = this._onLoad.bind(this); + this._xhr.onprogress = this._onProgress.bind(this); + this._xhr.onerror = this._delegate.onError.bind(this._delegate, this); + this._xhr.send(null); + + this._output.startTransfer(); + this._delegate.onTransferStarted(this); + }, + + cancel: function() + { + this._isCanceled = true; + this._xhr.abort(); + }, + + loadedSize: function() + { + return this._loadedSize; + }, + + fileSize: function() + { + return this._fileSize; + }, + + fileName: function() + { + return this._url; + }, + + /** + * @param {Event} event + */ + _onProgress: function(event) + { + if (this._isCanceled) + return; + + if (event.lengthComputable) + this._fileSize = event.total; + + var data = this._xhr.responseText.substring(this._loadedSize); + if (!data.length) + return; + + this._loadedSize += data.length; + this._output.transferChunk(data); + if (this._isCanceled) + return; + this._delegate.onChunkTransferred(this); + }, + + /** + * @param {Event} event + */ + _onLoad: function(event) + { + this._onProgress(event); + + if (this._isCanceled) + return; + + this._output.finishTransfer(); + this._delegate.onTransferFinished(this); + } +} + +/** + * @param {function(File)} callback * @return {Node} */ WebInspector.createFileSelectorElement = function(callback) { @@ -159,3 +261,102 @@ WebInspector.createFileSelectorElement = function(callback) { }; return fileSelectorElement; } + +/** + * @param {string} source + * @param {number=} startIndex + * @param {number=} lastIndex + */ +WebInspector.findBalancedCurlyBrackets = function(source, startIndex, lastIndex) { + lastIndex = lastIndex || source.length; + startIndex = startIndex || 0; + var counter = 0; + var inString = false; + + for (var index = startIndex; index < lastIndex; ++index) { + var character = source[index]; + if (inString) { + if (character === "\\") + ++index; + else if (character === "\"") + inString = false; + } else { + if (character === "\"") + inString = true; + else if (character === "{") + ++counter; + else if (character === "}") { + if (--counter === 0) + return index + 1; + } + } + } + return -1; +} + +/** + * @constructor + * @implements {WebInspector.OutputStream} + * @param {string} fileName + * @param {!WebInspector.OutputStreamDelegate} delegate + */ +WebInspector.FileOutputStream = function(fileName, delegate) +{ + this._fileName = fileName; + this._delegate = delegate; +} + +WebInspector.FileOutputStream.prototype = { + /** + * @override + */ + startTransfer: function() + { + WebInspector.fileManager.addEventListener(WebInspector.FileManager.EventTypes.SavedURL, this._onTransferStarted, this); + WebInspector.fileManager.save(this._fileName, "", true); + }, + + /** + * @override + * @param {string} chunk + */ + transferChunk: function(chunk) + { + WebInspector.fileManager.append(this._fileName, chunk); + }, + + /** + * @override + */ + finishTransfer: function() + { + WebInspector.fileManager.removeEventListener(WebInspector.FileManager.EventTypes.AppendedToURL, this._onChunkTransferred, this); + this._delegate.onTransferFinished(this); + }, + + dispose: function() + { + }, + + /** + * @param {WebInspector.Event} event + */ + _onTransferStarted: function(event) + { + if (event.data !== this._fileName) + return; + this._delegate.onTransferStarted(this); + WebInspector.fileManager.removeEventListener(WebInspector.FileManager.EventTypes.SavedURL, this._onTransferStarted, this); + WebInspector.fileManager.addEventListener(WebInspector.FileManager.EventTypes.AppendedToURL, this._onChunkTransferred, this); + }, + + /** + * @param {WebInspector.Event} event + */ + _onChunkTransferred: function(event) + { + if (event.data !== this._fileName) + return; + this._delegate.onChunkTransferred(this); + } +} diff --git a/Source/WebCore/inspector/front-end/FilteredItemSelectionDialog.js b/Source/WebCore/inspector/front-end/FilteredItemSelectionDialog.js index f027765e4..e086dadaf 100644 --- a/Source/WebCore/inspector/front-end/FilteredItemSelectionDialog.js +++ b/Source/WebCore/inspector/front-end/FilteredItemSelectionDialog.js @@ -121,7 +121,7 @@ WebInspector.FilteredItemSelectionDialog.prototype = { _itemsLoaded: function(index, chunkLength, chunkIndex, chunkCount) { for (var i = index; i < index + chunkLength; ++i) - this._itemElementsContainer.appendChild(this._createItemElement(i, this._delegate.itemTitleAt(i))); + this._itemElementsContainer.appendChild(this._createItemElement(i)); this._filterItems(); if (chunkIndex === chunkCount) @@ -135,21 +135,21 @@ WebInspector.FilteredItemSelectionDialog.prototype = { /** * @param {number} index - * @param {string} title */ - _createItemElement: function(index, title) + _createItemElement: function(index) { if (this._itemElements[index]) return this._itemElements[index]; var itemElement = document.createElement("div"); itemElement.className = "item"; - var titleElement = itemElement.createChild("span"); - var subtitleElement = itemElement.createChild("span"); - titleElement.textContent = title; + itemElement._titleElement = itemElement.createChild("span"); + itemElement._titleElement.textContent = this._delegate.itemTitleAt(index); + itemElement._titleSuffixElement = itemElement.createChild("span"); + itemElement._subtitleElement = itemElement.createChild("span", "subtitle"); + itemElement._subtitleElement.textContent = this._delegate.itemSubtitleAt(index); this._elementIndexes.put(itemElement, index); this._itemElements.push(itemElement); - return itemElement; }, @@ -223,7 +223,7 @@ WebInspector.FilteredItemSelectionDialog.prototype = { var firstElement; for (var i = 0; i < this._itemElements.length; ++i) { var itemElement = this._itemElements[i]; - itemElement.lastChild.textContent = this._delegate.itemSubtitleAt(i); + itemElement._titleSuffixElement.textContent = this._delegate.itemSuffixAt(i); if (regex.test(this._delegate.itemKeyAt(i))) { this._showItemElement(itemElement); if (!firstElement) @@ -438,6 +438,12 @@ WebInspector.SelectionDialogContentProvider.prototype = { * @param {number} itemIndex * @return {string} */ + itemSuffixAt: function(itemIndex) { }, + + /* + * @param {number} itemIndex + * @return {string} + */ itemSubtitleAt: function(itemIndex) { }, /** @@ -512,11 +518,20 @@ WebInspector.JavaScriptOutlineDialog.prototype = { * @param {number} itemIndex * @return {string} */ - itemSubtitleAt: function(itemIndex) + itemSuffixAt: function(itemIndex) { return ""; }, + /* + * @param {number} itemIndex + * @return {string} + */ + itemSubtitleAt: function(itemIndex) + { + return ":" + (this._functionItems[itemIndex].line + 1); + }, + /** * @param {number} itemIndex * @return {string} @@ -636,11 +651,20 @@ WebInspector.OpenResourceDialog.prototype = { * @param {number} itemIndex * @return {string} */ - itemSubtitleAt: function(itemIndex) + itemSuffixAt: function(itemIndex) { return this._queryLineNumber || ""; }, + /* + * @param {number} itemIndex + * @return {string} + */ + itemSubtitleAt: function(itemIndex) + { + return this._uiSourceCodes[itemIndex].parsedURL.folderPathComponents; + }, + /** * @param {number} itemIndex * @return {string} diff --git a/Source/WebCore/inspector/front-end/HandlerRegistry.js b/Source/WebCore/inspector/front-end/HandlerRegistry.js index 84ae7fda5..ef47a7694 100644 --- a/Source/WebCore/inspector/front-end/HandlerRegistry.js +++ b/Source/WebCore/inspector/front-end/HandlerRegistry.js @@ -96,6 +96,16 @@ WebInspector.HandlerRegistry.prototype = { */ appendApplicableItems: function(contextMenu, target) { + this._appendContentProviderItems(contextMenu, target); + this._appendHrefItems(contextMenu, target); + }, + + /** + * @param {WebInspector.ContextMenu} contextMenu + * @param {Object} target + */ + _appendContentProviderItems: function(contextMenu, target) + { if (!(target instanceof WebInspector.UISourceCode || target instanceof WebInspector.Resource || target instanceof WebInspector.NetworkRequest)) return; var contentProvider = /** @type {WebInspector.ContentProvider} */ target; @@ -140,6 +150,31 @@ WebInspector.HandlerRegistry.prototype = { contextMenu.appendSeparator(); contextMenu.appendItem(WebInspector.UIString("Save"), save.bind(this, false)); contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Save as..." : "Save As..."), save.bind(this, true)); + }, + + /** + * @param {WebInspector.ContextMenu} contextMenu + * @param {Object} target + */ + _appendHrefItems: function(contextMenu, target) + { + if (!(target instanceof Node)) + return; + var targetNode = /** @type {Node} */ target; + + var anchorElement = targetNode.enclosingNodeOrSelfWithClass("webkit-html-resource-link") || targetNode.enclosingNodeOrSelfWithClass("webkit-html-external-link"); + if (!anchorElement) + return; + + var resourceURL = anchorElement.href; + if (!resourceURL) + return; + + // 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)); } } diff --git a/Source/WebCore/inspector/front-end/HeapSnapshot.js b/Source/WebCore/inspector/front-end/HeapSnapshot.js index 0ad93fd9d..169654056 100644 --- a/Source/WebCore/inspector/front-end/HeapSnapshot.js +++ b/Source/WebCore/inspector/front-end/HeapSnapshot.js @@ -919,7 +919,7 @@ WebInspector.HeapSnapshot.prototype = { var node = iter.edge.node(); if (node.isWindow()) { nodesToVisit[nodesToVisitLength++] = node.nodeIndex; - distances[node.nodeIndex / nodeFieldCount] = 0; + distances[node.nodeIndex / nodeFieldCount] = 1; } } this._bfs(nodesToVisit, nodesToVisitLength, distances); @@ -927,7 +927,7 @@ WebInspector.HeapSnapshot.prototype = { // bfs for root nodesToVisitLength = 0; nodesToVisit[nodesToVisitLength++] = this._rootNodeIndex; - distances[this._rootNodeIndex / nodeFieldCount] = 0; + distances[this._rootNodeIndex / nodeFieldCount] = 1; this._bfs(nodesToVisit, nodesToVisitLength, distances); this._distancesToWindow = distances; }, @@ -940,9 +940,12 @@ WebInspector.HeapSnapshot.prototype = { var containmentEdges = this._containmentEdges; var firstEdgeIndexes = this._firstEdgeIndexes; var edgeToNodeOffset = this._edgeToNodeOffset; + var edgeTypeOffset = this._edgeTypeOffset; var nodes = this._nodes; var nodeCount = this.nodeCount; var containmentEdgesLength = containmentEdges.length; + var edgeWeakType = this._edgeWeakType; + var edgeShortcutType = this._edgeShortcutType; var index = 0; while (index < nodesToVisitLength) { @@ -951,8 +954,11 @@ WebInspector.HeapSnapshot.prototype = { var distance = distances[nodeOrdinal] + 1; var firstEdgeIndex = firstEdgeIndexes[nodeOrdinal]; var edgesEnd = firstEdgeIndexes[nodeOrdinal + 1]; - for (var edgeToNodeIndex = firstEdgeIndex + edgeToNodeOffset; edgeToNodeIndex < edgesEnd; edgeToNodeIndex += edgeFieldsCount) { - var childNodeIndex = containmentEdges[edgeToNodeIndex]; + for (var edgeIndex = firstEdgeIndex; edgeIndex < edgesEnd; edgeIndex += edgeFieldsCount) { + var edgeType = containmentEdges[edgeIndex + edgeTypeOffset]; + if (edgeType == edgeWeakType) + continue; + var childNodeIndex = containmentEdges[edgeIndex + edgeToNodeOffset]; var childNodeOrdinal = childNodeIndex / nodeFieldCount; if (distances[childNodeOrdinal]) continue; @@ -1450,6 +1456,7 @@ WebInspector.HeapSnapshot.prototype = { var hiddenEdgeType = this._edgeHiddenType; var internalEdgeType = this._edgeInternalType; var invisibleEdgeType = this._edgeInvisibleType; + var weakEdgeType = this._edgeWeakType; var edgeToNodeOffset = this._edgeToNodeOffset; var edgeTypeOffset = this._edgeTypeOffset; var edgeFieldsCount = this._edgeFieldsCount; @@ -1480,7 +1487,7 @@ WebInspector.HeapSnapshot.prototype = { if (flags[childNodeOrdinal] & flag) continue; var type = containmentEdges[edgeIndex + edgeTypeOffset]; - if (type === hiddenEdgeType || type === invisibleEdgeType || type === internalEdgeType) + if (type === hiddenEdgeType || type === invisibleEdgeType || type === internalEdgeType || type === weakEdgeType) continue; list.push(childNodeOrdinal); } diff --git a/Source/WebCore/inspector/front-end/HeapSnapshotGridNodes.js b/Source/WebCore/inspector/front-end/HeapSnapshotGridNodes.js index f8c8b4a89..88564f1f8 100644 --- a/Source/WebCore/inspector/front-end/HeapSnapshotGridNodes.js +++ b/Source/WebCore/inspector/front-end/HeapSnapshotGridNodes.js @@ -542,7 +542,7 @@ WebInspector.HeapSnapshotObjectNode.prototype = { var showHiddenData = WebInspector.settings.showHeapSnapshotObjectsHiddenProperties.get(); var filter = "function(edge) {\n" + " return !edge.isInvisible()\n" + - " && (" + !tree.showRetainingEdges + " || (edge.node().id() !== 1 && !edge.node().isSynthetic()))\n" + + " && (" + !tree.showRetainingEdges + " || (edge.node().id() !== 1 && !edge.node().isSynthetic() && !edge.isWeak()))\n" + " && (" + showHiddenData + " || (!edge.isHidden() && !edge.node().isHidden()));\n" + "}\n"; var snapshot = this._isFromBaseSnapshot ? tree.baseSnapshot : tree.snapshot; diff --git a/Source/WebCore/inspector/front-end/HeapSnapshotLoader.js b/Source/WebCore/inspector/front-end/HeapSnapshotLoader.js index fc8e45a8d..e4e6f225e 100644 --- a/Source/WebCore/inspector/front-end/HeapSnapshotLoader.js +++ b/Source/WebCore/inspector/front-end/HeapSnapshotLoader.js @@ -54,22 +54,6 @@ WebInspector.HeapSnapshotLoader.prototype = { this._snapshot = {}; }, - _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; - }, - finishTransfer: function() { if (this._json) @@ -148,7 +132,7 @@ WebInspector.HeapSnapshotLoader.prototype = { break; } case "parse-snapshot-info": { - var closingBracketIndex = this._findBalancedCurlyBrackets(); + var closingBracketIndex = WebInspector.findBalancedCurlyBrackets(this._json); if (closingBracketIndex === -1) return; this._snapshot.snapshot = /** @type {HeapSnapshotHeader} */JSON.parse(this._json.slice(0, closingBracketIndex)); diff --git a/Source/WebCore/inspector/front-end/HeapSnapshotView.js b/Source/WebCore/inspector/front-end/HeapSnapshotView.js index b7f5019fd..d98ea7424 100644 --- a/Source/WebCore/inspector/front-end/HeapSnapshotView.js +++ b/Source/WebCore/inspector/front-end/HeapSnapshotView.js @@ -122,7 +122,7 @@ WebInspector.HeapSnapshotView = function(parent, profile) this._profileUid = profile.uid; this.baseSelectElement = document.createElement("select"); - this.baseSelectElement.className = "status-bar-item hidden"; + this.baseSelectElement.className = "status-bar-item"; this.baseSelectElement.addEventListener("change", this._changeBase.bind(this), false); this._updateBaseOptions(); @@ -172,7 +172,17 @@ WebInspector.HeapSnapshotView.prototype = { get statusBarItems() { - return [this.viewSelectElement, this.baseSelectElement, this.filterSelectElement, this.helpButton.element]; + /** + * @param {boolean=} hidden + */ + function appendArrowImage(element, hidden) + { + var span = document.createElement("span"); + span.className = "status-bar-select-container" + (hidden ? " hidden" : ""); + span.appendChild(element); + return span; + } + return [appendArrowImage(this.viewSelectElement), appendArrowImage(this.baseSelectElement, true), appendArrowImage(this.filterSelectElement), this.helpButton.element]; }, get profile() @@ -520,6 +530,19 @@ WebInspector.HeapSnapshotView.prototype = { this._changeView(event.target.selectedIndex); }, + _updateSelectorsVisibility: function() + { + if (this.currentView === this.diffView) + this.baseSelectElement.parentElement.removeStyleClass("hidden"); + else + this.baseSelectElement.parentElement.addStyleClass("hidden"); + + if (this.currentView === this.constructorsView) + this.filterSelectElement.parentElement.removeStyleClass("hidden"); + else + this.filterSelectElement.parentElement.addStyleClass("hidden"); + }, + _changeView: function(selectedIndex) { if (selectedIndex === this.views.current) @@ -534,18 +557,10 @@ WebInspector.HeapSnapshotView.prototype = { this.refreshVisibleData(); this.dataGrid.updateWidths(); - if (this.currentView === this.diffView) - this.baseSelectElement.removeStyleClass("hidden"); - else - this.baseSelectElement.addStyleClass("hidden"); + this._updateSelectorsVisibility(); this._updateDataSourceAndView(); - if (this.currentView === this.constructorsView) - this.filterSelectElement.removeStyleClass("hidden"); - else - this.filterSelectElement.addStyleClass("hidden"); - if (!this.currentQuery || !this._searchFinishedCallback || !this._searchResults) return; @@ -944,7 +959,7 @@ WebInspector.HeapProfileHeader.prototype = { */ _createFileWriter: function(fileName, delegate) { - return new WebInspector.ChunkedFileWriter(fileName, delegate); + return new WebInspector.FileOutputStream(fileName, delegate); }, /** @@ -1024,73 +1039,6 @@ WebInspector.HeapSnapshotLoadFromFileDelegate.prototype = { /** * @constructor - * @implements {WebInspector.OutputStream} - * @param {!string} fileName - * @param {!WebInspector.OutputStreamDelegate} delegate - */ -WebInspector.ChunkedFileWriter = function(fileName, delegate) -{ - this._fileName = fileName; - this._delegate = delegate; -} - -WebInspector.ChunkedFileWriter.prototype = { - /** - * @override - */ - startTransfer: function() - { - WebInspector.fileManager.addEventListener(WebInspector.FileManager.EventTypes.SavedURL, this._onTransferStarted, this); - WebInspector.fileManager.save(this._fileName, "", true); - }, - - /** - * @override - * @param {string} chunk - */ - transferChunk: function(chunk) - { - WebInspector.fileManager.append(this._fileName, chunk); - }, - - /** - * @override - */ - finishTransfer: function() - { - WebInspector.fileManager.removeEventListener(WebInspector.FileManager.EventTypes.AppendedToURL, this._onChunkTransferred, this); - this._delegate.onTransferFinished(this); - }, - - dispose: function() - { - }, - - /** - * @param {WebInspector.Event} event - */ - _onTransferStarted: function(event) - { - if (event.data !== this._fileName) - return; - this._delegate.onTransferStarted(this); - WebInspector.fileManager.removeEventListener(WebInspector.FileManager.EventTypes.SavedURL, this._onTransferStarted, this); - WebInspector.fileManager.addEventListener(WebInspector.FileManager.EventTypes.AppendedToURL, this._onChunkTransferred, this); - }, - - /** - * @param {WebInspector.Event} event - */ - _onChunkTransferred: function(event) - { - if (event.data !== this._fileName) - return; - this._delegate.onChunkTransferred(this); - } -} - -/** - * @constructor * @implements {WebInspector.OutputStreamDelegate} */ WebInspector.HeapSnapshotSaveToFileDelegate = function(snapshotHeader) diff --git a/Source/WebCore/inspector/front-end/HeapSnapshotWorker.js b/Source/WebCore/inspector/front-end/HeapSnapshotWorker.js index 9cb4a25ec..4e2b466d9 100644 --- a/Source/WebCore/inspector/front-end/HeapSnapshotWorker.js +++ b/Source/WebCore/inspector/front-end/HeapSnapshotWorker.js @@ -34,6 +34,7 @@ WebInspector.UIString = function(s) { return s; }; importScripts("HeapSnapshot.js"); importScripts("HeapSnapshotLoader.js"); importScripts("HeapSnapshotWorkerDispatcher.js"); +importScripts("FileUtils.js"); importScripts("utilities.js"); function postMessageWrapper(message) diff --git a/Source/WebCore/inspector/front-end/Images/statusbarButtonGlyphs2x.png b/Source/WebCore/inspector/front-end/Images/statusbarButtonGlyphs2x.png Binary files differnew file mode 100644 index 000000000..4e8a5dfd1 --- /dev/null +++ b/Source/WebCore/inspector/front-end/Images/statusbarButtonGlyphs2x.png diff --git a/Source/WebCore/inspector/front-end/IndexedDBModel.js b/Source/WebCore/inspector/front-end/IndexedDBModel.js index 60e2eea39..6f9fa4200 100644 --- a/Source/WebCore/inspector/front-end/IndexedDBModel.js +++ b/Source/WebCore/inspector/front-end/IndexedDBModel.js @@ -34,7 +34,7 @@ */ WebInspector.IndexedDBModel = function() { - this._indexedDBRequestManager = new WebInspector.IndexedDBRequestManager(); + IndexedDBAgent.enable(); WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameAdded, this._frameNavigated, this); WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameNavigated, this._frameNavigated, this); @@ -209,15 +209,12 @@ WebInspector.IndexedDBModel.prototype = { { var resourceTreeFrame = /** @type {WebInspector.ResourceTreeFrame} */ event.data; this._originRemovedFromFrame(resourceTreeFrame.id); - this._indexedDBRequestManager._frameDetached(resourceTreeFrame.id); }, _reset: function() { for (var frameId in this._frames) this._originRemovedFromFrame(frameId); - - this._indexedDBRequestManager._reset(); }, /** @@ -327,8 +324,6 @@ WebInspector.IndexedDBModel.prototype = { */ _databaseRemoved: function(securityOrigin, databaseName) { - this._indexedDBRequestManager._databaseRemoved(this._frameIdsBySecurityOrigin[securityOrigin], databaseName); - var databaseId = new WebInspector.IndexedDBModel.DatabaseId(securityOrigin, databaseName); this.dispatchEventToListeners(WebInspector.IndexedDBModel.EventTypes.DatabaseRemoved, databaseId); }, @@ -339,10 +334,16 @@ WebInspector.IndexedDBModel.prototype = { _loadDatabaseNamesForFrame: function(frameId) { /** + * @param {?Protocol.Error} error * @param {IndexedDBAgent.SecurityOriginWithDatabaseNames} securityOriginWithDatabaseNames */ - function callback(securityOriginWithDatabaseNames) + function callback(error, securityOriginWithDatabaseNames) { + if (error) { + console.error("IndexedDBAgent error: " + error); + return; + } + var databaseNames = securityOriginWithDatabaseNames.databaseNames; var oldSecurityOrigin = this._frames[frameId] ? this._frames[frameId].securityOrigin : null; if (!oldSecurityOrigin || oldSecurityOrigin !== securityOriginWithDatabaseNames.securityOrigin) { @@ -352,7 +353,7 @@ WebInspector.IndexedDBModel.prototype = { this._updateOriginDatabaseNames(securityOriginWithDatabaseNames.securityOrigin, securityOriginWithDatabaseNames.databaseNames); } - this._indexedDBRequestManager.requestDatabaseNamesForFrame(frameId, callback.bind(this)); + IndexedDBAgent.requestDatabaseNamesForFrame(frameId, callback.bind(this)); }, /** @@ -378,10 +379,16 @@ WebInspector.IndexedDBModel.prototype = { return; /** + * @param {?Protocol.Error} error * @param {IndexedDBAgent.DatabaseWithObjectStores} databaseWithObjectStores */ - function callback(databaseWithObjectStores) + function callback(error, databaseWithObjectStores) { + if (error) { + console.error("IndexedDBAgent error: " + error); + return; + } + if (!this._frames[frameId]) return; @@ -403,7 +410,7 @@ WebInspector.IndexedDBModel.prototype = { this.dispatchEventToListeners(WebInspector.IndexedDBModel.EventTypes.DatabaseLoaded, databaseModel); } - this._indexedDBRequestManager.requestDatabase(frameId, databaseId.name, callback.bind(this)); + IndexedDBAgent.requestDatabase(frameId, databaseId.name, callback.bind(this)); }, /** @@ -416,27 +423,7 @@ WebInspector.IndexedDBModel.prototype = { */ loadObjectStoreData: function(databaseId, objectStoreName, idbKeyRange, skipCount, pageSize, callback) { - var frameId = this._assertFrameId(databaseId); - if (!frameId) - return; - - /** - * @param {Array.<IndexedDBAgent.DataEntry>} dataEntries - * @param {boolean} hasMore - */ - function innerCallback(dataEntries, hasMore) - { - var entries = []; - for (var i = 0; i < dataEntries.length; ++i) { - var key = WebInspector.IndexedDBModel.idbKeyFromKey(dataEntries[i].key); - var primaryKey = WebInspector.IndexedDBModel.idbKeyFromKey(dataEntries[i].primaryKey); - var value = WebInspector.RemoteObject.fromPayload(dataEntries[i].value); - entries.push(new WebInspector.IndexedDBModel.Entry(key, primaryKey, value)); - } - callback(entries, hasMore); - } - - this._indexedDBRequestManager.requestObjectStoreData(frameId, databaseId.name, objectStoreName, idbKeyRange, skipCount, pageSize, innerCallback); + this._requestData(databaseId, databaseId.name, objectStoreName, "", idbKeyRange, skipCount, pageSize, callback); }, /** @@ -450,16 +437,40 @@ WebInspector.IndexedDBModel.prototype = { */ loadIndexData: function(databaseId, objectStoreName, indexName, idbKeyRange, skipCount, pageSize, callback) { + this._requestData(databaseId, databaseId.name, objectStoreName, indexName, idbKeyRange, skipCount, pageSize, callback); + }, + + /** + * @param {WebInspector.IndexedDBModel.DatabaseId} databaseId + * @param {string} databaseName + * @param {string} objectStoreName + * @param {string} indexName + * @param {webkitIDBKeyRange} idbKeyRange + * @param {number} skipCount + * @param {number} pageSize + * @param {function(Array.<IndexedDBAgent.DataEntry>, boolean)} callback + */ + _requestData: function(databaseId, databaseName, objectStoreName, indexName, idbKeyRange, skipCount, pageSize, callback) + { var frameId = this._assertFrameId(databaseId); if (!frameId) return; /** + * @param {?Protocol.Error} error * @param {Array.<IndexedDBAgent.DataEntry>} dataEntries * @param {boolean} hasMore */ - function innerCallback(dataEntries, hasMore) + function innerCallback(error, dataEntries, hasMore) { + if (error) { + console.error("IndexedDBAgent error: " + error); + return; + } + + if (!this._frames[frameId]) + return; + var entries = []; for (var i = 0; i < dataEntries.length; ++i) { var key = WebInspector.IndexedDBModel.idbKeyFromKey(dataEntries[i].key); @@ -470,7 +481,8 @@ WebInspector.IndexedDBModel.prototype = { callback(entries, hasMore); } - this._indexedDBRequestManager.requestIndexData(frameId, databaseId.name, objectStoreName, indexName, idbKeyRange, skipCount, pageSize, innerCallback.bind(this)); + var keyRange = WebInspector.IndexedDBModel.keyRangeFromIDBKeyRange(idbKeyRange); + IndexedDBAgent.requestData(frameId, databaseName, objectStoreName, indexName, skipCount, pageSize, keyRange ? keyRange : undefined, innerCallback.bind(this)); } } @@ -578,317 +590,3 @@ WebInspector.IndexedDBModel.Index.prototype = { return WebInspector.IndexedDBModel.keyPathStringFromIDBKeyPath(this.keyPath); } } - -/** - * @constructor - */ -WebInspector.IndexedDBRequestManager = function() -{ - this._lastRequestId = 0; - this._requestDatabaseNamesForFrameCallbacks = {}; - this._requestDatabaseCallbacks = {}; - this._requestDataCallbacks = {}; - - 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) - return; - - request.callback(securityOriginWithDatabaseNames); - }, - - /** - * @param {string} frameId - * @param {string} databaseName - * @param {function(IndexedDBAgent.DatabaseWithObjectStores)} callback - */ - requestDatabase: function(frameId, databaseName, callback) - { - var requestId = this._requestId(); - var request = new WebInspector.IndexedDBRequestManager.DatabaseRequest(frameId, databaseName, callback); - this._requestDatabaseCallbacks[requestId] = request; - - function innerCallback(error) - { - if (error) { - console.error("IndexedDBAgent error: " + error); - return; - } - } - - IndexedDBAgent.requestDatabase(requestId, frameId, databaseName, innerCallback); - }, - - /** - * @param {number} requestId - * @param {IndexedDBAgent.DatabaseWithObjectStores} databaseWithObjectStores - */ - _databaseLoaded: function(requestId, databaseWithObjectStores) - { - var request = this._requestDatabaseCallbacks[requestId]; - if (!request) - return; - - request.callback(databaseWithObjectStores); - }, - - /** - * @param {string} frameId - * @param {string} databaseName - * @param {string} objectStoreName - * @param {string} indexName - * @param {webkitIDBKeyRange} idbKeyRange - * @param {number} skipCount - * @param {number} pageSize - * @param {function(Array.<IndexedDBAgent.DataEntry>, boolean)} callback - */ - _requestData: function(frameId, databaseName, objectStoreName, indexName, idbKeyRange, skipCount, pageSize, callback) - { - var requestId = this._requestId(); - var request = new WebInspector.IndexedDBRequestManager.DataRequest(frameId, databaseName, objectStoreName, indexName, callback); - this._requestDataCallbacks[requestId] = request; - - function innerCallback(error) - { - if (error) { - console.error("IndexedDBAgent error: " + error); - return; - } - } - - var keyRange = WebInspector.IndexedDBModel.keyRangeFromIDBKeyRange(idbKeyRange); - IndexedDBAgent.requestData(requestId, frameId, databaseName, objectStoreName, indexName, skipCount, pageSize, keyRange ? keyRange : undefined, innerCallback); - }, - - /** - * @param {string} frameId - * @param {string} databaseName - * @param {string} objectStoreName - * @param {webkitIDBKeyRange} idbKeyRange - * @param {number} skipCount - * @param {number} pageSize - * @param {function(Array.<IndexedDBAgent.DataEntry>, boolean)} callback - */ - requestObjectStoreData: function(frameId, databaseName, objectStoreName, idbKeyRange, skipCount, pageSize, callback) - { - this._requestData(frameId, databaseName, objectStoreName, "", idbKeyRange, skipCount, pageSize, callback); - }, - - /** - * @param {number} requestId - * @param {Array.<IndexedDBAgent.DataEntry>} dataEntries - * @param {boolean} hasMore - */ - _objectStoreDataLoaded: function(requestId, dataEntries, hasMore) - { - var request = this._requestDataCallbacks[requestId]; - if (!request.callback) - return; - - request.callback(dataEntries, hasMore); - }, - - /** - * @param {string} frameId - * @param {string} databaseName - * @param {string} objectStoreName - * @param {string} indexName - * @param {webkitIDBKeyRange} idbKeyRange - * @param {number} skipCount - * @param {number} pageSize - * @param {function(Array.<IndexedDBAgent.DataEntry>, boolean)} callback - */ - requestIndexData: function(frameId, databaseName, objectStoreName, indexName, idbKeyRange, skipCount, pageSize, callback) - { - this._requestData(frameId, databaseName, objectStoreName, indexName, idbKeyRange, skipCount, pageSize, callback); - }, - - /** - * @param {number} requestId - * @param {Array.<IndexedDBAgent.DataEntry>} dataEntries - * @param {boolean} hasMore - */ - _indexDataLoaded: function(requestId, dataEntries, hasMore) - { - var request = this._requestDataCallbacks[requestId]; - if (!request.callback) - return; - - request.callback(dataEntries, hasMore); - }, - - /** - * @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]; - } - - for (var requestId in this._requestDatabaseCallbacks) { - if (this._requestDatabaseCallbacks[requestId].frameId === frameId) - delete this._requestDatabaseCallbacks[requestId]; - } - - for (var requestId in this._requestDataCallbacks) { - if (this._requestDataCallbacks[requestId].frameId === frameId) - delete this._requestDataCallbacks[requestId]; - } - }, - - /** - * @param {string} frameId - */ - _databaseRemoved: function(frameId, databaseName) - { - for (var requestId in this._requestDatabaseCallbacks) { - if (this._requestDatabaseCallbacks[requestId].frameId === frameId && this._requestDatabaseCallbacks[requestId].databaseName === databaseName) - delete this._requestDatabaseCallbacks[requestId]; - } - - for (var requestId in this._requestDataCallbacks) { - if (this._requestDataCallbacks[requestId].frameId === frameId && this._requestDataCallbacks[requestId].databaseName === databaseName) - delete this._requestDataCallbacks[requestId]; - } - }, - - _reset: function() - { - this._requestDatabaseNamesForFrameCallbacks = {}; - this._requestDatabaseCallbacks = {}; - this._requestDataCallbacks = {}; - } -} - -/** - * @constructor - * @param {string} frameId - * @param {function(IndexedDBAgent.SecurityOriginWithDatabaseNames)} callback -*/ -WebInspector.IndexedDBRequestManager.DatabasesForFrameRequest = function(frameId, callback) -{ - this.frameId = frameId; - this.callback = callback; -} - -/** - * @constructor - * @param {string} frameId - * @param {string} databaseName - * @param {function(IndexedDBAgent.DatabaseWithObjectStores)} callback - */ -WebInspector.IndexedDBRequestManager.DatabaseRequest = function(frameId, databaseName, callback) -{ - this.frameId = frameId; - this.databaseName = databaseName; - this.callback = callback; -} - -/** - * @constructor - * @param {string} frameId - * @param {string} databaseName - * @param {string} objectStoreName - * @param {string} indexName - * @param {function(Array.<IndexedDBAgent.DataEntry>, boolean)} callback - */ -WebInspector.IndexedDBRequestManager.DataRequest = function(frameId, databaseName, objectStoreName, indexName, callback) -{ - this.frameId = frameId; - this.databaseName = databaseName; - this.objectStoreName = objectStoreName; - this.indexName = indexName; - 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); - }, - - /** - * @param {number} requestId - * @param {IndexedDBAgent.DatabaseWithObjectStores} databaseWithObjectStores - */ - databaseLoaded: function(requestId, databaseWithObjectStores) - { - this._agentWrapper._databaseLoaded(requestId, databaseWithObjectStores); - }, - - /** - * @param {number} requestId - * @param {Array.<IndexedDBAgent.DataEntry>} dataEntries - * @param {boolean} hasMore - */ - objectStoreDataLoaded: function(requestId, dataEntries, hasMore) - { - this._agentWrapper._objectStoreDataLoaded(requestId, dataEntries, hasMore); - }, - - /** - * @param {number} requestId - * @param {Array.<IndexedDBAgent.DataEntry>} dataEntries - * @param {boolean} hasMore - */ - indexDataLoaded: function(requestId, dataEntries, hasMore) - { - this._agentWrapper._indexDataLoaded(requestId, dataEntries, hasMore); - } -} - diff --git a/Source/WebCore/inspector/front-end/JavaScriptSource.js b/Source/WebCore/inspector/front-end/JavaScriptSource.js index 2ac4953ce..a641c2d18 100644 --- a/Source/WebCore/inspector/front-end/JavaScriptSource.js +++ b/Source/WebCore/inspector/front-end/JavaScriptSource.js @@ -34,11 +34,10 @@ * @param {string} url * @param {WebInspector.Resource} resource * @param {WebInspector.ContentProvider} contentProvider - * @param {WebInspector.SourceMapping} sourceMapping */ -WebInspector.JavaScriptSource = function(url, resource, contentProvider, sourceMapping, isEditable) +WebInspector.JavaScriptSource = function(url, resource, contentProvider, isEditable) { - WebInspector.UISourceCode.call(this, url, resource, contentProvider, sourceMapping); + WebInspector.UISourceCode.call(this, url, resource, contentProvider); this._isEditable = isEditable; } diff --git a/Source/WebCore/inspector/front-end/Linkifier.js b/Source/WebCore/inspector/front-end/Linkifier.js index fab18bae1..d08280b4c 100644 --- a/Source/WebCore/inspector/front-end/Linkifier.js +++ b/Source/WebCore/inspector/front-end/Linkifier.js @@ -97,7 +97,7 @@ WebInspector.Linkifier.prototype = { _updateAnchor: function(anchor, uiLocation) { anchor.preferredPanel = "scripts"; - anchor.href = uiLocation.uiSourceCode.url; + anchor.href = sanitizeHref(uiLocation.uiSourceCode.url); anchor.uiSourceCode = uiLocation.uiSourceCode; anchor.lineNumber = uiLocation.lineNumber; this._formatter.formatLiveAnchor(anchor, uiLocation); diff --git a/Source/WebCore/inspector/front-end/NativeMemorySnapshotView.js b/Source/WebCore/inspector/front-end/NativeMemorySnapshotView.js index 1b0ce1e06..e32959268 100644 --- a/Source/WebCore/inspector/front-end/NativeMemorySnapshotView.js +++ b/Source/WebCore/inspector/front-end/NativeMemorySnapshotView.js @@ -216,8 +216,9 @@ WebInspector.MemoryBlockViewProperties._initialize = function() WebInspector.MemoryBlockViewProperties._standardBlocks[name] = new WebInspector.MemoryBlockViewProperties(fillStyle, name, WebInspector.UIString(description)); } addBlock("hsl( 0, 0%, 100%)", "ProcessPrivateMemory", "Total"); + addBlock("hsl( 0, 0%, 80%)", "OwnersTypePlaceholder", "OwnersTypePlaceholder"); addBlock("hsl( 0, 0%, 80%)", "Other", "Other"); - addBlock("hsl(300, 30%, 80%)", "DOM", "DOM tree structures"); + addBlock("hsl(300, 30%, 80%)", "Page", "Page's structures"); addBlock("hsl( 90, 60%, 80%)", "JSHeapAllocated", "JavaScript heap"); addBlock("hsl( 90, 80%, 80%)", "JSHeapUsed", "Used JavaScript heap"); addBlock("hsl( 90, 30%, 80%)", "JSExternalResources", "JavaScript external resources"); diff --git a/Source/WebCore/inspector/front-end/NetworkPanel.js b/Source/WebCore/inspector/front-end/NetworkPanel.js index b0b11e011..5c80ac178 100644 --- a/Source/WebCore/inspector/front-end/NetworkPanel.js +++ b/Source/WebCore/inspector/front-end/NetworkPanel.js @@ -29,9 +29,6 @@ */ importScript("RequestView.js"); -importScript("ResourceView.js"); -importScript("FontView.js"); -importScript("ImageView.js"); importScript("NetworkItemView.js"); importScript("RequestCookiesView.js"); importScript("RequestHeadersView.js"); @@ -1928,8 +1925,7 @@ WebInspector.NetworkDataGridNode.prototype = { this._nameCell.appendChild(iconElement); this._nameCell.appendChild(document.createTextNode(this._fileName())); - - var subtitle = WebInspector.displayDomain(this._request.parsedURL.host); + var subtitle = this._request.parsedURL.host === WebInspector.inspectedPageDomain ? "" : this._request.parsedURL.host; if (this._request.parsedURL.path) subtitle += this._request.folder; diff --git a/Source/WebCore/inspector/front-end/NetworkUISourceCodeProvider.js b/Source/WebCore/inspector/front-end/NetworkUISourceCodeProvider.js new file mode 100644 index 000000000..f1625f64c --- /dev/null +++ b/Source/WebCore/inspector/front-end/NetworkUISourceCodeProvider.js @@ -0,0 +1,96 @@ +/* + * 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 {WebInspector.Workspace} workspace + */ +WebInspector.NetworkUISourceCodeProvider = function(workspace) +{ + this._workspace = workspace; + WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.ResourceAdded, this._resourceAdded, this); + this._workspace.addEventListener(WebInspector.Workspace.Events.ProjectWillReset, this._projectWillReset, this); + this._workspace.addEventListener(WebInspector.Workspace.Events.ProjectDidReset, this._projectDidReset, this); + + this._uiSourceCodeForResource = {}; +} + +WebInspector.NetworkUISourceCodeProvider.prototype = { + _populate: function() + { + function populateFrame(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); + }, + + /** + * @param {WebInspector.Event} event + */ + _resourceAdded: function(event) + { + var resource = /** @type {WebInspector.Resource} */ event.data; + if (this._uiSourceCodeForResource[resource.url]) + return; + var uiSourceCode; + switch (resource.type) { + case WebInspector.resourceTypes.Stylesheet: + uiSourceCode = new WebInspector.StyleSource(resource); + break; + case WebInspector.resourceTypes.Document: + uiSourceCode = new WebInspector.JavaScriptSource(resource.url, resource, resource, false); + break; + case WebInspector.resourceTypes.Script: + uiSourceCode = new WebInspector.JavaScriptSource(resource.url, resource, resource, true); + break; + } + if (uiSourceCode) { + this._uiSourceCodeForResource[resource.url] = uiSourceCode; + this._workspace.project().addUISourceCode(uiSourceCode); + } + }, + + _projectWillReset: function() + { + this._uiSourceCodeForResource = {}; + }, + + _projectDidReset: function() + { + this._populate(); + } +} diff --git a/Source/WebCore/inspector/front-end/ObjectPropertiesSection.js b/Source/WebCore/inspector/front-end/ObjectPropertiesSection.js index f1c5069d7..e9a097045 100644 --- a/Source/WebCore/inspector/front-end/ObjectPropertiesSection.js +++ b/Source/WebCore/inspector/front-end/ObjectPropertiesSection.js @@ -60,8 +60,7 @@ WebInspector.ObjectPropertiesSection.prototype = { { var contextMenu = new WebInspector.ContextMenu(); contextMenu.appendApplicableItems(this.object); - if (!contextMenu.isEmpty()) - contextMenu.show(event); + contextMenu.show(event); }, onpopulate: function() @@ -234,18 +233,14 @@ WebInspector.ObjectPropertyTreeElement.prototype = { } 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.valueElement.addEventListener("contextmenu", this._contextMenuFired.bind(this, this.property.value), false); this.valueElement.title = description || ""; this.listItemElement.removeChildren(); @@ -256,42 +251,10 @@ WebInspector.ObjectPropertyTreeElement.prototype = { this.hasChildren = this.property.value.hasChildren && !this.property.wasThrown; }, - _contextMenuEventFired: function(event) + _contextMenuFired: function(value, 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 didGetDetails(error, response) - { - if (error) { - console.error(error); - return; - } - WebInspector.panel("scripts").showFunctionDefinition(response.location); - } - - function revealFunction() - { - DebuggerAgent.getFunctionDetails(this.property.value.objectId, didGetDetails.bind(this)); - } - var contextMenu = new WebInspector.ContextMenu(); - contextMenu.appendItem(WebInspector.UIString("Show function definition"), revealFunction.bind(this)); + contextMenu.appendApplicableItems(value); contextMenu.show(event); }, diff --git a/Source/WebCore/inspector/front-end/ParsedURL.js b/Source/WebCore/inspector/front-end/ParsedURL.js index a05a4c398..49d1fde76 100644 --- a/Source/WebCore/inspector/front-end/ParsedURL.js +++ b/Source/WebCore/inspector/front-end/ParsedURL.js @@ -96,16 +96,17 @@ WebInspector.ParsedURL = function(url) WebInspector.ParsedURL.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.startsWith("data:") || trimmedHref.startsWith("javascript:") || trimmedHref.startsWith("blob:")) + if (trimmedHref.startsWith("data:") || trimmedHref.startsWith("blob:") || trimmedHref.startsWith("javascript:")) return href; - } + + // Return absolute URLs as-is. + var parsedHref = trimmedHref.asParsedURL(); + if (parsedHref && parsedHref.scheme) + return trimmedHref; + } else + return baseURL; var parsedURL = baseURL.asParsedURL(); if (parsedURL) { @@ -155,7 +156,7 @@ WebInspector.ParsedURL.prototype = { this._displayName = this.lastPathComponent; if (!this._displayName) - this._displayName = WebInspector.displayDomain(this.host); + this._displayName = this.host; if (!this._displayName && this.url) this._displayName = this.url.trimURL(WebInspector.inspectedPageDomain ? WebInspector.inspectedPageDomain : ""); if (this._displayName === "/") diff --git a/Source/WebCore/inspector/front-end/Popover.js b/Source/WebCore/inspector/front-end/Popover.js index c74987795..5dfb33fe4 100644 --- a/Source/WebCore/inspector/front-end/Popover.js +++ b/Source/WebCore/inspector/front-end/Popover.js @@ -217,7 +217,7 @@ WebInspector.PopoverHelper.prototype = { _mouseDown: function(event) { - if (this._disableOnClick) + if (this._disableOnClick || !event.target.isSelfOrDescendant(this._hoverElement)) this.hidePopover(); else { this._killHidePopoverTimer(); diff --git a/Source/WebCore/inspector/front-end/ProfilesPanel.js b/Source/WebCore/inspector/front-end/ProfilesPanel.js index 09b0fb944..6a8b4d89f 100644 --- a/Source/WebCore/inspector/front-end/ProfilesPanel.js +++ b/Source/WebCore/inspector/front-end/ProfilesPanel.js @@ -248,6 +248,8 @@ WebInspector.ProfilesPanel = function() this._registerProfileType(new WebInspector.HeapSnapshotProfileType()); if (WebInspector.experimentsSettings.nativeMemorySnapshots.isEnabled()) this._registerProfileType(new WebInspector.NativeMemoryProfileType()); + if (WebInspector.experimentsSettings.webGLInspection.isEnabled()) + this._registerProfileType(new WebInspector.WebGLProfileType()); InspectorBackend.registerProfilerDispatcher(new WebInspector.ProfilerDispatcher(this)); @@ -1317,3 +1319,4 @@ importScript("HeapSnapshotWorkerDispatcher.js"); importScript("NativeMemorySnapshotView.js"); importScript("ProfileLauncherView.js"); importScript("TopDownProfileDataGridTree.js"); +importScript("WebGLProfileView.js"); diff --git a/Source/WebCore/inspector/front-end/RawSourceCode.js b/Source/WebCore/inspector/front-end/RawSourceCode.js index 7e1b44cda..e69de29bb 100644 --- a/Source/WebCore/inspector/front-end/RawSourceCode.js +++ b/Source/WebCore/inspector/front-end/RawSourceCode.js @@ -1,145 +0,0 @@ -/* - * 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.NetworkRequest} request - * @param {WebInspector.SourceMapping} sourceMapping - */ -WebInspector.RawSourceCode = function(id, script, resource, request, sourceMapping) -{ - this.id = id; - this.url = script.sourceURL; - this.isContentScript = script.isContentScript; - this._scripts = [script]; - this._resource = resource; - this._pendingRequest = request; - this._sourceMapping = sourceMapping; - - this._uiSourceCode = null; - if (this._pendingRequest) - this._pendingRequest.addEventListener(WebInspector.NetworkRequest.Events.FinishedLoading, this._finishedLoading, this); - else - this._uiSourceCode = this._createUISourceCode(); -} - -WebInspector.RawSourceCode.Events = { - UISourceCodeChanged: "us-source-code-changed" -} - -WebInspector.RawSourceCode.prototype = { - /** - * @param {WebInspector.Script} script - */ - addScript: function(script) - { - this._scripts.push(script); - if (this._temporaryUISourceCode) { - var oldUISourceCode = this._temporaryUISourceCode; - this._temporaryUISourceCode = this._createUISourceCode(); - this.dispatchEventToListeners(WebInspector.RawSourceCode.Events.UISourceCodeChanged, { uiSourceCode: this._temporaryUISourceCode, oldUISourceCode: oldUISourceCode }); - } - }, - - /** - * @param {WebInspector.DebuggerModel.Location} rawLocation - * @return {WebInspector.UILocation} - */ - rawLocationToUILocation: function(rawLocation) - { - var uiSourceCode = this._uiSourceCode || this._temporaryUISourceCode; - if (!uiSourceCode) { - this._temporaryUISourceCode = this._createUISourceCode(); - uiSourceCode = this._temporaryUISourceCode; - this.dispatchEventToListeners(WebInspector.RawSourceCode.Events.UISourceCodeChanged, { uiSourceCode: uiSourceCode }); - } - return new WebInspector.UILocation(uiSourceCode, rawLocation.lineNumber, rawLocation.columnNumber || 0); - }, - - /** - * @return {WebInspector.UISourceCode} - */ - _createUISourceCode: function() - { - var isStandaloneScript = this._scripts.length === 1 && !this._scripts[0].isInlineScript(); - - var contentProvider; - if (this._resource) - contentProvider = this._resource; - else if (isStandaloneScript) - contentProvider = this._scripts[0]; - else - contentProvider = new WebInspector.ConcatenatedScriptsContentProvider(this._scripts); - - var uiSourceCode = new WebInspector.JavaScriptSource(this.url, this._resource, contentProvider, this._sourceMapping, isStandaloneScript); - uiSourceCode.isContentScript = this.isContentScript; - return uiSourceCode; - }, - - /** - * @param {WebInspector.UISourceCode} uiSourceCode - * @param {number} lineNumber - * @param {number} columnNumber - * @return {WebInspector.RawLocation} - */ - uiLocationToRawLocation: function(uiSourceCode, lineNumber, columnNumber) - { - if (this.url) - return WebInspector.debuggerModel.createRawLocationByURL(this.url, lineNumber, columnNumber); - return WebInspector.debuggerModel.createRawLocation(this._scripts[0], lineNumber, columnNumber); - }, - - /** - * @return {WebInspector.UISourceCode|null} - */ - uiSourceCode: function() - { - return this._uiSourceCode || this._temporaryUISourceCode; - }, - - _finishedLoading: function(event) - { - this._resource = WebInspector.resourceForURL(this._pendingRequest.url); - delete this._pendingRequest; - var oldUISourceCode = this._uiSourceCode || this._temporaryUISourceCode; - delete this._temporaryUISourceCode; - this._uiSourceCode = this._createUISourceCode(); - this.dispatchEventToListeners(WebInspector.RawSourceCode.Events.UISourceCodeChanged, { uiSourceCode: this._uiSourceCode, oldUISourceCode: oldUISourceCode }); - } -} - -WebInspector.RawSourceCode.prototype.__proto__ = WebInspector.Object.prototype; diff --git a/Source/WebCore/inspector/front-end/Resource.js b/Source/WebCore/inspector/front-end/Resource.js index 8329a0b7a..9fa6b8c0a 100644 --- a/Source/WebCore/inspector/front-end/Resource.js +++ b/Source/WebCore/inspector/front-end/Resource.js @@ -311,13 +311,12 @@ WebInspector.Resource.prototype = { this._contentRequested = true; /** - * @param {?Protocol.Error} error * @param {string} content * @param {boolean} contentEncoded */ - function callback(error, content, contentEncoded) + function contentLoaded(content, contentEncoded) { - this._content = error ? null : content; + this._content = content; this._contentEncoded = contentEncoded; var callbacks = this._pendingContentCallbacks.slice(); for (var i = 0; i < callbacks.length; ++i) @@ -325,7 +324,34 @@ WebInspector.Resource.prototype = { this._pendingContentCallbacks.length = 0; delete this._contentRequested; } - PageAgent.getResourceContent(this.frameId, this.url, callback.bind(this)); + + /** + * @param {?Protocol.Error} error + * @param {string} content + * @param {boolean} contentEncoded + */ + function resourceContentLoaded(error, content, contentEncoded) + { + if (error) + console.error("Resource content request failed: " + error); + contentLoaded.call(this, error ? null : content, contentEncoded); + } + + if (this.request) { + /** + * @param {string} content + * @param {boolean} contentEncoded + * @param {string} mimeType + */ + function requestContentLoaded(content, contentEncoded, mimeType) + { + contentLoaded.call(this, content, contentEncoded); + } + + this.request.requestContent(requestContentLoaded.bind(this)); + return; + } + PageAgent.getResourceContent(this.frameId, this.url, resourceContentLoaded.bind(this)); }, /** diff --git a/Source/WebCore/inspector/front-end/ResourceScriptMapping.js b/Source/WebCore/inspector/front-end/ResourceScriptMapping.js index 6e2519f26..02eb62e72 100644 --- a/Source/WebCore/inspector/front-end/ResourceScriptMapping.js +++ b/Source/WebCore/inspector/front-end/ResourceScriptMapping.js @@ -30,17 +30,21 @@ /** * @constructor - * @extends {WebInspector.Object} * @implements {WebInspector.SourceMapping} - * @implements {WebInspector.UISourceCodeProvider} + * @param {WebInspector.Workspace} workspace */ -WebInspector.ResourceScriptMapping = function() +WebInspector.ResourceScriptMapping = function(workspace) { - this._rawSourceCodes = []; - this._rawSourceCodeForScriptId = {}; - this._rawSourceCodeForURL = {}; - this._rawSourceCodeForDocumentURL = {}; - this._rawSourceCodeForUISourceCode = new Map(); + this._workspace = workspace; + this._workspace.addEventListener(WebInspector.Workspace.Events.ProjectWillReset, this._reset, this); + this._workspace.addEventListener(WebInspector.UISourceCodeProvider.Events.UISourceCodeAdded, this._uiSourceCodeAddedToWorkspace, this); + + /** @type {Object.<string, WebInspector.UISourceCode>} */ + this._uiSourceCodeForScriptId = {}; + this._scriptIdForUISourceCode = new Map(); + this._temporaryUISourceCodes = new Map(); + /** @type {Object.<string, number>} */ + this._nextDynamicScriptIndexForURL = {}; } WebInspector.ResourceScriptMapping.prototype = { @@ -51,8 +55,9 @@ WebInspector.ResourceScriptMapping.prototype = { rawLocationToUILocation: function(rawLocation) { var debuggerModelLocation = /** @type {WebInspector.DebuggerModel.Location} */ rawLocation; - var rawSourceCode = this._rawSourceCodeForScriptId[debuggerModelLocation.scriptId]; - return rawSourceCode.rawLocationToUILocation(debuggerModelLocation); + var script = WebInspector.debuggerModel.scriptForId(debuggerModelLocation.scriptId); + var uiSourceCode = this._uiSourceCodeForScriptId[debuggerModelLocation.scriptId]; + return new WebInspector.UILocation(uiSourceCode, debuggerModelLocation.lineNumber, debuggerModelLocation.columnNumber || 0); }, /** @@ -63,164 +68,157 @@ WebInspector.ResourceScriptMapping.prototype = { */ uiLocationToRawLocation: function(uiSourceCode, lineNumber, columnNumber) { - var rawSourceCode = this._rawSourceCodeForUISourceCode.get(uiSourceCode); - return rawSourceCode.uiLocationToRawLocation(uiSourceCode, lineNumber, columnNumber); + var scriptId = this._scriptIdForUISourceCode.get(uiSourceCode); + var script = WebInspector.debuggerModel.scriptForId(scriptId); + return WebInspector.debuggerModel.createRawLocation(script, lineNumber, columnNumber); }, /** - * @return {Array.<WebInspector.UISourceCode>} + * @param {WebInspector.Script} script */ - uiSourceCodes: function() + addScript: function(script) { - var result = []; - for (var i = 0; i < this._rawSourceCodes.length; ++i) { - var uiSourceCode = this._rawSourceCodes[i].uiSourceCode(); - if (uiSourceCode) - result.push(uiSourceCode); + console.assert(!this._uiSourceCodeForScriptId[script.scriptId]); + + var isDynamicScript = false; + if (!script.isAnonymousScript()) { + var uiSourceCode = this._workspace.uiSourceCodeForURL(script.sourceURL); + isDynamicScript = !!uiSourceCode && uiSourceCode.contentType() === WebInspector.resourceTypes.Document && !script.isInlineScript(); + if (uiSourceCode && !isDynamicScript && !this._temporaryUISourceCodes.get(uiSourceCode)) + this._bindUISourceCodeToScripts(uiSourceCode, [script]); } - return result; + if (!this._uiSourceCodeForScriptId[script.scriptId]) + this._addOrReplaceTemporaryUISourceCode(script, isDynamicScript); + + console.assert(this._uiSourceCodeForScriptId[script.scriptId]); }, /** - * @param {WebInspector.Script} script + * @param {WebInspector.UISourceCode} uiSourceCode + * @param {Array.<WebInspector.Script>} scripts */ - addScript: function(script) + _bindUISourceCodeToScripts: function(uiSourceCode, scripts) { - var resource = null; - var request = null; - if (!script.isAnonymousScript()) { - // First lookup the resource that has already been loaded. - resource = WebInspector.resourceForURL(script.sourceURL); - // Ignore resource in case it has not yet finished loading. - if (resource && resource.request && !resource.request.finished) - resource = null; - // Only bind inline and standalone scripts. - if (resource && !this._shouldBindScriptToContentProvider(script, resource)) - resource = null; - if (!resource) { - // When there is no resource, lookup in-flight requests. - request = WebInspector.networkManager.inflightRequestForURL(script.sourceURL); - // Only bind inline and standalone scripts. - if (request && !this._shouldBindScriptToContentProvider(script, request)) - request = null; - } - } - console.assert(!resource || !request); - - var isInlineScript = script.isInlineScript() && (request || resource); - // If either of these exists, we bind script to the resource. - if (isInlineScript) { - var rawSourceCode = this._rawSourceCodeForDocumentURL[script.sourceURL]; - if (rawSourceCode) { - rawSourceCode.addScript(script); - this._bindScriptToRawSourceCode(script, rawSourceCode); - return; - } - } - - var rawSourceCode = new WebInspector.RawSourceCode(script.scriptId, script, resource, request, this); - this._rawSourceCodes.push(rawSourceCode); - this._bindScriptToRawSourceCode(script, rawSourceCode); - if (isInlineScript) - this._rawSourceCodeForDocumentURL[script.sourceURL] = rawSourceCode; + console.assert(scripts.length); - if (rawSourceCode.uiSourceCode()) - this._uiSourceCodeAdded(rawSourceCode, rawSourceCode.uiSourceCode()); - rawSourceCode.addEventListener(WebInspector.RawSourceCode.Events.UISourceCodeChanged, this._handleUISourceCodeChanged, this); + for (var i = 0; i < scripts.length; ++i) { + this._uiSourceCodeForScriptId[scripts[i].scriptId] = uiSourceCode; + scripts[i].setSourceMapping(this); + } + uiSourceCode.isContentScript = scripts[0].isContentScript; + uiSourceCode.setSourceMapping(this); + this._scriptIdForUISourceCode.put(uiSourceCode, scripts[0].scriptId); }, /** - * @param {WebInspector.Script} script - * @param {WebInspector.ContentProvider} contentProvider - * @return {boolean} + * @param {string} sourceURL + * @param {boolean} isInlineScript + * @return {Array.<WebInspector.Script>} */ - _shouldBindScriptToContentProvider: function(script, contentProvider) + _scriptsForSourceURL: function(sourceURL, isInlineScript) { - if (script.isInlineScript()) - return contentProvider.contentType() === WebInspector.resourceTypes.Document; - return contentProvider.contentType() === WebInspector.resourceTypes.Script; + function filter(script) + { + return script.sourceURL === sourceURL && script.isInlineScript() === isInlineScript; + } + + return Object.values(WebInspector.debuggerModel.scripts).filter(filter); }, /** - * @param {WebInspector.Event} event + * @param {WebInspector.Script} script + * @param {boolean} isDynamicScript */ - _handleUISourceCodeChanged: function(event) + _addOrReplaceTemporaryUISourceCode: function(script, isDynamicScript) { - var rawSourceCode = /** @type {WebInspector.RawSourceCode} */ event.target; - var uiSourceCode = /** @type {WebInspector.UISourceCode} */ event.data.uiSourceCode; - var oldUISourceCode = /** @type {WebInspector.UISourceCode} */ event.data.oldUISourceCode; - if (!oldUISourceCode) - this._uiSourceCodeAdded(rawSourceCode, uiSourceCode); + var scripts = script.isInlineScript() ? this._scriptsForSourceURL(script.sourceURL, true) : [script]; + + var oldUISourceCode; + for (var i = 0; i < scripts.length; ++i) { + oldUISourceCode = this._uiSourceCodeForScriptId[scripts[i].scriptId]; + if (oldUISourceCode) + break; + } + console.assert(!oldUISourceCode || this._temporaryUISourceCodes.get(oldUISourceCode)); + + var contentProvider = script.isInlineScript() ? new WebInspector.ConcatenatedScriptsContentProvider(scripts) : script; + var url = script.sourceURL; + if (isDynamicScript) { + var nextIndex = this._nextDynamicScriptIndexForURL[script.sourceURL] || 1; + url += " (" + nextIndex + ")"; + this._nextDynamicScriptIndexForURL[script.sourceURL] = nextIndex + 1; + } + var uiSourceCode = new WebInspector.JavaScriptSource(url, null, contentProvider, !script.isInlineScript()); + this._temporaryUISourceCodes.put(uiSourceCode, uiSourceCode); + this._bindUISourceCodeToScripts(uiSourceCode, scripts); + + if (!script.sourceURL) + return uiSourceCode; + + if (oldUISourceCode) + this._uiSourceCodeReplaced(oldUISourceCode, uiSourceCode); else - this._uiSourceCodeReplaced(rawSourceCode, oldUISourceCode, uiSourceCode); + this._workspace.project().addUISourceCode(uiSourceCode); + return uiSourceCode; }, - /** - * @param {WebInspector.RawSourceCode} rawSourceCode - * @paran {WebInspector.UISourceCode} uiSourceCode - */ - _uiSourceCodeAdded: function(rawSourceCode, uiSourceCode) + _uiSourceCodeAddedToWorkspace: function(event) { - if (!uiSourceCode.url) + var uiSourceCode = /** @type {WebInspector.UISourceCode} */ event.data; + console.assert(!this._scriptIdForUISourceCode.get(uiSourceCode) || this._temporaryUISourceCodes.get(uiSourceCode)); + if (!uiSourceCode.url || this._temporaryUISourceCodes.get(uiSourceCode)) return; - this._rawSourceCodeForUISourceCode.put(uiSourceCode, rawSourceCode); - this.dispatchEventToListeners(WebInspector.UISourceCodeProvider.Events.UISourceCodeAdded, uiSourceCode); + this._addUISourceCode(uiSourceCode); }, /** - * @param {WebInspector.RawSourceCode} rawSourceCode - * @param {WebInspector.UISourceCode} oldUISourceCode * @param {WebInspector.UISourceCode} uiSourceCode */ - _uiSourceCodeReplaced: function(rawSourceCode, oldUISourceCode, uiSourceCode) + _addUISourceCode: function(uiSourceCode) { - if (!uiSourceCode.url) + var isInlineScript; + switch (uiSourceCode.contentType()) { + case WebInspector.resourceTypes.Document: + isInlineScript = true; + break; + case WebInspector.resourceTypes.Script: + isInlineScript = false; + break; + default: return; - this._rawSourceCodeForUISourceCode.remove(oldUISourceCode); - this._rawSourceCodeForUISourceCode.put(uiSourceCode, rawSourceCode); + } - for (var i = 0; i < rawSourceCode._scripts.length; ++i) - rawSourceCode._scripts[i].setSourceMapping(this); + var scripts = this._scriptsForSourceURL(uiSourceCode.url, isInlineScript); + if (!scripts.length) + return; - var data = { oldUISourceCode: oldUISourceCode, uiSourceCode: uiSourceCode }; - this.dispatchEventToListeners(WebInspector.UISourceCodeProvider.Events.UISourceCodeReplaced, data); - }, + var oldUISourceCode = this._uiSourceCodeForScriptId[scripts[0].scriptId]; + this._bindUISourceCodeToScripts(uiSourceCode, scripts); - /** - * @param {WebInspector.RawSourceCode} rawSourceCode - * @paran {WebInspector.UISourceCode} uiSourceCode - */ - _uiSourceCodeRemoved: function(rawSourceCode, uiSourceCode) - { - if (!uiSourceCode.url) - return; - this._rawSourceCodeForUISourceCode.remove(uiSourceCode); + if (oldUISourceCode) { + console.assert(this._temporaryUISourceCodes.get(oldUISourceCode)); + this._uiSourceCodeReplaced(oldUISourceCode, uiSourceCode); + } + + console.assert(this._scriptIdForUISourceCode.get(uiSourceCode) && !this._temporaryUISourceCodes.get(uiSourceCode)); }, /** - * @param {WebInspector.Script} script - * @param {WebInspector.RawSourceCode} rawSourceCode + * @param {WebInspector.UISourceCode} oldUISourceCode + * @param {WebInspector.UISourceCode} uiSourceCode */ - _bindScriptToRawSourceCode: function(script, rawSourceCode) + _uiSourceCodeReplaced: function(oldUISourceCode, uiSourceCode) { - this._rawSourceCodeForScriptId[script.scriptId] = rawSourceCode; - this._rawSourceCodeForURL[script.sourceURL] = rawSourceCode; - script.setSourceMapping(this); + this._temporaryUISourceCodes.remove(oldUISourceCode); + this._scriptIdForUISourceCode.remove(oldUISourceCode); + this._workspace.project().replaceUISourceCode(oldUISourceCode, uiSourceCode); }, - reset: function() + _reset: function() { - for (var i = 0; i < this._rawSourceCodes.length; ++i) { - var rawSourceCode = this._rawSourceCodes[i]; - this._uiSourceCodeRemoved(rawSourceCode, rawSourceCode.uiSourceCode()); - rawSourceCode.removeAllListeners(); - } - this._rawSourceCodes = []; - this._rawSourceCodeForScriptId = {}; - this._rawSourceCodeForURL = {}; - this._rawSourceCodeForDocumentURL = {}; - this._rawSourceCodeForUISourceCode.clear(); - } + this._uiSourceCodeForScriptId = {}; + this._scriptIdForUISourceCode.clear(); + this._temporaryUISourceCodes.clear(); + this._nextDynamicScriptIndexForURL = {}; + }, } - -WebInspector.ResourceScriptMapping.prototype.__proto__ = WebInspector.Object.prototype; diff --git a/Source/WebCore/inspector/front-end/ResourceTreeModel.js b/Source/WebCore/inspector/front-end/ResourceTreeModel.js index ca25c959f..d503dae60 100644 --- a/Source/WebCore/inspector/front-end/ResourceTreeModel.js +++ b/Source/WebCore/inspector/front-end/ResourceTreeModel.js @@ -35,8 +35,7 @@ */ WebInspector.ResourceTreeModel = function(networkManager) { - networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.RequestUpdated, this._onRequestUpdated, this); - networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.RequestFinished, this._onRequestUpdated, this); + networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.RequestFinished, this._onRequestFinished, this); networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.RequestUpdateDropped, this._onRequestUpdateDropped, this); WebInspector.console.addEventListener(WebInspector.ConsoleModel.Events.MessageAdded, this._consoleMessageAdded, this); @@ -116,9 +115,6 @@ WebInspector.ResourceTreeModel.prototype = { */ _frameNavigated: function(framePayload) { - if (this._frontendReused(framePayload)) - return; - // Do nothing unless cached resource tree is processed - it will overwrite everything. if (!this._cachedResourcesProcessed) return; @@ -154,20 +150,6 @@ WebInspector.ResourceTreeModel.prototype = { }, /** - * @param {PageAgent.Frame} framePayload - * @return {boolean} - */ - _frontendReused: function(framePayload) - { - if (!framePayload.parentId && !WebInspector.networkLog.requests.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) @@ -189,7 +171,7 @@ WebInspector.ResourceTreeModel.prototype = { /** * @param {WebInspector.Event} event */ - _onRequestUpdated: function(event) + _onRequestFinished: function(event) { if (!this._cachedResourcesProcessed) return; diff --git a/Source/WebCore/inspector/front-end/ResourceUtils.js b/Source/WebCore/inspector/front-end/ResourceUtils.js index 54909c730..16a62676e 100644 --- a/Source/WebCore/inspector/front-end/ResourceUtils.js +++ b/Source/WebCore/inspector/front-end/ResourceUtils.js @@ -46,16 +46,6 @@ WebInspector.forAllResources = function(callback) } /** - * @param {string} host - */ -WebInspector.displayDomain = function(host) -{ - if (host && (!WebInspector.inspectedPageDomain || (WebInspector.inspectedPageDomain && host !== WebInspector.inspectedPageDomain))) - return host; - return ""; -} - -/** * @param {string} url * @return {string} */ @@ -181,7 +171,7 @@ WebInspector.linkifyURLAsNode = function(url, linkText, classes, isExternal, too classes += isExternal ? "webkit-html-external-link" : "webkit-html-resource-link"; var a = document.createElement("a"); - a.href = url; + a.href = sanitizeHref(url); a.className = classes; if (typeof tooltipText === "undefined") a.title = url; @@ -236,36 +226,3 @@ WebInspector.linkifyRequestAsNode = function(request, classes) 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().startsWith("javascript:")) - return null; // Do not provide a resource URL for security. - - for (var frameOwnerCandidate = node; frameOwnerCandidate; frameOwnerCandidate = frameOwnerCandidate.parentNode) { - if (frameOwnerCandidate.documentURL) { - var result = WebInspector.ParsedURL.completeURL(frameOwnerCandidate.documentURL, url); - if (result) - return result; - break; - } - } - - // documentURL not found or has bad value - var resourceURL = url; - function callback(resource) - { - if (resource.parsedURL.path === url) { - resourceURL = resource.url; - return true; - } - } - WebInspector.forAllResources(callback); - return resourceURL; -} diff --git a/Source/WebCore/inspector/front-end/RevisionHistoryView.js b/Source/WebCore/inspector/front-end/RevisionHistoryView.js index 5e8890374..f80e498aa 100644 --- a/Source/WebCore/inspector/front-end/RevisionHistoryView.js +++ b/Source/WebCore/inspector/front-end/RevisionHistoryView.js @@ -57,7 +57,7 @@ WebInspector.RevisionHistoryView = function() WebInspector.workspace.addEventListener(WebInspector.Workspace.Events.UISourceCodeContentCommitted, this._revisionAdded, this); WebInspector.workspace.addEventListener(WebInspector.UISourceCodeProvider.Events.UISourceCodeReplaced, this._uiSourceCodeReplaced, this); WebInspector.workspace.addEventListener(WebInspector.UISourceCodeProvider.Events.UISourceCodeRemoved, this._uiSourceCodeRemoved, this); - WebInspector.workspace.addEventListener(WebInspector.Workspace.Events.WorkspaceReset, this._reset, this); + WebInspector.workspace.addEventListener(WebInspector.Workspace.Events.ProjectWillReset, this._reset, this); this._statusElement = document.createElement("span"); this._statusElement.textContent = WebInspector.UIString("Local modifications"); diff --git a/Source/WebCore/inspector/front-end/JavaScriptContextManager.js b/Source/WebCore/inspector/front-end/RuntimeModel.js index c37190089..f56335622 100644 --- a/Source/WebCore/inspector/front-end/JavaScriptContextManager.js +++ b/Source/WebCore/inspector/front-end/RuntimeModel.js @@ -31,40 +31,53 @@ /** * @constructor * @extends {WebInspector.Object} + * @param {WebInspector.ResourceTreeModel} resourceTreeModel */ -WebInspector.JavaScriptContextManager = function(resourceTreeModel, consoleView) +WebInspector.RuntimeModel = function(resourceTreeModel) { 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); resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.CachedResourcesLoaded, this._didLoadCachedResources, this); - this._consoleView = consoleView; - this._frameIdToContext = {}; + this._frameIdToContextList = {}; } -WebInspector.JavaScriptContextManager.prototype = { +WebInspector.RuntimeModel.Events = { + FrameExecutionContextListAdded: "FrameExecutionContextListAdded", + FrameExecutionContextListRemoved: "FrameExecutionContextListRemoved", +} + +WebInspector.RuntimeModel.prototype = { + /** + * @return {Array.<WebInspector.FrameExecutionContextList>} + */ + contextLists: function() + { + return Object.values(this._frameIdToContextList); + }, + /** * @param {WebInspector.ResourceTreeFrame} frame * @param {string} securityOrigin */ contextByFrameAndSecurityOrigin: function(frame, securityOrigin) { - var frameContext = this._frameIdToContext[frame.id]; + var frameContext = this._frameIdToContextList[frame.id]; return frameContext && frameContext.contextBySecurityOrigin(securityOrigin); }, _frameAdded: function(event) { var frame = event.data; - var context = new WebInspector.FrameEvaluationContext(frame); - this._frameIdToContext[frame.id] = context; - this._consoleView.addContext(context); + var context = new WebInspector.FrameExecutionContextList(frame); + this._frameIdToContextList[frame.id] = context; + this.dispatchEventToListeners(WebInspector.RuntimeModel.Events.FrameExecutionContextListAdded, context); }, _frameNavigated: function(event) { var frame = event.data; - var context = this._frameIdToContext[frame.id]; + var context = this._frameIdToContextList[frame.id]; if (context) context._frameNavigated(frame); }, @@ -72,11 +85,11 @@ WebInspector.JavaScriptContextManager.prototype = { _frameDetached: function(event) { var frame = event.data; - var context = this._frameIdToContext[frame.id]; + var context = this._frameIdToContextList[frame.id]; if (!context) return; - this._consoleView.removeContext(context); - delete this._frameIdToContext[frame.id]; + this.dispatchEventToListeners(WebInspector.RuntimeModel.Events.FrameExecutionContextListRemoved, context); + delete this._frameIdToContextList[frame.id]; }, _didLoadCachedResources: function() @@ -85,37 +98,37 @@ WebInspector.JavaScriptContextManager.prototype = { RuntimeAgent.setReportExecutionContextCreation(true); }, - isolatedContextCreated: function(context) + _executionContextCreated: function(context) { - var frameEvaluationContext = this._frameIdToContext[context.frameId]; + var contextList = this._frameIdToContextList[context.frameId]; // FIXME(85708): this should never happen - if (!frameEvaluationContext) + if (!contextList) return; - frameEvaluationContext._addExecutionContext(new WebInspector.ExecutionContext(context.id, context.name, context.isPageContext)); + contextList._addExecutionContext(new WebInspector.ExecutionContext(context.id, context.name, context.isPageContext)); } } -WebInspector.JavaScriptContextManager.prototype.__proto__ = WebInspector.Object.prototype; +WebInspector.RuntimeModel.prototype.__proto__ = WebInspector.Object.prototype; /** - * @type {WebInspector.JavaScriptContextManager} + * @type {WebInspector.RuntimeModel} */ -WebInspector.javaScriptContextManager = null; +WebInspector.runtimeModel = null; /** * @constructor * @implements {RuntimeAgent.Dispatcher} - * @param {WebInspector.JavaScriptContextManager} contextManager + * @param {WebInspector.RuntimeModel} runtimeModel */ -WebInspector.RuntimeDispatcher = function(contextManager) +WebInspector.RuntimeDispatcher = function(runtimeModel) { - this._contextManager = contextManager; + this._runtimeModel = runtimeModel; } WebInspector.RuntimeDispatcher.prototype = { - isolatedContextCreated: function(context) + executionContextCreated: function(context) { - this._contextManager.isolatedContextCreated(context); + this._runtimeModel._executionContextCreated(context); } } @@ -149,26 +162,24 @@ WebInspector.ExecutionContext.comparator = function(a, b) * @constructor * @extends {WebInspector.Object} */ -WebInspector.FrameEvaluationContext = function(frame) +WebInspector.FrameExecutionContextList = function(frame) { this._frame = frame; - this._mainWorldContext = null; - this._isolatedContexts = []; + this._executionContexts = []; } -WebInspector.FrameEvaluationContext.EventTypes = { - Updated: "Updated", - AddedExecutionContext: "AddedExecutionContext" +WebInspector.FrameExecutionContextList.EventTypes = { + ContextsUpdated: "ContextsUpdated", + ContextAdded: "ContextAdded" } -WebInspector.FrameEvaluationContext.prototype = +WebInspector.FrameExecutionContextList.prototype = { _frameNavigated: function(frame) { this._frame = frame; - this._mainWorldContext = null; - this._isolatedContexts = []; - this.dispatchEventToListeners(WebInspector.FrameEvaluationContext.EventTypes.Updated, this); + this._executionContexts = []; + this.dispatchEventToListeners(WebInspector.FrameExecutionContextList.EventTypes.ContextsUpdated, this); }, /** @@ -176,23 +187,14 @@ WebInspector.FrameEvaluationContext.prototype = */ _addExecutionContext: function(context) { - if (context.isMainWorldContext) - this._mainWorldContext = context; - else { - var insertAt = insertionIndexForObjectInListSortedByFunction(context, this._isolatedContexts, WebInspector.ExecutionContext.comparator); - this._isolatedContexts.splice(insertAt, 0, context); - } - this.dispatchEventToListeners(WebInspector.FrameEvaluationContext.EventTypes.AddedExecutionContext, this); - }, - - mainWorldContext: function() - { - return this._mainWorldContext; + var insertAt = insertionIndexForObjectInListSortedByFunction(context, this._executionContexts, WebInspector.ExecutionContext.comparator); + this._executionContexts.splice(insertAt, 0, context); + this.dispatchEventToListeners(WebInspector.FrameExecutionContextList.EventTypes.ContextAdded, this); }, - isolatedContexts: function() + executionContexts: function() { - return this._isolatedContexts; + return this._executionContexts; }, /** @@ -200,8 +202,8 @@ WebInspector.FrameEvaluationContext.prototype = */ contextBySecurityOrigin: function(securityOrigin) { - for (var i = 0; i < this._isolatedContexts.length; ++i) { - var context = this._isolatedContexts[i]; + for (var i = 0; i < this._executionContexts.length; ++i) { + var context = this._executionContexts[i]; if (!context.isMainWorldContext && context.name === securityOrigin) return context; } @@ -232,4 +234,4 @@ WebInspector.FrameEvaluationContext.prototype = } } -WebInspector.FrameEvaluationContext.prototype.__proto__ = WebInspector.Object.prototype; +WebInspector.FrameExecutionContextList.prototype.__proto__ = WebInspector.Object.prototype; diff --git a/Source/WebCore/inspector/front-end/SASSSourceMapping.js b/Source/WebCore/inspector/front-end/SASSSourceMapping.js index e1c0aa700..0b8e96e6e 100644 --- a/Source/WebCore/inspector/front-end/SASSSourceMapping.js +++ b/Source/WebCore/inspector/front-end/SASSSourceMapping.js @@ -30,19 +30,16 @@ /** * @constructor - * @extends {WebInspector.Object} * @implements {WebInspector.SourceMapping} - * @implements {WebInspector.UISourceCodeProvider} + * @param {WebInspector.Workspace} workspace */ -WebInspector.SASSSourceMapping = function() +WebInspector.SASSSourceMapping = function(workspace) { - /** - * @type {Array.<WebInspector.UISourceCode>} - */ - this._uiSourceCodes = []; + this._workspace = workspace; this._uiSourceCodeForURL = {}; this._uiLocations = {}; WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.ResourceAdded, this._resourceAdded, this); + this._workspace.addEventListener(WebInspector.Workspace.Events.ProjectWillReset, this._reset, this); } WebInspector.SASSSourceMapping.prototype = { @@ -119,8 +116,7 @@ WebInspector.SASSSourceMapping.prototype = { if (!uiSourceCode) { uiSourceCode = new WebInspector.SASSSource(url); this._uiSourceCodeForURL[url] = uiSourceCode; - this._uiSourceCodes.push(uiSourceCode); - this.dispatchEventToListeners(WebInspector.UISourceCodeProvider.Events.UISourceCodeAdded, uiSourceCode); + this._workspace.project().addUISourceCode(uiSourceCode); WebInspector.cssModel.setSourceMapping(rawURL, this); } var rawLocationString = rawURL + ":" + (rawLine + 1); // Next line after mapping metainfo @@ -136,7 +132,7 @@ WebInspector.SASSSourceMapping.prototype = { var location = /** @type WebInspector.CSSLocation */ rawLocation; var uiLocation = this._uiLocations[location.url + ":" + location.lineNumber]; if (!uiLocation) { - var uiSourceCode = WebInspector.workspace.uiSourceCodeForURL(location.url); + var uiSourceCode = this._workspace.uiSourceCodeForURL(location.url); uiLocation = new WebInspector.UILocation(uiSourceCode, location.lineNumber, 0); } return uiLocation; @@ -154,25 +150,14 @@ WebInspector.SASSSourceMapping.prototype = { return new WebInspector.CSSLocation(uiSourceCode.contentURL() || "", lineNumber); }, - /** - * @return {Array.<WebInspector.UISourceCode>} - */ - uiSourceCodes: function() - { - return this._uiSourceCodes; - }, - - reset: function() + _reset: function() { - this._uiSourceCodes = []; this._uiSourceCodeForURL = {}; this._uiLocations = {}; this._populate(); } } -WebInspector.SASSSourceMapping.prototype.__proto__ = WebInspector.Object.prototype; - /** * @constructor * @extends {WebInspector.UISourceCode} @@ -181,7 +166,7 @@ WebInspector.SASSSourceMapping.prototype.__proto__ = WebInspector.Object.prototy WebInspector.SASSSource = function(sassURL) { var content = InspectorFrontendHost.loadResourceSynchronously(sassURL); - var contentProvider = new WebInspector.StaticContentProvider(WebInspector.resourceTypes.Stylesheet, content); + var contentProvider = new WebInspector.StaticContentProvider(WebInspector.resourceTypes.Stylesheet, content, "text/x-scss"); WebInspector.UISourceCode.call(this, sassURL, null, contentProvider); } diff --git a/Source/WebCore/inspector/front-end/ScriptSnippetModel.js b/Source/WebCore/inspector/front-end/ScriptSnippetModel.js index 392448dfa..60a667233 100644 --- a/Source/WebCore/inspector/front-end/ScriptSnippetModel.js +++ b/Source/WebCore/inspector/front-end/ScriptSnippetModel.js @@ -31,9 +31,11 @@ /** * @constructor * @extends {WebInspector.Object} + * @param {WebInspector.Workspace} workspace */ -WebInspector.ScriptSnippetModel = function() +WebInspector.ScriptSnippetModel = function(workspace) { + this._workspace = workspace; this._uiSourceCodeForScriptId = {}; this._scriptForUISourceCode = new Map(); this._snippetJavaScriptSourceForSnippetId = {}; @@ -41,6 +43,9 @@ WebInspector.ScriptSnippetModel = function() this._snippetStorage = new WebInspector.SnippetStorage("script", "Script snippet #"); this._lastSnippetEvaluationIndexSetting = WebInspector.settings.createSetting("lastSnippetEvaluationIndex", 0); this._snippetScriptMapping = new WebInspector.SnippetScriptMapping(this); + this._workspace.addEventListener(WebInspector.Workspace.Events.ProjectWillReset, this._projectWillReset, this); + this._workspace.addEventListener(WebInspector.Workspace.Events.ProjectDidReset, this._projectDidReset, this); + this._loadSnippets(); } WebInspector.ScriptSnippetModel.snippetSourceURLPrefix = "snippets:///"; @@ -77,8 +82,9 @@ WebInspector.ScriptSnippetModel.prototype = { _addScriptSnippet: function(snippet) { var snippetJavaScriptSource = new WebInspector.SnippetJavaScriptSource(snippet.id, snippet.name, new WebInspector.SnippetContentProvider(snippet), this); + snippetJavaScriptSource.setSourceMapping(this._snippetScriptMapping); this._snippetJavaScriptSourceForSnippetId[snippet.id] = snippetJavaScriptSource; - this._snippetScriptMapping._fireUISourceCodeAdded(snippetJavaScriptSource); + this._workspace.project().addUISourceCode(snippetJavaScriptSource); return snippetJavaScriptSource; }, @@ -92,7 +98,7 @@ WebInspector.ScriptSnippetModel.prototype = { this._removeBreakpoints(snippetJavaScriptSource); this._releaseSnippetScript(snippetJavaScriptSource); delete this._snippetJavaScriptSourceForSnippetId[snippet.id]; - this._snippetScriptMapping._fireUISourceCodeRemoved(snippetJavaScriptSource); + this._workspace.project().removeUISourceCode(snippetJavaScriptSource); }, /** @@ -239,17 +245,6 @@ WebInspector.ScriptSnippetModel.prototype = { /** * @return {Array.<WebInspector.UISourceCode>} */ - _uiSourceCodes: function() - { - var result = this._releasedUISourceCodes(); - for (var snippetId in this._snippetJavaScriptSourceForSnippetId) - result.push(this._snippetJavaScriptSourceForSnippetId[snippetId]); - return result; - }, - - /** - * @return {Array.<WebInspector.UISourceCode>} - */ _releasedUISourceCodes: function() { var result = []; @@ -285,7 +280,8 @@ WebInspector.ScriptSnippetModel.prototype = { */ _createUISourceCodeForScript: function(script) { - var uiSourceCode = new WebInspector.JavaScriptSource(script.sourceURL, null, script, this._snippetScriptMapping, false); + var uiSourceCode = new WebInspector.JavaScriptSource(script.sourceURL, null, script, false); + uiSourceCode.setSourceMapping(this._snippetScriptMapping); uiSourceCode.isSnippetEvaluation = true; this._uiSourceCodeForScriptId[script.scriptId] = uiSourceCode; this._scriptForUISourceCode.put(uiSourceCode, script); @@ -357,13 +353,17 @@ WebInspector.ScriptSnippetModel.prototype = { return snippetId; }, - _reset: function() + _projectWillReset: function() { var removedUISourceCodes = this._releasedUISourceCodes(); this._uiSourceCodeForScriptId = {}; this._scriptForUISourceCode = new Map(); this._snippetJavaScriptSourceForSnippetId = {}; - setTimeout(this._loadSnippets.bind(this), 0); + }, + + _projectDidReset: function() + { + this._loadSnippets(); } } @@ -379,7 +379,7 @@ WebInspector.ScriptSnippetModel.prototype.__proto__ = WebInspector.Object.protot */ WebInspector.SnippetJavaScriptSource = function(snippetId, snippetName, contentProvider, scriptSnippetModel) { - WebInspector.JavaScriptSource.call(this, snippetName, null, contentProvider, scriptSnippetModel.scriptMapping, true); + WebInspector.JavaScriptSource.call(this, snippetName, null, contentProvider, true); this._snippetId = snippetId; this._scriptSnippetModel = scriptSnippetModel; this.isSnippet = true; @@ -450,9 +450,7 @@ WebInspector.SnippetJavaScriptSource.prototype.__proto__ = WebInspector.JavaScri /** * @constructor - * @extends {WebInspector.Object} * @implements {WebInspector.SourceMapping} - * @implements {WebInspector.UISourceCodeProvider} * @param {WebInspector.ScriptSnippetModel} scriptSnippetModel */ WebInspector.SnippetScriptMapping = function(scriptSnippetModel) @@ -483,14 +481,6 @@ WebInspector.SnippetScriptMapping.prototype = { }, /** - * @return {Array.<WebInspector.UISourceCode>} - */ - uiSourceCodes: function() - { - return this._scriptSnippetModel._uiSourceCodes(); - }, - - /** * @param {string} sourceURL * @return {string|null} */ @@ -505,32 +495,9 @@ WebInspector.SnippetScriptMapping.prototype = { addScript: function(script) { this._scriptSnippetModel._addScript(script); - }, - - /** - * @param {WebInspector.UISourceCode} uiSourceCode - */ - _fireUISourceCodeAdded: function(uiSourceCode) - { - this.dispatchEventToListeners(WebInspector.UISourceCodeProvider.Events.UISourceCodeAdded, uiSourceCode); - }, - - /** - * @param {WebInspector.UISourceCode} uiSourceCode - */ - _fireUISourceCodeRemoved: function(uiSourceCode) - { - this.dispatchEventToListeners(WebInspector.UISourceCodeProvider.Events.UISourceCodeRemoved, uiSourceCode); - }, - - reset: function() - { - this._scriptSnippetModel._reset(); } } -WebInspector.SnippetScriptMapping.prototype.__proto__ = WebInspector.Object.prototype; - /** * @constructor * @extends {WebInspector.StaticContentProvider} diff --git a/Source/WebCore/inspector/front-end/ScriptsPanel.js b/Source/WebCore/inspector/front-end/ScriptsPanel.js index 49dad8914..cb818ef64 100644 --- a/Source/WebCore/inspector/front-end/ScriptsPanel.js +++ b/Source/WebCore/inspector/front-end/ScriptsPanel.js @@ -196,7 +196,7 @@ WebInspector.ScriptsPanel = function(workspaceForTest) this._workspace.addEventListener(WebInspector.UISourceCodeProvider.Events.UISourceCodeAdded, this._uiSourceCodeAdded, this); this._workspace.addEventListener(WebInspector.UISourceCodeProvider.Events.UISourceCodeReplaced, this._uiSourceCodeReplaced, this); this._workspace.addEventListener(WebInspector.UISourceCodeProvider.Events.UISourceCodeRemoved, this._uiSourceCodeRemoved, this); - this._workspace.addEventListener(WebInspector.Workspace.Events.WorkspaceReset, this._reset.bind(this), this); + this._workspace.addEventListener(WebInspector.Workspace.Events.ProjectWillReset, this._reset.bind(this), this); WebInspector.advancedSearchController.registerSearchScope(new WebInspector.ScriptsSearchScope(this._workspace)); } @@ -294,9 +294,11 @@ WebInspector.ScriptsPanel.prototype = { } 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) { + } else if (details.reason === WebInspector.DebuggerModel.BreakReason.Exception) this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on exception: '%s'.", details.auxData.description)); - } else { + else if (details.reason === WebInspector.DebuggerModel.BreakReason.Assert) + this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on assertion.")); + else { function didGetUILocation(uiLocation) { var breakpoint = WebInspector.breakpointManager.findBreakpoint(uiLocation.uiSourceCode, uiLocation.lineNumber); @@ -389,13 +391,6 @@ WebInspector.ScriptsPanel.prototype = { this._showSourceLine(anchor.uiSourceCode, anchor.lineNumber); }, - showFunctionDefinition: function(functionLocation) - { - WebInspector.inspectorView.showPanelForAnchorNavigation(this); - var uiLocation = WebInspector.debuggerModel.rawLocationToUILocation(functionLocation); - this._showSourceLine(uiLocation.uiSourceCode, uiLocation.lineNumber); - }, - /** * @param {WebInspector.UISourceCode} uiSourceCode * @param {number} lineNumber @@ -995,6 +990,7 @@ WebInspector.ScriptsPanel.prototype = { this._toggleDebuggerSidebarButton.state = "shown"; this._toggleDebuggerSidebarButton.title = WebInspector.UIString("Hide debugger"); this.splitView.showSidebarElement(); + this.debugSidebarResizeWidgetElement.removeStyleClass("hidden"); WebInspector.settings.debuggerSidebarHidden.set(false); }, @@ -1005,6 +1001,7 @@ WebInspector.ScriptsPanel.prototype = { this._toggleDebuggerSidebarButton.state = "hidden"; this._toggleDebuggerSidebarButton.title = WebInspector.UIString("Show debugger"); this.splitView.hideSidebarElement(); + this.debugSidebarResizeWidgetElement.addStyleClass("hidden"); WebInspector.settings.debuggerSidebarHidden.set(true); }, @@ -1086,6 +1083,16 @@ WebInspector.ScriptsPanel.prototype = { */ appendApplicableItems: function(contextMenu, target) { + this._appendUISourceCodeItems(contextMenu, target); + this._appendFunctionItems(contextMenu, target); + }, + + /** + * @param {WebInspector.ContextMenu} contextMenu + * @param {Object} target + */ + _appendUISourceCodeItems: function(contextMenu, target) + { if (!(target instanceof WebInspector.UISourceCode)) return; @@ -1095,6 +1102,37 @@ WebInspector.ScriptsPanel.prototype = { contextMenu.appendApplicableItems(uiSourceCode.resource().request); }, + /** + * @param {WebInspector.ContextMenu} contextMenu + * @param {Object} target + */ + _appendFunctionItems: function(contextMenu, target) + { + if (!(target instanceof WebInspector.RemoteObject)) + return; + var remoteObject = /** @type {WebInspector.RemoteObject} */ target; + if (remoteObject.type !== "function") + return; + + function didGetDetails(error, response) + { + if (error) { + console.error(error); + return; + } + WebInspector.inspectorView.showPanelForAnchorNavigation(this); + var uiLocation = WebInspector.debuggerModel.rawLocationToUILocation(response.location); + this._showSourceLine(uiLocation.uiSourceCode, uiLocation.lineNumber); + } + + function revealFunction() + { + DebuggerAgent.getFunctionDetails(remoteObject.objectId, didGetDetails.bind(this)); + } + + contextMenu.appendItem(WebInspector.UIString("Show function definition"), revealFunction.bind(this)); + }, + showGoToSourceDialog: function() { WebInspector.OpenResourceDialog.show(this, this._workspace, this.editorView.mainElement); diff --git a/Source/WebCore/inspector/front-end/ScriptsPanelDescriptor.js b/Source/WebCore/inspector/front-end/ScriptsPanelDescriptor.js index 01a873e42..5516f1f23 100644 --- a/Source/WebCore/inspector/front-end/ScriptsPanelDescriptor.js +++ b/Source/WebCore/inspector/front-end/ScriptsPanelDescriptor.js @@ -44,8 +44,14 @@ WebInspector.ScriptsPanelDescriptor.prototype = { */ appendApplicableItems: function(contextMenu, target) { - if (!(target instanceof WebInspector.UISourceCode)) - return; + var hasApplicableItems = target instanceof WebInspector.UISourceCode; + + if (!hasApplicableItems && target instanceof WebInspector.RemoteObject) { + var remoteObject = /** @type {WebInspector.RemoteObject} */ target; + if (remoteObject.type !== "function") + return; + } + this.panel().appendApplicableItems(contextMenu, target); } } diff --git a/Source/WebCore/inspector/front-end/Settings.js b/Source/WebCore/inspector/front-end/Settings.js index ee13ebc27..6765dc542 100644 --- a/Source/WebCore/inspector/front-end/Settings.js +++ b/Source/WebCore/inspector/front-end/Settings.js @@ -191,6 +191,7 @@ WebInspector.ExperimentsSettings = function() this.nativeMemorySnapshots = this._createExperiment("nativeMemorySnapshots", "Native memory profiling"); this.liveNativeMemoryChart = this._createExperiment("liveNativeMemoryChart", "Live native memory chart"); this.fileSystemInspection = this._createExperiment("fileSystemInspection", "FileSystem inspection"); + this.webGLInspection = this._createExperiment("webGLInspection ", "WebGL inspection"); this.mainThreadMonitoring = this._createExperiment("mainThreadMonitoring", "Show CPU activity in Timeline"); this.geolocationOverride = this._createExperiment("geolocationOverride", "Override Device Geolocation"); this.deviceOrientationOverride = this._createExperiment("deviceOrientationOverride", "Override Device Orientation"); diff --git a/Source/WebCore/inspector/front-end/SettingsScreen.js b/Source/WebCore/inspector/front-end/SettingsScreen.js index eb67a756f..728389c7f 100644 --- a/Source/WebCore/inspector/front-end/SettingsScreen.js +++ b/Source/WebCore/inspector/front-end/SettingsScreen.js @@ -38,7 +38,7 @@ WebInspector.SettingsScreen = function(onHide) WebInspector.HelpScreen.call(this); this.element.id = "settings-screen"; - /** @type {!function()} */ + /** @type {function()} */ this._onHide = onHide; this._tabbedPane = new WebInspector.TabbedPane(); @@ -65,7 +65,7 @@ WebInspector.SettingsScreen.Tabs = { WebInspector.SettingsScreen.prototype = { /** - * @param {!string} tabId + * @param {string} tabId */ selectTab: function(tabId) { diff --git a/Source/WebCore/inspector/front-end/SourceCSSTokenizer.js b/Source/WebCore/inspector/front-end/SourceCSSTokenizer.js index 8d5b8de82..618913969 100644 --- a/Source/WebCore/inspector/front-end/SourceCSSTokenizer.js +++ b/Source/WebCore/inspector/front-end/SourceCSSTokenizer.js @@ -1,4 +1,4 @@ -/* Generated by re2c 0.13.5 on Mon Jul 9 19:31:30 2012 */ +/* Generated by re2c 0.13.5 on Fri Sep 7 17:09:30 2012 */ /* * Copyright (C) 2009 Google Inc. All rights reserved. * @@ -52,7 +52,7 @@ WebInspector.SourceCSSTokenizer = function() { WebInspector.SourceTokenizer.call(this); - this._propertyKeywords = WebInspector.CSSCompletions.cssPropertiesMetainfo.keySet(); + this._propertyKeywords = WebInspector.CSSCompletions.cssPropertiesMetainfoKeySet(); this._colorKeywords = WebInspector.CSSKeywordCompletions.colors(); this._valueKeywords = [ @@ -105,7 +105,12 @@ WebInspector.SourceCSSTokenizer = function() "-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._scssValueKeywords = [ + "abs", "adjust-color", "adjust-hue", "alpha", "append", "ceil", "change-color", "comparable", "complement", "darken", "desaturate", + "fade-in", "fade-out", "floor", "grayscale", "hue", "ie-hex-str", "invert", "join", "length", "lighten", + "lightness", "max", "min", "mix", "nth", "opacify", "opacity", "percentage", "quote", "round", "saturate", + "saturation", "scale-color", "transparentize", "type-of", "unit", "unitless", "unquote", "zip" + ].keySet(); this._lexConditions = { INITIAL: 0, @@ -130,6 +135,10 @@ WebInspector.SourceCSSTokenizer = function() this.condition = this.createInitialCondition(); } +WebInspector.SourceCSSTokenizer.SCSSAtRelatedKeywords = ["from", "if", "in", "through"].keySet(); + +WebInspector.SourceCSSTokenizer.MediaTypes = ["all", "aural", "braille", "embossed", "handheld", "import", "print", "projection", "screen", "tty", "tv"].keySet(); + WebInspector.SourceCSSTokenizer.prototype = { createInitialCondition: function() { @@ -153,6 +162,11 @@ WebInspector.SourceCSSTokenizer.prototype = { return this._condition.parseCondition === this._parseConditions.PROPERTY_VALUE || this._condition.parseCondition === this._parseConditions.AT_RULE; }, + _setParseCondition: function(condition) + { + this._condition.parseCondition = condition; + }, + nextToken: function(cursor) { var cursorOnEnter = cursor; @@ -341,43 +355,44 @@ case 26: /* *********************************** */ case this.case_INITIAL: yych = this._charAt(cursor); - if (yych <= ';') { - if (yych <= '\'') { + 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; }; + if (yych <= '$') { gotoCase = 35; continue; }; + if (yych >= '&') { gotoCase = 31; continue; }; } } else { - if (yych <= '.') { - if (yych <= ',') { gotoCase = 29; continue; }; - if (yych <= '-') { gotoCase = 36; continue; }; - { gotoCase = 37; continue; }; + if (yych <= '-') { + if (yych <= '\'') { gotoCase = 36; continue; }; + if (yych >= '-') { gotoCase = 37; continue; }; } else { - if (yych <= '/') { gotoCase = 38; continue; }; - if (yych <= '9') { gotoCase = 39; continue; }; - if (yych <= ':') { gotoCase = 41; continue; }; - { gotoCase = 43; continue; }; + if (yych <= '.') { gotoCase = 38; continue; }; + if (yych <= '/') { gotoCase = 39; continue; }; + if (yych <= '9') { gotoCase = 40; continue; }; + { gotoCase = 42; continue; }; } } } else { - if (yych <= '^') { - if (yych <= '?') { - if (yych == '=') { gotoCase = 31; continue; }; + if (yych <= ']') { + if (yych <= '=') { + if (yych <= ';') { gotoCase = 44; continue; }; + if (yych >= '=') { gotoCase = 31; continue; }; } else { - if (yych == '\\') { gotoCase = 29; continue; }; - if (yych <= ']') { gotoCase = 31; continue; }; + if (yych <= '?') { gotoCase = 29; continue; }; + if (yych != '\\') { gotoCase = 31; continue; }; } } else { if (yych <= 'z') { - if (yych != '`') { gotoCase = 31; continue; }; + if (yych == '_') { gotoCase = 31; continue; }; + if (yych >= 'a') { gotoCase = 31; continue; }; } else { - if (yych <= '{') { gotoCase = 45; continue; }; - if (yych == '}') { gotoCase = 47; continue; }; + if (yych <= '{') { gotoCase = 46; continue; }; + if (yych == '}') { gotoCase = 48; continue; }; } } } @@ -388,79 +403,89 @@ case 30: case 31: ++cursor; yych = this._charAt(cursor); - { gotoCase = 50; continue; }; + { gotoCase = 51; continue; }; case 32: { var token = this._line.substring(cursorOnEnter, cursor); - if (this._condition.parseCondition === this._parseConditions.INITIAL) { - if (token === "@media") { + this.tokenType = null; + if (this._condition.parseCondition === this._parseConditions.INITIAL || this._condition.parseCondition === this._parseConditions.PROPERTY) { + if (token.charAt(0) === "@") { this.tokenType = "css-at-rule"; - this._condition.parseCondition = this._parseConditions.AT_MEDIA_RULE; - } else if (token.startsWith("@")) { + this._setParseCondition(token === "@media" ? this._parseConditions.AT_MEDIA_RULE : this._parseConditions.AT_RULE); + this._condition.atKeyword = token; + } else if (this._condition.parseCondition === this._parseConditions.INITIAL) + this.tokenType = "css-selector"; + else if (this._propertyKeywords.hasOwnProperty(token)) + this.tokenType = "css-property"; + } else if (this._condition.parseCondition === this._parseConditions.AT_MEDIA_RULE || this._condition.parseCondition === this._parseConditions.AT_RULE) { + if (WebInspector.SourceCSSTokenizer.SCSSAtRelatedKeywords.hasOwnProperty(token)) this.tokenType = "css-at-rule"; - this._condition.parseCondition = this._parseConditions.AT_RULE; - } else + else if (WebInspector.SourceCSSTokenizer.MediaTypes.hasOwnProperty(token)) + this.tokenType = "css-keyword"; + } + if (this.tokenType) + return cursor; + + if (this._isPropertyValue()) { + var firstChar = token.charAt(0); + if (firstChar === "$") + this.tokenType = "scss-variable"; + else if (firstChar === "!") + this.tokenType = "css-bang-keyword"; + else if (this._condition.atKeyword === "@extend") 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) + else if (this._valueKeywords.hasOwnProperty(token) || this._scssValueKeywords.hasOwnProperty(token)) this.tokenType = "css-keyword"; - else if (token in this._colorKeywords) { + else if (this._colorKeywords.hasOwnProperty(token)) { // 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; + } + } else if (this._condition.parseCondition !== this._parseConditions.PROPERTY_VALUE) + this.tokenType = "css-selector"; return cursor; } case 33: yyaccept = 0; yych = this._charAt(YYMARKER = ++cursor); - if (yych <= '-') { + if (yych <= '.') { if (yych <= '!') { if (yych <= '\f') { if (yych == '\n') { gotoCase = 32; continue; }; - { gotoCase = 128; continue; }; + { gotoCase = 132; continue; }; } else { if (yych <= '\r') { gotoCase = 32; continue; }; - if (yych <= ' ') { gotoCase = 128; continue; }; - { gotoCase = 126; continue; }; + if (yych <= ' ') { gotoCase = 132; continue; }; + { gotoCase = 130; continue; }; } } else { - if (yych <= '$') { - if (yych <= '"') { gotoCase = 115; continue; }; - if (yych <= '#') { gotoCase = 128; continue; }; - { gotoCase = 126; continue; }; + if (yych <= '\'') { + if (yych <= '"') { gotoCase = 116; continue; }; + if (yych <= '%') { gotoCase = 132; continue; }; + { gotoCase = 130; continue; }; } else { - if (yych == '\'') { gotoCase = 126; continue; }; - if (yych <= ',') { gotoCase = 128; continue; }; - { gotoCase = 126; continue; }; + if (yych == '-') { gotoCase = 130; continue; }; + { gotoCase = 132; continue; }; } } } else { - if (yych <= '[') { - if (yych <= '<') { - if (yych <= '.') { gotoCase = 128; continue; }; - if (yych <= '9') { gotoCase = 126; continue; }; - { gotoCase = 128; continue; }; + if (yych <= '\\') { + if (yych <= '=') { + if (yych <= '9') { gotoCase = 130; continue; }; + if (yych <= '<') { gotoCase = 132; continue; }; + { gotoCase = 130; continue; }; } else { - if (yych <= '=') { gotoCase = 126; continue; }; - if (yych <= '?') { gotoCase = 128; continue; }; - { gotoCase = 126; continue; }; + if (yych <= '?') { gotoCase = 132; continue; }; + if (yych <= '[') { gotoCase = 130; continue; }; + { gotoCase = 134; continue; }; } } else { - if (yych <= '^') { - if (yych <= '\\') { gotoCase = 130; continue; }; - if (yych <= ']') { gotoCase = 126; continue; }; - { gotoCase = 128; continue; }; + if (yych <= '_') { + if (yych == '^') { gotoCase = 132; continue; }; + { gotoCase = 130; continue; }; } else { - if (yych == '`') { gotoCase = 128; continue; }; - if (yych <= 'z') { gotoCase = 126; continue; }; - { gotoCase = 128; continue; }; + if (yych <= '`') { gotoCase = 132; continue; }; + if (yych <= 'z') { gotoCase = 130; continue; }; + { gotoCase = 132; continue; }; } } } @@ -468,84 +493,121 @@ case 34: yych = this._charAt(++cursor); if (yych <= '@') { if (yych <= '/') { gotoCase = 30; continue; }; - if (yych <= '9') { gotoCase = 123; continue; }; + if (yych <= '9') { gotoCase = 127; continue; }; { gotoCase = 30; continue; }; } else { - if (yych <= 'F') { gotoCase = 123; continue; }; + if (yych <= 'Z') { gotoCase = 127; continue; }; if (yych <= '`') { gotoCase = 30; continue; }; - if (yych <= 'f') { gotoCase = 123; continue; }; + if (yych <= 'z') { gotoCase = 127; continue; }; { gotoCase = 30; continue; }; } case 35: + yych = this._charAt(++cursor); + if (yych <= '<') { + if (yych <= '\'') { + if (yych <= ' ') { gotoCase = 30; continue; }; + if (yych <= '"') { gotoCase = 124; continue; }; + if (yych <= '%') { gotoCase = 30; continue; }; + { gotoCase = 124; continue; }; + } else { + if (yych <= '-') { + if (yych <= ',') { gotoCase = 30; continue; }; + { gotoCase = 124; continue; }; + } else { + if (yych <= '.') { gotoCase = 30; continue; }; + if (yych <= '9') { gotoCase = 124; continue; }; + { gotoCase = 30; continue; }; + } + } + } else { + if (yych <= ']') { + if (yych <= '?') { + if (yych <= '=') { gotoCase = 124; continue; }; + { gotoCase = 30; continue; }; + } else { + if (yych == '\\') { gotoCase = 30; continue; }; + { gotoCase = 124; continue; }; + } + } else { + if (yych <= '_') { + if (yych <= '^') { gotoCase = 30; continue; }; + { gotoCase = 124; continue; }; + } else { + if (yych <= '`') { gotoCase = 30; continue; }; + if (yych <= 'z') { gotoCase = 124; continue; }; + { gotoCase = 30; continue; }; + } + } + } +case 36: yyaccept = 0; yych = this._charAt(YYMARKER = ++cursor); - if (yych <= '-') { + if (yych <= '.') { if (yych <= '"') { if (yych <= '\f') { if (yych == '\n') { gotoCase = 32; continue; }; - { gotoCase = 117; continue; }; + { gotoCase = 118; continue; }; } else { if (yych <= '\r') { gotoCase = 32; continue; }; - if (yych <= ' ') { gotoCase = 117; continue; }; - { gotoCase = 113; continue; }; + if (yych <= ' ') { gotoCase = 118; continue; }; + { gotoCase = 114; continue; }; } } else { - if (yych <= '&') { - if (yych == '$') { gotoCase = 113; continue; }; - { gotoCase = 117; continue; }; + if (yych <= '\'') { + if (yych <= '%') { gotoCase = 118; continue; }; + if (yych <= '&') { gotoCase = 114; continue; }; + { gotoCase = 116; continue; }; } else { - if (yych <= '\'') { gotoCase = 115; continue; }; - if (yych <= ',') { gotoCase = 117; continue; }; - { gotoCase = 113; continue; }; + if (yych == '-') { gotoCase = 114; continue; }; + { gotoCase = 118; continue; }; } } } else { - if (yych <= '[') { - if (yych <= '<') { - if (yych <= '.') { gotoCase = 117; continue; }; - if (yych <= '9') { gotoCase = 113; continue; }; - { gotoCase = 117; continue; }; + if (yych <= '\\') { + if (yych <= '=') { + if (yych <= '9') { gotoCase = 114; continue; }; + if (yych <= '<') { gotoCase = 118; continue; }; + { gotoCase = 114; continue; }; } else { - if (yych <= '=') { gotoCase = 113; continue; }; - if (yych <= '?') { gotoCase = 117; continue; }; - { gotoCase = 113; continue; }; + if (yych <= '?') { gotoCase = 118; continue; }; + if (yych <= '[') { gotoCase = 114; continue; }; + { gotoCase = 120; continue; }; } } else { - if (yych <= '^') { - if (yych <= '\\') { gotoCase = 119; continue; }; - if (yych <= ']') { gotoCase = 113; continue; }; - { gotoCase = 117; continue; }; + if (yych <= '_') { + if (yych == '^') { gotoCase = 118; continue; }; + { gotoCase = 114; continue; }; } else { - if (yych == '`') { gotoCase = 117; continue; }; - if (yych <= 'z') { gotoCase = 113; continue; }; - { gotoCase = 117; continue; }; + if (yych <= '`') { gotoCase = 118; continue; }; + if (yych <= 'z') { gotoCase = 114; continue; }; + { gotoCase = 118; continue; }; } } } -case 36: +case 37: 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: + if (yych == '.') { gotoCase = 67; continue; }; + if (yych <= '/') { gotoCase = 51; continue; }; + if (yych <= '9') { gotoCase = 52; continue; }; + { gotoCase = 51; continue; }; +case 38: yych = this._charAt(++cursor); if (yych <= '/') { gotoCase = 30; continue; }; - if (yych <= '9') { gotoCase = 69; continue; }; + if (yych <= '9') { gotoCase = 70; continue; }; { gotoCase = 30; continue; }; -case 38: +case 39: yyaccept = 0; yych = this._charAt(YYMARKER = ++cursor); - if (yych == '*') { gotoCase = 105; continue; }; - { gotoCase = 50; continue; }; -case 39: + if (yych == '*') { gotoCase = 106; continue; }; + { gotoCase = 51; continue; }; +case 40: yyaccept = 1; yych = this._charAt(YYMARKER = ++cursor); switch (yych) { case '!': case '"': - case '$': + case '&': case '\'': case '-': case '/': @@ -592,9 +654,9 @@ case 39: case 'w': case 'x': case 'y': - case 'z': { gotoCase = 49; continue; }; - case '%': { gotoCase = 68; continue; }; - case '.': { gotoCase = 66; continue; }; + case 'z': { gotoCase = 50; continue; }; + case '%': { gotoCase = 69; continue; }; + case '.': { gotoCase = 67; continue; }; case '0': case '1': case '2': @@ -604,23 +666,23 @@ case 39: 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 '9': { gotoCase = 52; continue; }; + case 'H': { gotoCase = 54; continue; }; + case '_': { gotoCase = 55; continue; }; + case 'c': { gotoCase = 56; continue; }; + case 'd': { gotoCase = 57; continue; }; + case 'e': { gotoCase = 58; continue; }; + case 'g': { gotoCase = 59; continue; }; + case 'i': { gotoCase = 60; continue; }; + case 'k': { gotoCase = 61; continue; }; + case 'm': { gotoCase = 62; continue; }; + case 'p': { gotoCase = 63; continue; }; + case 'r': { gotoCase = 64; continue; }; + case 's': { gotoCase = 65; continue; }; + case 't': { gotoCase = 66; continue; }; + default: { gotoCase = 41; continue; }; } -case 40: +case 41: { if (this._isPropertyValue()) this.tokenType = "css-number"; @@ -628,92 +690,91 @@ case 40: this.tokenType = null; return cursor; } -case 41: +case 42: ++cursor; { this.tokenType = null; - if (this._condition.parseCondition === this._parseConditions.PROPERTY) - this._condition.parseCondition = this._parseConditions.PROPERTY_VALUE; + if (this._condition.parseCondition === this._parseConditions.PROPERTY || this._condition.parseCondition === this._parseConditions.INITIAL) + this._setParseCondition(this._parseConditions.PROPERTY_VALUE); return cursor; } -case 43: +case 44: ++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; + this._setParseCondition(this._condition.openBraces ? this._parseConditions.PROPERTY : this._parseConditions.INITIAL); + delete this._condition.atKeyword; return cursor; } -case 45: +case 46: ++cursor; { this.tokenType = "block-start"; + this._condition.openBraces = (this._condition.openBraces || 0) + 1; if (this._condition.parseCondition === this._parseConditions.AT_MEDIA_RULE) - this._condition.parseCondition = this._parseConditions.INITIAL; + this._setParseCondition(this._parseConditions.INITIAL); else - this._condition.parseCondition = this._parseConditions.PROPERTY; + this._setParseCondition(this._parseConditions.PROPERTY); return cursor; } -case 47: +case 48: ++cursor; { this.tokenType = "block-end"; - this._condition.parseCondition = this._parseConditions.INITIAL; + if (this._condition.openBraces > 0) + --this._condition.openBraces; + this._setParseCondition(this._condition.openBraces ? this._parseConditions.PROPERTY : this._parseConditions.INITIAL); + delete this._condition.atKeyword; return cursor; } -case 49: +case 50: ++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; }; - } +case 51: + if (yych <= '<') { + if (yych <= '\'') { + if (yych <= ' ') { gotoCase = 32; continue; }; + if (yych <= '"') { gotoCase = 50; continue; }; + if (yych <= '%') { gotoCase = 32; continue; }; + { gotoCase = 50; continue; }; } else { - if (yych <= ',') { - if (yych <= '\'') { gotoCase = 49; continue; }; - { gotoCase = 32; continue; }; + if (yych <= '-') { + if (yych <= ',') { gotoCase = 32; continue; }; + { gotoCase = 50; continue; }; } else { - if (yych == '.') { gotoCase = 32; continue; }; - { gotoCase = 49; continue; }; + if (yych <= '.') { gotoCase = 32; continue; }; + if (yych <= '9') { gotoCase = 50; continue; }; + { gotoCase = 32; 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; }; + if (yych <= ']') { + if (yych <= '?') { + if (yych <= '=') { gotoCase = 50; continue; }; { gotoCase = 32; continue; }; + } else { + if (yych == '\\') { gotoCase = 32; continue; }; + { gotoCase = 50; continue; }; } } else { if (yych <= '_') { - if (yych == '^') { gotoCase = 32; continue; }; - { gotoCase = 49; continue; }; + if (yych <= '^') { gotoCase = 32; continue; }; + { gotoCase = 50; continue; }; } else { if (yych <= '`') { gotoCase = 32; continue; }; - if (yych <= 'z') { gotoCase = 49; continue; }; + if (yych <= 'z') { gotoCase = 50; continue; }; { gotoCase = 32; continue; }; } } } -case 51: +case 52: yyaccept = 1; YYMARKER = ++cursor; yych = this._charAt(cursor); switch (yych) { case '!': case '"': - case '$': + case '&': case '\'': case '-': case '/': @@ -760,9 +821,9 @@ case 51: case 'w': case 'x': case 'y': - case 'z': { gotoCase = 49; continue; }; - case '%': { gotoCase = 68; continue; }; - case '.': { gotoCase = 66; continue; }; + case 'z': { gotoCase = 50; continue; }; + case '%': { gotoCase = 69; continue; }; + case '.': { gotoCase = 67; continue; }; case '0': case '1': case '2': @@ -772,584 +833,617 @@ case 51: 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 '9': { gotoCase = 52; continue; }; + case 'H': { gotoCase = 54; continue; }; + case '_': { gotoCase = 55; continue; }; + case 'c': { gotoCase = 56; continue; }; + case 'd': { gotoCase = 57; continue; }; + case 'e': { gotoCase = 58; continue; }; + case 'g': { gotoCase = 59; continue; }; + case 'i': { gotoCase = 60; continue; }; + case 'k': { gotoCase = 61; continue; }; + case 'm': { gotoCase = 62; continue; }; + case 'p': { gotoCase = 63; continue; }; + case 'r': { gotoCase = 64; continue; }; + case 's': { gotoCase = 65; continue; }; + case 't': { gotoCase = 66; continue; }; + default: { gotoCase = 41; 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; }; + if (yych == 'z') { gotoCase = 65; continue; }; + { gotoCase = 51; continue; }; case 55: yych = this._charAt(++cursor); - if (yych == 'm') { gotoCase = 64; continue; }; - { gotoCase = 50; continue; }; + if (yych == '_') { gotoCase = 103; continue; }; + { gotoCase = 51; continue; }; case 56: yych = this._charAt(++cursor); - if (yych == 'e') { gotoCase = 101; continue; }; - { gotoCase = 50; continue; }; + if (yych == 'm') { gotoCase = 65; continue; }; + { gotoCase = 51; continue; }; case 57: yych = this._charAt(++cursor); - if (yych == 'm') { gotoCase = 64; continue; }; - if (yych == 'x') { gotoCase = 64; continue; }; - { gotoCase = 50; continue; }; + if (yych == 'e') { gotoCase = 102; continue; }; + { gotoCase = 51; continue; }; case 58: yych = this._charAt(++cursor); - if (yych == 'r') { gotoCase = 99; continue; }; - { gotoCase = 50; continue; }; + if (yych == 'm') { gotoCase = 65; continue; }; + if (yych == 'x') { gotoCase = 65; continue; }; + { gotoCase = 51; continue; }; case 59: yych = this._charAt(++cursor); - if (yych == 'n') { gotoCase = 64; continue; }; - { gotoCase = 50; continue; }; + if (yych == 'r') { gotoCase = 100; continue; }; + { gotoCase = 51; continue; }; case 60: yych = this._charAt(++cursor); - if (yych == 'H') { gotoCase = 98; continue; }; - { gotoCase = 50; continue; }; + if (yych == 'n') { gotoCase = 65; continue; }; + { gotoCase = 51; continue; }; case 61: yych = this._charAt(++cursor); - if (yych == 'm') { gotoCase = 64; continue; }; - if (yych == 's') { gotoCase = 64; continue; }; - { gotoCase = 50; continue; }; + if (yych == 'H') { gotoCase = 99; continue; }; + { gotoCase = 51; continue; }; case 62: yych = this._charAt(++cursor); + if (yych == 'm') { gotoCase = 65; continue; }; + if (yych == 's') { gotoCase = 65; continue; }; + { gotoCase = 51; continue; }; +case 63: + yych = this._charAt(++cursor); if (yych <= 's') { - if (yych == 'c') { gotoCase = 64; continue; }; - { gotoCase = 50; continue; }; + if (yych == 'c') { gotoCase = 65; continue; }; + { gotoCase = 51; continue; }; } else { - if (yych <= 't') { gotoCase = 64; continue; }; - if (yych == 'x') { gotoCase = 64; continue; }; - { gotoCase = 50; continue; }; + if (yych <= 't') { gotoCase = 65; continue; }; + if (yych == 'x') { gotoCase = 65; continue; }; + { gotoCase = 51; 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; }; - } + if (yych == 'a') { gotoCase = 97; continue; }; + if (yych == 'e') { gotoCase = 98; continue; }; + { gotoCase = 51; continue; }; +case 65: + yych = this._charAt(++cursor); + if (yych <= '<') { + if (yych <= '\'') { + if (yych <= ' ') { gotoCase = 41; continue; }; + if (yych <= '"') { gotoCase = 50; continue; }; + if (yych <= '%') { gotoCase = 41; continue; }; + { gotoCase = 50; continue; }; } else { - if (yych <= ',') { - if (yych <= '\'') { gotoCase = 49; continue; }; - { gotoCase = 40; continue; }; + if (yych <= '-') { + if (yych <= ',') { gotoCase = 41; continue; }; + { gotoCase = 50; continue; }; } else { - if (yych == '.') { gotoCase = 40; continue; }; - { gotoCase = 49; continue; }; + if (yych <= '.') { gotoCase = 41; continue; }; + if (yych <= '9') { gotoCase = 50; continue; }; + { gotoCase = 41; continue; }; } } } else { - if (yych <= '\\') { - if (yych <= '=') { - if (yych <= '<') { gotoCase = 40; continue; }; - { gotoCase = 49; continue; }; + if (yych <= ']') { + if (yych <= '?') { + if (yych <= '=') { gotoCase = 50; continue; }; + { gotoCase = 41; continue; }; } else { - if (yych <= '?') { gotoCase = 40; continue; }; - if (yych <= '[') { gotoCase = 49; continue; }; - { gotoCase = 40; continue; }; + if (yych == '\\') { gotoCase = 41; continue; }; + { gotoCase = 50; continue; }; } } else { if (yych <= '_') { - if (yych == '^') { gotoCase = 40; continue; }; - { gotoCase = 49; continue; }; + if (yych <= '^') { gotoCase = 41; continue; }; + { gotoCase = 50; continue; }; } else { - if (yych <= '`') { gotoCase = 40; continue; }; - if (yych <= 'z') { gotoCase = 49; continue; }; - { gotoCase = 40; continue; }; + if (yych <= '`') { gotoCase = 41; continue; }; + if (yych <= 'z') { gotoCase = 50; continue; }; + { gotoCase = 41; 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; }; + if (yych == 'u') { gotoCase = 95; continue; }; + { gotoCase = 51; continue; }; case 67: + yych = this._charAt(++cursor); + if (yych <= '/') { gotoCase = 68; continue; }; + if (yych <= '9') { gotoCase = 70; continue; }; +case 68: cursor = YYMARKER; if (yyaccept <= 0) { { gotoCase = 32; continue; }; } else { - { gotoCase = 40; continue; }; + { gotoCase = 41; continue; }; } -case 68: - yych = this._charAt(++cursor); - { gotoCase = 40; continue; }; case 69: + yych = this._charAt(++cursor); + { gotoCase = 41; continue; }; +case 70: yyaccept = 1; YYMARKER = ++cursor; yych = this._charAt(cursor); if (yych <= 'f') { if (yych <= 'H') { if (yych <= '/') { - if (yych == '%') { gotoCase = 68; continue; }; - { gotoCase = 40; continue; }; + if (yych == '%') { gotoCase = 69; continue; }; + { gotoCase = 41; continue; }; } else { - if (yych <= '9') { gotoCase = 69; continue; }; - if (yych <= 'G') { gotoCase = 40; continue; }; - { gotoCase = 81; continue; }; + if (yych <= '9') { gotoCase = 70; continue; }; + if (yych <= 'G') { gotoCase = 41; continue; }; + { gotoCase = 82; continue; }; } } else { if (yych <= 'b') { - if (yych == '_') { gotoCase = 73; continue; }; - { gotoCase = 40; continue; }; + if (yych == '_') { gotoCase = 74; continue; }; + { gotoCase = 41; continue; }; } else { - if (yych <= 'c') { gotoCase = 75; continue; }; - if (yych <= 'd') { gotoCase = 78; continue; }; - if (yych >= 'f') { gotoCase = 40; continue; }; + if (yych <= 'c') { gotoCase = 76; continue; }; + if (yych <= 'd') { gotoCase = 79; continue; }; + if (yych >= 'f') { gotoCase = 41; continue; }; } } } else { if (yych <= 'm') { if (yych <= 'i') { - if (yych <= 'g') { gotoCase = 79; continue; }; - if (yych <= 'h') { gotoCase = 40; continue; }; - { gotoCase = 77; continue; }; + if (yych <= 'g') { gotoCase = 80; continue; }; + if (yych <= 'h') { gotoCase = 41; continue; }; + { gotoCase = 78; continue; }; } else { - if (yych == 'k') { gotoCase = 82; continue; }; - if (yych <= 'l') { gotoCase = 40; continue; }; - { gotoCase = 76; continue; }; + if (yych == 'k') { gotoCase = 83; continue; }; + if (yych <= 'l') { gotoCase = 41; continue; }; + { gotoCase = 77; continue; }; } } else { if (yych <= 'q') { - if (yych == 'p') { gotoCase = 74; continue; }; - { gotoCase = 40; continue; }; + if (yych == 'p') { gotoCase = 75; continue; }; + { gotoCase = 41; continue; }; } else { - if (yych <= 'r') { gotoCase = 72; continue; }; - if (yych <= 's') { gotoCase = 68; continue; }; - if (yych <= 't') { gotoCase = 80; continue; }; - { gotoCase = 40; continue; }; + if (yych <= 'r') { gotoCase = 73; continue; }; + if (yych <= 's') { gotoCase = 69; continue; }; + if (yych <= 't') { gotoCase = 81; continue; }; + { gotoCase = 41; 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; }; + if (yych == 'm') { gotoCase = 69; continue; }; + if (yych == 'x') { gotoCase = 69; continue; }; + { gotoCase = 68; continue; }; case 73: yych = this._charAt(++cursor); - if (yych == '_') { gotoCase = 89; continue; }; - { gotoCase = 67; continue; }; + if (yych == 'a') { gotoCase = 93; continue; }; + if (yych == 'e') { gotoCase = 94; continue; }; + { gotoCase = 68; continue; }; case 74: yych = this._charAt(++cursor); + if (yych == '_') { gotoCase = 90; continue; }; + { gotoCase = 68; continue; }; +case 75: + yych = this._charAt(++cursor); if (yych <= 's') { - if (yych == 'c') { gotoCase = 68; continue; }; - { gotoCase = 67; continue; }; + if (yych == 'c') { gotoCase = 69; continue; }; + { gotoCase = 68; continue; }; } else { - if (yych <= 't') { gotoCase = 68; continue; }; - if (yych == 'x') { gotoCase = 68; continue; }; - { gotoCase = 67; continue; }; + if (yych <= 't') { gotoCase = 69; continue; }; + if (yych == 'x') { gotoCase = 69; continue; }; + { gotoCase = 68; 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; }; + if (yych == 'm') { gotoCase = 69; continue; }; + { gotoCase = 68; continue; }; case 77: yych = this._charAt(++cursor); - if (yych == 'n') { gotoCase = 68; continue; }; - { gotoCase = 67; continue; }; + if (yych == 'm') { gotoCase = 69; continue; }; + if (yych == 's') { gotoCase = 69; continue; }; + { gotoCase = 68; continue; }; case 78: yych = this._charAt(++cursor); - if (yych == 'e') { gotoCase = 88; continue; }; - { gotoCase = 67; continue; }; + if (yych == 'n') { gotoCase = 69; continue; }; + { gotoCase = 68; continue; }; case 79: yych = this._charAt(++cursor); - if (yych == 'r') { gotoCase = 86; continue; }; - { gotoCase = 67; continue; }; + if (yych == 'e') { gotoCase = 89; continue; }; + { gotoCase = 68; continue; }; case 80: yych = this._charAt(++cursor); - if (yych == 'u') { gotoCase = 84; continue; }; - { gotoCase = 67; continue; }; + if (yych == 'r') { gotoCase = 87; continue; }; + { gotoCase = 68; continue; }; case 81: yych = this._charAt(++cursor); - if (yych == 'z') { gotoCase = 68; continue; }; - { gotoCase = 67; continue; }; + if (yych == 'u') { gotoCase = 85; continue; }; + { gotoCase = 68; continue; }; case 82: yych = this._charAt(++cursor); - if (yych != 'H') { gotoCase = 67; continue; }; + if (yych == 'z') { gotoCase = 69; continue; }; + { gotoCase = 68; continue; }; +case 83: yych = this._charAt(++cursor); - if (yych == 'z') { gotoCase = 68; continue; }; - { gotoCase = 67; continue; }; -case 84: + if (yych != 'H') { gotoCase = 68; continue; }; yych = this._charAt(++cursor); - if (yych != 'r') { gotoCase = 67; continue; }; + if (yych == 'z') { gotoCase = 69; continue; }; + { gotoCase = 68; continue; }; +case 85: yych = this._charAt(++cursor); - if (yych == 'n') { gotoCase = 68; continue; }; - { gotoCase = 67; continue; }; -case 86: + if (yych != 'r') { gotoCase = 68; continue; }; yych = this._charAt(++cursor); - if (yych != 'a') { gotoCase = 67; continue; }; + if (yych == 'n') { gotoCase = 69; continue; }; + { gotoCase = 68; continue; }; +case 87: yych = this._charAt(++cursor); - if (yych == 'd') { gotoCase = 68; continue; }; - { gotoCase = 67; continue; }; -case 88: + if (yych != 'a') { gotoCase = 68; continue; }; yych = this._charAt(++cursor); - if (yych == 'g') { gotoCase = 68; continue; }; - { gotoCase = 67; continue; }; + if (yych == 'd') { gotoCase = 69; continue; }; + { gotoCase = 68; continue; }; case 89: yych = this._charAt(++cursor); - if (yych != 'q') { gotoCase = 67; continue; }; + if (yych == 'g') { gotoCase = 69; continue; }; + { gotoCase = 68; continue; }; +case 90: yych = this._charAt(++cursor); - if (yych != 'e') { gotoCase = 67; continue; }; + if (yych != 'q') { gotoCase = 68; continue; }; yych = this._charAt(++cursor); - if (yych == 'm') { gotoCase = 68; continue; }; - { gotoCase = 67; continue; }; -case 92: + if (yych != 'e') { gotoCase = 68; continue; }; yych = this._charAt(++cursor); - if (yych == 'd') { gotoCase = 68; continue; }; - { gotoCase = 67; continue; }; + if (yych == 'm') { gotoCase = 69; continue; }; + { gotoCase = 68; continue; }; case 93: yych = this._charAt(++cursor); - if (yych == 'm') { gotoCase = 68; continue; }; - { gotoCase = 67; continue; }; + if (yych == 'd') { gotoCase = 69; continue; }; + { gotoCase = 68; continue; }; case 94: yych = this._charAt(++cursor); - if (yych != 'r') { gotoCase = 50; continue; }; + if (yych == 'm') { gotoCase = 69; continue; }; + { gotoCase = 68; continue; }; +case 95: yych = this._charAt(++cursor); - if (yych == 'n') { gotoCase = 64; continue; }; - { gotoCase = 50; continue; }; -case 96: + if (yych != 'r') { gotoCase = 51; continue; }; yych = this._charAt(++cursor); - if (yych == 'd') { gotoCase = 64; continue; }; - { gotoCase = 50; continue; }; + if (yych == 'n') { gotoCase = 65; continue; }; + { gotoCase = 51; continue; }; case 97: yych = this._charAt(++cursor); - if (yych == 'm') { gotoCase = 64; continue; }; - { gotoCase = 50; continue; }; + if (yych == 'd') { gotoCase = 65; continue; }; + { gotoCase = 51; continue; }; case 98: yych = this._charAt(++cursor); - if (yych == 'z') { gotoCase = 64; continue; }; - { gotoCase = 50; continue; }; + if (yych == 'm') { gotoCase = 65; continue; }; + { gotoCase = 51; continue; }; case 99: yych = this._charAt(++cursor); - if (yych != 'a') { gotoCase = 50; continue; }; + if (yych == 'z') { gotoCase = 65; continue; }; + { gotoCase = 51; continue; }; +case 100: yych = this._charAt(++cursor); - if (yych == 'd') { gotoCase = 64; continue; }; - { gotoCase = 50; continue; }; -case 101: + if (yych != 'a') { gotoCase = 51; continue; }; yych = this._charAt(++cursor); - if (yych == 'g') { gotoCase = 64; continue; }; - { gotoCase = 50; continue; }; + if (yych == 'd') { gotoCase = 65; continue; }; + { gotoCase = 51; continue; }; case 102: yych = this._charAt(++cursor); - if (yych != 'q') { gotoCase = 50; continue; }; + if (yych == 'g') { gotoCase = 65; continue; }; + { gotoCase = 51; continue; }; +case 103: + yych = this._charAt(++cursor); + if (yych != 'q') { gotoCase = 51; continue; }; yych = this._charAt(++cursor); - if (yych != 'e') { gotoCase = 50; continue; }; + if (yych != 'e') { gotoCase = 51; continue; }; yych = this._charAt(++cursor); - if (yych == 'm') { gotoCase = 64; continue; }; - { gotoCase = 50; continue; }; -case 105: + if (yych == 'm') { gotoCase = 65; continue; }; + { gotoCase = 51; continue; }; +case 106: ++cursor; yych = this._charAt(cursor); if (yych <= '\f') { - if (yych == '\n') { gotoCase = 109; continue; }; - { gotoCase = 105; continue; }; + if (yych == '\n') { gotoCase = 110; continue; }; + { gotoCase = 106; continue; }; } else { - if (yych <= '\r') { gotoCase = 109; continue; }; - if (yych != '*') { gotoCase = 105; continue; }; + if (yych <= '\r') { gotoCase = 110; continue; }; + if (yych != '*') { gotoCase = 106; continue; }; } -case 107: +case 108: ++cursor; yych = this._charAt(cursor); - if (yych == '*') { gotoCase = 107; continue; }; - if (yych == '/') { gotoCase = 111; continue; }; - { gotoCase = 105; continue; }; -case 109: + if (yych == '*') { gotoCase = 108; continue; }; + if (yych == '/') { gotoCase = 112; continue; }; + { gotoCase = 106; continue; }; +case 110: ++cursor; this.setLexCondition(this._lexConditions.COMMENT); { this.tokenType = "css-comment"; return cursor; } -case 111: +case 112: ++cursor; { this.tokenType = "css-comment"; return cursor; } -case 113: +case 114: yyaccept = 0; YYMARKER = ++cursor; yych = this._charAt(cursor); - if (yych <= '-') { + if (yych <= '.') { if (yych <= '"') { if (yych <= '\f') { if (yych == '\n') { gotoCase = 32; continue; }; - { gotoCase = 117; continue; }; + { gotoCase = 118; continue; }; } else { if (yych <= '\r') { gotoCase = 32; continue; }; - if (yych <= ' ') { gotoCase = 117; continue; }; - { gotoCase = 113; continue; }; + if (yych <= ' ') { gotoCase = 118; continue; }; + { gotoCase = 114; continue; }; } } else { - if (yych <= '&') { - if (yych == '$') { gotoCase = 113; continue; }; - { gotoCase = 117; continue; }; + if (yych <= '\'') { + if (yych <= '%') { gotoCase = 118; continue; }; + if (yych <= '&') { gotoCase = 114; continue; }; } else { - if (yych <= '\'') { gotoCase = 115; continue; }; - if (yych <= ',') { gotoCase = 117; continue; }; - { gotoCase = 113; continue; }; + if (yych == '-') { gotoCase = 114; continue; }; + { gotoCase = 118; continue; }; } } } else { - if (yych <= '[') { - if (yych <= '<') { - if (yych <= '.') { gotoCase = 117; continue; }; - if (yych <= '9') { gotoCase = 113; continue; }; - { gotoCase = 117; continue; }; + if (yych <= '\\') { + if (yych <= '=') { + if (yych <= '9') { gotoCase = 114; continue; }; + if (yych <= '<') { gotoCase = 118; continue; }; + { gotoCase = 114; continue; }; } else { - if (yych <= '=') { gotoCase = 113; continue; }; - if (yych <= '?') { gotoCase = 117; continue; }; - { gotoCase = 113; continue; }; + if (yych <= '?') { gotoCase = 118; continue; }; + if (yych <= '[') { gotoCase = 114; continue; }; + { gotoCase = 120; continue; }; } } else { - if (yych <= '^') { - if (yych <= '\\') { gotoCase = 119; continue; }; - if (yych <= ']') { gotoCase = 113; continue; }; - { gotoCase = 117; continue; }; + if (yych <= '_') { + if (yych == '^') { gotoCase = 118; continue; }; + { gotoCase = 114; continue; }; } else { - if (yych == '`') { gotoCase = 117; continue; }; - if (yych <= 'z') { gotoCase = 113; continue; }; - { gotoCase = 117; continue; }; + if (yych <= '`') { gotoCase = 118; continue; }; + if (yych <= 'z') { gotoCase = 114; continue; }; + { gotoCase = 118; continue; }; } } } -case 115: +case 116: ++cursor; - if ((yych = this._charAt(cursor)) <= '9') { - if (yych <= '&') { - if (yych <= '"') { - if (yych >= '!') { gotoCase = 49; continue; }; - } else { - if (yych == '$') { gotoCase = 49; continue; }; - } + if ((yych = this._charAt(cursor)) <= '<') { + if (yych <= '\'') { + if (yych <= ' ') { gotoCase = 117; continue; }; + if (yych <= '"') { gotoCase = 50; continue; }; + if (yych >= '&') { gotoCase = 50; continue; }; } else { - if (yych <= ',') { - if (yych <= '\'') { gotoCase = 49; continue; }; + if (yych <= '-') { + if (yych >= '-') { gotoCase = 50; continue; }; } else { - if (yych != '.') { gotoCase = 49; continue; }; + if (yych <= '.') { gotoCase = 117; continue; }; + if (yych <= '9') { gotoCase = 50; continue; }; } } } else { - if (yych <= '\\') { - if (yych <= '=') { - if (yych >= '=') { gotoCase = 49; continue; }; + if (yych <= ']') { + if (yych <= '?') { + if (yych <= '=') { gotoCase = 50; continue; }; } else { - if (yych <= '?') { gotoCase = 116; continue; }; - if (yych <= '[') { gotoCase = 49; continue; }; + if (yych != '\\') { gotoCase = 50; continue; }; } } else { if (yych <= '_') { - if (yych != '^') { gotoCase = 49; continue; }; + if (yych >= '_') { gotoCase = 50; continue; }; } else { - if (yych <= '`') { gotoCase = 116; continue; }; - if (yych <= 'z') { gotoCase = 49; continue; }; + if (yych <= '`') { gotoCase = 117; continue; }; + if (yych <= 'z') { gotoCase = 50; continue; }; } } } -case 116: - { return this._stringToken(cursor, true); } case 117: + { return this._stringToken(cursor, true); } +case 118: ++cursor; yych = this._charAt(cursor); if (yych <= '\r') { - if (yych == '\n') { gotoCase = 67; continue; }; - if (yych <= '\f') { gotoCase = 117; continue; }; - { gotoCase = 67; continue; }; + if (yych == '\n') { gotoCase = 68; continue; }; + if (yych <= '\f') { gotoCase = 118; continue; }; + { gotoCase = 68; continue; }; } else { if (yych <= '\'') { - if (yych <= '&') { gotoCase = 117; continue; }; - { gotoCase = 122; continue; }; + if (yych <= '&') { gotoCase = 118; continue; }; + { gotoCase = 123; continue; }; } else { - if (yych != '\\') { gotoCase = 117; continue; }; + if (yych != '\\') { gotoCase = 118; continue; }; } } -case 119: +case 120: ++cursor; yych = this._charAt(cursor); if (yych <= 'a') { if (yych <= '!') { if (yych <= '\n') { - if (yych <= '\t') { gotoCase = 67; continue; }; + if (yych <= '\t') { gotoCase = 68; continue; }; } else { - if (yych != '\r') { gotoCase = 67; continue; }; + if (yych != '\r') { gotoCase = 68; continue; }; } } else { if (yych <= '\'') { - if (yych <= '"') { gotoCase = 117; continue; }; - if (yych <= '&') { gotoCase = 67; continue; }; - { gotoCase = 117; continue; }; + if (yych <= '"') { gotoCase = 118; continue; }; + if (yych <= '&') { gotoCase = 68; continue; }; + { gotoCase = 118; continue; }; } else { - if (yych == '\\') { gotoCase = 117; continue; }; - { gotoCase = 67; continue; }; + if (yych == '\\') { gotoCase = 118; continue; }; + { gotoCase = 68; continue; }; } } } else { if (yych <= 'q') { if (yych <= 'f') { - if (yych <= 'b') { gotoCase = 117; continue; }; - if (yych <= 'e') { gotoCase = 67; continue; }; - { gotoCase = 117; continue; }; + if (yych <= 'b') { gotoCase = 118; continue; }; + if (yych <= 'e') { gotoCase = 68; continue; }; + { gotoCase = 118; continue; }; } else { - if (yych == 'n') { gotoCase = 117; continue; }; - { gotoCase = 67; continue; }; + if (yych == 'n') { gotoCase = 118; continue; }; + { gotoCase = 68; continue; }; } } else { if (yych <= 't') { - if (yych == 's') { gotoCase = 67; continue; }; - { gotoCase = 117; continue; }; + if (yych == 's') { gotoCase = 68; continue; }; + { gotoCase = 118; continue; }; } else { - if (yych == 'v') { gotoCase = 117; continue; }; - { gotoCase = 67; continue; }; + if (yych == 'v') { gotoCase = 118; continue; }; + { gotoCase = 68; continue; }; } } } ++cursor; this.setLexCondition(this._lexConditions.SSTRING); { return this._stringToken(cursor); } -case 122: - yych = this._charAt(++cursor); - { gotoCase = 116; continue; }; case 123: + yych = this._charAt(++cursor); + { gotoCase = 117; continue; }; +case 124: + ++cursor; + yych = this._charAt(cursor); + if (yych <= '<') { + if (yych <= '\'') { + if (yych <= ' ') { gotoCase = 126; continue; }; + if (yych <= '"') { gotoCase = 124; continue; }; + if (yych >= '&') { gotoCase = 124; continue; }; + } else { + if (yych <= '-') { + if (yych >= '-') { gotoCase = 124; continue; }; + } else { + if (yych <= '.') { gotoCase = 126; continue; }; + if (yych <= '9') { gotoCase = 124; continue; }; + } + } + } else { + if (yych <= ']') { + if (yych <= '?') { + if (yych <= '=') { gotoCase = 124; continue; }; + } else { + if (yych != '\\') { gotoCase = 124; continue; }; + } + } else { + if (yych <= '_') { + if (yych >= '_') { gotoCase = 124; continue; }; + } else { + if (yych <= '`') { gotoCase = 126; continue; }; + if (yych <= 'z') { gotoCase = 124; continue; }; + } + } + } +case 126: + { + if (this._condition.parseCondition === this._condition.parseCondition.INITIAL || this._condition.parseCondition === this._condition.parseCondition.AT_RULE) + this._setParseCondition(this._parseConditions.PROPERTY); + this.tokenType = "scss-variable"; + return cursor; + } +case 127: ++cursor; yych = this._charAt(cursor); if (yych <= '@') { - if (yych <= '/') { gotoCase = 125; continue; }; - if (yych <= '9') { gotoCase = 123; continue; }; + if (yych <= '/') { gotoCase = 129; continue; }; + if (yych <= '9') { gotoCase = 127; continue; }; } else { - if (yych <= 'F') { gotoCase = 123; continue; }; - if (yych <= '`') { gotoCase = 125; continue; }; - if (yych <= 'f') { gotoCase = 123; continue; }; + if (yych <= 'Z') { gotoCase = 127; continue; }; + if (yych <= '`') { gotoCase = 129; continue; }; + if (yych <= 'z') { gotoCase = 127; continue; }; } -case 125: +case 129: { if (this._isPropertyValue()) this.tokenType = "css-color"; + else if (this._condition.parseCondition === this._parseConditions.INITIAL) + this.tokenType = "css-selector"; else this.tokenType = null; return cursor; } -case 126: +case 130: yyaccept = 0; YYMARKER = ++cursor; yych = this._charAt(cursor); - if (yych <= '-') { + 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; }; + if (yych >= '!') { gotoCase = 130; continue; }; } } else { - if (yych <= '$') { - if (yych <= '"') { gotoCase = 115; continue; }; - if (yych >= '$') { gotoCase = 126; continue; }; + if (yych <= '\'') { + if (yych <= '"') { gotoCase = 116; continue; }; + if (yych >= '&') { gotoCase = 130; continue; }; } else { - if (yych == '\'') { gotoCase = 126; continue; }; - if (yych >= '-') { gotoCase = 126; continue; }; + if (yych == '-') { gotoCase = 130; continue; }; } } } else { - if (yych <= '[') { - if (yych <= '<') { - if (yych <= '.') { gotoCase = 128; continue; }; - if (yych <= '9') { gotoCase = 126; continue; }; + if (yych <= '\\') { + if (yych <= '=') { + if (yych <= '9') { gotoCase = 130; continue; }; + if (yych >= '=') { gotoCase = 130; continue; }; } else { - if (yych <= '=') { gotoCase = 126; continue; }; - if (yych >= '@') { gotoCase = 126; continue; }; + if (yych <= '?') { gotoCase = 132; continue; }; + if (yych <= '[') { gotoCase = 130; continue; }; + { gotoCase = 134; continue; }; } } else { - if (yych <= '^') { - if (yych <= '\\') { gotoCase = 130; continue; }; - if (yych <= ']') { gotoCase = 126; continue; }; + if (yych <= '_') { + if (yych != '^') { gotoCase = 130; continue; }; } else { - if (yych == '`') { gotoCase = 128; continue; }; - if (yych <= 'z') { gotoCase = 126; continue; }; + if (yych <= '`') { gotoCase = 132; continue; }; + if (yych <= 'z') { gotoCase = 130; continue; }; } } } -case 128: +case 132: ++cursor; yych = this._charAt(cursor); if (yych <= '\r') { - if (yych == '\n') { gotoCase = 67; continue; }; - if (yych <= '\f') { gotoCase = 128; continue; }; - { gotoCase = 67; continue; }; + if (yych == '\n') { gotoCase = 68; continue; }; + if (yych <= '\f') { gotoCase = 132; continue; }; + { gotoCase = 68; continue; }; } else { if (yych <= '"') { - if (yych <= '!') { gotoCase = 128; continue; }; - { gotoCase = 122; continue; }; + if (yych <= '!') { gotoCase = 132; continue; }; + { gotoCase = 123; continue; }; } else { - if (yych != '\\') { gotoCase = 128; continue; }; + if (yych != '\\') { gotoCase = 132; continue; }; } } -case 130: +case 134: ++cursor; yych = this._charAt(cursor); if (yych <= 'a') { if (yych <= '!') { if (yych <= '\n') { - if (yych <= '\t') { gotoCase = 67; continue; }; + if (yych <= '\t') { gotoCase = 68; continue; }; } else { - if (yych != '\r') { gotoCase = 67; continue; }; + if (yych != '\r') { gotoCase = 68; continue; }; } } else { if (yych <= '\'') { - if (yych <= '"') { gotoCase = 128; continue; }; - if (yych <= '&') { gotoCase = 67; continue; }; - { gotoCase = 128; continue; }; + if (yych <= '"') { gotoCase = 132; continue; }; + if (yych <= '&') { gotoCase = 68; continue; }; + { gotoCase = 132; continue; }; } else { - if (yych == '\\') { gotoCase = 128; continue; }; - { gotoCase = 67; continue; }; + if (yych == '\\') { gotoCase = 132; continue; }; + { gotoCase = 68; continue; }; } } } else { if (yych <= 'q') { if (yych <= 'f') { - if (yych <= 'b') { gotoCase = 128; continue; }; - if (yych <= 'e') { gotoCase = 67; continue; }; - { gotoCase = 128; continue; }; + if (yych <= 'b') { gotoCase = 132; continue; }; + if (yych <= 'e') { gotoCase = 68; continue; }; + { gotoCase = 132; continue; }; } else { - if (yych == 'n') { gotoCase = 128; continue; }; - { gotoCase = 67; continue; }; + if (yych == 'n') { gotoCase = 132; continue; }; + { gotoCase = 68; continue; }; } } else { if (yych <= 't') { - if (yych == 's') { gotoCase = 67; continue; }; - { gotoCase = 128; continue; }; + if (yych == 's') { gotoCase = 68; continue; }; + { gotoCase = 132; continue; }; } else { - if (yych == 'v') { gotoCase = 128; continue; }; - { gotoCase = 67; continue; }; + if (yych == 'v') { gotoCase = 132; continue; }; + { gotoCase = 68; continue; }; } } } @@ -1360,114 +1454,114 @@ case 130: 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; }; + if (yych == '\n') { gotoCase = 141; continue; }; + if (yych <= '\f') { gotoCase = 140; continue; }; + { gotoCase = 141; continue; }; } else { if (yych <= '\'') { - if (yych <= '&') { gotoCase = 136; continue; }; - { gotoCase = 139; continue; }; + if (yych <= '&') { gotoCase = 140; continue; }; + { gotoCase = 143; continue; }; } else { - if (yych == '\\') { gotoCase = 141; continue; }; - { gotoCase = 136; continue; }; + if (yych == '\\') { gotoCase = 145; continue; }; + { gotoCase = 140; continue; }; } } -case 135: +case 139: { return this._stringToken(cursor); } -case 136: +case 140: yyaccept = 0; yych = this._charAt(YYMARKER = ++cursor); - { gotoCase = 143; continue; }; -case 137: + { gotoCase = 147; continue; }; +case 141: ++cursor; -case 138: +case 142: { this.tokenType = null; return cursor; } -case 139: +case 143: ++cursor; -case 140: +case 144: this.setLexCondition(this._lexConditions.INITIAL); { return this._stringToken(cursor, true); } -case 141: +case 145: yych = this._charAt(++cursor); if (yych <= 'e') { if (yych <= '\'') { - if (yych == '"') { gotoCase = 142; continue; }; - if (yych <= '&') { gotoCase = 138; continue; }; + if (yych == '"') { gotoCase = 146; continue; }; + if (yych <= '&') { gotoCase = 142; continue; }; } else { if (yych <= '\\') { - if (yych <= '[') { gotoCase = 138; continue; }; + if (yych <= '[') { gotoCase = 142; continue; }; } else { - if (yych != 'b') { gotoCase = 138; continue; }; + if (yych != 'b') { gotoCase = 142; continue; }; } } } else { if (yych <= 'r') { if (yych <= 'm') { - if (yych >= 'g') { gotoCase = 138; continue; }; + if (yych >= 'g') { gotoCase = 142; continue; }; } else { - if (yych <= 'n') { gotoCase = 142; continue; }; - if (yych <= 'q') { gotoCase = 138; continue; }; + if (yych <= 'n') { gotoCase = 146; continue; }; + if (yych <= 'q') { gotoCase = 142; continue; }; } } else { if (yych <= 't') { - if (yych <= 's') { gotoCase = 138; continue; }; + if (yych <= 's') { gotoCase = 142; continue; }; } else { - if (yych != 'v') { gotoCase = 138; continue; }; + if (yych != 'v') { gotoCase = 142; continue; }; } } } -case 142: +case 146: yyaccept = 0; YYMARKER = ++cursor; yych = this._charAt(cursor); -case 143: +case 147: if (yych <= '\r') { - if (yych == '\n') { gotoCase = 135; continue; }; - if (yych <= '\f') { gotoCase = 142; continue; }; - { gotoCase = 135; continue; }; + if (yych == '\n') { gotoCase = 139; continue; }; + if (yych <= '\f') { gotoCase = 146; continue; }; + { gotoCase = 139; continue; }; } else { if (yych <= '\'') { - if (yych <= '&') { gotoCase = 142; continue; }; - { gotoCase = 146; continue; }; + if (yych <= '&') { gotoCase = 146; continue; }; + { gotoCase = 150; continue; }; } else { - if (yych != '\\') { gotoCase = 142; continue; }; + if (yych != '\\') { gotoCase = 146; continue; }; } } ++cursor; yych = this._charAt(cursor); if (yych <= 'e') { if (yych <= '\'') { - if (yych == '"') { gotoCase = 142; continue; }; - if (yych >= '\'') { gotoCase = 142; continue; }; + if (yych == '"') { gotoCase = 146; continue; }; + if (yych >= '\'') { gotoCase = 146; continue; }; } else { if (yych <= '\\') { - if (yych >= '\\') { gotoCase = 142; continue; }; + if (yych >= '\\') { gotoCase = 146; continue; }; } else { - if (yych == 'b') { gotoCase = 142; continue; }; + if (yych == 'b') { gotoCase = 146; continue; }; } } } else { if (yych <= 'r') { if (yych <= 'm') { - if (yych <= 'f') { gotoCase = 142; continue; }; + if (yych <= 'f') { gotoCase = 146; continue; }; } else { - if (yych <= 'n') { gotoCase = 142; continue; }; - if (yych >= 'r') { gotoCase = 142; continue; }; + if (yych <= 'n') { gotoCase = 146; continue; }; + if (yych >= 'r') { gotoCase = 146; continue; }; } } else { if (yych <= 't') { - if (yych >= 't') { gotoCase = 142; continue; }; + if (yych >= 't') { gotoCase = 146; continue; }; } else { - if (yych == 'v') { gotoCase = 142; continue; }; + if (yych == 'v') { gotoCase = 146; continue; }; } } } cursor = YYMARKER; - { gotoCase = 135; continue; }; -case 146: + { gotoCase = 139; continue; }; +case 150: ++cursor; yych = this._charAt(cursor); - { gotoCase = 140; continue; }; + { gotoCase = 144; continue; }; } } diff --git a/Source/WebCore/inspector/front-end/SourceCSSTokenizer.re2js b/Source/WebCore/inspector/front-end/SourceCSSTokenizer.re2js index 9e7b3ff22..f33f5a924 100644 --- a/Source/WebCore/inspector/front-end/SourceCSSTokenizer.re2js +++ b/Source/WebCore/inspector/front-end/SourceCSSTokenizer.re2js @@ -51,7 +51,7 @@ WebInspector.SourceCSSTokenizer = function() { WebInspector.SourceTokenizer.call(this); - this._propertyKeywords = WebInspector.CSSCompletions.cssPropertiesMetainfo.keySet(); + this._propertyKeywords = WebInspector.CSSCompletions.cssPropertiesMetainfoKeySet(); this._colorKeywords = WebInspector.CSSKeywordCompletions.colors(); this._valueKeywords = [ @@ -104,7 +104,12 @@ WebInspector.SourceCSSTokenizer = function() "-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._scssValueKeywords = [ + "abs", "adjust-color", "adjust-hue", "alpha", "append", "ceil", "change-color", "comparable", "complement", "darken", "desaturate", + "fade-in", "fade-out", "floor", "grayscale", "hue", "ie-hex-str", "invert", "join", "length", "lighten", + "lightness", "max", "min", "mix", "nth", "opacify", "opacity", "percentage", "quote", "round", "saturate", + "saturation", "scale-color", "transparentize", "type-of", "unit", "unitless", "unquote", "zip" + ].keySet(); this._lexConditions = { INITIAL: 0, @@ -129,6 +134,10 @@ WebInspector.SourceCSSTokenizer = function() this.condition = this.createInitialCondition(); } +WebInspector.SourceCSSTokenizer.SCSSAtRelatedKeywords = ["from", "if", "in", "through"].keySet(); + +WebInspector.SourceCSSTokenizer.MediaTypes = ["all", "aural", "braille", "embossed", "handheld", "import", "print", "projection", "screen", "tty", "tv"].keySet(); + WebInspector.SourceCSSTokenizer.prototype = { createInitialCondition: function() { @@ -152,6 +161,11 @@ WebInspector.SourceCSSTokenizer.prototype = { return this._condition.parseCondition === this._parseConditions.PROPERTY_VALUE || this._condition.parseCondition === this._parseConditions.AT_RULE; }, + _setParseCondition: function(condition) + { + this._condition.parseCondition = condition; + }, + nextToken: function(cursor) { var cursorOnEnter = cursor; @@ -186,8 +200,9 @@ WebInspector.SourceCSSTokenizer.prototype = { NumericLiteral = "-"? ([0-9]+ | [0-9]* "." [0-9]+) ("em" | "rem" | "__qem" | "ex" | "px" | "cm" | "mm" | "in" | "pt" | "pc" | "deg" | "rad" | "grad" | "turn" | "ms" | "s" | "Hz" | "kHz" | "%")?; - Color = "#" [0-9A-Fa-f]+; - Identifier = [@!_\-$0-9a-zA-Z\[\]='"/]+; + ColorOrSelector = "#" [0-9A-Za-z]+; + Identifier = [@!_\-0-9a-zA-Z\[\]='"/&]+; + Variable = "$" Identifier; DoubleStringContent = ([^\r\n\"\\] | "\\" ['"\\bfnrtv])*; SingleStringContent = ([^\r\n\'\\] | "\\" ['"\\bfnrtv])*; @@ -213,35 +228,37 @@ WebInspector.SourceCSSTokenizer.prototype = { <INITIAL> OpenCurlyBracket { this.tokenType = "block-start"; + this._condition.openBraces = (this._condition.openBraces || 0) + 1; if (this._condition.parseCondition === this._parseConditions.AT_MEDIA_RULE) - this._condition.parseCondition = this._parseConditions.INITIAL; + this._setParseCondition(this._parseConditions.INITIAL); else - this._condition.parseCondition = this._parseConditions.PROPERTY; + this._setParseCondition(this._parseConditions.PROPERTY); return cursor; } <INITIAL> CloseCurlyBracket { this.tokenType = "block-end"; - this._condition.parseCondition = this._parseConditions.INITIAL; + if (this._condition.openBraces > 0) + --this._condition.openBraces; + this._setParseCondition(this._condition.openBraces ? this._parseConditions.PROPERTY : this._parseConditions.INITIAL); + delete this._condition.atKeyword; return cursor; } <INITIAL> Colon { this.tokenType = null; - if (this._condition.parseCondition === this._parseConditions.PROPERTY) - this._condition.parseCondition = this._parseConditions.PROPERTY_VALUE; + if (this._condition.parseCondition === this._parseConditions.PROPERTY || this._condition.parseCondition === this._parseConditions.INITIAL) + this._setParseCondition(this._parseConditions.PROPERTY_VALUE); return cursor; } <INITIAL> Semicolon { this.tokenType = null; - if (this._condition.parseCondition === this._parseConditions.AT_RULE) - this._condition.parseCondition = this._parseConditions.INITIAL; - else - this._condition.parseCondition = this._parseConditions.PROPERTY; + this._setParseCondition(this._condition.openBraces ? this._parseConditions.PROPERTY : this._parseConditions.INITIAL); + delete this._condition.atKeyword; return cursor; } @@ -254,41 +271,63 @@ WebInspector.SourceCSSTokenizer.prototype = { return cursor; } - <INITIAL> Color + <INITIAL> ColorOrSelector { if (this._isPropertyValue()) this.tokenType = "css-color"; + else if (this._condition.parseCondition === this._parseConditions.INITIAL) + this.tokenType = "css-selector"; else this.tokenType = null; return cursor; } + <INITIAL> Variable + { + if (this._condition.parseCondition === this._condition.parseCondition.INITIAL || this._condition.parseCondition === this._condition.parseCondition.AT_RULE) + this._setParseCondition(this._parseConditions.PROPERTY); + this.tokenType = "scss-variable"; + return cursor; + } + <INITIAL> Identifier { var token = this._line.substring(cursorOnEnter, cursor); - if (this._condition.parseCondition === this._parseConditions.INITIAL) { - if (token === "@media") { + this.tokenType = null; + if (this._condition.parseCondition === this._parseConditions.INITIAL || this._condition.parseCondition === this._parseConditions.PROPERTY) { + if (token.charAt(0) === "@") { this.tokenType = "css-at-rule"; - this._condition.parseCondition = this._parseConditions.AT_MEDIA_RULE; - } else if (token.startsWith("@")) { + this._setParseCondition(token === "@media" ? this._parseConditions.AT_MEDIA_RULE : this._parseConditions.AT_RULE); + this._condition.atKeyword = token; + } else if (this._condition.parseCondition === this._parseConditions.INITIAL) + this.tokenType = "css-selector"; + else if (this._propertyKeywords.hasOwnProperty(token)) + this.tokenType = "css-property"; + } else if (this._condition.parseCondition === this._parseConditions.AT_MEDIA_RULE || this._condition.parseCondition === this._parseConditions.AT_RULE) { + if (WebInspector.SourceCSSTokenizer.SCSSAtRelatedKeywords.hasOwnProperty(token)) this.tokenType = "css-at-rule"; - this._condition.parseCondition = this._parseConditions.AT_RULE; - } else + else if (WebInspector.SourceCSSTokenizer.MediaTypes.hasOwnProperty(token)) + this.tokenType = "css-keyword"; + } + if (this.tokenType) + return cursor; + + if (this._isPropertyValue()) { + var firstChar = token.charAt(0); + if (firstChar === "$") + this.tokenType = "scss-variable"; + else if (firstChar === "!") + this.tokenType = "css-bang-keyword"; + else if (this._condition.atKeyword === "@extend") 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) + else if (this._valueKeywords.hasOwnProperty(token) || this._scssValueKeywords.hasOwnProperty(token)) this.tokenType = "css-keyword"; - else if (token in this._colorKeywords) { + else if (this._colorKeywords.hasOwnProperty(token)) { // 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; + } + } else if (this._condition.parseCondition !== this._parseConditions.PROPERTY_VALUE) + this.tokenType = "css-selector"; return cursor; } <*> [^] { this.tokenType = null; return cursor; } diff --git a/Source/WebCore/inspector/front-end/SourceFrame.js b/Source/WebCore/inspector/front-end/SourceFrame.js index 2f498f3a0..cb930e14f 100644 --- a/Source/WebCore/inspector/front-end/SourceFrame.js +++ b/Source/WebCore/inspector/front-end/SourceFrame.js @@ -695,6 +695,17 @@ WebInspector.TextEditorDelegateForSourceFrame.prototype = { populateTextAreaContextMenu: function(contextMenu, lineNumber) { this._sourceFrame.populateTextAreaContextMenu(contextMenu, lineNumber); + }, + + /** + * @param {string} hrefValue + * @param {boolean} isExternal + * @return {Element} + */ + createLink: function(hrefValue, isExternal) + { + var targetLocation = WebInspector.ParsedURL.completeURL(this._sourceFrame._url, hrefValue); + return WebInspector.linkifyURLAsNode(targetLocation || hrefValue, hrefValue, undefined, isExternal); } } diff --git a/Source/WebCore/inspector/front-end/SourceTokenizer.js b/Source/WebCore/inspector/front-end/SourceTokenizer.js index 7a8a6acfb..9ae78a65d 100644 --- a/Source/WebCore/inspector/front-end/SourceTokenizer.js +++ b/Source/WebCore/inspector/front-end/SourceTokenizer.js @@ -83,7 +83,8 @@ WebInspector.SourceTokenizer.Registry = function() { this._tokenizerConstructors = { "text/css": "SourceCSSTokenizer", "text/html": "SourceHTMLTokenizer", - "text/javascript": "SourceJavaScriptTokenizer" + "text/javascript": "SourceJavaScriptTokenizer", + "text/x-scss": "SourceCSSTokenizer" }; } diff --git a/Source/WebCore/inspector/front-end/StyleSheetOutlineDialog.js b/Source/WebCore/inspector/front-end/StyleSheetOutlineDialog.js index c251072b2..25141bda0 100644 --- a/Source/WebCore/inspector/front-end/StyleSheetOutlineDialog.js +++ b/Source/WebCore/inspector/front-end/StyleSheetOutlineDialog.js @@ -68,11 +68,20 @@ WebInspector.StyleSheetOutlineDialog.prototype = { * @param {number} itemIndex * @return {string} */ - itemSubtitleAt: function(itemIndex) + itemSuffixAt: function(itemIndex) { return ""; }, + /* + * @param {number} itemIndex + * @return {string} + */ + itemSubtitleAt: function(itemIndex) + { + return ":" + (this._rules[itemIndex].sourceLine + 1); + }, + /** * @param {number} itemIndex * @return {string} diff --git a/Source/WebCore/inspector/front-end/StyleSource.js b/Source/WebCore/inspector/front-end/StyleSource.js index 6e3873a91..4d21f518a 100644 --- a/Source/WebCore/inspector/front-end/StyleSource.js +++ b/Source/WebCore/inspector/front-end/StyleSource.js @@ -28,94 +28,6 @@ /** * @constructor - * @extends {WebInspector.Object} - * @implements {WebInspector.UISourceCodeProvider} - * @implements {WebInspector.SourceMapping} - */ -WebInspector.StylesUISourceCodeProvider = function() -{ - /** - * @type {Array.<WebInspector.UISourceCode>} - */ - this._uiSourceCodes = []; - this._uiSourceCodeForURL = {}; - WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.ResourceAdded, this._resourceAdded, this); -} - -WebInspector.StylesUISourceCodeProvider.prototype = { - /** - * @return {Array.<WebInspector.UISourceCode>} - */ - uiSourceCodes: function() - { - return this._uiSourceCodes; - }, - - /** - * @param {WebInspector.RawLocation} rawLocation - * @return {WebInspector.UILocation} - */ - rawLocationToUILocation: function(rawLocation) - { - var location = /** @type WebInspector.CSSLocation */ rawLocation; - var uiSourceCode = this._uiSourceCodeForURL[location.url]; - return new WebInspector.UILocation(uiSourceCode, location.lineNumber, 0); - }, - - /** - * @param {WebInspector.UISourceCode} uiSourceCode - * @param {number} lineNumber - * @param {number} columnNumber - * @return {WebInspector.RawLocation} - */ - uiLocationToRawLocation: function(uiSourceCode, lineNumber, columnNumber) - { - return new WebInspector.CSSLocation(uiSourceCode.contentURL() || "", lineNumber); - }, - - _populate: function() - { - function populateFrame(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); - }, - - /** - * @param {WebInspector.Event} event - */ - _resourceAdded: function(event) - { - var resource = /** @type {WebInspector.Resource} */ event.data; - if (resource.type !== WebInspector.resourceTypes.Stylesheet) - return; - var uiSourceCode = new WebInspector.StyleSource(resource); - this._uiSourceCodes.push(uiSourceCode); - this._uiSourceCodeForURL[resource.url] = uiSourceCode; - WebInspector.cssModel.setSourceMapping(resource.url, this); - this.dispatchEventToListeners(WebInspector.UISourceCodeProvider.Events.UISourceCodeAdded, uiSourceCode); - }, - - reset: function() - { - this._uiSourceCodes = []; - this._uiSourceCodeForURL = {}; - WebInspector.cssModel.resetSourceMappings(); - this._populate(); - } -} - -WebInspector.StylesUISourceCodeProvider.prototype.__proto__ = WebInspector.Object.prototype; - -/** - * @constructor * @extends {WebInspector.UISourceCode} * @param {WebInspector.Resource} resource */ diff --git a/Source/WebCore/inspector/front-end/StylesSidebarPane.js b/Source/WebCore/inspector/front-end/StylesSidebarPane.js index f0fbb4811..04678b094 100644 --- a/Source/WebCore/inspector/front-end/StylesSidebarPane.js +++ b/Source/WebCore/inspector/front-end/StylesSidebarPane.js @@ -134,9 +134,11 @@ WebInspector.StylesSidebarPane.canonicalPropertyName = function(name) WebInspector.StylesSidebarPane.prototype = { _contextMenuEventFired: function(event) { + // We start editing upon click -> default navigation to resources panel is not available + // Hence we add a soft context menu for hrefs. var contextMenu = new WebInspector.ContextMenu(); - if (WebInspector.populateHrefContextMenu(contextMenu, this.node, event)) - contextMenu.show(event); + contextMenu.appendApplicableItems(event.target); + contextMenu.show(event); }, get _forcedPseudoClasses() @@ -410,7 +412,7 @@ WebInspector.StylesSidebarPane.prototype = { 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) }; + var styleRule = { section: section, style: section.styleRule.style, computedStyle: section.computedStyle, rule: section.rule, editable: !!(section.styleRule.style && section.styleRule.style.id), isAttribute: section.styleRule.isAttribute }; styleRules.push(styleRule); } return styleRules; @@ -504,9 +506,8 @@ WebInspector.StylesSidebarPane.prototype = { _markUsedProperties: function(styleRules, usedProperties) { - var priorityUsed = false; - - // Walk the style rules and make a list of all used and overloaded properties. + var foundImportantProperties = {}; + var propertyToEffectiveRule = {}; for (var i = 0; i < styleRules.length; ++i) { var styleRule = styleRules[i]; if (styleRule.computedStyle || styleRule.isStyleSeparator) @@ -524,47 +525,22 @@ WebInspector.StylesSidebarPane.prototype = { continue; var canonicalName = WebInspector.StylesSidebarPane.canonicalPropertyName(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 (!(canonicalName in usedProperties)) - styleRule.usedProperties[canonicalName] = 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 canonicalName in styleRules[i].usedProperties) - usedProperties[canonicalName] = true; - } - - if (priorityUsed) { - // Walk the properties again and account for !important. - var foundPriorityProperties = {}; + if (foundImportantProperties.hasOwnProperty(canonicalName)) + continue; - // 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) + var isImportant = property.priority.length; + if (!isImportant && usedProperties.hasOwnProperty(canonicalName)) 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 canonicalName = WebInspector.StylesSidebarPane.canonicalPropertyName(property.name); - if (property.priority.length) { - if (!(canonicalName in foundPriorityProperties)) - styleRules[i].usedProperties[canonicalName] = true; - else - delete styleRules[i].usedProperties[canonicalName]; - foundPriorityProperties[canonicalName] = true; - } else if (canonicalName in foundPriorityProperties) - delete styleRules[i].usedProperties[canonicalName]; + if (isImportant) { + foundImportantProperties[canonicalName] = true; + if (propertyToEffectiveRule.hasOwnProperty(canonicalName)) + delete propertyToEffectiveRule[canonicalName].usedProperties[canonicalName]; } + + styleRule.usedProperties[canonicalName] = true; + usedProperties[canonicalName] = true; + propertyToEffectiveRule[canonicalName] = styleRule; } } }, @@ -621,10 +597,9 @@ WebInspector.StylesSidebarPane.prototype = { editable = true; if (computedStyle) - var section = new WebInspector.ComputedStylePropertiesSection(styleRule, usedProperties); + var section = new WebInspector.ComputedStylePropertiesSection(this, styleRule, usedProperties); else var section = new WebInspector.StylePropertiesSection(this, styleRule, editable, styleRule.isInherited, lastWasSeparator); - section.pane = this; section.expanded = true; if (computedStyle) { @@ -693,7 +668,6 @@ WebInspector.StylesSidebarPane.prototype = { 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); @@ -958,6 +932,11 @@ WebInspector.StylePropertiesSection = function(parentPane, styleRule, editable, } WebInspector.StylePropertiesSection.prototype = { + get pane() + { + return this._parentPane; + }, + collapse: function(dontRememberState) { // Overriding with empty body. @@ -1341,12 +1320,16 @@ WebInspector.StylePropertiesSection.prototype.__proto__ = WebInspector.Propertie /** * @constructor * @extends {WebInspector.PropertiesSection} + * @param {!WebInspector.StylesSidebarPane} parentPane + * @param {!Object} styleRule + * @param {!Object.<string, boolean>} usedProperties */ -WebInspector.ComputedStylePropertiesSection = function(styleRule, usedProperties) +WebInspector.ComputedStylePropertiesSection = function(parentPane, styleRule, usedProperties) { WebInspector.PropertiesSection.call(this, ""); this.headerElement.addStyleClass("hidden"); this.element.className = "styles-section monospace first-styles-section read-only computed-style"; + this._parentPane = parentPane; this.styleRule = styleRule; this._usedProperties = usedProperties; this._alwaysShowComputedProperties = { "display": true, "height": true, "width": true }; @@ -1356,6 +1339,11 @@ WebInspector.ComputedStylePropertiesSection = function(styleRule, usedProperties } WebInspector.ComputedStylePropertiesSection.prototype = { + get pane() + { + return this._parentPane; + }, + collapse: function(dontRememberState) { // Overriding with empty body. @@ -1400,7 +1388,7 @@ WebInspector.ComputedStylePropertiesSection.prototype = { for (var i = 0; i < uniqueProperties.length; ++i) { var property = uniqueProperties[i]; var inherited = this._isPropertyInherited(property.name); - var item = new WebInspector.StylePropertyTreeElement(this, null, this.styleRule, style, property, false, inherited, false); + var item = new WebInspector.StylePropertyTreeElement(this, this._parentPane, this.styleRule, style, property, false, inherited, false); this.propertiesTreeOutline.appendChild(item); this._propertyTreeElements[property.name] = item; } @@ -1718,8 +1706,8 @@ WebInspector.StylePropertyTreeElement.prototype = { container.appendChild(document.createTextNode("url(")); if (self._styleRule.sourceURL) hrefUrl = WebInspector.ParsedURL.completeURL(self._styleRule.sourceURL, hrefUrl); - else if (this._parentPane.node) - hrefUrl = WebInspector.resourceURLForRelatedNode(this._parentPane.node, hrefUrl); + else if (self._parentPane.node) + hrefUrl = self._parentPane.node.resolveURL(hrefUrl); var hasResource = !!WebInspector.resourceForURL(hrefUrl); // FIXME: WebInspector.linkifyURLAsNode() should really use baseURI. container.appendChild(WebInspector.linkifyURLAsNode(hrefUrl, url, undefined, !hasResource)); diff --git a/Source/WebCore/inspector/front-end/StylesSourceMapping.js b/Source/WebCore/inspector/front-end/StylesSourceMapping.js new file mode 100644 index 000000000..0767e9ae0 --- /dev/null +++ b/Source/WebCore/inspector/front-end/StylesSourceMapping.js @@ -0,0 +1,95 @@ +/* + * 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 + * @implements {WebInspector.SourceMapping} + * @param {WebInspector.Workspace} workspace + */ +WebInspector.StylesSourceMapping = function(workspace) +{ + this._workspace = workspace; + this._workspace.addEventListener(WebInspector.Workspace.Events.ProjectWillReset, this._reset, this); + this._workspace.addEventListener(WebInspector.UISourceCodeProvider.Events.UISourceCodeAdded, this._uiSourceCodeAddedToWorkspace, this); + + this._uiSourceCodeForURL = {}; +} + +WebInspector.StylesSourceMapping.prototype = { + /** + * @param {WebInspector.RawLocation} rawLocation + * @return {WebInspector.UILocation} + */ + rawLocationToUILocation: function(rawLocation) + { + var location = /** @type WebInspector.CSSLocation */ rawLocation; + var uiSourceCode = this._uiSourceCodeForURL[location.url]; + return new WebInspector.UILocation(uiSourceCode, location.lineNumber, 0); + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + * @param {number} lineNumber + * @param {number} columnNumber + * @return {WebInspector.RawLocation} + */ + uiLocationToRawLocation: function(uiSourceCode, lineNumber, columnNumber) + { + return new WebInspector.CSSLocation(uiSourceCode.contentURL() || "", lineNumber); + }, + + _uiSourceCodeAddedToWorkspace: function(event) + { + var uiSourceCode = /** @type {WebInspector.UISourceCode} */ event.data; + if (!uiSourceCode.url || this._uiSourceCodeForURL[uiSourceCode.url]) + return; + if (uiSourceCode.contentType() !== WebInspector.resourceTypes.StyleSheet) + return; + + this._addUISourceCode(uiSourceCode); + }, + + /** + * @param {WebInspector.UISourceCode} uiSourceCode + */ + _addUISourceCode: function(uiSourceCode) + { + this._uiSourceCodeForURL[uiSourceCode.url] = uiSourceCode; + uiSourceCode.setSourceMapping(this); + WebInspector.cssModel.setSourceMapping(uiSourceCode.url, this); + }, + + _reset: function() + { + this._uiSourceCodeForURL = {}; + WebInspector.cssModel.resetSourceMappings(); + } +} + diff --git a/Source/WebCore/inspector/front-end/TextEditor.js b/Source/WebCore/inspector/front-end/TextEditor.js index 4be8f0d81..c4494385d 100644 --- a/Source/WebCore/inspector/front-end/TextEditor.js +++ b/Source/WebCore/inspector/front-end/TextEditor.js @@ -236,6 +236,12 @@ WebInspector.TextEditorDelegate.prototype = { * @param {WebInspector.ContextMenu} contextMenu * @param {number} lineNumber */ - populateTextAreaContextMenu: function(contextMenu, lineNumber) { } -} + populateTextAreaContextMenu: function(contextMenu, lineNumber) { }, + /** + * @param {string} hrefValue + * @param {boolean} isExternal + * @return {Element} + */ + createLink: function(hrefValue, isExternal) { } +} diff --git a/Source/WebCore/inspector/front-end/TimelineGrid.js b/Source/WebCore/inspector/front-end/TimelineGrid.js index a0cd7c85c..4323fcb60 100644 --- a/Source/WebCore/inspector/front-end/TimelineGrid.js +++ b/Source/WebCore/inspector/front-end/TimelineGrid.js @@ -87,7 +87,7 @@ WebInspector.TimelineGrid.prototype = { { var dividersElementClientWidth = this._dividersElement.clientWidth; var dividerCount = Math.round(dividersElementClientWidth / 64); - var slice = calculator.boundarySpan / dividerCount; + var slice = calculator.boundarySpan() / dividerCount; this._currentDividerSlice = slice; diff --git a/Source/WebCore/inspector/front-end/TimelineModel.js b/Source/WebCore/inspector/front-end/TimelineModel.js index dff3044b2..74e635b2d 100644 --- a/Source/WebCore/inspector/front-end/TimelineModel.js +++ b/Source/WebCore/inspector/front-end/TimelineModel.js @@ -43,14 +43,18 @@ WebInspector.TimelineModel = function() WebInspector.timelineManager.addEventListener(WebInspector.TimelineManager.EventTypes.TimelineEventRecorded, this._onRecordAdded, this); } +WebInspector.TimelineModel.TransferChunkLengthBytes = 5000000; + WebInspector.TimelineModel.RecordType = { Root: "Root", Program: "Program", EventDispatch: "EventDispatch", BeginFrame: "BeginFrame", - Layout: "Layout", + ScheduleStyleRecalculation: "ScheduleStyleRecalculation", RecalculateStyles: "RecalculateStyles", + InvalidateLayout: "InvalidateLayout", + Layout: "Layout", Paint: "Paint", DecodeImage: "DecodeImage", ResizeImage: "ResizeImage", @@ -115,7 +119,7 @@ WebInspector.TimelineModel.aggregateTimeForRecord = function(total, rawRecord) { var childrenTime = 0; var children = rawRecord["children"] || []; - for (var i = 0; i < children.length; ++i) { + for (var i = 0; i < children.length; ++i) { WebInspector.TimelineModel.aggregateTimeForRecord(total, children[i]); childrenTime += WebInspector.TimelineModel.durationInSeconds(children[i]); } @@ -162,90 +166,15 @@ WebInspector.TimelineModel.prototype = { }, /** - * @param {WebInspector.Progress} progress - * @param {Array.<Object>} data - * @param {number} index - */ - _loadNextChunk: function(progress, data, index) - { - if (progress.isCanceled()) { - this.reset(); - progress.done(); - return; - } - progress.setWorked(index); - - for (var i = 0; i < 100 && index < data.length; ++i, ++index) - this._addRecord(data[index]); - - if (index !== data.length) - setTimeout(this._loadNextChunk.bind(this, progress, data, index), 0); - else - progress.done(); - }, - - /** * @param {!Blob} file - * @param {WebInspector.Progress} progress + * @param {!WebInspector.Progress} progress */ loadFromFile: function(file, progress) { - var compositeProgress = new WebInspector.CompositeProgress(progress); - var loadingProgress = compositeProgress.createSubProgress(1); - var parsingProgress = compositeProgress.createSubProgress(1); - var processingProgress = compositeProgress.createSubProgress(1); - - function parseAndImportData(data) - { - try { - var records = JSON.parse(data); - parsingProgress.done(); - this.reset(); - processingProgress.setTotalWork(records.length); - this._loadNextChunk(processingProgress, records, 1); - } catch (e) { - WebInspector.showErrorMessage("Malformed timeline data."); - progress.done(); - } - } - - function onLoad(e) - { - loadingProgress.done(); - parsingProgress.setTotalWork(1); - setTimeout(parseAndImportData.bind(this, e.target.result), 0); - } - - function onError(e) - { - progress.done(); - switch(e.target.error.code) { - case e.target.error.NOT_FOUND_ERR: - WebInspector.showErrorMessage(WebInspector.UIString("File \"%s\" not found.", file.name)); - break; - case e.target.error.NOT_READABLE_ERR: - WebInspector.showErrorMessage(WebInspector.UIString("File \"%s\" is not readable", file.name)); - break; - case e.target.error.ABORT_ERR: - break; - default: - WebInspector.showErrorMessage(WebInspector.UIString("An error occurred while reading the file \"%s\"", file.name)); - } - } - - function onProgress(e) - { - if (e.lengthComputable) - loadingProgress.setWorked(e.loaded / e.total); - } - - var reader = new FileReader(); - reader.onload = onLoad.bind(this); - reader.onerror = onError; - reader.onprogress = onProgress; - loadingProgress.setTitle(WebInspector.UIString("Loading\u2026")); - loadingProgress.setTotalWork(1); - reader.readAsText(file); + var delegate = new WebInspector.TimelineModelLoadFromFileDelegate(this, progress); + var fileReader = this._createFileReader(file, delegate); + var loader = new WebInspector.TimelineModelLoader(this, fileReader, progress); + fileReader.start(loader); }, /** @@ -253,46 +182,30 @@ WebInspector.TimelineModel.prototype = { */ loadFromURL: function(url, progress) { - var compositeProgress = new WebInspector.CompositeProgress(progress); - var loadingProgress = compositeProgress.createSubProgress(1); - var parsingProgress = compositeProgress.createSubProgress(1); - var processingProgress = compositeProgress.createSubProgress(1); - - // FIXME: extract parsing routines so that they did not require too many progress objects. - function parseAndImportData(data) - { - try { - var records = JSON.parse(data); - parsingProgress.done(); - this.reset(); - processingProgress.setTotalWork(records.length); - this._loadNextChunk(processingProgress, records, 1); - } catch (e) { - WebInspector.showErrorMessage("Malformed timeline data."); - progress.done(); - } - } + var delegate = new WebInspector.TimelineModelLoadFromFileDelegate(this, progress); + var urlReader = new WebInspector.ChunkedXHRReader(url, delegate); + var loader = new WebInspector.TimelineModelLoader(this, urlReader, progress); + urlReader.start(loader); + }, - var responseText = loadXHR(url); - if (responseText) { - loadingProgress.done(); - parsingProgress.setTotalWork(1); - setTimeout(parseAndImportData.bind(this, responseText), 0); - } + _createFileReader: function(file, delegate) + { + return new WebInspector.ChunkedFileReader(file, WebInspector.TimelineModel.TransferChunkLengthBytes, delegate); }, 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 fileName = "TimelineRawData-" + now.toISO8601Compact() + ".json"; - WebInspector.fileManager.save(fileName, records.join(",\n"), true); + var delegate = new WebInspector.TimelineModelWriteToFileDelegate(this._records, window.navigator.appVersion); + var writer = this._createFileWriter(fileName, delegate); + writer.startTransfer(); + }, + + _createFileWriter: function(fileName, delegate) + { + return new WebInspector.FileOutputStream(fileName, delegate); }, reset: function() @@ -335,3 +248,192 @@ WebInspector.TimelineModel.prototype = { } WebInspector.TimelineModel.prototype.__proto__ = WebInspector.Object.prototype; + +/** + * @constructor + * @implements {WebInspector.OutputStream} + * @param {!WebInspector.TimelineModel} model + * @param {!{cancel: function()}} reader + * @param {!WebInspector.Progress} progress + */ +WebInspector.TimelineModelLoader = function(model, reader, progress) +{ + this._model = model; + this._reader = reader; + this._progress = progress; + this._buffer = ""; +} + +WebInspector.TimelineModelLoader.prototype = { + startTransfer: function() + { + this._model.reset(); + this._firstChunk = true; + return true; + }, + + /** + * @param {string} chunk + */ + transferChunk: function(chunk) + { + var data = this._buffer + chunk; + var lastIndex = 0; + var index; + do { + index = lastIndex; + lastIndex = WebInspector.findBalancedCurlyBrackets(data, index); + } while (lastIndex !== -1) + + var json = data.slice(0, index) + "]"; + this._buffer = data.slice(index); + + if (!index) + return; + + // Prepending "0" to turn string into valid JSON. + if (!this._firstChunk) + json = "[0" + json; + + var items; + try { + items = /** @type {Array} */ JSON.parse(json); + } catch (e) { + WebInspector.showErrorMessage("Malformed timeline data."); + this._model.reset(); + this._reader.cancel(); + this._progress.done(); + return; + } + + if (this._firstChunk) { + this._version = items[0]; + this._firstChunk = false; + } + + // Skip 0-th element - it is either version or 0. + for (var i = 1, size = items.length; i < size; ++i) + this._model._addRecord(items[i]); + }, + + finishTransfer: function() { }, + + dispose: function() { } +} + +/** + * @constructor + * @implements {WebInspector.OutputStreamDelegate} + * @param {!WebInspector.TimelineModel} model + * @param {!WebInspector.Progress} progress + */ +WebInspector.TimelineModelLoadFromFileDelegate = function(model, progress) +{ + this._model = model; + this._progress = progress; +} + +WebInspector.TimelineModelLoadFromFileDelegate.prototype = { + onTransferStarted: function(reader) + { + this._progress.setTitle(WebInspector.UIString("Loading\u2026")); + }, + + onChunkTransferred: function(reader) + { + if (this._progress.isCanceled()) { + reader.cancel(); + this._progress.done(); + this._model.reset(); + return; + } + + var totalSize = reader.fileSize(); + if (totalSize) { + this._progress.setTotalWork(totalSize); + this._progress.setWorked(reader.loadedSize()); + } + }, + + onTransferFinished: function(reader) + { + this._progress.done(); + }, + + onError: function(reader, event) + { + this._progress.done(); + this._model.reset(); + switch (event.target.error.code) { + case FileError.NOT_FOUND_ERR: + WebInspector.showErrorMessage(WebInspector.UIString("File \"%s\" not found.", reader.fileName())); + break; + case FileError.NOT_READABLE_ERR: + WebInspector.showErrorMessage(WebInspector.UIString("File \"%s\" is not readable", reader.fileName())); + break; + case FileError.ABORT_ERR: + break; + default: + WebInspector.showErrorMessage(WebInspector.UIString("An error occurred while reading the file \"%s\"", reader.fileName())); + } + } +} + +/** + * @constructor + * @implements WebInspector.OutputStreamDelegate + * @param {Array} records + * @param {string} version + */ +WebInspector.TimelineModelWriteToFileDelegate = function(records, version) +{ + this._records = records; + this._recordIndex = 0; + this._prologue = "[" + JSON.stringify(new String(version)); +} + +WebInspector.TimelineModelWriteToFileDelegate.prototype = { + onTransferStarted: function(writer) + { + this._pushChunk(writer); + }, + + onChunkTransferred: function(writer) + { + if (this._recordIndex === this._records.length) + writer.finishTransfer(); + else + this._pushChunk(writer); + }, + + onTransferFinished: function(writer) { }, + + onError: function(writer, event) { }, + + _pushChunk: function(writer) + { + const separator = ",\n"; + var data = []; + var length = 0; + + if (this._prologue) { + data.push(this._prologue); + length += this._prologue.length; + delete this._prologue; + } else + data.push(""); + + while (this._recordIndex < this._records.length) { + var item = JSON.stringify(this._records[this._recordIndex]); + var itemLength = item.length + separator.length; + if (length + itemLength > WebInspector.TimelineModel.TransferChunkLengthBytes) + break; + length += itemLength; + data.push(item); + ++this._recordIndex; + } + if (this._recordIndex === this._records.length) + data.push(data.pop() + "]"); + writer.transferChunk(data.join(separator)); + } +} diff --git a/Source/WebCore/inspector/front-end/TimelinePanel.js b/Source/WebCore/inspector/front-end/TimelinePanel.js index dbfd8a8c0..d4c0ce6fe 100644 --- a/Source/WebCore/inspector/front-end/TimelinePanel.js +++ b/Source/WebCore/inspector/front-end/TimelinePanel.js @@ -46,8 +46,11 @@ WebInspector.TimelinePanel = function() this._model = new WebInspector.TimelineModel(); this._presentationModel = new WebInspector.TimelinePresentationModel(); + this._overviewModeSetting = WebInspector.settings.createSetting("timelineOverviewMode", WebInspector.TimelineOverviewPane.Mode.Events); + this._glueRecordsSetting = WebInspector.settings.createSetting("timelineGlueRecords", true); + this._overviewPane = new WebInspector.TimelineOverviewPane(this._model); - this._overviewPane.addEventListener(WebInspector.TimelineOverviewPane.Events.WindowChanged, this._scheduleRefresh.bind(this, false)); + this._overviewPane.addEventListener(WebInspector.TimelineOverviewPane.Events.WindowChanged, this._invalidateAndScheduleRefresh.bind(this, false)); this._overviewPane.addEventListener(WebInspector.TimelineOverviewPane.Events.ModeChanged, this._overviewModeChanged, this); this._overviewPane.show(this.element); @@ -145,8 +148,6 @@ WebInspector.TimelinePanel = function() this._presentationModel.addFilter(this._overviewPane); this._presentationModel.addFilter(new WebInspector.TimelineCategoryFilter()); this._presentationModel.addFilter(new WebInspector.TimelineIsLongFilter(this)); - - this._overviewModeSetting = WebInspector.settings.createSetting("timelineOverviewMode", WebInspector.TimelineOverviewPane.Mode.Events); } // Define row height, should be in sync with styles for timeline graphs. @@ -235,8 +236,8 @@ WebInspector.TimelinePanel.prototype = { this._statusBarButtons.push(this.garbageCollectButton); this._glueParentButton = new WebInspector.StatusBarButton(WebInspector.UIString("Glue asynchronous events to causes"), "glue-async-status-bar-item"); - this._glueParentButton.toggled = true; - this._presentationModel.setGlueRecords(true); + this._glueParentButton.toggled = this._glueRecordsSetting.get(); + this._presentationModel.setGlueRecords(this._glueParentButton.toggled); this._glueParentButton.addEventListener("click", this._glueParentButtonClicked, this); this._statusBarButtons.push(this._glueParentButton); @@ -283,7 +284,7 @@ WebInspector.TimelinePanel.prototype = { _onCategoryCheckboxClicked: function(category, event) { category.hidden = !event.target.checked; - this._scheduleRefresh(true); + this._invalidateAndScheduleRefresh(true); }, /** @@ -529,7 +530,7 @@ WebInspector.TimelinePanel.prototype = { this._showShortEvents = this.toggleFilterButton.toggled; this._overviewPane.setShowShortEvents(this._showShortEvents); this.toggleFilterButton.element.title = this._showShortEvents ? this._hideShortRecordsTitleText : this._showShortRecordsTitleText; - this._scheduleRefresh(true); + this._invalidateAndScheduleRefresh(true); }, _garbageCollectButtonClicked: function() @@ -539,24 +540,27 @@ WebInspector.TimelinePanel.prototype = { _glueParentButtonClicked: function() { - this._glueParentButton.toggled = !this._glueParentButton.toggled; - this._presentationModel.setGlueRecords(this._glueParentButton.toggled); + var newValue = !this._glueParentButton.toggled; + this._glueParentButton.toggled = newValue; + this._presentationModel.setGlueRecords(newValue); + this._glueRecordsSetting.set(newValue); this._repopulateRecords(); }, _repopulateRecords: function() { this._resetPanel(); + this._automaticallySizeWindow = false; var records = this._model.records; for (var i = 0; i < records.length; ++i) this._innerAddRecordToTimeline(records[i], this._rootRecord()); - this._scheduleRefresh(false); + this._invalidateAndScheduleRefresh(false); }, _onTimelineEventRecorded: function(event) { if (this._innerAddRecordToTimeline(event.data, this._rootRecord())) - this._scheduleRefresh(false); + this._invalidateAndScheduleRefresh(false); }, _innerAddRecordToTimeline: function(record, parentRecord) @@ -618,7 +622,7 @@ WebInspector.TimelinePanel.prototype = { _onRecordsCleared: function() { this._resetPanel(); - this._refresh(); + this._invalidateAndScheduleRefresh(true); }, _resetPanel: function() @@ -664,6 +668,15 @@ WebInspector.TimelinePanel.prototype = { this._scheduleRefresh(true); }, + _invalidateAndScheduleRefresh: function(preserveBoundaries) + { + this._presentationModel.invalidateFilteredRecords(); + this._scheduleRefresh(preserveBoundaries); + }, + + /** + * @param {boolean} preserveBoundaries + */ _scheduleRefresh: function(preserveBoundaries) { this._closeRecordDetails(); @@ -771,7 +784,7 @@ WebInspector.TimelinePanel.prototype = { var width = this._graphRowsElementWidth; this._itemsGraphsElement.removeChild(this._graphRowsElement); var graphRowElement = this._graphRowsElement.firstChild; - var scheduleRefreshCallback = this._scheduleRefresh.bind(this, true); + var scheduleRefreshCallback = this._invalidateAndScheduleRefresh.bind(this, true); this._itemsGraphsElement.removeChild(this._expandElements); this._expandElements.removeChildren(); @@ -1112,7 +1125,14 @@ WebInspector.TimelineRecordListRow.prototype = { this._record = record; this._offset = offset; - this.element.className = "timeline-tree-item timeline-category-" + record.category.name + (isEven ? " even" : ""); + this.element.className = "timeline-tree-item timeline-category-" + record.category.name; + if (isEven) + this.element.addStyleClass("even"); + if (record.hasWarning) + this.element.addStyleClass("warning"); + else if (record.childHasWarning) + this.element.addStyleClass("child-warning"); + this._typeElement.textContent = record.title; if (this._dataElement.firstChild) diff --git a/Source/WebCore/inspector/front-end/TimelinePresentationModel.js b/Source/WebCore/inspector/front-end/TimelinePresentationModel.js index 8ebc1123d..a15ce36f3 100644 --- a/Source/WebCore/inspector/front-end/TimelinePresentationModel.js +++ b/Source/WebCore/inspector/front-end/TimelinePresentationModel.js @@ -59,7 +59,7 @@ WebInspector.TimelinePresentationModel.categories = function() /** * @return {!Object.<string, {title: string, category}>} */ -WebInspector.TimelinePresentationModel.initRecordStyles_ = function() +WebInspector.TimelinePresentationModel._initRecordStyles = function() { if (WebInspector.TimelinePresentationModel._recordStylesMap) return WebInspector.TimelinePresentationModel._recordStylesMap; @@ -72,8 +72,10 @@ WebInspector.TimelinePresentationModel.initRecordStyles_ = function() recordStyles[recordTypes.Program] = { title: WebInspector.UIString("Program"), category: categories["program"] }; recordStyles[recordTypes.EventDispatch] = { title: WebInspector.UIString("Event"), category: categories["scripting"] }; recordStyles[recordTypes.BeginFrame] = { title: WebInspector.UIString("Frame Start"), category: categories["rendering"] }; - recordStyles[recordTypes.Layout] = { title: WebInspector.UIString("Layout"), category: categories["rendering"] }; + recordStyles[recordTypes.ScheduleStyleRecalculation] = { title: WebInspector.UIString("Schedule Style Recalculation"), category: categories["rendering"] }; recordStyles[recordTypes.RecalculateStyles] = { title: WebInspector.UIString("Recalculate Style"), category: categories["rendering"] }; + recordStyles[recordTypes.InvalidateLayout] = { title: WebInspector.UIString("Invalidate Layout"), category: categories["rendering"] }; + recordStyles[recordTypes.Layout] = { title: WebInspector.UIString("Layout"), category: categories["rendering"] }; recordStyles[recordTypes.Paint] = { title: WebInspector.UIString("Paint"), category: categories["painting"] }; recordStyles[recordTypes.DecodeImage] = { title: WebInspector.UIString("Image Decode"), category: categories["painting"] }; recordStyles[recordTypes.ResizeImage] = { title: WebInspector.UIString("Image Resize"), category: categories["painting"] }; @@ -110,7 +112,7 @@ WebInspector.TimelinePresentationModel.initRecordStyles_ = function() */ WebInspector.TimelinePresentationModel.recordStyle = function(record) { - var recordStyles = WebInspector.TimelinePresentationModel.initRecordStyles_(); + var recordStyles = WebInspector.TimelinePresentationModel._initRecordStyles(); var result = recordStyles[record.type]; if (!result) { result = { @@ -238,7 +240,7 @@ WebInspector.TimelinePresentationModel.prototype = { reset: function() { this._linkifier.reset(); - this._rootRecord = new WebInspector.TimelinePresentationModel.Record(this, { type: WebInspector.TimelineModel.RecordType.Root }, null, null); + this._rootRecord = new WebInspector.TimelinePresentationModel.Record(this, { type: WebInspector.TimelineModel.RecordType.Root }, null, null, false); this._sendRequestRecords = {}; this._scheduledResourceRequests = {}; this._timerRecords = {}; @@ -246,6 +248,8 @@ WebInspector.TimelinePresentationModel.prototype = { this._timeRecords = {}; this._frames = []; this._minimumRecordTime = -1; + this._lastInvalidateLayout = {}; + this._lastScheduleStyleRecalculation = {}; }, addFrame: function(frame) @@ -273,19 +277,18 @@ WebInspector.TimelinePresentationModel.prototype = { _innerAddRecord: function(record, parentRecord) { + const recordTypes = WebInspector.TimelineModel.RecordType; + const hiddenRecords = [ + recordTypes.MarkDOMContent, + recordTypes.MarkLoad, + recordTypes.ScheduleStyleRecalculation, + recordTypes.InvalidateLayout + ]; + var isHiddenRecord = hiddenRecords.indexOf(record.type) >= 0; var connectedToOldRecord = false; - var recordTypes = WebInspector.TimelineModel.RecordType; - - switch (record.type) { - // No bar entry for load events. - case recordTypes.MarkDOMContent: - case recordTypes.MarkLoad: - parentRecord = null; - break; - case recordTypes.Time: + if (record.type === recordTypes.Time) parentRecord = this._rootRecord; - break; - default: + else if (!isHiddenRecord) { var newParentRecord = this._findParentRecord(record); if (newParentRecord) { parentRecord = newParentRecord; @@ -313,9 +316,9 @@ WebInspector.TimelinePresentationModel.prototype = { } } - var formattedRecord = new WebInspector.TimelinePresentationModel.Record(this, record, parentRecord, scriptDetails); + var formattedRecord = new WebInspector.TimelinePresentationModel.Record(this, record, parentRecord, scriptDetails, isHiddenRecord); - if (record.type === recordTypes.MarkDOMContent || record.type === recordTypes.MarkLoad) + if (isHiddenRecord) return formattedRecord; formattedRecord.collapsed = (parentRecord === this._rootRecord); @@ -375,8 +378,16 @@ WebInspector.TimelinePresentationModel.prototype = { this._glueRecords = glue; }, + invalidateFilteredRecords: function() + { + delete this._filteredRecords; + }, + filteredRecords: function() { + if (this._filteredRecords) + return this._filteredRecords; + var recordsInWindow = []; var stack = [{children: this._rootRecord.children, index: 0, parentIsCollapsed: false}]; @@ -407,6 +418,7 @@ WebInspector.TimelinePresentationModel.prototype = { } } + this._filteredRecords = recordsInWindow; return recordsInWindow; }, @@ -424,16 +436,22 @@ WebInspector.TimelinePresentationModel.prototype.__proto__ = WebInspector.Object /** * @constructor + * @param {WebInspector.TimelinePresentationModel} presentationModel + * @param {Object} record + * @param {WebInspector.TimelinePresentationModel.Record} parentRecord + * @param {Object|undefined} scriptDetails + * @param {boolean} hidden */ -WebInspector.TimelinePresentationModel.Record = function(presentationModel, record, parentRecord, scriptDetails) +WebInspector.TimelinePresentationModel.Record = function(presentationModel, record, parentRecord, scriptDetails, hidden) { this._linkifier = presentationModel._linkifier; this._aggregatedStats = []; this._record = record; this._children = []; - this.parent = parentRecord; - if (parentRecord) + if (!hidden && parentRecord) { + this.parent = parentRecord; parentRecord.children.push(this); + } this._selfTime = this.endTime - this.startTime; this._lastChildEndTime = this.endTime; @@ -445,6 +463,8 @@ WebInspector.TimelinePresentationModel.Record = function(presentationModel, reco this.scriptName = scriptDetails.scriptName; this.scriptLine = scriptDetails.scriptLine; } + if (parentRecord && parentRecord.callSiteStackTrace) + this.callSiteStackTrace = parentRecord.callSiteStackTrace; var recordTypes = WebInspector.TimelineModel.RecordType; switch (record.type) { @@ -512,6 +532,30 @@ WebInspector.TimelinePresentationModel.Record = function(presentationModel, reco timeRecord.intervalDuration = intervalDuration; } break; + + case recordTypes.ScheduleStyleRecalculation: + presentationModel._lastScheduleStyleRecalculation[this.frameId] = this; + break; + + case recordTypes.RecalculateStyles: + var scheduleStyleRecalculationRecord = presentationModel._lastScheduleStyleRecalculation[this.frameId]; + if (!scheduleStyleRecalculationRecord) + break; + this.callSiteStackTrace = scheduleStyleRecalculationRecord.stackTrace; + break; + + case recordTypes.InvalidateLayout: + presentationModel._lastInvalidateLayout[this.frameId] = this; + break; + + case recordTypes.Layout: + var invalidateLayoutRecord = presentationModel._lastInvalidateLayout[this.frameId]; + if (invalidateLayoutRecord) + this.callSiteStackTrace = invalidateLayoutRecord.stackTrace || invalidateLayoutRecord.callSiteStackTrace; + if (this.stackTrace) + this.setHasWarning(); + presentationModel._lastInvalidateLayout[this.frameId] = null; + break; } } @@ -630,9 +674,9 @@ WebInspector.TimelinePresentationModel.Record.prototype = { /** * @return {number} */ - get totalHeapSize() + get usedHeapSizeDelta() { - return this._record.totalHeapSize; + return this._record.usedHeapSizeDelta || 0; }, /** @@ -664,7 +708,7 @@ WebInspector.TimelinePresentationModel.Record.prototype = { generatePopupContent: function(callback) { if (WebInspector.TimelinePresentationModel.needsPreviewElement(this.type)) - WebInspector.buildImagePreviewContents(this.url, false, this._generatePopupContentWithImagePreview.bind(this, callback)); + WebInspector.DOMPresentationUtils.buildImagePreviewContents(this.url, false, this._generatePopupContentWithImagePreview.bind(this, callback)); else this._generatePopupContentWithImagePreview(callback); }, @@ -688,6 +732,10 @@ WebInspector.TimelinePresentationModel.Record.prototype = { } const recordTypes = WebInspector.TimelineModel.RecordType; + // The messages may vary per record type; + var callSiteStackTraceLabel; + var callStackLabel; + switch (this.type) { case recordTypes.GCEvent: contentHelper._appendTextRow(WebInspector.UIString("Collected"), Number.bytesToString(this.data["usedHeapSizeDelta"])); @@ -712,7 +760,7 @@ WebInspector.TimelinePresentationModel.Record.prototype = { case recordTypes.ResourceReceiveResponse: case recordTypes.ResourceReceivedData: case recordTypes.ResourceFinish: - contentHelper._appendElementRow(WebInspector.UIString("Resource"), this._linkifyLocation(this.url)); + contentHelper._appendElementRow(WebInspector.UIString("Resource"), WebInspector.linkifyResourceAsNode(this.url)); if (previewElement) contentHelper._appendElementRow(WebInspector.UIString("Preview"), previewElement); if (this.data["requestMethod"]) @@ -733,6 +781,15 @@ WebInspector.TimelinePresentationModel.Record.prototype = { contentHelper._appendTextRow(WebInspector.UIString("Dimensions"), WebInspector.UIString("%d × %d", this.data["width"], this.data["height"])); break; case recordTypes.RecalculateStyles: // We don't want to see default details. + callSiteStackTraceLabel = WebInspector.UIString("Styles invalidated"); + callStackLabel = WebInspector.UIString("Styles recalculation forced"); + break; + case recordTypes.Layout: + callSiteStackTraceLabel = WebInspector.UIString("Layout invalidated"); + if (this.stackTrace) { + callStackLabel = WebInspector.UIString("Layout forced"); + contentHelper._appendTextRow(WebInspector.UIString("Note"), WebInspector.UIString("Forced synchronous layout is a possible performance bottlenck.")); + } break; case recordTypes.Time: case recordTypes.TimeEnd: @@ -748,14 +805,20 @@ WebInspector.TimelinePresentationModel.Record.prototype = { if (this.scriptName && this.type !== recordTypes.FunctionCall) contentHelper._appendElementRow(WebInspector.UIString("Function Call"), this._linkifyScriptLocation()); - 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.usedHeapSize) { + if (this.usedHeapSizeDelta) { + var sign = this.usedHeapSizeDelta > 0 ? "+" : "-"; + contentHelper._appendTextRow(WebInspector.UIString("Used Heap Size"), + WebInspector.UIString("%s (%s%s)", Number.bytesToString(this.usedHeapSize), sign, Number.bytesToString(this.usedHeapSizeDelta))); + } else if (this.category === WebInspector.TimelinePresentationModel.categories().scripting) + contentHelper._appendTextRow(WebInspector.UIString("Used Heap Size"), Number.bytesToString(this.usedHeapSize)); + } - if (this.callSiteStackTrace && this.callSiteStackTrace.length) - contentHelper._appendStackTrace(WebInspector.UIString("Call Site stack"), this.callSiteStackTrace, this._linkifyCallFrame.bind(this)); + if (this.callSiteStackTrace) + contentHelper._appendStackTrace(callSiteStackTraceLabel || WebInspector.UIString("Call Site stack"), this.callSiteStackTrace, this._linkifyCallFrame.bind(this)); if (this.stackTrace) - contentHelper._appendStackTrace(WebInspector.UIString("Call Stack"), this.stackTrace, this._linkifyCallFrame.bind(this)); + contentHelper._appendStackTrace(callStackLabel || WebInspector.UIString("Call Stack"), this.stackTrace, this._linkifyCallFrame.bind(this)); callback(contentHelper._contentTable); }, @@ -822,15 +885,14 @@ WebInspector.TimelinePresentationModel.Record.prototype = { /** * @param {string} url - * @param {number=} lineNumber + * @param {number} lineNumber * @param {number=} columnNumber */ _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"); + return this._linkifier.linkifyLocation(url, lineNumber - 1, columnNumber, "timeline-details"); }, _linkifyCallFrame: function(callFrame) @@ -843,7 +905,11 @@ WebInspector.TimelinePresentationModel.Record.prototype = { */ _linkifyTopCallFrame: function(defaultValue) { - return this.stackTrace ? this._linkifyCallFrame(this.stackTrace[0]) : defaultValue; + if (this.stackTrace) + return this._linkifyCallFrame(this.stackTrace[0]); + if (this.callSiteStackTrace) + return this._linkifyCallFrame(this.callSiteStackTrace[0]); + return defaultValue; }, /** @@ -874,6 +940,13 @@ WebInspector.TimelinePresentationModel.Record.prototype = { get aggregatedStats() { return this._aggregatedStats; + }, + + setHasWarning: function() + { + this.hasWarning = true; + for (var parent = this.parent; parent && !parent.childHasWarning; parent = parent.parent) + parent.childHasWarning = true; } } diff --git a/Source/WebCore/inspector/front-end/UISourceCode.js b/Source/WebCore/inspector/front-end/UISourceCode.js index 17aaaa0b1..47c8c3425 100644 --- a/Source/WebCore/inspector/front-end/UISourceCode.js +++ b/Source/WebCore/inspector/front-end/UISourceCode.js @@ -36,15 +36,13 @@ * @param {string} url * @param {WebInspector.Resource} resource * @param {WebInspector.ContentProvider} contentProvider - * @param {WebInspector.SourceMapping=} sourceMapping */ -WebInspector.UISourceCode = function(url, resource, contentProvider, sourceMapping) +WebInspector.UISourceCode = function(url, resource, contentProvider) { this._url = url; this._resource = resource; this._parsedURL = new WebInspector.ParsedURL(url); this._contentProvider = contentProvider; - this._sourceMapping = sourceMapping; this.isContentScript = false; /** * @type Array.<function(?string,boolean,string)> @@ -384,6 +382,8 @@ WebInspector.UISourceCode.prototype = { */ uiLocationToRawLocation: function(lineNumber, columnNumber) { + if (!this._sourceMapping) + return null; var location = this._formatterMapping.formattedToOriginal(lineNumber, columnNumber); return this._sourceMapping.uiLocationToRawLocation(this, location[0], location[1]); }, @@ -537,6 +537,14 @@ WebInspector.UISourceCode.prototype = { return null; }, + /** + * @param {WebInspector.SourceMapping} sourceMapping + */ + setSourceMapping: function(sourceMapping) + { + this._sourceMapping = sourceMapping; + }, + formattedChanged: function() { } diff --git a/Source/WebCore/inspector/front-end/UIUtils.js b/Source/WebCore/inspector/front-end/UIUtils.js index e140cf6f7..ac7419531 100644 --- a/Source/WebCore/inspector/front-end/UIUtils.js +++ b/Source/WebCore/inspector/front-end/UIUtils.js @@ -1031,77 +1031,6 @@ WebInspector.revertDomChanges = function(domChanges) } } -/** - * @param {string} imageURL - * @param {boolean} showDimensions - * @param {function(Element=)} userCallback - * @param {Object=} precomputedDimensions - */ -WebInspector.buildImagePreviewContents = function(imageURL, showDimensions, userCallback, precomputedDimensions) -{ - var resource = WebInspector.resourceTreeModel.resourceForURL(imageURL); - if (!resource) { - userCallback(); - return; - } - - var imageElement = document.createElement("img"); - imageElement.addEventListener("load", buildContent, false); - imageElement.addEventListener("error", errorCallback, false); - resource.populateImageSource(imageElement); - - function errorCallback() - { - // Drop the event parameter when invoking userCallback. - userCallback(); - } - - function buildContent() - { - var container = document.createElement("table"); - container.className = "image-preview-container"; - var naturalWidth = precomputedDimensions ? precomputedDimensions.naturalWidth : imageElement.naturalWidth; - var naturalHeight = precomputedDimensions ? precomputedDimensions.naturalHeight : imageElement.naturalHeight; - var offsetWidth = precomputedDimensions ? precomputedDimensions.offsetWidth : naturalWidth; - var offsetHeight = precomputedDimensions ? precomputedDimensions.offsetHeight : naturalHeight; - var description; - if (showDimensions) { - if (offsetHeight === naturalHeight && offsetWidth === naturalWidth) - description = WebInspector.UIString("%d \xd7 %d pixels", offsetWidth, offsetHeight); - else - description = WebInspector.UIString("%d \xd7 %d pixels (Natural: %d \xd7 %d pixels)", offsetWidth, offsetHeight, naturalWidth, naturalHeight); - } - - container.createChild("tr").createChild("td", "image-container").appendChild(imageElement); - if (description) - container.createChild("tr").createChild("td").createChild("span", "description").textContent = description; - userCallback(container); - } -} - -/** - * @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; -} - WebInspector._coalescingLevel = 0; WebInspector.startBatchUpdate = function() diff --git a/Source/WebCore/inspector/front-end/WebGLProfileView.js b/Source/WebCore/inspector/front-end/WebGLProfileView.js new file mode 100644 index 000000000..a504f63ee --- /dev/null +++ b/Source/WebCore/inspector/front-end/WebGLProfileView.js @@ -0,0 +1,278 @@ +/* + * 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.View} + */ +WebInspector.WebGLProfileView = function(profile) +{ + WebInspector.View.call(this); + this.registerRequiredCSS("webGLProfiler.css"); + this._profile = profile; + this.element.addStyleClass("webgl-profile-view"); + + this._traceLogElement = document.createElement("div"); + this._traceLogElement.className = "webgl-trace-log"; + this._traceLogElement.addEventListener("click", this._onTraceLogItemClick.bind(this), false); + this.element.appendChild(this._traceLogElement); + + var replayImageContainer = document.createElement("div"); + replayImageContainer.id = "webgl-replay-image-container"; + this.element.appendChild(replayImageContainer); + + this._replayImageElement = document.createElement("image"); + this._replayImageElement.id = "webgl-replay-image"; + replayImageContainer.appendChild(this._replayImageElement); + + this._debugInfoElement = document.createElement("div"); + replayImageContainer.appendChild(this._debugInfoElement); + + this._linkifier = new WebInspector.Linkifier(); + + this._showTraceLog(); +} + +WebInspector.WebGLProfileView.prototype = { + dispose: function() + { + this._linkifier.reset(); + WebGLAgent.dropTraceLog(this._profile.traceLogId()); + }, + + get statusBarItems() + { + return []; + }, + + get profile() + { + return this._profile; + }, + + wasShown: function() + { + var scrollPosition = this._traceLogElementScrollPosition; + delete this._traceLogElementScrollPosition; + if (scrollPosition) { + this._traceLogElement.scrollTop = scrollPosition.top; + this._traceLogElement.scrollLeft = scrollPosition.left; + } + }, + + willHide: function() + { + this._traceLogElementScrollPosition = { + top: this._traceLogElement.scrollTop, + left: this._traceLogElement.scrollLeft + }; + }, + + _showTraceLog: function() + { + function didReceiveTraceLog(error, traceLog) + { + this._traceLogElement.innerHTML = ""; + if (!traceLog) + return; + var calls = traceLog.calls; + for (var i = 0, n = calls.length; i < n; ++i) { + var call = calls[i]; + var traceLogItem = document.createElement("div"); + traceLogItem.traceLogId = traceLog.id; + traceLogItem.stepNo = i; + traceLogItem.appendChild(document.createTextNode("(" + (i+1) + ") ")); + + if (call.sourceURL) { + // FIXME(62725): stack trace line/column numbers are one-based. + var lineNumber = Math.max(0, call.lineNumber - 1) || 0; + var columnNumber = Math.max(0, call.columnNumber - 1) || 0; + var linkElement = this._linkifier.linkifyLocation(call.sourceURL, lineNumber, columnNumber); + linkElement.textContent = call.functionName; + traceLogItem.appendChild(linkElement); + } else + traceLogItem.appendChild(document.createTextNode(call.functionName)); + + traceLogItem.appendChild(document.createTextNode("(" + call.arguments.join(", ") + ")")); + if (typeof call.result !== "undefined") + traceLogItem.appendChild(document.createTextNode(" => " + call.result)); + this._traceLogElement.appendChild(traceLogItem); + } + } + WebGLAgent.getTraceLog(this._profile.traceLogId(), didReceiveTraceLog.bind(this)); + }, + + _onTraceLogItemClick: function(e) + { + var item = e.target; + if (!item || !item.traceLogId) + return; + var time = Date.now(); + function didReplayTraceLog(error, dataURL) + { + this._debugInfoElement.textContent = "Replay time: " + (Date.now() - time) + "ms"; + if (this._activeTraceLogItem) + this._activeTraceLogItem.style.backgroundColor = ""; + this._activeTraceLogItem = item; + this._activeTraceLogItem.style.backgroundColor = "yellow"; + this._replayImageElement.src = dataURL; + } + WebGLAgent.replayTraceLog(item.traceLogId, item.stepNo, didReplayTraceLog.bind(this)); + } +} + +WebInspector.WebGLProfileView.prototype.__proto__ = WebInspector.View.prototype; + +/** + * @constructor + * @extends {WebInspector.ProfileType} + */ +WebInspector.WebGLProfileType = function() +{ + WebInspector.ProfileType.call(this, WebInspector.WebGLProfileType.TypeId, WebInspector.UIString("Capture WebGL Frame")); + this._nextProfileUid = 1; + // FIXME: enable/disable by a UI action? + WebGLAgent.enable(); +} + +WebInspector.WebGLProfileType.TypeId = "WEBGL_PROFILE"; + +WebInspector.WebGLProfileType.prototype = { + get buttonTooltip() + { + return WebInspector.UIString("Capture WebGL frame."); + }, + + /** + * @override + * @param {WebInspector.ProfilesPanel} profilesPanel + * @return {boolean} + */ + buttonClicked: function(profilesPanel) + { + var profileHeader = new WebInspector.WebGLProfileHeader(this, WebInspector.UIString("Trace Log %d", this._nextProfileUid), this._nextProfileUid); + ++this._nextProfileUid; + profileHeader.isTemporary = true; + profilesPanel.addProfileHeader(profileHeader); + function didStartCapturingFrame(error, traceLogId) + { + profileHeader._traceLogId = traceLogId; + profileHeader.isTemporary = false; + } + WebGLAgent.captureFrame(didStartCapturingFrame.bind(this)); + return false; + }, + + get treeItemTitle() + { + return WebInspector.UIString("WEBGL PROFILE"); + }, + + get description() + { + return WebInspector.UIString("WebGL calls instrumentation"); + }, + + /** + * @override + */ + reset: function() + { + this._nextProfileUid = 1; + }, + + /** + * @override + * @param {string=} title + * @return {WebInspector.ProfileHeader} + */ + createTemporaryProfile: function(title) + { + title = title || WebInspector.UIString("Capturing\u2026"); + return new WebInspector.WebGLProfileHeader(this, title); + }, + + /** + * @override + * @param {ProfilerAgent.ProfileHeader} profile + * @return {WebInspector.ProfileHeader} + */ + createProfile: function(profile) + { + return new WebInspector.WebGLProfileHeader(this, profile.title, -1); + } +} + +WebInspector.WebGLProfileType.prototype.__proto__ = WebInspector.ProfileType.prototype; + +/** + * @constructor + * @extends {WebInspector.ProfileHeader} + * @param {WebInspector.WebGLProfileType} type + * @param {string} title + * @param {number=} uid + */ +WebInspector.WebGLProfileHeader = function(type, title, uid) +{ + WebInspector.ProfileHeader.call(this, type, title, uid); + + /** + * @type {string?} + */ + this._traceLogId = null; +} + +WebInspector.WebGLProfileHeader.prototype = { + /** + * @return {string?} + */ + traceLogId: function() { + return this._traceLogId; + }, + + /** + * @override + */ + createSidebarTreeElement: function() + { + return new WebInspector.ProfileSidebarTreeElement(this, WebInspector.UIString("Trace Log %d"), "profile-sidebar-tree-item"); + }, + + /** + * @override + * @param {WebInspector.ProfilesPanel} profilesPanel + */ + createView: function(profilesPanel) + { + return new WebInspector.WebGLProfileView(this); + } +} + +WebInspector.WebGLProfileHeader.prototype.__proto__ = WebInspector.ProfileHeader.prototype; diff --git a/Source/WebCore/inspector/front-end/WebKit.qrc b/Source/WebCore/inspector/front-end/WebKit.qrc index b19fbe25c..75b891427 100644 --- a/Source/WebCore/inspector/front-end/WebKit.qrc +++ b/Source/WebCore/inspector/front-end/WebKit.qrc @@ -57,6 +57,7 @@ <file>DOMSyntaxHighlighter.js</file> <file>Drawer.js</file> <file>ElementsPanel.js</file> + <file>ElementsPanelDescriptor.js</file> <file>ElementsTreeOutline.js</file> <file>EmptyView.js</file> <file>EventListenersSidebarPane.js</file> @@ -93,7 +94,6 @@ <file>InspectorFrontendAPI.js</file> <file>InspectorFrontendHostStub.js</file> <file>InspectorView.js</file> - <file>JavaScriptContextManager.js</file> <file>JavaScriptFormatter.js</file> <file>JavaScriptSource.js</file> <file>JavaScriptSourceFrame.js</file> @@ -108,6 +108,7 @@ <file>NavigatorView.js</file> <file>NetworkItemView.js</file> <file>NetworkLog.js</file> + <file>NetworkUISourceCodeProvider.js</file> <file>NetworkManager.js</file> <file>NetworkPanel.js</file> <file>NetworkPanelDescriptor.js</file> @@ -127,7 +128,6 @@ <file>ProgressBar.js</file> <file>PropertiesSection.js</file> <file>PropertiesSidebarPane.js</file> - <file>RawSourceCode.js</file> <file>RemoteObject.js</file> <file>Resource.js</file> <file>RequestCookiesView.js</file> @@ -146,6 +146,7 @@ <file>ResourceWebSocketFrameView.js</file> <file>ResourcesPanel.js</file> <file>RevisionHistoryView.js</file> + <file>RuntimeModel.js</file> <file>SASSSourceMapping.js</file> <file>ScopeChainSidebarPane.js</file> <file>Script.js</file> @@ -179,6 +180,7 @@ <file>StatusBarButton.js</file> <file>StyleSheetOutlineDialog.js</file> <file>StyleSource.js</file> + <file>StylesSourceMapping.js</file> <file>StylesSidebarPane.js</file> <file>TabbedEditorContainer.js</file> <file>TabbedPane.js</file> @@ -206,6 +208,7 @@ <file>utilities.js</file> <file>View.js</file> <file>WatchExpressionsSidebarPane.js</file> + <file>WebGLProfileView.js</file> <file>WorkerManager.js</file> <file>WorkersSidebarPane.js</file> <file>Workspace.js</file> @@ -239,6 +242,7 @@ <file>textEditor.css</file> <file>textPrompt.css</file> <file>timelinePanel.css</file> + <file>webGLProfiler.css</file> <file>Images/applicationCache.png</file> <file>Images/back.png</file> <file>Images/breakpointBorder.png</file> @@ -330,6 +334,7 @@ <file>Images/splitviewDimple.png</file> <file>Images/splitviewDividerBackground.png</file> <file>Images/statusbarButtonGlyphs.png</file> + <file>Images/statusbarButtonGlyphs2x.png</file> <file>Images/statusbarResizerHorizontal.png</file> <file>Images/statusbarResizerVertical.png</file> <file>Images/successGreenDot.png</file> diff --git a/Source/WebCore/inspector/front-end/WorkerManager.js b/Source/WebCore/inspector/front-end/WorkerManager.js index ec295d449..9d14da9b9 100644 --- a/Source/WebCore/inspector/front-end/WorkerManager.js +++ b/Source/WebCore/inspector/front-end/WorkerManager.js @@ -161,10 +161,16 @@ WebInspector.WorkerManager.prototype = { _openInspectorWindow: function(workerId, workerIsPaused) { - var url = window.location.href + "&dedicatedWorkerId=" + workerId; + var search = window.location.search; + var hash = window.location.hash; + var url = window.location.href; + // Make sure hash is in rear + url = url.replace(hash, ""); + url += (search ? "&dedicatedWorkerId=" : "?dedicatedWorkerId=") + workerId; if (workerIsPaused) url += "&workerPaused=true"; url = url.replace("docked=true&", ""); + url += hash; // 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; diff --git a/Source/WebCore/inspector/front-end/Workspace.js b/Source/WebCore/inspector/front-end/Workspace.js index 40da8dd29..05087c8d5 100644 --- a/Source/WebCore/inspector/front-end/Workspace.js +++ b/Source/WebCore/inspector/front-end/Workspace.js @@ -30,57 +30,72 @@ /** * @constructor - * @extends {WebInspector.Object} - * @implements {WebInspector.UISourceCodeProvider} - * @param {Array.<WebInspector.UISourceCodeProvider>} uiSourceCodeProviders */ -WebInspector.CompositeUISourceCodeProvider = function(uiSourceCodeProviders) +WebInspector.WorkspaceController = function(workspace) { - WebInspector.Object.call(this); - this._uiSourceCodeProviders = []; - for (var i = 0; i < uiSourceCodeProviders.length; ++i) - this._registerUISourceCodeProvider(uiSourceCodeProviders[i]); + this._workspace = workspace; + WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, this._mainFrameNavigated, this); } -WebInspector.CompositeUISourceCodeProvider.prototype = { - /** - * @param {WebInspector.UISourceCodeProvider} uiSourceCodeProvider - */ - _registerUISourceCodeProvider: function(uiSourceCodeProvider) +WebInspector.WorkspaceController.prototype = { + _mainFrameNavigated: function() { - this._uiSourceCodeProviders.push(uiSourceCodeProvider); - uiSourceCodeProvider.addEventListener(WebInspector.UISourceCodeProvider.Events.UISourceCodeAdded, this._handleUISourceCodeAdded, this); - uiSourceCodeProvider.addEventListener(WebInspector.UISourceCodeProvider.Events.UISourceCodeReplaced, this._handleUISourceCodeReplaced, this); - uiSourceCodeProvider.addEventListener(WebInspector.UISourceCodeProvider.Events.UISourceCodeRemoved, this._handleUISourceCodeRemoved, this); - }, + WebInspector.Revision.filterOutStaleRevisions(); + this._workspace.dispatchEventToListeners(WebInspector.Workspace.Events.ProjectWillReset, this._workspace.project()); + this._workspace.project().reset(); + this._workspace.dispatchEventToListeners(WebInspector.Workspace.Events.ProjectDidReset, this._workspace.project()); + } +} + +/** + * @type {?WebInspector.WorkspaceController} + */ +WebInspector.workspaceController = null; - _handleUISourceCodeAdded: function(event) +/** + * @constructor + */ +WebInspector.Project = function(workspace) +{ + this._uiSourceCodes = []; + this._workspace = workspace; +} + +WebInspector.Project.prototype = { + reset: function() { - this.dispatchEventToListeners(WebInspector.UISourceCodeProvider.Events.UISourceCodeAdded, event.data); + this._uiSourceCodes = []; }, /** - * @param {WebInspector.Event} event + * @param {WebInspector.UISourceCode} uiSourceCode */ - _handleUISourceCodeReplaced: function(event) + addUISourceCode: function(uiSourceCode) { - this.dispatchEventToListeners(WebInspector.UISourceCodeProvider.Events.UISourceCodeReplaced, event.data); + this._uiSourceCodes.push(uiSourceCode); + this._workspace.dispatchEventToListeners(WebInspector.UISourceCodeProvider.Events.UISourceCodeAdded, uiSourceCode); }, /** - * @param {WebInspector.Event} event + * @param {WebInspector.UISourceCode} oldUISourceCode + * @param {WebInspector.UISourceCode} uiSourceCode */ - _handleUISourceCodeRemoved: function(event) + replaceUISourceCode: function(oldUISourceCode, uiSourceCode) { - this.dispatchEventToListeners(WebInspector.UISourceCodeProvider.Events.UISourceCodeRemoved, event.data); + this._uiSourceCodes.splice(this._uiSourceCodes.indexOf(oldUISourceCode), 1); + if (this._uiSourceCodes.indexOf(uiSourceCode) === -1) + this._uiSourceCodes.push(uiSourceCode); + var data = { oldUISourceCode: oldUISourceCode, uiSourceCode: uiSourceCode }; + this._workspace.dispatchEventToListeners(WebInspector.UISourceCodeProvider.Events.UISourceCodeReplaced, data); }, /** - * @return {Array.<WebInspector.UISourceCodeProvider>} + * @param {WebInspector.UISourceCode} uiSourceCode */ - uiSourceCodeProviders: function() + removeUISourceCode: function(uiSourceCode) { - return this._uiSourceCodeProviders.slice(0); + this._uiSourceCodes.splice(this._uiSourceCodes.indexOf(uiSourceCode), 1); + this._workspace.dispatchEventToListeners(WebInspector.UISourceCodeProvider.Events.UISourceCodeRemoved, uiSourceCode); }, /** @@ -89,12 +104,9 @@ WebInspector.CompositeUISourceCodeProvider.prototype = { */ uiSourceCodeForURL: function(url) { - for (var i = 0; i < this._uiSourceCodeProviders.length; ++i) { - var uiSourceCodes = this._uiSourceCodeProviders[i].uiSourceCodes(); - for (var j = 0; j < uiSourceCodes.length; ++j) { - if (uiSourceCodes[j].url === url) - return uiSourceCodes[j]; - } + for (var i = 0; i < this._uiSourceCodes.length; ++i) { + if (this._uiSourceCodes[i].url === url) + return this._uiSourceCodes[i]; } return null; }, @@ -104,63 +116,55 @@ WebInspector.CompositeUISourceCodeProvider.prototype = { */ uiSourceCodes: function() { - var result = []; - for (var i = 0; i < this._uiSourceCodeProviders.length; ++i) { - var uiSourceCodes = this._uiSourceCodeProviders[i].uiSourceCodes(); - for (var j = 0; j < uiSourceCodes.length; ++j) - result.push(uiSourceCodes[j]); - } - return result; + return this._uiSourceCodes; } } -WebInspector.CompositeUISourceCodeProvider.prototype.__proto__ = WebInspector.Object.prototype; - /** * @constructor - * @extends {WebInspector.CompositeUISourceCodeProvider} + * @implements {WebInspector.UISourceCodeProvider} + * @extends {WebInspector.Object} */ WebInspector.Workspace = function() { - var scriptMapping = new WebInspector.DebuggerScriptMapping(); - var styleProviders = [new WebInspector.StylesUISourceCodeProvider()]; - if (WebInspector.experimentsSettings.sass.isEnabled()) - styleProviders.push(new WebInspector.SASSSourceMapping()); - var providers = scriptMapping.uiSourceCodeProviders().concat(styleProviders); - WebInspector.CompositeUISourceCodeProvider.call(this, providers); - - new WebInspector.PresentationConsoleMessageHelper(this); - - WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, this._reset, this); - WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.CachedResourcesLoaded, this._reset, this); + this._project = new WebInspector.Project(this); } WebInspector.Workspace.Events = { - UISourceCodeContentCommitted: "uiSourceCodeContentCommitted", - WorkspaceReset: "WorkspaceReset" + UISourceCodeContentCommitted: "UISourceCodeContentCommitted", + ProjectWillReset: "ProjectWillReset", + ProjectDidReset: "ProjectDidReset" } WebInspector.Workspace.prototype = { /** - * @param {WebInspector.UISourceCodeProvider} uiSourceCodeProvider + * @param {string} url + * @return {?WebInspector.UISourceCode} */ - registerUISourceCodeProvider: function(uiSourceCodeProvider) + uiSourceCodeForURL: function(url) { - this._registerUISourceCodeProvider(uiSourceCodeProvider); + return this._project.uiSourceCodeForURL(url); }, - _reset: function() + /** + * @return {WebInspector.Project} + */ + project: function() { - var uiSourceCodeProviders = this.uiSourceCodeProviders(); - for (var i = 0; i < uiSourceCodeProviders.length; ++i) { - uiSourceCodeProviders[i].reset(); - } - WebInspector.Revision.filterOutStaleRevisions(); - this.dispatchEventToListeners(WebInspector.Workspace.Events.WorkspaceReset, null); + // FIXME: support several projects. + return this._project; + }, + + /** + * @return {Array.<WebInspector.UISourceCode>} + */ + uiSourceCodes: function() + { + return this._project.uiSourceCodes(); } } -WebInspector.Workspace.prototype.__proto__ = WebInspector.CompositeUISourceCodeProvider.prototype; +WebInspector.Workspace.prototype.__proto__ = WebInspector.Object.prototype; /** * @type {?WebInspector.Workspace} diff --git a/Source/WebCore/inspector/front-end/filteredItemSelectionDialog.css b/Source/WebCore/inspector/front-end/filteredItemSelectionDialog.css index bea008c44..36510712a 100644 --- a/Source/WebCore/inspector/front-end/filteredItemSelectionDialog.css +++ b/Source/WebCore/inspector/front-end/filteredItemSelectionDialog.css @@ -28,7 +28,13 @@ white-space: nowrap; text-overflow: ellipsis; overflow: hidden; - color: rgb(105, 105, 105); + color: rgb(95, 95, 95); +} + +.js-outline-dialog span.subtitle { + color: rgb(155, 155, 155); + padding-right: 2px; + float: right; } .js-outline-dialog > .container > div.item.selected { diff --git a/Source/WebCore/inspector/front-end/heapProfiler.css b/Source/WebCore/inspector/front-end/heapProfiler.css index 8a8b49284..73d5365b3 100644 --- a/Source/WebCore/inspector/front-end/heapProfiler.css +++ b/Source/WebCore/inspector/front-end/heapProfiler.css @@ -217,8 +217,9 @@ body.inactive .heap-snapshot-sidebar-tree-item.wait.selected .icon { } .heap-snapshot-view .retainers-view-header { - background-image: url(Images/statusbarResizerVertical.png), url(Images/statusbarBackground.png); - background-repeat: no-repeat, repeat-x; + background-image: url(Images/statusbarResizerVertical.png), -webkit-linear-gradient(rgb(253,253,253), rgb(230,230,230) 75%, rgb(230,230,230)); + border-top: 1px solid rgb(202, 202, 202); + background-repeat: no-repeat; background-position: right center, center; cursor: row-resize; height: 23px; diff --git a/Source/WebCore/inspector/front-end/inspector.css b/Source/WebCore/inspector/front-end/inspector.css index 0f69372cd..fd07c43b9 100644 --- a/Source/WebCore/inspector/front-end/inspector.css +++ b/Source/WebCore/inspector/front-end/inspector.css @@ -544,7 +544,6 @@ body.drawer-visible #main-panels { display: inline-block; pointer-events: auto; cursor: default; - -webkit-flex: 0; height: 24px; padding: 0; margin-left: -1px; @@ -611,9 +610,16 @@ body.drawer-visible #floating-status-bar-container { background-color: rgba(0, 0, 0, 0.75); -webkit-mask-image: url(Images/statusbarButtonGlyphs.png); -webkit-mask-position: -288px -48px; + -webkit-mask-size: 320px 72px; z-index: 1; } +@media (-webkit-min-device-pixel-ratio: 1.5) { +.long-click-glyph { + -webkit-mask-image: url(Images/statusbarButtonGlyphs2x.png); +} +} + .long-click-glyph.shadow { top: 1px; background-color: white !important; @@ -688,6 +694,13 @@ select.status-bar-item, select.status-bar-item:hover { .status-bar-item > .glyph { -webkit-mask-image: url(Images/statusbarButtonGlyphs.png); + -webkit-mask-size: 320px 72px; +} + +@media (-webkit-min-device-pixel-ratio: 1.5) { +.status-bar-item > .glyph { + -webkit-mask-image: url(Images/statusbarButtonGlyphs2x.png); +} } button.dock-status-bar-item.status-bar-item.toggled-undock .glyph { diff --git a/Source/WebCore/inspector/front-end/inspector.html b/Source/WebCore/inspector/front-end/inspector.html index 1b08cfd8d..cb9b8e86b 100644 --- a/Source/WebCore/inspector/front-end/inspector.html +++ b/Source/WebCore/inspector/front-end/inspector.html @@ -107,6 +107,9 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. <script type="text/javascript" src="TextEditor.js"></script> <script type="text/javascript" src="DefaultTextEditor.js"></script> <script type="text/javascript" src="SourceFrame.js"></script> + <script type="text/javascript" src="ResourceView.js"></script> + <script type="text/javascript" src="FontView.js"></script> + <script type="text/javascript" src="ImageView.js"></script> <script type="text/javascript" src="SplitView.js"></script> <script type="text/javascript" src="ConsolePanel.js"></script> <script type="text/javascript" src="ExtensionAPI.js"></script> @@ -136,7 +139,6 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. <script type="text/javascript" src="Workspace.js"></script> <script type="text/javascript" src="BreakpointManager.js"></script> <script type="text/javascript" src="ContentProviders.js"></script> - <script type="text/javascript" src="RawSourceCode.js"></script> <script type="text/javascript" src="ResourceScriptMapping.js"></script> <script type="text/javascript" src="CompilerScriptMapping.js"></script> <script type="text/javascript" src="SASSSourceMapping.js"></script> @@ -153,12 +155,15 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. <script type="text/javascript" src="SearchController.js"></script> <script type="text/javascript" src="WorkerManager.js"></script> <script type="text/javascript" src="UserMetrics.js"></script> - <script type="text/javascript" src="JavaScriptContextManager.js"></script> + <script type="text/javascript" src="RuntimeModel.js"></script> <script type="text/javascript" src="HandlerRegistry.js"></script> <script type="text/javascript" src="SnippetStorage.js"></script> <script type="text/javascript" src="ScriptSnippetModel.js"></script> <script type="text/javascript" src="ProgressBar.js"></script> + <script type="text/javascript" src="StylesSourceMapping.js"></script> <script type="text/javascript" src="StyleSource.js"></script> + <script type="text/javascript" src="NetworkUISourceCodeProvider.js"></script> + <script type="text/javascript" src="ElementsPanelDescriptor.js"></script> <script type="text/javascript" src="NetworkPanelDescriptor.js"></script> <script type="text/javascript" src="ScriptsPanelDescriptor.js"></script> </head> diff --git a/Source/WebCore/inspector/front-end/inspector.js b/Source/WebCore/inspector/front-end/inspector.js index 28dfa2eee..ffc1f7b35 100644 --- a/Source/WebCore/inspector/front-end/inspector.js +++ b/Source/WebCore/inspector/front-end/inspector.js @@ -37,7 +37,7 @@ var WebInspector = { WebInspector.inspectorView.show(parentElement); WebInspector.inspectorView.addEventListener(WebInspector.InspectorView.Events.PanelSelected, this._panelSelected, this); - var elements = new WebInspector.PanelDescriptor("elements", WebInspector.UIString("Elements"), "ElementsPanel", "ElementsPanel.js"); + var elements = new WebInspector.ElementsPanelDescriptor(); var resources = new WebInspector.PanelDescriptor("resources", WebInspector.UIString("Resources"), "ResourcesPanel", "ResourcesPanel.js"); var network = new WebInspector.NetworkPanelDescriptor(); var scripts = new WebInspector.ScriptsPanelDescriptor(); @@ -58,7 +58,7 @@ var WebInspector = { var allDescriptors = [elements, resources, network, scripts, timeline, profiles, audits, console]; var hiddenPanels = InspectorFrontendHost.hiddenPanels(); for (var i = 0; i < allDescriptors.length; ++i) { - if (hiddenPanels.indexOf(allDescriptors[i].name) === -1) + if (hiddenPanels.indexOf(allDescriptors[i].name()) === -1) panelDescriptors.push(allDescriptors[i]); } return panelDescriptors; @@ -484,7 +484,6 @@ WebInspector._doLoadedDoneWithCapabilities = function() WebInspector.CSSCompletions.requestCSSNameCompletions(); 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); @@ -492,9 +491,9 @@ WebInspector._doLoadedDoneWithCapabilities = function() this.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this); this.networkLog = new WebInspector.NetworkLog(); this.domAgent = new WebInspector.DOMAgent(); - this.javaScriptContextManager = new WebInspector.JavaScriptContextManager(this.resourceTreeModel, this.consoleView); + this.runtimeModel = new WebInspector.RuntimeModel(this.resourceTreeModel); - this.scriptSnippetModel = new WebInspector.ScriptSnippetModel(); + this.consoleView = new WebInspector.ConsoleView(WebInspector.WorkerManager.isWorkerFrontend()); InspectorBackend.registerInspectorDispatcher(this); @@ -518,8 +517,19 @@ WebInspector._doLoadedDoneWithCapabilities = function() this.openAnchorLocationRegistry.registerHandler(autoselectPanel, function() { return false; }); this.workspace = new WebInspector.Workspace(); + this.workspaceController = new WebInspector.WorkspaceController(this.workspace); + this.breakpointManager = new WebInspector.BreakpointManager(WebInspector.settings.breakpoints, this.debuggerModel, this.workspace); + this.scriptSnippetModel = new WebInspector.ScriptSnippetModel(this.workspace); + new WebInspector.DebuggerScriptMapping(this.workspace); + new WebInspector.NetworkUISourceCodeProvider(this.workspace); + new WebInspector.StylesSourceMapping(this.workspace); + if (WebInspector.experimentsSettings.sass.isEnabled()) + new WebInspector.SASSSourceMapping(this.workspace); + + new WebInspector.PresentationConsoleMessageHelper(this.workspace); + this._createGlobalStatusBarItems(); WebInspector._installDockToRight(); @@ -1084,9 +1094,4 @@ WebInspector.addMainEventListeners = function(doc) doc.addEventListener("click", this.documentClick.bind(this), true); } -WebInspector.frontendReused = function() -{ - this.resourceTreeModel.frontendReused(); -} - WebInspector.ProfileURLRegExp = /webkit-profile:\/\/(.+)\/(.+)#([0-9]+)/; diff --git a/Source/WebCore/inspector/front-end/inspectorSyntaxHighlight.css b/Source/WebCore/inspector/front-end/inspectorSyntaxHighlight.css index 748631e11..81897d8d4 100644 --- a/Source/WebCore/inspector/front-end/inspectorSyntaxHighlight.css +++ b/Source/WebCore/inspector/front-end/inspectorSyntaxHighlight.css @@ -46,7 +46,7 @@ color: black; } -.webkit-css-important { +.webkit-css-bang-keyword { color: rgb(200, 0, 180); } diff --git a/Source/WebCore/inspector/front-end/scriptsPanel.css b/Source/WebCore/inspector/front-end/scriptsPanel.css index 3ece7eb1f..cf45abfe5 100644 --- a/Source/WebCore/inspector/front-end/scriptsPanel.css +++ b/Source/WebCore/inspector/front-end/scriptsPanel.css @@ -116,9 +116,16 @@ .toggle-breakpoints .glyph { -webkit-mask-image: url(Images/statusbarButtonGlyphs.png); -webkit-mask-position: -32px 0; + -webkit-mask-size: 320px 72px; background-color: rgb(96, 96, 96) !important; } +@media (-webkit-min-device-pixel-ratio: 1.5) { +.toggle-breakpoints .glyph { + -webkit-mask-image: url(Images/statusbarButtonGlyphs2x.png); +} +} + .toggle-breakpoints.toggled-on .glyph { -webkit-mask-position: 0 -24px; } @@ -157,8 +164,9 @@ .status-bar-item.scripts-navigator-show-hide-button > .glyph { background-color: rgba(0, 0, 0, 0.5); - -webkit-mask-position: 0 0; -webkit-mask-image: url(Images/navigatorShowHideButton.png); + -webkit-mask-position: 0 0; + -webkit-mask-size: 48px 32px; } .status-bar-item.scripts-navigator-show-hide-button.toggled-pinned > .glyph { @@ -258,7 +266,6 @@ button.status-bar-item.scripts-navigator-show-hide-button.toggled-overlay button.status-bar-item.scripts-debugger-show-hide-button { position: absolute; top: 0; - right: 16px; background-image: none; height: 16px; width: 16px; @@ -268,19 +275,35 @@ button.status-bar-item.scripts-debugger-show-hide-button { button.status-bar-item.scripts-debugger-show-hide-button:active { top: 1px; - right: 15px; } .status-bar-item.scripts-debugger-show-hide-button > .glyph { background-color: rgba(0, 0, 0, 0.5); - -webkit-mask-position: 0 0; -webkit-mask-image: url(Images/navigatorShowHideButton.png); + -webkit-mask-position: 0 0; + -webkit-mask-size: 48px 32px; +} + +button.status-bar-item.scripts-debugger-show-hide-button.toggled-shown { + right: 16px; +} + +button.status-bar-item.scripts-debugger-show-hide-button.toggled-shown:active { + right: 15px; } .status-bar-item.scripts-debugger-show-hide-button.toggled-shown > .glyph { -webkit-mask-position: 0 -16px; } +button.status-bar-item.scripts-debugger-show-hide-button.toggled-hidden { + right: 1px; +} + +button.status-bar-item.scripts-debugger-show-hide-button.toggled-hidden:active { + right: 0px; +} + .status-bar-item.scripts-debugger-show-hide-button.toggled-hidden > .glyph { -webkit-mask-position: -16px -16px; } diff --git a/Source/WebCore/inspector/front-end/timelinePanel.css b/Source/WebCore/inspector/front-end/timelinePanel.css index f5381bcc4..c9dfabe2b 100644 --- a/Source/WebCore/inspector/front-end/timelinePanel.css +++ b/Source/WebCore/inspector/front-end/timelinePanel.css @@ -271,6 +271,17 @@ background-color: rgba(0, 0, 0, 0.05); } +.timeline-tree-item.warning::after, +.timeline-tree-item.child-warning::after { + content: url(Images/warningIcon.png); + float: right; + padding-top: 1px; +} + +.timeline-tree-item.child-warning::after { + opacity: 0.5; +} + .timeline-tree-item .data.dimmed { color: rgba(0, 0, 0, 0.7); } @@ -475,9 +486,16 @@ margin-left: 0; margin-right: 0; -webkit-mask-image: url(Images/statusbarButtonGlyphs.png); + -webkit-mask-size: 320px 72px; background-color: black; } +@media (-webkit-min-device-pixel-ratio: 1.5) { +#timeline-overview-sidebar .icon { + -webkit-mask-image: url(Images/statusbarButtonGlyphs2x.png); +} +} + .timeline-overview-sidebar-events .icon { -webkit-mask-position: -192px -48px; } diff --git a/Source/WebCore/inspector/front-end/utilities.js b/Source/WebCore/inspector/front-end/utilities.js index bba9a95a4..26bf47ef8 100644 --- a/Source/WebCore/inspector/front-end/utilities.js +++ b/Source/WebCore/inspector/front-end/utilities.js @@ -133,6 +133,15 @@ String.prototype.trimURL = function(baseURLDomain) return result; } +/** + * @param {string} href + * @return {string} + */ +function sanitizeHref(href) +{ + return href && href.trim().toLowerCase().startsWith("javascript:") ? "" : href; +} + String.prototype.removeURLFragment = function() { var fragmentIndex = this.indexOf("#"); @@ -675,6 +684,7 @@ function numberToStringWithSpacesPadding(value, symbolsCount) var Map = function() { this._map = {}; + this._size = 0; } Map._lastObjectIdentifier = 0; @@ -690,6 +700,8 @@ Map.prototype = { objectIdentifier = ++Map._lastObjectIdentifier; key.__identifier = objectIdentifier; } + if (!this._map[objectIdentifier]) + ++this._size; this._map[objectIdentifier] = [key, value]; }, @@ -700,6 +712,7 @@ Map.prototype = { { var result = this._map[key.__identifier]; delete this._map[key.__identifier]; + --this._size; return result ? result[1] : undefined; }, @@ -721,9 +734,10 @@ Map.prototype = { */ _list: function(index) { - var result = []; + var result = new Array(this._size); + var i = 0; for (var objectIdentifier in this._map) - result.push(this._map[objectIdentifier][index]); + result[i++] = this._map[objectIdentifier][index]; return result; }, @@ -735,10 +749,16 @@ Map.prototype = { var entry = this._map[key.__identifier]; return entry ? entry[1] : undefined; }, - + + size: function() + { + return this._size; + }, + clear: function() { this._map = {}; + this._size = 0; } } /** diff --git a/Source/WebCore/inspector/front-end/webGLProfiler.css b/Source/WebCore/inspector/front-end/webGLProfiler.css new file mode 100644 index 000000000..ba1681a63 --- /dev/null +++ b/Source/WebCore/inspector/front-end/webGLProfiler.css @@ -0,0 +1,67 @@ +/* + * 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. + */ + +.webgl-profile-view { + overflow: hidden; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; +} + +.webgl-trace-log { + position: absolute; + top: 10px; + left: 0; + bottom: 10px; + font-size: 13px; + overflow: auto; + white-space: nowrap; + padding: 0 20px; +} + +.webgl-trace-log div { + padding-bottom: 4px; +} + +#webgl-replay-image-container { + position: absolute; + right: 0; + top: 0; + padding: 10px; + background-color: white; +} + +#webgl-replay-image { + width: 400px; + height: 400px; + display: block; +} diff --git a/Source/WebCore/inspector/generate-inspector-protocol-version b/Source/WebCore/inspector/generate-inspector-protocol-version index e7d633c04..bd606b46e 100755 --- a/Source/WebCore/inspector/generate-inspector-protocol-version +++ b/Source/WebCore/inspector/generate-inspector-protocol-version @@ -339,8 +339,9 @@ def main(): output_file.write(""" #ifndef InspectorProtocolVersion_h #define InspectorProtocolVersion_h -#include "PlatformString.h" + #include <wtf/Vector.h> +#include <wtf/text/WTFString.h> namespace WebCore { |